diff --git a/Jakefile.js b/Jakefile.js index 57e05f8acba..0793659183b 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -3,7 +3,6 @@ /// const fs = require("fs"); -const fs2 = require("fs-extra"); const os = require("os"); const path = require("path"); const fold = require("travis-fold"); diff --git a/lib/cancellationToken.js b/lib/cancellationToken.js index 1757efbb9bd..d63145f3fc5 100644 --- a/lib/cancellationToken.js +++ b/lib/cancellationToken.js @@ -70,5 +70,4 @@ function createCancellationToken(args) { } } module.exports = createCancellationToken; - -//# sourceMappingURL=cancellationToken.js.map +//# sourceMappingURL=cancellationToken.js.map \ No newline at end of file diff --git a/lib/protocol.d.ts b/lib/protocol.d.ts index 987fbf9ae24..cd239619457 100644 --- a/lib/protocol.d.ts +++ b/lib/protocol.d.ts @@ -458,7 +458,7 @@ declare namespace ts.server.protocol { scope: OrganizeImportsScope; } interface OrganizeImportsResponse extends Response { - edits: ReadonlyArray; + body: ReadonlyArray; } interface GetEditsForFileRenameRequest extends Request { command: CommandTypes.GetEditsForFileRename; @@ -469,7 +469,7 @@ declare namespace ts.server.protocol { readonly newFilePath: string; } interface GetEditsForFileRenameResponse extends Response { - edits: ReadonlyArray; + body: ReadonlyArray; } /** * Request for the available codefixes at a specific position. @@ -2255,6 +2255,7 @@ declare namespace ts.server.protocol { interface TextInsertion { newText: string; + /** The position in newText the caret should point to after the insertion. */ caretOffset: number; } @@ -2270,9 +2271,13 @@ declare namespace ts.server.protocol { } enum OutliningSpanKind { + /** Single or multi-line comments */ Comment = "comment", + /** Sections marked by '// #region' and '// #endregion' comments */ Region = "region", + /** Declarations and expressions */ Code = "code", + /** Contiguous blocks of import declarations */ Imports = "imports" } @@ -2286,27 +2291,56 @@ declare namespace ts.server.protocol { enum ScriptElementKind { unknown = "", warning = "warning", + /** predefined type (void) or keyword (class) */ keyword = "keyword", + /** top level script node */ scriptElement = "script", + /** module foo {} */ moduleElement = "module", + /** class X {} */ classElement = "class", + /** var x = class X {} */ localClassElement = "local class", + /** interface Y {} */ interfaceElement = "interface", + /** type T = ... */ typeElement = "type", + /** enum E */ enumElement = "enum", enumMemberElement = "enum member", + /** + * Inside module and script only + * const v = .. + */ variableElement = "var", + /** Inside function */ localVariableElement = "local var", + /** + * Inside module and script only + * function f() { } + */ functionElement = "function", + /** Inside function */ localFunctionElement = "local function", + /** class X { [public|private]* foo() {} } */ memberFunctionElement = "method", + /** class X { [public|private]* [get|set] foo:number; } */ memberGetAccessorElement = "getter", memberSetAccessorElement = "setter", + /** + * class X { [public|private]* foo:number; } + * interface Y { foo:number; } + */ memberVariableElement = "property", + /** class X { constructor() { } } */ constructorImplementationElement = "constructor", + /** interface Y { ():number; } */ callSignatureElement = "call", + /** interface Y { []:number; } */ indexSignatureElement = "index", + /** interface Y { new():Y; } */ constructSignatureElement = "construct", + /** function foo(*Y*: string) */ parameterElement = "parameter", typeParameterElement = "type parameter", primitiveType = "primitive type", @@ -2316,7 +2350,11 @@ declare namespace ts.server.protocol { letElement = "let", directory = "directory", externalModuleName = "external module name", + /** + * + */ jsxAttribute = "JSX attribute", + /** String literal */ string = "string" } @@ -2339,6 +2377,11 @@ declare namespace ts.server.protocol { text?: string; } + /** + * Type of objects whose values are all of the same type. + * The `in` and `for-in` operators can *not* be safely used, + * since `Object.prototype` may be modified by outside code. + */ interface MapLike { [index: string]: T; } @@ -2348,9 +2391,13 @@ declare namespace ts.server.protocol { } interface ProjectReference { + /** A normalized path on disk */ path: string; + /** The path as the user originally wrote it */ originalPath?: string; + /** True if the output of this reference should be prepended to the output of this project. Only valid for --outFile compilations */ prepend?: boolean; + /** True if it is intended that this reference form a circularity */ circular?: boolean; } diff --git a/lib/tsc.js b/lib/tsc.js index 5ee4b284add..c4211aa1b3b 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -1,11 +1,14 @@ "use strict";"use strict"; -var __assign = (this && this.__assign) || Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); }; var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) { if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } @@ -53963,7 +53966,7 @@ var ts; name: "typescript:assign", scoped: false, priority: 1, - text: "\n var __assign = (this && this.__assign) || Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };" + text: "\n var __assign = (this && this.__assign) || function () {\n __assign = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign.apply(this, arguments);\n };" }; function createAssignHelper(context, attributesSegments) { if (context.getCompilerOptions().target >= 2) { @@ -56440,7 +56443,7 @@ var ts; name: "typescript:extends", scoped: false, priority: 0, - text: "\n var __extends = (this && this.__extends) || (function () {\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n })();" + text: "\n var __extends = (this && this.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n }\n\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n })();" }; var templateObjectHelper = { name: "typescript:makeTemplateObject", @@ -61783,13 +61786,17 @@ var ts; var offsetLine_1 = writer.getLine(); var firstLineColumnOffset_1 = writer.getColumn(); var originalMap_1 = parsed; + var sourcesDirectoryPath_1 = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir; + var resolvedPathCache_1 = ts.createMap(); ts.sourcemaps.calculateDecodedMappings(originalMap_1, function (raw) { var rawPath = originalMap_1.sources[raw.sourceIndex]; var relativePath = originalMap_1.sourceRoot ? ts.combinePaths(originalMap_1.sourceRoot, rawPath) : rawPath; var combinedPath = ts.combinePaths(ts.getDirectoryPath(node.sourceMapPath), relativePath); - var sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir; - var resolvedPath = ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, combinedPath, host.getCurrentDirectory(), host.getCanonicalFileName, true); - var absolutePath = ts.getNormalizedAbsolutePath(resolvedPath, sourcesDirectoryPath); + if (!resolvedPathCache_1.has(combinedPath)) { + resolvedPathCache_1.set(combinedPath, ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath_1, combinedPath, host.getCurrentDirectory(), host.getCanonicalFileName, true)); + } + var resolvedPath = resolvedPathCache_1.get(combinedPath); + var absolutePath = ts.getNormalizedAbsolutePath(resolvedPath, sourcesDirectoryPath_1); setupSourceEntry(absolutePath, originalMap_1.sourcesContent ? originalMap_1.sourcesContent[raw.sourceIndex] : null); var newIndex = sourceMapData.sourceMapSources.indexOf(resolvedPath); encodeLastRecordedSourceMapSpan(); @@ -70335,11 +70342,6 @@ var ts; } ts.createSolutionBuilder = createSolutionBuilder; function getUpToDateStatus(host, project) { - if (project === undefined) { - return { - type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" - }; - } if (project === undefined) { return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" }; } @@ -70415,6 +70417,7 @@ var ts; } var pseudoUpToDate = false; var usesPrepend = false; + var upstreamChangedProject; if (project.projectReferences && host.parseConfigFile) { for (var _c = 0, _d = project.projectReferences; _c < _d.length; _c++) { var ref = _d[_c]; @@ -70438,6 +70441,7 @@ var ts; } if (refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) { pseudoUpToDate = true; + upstreamChangedProject = ref.path; continue; } ts.Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here"); @@ -70461,8 +70465,12 @@ var ts; newerInputFileName: newestInputFileName }; } - if (usesPrepend) { - pseudoUpToDate = false; + if (usesPrepend && pseudoUpToDate) { + return { + type: UpToDateStatusType.OutOfDateWithUpstream, + outOfDateOutputFileName: oldestOutputFileName, + newerProjectName: upstreamChangedProject + }; } return { type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate, diff --git a/lib/tsserver.js b/lib/tsserver.js index de09a6a2e03..0fe2f989a21 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -65494,7 +65494,7 @@ var ts; name: "typescript:assign", scoped: false, priority: 1, - text: "\n var __assign = (this && this.__assign) || Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };" + text: "\n var __assign = (this && this.__assign) || function () {\n __assign = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign.apply(this, arguments);\n };" }; function createAssignHelper(context, attributesSegments) { if (context.getCompilerOptions().target >= 2 /* ES2015 */) { @@ -69112,7 +69112,7 @@ var ts; name: "typescript:extends", scoped: false, priority: 0, - text: "\n var __extends = (this && this.__extends) || (function () {\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n })();" + text: "\n var __extends = (this && this.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n }\n\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n })();" }; var templateObjectHelper = { name: "typescript:makeTemplateObject", @@ -76863,15 +76863,19 @@ var ts; var firstLineColumnOffset_1 = writer.getColumn(); // First, decode the old component sourcemap var originalMap_1 = parsed; + var sourcesDirectoryPath_1 = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir; + var resolvedPathCache_1 = ts.createMap(); ts.sourcemaps.calculateDecodedMappings(originalMap_1, function (raw) { // Apply offsets to each position and fixup source entries var rawPath = originalMap_1.sources[raw.sourceIndex]; var relativePath = originalMap_1.sourceRoot ? ts.combinePaths(originalMap_1.sourceRoot, rawPath) : rawPath; var combinedPath = ts.combinePaths(ts.getDirectoryPath(node.sourceMapPath), relativePath); - var sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir; - var resolvedPath = ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, combinedPath, host.getCurrentDirectory(), host.getCanonicalFileName, - /*isAbsolutePathAnUrl*/ true); - var absolutePath = ts.getNormalizedAbsolutePath(resolvedPath, sourcesDirectoryPath); + if (!resolvedPathCache_1.has(combinedPath)) { + resolvedPathCache_1.set(combinedPath, ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath_1, combinedPath, host.getCurrentDirectory(), host.getCanonicalFileName, + /*isAbsolutePathAnUrl*/ true)); + } + var resolvedPath = resolvedPathCache_1.get(combinedPath); + var absolutePath = ts.getNormalizedAbsolutePath(resolvedPath, sourcesDirectoryPath_1); // tslint:disable-next-line:no-null-keyword setupSourceEntry(absolutePath, originalMap_1.sourcesContent ? originalMap_1.sourcesContent[raw.sourceIndex] : null); // TODO: Lookup content for inlining? var newIndex = sourceMapData.sourceMapSources.indexOf(resolvedPath); @@ -82959,7 +82963,7 @@ var ts; } function parseProjectReferenceConfigFile(ref) { // The actual filename (i.e. add "/tsconfig.json" if necessary) - var refPath = resolveProjectReferencePath(host, ref); // TODO: GH#18217 + var refPath = resolveProjectReferencePath(host, ref); // An absolute path pointing to the containing directory of the config file var basePath = ts.getNormalizedAbsolutePath(ts.getDirectoryPath(refPath), host.getCurrentDirectory()); var sourceFile = host.getSourceFile(refPath, 100 /* JSON */); @@ -86542,11 +86546,6 @@ var ts; * Gets the UpToDateStatus for a project */ function getUpToDateStatus(host, project) { - if (project === undefined) { - return { - type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" - }; - } if (project === undefined) { return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" }; } @@ -86633,6 +86632,7 @@ var ts; } var pseudoUpToDate = false; var usesPrepend = false; + var upstreamChangedProject; if (project.projectReferences && host.parseConfigFile) { for (var _c = 0, _d = project.projectReferences; _c < _d.length; _c++) { var ref = _d[_c]; @@ -86662,6 +86662,7 @@ var ts; // *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild if (refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) { pseudoUpToDate = true; + upstreamChangedProject = ref.path; continue; } // We have an output older than an upstream output - we are out of date @@ -86686,8 +86687,12 @@ var ts; newerInputFileName: newestInputFileName }; } - if (usesPrepend) { - pseudoUpToDate = false; + if (usesPrepend && pseudoUpToDate) { + return { + type: UpToDateStatusType.OutOfDateWithUpstream, + outOfDateOutputFileName: oldestOutputFileName, + newerProjectName: upstreamChangedProject + }; } // Up to date return { @@ -86745,7 +86750,6 @@ var ts; } ts.formatUpToDateStatus = formatUpToDateStatus; })(ts || (ts = {})); - //# sourceMappingURL=compiler.js.map "use strict"; var __assign = (this && this.__assign) || Object.assign || function(t) { @@ -111803,7 +111807,6 @@ var TypeScript; // TODO: it should be moved into a namespace though. /* @internal */ var toolsVersion = ts.versionMajorMinor; - //# sourceMappingURL=services.js.map "use strict"; /* @internal */ @@ -112214,7 +112217,6 @@ var ts; }()); ts.Semver = Semver; })(ts || (ts = {})); - //# sourceMappingURL=jsTyping.js.map "use strict"; var __assign = (this && this.__assign) || Object.assign || function(t) { @@ -118419,8 +118421,8 @@ var ts; }()); })(server = ts.server || (ts.server = {})); })(ts || (ts = {})); - //# sourceMappingURL=server.js.map +// tslint:disable no-unnecessary-type-assertion (TODO: tslint can't find node types) var ts; (function (ts) { var server; @@ -118472,7 +118474,7 @@ var ts; output: process.stdout, terminal: false, }); - var Logger = (function () { + var Logger = /** @class */ (function () { function Logger(logFilename, traceToConsole, level) { this.logFilename = logFilename; this.traceToConsole = traceToConsole; @@ -118486,6 +118488,7 @@ var ts; this.fd = fs.openSync(this.logFilename, "w"); } catch (_) { + // swallow the error and keep logging disabled if file cannot be opened } } } @@ -118546,7 +118549,8 @@ var ts; Logger.prototype.write = function (s) { if (this.fd >= 0) { var buf = new Buffer(s); - fs.writeSync(this.fd, buf, 0, buf.length, null); + // tslint:disable-next-line no-null-keyword + fs.writeSync(this.fd, buf, 0, buf.length, /*position*/ null); // TODO: GH#18217 } if (this.traceToConsole) { console.warn(s); @@ -118554,7 +118558,7 @@ var ts; }; return Logger; }()); - var NodeTypingsInstaller = (function () { + var NodeTypingsInstaller = /** @class */ (function () { function NodeTypingsInstaller(telemetryEnabled, logger, host, globalTypingsCacheLocation, typingSafeListLocation, typesMapLocation, npmLocation, event) { this.telemetryEnabled = telemetryEnabled; this.logger = logger; @@ -118566,11 +118570,12 @@ var ts; this.event = event; this.activeRequestCount = 0; this.requestQueue = []; - this.requestMap = ts.createMap(); + this.requestMap = ts.createMap(); // Maps operation ID to newest requestQueue entry with that ID } NodeTypingsInstaller.prototype.isKnownTypesPackageName = function (name) { + // We want to avoid looking this up in the registry as that is expensive. So first check that it's actually an NPM package. var validationResult = ts.JsTyping.validatePackageName(name); - if (validationResult !== 0) { + if (validationResult !== 0 /* Ok */) { return false; } if (this.requestedRegistry) { @@ -118616,6 +118621,8 @@ var ts; var arg = _a[_i]; var match = /^--((?:debug|inspect)(?:-brk)?)(?:=(\d+))?$/.exec(arg); if (match) { + // if port is specified - use port + 1 + // otherwise pick a default port depending on if 'debug' or 'inspect' and use its value + 1 var currentPort = match[2] !== undefined ? +match[2] : match[1].charAt(0) === "d" ? 5858 : 9229; @@ -118681,6 +118688,7 @@ var ts; } this.packageInstalledPromise = undefined; this.projectService.updateTypingsForProject(response); + // The behavior is the same as for setTypings, so send the same event. this.event(response, "setTypings"); break; } @@ -118765,11 +118773,16 @@ var ts; this.activeRequestCount++; this.host.setTimeout(request.operation, NodeTypingsInstaller.requestDelayMillis); }; + // This number is essentially arbitrary. Processing more than one typings request + // at a time makes sense, but having too many in the pipe results in a hang + // (see https://github.com/nodejs/node/issues/7657). + // It would be preferable to base our limit on the amount of space left in the + // buffer, but we have yet to find a way to retrieve that value. NodeTypingsInstaller.maxActiveRequestCount = 10; NodeTypingsInstaller.requestDelayMillis = 100; return NodeTypingsInstaller; }()); - var IOSession = (function (_super) { + var IOSession = /** @class */ (function (_super) { __extends(IOSession, _super); function IOSession() { var _this = this; @@ -118778,6 +118791,10 @@ var ts; _this.event(body, eventName); } else { + // It is unsafe to dereference `this` before initialization completes, + // so we defer until the next tick. + // + // Construction should finish before the next tick fires, so we do not need to do this recursively. setImmediate(function () { return _this.event(body, eventName); }); } }; @@ -118807,6 +118824,7 @@ var ts; var s_1 = net.connect({ port: _this.eventPort }, function () { _this.eventSocket = s_1; if (_this.socketEventQueue) { + // flush queue. for (var _i = 0, _a = _this.socketEventQueue; _i < _a.length; _i++) { var event_1 = _a[_i]; _this.writeToEventSocket(event_1.body, event_1.eventName); @@ -118890,13 +118908,13 @@ var ts; function getEntireValue(initialIndex) { var pathStart = args[initialIndex]; var extraPartCounter = 0; - if (pathStart.charCodeAt(0) === 34 && - pathStart.charCodeAt(pathStart.length - 1) !== 34) { + if (pathStart.charCodeAt(0) === 34 /* doubleQuote */ && + pathStart.charCodeAt(pathStart.length - 1) !== 34 /* doubleQuote */) { for (var i = initialIndex + 1; i < args.length; i++) { pathStart += " "; pathStart += args[i]; extraPartCounter++; - if (pathStart.charCodeAt(pathStart.length - 1) === 34) + if (pathStart.charCodeAt(pathStart.length - 1) === 34 /* doubleQuote */) break; } } @@ -118914,6 +118932,7 @@ var ts; } return undefined; } + // TSS_LOG "{ level: "normal | verbose | terse", file?: string}" function createLogger() { var cmdLineLogFileName = server.findArgument("--logFile"); var cmdLineVerbosity = getLogLevel(server.findArgument("--logVerbosity")); @@ -118924,8 +118943,12 @@ var ts; ? envLogOptions.file || (__dirname + "/.log" + process.pid.toString()) : undefined; var logVerbosity = cmdLineVerbosity || envLogOptions.detailLevel; - return new Logger(logFileName, envLogOptions.traceToConsole, logVerbosity); + return new Logger(logFileName, envLogOptions.traceToConsole, logVerbosity); // TODO: GH#18217 } + // This places log file in the directory containing editorServices.js + // TODO: check that this location is writable + // average async stat takes about 30 microseconds + // set chunk size to do 30 files in < 1 millisecond function createPollingWatchedFileSet(interval, chunkSize) { if (interval === void 0) { interval = 2500; } if (chunkSize === void 0) { chunkSize = 30; } @@ -118957,6 +118980,9 @@ var ts; } }); } + // this implementation uses polling and + // stat due to inconsistencies of fs.watch + // and efficiency of stat on modern filesystems function startWatchTimer() { setInterval(function () { var count = 0; @@ -118982,7 +119008,7 @@ var ts; callback: callback, mtime: sys.fileExists(fileName) ? getModifiedTime(fileName) - : ts.missingFileModifiedTime + : ts.missingFileModifiedTime // Any subsequent modification will occur after this time }; watchedFiles.push(file); if (watchedFiles.length === 1) { @@ -118994,6 +119020,19 @@ var ts; ts.unorderedRemoveItem(watchedFiles, file); } } + // REVIEW: for now this implementation uses polling. + // The advantage of polling is that it works reliably + // on all os and with network mounted files. + // For 90 referenced files, the average time to detect + // changes is 2*msInterval (by default 5 seconds). + // The overhead of this is .04 percent (1/2500) with + // average pause of < 1 millisecond (and max + // pause less than 1.5 milliseconds); question is + // do we anticipate reference sets in the 100s and + // do we care about waiting 10-20 seconds to detect + // changes for large reference sets? If so, do we want + // to increase the chunk size or decrease the interval + // time dynamically to match the large reference set? var pollingWatchedFileSet = createPollingWatchedFileSet(); var pending = []; var canWrite = true; @@ -119015,30 +119054,40 @@ var ts; function extractWatchDirectoryCacheKey(path, currentDriveKey) { path = ts.normalizeSlashes(path); if (isUNCPath(path)) { + // UNC path: extract server name + // //server/location + // ^ <- from 0 to this position var firstSlash = path.indexOf(ts.directorySeparator, 2); return firstSlash !== -1 ? path.substring(0, firstSlash).toLowerCase() : path; } var rootLength = ts.getRootLength(path); if (rootLength === 0) { + // relative path - assume file is on the current drive return currentDriveKey; } - if (path.charCodeAt(1) === 58 && path.charCodeAt(2) === 47) { + if (path.charCodeAt(1) === 58 /* colon */ && path.charCodeAt(2) === 47 /* slash */) { + // rooted path that starts with c:/... - extract drive letter return path.charAt(0).toLowerCase(); } - if (path.charCodeAt(0) === 47 && path.charCodeAt(1) !== 47) { + if (path.charCodeAt(0) === 47 /* slash */ && path.charCodeAt(1) !== 47 /* slash */) { + // rooted path that starts with slash - /somename - use key for current drive return currentDriveKey; } + // do not cache any other cases return undefined; } function isUNCPath(s) { - return s.length > 2 && s.charCodeAt(0) === 47 && s.charCodeAt(1) === 47; + return s.length > 2 && s.charCodeAt(0) === 47 /* slash */ && s.charCodeAt(1) === 47 /* slash */; } var logger = createLogger(); var sys = ts.sys; var nodeVersion = ts.getNodeMajorVersion(); + // use watchGuard process on Windows when node version is 4 or later var useWatchGuard = process.platform === "win32" && nodeVersion >= 4; var originalWatchDirectory = sys.watchDirectory.bind(sys); var noopWatcher = { close: ts.noop }; + // This is the function that catches the exceptions when watching directory, and yet lets project service continue to function + // Eg. on linux the number of watches are limited and one could easily exhaust watches and the exception ENOSPC is thrown when creating watcher at that point function watchDirectorySwallowingException(path, callback, recursive) { try { return originalWatchDirectory(path, callback, recursive); @@ -119049,7 +119098,7 @@ var ts; } } if (useWatchGuard) { - var currentDrive_1 = extractWatchDirectoryCacheKey(sys.resolvePath(sys.getCurrentDirectory()), undefined); + var currentDrive_1 = extractWatchDirectoryCacheKey(sys.resolvePath(sys.getCurrentDirectory()), /*currentDriveKey*/ undefined); var statusCache_1 = ts.createMap(); sys.watchDirectory = function (path, callback, recursive) { var cacheKey = extractWatchDirectoryCacheKey(path, currentDrive_1); @@ -119083,9 +119132,11 @@ var ts; logger.info("watchDirectory for " + path + " uses cached drive information."); } if (status) { + // this drive is safe to use - call real 'watchDirectory' return watchDirectorySwallowingException(path, callback, recursive); } else { + // this drive is unsafe - return no-op watcher return noopWatcher; } }; @@ -119093,6 +119144,7 @@ var ts; else { sys.watchDirectory = watchDirectorySwallowingException; } + // Override sys.write because fs.writeSync is not reliable on Node 4 sys.write = function (s) { return writeMessage(new Buffer(s, "utf8")); }; sys.watchFile = function (fileName, callback) { var watchedFile = pollingWatchedFileSet.addFile(fileName, callback); @@ -119136,7 +119188,7 @@ var ts; ts.validateLocaleAndSetLanguage(localeStr, sys); } ts.setStackTraceLimit(); - var typingSafeListLocation = server.findArgument(server.Arguments.TypingSafeListLocation); + var typingSafeListLocation = server.findArgument(server.Arguments.TypingSafeListLocation); // TODO: GH#18217 var typesMapLocation = server.findArgument(server.Arguments.TypesMapLocation) || ts.combinePaths(sys.getExecutingFilePath(), "../typesMap.json"); var npmLocation = server.findArgument(server.Arguments.NpmLocation); function parseStringArray(argName) { @@ -119164,9 +119216,11 @@ var ts; process.on("uncaughtException", function (err) { ioSession.logError(err, "unknown"); }); + // See https://github.com/Microsoft/TypeScript/issues/11348 + // tslint:disable-next-line no-unnecessary-type-assertion-2 process.noAsar = true; + // Start listening ioSession.listen(); })(server = ts.server || (ts.server = {})); })(ts || (ts = {})); - -//# sourceMappingURL=tsserver.js.map +//# sourceMappingURL=tsserver.js.map \ No newline at end of file diff --git a/lib/tsserverlibrary.d.ts b/lib/tsserverlibrary.d.ts index 785921fa685..44036c3fe28 100644 --- a/lib/tsserverlibrary.d.ts +++ b/lib/tsserverlibrary.d.ts @@ -14,6 +14,7 @@ and limitations under the License. ***************************************************************************** */ + declare namespace ts { const versionMajorMinor = "3.0"; /** The version of the TypeScript compiler release */ @@ -12460,7 +12461,7 @@ declare namespace ts.server.protocol { scope: OrganizeImportsScope; } interface OrganizeImportsResponse extends Response { - edits: ReadonlyArray; + body: ReadonlyArray; } interface GetEditsForFileRenameRequest extends Request { command: CommandTypes.GetEditsForFileRename; @@ -12471,7 +12472,7 @@ declare namespace ts.server.protocol { readonly newFilePath: string; } interface GetEditsForFileRenameResponse extends Response { - edits: ReadonlyArray; + body: ReadonlyArray; } interface CodeFixRequest extends Request { command: CommandTypes.GetCodeFixes; diff --git a/lib/typescript.d.ts b/lib/typescript.d.ts index d86ab147651..d9addcbcdbf 100644 --- a/lib/typescript.d.ts +++ b/lib/typescript.d.ts @@ -16,15 +16,22 @@ and limitations under the License. declare namespace ts { const versionMajorMinor = "3.0"; + /** The version of the TypeScript compiler release */ const version: string; } declare namespace ts { + /** + * Type of objects whose values are all of the same type. + * The `in` and `for-in` operators can *not* be safely used, + * since `Object.prototype` may be modified by outside code. + */ interface MapLike { [index: string]: T; } interface SortedArray extends Array { " __sortedArrayBrand": any; } + /** ES6 Map interface, only read methods included. */ interface ReadonlyMap { get(key: string): T | undefined; has(key: string): boolean; @@ -34,11 +41,13 @@ declare namespace ts { values(): Iterator; entries(): Iterator<[string, T]>; } + /** ES6 Map interface. */ interface Map extends ReadonlyMap { set(key: string, value: T): this; delete(key: string): boolean; clear(): void; } + /** ES6 Iterator type. */ interface Iterator { next(): { value: T; @@ -48,6 +57,7 @@ declare namespace ts { done: true; }; } + /** Array that is only intended to be pushed to, never read. */ interface Push { push(...values: T[]): void; } @@ -452,7 +462,9 @@ declare namespace ts { } enum JsxFlags { None = 0, + /** An element from a named property of the JSX.IntrinsicElements interface */ IntrinsicNamedElement = 1, + /** An element inferred from the string index signature of the JSX.IntrinsicElements interface */ IntrinsicIndexedElement = 2, IntrinsicElement = 3 } @@ -492,6 +504,10 @@ declare namespace ts { type ModifiersArray = NodeArray; interface Identifier extends PrimaryExpression, Declaration { kind: SyntaxKind.Identifier; + /** + * Prefer to use `id.unescapedText`. (Note: This is available only in services, not internally to the TypeScript compiler.) + * Text of identifier, but if the identifier begins with two underscores, this will begin with three. + */ escapedText: __String; originalKeywordKind?: SyntaxKind; isInJSDocNamespace?: boolean; @@ -635,6 +651,14 @@ declare namespace ts { } type BindingPattern = ObjectBindingPattern | ArrayBindingPattern; type ArrayBindingElement = BindingElement | OmittedExpression; + /** + * Several node kinds share function-like features such as a signature, + * a name, and a body. These nodes should extend FunctionLikeDeclarationBase. + * Examples: + * - FunctionDeclaration + * - MethodDeclaration + * - AccessorDeclaration + */ interface FunctionLikeDeclarationBase extends SignatureDeclarationBase { _functionLikeDeclarationBrand: any; asteriskToken?: AsteriskToken; @@ -642,6 +666,7 @@ declare namespace ts { body?: Block | Expression; } type FunctionLikeDeclaration = FunctionDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ConstructorDeclaration | FunctionExpression | ArrowFunction; + /** @deprecated Use SignatureDeclaration */ type FunctionLike = SignatureDeclaration; interface FunctionDeclaration extends FunctionLikeDeclarationBase, DeclarationStatement { kind: SyntaxKind.FunctionDeclaration; @@ -664,6 +689,7 @@ declare namespace ts { parent: ClassLikeDeclaration; body?: FunctionBody; } + /** For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. */ interface SemicolonClassElement extends ClassElement { kind: SyntaxKind.SemicolonClassElement; parent: ClassLikeDeclaration; @@ -803,6 +829,7 @@ declare namespace ts { interface UnaryExpression extends Expression { _unaryExpressionBrand: any; } + /** Deprecated, please use UpdateExpression */ type IncrementExpression = UpdateExpression; interface UpdateExpression extends UnaryExpression { _updateExpressionBrand: any; @@ -984,6 +1011,12 @@ declare namespace ts { parent: ArrayLiteralExpression | CallExpression | NewExpression; expression: Expression; } + /** + * This interface is a base interface for ObjectLiteralExpression and JSXAttributes to extend from. JSXAttributes is similar to + * ObjectLiteralExpression in that it contains array of properties; however, JSXAttributes' properties can only be + * JSXAttribute or JSXSpreadAttribute. ObjectLiteralExpression, on the other hand, can only have properties of type + * ObjectLiteralElement (e.g. PropertyAssignment, ShorthandPropertyAssignment etc.) + */ interface ObjectLiteralExpressionBase extends PrimaryExpression, Declaration { properties: NodeArray; } @@ -1000,6 +1033,7 @@ declare namespace ts { interface SuperPropertyAccessExpression extends PropertyAccessExpression { expression: SuperExpression; } + /** Brand for a PropertyAccessExpression which, like a QualifiedName, consists of a sequence of identifiers separated by dots. */ interface PropertyAccessEntityNameExpression extends PropertyAccessExpression { _propertyAccessExpressionLikeQualifiedNameBrand?: any; expression: EntityNameExpression; @@ -1136,6 +1170,9 @@ declare namespace ts { interface NotEmittedStatement extends Statement { kind: SyntaxKind.NotEmittedStatement; } + /** + * A list of comma-separated expressions. This node is only created by transformations. + */ interface CommaListExpression extends Expression { kind: SyntaxKind.CommaListExpression; elements: NodeArray; @@ -1272,6 +1309,7 @@ declare namespace ts { } interface ClassDeclaration extends ClassLikeDeclarationBase, DeclarationStatement { kind: SyntaxKind.ClassDeclaration; + /** May be undefined in `export default class { ... }`. */ name?: Identifier; } interface ClassExpression extends ClassLikeDeclarationBase, PrimaryExpression { @@ -1341,6 +1379,11 @@ declare namespace ts { statements: NodeArray; } type ModuleReference = EntityName | ExternalModuleReference; + /** + * One of: + * - import x = require("mod"); + * - import x = M.x; + */ interface ImportEqualsDeclaration extends DeclarationStatement, JSDocContainer { kind: SyntaxKind.ImportEqualsDeclaration; parent: SourceFile | ModuleBlock; @@ -1356,6 +1399,7 @@ declare namespace ts { kind: SyntaxKind.ImportDeclaration; parent: SourceFile | ModuleBlock; importClause?: ImportClause; + /** If this is not a StringLiteral it will be a grammar error. */ moduleSpecifier: Expression; } type NamedImportBindings = NamespaceImport | NamedImports; @@ -1377,7 +1421,9 @@ declare namespace ts { interface ExportDeclaration extends DeclarationStatement { kind: SyntaxKind.ExportDeclaration; parent: SourceFile | ModuleBlock; + /** Will not be assigned in the case of `export * from "foo";` */ exportClause?: NamedExports; + /** If this is not a StringLiteral it will be a grammar error. */ moduleSpecifier?: Expression; } interface NamedImports extends Node { @@ -1404,6 +1450,10 @@ declare namespace ts { name: Identifier; } type ImportOrExportSpecifier = ImportSpecifier | ExportSpecifier; + /** + * This is either an `export =` or an `export default` declaration. + * Unless `isExportEquals` is set, this node was parsed as an `export default`. + */ interface ExportAssignment extends DeclarationStatement { kind: SyntaxKind.ExportAssignment; parent: SourceFile; @@ -1474,6 +1524,10 @@ declare namespace ts { interface JSDocUnknownTag extends JSDocTag { kind: SyntaxKind.JSDocTag; } + /** + * Note that `@extends` is a synonym of `@augments`. + * Both tags are represented by this interface. + */ interface JSDocAugmentsTag extends JSDocTag { kind: SyntaxKind.JSDocAugmentsTag; class: ExpressionWithTypeArguments & { @@ -1523,6 +1577,7 @@ declare namespace ts { parent: JSDoc; name: EntityName; typeExpression?: JSDocTypeExpression; + /** Whether the property name came before the type -- non-standard for JSDoc, but Typescript-like */ isNameFirst: boolean; isBracketed: boolean; } @@ -1535,6 +1590,7 @@ declare namespace ts { interface JSDocTypeLiteral extends JSDocType { kind: SyntaxKind.JSDocTypeLiteral; jsDocPropertyTags?: ReadonlyArray; + /** If true, then this type literal represents an *array* of its type. */ isArrayType?: boolean; } enum FlowFlags { @@ -1615,6 +1671,14 @@ declare namespace ts { libReferenceDirectives: ReadonlyArray; languageVariant: LanguageVariant; isDeclarationFile: boolean; + /** + * lib.d.ts should have a reference comment like + * + * /// + * + * 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. + */ hasNoDefaultLib: boolean; languageVersion: ScriptTarget; } @@ -1661,9 +1725,18 @@ declare namespace ts { interface ParseConfigHost { useCaseSensitiveFileNames: boolean; readDirectory(rootDir: string, extensions: ReadonlyArray, excludes: ReadonlyArray | undefined, includes: ReadonlyArray, depth?: number): string[]; + /** + * Gets a value indicating whether the specified path exists and is a file. + * @param path The path to test. + */ fileExists(path: string): boolean; readFile(path: string): string | undefined; } + /** + * Branded string for keeping track of when we've turned an ambiguous path + * specified like "./blah" to an absolute path to an actual + * tsconfig file, e.g. "/root/blah/tsconfig.json" + */ type ResolvedConfigFileName = string & { _isResolvedConfigFileName: never; }; @@ -1672,18 +1745,39 @@ declare namespace ts { } interface CancellationToken { isCancellationRequested(): boolean; + /** @throws OperationCanceledException if isCancellationRequested is true */ throwIfCancellationRequested(): void; } interface Program extends ScriptReferenceHost { + /** + * Get a list of root file names that were passed to a 'createProgram' + */ getRootFileNames(): ReadonlyArray; + /** + * Get a list of files in the program + */ getSourceFiles(): ReadonlyArray; + /** + * Emits the JavaScript and declaration files. If targetSourceFile is not specified, then + * the JavaScript and declaration files will be produced for all the files in this program. + * If targetSourceFile is specified, then only the JavaScript and declaration for that + * specific file will be generated. + * + * If writeFile is not specified then the writeFile callback from the compiler host will be + * used for writing the JavaScript and declaration files. Otherwise, the writeFile parameter + * will be invoked when writing the JavaScript and declaration files. + */ emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult; getOptionsDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray; getGlobalDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray; getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray; + /** The first time this is called, it will return global diagnostics (no location). */ getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray; getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray; getConfigFileParsingDiagnostics(): ReadonlyArray; + /** + * Gets a type checker that can be used to semantically analyze source files in the program. + */ getTypeChecker(): TypeChecker; isSourceFileFromExternalLibrary(file: SourceFile): boolean; getProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined; @@ -1693,16 +1787,25 @@ declare namespace ts { sourceFile: SourceFile; } interface CustomTransformers { + /** Custom transformers to evaluate before built-in .js transformations. */ before?: TransformerFactory[]; + /** Custom transformers to evaluate after built-in .js transformations. */ after?: TransformerFactory[]; + /** Custom transformers to evaluate after built-in .d.ts transformations. */ afterDeclarations?: TransformerFactory[]; } interface SourceMapSpan { + /** Line number in the .js file. */ emittedLine: number; + /** Column number in the .js file. */ emittedColumn: number; + /** Line number in the .ts file. */ sourceLine: number; + /** Column number in the .ts file. */ sourceColumn: number; + /** Optional name (index into names array) associated with this span. */ nameIndex?: number; + /** .ts file (index into sources array) associated with this span */ sourceIndex: number; } interface SourceMapData { @@ -1717,6 +1820,7 @@ declare namespace ts { sourceMapMappings: string; sourceMapDecodedMappings: SourceMapSpan[]; } + /** Return code used by getEmitOutput function to indicate status of the function */ enum ExitStatus { Success = 0, DiagnosticsPresent_OutputsSkipped = 1, @@ -1724,6 +1828,7 @@ declare namespace ts { } interface EmitResult { emitSkipped: boolean; + /** Contains declaration emit diagnostics */ diagnostics: ReadonlyArray; emittedFiles?: string[]; } @@ -1741,21 +1846,41 @@ declare namespace ts { getReturnTypeOfSignature(signature: Signature): Type; getNullableType(type: Type, flags: TypeFlags): Type; getNonNullableType(type: Type): Type; + /** Note that the resulting nodes cannot be checked. */ typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeNode | undefined; + /** Note that the resulting nodes cannot be checked. */ signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): (SignatureDeclaration & { typeArguments?: NodeArray; }) | undefined; + /** Note that the resulting nodes cannot be checked. */ indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): IndexSignatureDeclaration | undefined; + /** Note that the resulting nodes cannot be checked. */ symbolToEntityName(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): EntityName | undefined; + /** Note that the resulting nodes cannot be checked. */ symbolToExpression(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): Expression | undefined; + /** Note that the resulting nodes cannot be checked. */ symbolToTypeParameterDeclarations(symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): NodeArray | undefined; + /** Note that the resulting nodes cannot be checked. */ symbolToParameterDeclaration(symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): ParameterDeclaration | undefined; + /** Note that the resulting nodes cannot be checked. */ typeParameterToDeclaration(parameter: TypeParameter, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeParameterDeclaration | undefined; getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[]; getSymbolAtLocation(node: Node): Symbol | undefined; getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[]; + /** + * The function returns the value (local variable) symbol of an identifier in the short-hand property assignment. + * This is necessary as an identifier in short-hand property assignment can contains two meaning: property name and property value. + */ getShorthandAssignmentValueSymbol(location: Node): Symbol | undefined; getExportSpecifierLocalTargetSymbol(location: ExportSpecifier): Symbol | undefined; + /** + * If a symbol is a local symbol with an associated exported symbol, returns the exported symbol. + * Otherwise returns its input. + * For example, at `export type T = number;`: + * - `getSymbolAtLocation` at the location `T` will return the exported symbol for `T`. + * - But the result of `getSymbolsInScope` will contain the *local* symbol for `T`, not the exported symbol. + * - Calling `getExportSymbolOfSymbol` on that local symbol will return the exported symbol. + */ getExportSymbolOfSymbol(symbol: Symbol): Symbol; getPropertySymbolOfDestructuringAssignment(location: Identifier): Symbol | undefined; getTypeAtLocation(node: Node): Type | undefined; @@ -1764,11 +1889,20 @@ declare namespace ts { typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): string; typePredicateToString(predicate: TypePredicate, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; + /** + * @deprecated Use the createX factory functions or XToY typechecker methods and `createPrinter` or the `xToString` methods instead + * This will be removed in a future version. + */ getSymbolDisplayBuilder(): SymbolDisplayBuilder; getFullyQualifiedName(symbol: Symbol): string; getAugmentedPropertiesOfType(type: Type): Symbol[]; getRootSymbols(symbol: Symbol): Symbol[]; getContextualType(node: Expression): Type | undefined; + /** + * returns unknownSignature in the case of an error. + * returns undefined if the node is not valid. + * @param argumentCount Apparent number of arguments, passed in case of a possibly incomplete call. This should come from an ArgumentListInfo. See `signatureHelp.ts`. + */ getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined; getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature | undefined; isImplementationOfOverload(node: SignatureDeclaration): boolean | undefined; @@ -1777,6 +1911,7 @@ declare namespace ts { isUnknownSymbol(symbol: Symbol): boolean; getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): string | number | undefined; isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName | ImportTypeNode, propertyName: string): boolean; + /** Follow all aliases to get the original symbol. */ getAliasedSymbol(symbol: Symbol): Symbol; getExportsOfModule(moduleSymbol: Symbol): Symbol[]; getAllAttributesTypeFromJsxOpeningLikeElement(elementNode: JsxOpeningLikeElement): Type | undefined; @@ -1790,6 +1925,11 @@ declare namespace ts { getSuggestionForNonexistentModule(node: Identifier, target: Symbol): string | undefined; getBaseConstraintOfType(type: Type): Type | undefined; getDefaultFromTypeParameter(type: Type): Type | undefined; + /** + * Depending on the operation performed, it may be appropriate to throw away the checker + * if the cancellation token is triggered. Typically, if it is used for error checking + * and the operation is cancelled, then it should be discarded, otherwise it is safe to keep. + */ runWithCancellationToken(token: CancellationToken, cb: (checker: TypeChecker) => T): T; } enum NodeBuilderFlags { @@ -1842,7 +1982,7 @@ declare namespace ts { InElementType = 2097152, InFirstTypeArgument = 4194304, InTypeAlias = 8388608, - WriteOwnNameForAnyLike = 0, + /** @deprecated */ WriteOwnNameForAnyLike = 0, NodeBuilderFlagsMask = 9469291 } enum SymbolFormatFlags { @@ -1852,19 +1992,25 @@ declare namespace ts { AllowAnyNodeKind = 4, UseAliasDefinedOutsideCurrentScope = 8 } + /** + * @deprecated + */ interface SymbolDisplayBuilder { - buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void; - buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void; - buildIndexSignatureDisplay(info: IndexInfo, writer: SymbolWriter, kind: IndexKind, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]): void; - buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildTypePredicateDisplay(predicate: TypePredicate, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildDisplayForParametersAndDelimiters(thisParameter: Symbol, parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void; + /** @deprecated */ buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void; + /** @deprecated */ buildIndexSignatureDisplay(info: IndexInfo, writer: SymbolWriter, kind: IndexKind, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]): void; + /** @deprecated */ buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildTypePredicateDisplay(predicate: TypePredicate, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildDisplayForParametersAndDelimiters(thisParameter: Symbol, parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; } + /** + * @deprecated Migrate to other methods of generating symbol names, ex symbolToEntityName + a printer or symbolToString + */ interface SymbolWriter extends SymbolTracker { writeKeyword(text: string): void; writeOperator(text: string): void; @@ -1985,11 +2131,20 @@ declare namespace ts { ExportEquals = "export=", Default = "default" } + /** + * This represents a string whose leading underscore have been escaped by adding extra leading underscores. + * The shape of this brand is rather unique compared to others we've used. + * Instead of just an intersection of a string and an object, it is that union-ed + * with an intersection of void and an object. This makes it wholly incompatible + * with a normal string (which is good, it cannot be misused on assignment or on usage), + * while still being comparable with a normal string via === (also good) and castable from a string. + */ type __String = (string & { __escapedIdentifier: void; }) | (void & { __escapedIdentifier: void; }) | InternalSymbolName; + /** ReadonlyMap where keys are `__String`s. */ interface ReadonlyUnderscoreEscapedMap { get(key: __String): T | undefined; has(key: __String): boolean; @@ -1999,11 +2154,13 @@ declare namespace ts { values(): Iterator; entries(): Iterator<[__String, T]>; } + /** Map where keys are `__String`s. */ interface UnderscoreEscapedMap extends ReadonlyUnderscoreEscapedMap { set(key: __String, value: T): this; delete(key: __String): boolean; clear(): void; } + /** SymbolTable based on ES6 Map interface. */ type SymbolTable = UnderscoreEscapedMap; enum TypeFlags { Any = 1, @@ -2095,6 +2252,7 @@ declare namespace ts { interface ObjectType extends Type { objectFlags: ObjectFlags; } + /** Class and interface types (ObjectFlags.Class and ObjectFlags.Interface). */ interface InterfaceType extends ObjectType { typeParameters: TypeParameter[] | undefined; outerTypeParameters: TypeParameter[] | undefined; @@ -2109,6 +2267,16 @@ declare namespace ts { declaredStringIndexInfo?: IndexInfo; declaredNumberIndexInfo?: IndexInfo; } + /** + * Type references (ObjectFlags.Reference). When a class or interface has type parameters or + * a "this" type, references to the class or interface are made using type references. The + * typeArguments property specifies the types to substitute for the type parameters of the + * class or interface and optionally includes an extra element that specifies the type to + * substitute for "this" in the resulting instantiation. When no extra argument is present, + * the type reference itself is substituted for "this". The typeArguments property is undefined + * if the class or interface has no type parameters and the reference isn't specifying an + * explicit "this" argument. + */ interface TypeReference extends ObjectType { target: GenericType; typeArguments?: Type[]; @@ -2193,6 +2361,7 @@ declare namespace ts { AlwaysStrict = 64, PriorityImpliesCombination = 28 } + /** @deprecated Use FileExtensionInfo instead. */ type JsFileExtensionInfo = FileExtensionInfo; interface FileExtensionInfo { extension: string; @@ -2206,6 +2375,12 @@ declare namespace ts { message: string; reportsUnnecessary?: {}; } + /** + * A linked list of formatted diagnostic messages to be used as part of a multiline message. + * It is built from the bottom up, leaving the head to be the "main" diagnostic. + * While it seems that DiagnosticMessageChain is structurally similar to DiagnosticMessage, + * the difference is that messages are all preformatted in DMC. + */ interface DiagnosticMessageChain { messageText: string; category: DiagnosticCategory; @@ -2214,6 +2389,7 @@ declare namespace ts { } interface Diagnostic extends DiagnosticRelatedInformation { category: DiagnosticCategory; + /** May store more in future. For now, this will simply be `true` to indicate when a diagnostic is an unused-identifier diagnostic. */ reportsUnnecessary?: {}; code: number; source?: string; @@ -2244,9 +2420,13 @@ declare namespace ts { name: string; } interface ProjectReference { + /** A normalized path on disk */ path: string; + /** The path as the user originally wrote it */ originalPath?: string; + /** True if the output of this reference should be prepended to the output of this project. Only valid for --outFile compilations */ prepend?: boolean; + /** True if it is intended that this reference form a circularity */ circular?: boolean; } type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | ProjectReference[] | null | undefined; @@ -2323,6 +2503,7 @@ declare namespace ts { traceResolution?: boolean; resolveJsonModule?: boolean; types?: string[]; + /** Paths used to compute primary types search locations */ typeRoots?: string[]; esModuleInterop?: boolean; [option: string]: CompilerOptionsValue | TsConfigSourceFile | undefined; @@ -2354,6 +2535,7 @@ declare namespace ts { LineFeed = 1 } interface LineAndCharacter { + /** 0-based. */ line: number; character: number; } @@ -2365,6 +2547,10 @@ declare namespace ts { TSX = 4, External = 5, JSON = 6, + /** + * Used on extensions that doesn't define the ScriptKind but the content defines it. + * Deferred extensions are going to be included in all project contexts. + */ Deferred = 7 } enum ScriptTarget { @@ -2382,6 +2568,7 @@ declare namespace ts { Standard = 0, JSX = 1 } + /** Either a parsed command line or a parsed tsconfig.json */ interface ParsedCommandLine { options: CompilerOptions; typeAcquisition?: TypeAcquisition; @@ -2422,21 +2609,57 @@ declare namespace ts { readFile(fileName: string): string | undefined; trace?(s: string): void; directoryExists?(directoryName: string): boolean; + /** + * Resolve a symbolic link. + * @see https://nodejs.org/api/fs.html#fs_fs_realpathsync_path_options + */ realpath?(path: string): string; getCurrentDirectory?(): string; getDirectories?(path: string): string[]; } + /** + * Represents the result of module resolution. + * Module resolution will pick up tsx/jsx/js files even if '--jsx' and '--allowJs' are turned off. + * The Program will then filter results based on these flags. + * + * Prefer to return a `ResolvedModuleFull` so that the file type does not have to be inferred. + */ interface ResolvedModule { + /** Path of the file the module was resolved to. */ resolvedFileName: string; + /** True if `resolvedFileName` comes from `node_modules`. */ isExternalLibraryImport?: boolean; } + /** + * ResolvedModule with an explicitly provided `extension` property. + * Prefer this over `ResolvedModule`. + * If changing this, remember to change `moduleResolutionIsEqualTo`. + */ interface ResolvedModuleFull extends ResolvedModule { + /** + * Extension of resolvedFileName. This must match what's at the end of resolvedFileName. + * This is optional for backwards-compatibility, but will be added if not provided. + */ extension: Extension; packageId?: PackageId; } + /** + * Unique identifier with a package name and version. + * If changing this, remember to change `packageIdIsEqual`. + */ interface PackageId { + /** + * Name of the package. + * Should not include `@types`. + * If accessing a non-index file, this should include its name e.g. "foo/bar". + */ name: string; + /** + * Name of a submodule within this package. + * May be "". + */ subModuleName: string; + /** Version of the package, e.g. "1.2.3" */ version: string; } enum Extension { @@ -2473,6 +2696,9 @@ declare namespace ts { getNewLine(): string; readDirectory?(rootDir: string, extensions: ReadonlyArray, excludes: ReadonlyArray | undefined, includes: ReadonlyArray, depth?: number): string[]; resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): (ResolvedModule | undefined)[]; + /** + * This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files + */ resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; getEnvironmentVariable?(name: string): string | undefined; createHash?(data: string): string; @@ -2534,42 +2760,163 @@ declare namespace ts { Unspecified = 4 } interface TransformationContext { + /** Gets the compiler options supplied to the transformer. */ getCompilerOptions(): CompilerOptions; + /** Starts a new lexical environment. */ startLexicalEnvironment(): void; + /** Suspends the current lexical environment, usually after visiting a parameter list. */ suspendLexicalEnvironment(): void; + /** Resumes a suspended lexical environment, usually before visiting a function body. */ resumeLexicalEnvironment(): void; + /** Ends a lexical environment, returning any declarations. */ endLexicalEnvironment(): Statement[] | undefined; + /** Hoists a function declaration to the containing scope. */ hoistFunctionDeclaration(node: FunctionDeclaration): void; + /** Hoists a variable declaration to the containing scope. */ hoistVariableDeclaration(node: Identifier): void; + /** Records a request for a non-scoped emit helper in the current context. */ requestEmitHelper(helper: EmitHelper): void; + /** Gets and resets the requested non-scoped emit helpers. */ readEmitHelpers(): EmitHelper[] | undefined; + /** Enables expression substitutions in the pretty printer for the provided SyntaxKind. */ enableSubstitution(kind: SyntaxKind): void; + /** Determines whether expression substitutions are enabled for the provided node. */ isSubstitutionEnabled(node: Node): boolean; + /** + * Hook used by transformers to substitute expressions just before they + * are emitted by the pretty printer. + * + * NOTE: Transformation hooks should only be modified during `Transformer` initialization, + * before returning the `NodeTransformer` callback. + */ onSubstituteNode: (hint: EmitHint, node: Node) => Node; + /** + * Enables before/after emit notifications in the pretty printer for the provided + * SyntaxKind. + */ enableEmitNotification(kind: SyntaxKind): void; + /** + * Determines whether before/after emit notifications should be raised in the pretty + * printer when it emits a node. + */ isEmitNotificationEnabled(node: Node): boolean; + /** + * Hook used to allow transformers to capture state before or after + * the printer emits a node. + * + * NOTE: Transformation hooks should only be modified during `Transformer` initialization, + * before returning the `NodeTransformer` callback. + */ onEmitNode: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; } interface TransformationResult { + /** Gets the transformed source files. */ transformed: T[]; + /** Gets diagnostics for the transformation. */ diagnostics?: DiagnosticWithLocation[]; + /** + * Gets a substitute for a node, if one is available; otherwise, returns the original node. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to substitute. + */ substituteNode(hint: EmitHint, node: Node): Node; + /** + * Emits a node with possible notification. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emitCallback A callback used to emit the node. + */ emitNodeWithNotification(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void; + /** + * Clean up EmitNode entries on any parse-tree nodes. + */ dispose(): void; } + /** + * A function that is used to initialize and return a `Transformer` callback, which in turn + * will be used to transform one or more nodes. + */ type TransformerFactory = (context: TransformationContext) => Transformer; + /** + * A function that transforms a node. + */ type Transformer = (node: T) => T; + /** + * A function that accepts and possibly transforms a node. + */ type Visitor = (node: Node) => VisitResult; type VisitResult = T | T[] | undefined; interface Printer { + /** + * Print a node and its subtree as-is, without any emit transformations. + * @param hint A value indicating the purpose of a node. This is primarily used to + * distinguish between an `Identifier` used in an expression position, versus an + * `Identifier` used as an `IdentifierName` as part of a declaration. For most nodes you + * should just pass `Unspecified`. + * @param node The node to print. The node and its subtree are printed as-is, without any + * emit transformations. + * @param sourceFile A source file that provides context for the node. The source text of + * the file is used to emit the original source content for literals and identifiers, while + * the identifiers of the source file are used when generating unique names to avoid + * collisions. + */ printNode(hint: EmitHint, node: Node, sourceFile: SourceFile): string; + /** + * Prints a list of nodes using the given format flags + */ printList(format: ListFormat, list: NodeArray, sourceFile: SourceFile): string; + /** + * Prints a source file as-is, without any emit transformations. + */ printFile(sourceFile: SourceFile): string; + /** + * Prints a bundle of source files as-is, without any emit transformations. + */ printBundle(bundle: Bundle): string; } interface PrintHandlers { + /** + * A hook used by the Printer when generating unique names to avoid collisions with + * globally defined names that exist outside of the current source file. + */ hasGlobalName?(name: string): boolean; + /** + * A hook used by the Printer to provide notifications prior to emitting a node. A + * compatible implementation **must** invoke `emitCallback` with the provided `hint` and + * `node` values. + * @param hint A hint indicating the intended purpose of the node. + * @param node The node to emit. + * @param emitCallback A callback that, when invoked, will emit the node. + * @example + * ```ts + * var printer = createPrinter(printerOptions, { + * onEmitNode(hint, node, emitCallback) { + * // set up or track state prior to emitting the node... + * emitCallback(hint, node); + * // restore state after emitting the node... + * } + * }); + * ``` + */ onEmitNode?(hint: EmitHint, node: Node | undefined, emitCallback: (hint: EmitHint, node: Node | undefined) => void): void; + /** + * A hook used by the Printer to perform just-in-time substitution of a node. This is + * primarily used by node transformations that need to substitute one node for another, + * such as replacing `myExportedVar` with `exports.myExportedVar`. + * @param hint A hint indicating the intended purpose of the node. + * @param node The node to emit. + * @example + * ```ts + * var printer = createPrinter(printerOptions, { + * substituteNode(hint, node) { + * // perform substitution if necessary... + * return node; + * } + * }); + * ``` + */ substituteNode?(hint: EmitHint, node: Node): Node; } interface PrinterOptions { @@ -2582,6 +2929,7 @@ declare namespace ts { directoryExists?(directoryName: string): boolean; getCurrentDirectory?(): string; } + /** @deprecated See comment on SymbolWriter */ interface SymbolTracker { trackSymbol?(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void; reportInaccessibleThisError?(): void; @@ -2684,6 +3032,10 @@ declare namespace ts { readFile(path: string, encoding?: string): string | undefined; getFileSize?(path: string): number; writeFile(path: string, data: string, writeByteOrderMark?: boolean): void; + /** + * @pollingInterval - this parameter is used in polling-based watchers and ignored in watchers that + * use native OS file watching + */ watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher; watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher; resolvePath(path: string): string; @@ -2697,7 +3049,11 @@ declare namespace ts { getModifiedTime?(path: string): Date; setModifiedTime?(path: string, time: Date): void; deleteFile?(path: string): void; + /** + * A good implementation is node.js' `crypto.createHash`. (https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm) + */ createHash?(data: string): string; + /** This must be cryptographically secure. Only implement this method using `crypto.createHash("sha256")`. */ createSHA256Hash?(data: string): string; getMemoryUsage?(): number; exit(exitCode?: number): void; @@ -2751,6 +3107,7 @@ declare namespace ts { function getPositionOfLineAndCharacter(sourceFile: SourceFileLike, line: number, character: number): number; function getLineAndCharacterOfPosition(sourceFile: SourceFileLike, position: number): LineAndCharacter; function isWhiteSpaceLike(ch: number): boolean; + /** Does not include line breaks. For that, see isWhiteSpaceLike. */ function isWhiteSpaceSingleLine(ch: number): boolean; function isLineBreak(ch: number): boolean; function couldStartTrivia(text: string, pos: number): boolean; @@ -2762,11 +3119,13 @@ declare namespace ts { function reduceEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U): U | undefined; function getLeadingCommentRanges(text: string, pos: number): CommentRange[] | undefined; function getTrailingCommentRanges(text: string, pos: number): CommentRange[] | undefined; + /** Optionally, get the shebang */ function getShebang(text: string): string | undefined; function isIdentifierStart(ch: number, languageVersion: ScriptTarget | undefined): boolean; function isIdentifierPart(ch: number, languageVersion: ScriptTarget | undefined): boolean; function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, languageVariant?: LanguageVariant, textInitial?: string, onError?: ErrorCallback, start?: number, length?: number): Scanner; } +/** Non-internal stuff goes here */ declare namespace ts { function isExternalModuleNameRelative(moduleName: string): boolean; function sortAndDeduplicateDiagnostics(diagnostics: ReadonlyArray): T[]; @@ -2790,6 +3149,14 @@ declare namespace ts { function textChangeRangeIsUnchanged(range: TextChangeRange): boolean; function createTextChangeRange(span: TextSpan, newLength: number): TextChangeRange; let unchangedTextChangeRange: TextChangeRange; + /** + * Called to merge all the changes that occurred across several versions of a script snapshot + * into a single change. i.e. if a user keeps making successive edits to a script we will + * have a text change from V1 to V2, V2 to V3, ..., Vn. + * + * This function will then merge those changes into a single change range valid between V1 and + * Vn. + */ function collapseTextChangeRangesAcrossMultipleVersions(changes: ReadonlyArray): TextChangeRange; function getTypeParameterOwner(d: Declaration): Declaration | undefined; type ParameterPropertyDeclaration = ParameterDeclaration & { @@ -2801,6 +3168,10 @@ declare namespace ts { function isEmptyBindingElement(node: BindingElement): boolean; function getCombinedModifierFlags(node: Node): ModifierFlags; function getCombinedNodeFlags(node: Node): NodeFlags; + /** + * Checks to see if the locale is in the appropriate format, + * and if it is, attempts to set the appropriate language. + */ function validateLocaleAndSetLanguage(locale: string, sys: { getExecutingFilePath(): string; resolvePath(path: string): string; @@ -2811,26 +3182,100 @@ declare namespace ts { function getOriginalNode(node: Node, nodeTest: (node: Node) => node is T): T; function getOriginalNode(node: Node | undefined): Node | undefined; function getOriginalNode(node: Node | undefined, nodeTest: (node: Node | undefined) => node is T): T | undefined; + /** + * Gets a value indicating whether a node originated in the parse tree. + * + * @param node The node to test. + */ function isParseTreeNode(node: Node): boolean; + /** + * Gets the original parse tree node for a node. + * + * @param node The original node. + * @returns The original parse tree node if found; otherwise, undefined. + */ function getParseTreeNode(node: Node): Node; + /** + * Gets the original parse tree node for a node. + * + * @param node The original node. + * @param nodeTest A callback used to ensure the correct type of parse tree node is returned. + * @returns The original parse tree node if found; otherwise, undefined. + */ function getParseTreeNode(node: Node | undefined, nodeTest?: (node: Node) => node is T): T | undefined; + /** + * Remove extra underscore from escaped identifier text content. + * + * @param identifier The escaped identifier text. + * @returns The unescaped identifier text. + */ function unescapeLeadingUnderscores(identifier: __String): string; function idText(identifier: Identifier): string; function symbolName(symbol: Symbol): string; + /** + * Remove extra underscore from escaped identifier text content. + * @deprecated Use `id.text` for the unescaped text. + * @param identifier The escaped identifier text. + * @returns The unescaped identifier text. + */ function unescapeIdentifier(id: string): string; function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined; function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName; + /** + * Gets the JSDoc parameter tags for the node if present. + * + * @remarks Returns any JSDoc param tag that matches the provided + * parameter, whether a param tag on a containing function + * expression, or a param tag on a variable declaration whose + * initializer is the containing function. The tags closest to the + * node are returned first, so in the previous example, the param + * tag on the containing function expression would be first. + * + * Does not return tags for binding patterns, because JSDoc matches + * parameters by name and binding patterns do not have a name. + */ function getJSDocParameterTags(param: ParameterDeclaration): ReadonlyArray; + /** + * Return true if the node has JSDoc parameter tags. + * + * @remarks Includes parameter tags that are not directly on the node, + * for example on a variable declaration whose initializer is a function expression. + */ function hasJSDocParameterTags(node: FunctionLikeDeclaration | SignatureDeclaration): boolean; + /** Gets the JSDoc augments tag for the node if present */ function getJSDocAugmentsTag(node: Node): JSDocAugmentsTag | undefined; + /** Gets the JSDoc class tag for the node if present */ function getJSDocClassTag(node: Node): JSDocClassTag | undefined; + /** Gets the JSDoc this tag for the node if present */ function getJSDocThisTag(node: Node): JSDocThisTag | undefined; + /** Gets the JSDoc return tag for the node if present */ function getJSDocReturnTag(node: Node): JSDocReturnTag | undefined; + /** Gets the JSDoc template tag for the node if present */ function getJSDocTemplateTag(node: Node): JSDocTemplateTag | undefined; + /** Gets the JSDoc type tag for the node if present and valid */ function getJSDocTypeTag(node: Node): JSDocTypeTag | undefined; + /** + * Gets the type node for the node if provided via JSDoc. + * + * @remarks The search includes any JSDoc param tag that relates + * to the provided parameter, for example a type tag on the + * parameter itself, or a param tag on a containing function + * expression, or a param tag on a variable declaration whose + * initializer is the containing function. The tags closest to the + * node are examined first, so in the previous example, the type + * tag directly on the node would be returned. + */ function getJSDocType(node: Node): TypeNode | undefined; + /** + * Gets the return type node for the node if provided via JSDoc's return tag. + * + * @remarks `getJSDocReturnTag` just gets the whole JSDoc tag. This function + * gets the type from inside the braces. + */ function getJSDocReturnType(node: Node): TypeNode | undefined; + /** Get all JSDoc tags related to a node, including those on parent nodes. */ function getJSDocTags(node: Node): ReadonlyArray; + /** Gets all JSDoc tags of a specified kind, or undefined if not present. */ function getAllJSDocTagsOfKind(node: Node, kind: SyntaxKind): ReadonlyArray; } declare namespace ts { @@ -3001,6 +3446,11 @@ declare namespace ts { function isJSDocSignature(node: Node): node is JSDocSignature; } declare namespace ts { + /** + * True if node is of some token syntax kind. + * For example, this is true for an IfKeyword but not for an IfStatement. + * Literals are considered tokens, except TemplateLiteral, but does include TemplateHead/Middle/Tail. + */ function isToken(n: Node): boolean; function isLiteralExpression(node: Node): node is LiteralExpression; type TemplateLiteralToken = NoSubstitutionTemplateLiteral | TemplateHead | TemplateMiddle | TemplateTail; @@ -3018,6 +3468,11 @@ declare namespace ts { function isTypeElement(node: Node): node is TypeElement; function isClassOrTypeElement(node: Node): node is ClassElement | TypeElement; function isObjectLiteralElementLike(node: Node): node is ObjectLiteralElementLike; + /** + * Node test that determines whether a node is a valid type node. + * This differs from the `isPartOfTypeNode` function which determines whether a node is *part* + * of a TypeNode. + */ function isTypeNode(node: Node): node is TypeNode; function isFunctionOrConstructorTypeNode(node: Node): node is FunctionTypeNode | ConstructorTypeNode; function isPropertyAccessOrQualifiedName(node: Node): node is PropertyAccessExpression | QualifiedName; @@ -3029,6 +3484,7 @@ declare namespace ts { function isIterationStatement(node: Node, lookInLabeledStatements: boolean): node is IterationStatement | LabeledStatement; function isJsxOpeningLikeElement(node: Node): node is JsxOpeningLikeElement; function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause; + /** True if node is of a kind that may contain comment text. */ function isJSDocCommentContainingNode(node: Node): boolean; function isSetAccessor(node: Node): node is SetAccessorDeclaration; function isGetAccessor(node: Node): node is GetAccessorDeclaration; @@ -3037,9 +3493,27 @@ declare namespace ts { } declare namespace ts { function createNode(kind: SyntaxKind, pos?: number, end?: number): Node; + /** + * Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes + * stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise, + * embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns + * a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned. + * + * @param node a given node to visit its children + * @param cbNode a callback to be invoked for all child nodes + * @param cbNodes a callback to be invoked for embedded array + * + * @remarks `forEachChild` must visit the children of a node in the order + * that they appear in the source code. The language service depends on this property to locate nodes by position. + */ function forEachChild(node: Node, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined; function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile; function parseIsolatedEntityName(text: string, languageVersion: ScriptTarget): EntityName | undefined; + /** + * Parse json text into SyntaxTree and return node and parse errors if any + * @param fileName + * @param sourceText + */ function parseJsonText(fileName: string, sourceText: string): JsonSourceFile; function isExternalModule(file: SourceFile): boolean; function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; @@ -3047,24 +3521,66 @@ declare namespace ts { declare namespace ts { function parseCommandLine(commandLine: ReadonlyArray, readFile?: (path: string) => string | undefined): ParsedCommandLine; type DiagnosticReporter = (diagnostic: Diagnostic) => void; + /** + * Reports config file diagnostics + */ interface ConfigFileDiagnosticsReporter { + /** + * Reports unrecoverable error when parsing config file + */ onUnRecoverableConfigFileDiagnostic: DiagnosticReporter; } + /** + * Interface extending ParseConfigHost to support ParseConfigFile that reads config file and reports errors + */ interface ParseConfigFileHost extends ParseConfigHost, ConfigFileDiagnosticsReporter { getCurrentDirectory(): string; } + /** + * Reads the config file, reports errors if any and exits if the config file cannot be found + */ function getParsedCommandLineOfConfigFile(configFileName: string, optionsToExtend: CompilerOptions, host: ParseConfigFileHost): ParsedCommandLine | undefined; + /** + * Read tsconfig.json file + * @param fileName The path to the config file + */ function readConfigFile(fileName: string, readFile: (path: string) => string | undefined): { config?: any; error?: Diagnostic; }; + /** + * Parse the text of the tsconfig.json file + * @param fileName The path to the config file + * @param jsonText The text of the config file + */ function parseConfigFileTextToJson(fileName: string, jsonText: string): { config?: any; error?: Diagnostic; }; + /** + * Read tsconfig.json file + * @param fileName The path to the config file + */ function readJsonConfigFile(fileName: string, readFile: (path: string) => string | undefined): TsConfigSourceFile; + /** + * Convert the json syntax tree into the json value + */ function convertToObject(sourceFile: JsonSourceFile, errors: Push): any; + /** + * Parse the contents of a config file (tsconfig.json). + * @param json The contents of the config file to parse + * @param host Instance of ParseConfigHost used to enumerate files in folder. + * @param basePath A root directory to resolve relative path entries in the config + * file to. e.g. outDir + */ function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: ReadonlyArray): ParsedCommandLine; + /** + * Parse the contents of a config file (tsconfig.json). + * @param jsonNode The contents of the config file to parse + * @param host Instance of ParseConfigHost used to enumerate files in folder. + * @param basePath A root directory to resolve relative path entries in the config + * file to. e.g. outDir + */ function parseJsonSourceFileConfigFileContent(sourceFile: TsConfigSourceFile, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: ReadonlyArray): ParsedCommandLine; function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions; @@ -3077,11 +3593,32 @@ declare namespace ts { } declare namespace ts { function getEffectiveTypeRoots(options: CompilerOptions, host: GetEffectiveTypeRootsHost): string[] | undefined; + /** + * @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. + * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups + * is assumed to be the same as root directory of the project. + */ function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost): ResolvedTypeReferenceDirectiveWithFailedLookupLocations; + /** + * Given a set of options, returns the set of type directive names + * that should be included for this program automatically. + * This list could either come from the config file, + * or from enumerating the types root + initial secondary types lookup location. + * More type directives might appear in the program later as a result of loading actual source files; + * this list is only the set of defaults that are implicitly included. + */ function getAutomaticTypeDirectiveNames(options: CompilerOptions, host: ModuleResolutionHost): string[]; + /** + * Cached module resolutions per containing directory. + * This assumes that any module id will have the same resolution for sibling files located in the same folder. + */ interface ModuleResolutionCache extends NonRelativeModuleNameResolutionCache { getOrCreateCacheForDirectory(directoryName: string): Map; } + /** + * Stored map from non-relative module name to a table: directory -> result of module lookup in this directory + * We support only non-relative module names because resolution of relative module names is usually more deterministic and thus less expensive. + */ interface NonRelativeModuleNameResolutionCache { getOrCreateCacheForModuleName(nonRelativeModuleName: string): PerModuleNameCache; } @@ -3097,6 +3634,7 @@ declare namespace ts { } declare namespace ts { function createNodeArray(elements?: ReadonlyArray, hasTrailingComma?: boolean): NodeArray; + /** If a node is passed, creates a string literal whose source text is read from a source node during emit. */ function createLiteral(value: string | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier): StringLiteral; function createLiteral(value: number): NumericLiteral; function createLiteral(value: boolean): BooleanLiteral; @@ -3106,11 +3644,17 @@ declare namespace ts { function createRegularExpressionLiteral(text: string): RegularExpressionLiteral; function createIdentifier(text: string): Identifier; function updateIdentifier(node: Identifier): Identifier; + /** Create a unique temporary variable. */ function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined): Identifier; + /** Create a unique temporary variable for use in a loop. */ function createLoopVariable(): Identifier; + /** Create a unique name based on the supplied text. */ function createUniqueName(text: string): Identifier; + /** Create a unique name based on the supplied text. */ function createOptimisticUniqueName(text: string): Identifier; + /** Create a unique name based on the supplied text. This does not consider names injected by the transformer. */ function createFileLevelUniqueName(text: string): Identifier; + /** Create a unique name generated for a node. */ function getGeneratedNameForNode(node: Node): Identifier; function createToken(token: TKind): Token; function createSuper(): SuperExpression; @@ -3379,8 +3923,25 @@ declare namespace ts { function createEnumMember(name: string | PropertyName, initializer?: Expression): EnumMember; function updateEnumMember(node: EnumMember, name: PropertyName, initializer: Expression | undefined): EnumMember; function updateSourceFileNode(node: SourceFile, statements: ReadonlyArray, isDeclarationFile?: boolean, referencedFiles?: SourceFile["referencedFiles"], typeReferences?: SourceFile["typeReferenceDirectives"], hasNoDefaultLib?: boolean, libReferences?: SourceFile["libReferenceDirectives"]): SourceFile; + /** + * Creates a shallow, memberwise clone of a node for mutation. + */ function getMutableClone(node: T): T; + /** + * Creates a synthetic statement to act as a placeholder for a not-emitted statement in + * order to preserve comments. + * + * @param original The original statement. + */ function createNotEmittedStatement(original: Node): NotEmittedStatement; + /** + * Creates a synthetic expression to act as a placeholder for a not-emitted expression in + * order to preserve comments or sourcemap positions. + * + * @param expression The inner expression to emit. + * @param original The original outer expression. + * @param location The location for the expression. Defaults to the positions from "original" if provided. + */ function createPartiallyEmittedExpression(expression: Expression, original?: Node): PartiallyEmittedExpression; function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression): PartiallyEmittedExpression; function createCommaList(elements: ReadonlyArray): CommaListExpression; @@ -3410,15 +3971,43 @@ declare namespace ts { function createVoidZero(): VoidExpression; function createExportDefault(expression: Expression): ExportAssignment; function createExternalModuleExport(exportName: Identifier): ExportDeclaration; + /** + * Clears any EmitNode entries from parse-tree nodes. + * @param sourceFile A source file. + */ function disposeEmitNodes(sourceFile: SourceFile): void; function setTextRange(range: T, location: TextRange | undefined): T; + /** + * Sets flags that control emit behavior of a node. + */ function setEmitFlags(node: T, emitFlags: EmitFlags): T; + /** + * Gets a custom text range to use when emitting source maps. + */ function getSourceMapRange(node: Node): SourceMapRange; + /** + * Sets a custom text range to use when emitting source maps. + */ function setSourceMapRange(node: T, range: SourceMapRange | undefined): T; + /** + * Create an external source map source file reference + */ function createSourceMapSource(fileName: string, text: string, skipTrivia?: (pos: number) => number): SourceMapSource; + /** + * Gets the TextRange to use for source maps for a token of a node. + */ function getTokenSourceMapRange(node: Node, token: SyntaxKind): SourceMapRange | undefined; + /** + * Sets the TextRange to use for source maps for a token of a node. + */ function setTokenSourceMapRange(node: T, token: SyntaxKind, range: SourceMapRange | undefined): T; + /** + * Gets a custom text range to use when emitting comments. + */ function getCommentRange(node: Node): TextRange; + /** + * Sets a custom text range to use when emitting comments. + */ function setCommentRange(node: T, range: TextRange): T; function getSyntheticLeadingComments(node: Node): SynthesizedComment[] | undefined; function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[] | undefined): T; @@ -3427,26 +4016,115 @@ declare namespace ts { function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[] | undefined): T; function addSyntheticTrailingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean): T; function moveSyntheticComments(node: T, original: Node): T; + /** + * Gets the constant value to emit for an expression. + */ function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression): string | number | undefined; + /** + * Sets the constant value to emit for an expression. + */ function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: string | number): PropertyAccessExpression | ElementAccessExpression; + /** + * Adds an EmitHelper to a node. + */ function addEmitHelper(node: T, helper: EmitHelper): T; + /** + * Add EmitHelpers to a node. + */ function addEmitHelpers(node: T, helpers: EmitHelper[] | undefined): T; + /** + * Removes an EmitHelper from a node. + */ function removeEmitHelper(node: Node, helper: EmitHelper): boolean; + /** + * Gets the EmitHelpers of a node. + */ function getEmitHelpers(node: Node): EmitHelper[] | undefined; + /** + * Moves matching emit helpers from a source node to a target node. + */ function moveEmitHelpers(source: Node, target: Node, predicate: (helper: EmitHelper) => boolean): void; function setOriginalNode(node: T, original: Node | undefined): T; } declare namespace ts { + /** + * Visits a Node using the supplied visitor, possibly returning a new Node in its place. + * + * @param node The Node to visit. + * @param visitor The callback used to visit the Node. + * @param test A callback to execute to verify the Node is valid. + * @param lift An optional callback to execute to lift a NodeArray into a valid Node. + */ function visitNode(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T; + /** + * Visits a Node using the supplied visitor, possibly returning a new Node in its place. + * + * @param node The Node to visit. + * @param visitor The callback used to visit the Node. + * @param test A callback to execute to verify the Node is valid. + * @param lift An optional callback to execute to lift a NodeArray into a valid Node. + */ function visitNode(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T | undefined; + /** + * Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place. + * + * @param nodes The NodeArray to visit. + * @param visitor The callback used to visit a Node. + * @param test A node test to execute for each node. + * @param start An optional value indicating the starting offset at which to start visiting. + * @param count An optional value indicating the maximum number of nodes to visit. + */ function visitNodes(nodes: NodeArray | undefined, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray; + /** + * Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place. + * + * @param nodes The NodeArray to visit. + * @param visitor The callback used to visit a Node. + * @param test A node test to execute for each node. + * @param start An optional value indicating the starting offset at which to start visiting. + * @param count An optional value indicating the maximum number of nodes to visit. + */ function visitNodes(nodes: NodeArray | undefined, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray | undefined; + /** + * Starts a new lexical environment and visits a statement list, ending the lexical environment + * and merging hoisted declarations upon completion. + */ function visitLexicalEnvironment(statements: NodeArray, visitor: Visitor, context: TransformationContext, start?: number, ensureUseStrict?: boolean): NodeArray; + /** + * Starts a new lexical environment and visits a parameter list, suspending the lexical + * environment upon completion. + */ function visitParameterList(nodes: NodeArray | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes): NodeArray; + /** + * Resumes a suspended lexical environment and visits a function body, ending the lexical + * environment and merging hoisted declarations upon completion. + */ function visitFunctionBody(node: FunctionBody, visitor: Visitor, context: TransformationContext): FunctionBody; + /** + * Resumes a suspended lexical environment and visits a function body, ending the lexical + * environment and merging hoisted declarations upon completion. + */ function visitFunctionBody(node: FunctionBody | undefined, visitor: Visitor, context: TransformationContext): FunctionBody | undefined; + /** + * Resumes a suspended lexical environment and visits a concise body, ending the lexical + * environment and merging hoisted declarations upon completion. + */ function visitFunctionBody(node: ConciseBody, visitor: Visitor, context: TransformationContext): ConciseBody; + /** + * Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place. + * + * @param node The Node whose children will be visited. + * @param visitor The callback used to visit each child. + * @param context A lexical environment context for the visitor. + */ function visitEachChild(node: T, visitor: Visitor, context: TransformationContext): T; + /** + * Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place. + * + * @param node The Node whose children will be visited. + * @param visitor The callback used to visit each child. + * @param context A lexical environment context for the visitor. + */ function visitEachChild(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes, tokenVisitor?: Visitor): T | undefined; } declare namespace ts { @@ -3467,8 +4145,35 @@ declare namespace ts { function formatDiagnosticsWithColorAndContext(diagnostics: ReadonlyArray, host: FormatDiagnosticsHost): string; function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain | undefined, newLine: string): string; function getConfigFileParsingDiagnostics(configFileParseResult: ParsedCommandLine): ReadonlyArray; + /** + * Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions' + * that represent a compilation unit. + * + * Creating a program proceeds from a set of root files, expanding the set of inputs by following imports and + * triple-slash-reference-path directives transitively. '@types' and triple-slash-reference-types are also pulled in. + * + * @param createProgramOptions - The options for creating a program. + * @returns A 'Program' object. + */ function createProgram(createProgramOptions: CreateProgramOptions): Program; + /** + * Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions' + * that represent a compilation unit. + * + * Creating a program proceeds from a set of root files, expanding the set of inputs by following imports and + * triple-slash-reference-path directives transitively. '@types' and triple-slash-reference-types are also pulled in. + * + * @param rootNames - A set of root files. + * @param options - The compiler options which should be used. + * @param host - The host interacts with the underlying file system. + * @param oldProgram - Reuses an old program structure. + * @param configFileParsingDiagnostics - error during config file parsing + * @returns A 'Program' object. + */ function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program; + /** + * Returns the target config filename of a project reference + */ function resolveProjectReferencePath(host: CompilerHost | UpToDateHost, ref: ProjectReference): ResolvedConfigFileName; } declare namespace ts { @@ -3488,43 +4193,137 @@ declare namespace ts { affected: SourceFile | Program; } | undefined; interface BuilderProgramHost { + /** + * return true if file names are treated with case sensitivity + */ useCaseSensitiveFileNames(): boolean; + /** + * If provided this would be used this hash instead of actual file shape text for detecting changes + */ createHash?: (data: string) => string; + /** + * When emit or emitNextAffectedFile are called without writeFile, + * this callback if present would be used to write files + */ writeFile?: WriteFileCallback; } + /** + * Builder to manage the program state changes + */ interface BuilderProgram { + /** + * Returns current program + */ getProgram(): Program; + /** + * Get compiler options of the program + */ getCompilerOptions(): CompilerOptions; + /** + * Get the source file in the program with file name + */ getSourceFile(fileName: string): SourceFile | undefined; + /** + * Get a list of files in the program + */ getSourceFiles(): ReadonlyArray; + /** + * Get the diagnostics for compiler options + */ getOptionsDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray; + /** + * Get the diagnostics that dont belong to any file + */ getGlobalDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray; + /** + * Get the diagnostics from config file parsing + */ getConfigFileParsingDiagnostics(): ReadonlyArray; + /** + * Get the syntax diagnostics, for all source files if source file is not supplied + */ getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray; + /** + * Get all the dependencies of the file + */ getAllDependencies(sourceFile: SourceFile): ReadonlyArray; + /** + * Gets the semantic diagnostics from the program corresponding to this state of file (if provided) or whole program + * The semantic diagnostics are cached and managed here + * Note that it is assumed that when asked about semantic diagnostics through this API, + * the file has been taken out of affected files so it is safe to use cache or get from program and cache the diagnostics + * In case of SemanticDiagnosticsBuilderProgram if the source file is not provided, + * it will iterate through all the affected files, to ensure that cache stays valid and yet provide a way to get all semantic diagnostics + */ getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray; + /** + * Emits the JavaScript and declaration files. + * When targetSource file is specified, emits the files corresponding to that source file, + * otherwise for the whole program. + * In case of EmitAndSemanticDiagnosticsBuilderProgram, when targetSourceFile is specified, + * it is assumed that that file is handled from affected file list. If targetSourceFile is not specified, + * it will only emit all the affected files instead of whole program + * + * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host + * in that order would be used to write the files + */ emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult; + /** + * Get the current directory of the program + */ getCurrentDirectory(): string; } + /** + * The builder that caches the semantic diagnostics for the program and handles the changed files and affected files + */ interface SemanticDiagnosticsBuilderProgram extends BuilderProgram { + /** + * Gets the semantic diagnostics from the program for the next affected file and caches it + * Returns undefined if the iteration is complete + */ getSemanticDiagnosticsOfNextAffectedFile(cancellationToken?: CancellationToken, ignoreSourceFile?: (sourceFile: SourceFile) => boolean): AffectedFileResult>; } + /** + * The builder that can handle the changes in program and iterate through changed file to emit the files + * The semantic diagnostics are cached per file and managed by clearing for the changed/affected files + */ interface EmitAndSemanticDiagnosticsBuilderProgram extends BuilderProgram { + /** + * Emits the next affected file's emit result (EmitResult and sourceFiles emitted) or returns undefined if iteration is complete + * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host + * in that order would be used to write the files + */ emitNextAffectedFile(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): AffectedFileResult; } + /** + * Create the builder to manage semantic diagnostics and cache them + */ function createSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; + /** + * Create the builder that can handle the changes in program and iterate through changed files + * to emit the those files and manage semantic diagnostics cache as well + */ function createEmitAndSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; + /** + * Creates a builder thats just abstraction over program and can be used with watch + */ function createAbstractBuilder(newProgram: Program, host: BuilderProgramHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; function createAbstractBuilder(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; } declare namespace ts { type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void; + /** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */ type CreateProgram = (rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray) => T; interface WatchCompilerHost { + /** + * Used to create the program when need for program creation or recreation detected + */ createProgram: CreateProgram; + /** If provided, callback to invoke after every new program creation */ afterProgramCreate?(program: T): void; + /** If provided, called with Diagnostic message that informs about change in watch status */ onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions): void; useCaseSensitiveFileNames(): boolean; getNewLine(): string; @@ -3532,41 +4331,92 @@ declare namespace ts { getDefaultLibFileName(options: CompilerOptions): string; getDefaultLibLocation?(): string; createHash?(data: string): string; + /** + * Use to check file presence for source files and + * if resolveModuleNames is not provided (complier is in charge of module resolution) then module files as well + */ fileExists(path: string): boolean; + /** + * Use to read file text for source files and + * if resolveModuleNames is not provided (complier is in charge of module resolution) then module files as well + */ readFile(path: string, encoding?: string): string | undefined; + /** If provided, used for module resolution as well as to handle directory structure */ directoryExists?(path: string): boolean; + /** If provided, used in resolutions as well as handling directory structure */ getDirectories?(path: string): string[]; + /** If provided, used to cache and handle directory structure modifications */ readDirectory?(path: string, extensions?: ReadonlyArray, exclude?: ReadonlyArray, include?: ReadonlyArray, depth?: number): string[]; + /** Symbol links resolution */ realpath?(path: string): string; + /** If provided would be used to write log about compilation */ trace?(s: string): void; + /** If provided is used to get the environment variable */ getEnvironmentVariable?(name: string): string | undefined; + /** If provided, used to resolve the module names, otherwise typescript's default module resolution */ resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[]; + /** If provided, used to resolve type reference directives, otherwise typescript's default resolution */ resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; + /** Used to watch changes in source files, missing files needed to update the program or config file */ watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher; + /** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */ watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher; + /** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */ setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; + /** If provided, will be used to reset existing delayed compilation */ clearTimeout?(timeoutId: any): void; } + /** + * Host to create watch with root files and options + */ interface WatchCompilerHostOfFilesAndCompilerOptions extends WatchCompilerHost { + /** root files to use to generate program */ rootFiles: string[]; + /** Compiler options */ options: CompilerOptions; } + /** + * Host to create watch with config file + */ interface WatchCompilerHostOfConfigFile extends WatchCompilerHost, ConfigFileDiagnosticsReporter { + /** Name of the config file to compile */ configFileName: string; + /** Options to extend */ optionsToExtend?: CompilerOptions; + /** + * Used to generate source file names from the config file and its include, exclude, files rules + * and also to cache the directory stucture + */ readDirectory(path: string, extensions?: ReadonlyArray, exclude?: ReadonlyArray, include?: ReadonlyArray, depth?: number): string[]; } interface Watch { + /** Synchronize with host and get updated program */ getProgram(): T; } + /** + * Creates the watch what generates program using the config file + */ interface WatchOfConfigFile extends Watch { } + /** + * Creates the watch that generates program using the root files and compiler options + */ interface WatchOfFilesAndCompilerOptions extends Watch { + /** Updates the root files in the program, only if this is not config file compilation */ updateRootFileNames(fileNames: string[]): void; } + /** + * Create the watch compiler host for either configFile or fileNames and its options + */ function createWatchCompilerHost(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfFilesAndCompilerOptions; function createWatchCompilerHost(configFileName: string, optionsToExtend: CompilerOptions | undefined, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfConfigFile; + /** + * Creates the watch from the host for root files and compiler options + */ function createWatchProgram(host: WatchCompilerHostOfFilesAndCompilerOptions): WatchOfFilesAndCompilerOptions; + /** + * Creates the watch from the host for config file + */ function createWatchProgram(host: WatchCompilerHostOfConfigFile): WatchOfConfigFile; } declare namespace ts { @@ -3576,9 +4426,28 @@ declare namespace ts { errorDiagnostic(diag: Diagnostic): void; message(diag: DiagnosticMessage, ...args: string[]): void; } + /** + * A BuildContext tracks what's going on during the course of a build. + * + * Callers may invoke any number of build requests within the same context; + * until the context is reset, each project will only be built at most once. + * + * Example: In a standard setup where project B depends on project A, and both are out of date, + * a failed build of A will result in A remaining out of date. When we try to build + * B, we should immediately bail instead of recomputing A's up-to-date status again. + * + * This also matters for performing fast (i.e. fake) downstream builds of projects + * when their upstream .d.ts files haven't changed content (but have newer timestamps) + */ interface BuildContext { options: BuildOptions; + /** + * Map from output file name to its pre-build timestamp + */ unchangedOutputs: FileMap; + /** + * Map from config file name to up-to-date status + */ projectStatus: FileMap; invalidatedProjects: FileMap; queuedProjects: FileMap; @@ -3597,23 +4466,42 @@ declare namespace ts { enum UpToDateStatusType { Unbuildable = 0, UpToDate = 1, + /** + * The project appears out of date because its upstream inputs are newer than its outputs, + * but all of its outputs are actually newer than the previous identical outputs of its (.d.ts) inputs. + * This means we can Pseudo-build (just touch timestamps), as if we had actually built this project. + */ UpToDateWithUpstreamTypes = 2, OutputMissing = 3, OutOfDateWithSelf = 4, OutOfDateWithUpstream = 5, UpstreamOutOfDate = 6, UpstreamBlocked = 7, + /** + * Projects with no outputs (i.e. "solution" files) + */ ContainerOnly = 8 } type UpToDateStatus = Status.Unbuildable | Status.UpToDate | Status.OutputMissing | Status.OutOfDateWithSelf | Status.OutOfDateWithUpstream | Status.UpstreamOutOfDate | Status.UpstreamBlocked | Status.ContainerOnly; namespace Status { + /** + * The project can't be built at all in its current state. For example, + * its config file cannot be parsed, or it has a syntax error or missing file + */ interface Unbuildable { type: UpToDateStatusType.Unbuildable; reason: string; } + /** + * This project doesn't have any outputs, so "is it up to date" is a meaningless question. + */ interface ContainerOnly { type: UpToDateStatusType.ContainerOnly; } + /** + * The project is up to date with respect to its inputs. + * We track what the newest input file is. + */ interface UpToDate { type: UpToDateStatusType.UpToDate | UpToDateStatusType.UpToDateWithUpstreamTypes; newestInputFileTime: Date; @@ -3623,23 +4511,42 @@ declare namespace ts { newestOutputFileName: string; oldestOutputFileName: string; } + /** + * One or more of the outputs of the project does not exist. + */ interface OutputMissing { type: UpToDateStatusType.OutputMissing; + /** + * The name of the first output file that didn't exist + */ missingOutputFileName: string; } + /** + * One or more of the project's outputs is older than its newest input. + */ interface OutOfDateWithSelf { type: UpToDateStatusType.OutOfDateWithSelf; outOfDateOutputFileName: string; newerInputFileName: string; } + /** + * This project depends on an out-of-date project, so shouldn't be built yet + */ interface UpstreamOutOfDate { type: UpToDateStatusType.UpstreamOutOfDate; upstreamProjectName: string; } + /** + * This project depends an upstream project with build errors + */ interface UpstreamBlocked { type: UpToDateStatusType.UpstreamBlocked; upstreamProjectName: string; } + /** + * One or more of the project's outputs is older than the newest output of + * an upstream project. + */ interface OutOfDateWithUpstream { type: UpToDateStatusType.OutOfDateWithUpstream; outOfDateOutputFileName: string; @@ -3662,6 +4569,10 @@ declare namespace ts { }; function createBuildContext(options: BuildOptions): BuildContext; function performBuild(args: string[], compilerHost: CompilerHost, buildHost: BuildHost, system?: System): number | undefined; + /** + * A SolutionBuilder has an immutable set of rootNames that are the "entry point" projects, but + * can dynamically add/remove other projects based on changes on the rootNames' references + */ function createSolutionBuilder(compilerHost: CompilerHost, buildHost: BuildHost, rootNames: ReadonlyArray, defaultOptions: BuildOptions, system?: System): { buildAllProjects: () => ExitStatus; getUpToDateStatus: (project: ParsedCommandLine | undefined) => UpToDateStatus; @@ -3675,6 +4586,9 @@ declare namespace ts { resolveProjectName: (name: string) => ResolvedConfigFileName | undefined; startWatching: () => void; }; + /** + * Gets the UpToDateStatus for a project + */ function getUpToDateStatus(host: UpToDateHost, project: ParsedCommandLine | undefined): UpToDateStatus; function getAllProjectOutputs(project: ParsedCommandLine): ReadonlyArray; function formatUpToDateStatus(configFileName: string, status: UpToDateStatus, relName: (fileName: string) => string, formatMessage: (message: DiagnosticMessage, ...args: string[]) => T): T | undefined; @@ -3754,10 +4668,25 @@ declare namespace ts { interface SourceMapSource { getLineAndCharacterOfPosition(pos: number): LineAndCharacter; } + /** + * Represents an immutable snapshot of a script at a specified time.Once acquired, the + * snapshot is observably immutable. i.e. the same calls with the same parameters will return + * the same values. + */ interface IScriptSnapshot { + /** Gets a portion of the script snapshot specified by [start, end). */ getText(start: number, end: number): string; + /** Gets the length of this script snapshot. */ getLength(): number; + /** + * Gets the TextChangeRange that describe how the text changed between this text and + * an older version. This information is used by the incremental parser to determine + * what sections of the script need to be re-parsed. 'undefined' can be returned if the + * change range cannot be determined. However, in that case, incremental parsing will + * not happen and the entire document will be re - parsed. + */ getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange | undefined; + /** Releases all resources held by this script snapshot */ dispose?(): void; } namespace ScriptSnapshot { @@ -3804,6 +4733,9 @@ declare namespace ts { getResolvedModuleWithFailedLookupLocationsFromCache?(modulename: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined; resolveTypeReferenceDirectives?(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; getDirectories?(directoryName: string): string[]; + /** + * Gets a set of custom transformers to use during emit. + */ getCustomTransformers?(): CustomTransformers | undefined; isKnownTypesPackageName?(name: string): boolean; installPackage?(options: InstallPackageOptions): Promise; @@ -3819,10 +4751,17 @@ declare namespace ts { interface LanguageService { cleanupSemanticCache(): void; getSyntacticDiagnostics(fileName: string): DiagnosticWithLocation[]; + /** The first time this is called, it will return global diagnostics (no location). */ getSemanticDiagnostics(fileName: string): Diagnostic[]; getSuggestionDiagnostics(fileName: string): DiagnosticWithLocation[]; getCompilerOptionsDiagnostics(): Diagnostic[]; + /** + * @deprecated Use getEncodedSyntacticClassifications instead. + */ getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; + /** + * @deprecated Use getEncodedSemanticClassifications instead. + */ getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications; getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications; @@ -3842,6 +4781,7 @@ declare namespace ts { getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined; findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined; getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[] | undefined; + /** @deprecated */ getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined; getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles?: boolean): NavigateToItem[]; getNavigationBarItems(fileName: string): NavigationBarItem[]; @@ -3855,6 +4795,10 @@ declare namespace ts { getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion | undefined; isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; + /** + * This will return a defined result if the position is after the `>` of the opening tag, or somewhere in the text, of a JSXElement with no closing tag. + * Editors should call this after `>` is typed. + */ getJsxClosingTagAtPosition(fileName: string, position: number): JsxClosingTagInfo | undefined; getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan | undefined; toLineColumnOffset?(fileName: string, position: number): LineAndCharacter; @@ -3863,8 +4807,11 @@ declare namespace ts { applyCodeActionCommand(action: CodeActionCommand): Promise; applyCodeActionCommand(action: CodeActionCommand[]): Promise; applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[]): Promise; + /** @deprecated `fileName` will be ignored */ applyCodeActionCommand(fileName: string, action: CodeActionCommand): Promise; + /** @deprecated `fileName` will be ignored */ applyCodeActionCommand(fileName: string, action: CodeActionCommand[]): Promise; + /** @deprecated `fileName` will be ignored */ applyCodeActionCommand(fileName: string, action: CodeActionCommand | CodeActionCommand[]): Promise; getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined): ApplicableRefactorInfo[]; getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string, preferences: UserPreferences | undefined): RefactorEditInfo | undefined; @@ -3884,8 +4831,11 @@ declare namespace ts { type OrganizeImportsScope = CombinedCodeFixScope; type CompletionsTriggerCharacter = "." | '"' | "'" | "`" | "/" | "@" | "<"; interface GetCompletionsAtPositionOptions extends UserPreferences { + /** If the editor is asking for completions because a certain character was typed, and not because the user explicitly requested them, this should be set. */ triggerCharacter?: CompletionsTriggerCharacter; + /** @deprecated Use includeCompletionsForModuleExports */ includeExternalModuleExports?: boolean; + /** @deprecated Use includeCompletionsWithInsertText */ includeInsertTextCompletions?: boolean; } interface ApplyCodeActionCommandResult { @@ -3899,6 +4849,12 @@ declare namespace ts { textSpan: TextSpan; classificationType: ClassificationTypeNames; } + /** + * Navigation bar interface designed for visual studio's dual-column layout. + * This does not form a proper tree. + * The navbar is returned as a list of top-level items, each of which has a list of child items. + * Child items always have an empty array for their `childItems`. + */ interface NavigationBarItem { text: string; kind: ScriptElementKind; @@ -3909,12 +4865,23 @@ declare namespace ts { bolded: boolean; grayed: boolean; } + /** + * Node in a tree of nested declarations in a file. + * The top node is always a script or module node. + */ interface NavigationTree { + /** Name of the declaration, or a short description, e.g. "". */ text: string; kind: ScriptElementKind; + /** ScriptElementKindModifier separated by commas, e.g. "public,abstract" */ kindModifiers: string; + /** + * Spans of the nodes that generated this declaration. + * There will be more than one if this is the result of merging. + */ spans: TextSpan[]; nameSpan: TextSpan | undefined; + /** Present if non-empty */ childItems?: NavigationTree[]; } interface TodoCommentDescriptor { @@ -3936,12 +4903,23 @@ declare namespace ts { isNewFile?: boolean; } interface CodeAction { + /** Description of the code action to display in the UI of the editor */ description: string; + /** Text changes to apply to each file as part of the code action */ changes: FileTextChanges[]; + /** + * If the user accepts the code fix, the editor should send the action back in a `applyAction` request. + * This allows the language service to have side effects (e.g. installing dependencies) upon a code fix. + */ commands?: CodeActionCommand[]; } interface CodeFixAction extends CodeAction { + /** Short name to identify the fix, for use by telemetry. */ fixName: string; + /** + * If present, one may call 'getCombinedCodeFix' with this fixId. + * This may be omitted to indicate that the code fix can't be applied in a group. + */ fixId?: {}; fixAllDescription?: string; } @@ -3952,16 +4930,49 @@ declare namespace ts { type CodeActionCommand = InstallPackageAction; interface InstallPackageAction { } + /** + * A set of one or more available refactoring actions, grouped under a parent refactoring. + */ interface ApplicableRefactorInfo { + /** + * The programmatic name of the refactoring + */ name: string; + /** + * A description of this refactoring category to show to the user. + * If the refactoring gets inlined (see below), this text will not be visible. + */ description: string; + /** + * Inlineable refactorings can have their actions hoisted out to the top level + * of a context menu. Non-inlineanable refactorings should always be shown inside + * their parent grouping. + * + * If not specified, this value is assumed to be 'true' + */ inlineable?: boolean; actions: RefactorActionInfo[]; } + /** + * Represents a single refactoring action - for example, the "Extract Method..." refactor might + * offer several actions, each corresponding to a surround class or closure to extract into. + */ interface RefactorActionInfo { + /** + * The programmatic name of the refactoring action + */ name: string; + /** + * A description of this refactoring action to show to the user. + * If the parent refactoring is inlined away, this will be the only text shown, + * so this description should make sense by itself if the parent is inlineable=true + */ description: string; } + /** + * A set of edits to make in response to a refactor action, plus an optional + * location where renaming should be invoked from + */ interface RefactorEditInfo { edits: FileTextChanges[]; renameFilename?: string; @@ -3970,11 +4981,16 @@ declare namespace ts { } interface TextInsertion { newText: string; + /** The position in newText the caret should point to after the insertion. */ caretOffset: number; } interface DocumentSpan { textSpan: TextSpan; fileName: string; + /** + * If the span represents a location that was remapped (e.g. via a .d.ts.map file), + * then the original filename and span will be specified here + */ originalTextSpan?: TextSpan; originalFileName?: string; } @@ -4146,6 +5162,13 @@ declare namespace ts { displayParts: SymbolDisplayPart[]; isOptional: boolean; } + /** + * Represents a single signature to show in signature help. + * The id is used for subsequent calls into the language service to ask questions about the + * signature help item in the context of any documents that have been updated. i.e. after + * an edit has happened, while signature help is still active, the host can ask important + * questions like 'what parameter is the user currently contained within?'. + */ interface SignatureHelpItem { isVariadic: boolean; prefixDisplayParts: SymbolDisplayPart[]; @@ -4155,6 +5178,9 @@ declare namespace ts { documentation: SymbolDisplayPart[]; tags: JSDocTagInfo[]; } + /** + * Represents a set of signature help items, and the preferred item that should be selected. + */ interface SignatureHelpItems { items: SignatureHelpItem[]; applicableSpan: TextSpan; @@ -4163,8 +5189,12 @@ declare namespace ts { argumentCount: number; } interface CompletionInfo { + /** Not true for all glboal completions. This will be true if the enclosing scope matches a few syntax kinds. See `isSnippetScope`. */ isGlobalCompletion: boolean; isMemberCompletion: boolean; + /** + * true when the current location also allows for a new identifier + */ isNewIdentifierLocation: boolean; entries: CompletionEntry[]; } @@ -4174,6 +5204,11 @@ declare namespace ts { kindModifiers?: string; sortText: string; insertText?: string; + /** + * An optional span that indicates the text to be replaced by this completion item. + * If present, this span should be used instead of the default one. + * It will be set if the required span differs from the one generated by the default replacement behavior. + */ replacementSpan?: TextSpan; hasAction?: true; source?: string; @@ -4190,16 +5225,30 @@ declare namespace ts { source?: SymbolDisplayPart[]; } interface OutliningSpan { + /** The span of the document to actually collapse. */ textSpan: TextSpan; + /** The span of the document to display when the user hovers over the collapsed span. */ hintSpan: TextSpan; + /** The text to display in the editor for the collapsed region. */ bannerText: string; + /** + * Whether or not this region should be automatically collapsed when + * the 'Collapse to Definitions' command is invoked. + */ autoCollapse: boolean; + /** + * Classification of the contents of the span + */ kind: OutliningSpanKind; } enum OutliningSpanKind { + /** Single or multi-line comments */ Comment = "comment", + /** Sections marked by '// #region' and '// #endregion' comments */ Region = "region", + /** Declarations and expressions */ Code = "code", + /** Contiguous blocks of import declarations */ Imports = "imports" } enum OutputFileType { @@ -4236,33 +5285,82 @@ declare namespace ts { classification: TokenClass; } interface Classifier { + /** + * Gives lexical classifications of tokens on a line without any syntactic context. + * For instance, a token consisting of the text 'string' can be either an identifier + * named 'string' or the keyword 'string', however, because this classifier is not aware, + * it relies on certain heuristics to give acceptable results. For classifications where + * speed trumps accuracy, this function is preferable; however, for true accuracy, the + * syntactic classifier is ideal. In fact, in certain editing scenarios, combining the + * lexical, syntactic, and semantic classifiers may issue the best user experience. + * + * @param text The text of a line to classify. + * @param lexState The state of the lexical classifier at the end of the previous line. + * @param syntacticClassifierAbsent Whether the client is *not* using a syntactic classifier. + * If there is no syntactic classifier (syntacticClassifierAbsent=true), + * certain heuristics may be used in its place; however, if there is a + * syntactic classifier (syntacticClassifierAbsent=false), certain + * classifications which may be incorrectly categorized will be given + * back as Identifiers in order to allow the syntactic classifier to + * subsume the classification. + * @deprecated Use getLexicalClassifications instead. + */ getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult; getEncodedLexicalClassifications(text: string, endOfLineState: EndOfLineState, syntacticClassifierAbsent: boolean): Classifications; } enum ScriptElementKind { unknown = "", warning = "warning", + /** predefined type (void) or keyword (class) */ keyword = "keyword", + /** top level script node */ scriptElement = "script", + /** module foo {} */ moduleElement = "module", + /** class X {} */ classElement = "class", + /** var x = class X {} */ localClassElement = "local class", + /** interface Y {} */ interfaceElement = "interface", + /** type T = ... */ typeElement = "type", + /** enum E */ enumElement = "enum", enumMemberElement = "enum member", + /** + * Inside module and script only + * const v = .. + */ variableElement = "var", + /** Inside function */ localVariableElement = "local var", + /** + * Inside module and script only + * function f() { } + */ functionElement = "function", + /** Inside function */ localFunctionElement = "local function", + /** class X { [public|private]* foo() {} } */ memberFunctionElement = "method", + /** class X { [public|private]* [get|set] foo:number; } */ memberGetAccessorElement = "getter", memberSetAccessorElement = "setter", + /** + * class X { [public|private]* foo:number; } + * interface Y { foo:number; } + */ memberVariableElement = "property", + /** class X { constructor() { } } */ constructorImplementationElement = "constructor", + /** interface Y { ():number; } */ callSignatureElement = "call", + /** interface Y { []:number; } */ indexSignatureElement = "index", + /** interface Y { new():Y; } */ constructSignatureElement = "construct", + /** function foo(*Y*: string) */ parameterElement = "parameter", typeParameterElement = "type parameter", primitiveType = "primitive type", @@ -4272,7 +5370,11 @@ declare namespace ts { letElement = "let", directory = "directory", externalModuleName = "external module name", + /** + * + */ jsxAttribute = "JSX attribute", + /** String literal */ string = "string" } enum ScriptElementKindModifier { @@ -4342,12 +5444,62 @@ declare namespace ts { function createClassifier(): Classifier; } declare namespace ts { + /** + * The document registry represents a store of SourceFile objects that can be shared between + * multiple LanguageService instances. A LanguageService instance holds on the SourceFile (AST) + * of files in the context. + * SourceFile objects account for most of the memory usage by the language service. Sharing + * the same DocumentRegistry instance between different instances of LanguageService allow + * for more efficient memory utilization since all projects will share at least the library + * file (lib.d.ts). + * + * A more advanced use of the document registry is to serialize sourceFile objects to disk + * and re-hydrate them when needed. + * + * To create a default DocumentRegistry, use createDocumentRegistry to create one, and pass it + * to all subsequent createLanguageService calls. + */ interface DocumentRegistry { + /** + * Request a stored SourceFile with a given fileName and compilationSettings. + * The first call to acquire will call createLanguageServiceSourceFile to generate + * the SourceFile if was not found in the registry. + * + * @param fileName The name of the file requested + * @param compilationSettings Some compilation settings like target affects the + * shape of a the resulting SourceFile. This allows the DocumentRegistry to store + * multiple copies of the same file for different compilation settings. + * @param scriptSnapshot Text of the file. Only used if the file was not found + * in the registry and a new one was created. + * @param version Current version of the file. Only used if the file was not found + * in the registry and a new one was created. + */ acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; acquireDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; + /** + * Request an updated version of an already existing SourceFile with a given fileName + * and compilationSettings. The update will in-turn call updateLanguageServiceSourceFile + * to get an updated SourceFile. + * + * @param fileName The name of the file requested + * @param compilationSettings Some compilation settings like target affects the + * shape of a the resulting SourceFile. This allows the DocumentRegistry to store + * multiple copies of the same file for different compilation settings. + * @param scriptSnapshot Text of the file. + * @param version Current version of the file. + */ updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; updateDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey; + /** + * Informs the DocumentRegistry that a file is not needed any longer. + * + * Note: It is not allowed to call release on a SourceFile that was not acquired from + * this registry originally. + * + * @param fileName The name of the file to be released + * @param compilationSettings The compilation settings used to acquire the file + */ releaseDocument(fileName: string, compilationSettings: CompilerOptions): void; releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey): void; reportStats(): string; @@ -4378,6 +5530,7 @@ declare namespace ts { function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[], moduleName?: string): string; } declare namespace ts { + /** The version of the language service API */ const servicesVersion = "0.8"; function toEditorSettings(options: EditorOptions | EditorSettings): EditorSettings; function displayPartsToString(displayParts: SymbolDisplayPart[] | undefined): string; @@ -4387,10 +5540,21 @@ declare namespace ts { let disableIncrementalParsing: boolean; function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange | undefined, aggressiveChecks?: boolean): SourceFile; function createLanguageService(host: LanguageServiceHost, documentRegistry?: DocumentRegistry, syntaxOnly?: boolean): LanguageService; + /** + * Get the path of the default library files (lib.d.ts) as distributed with the typescript + * node package. + * The functionality is not supported if the ts module is consumed outside of a node module. + */ function getDefaultLibFilePath(options: CompilerOptions): string; } declare namespace ts { + /** + * Transform one or more nodes using the supplied transformers. + * @param source A single `Node` or an array of `Node` objects. + * @param transformers An array of `TransformerFactory` callbacks used to process the transformation. + * @param compilerOptions Optional compiler options. + */ function transform(source: T | T[], transformers: TransformerFactory[], compilerOptions?: CompilerOptions): TransformationResult; } //# sourceMappingURL=typescriptServices.d.ts.map -export = ts; \ No newline at end of file +export = ts \ No newline at end of file diff --git a/lib/typescript.js b/lib/typescript.js index 6794e291e7c..c1ead6a1fac 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -15,22 +15,28 @@ and limitations under the License. "use strict"; -var __assign = (this && this.__assign) || Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); }; var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) { if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } return cooked; }; var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + } return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } @@ -39,10 +45,14 @@ var __extends = (this && this.__extends) || (function () { })(); var ts; (function (ts) { + // WARNING: The script `configureNightly.ts` uses a regexp to parse out these values. + // If changing the text in this section, be sure to test `configureNightly` too. ts.versionMajorMinor = "3.0"; + /** The version of the TypeScript compiler release */ ts.version = ts.versionMajorMinor + ".0-dev"; })(ts || (ts = {})); (function (ts) { + /* @internal */ var Comparison; (function (Comparison) { Comparison[Comparison["LessThan"] = -1] = "LessThan"; @@ -50,13 +60,19 @@ var ts; Comparison[Comparison["GreaterThan"] = 1] = "GreaterThan"; })(Comparison = ts.Comparison || (ts.Comparison = {})); })(ts || (ts = {})); +/* @internal */ (function (ts) { + /** Create a MapLike with good performance. */ function createDictionaryObject() { - var map = Object.create(null); + var map = Object.create(/*prototype*/ null); // tslint:disable-line:no-null-keyword + // Using 'delete' on an object causes V8 to put the object in dictionary mode. + // This disables creation of hidden classes, which are expensive when an object is + // constantly changing shape. map.__ = undefined; delete map.__; return map; } + /** Create a new map. If a template object is provided, the map will copy entries from it. */ function createMap() { return new ts.MapCtr(); } @@ -72,6 +88,8 @@ var ts; ts.createMapFromEntries = createMapFromEntries; function createMapFromTemplate(template) { var map = new ts.MapCtr(); + // Copies keys/values from template. Note that for..in will not throw if + // template is undefined, and instead will just exit the loop. for (var key in template) { if (hasOwnProperty.call(template, key)) { map.set(key, template[key]); @@ -80,9 +98,12 @@ var ts; return map; } ts.createMapFromTemplate = createMapFromTemplate; + // Internet Explorer's Map doesn't support iteration, so don't use it. + // tslint:disable-next-line no-in-operator variable-name ts.MapCtr = typeof Map !== "undefined" && "entries" in Map.prototype ? Map : shimMap(); + // Keep the class inside a function so it doesn't get compiled if it's not used. function shimMap() { - var MapIterator = (function () { + var MapIterator = /** @class */ (function () { function MapIterator(data, selector) { this.index = 0; this.data = data; @@ -99,7 +120,7 @@ var ts; }; return MapIterator; }()); - return (function () { + return /** @class */ (function () { function class_1() { this.data = createDictionaryObject(); this.size = 0; @@ -115,6 +136,7 @@ var ts; return this; }; class_1.prototype.has = function (key) { + // tslint:disable-next-line:no-in-operator return key in this.data; }; class_1.prototype.delete = function (key) { @@ -150,6 +172,11 @@ var ts; return array ? array.length : 0; } ts.length = length; + /** + * Iterates through 'array' by index and performs the callback on each element of array until the callback + * returns a truthy value, then returns that value. + * If no such value is found, the callback is applied to each element of array and undefined is returned. + */ function forEach(array, callback) { if (array) { for (var i = 0; i < array.length; i++) { @@ -162,6 +189,7 @@ var ts; return undefined; } ts.forEach = forEach; + /** Like `forEach`, but suitable for use with numbers and strings (which may be falsy). */ function firstDefined(array, callback) { if (array === undefined) { return undefined; @@ -220,6 +248,11 @@ var ts; return map; } ts.zipToMap = zipToMap; + /** + * Iterates through `array` by index and performs the callback on each element of array until the callback + * returns a falsey value, then returns false. + * If no such value is found, the callback is applied to each element of array and `true` is returned. + */ function every(array, callback) { if (array) { for (var i = 0; i < array.length; i++) { @@ -251,6 +284,7 @@ var ts; return undefined; } ts.findLast = findLast; + /** Works like Array.prototype.findIndex, returning `-1` if no element satisfying the predicate is found. */ function findIndex(array, predicate, startIndex) { for (var i = startIndex || 0; i < array.length; i++) { if (predicate(array[i], i)) { @@ -269,6 +303,10 @@ var ts; return -1; } ts.findLastIndex = findLastIndex; + /** + * Returns the first truthy result of `callback`, or else fails. + * This is like `forEach`, but never returns undefined. + */ function findMap(array, callback) { for (var i = 0; i < array.length; i++) { var result = callback(array[i], i); @@ -599,6 +637,7 @@ var ts; return false; } ts.some = some; + /** Calls the callback with (start, afterEnd) index pairs for each range where 'pred' is true. */ function getRangesWhere(arr, pred, cb) { var start; for (var i = 0; i < arr.length; i++) { @@ -625,6 +664,8 @@ var ts; } ts.concatenate = concatenate; function deduplicateRelational(array, equalityComparer, comparer) { + // Perform a stable sort of the array. This ensures the first entry in a list of + // duplicates remains the first entry in the result. var indices = array.map(function (_, i) { return i; }); stableSortIndices(array, indices, comparer); var last = array[indices[0]]; @@ -637,6 +678,7 @@ var ts; last = item; } } + // restore original order deduplicated.sort(); return deduplicated.map(function (i) { return array[i]; }); } @@ -666,10 +708,13 @@ var ts; for (var i = 1; i < array.length; i++) { var next = array[i]; switch (comparer(next, last)) { + // equality comparison case true: - case 0: + // relational comparison + case 0 /* EqualTo */: continue; - case -1: + case -1 /* LessThan */: + // If `array` is sorted, `next` should **never** be less than `last`. return Debug.fail("Array is unsorted."); } deduplicated.push(last = next); @@ -725,25 +770,41 @@ var ts; return result || array; } ts.compact = compact; + /** + * Gets the relative complement of `arrayA` with respect to `arrayB`, returning the elements that + * are not present in `arrayA` but are present in `arrayB`. Assumes both arrays are sorted + * based on the provided comparer. + */ function relativeComplement(arrayA, arrayB, comparer) { if (!arrayB || !arrayA || arrayB.length === 0 || arrayA.length === 0) return arrayB; var result = []; loopB: for (var offsetA = 0, offsetB = 0; offsetB < arrayB.length; offsetB++) { if (offsetB > 0) { - Debug.assertGreaterThanOrEqual(comparer(arrayB[offsetB], arrayB[offsetB - 1]), 0); + // Ensure `arrayB` is properly sorted. + Debug.assertGreaterThanOrEqual(comparer(arrayB[offsetB], arrayB[offsetB - 1]), 0 /* EqualTo */); } loopA: for (var startA = offsetA; offsetA < arrayA.length; offsetA++) { if (offsetA > startA) { - Debug.assertGreaterThanOrEqual(comparer(arrayA[offsetA], arrayA[offsetA - 1]), 0); + // Ensure `arrayA` is properly sorted. We only need to perform this check if + // `offsetA` has changed since we entered the loop. + Debug.assertGreaterThanOrEqual(comparer(arrayA[offsetA], arrayA[offsetA - 1]), 0 /* EqualTo */); } switch (comparer(arrayB[offsetB], arrayA[offsetA])) { - case -1: + case -1 /* LessThan */: + // If B is less than A, B does not exist in arrayA. Add B to the result and + // move to the next element in arrayB without changing the current position + // in arrayA. result.push(arrayB[offsetB]); continue loopB; - case 0: + case 0 /* EqualTo */: + // If B is equal to A, B exists in arrayA. Move to the next element in + // arrayB without adding B to the result or changing the current position + // in arrayA. continue loopB; - case 1: + case 1 /* GreaterThan */: + // If B is greater than A, we need to keep looking for B in arrayA. Move to + // the next element in arrayA and recheck. continue loopA; } } @@ -769,6 +830,10 @@ var ts; return to; } ts.append = append; + /** + * Gets the actual offset into an array for a relative offset. Negative offsets indicate a + * position offset from the end of the array. + */ function toOffset(array, offset) { return offset < 0 ? array.length + offset : offset; } @@ -787,6 +852,9 @@ var ts; return to; } ts.addRange = addRange; + /** + * @return Whether the value was added. + */ function pushIfUnique(array, toAdd, equalityComparer) { if (contains(array, toAdd, equalityComparer)) { return false; @@ -797,6 +865,9 @@ var ts; } } ts.pushIfUnique = pushIfUnique; + /** + * Unlike `pushIfUnique`, this can take `undefined` as an input, and returns a new array. + */ function appendIfUnique(array, toAdd, equalityComparer) { if (array) { pushIfUnique(array, toAdd, equalityComparer); @@ -808,8 +879,12 @@ var ts; } ts.appendIfUnique = appendIfUnique; function stableSortIndices(array, indices, comparer) { + // sort indices by value then position indices.sort(function (x, y) { return comparer(array[x], array[y]) || compareValues(x, y); }); } + /** + * Returns a new sorted array. + */ function sort(array, comparer) { return array.slice().sort(comparer); } @@ -844,6 +919,9 @@ var ts; } }; } ts.arrayIterator = arrayIterator; + /** + * Stable sort of an array. Elements equal to each other maintain their relative position in the array. + */ function stableSort(array, comparer) { var indices = array.map(function (_, i) { return i; }); stableSortIndices(array, indices, comparer); @@ -860,6 +938,10 @@ var ts; return true; } ts.rangeEquals = rangeEquals; + /** + * Returns the element at a specific offset in an array if non-empty, `undefined` otherwise. + * A negative offset indicates the element should be retrieved from the end of the array. + */ function elementAt(array, offset) { if (array) { offset = toOffset(array, offset); @@ -870,6 +952,9 @@ var ts; return undefined; } ts.elementAt = elementAt; + /** + * Returns the first element of an array if non-empty, `undefined` otherwise. + */ function firstOrUndefined(array) { return array.length === 0 ? undefined : array[0]; } @@ -879,6 +964,9 @@ var ts; return array[0]; } ts.first = first; + /** + * Returns the last element of an array if non-empty, `undefined` otherwise. + */ function lastOrUndefined(array) { return array.length === 0 ? undefined : array[array.length - 1]; } @@ -888,6 +976,9 @@ var ts; return array[array.length - 1]; } ts.last = last; + /** + * Returns the only element of an array if it contains only one element, `undefined` otherwise. + */ function singleOrUndefined(array) { return array && array.length === 1 ? array[0] @@ -906,6 +997,17 @@ var ts; return result; } ts.replaceElement = replaceElement; + /** + * Performs a binary search, finding the index at which `value` occurs in `array`. + * If no such index is found, returns the 2's-complement of first index at which + * `array[index]` exceeds `value`. + * @param array A sorted array whose first element must be no larger than number + * @param value The value to be searched for in the array. + * @param keySelector A callback used to select the search key from `value` and each element of + * `array`. + * @param keyComparer A callback used to compare two keys in a sorted array. + * @param offset An offset into `array` at which to start the search. + */ function binarySearch(array, value, keySelector, keyComparer, offset) { if (!array || array.length === 0) { return -1; @@ -917,12 +1019,12 @@ var ts; var middle = low + ((high - low) >> 1); var midKey = keySelector(array[middle]); switch (keyComparer(midKey, key)) { - case -1: + case -1 /* LessThan */: low = middle + 1; break; - case 0: + case 0 /* EqualTo */: return middle; - case 1: + case 1 /* GreaterThan */: high = middle - 1; break; } @@ -955,14 +1057,29 @@ var ts; } ts.reduceLeft = reduceLeft; var hasOwnProperty = Object.prototype.hasOwnProperty; + /** + * Indicates whether a map-like contains an own property with the specified key. + * + * @param map A map-like. + * @param key A property key. + */ function hasProperty(map, key) { return hasOwnProperty.call(map, key); } ts.hasProperty = hasProperty; + /** + * Gets the value of an owned property in a map-like. + * + * @param map A map-like. + * @param key A property key. + */ function getProperty(map, key) { return hasOwnProperty.call(map, key) ? map[key] : undefined; } ts.getProperty = getProperty; + /** + * Gets the owned, enumerable property keys of a map-like. + */ function getOwnKeys(map) { var keys = []; for (var key in map) { @@ -1001,13 +1118,19 @@ var ts; var arg = args_1[_a]; for (var p in arg) { if (hasProperty(arg, p)) { - t[p] = arg[p]; + t[p] = arg[p]; // TODO: GH#23368 } } } return t; } ts.assign = assign; + /** + * Performs a shallow equality comparison of the contents of two map-likes. + * + * @param left A map-like whose properties should be compared. + * @param right A map-like whose properties should be compared. + */ function equalOwnProperties(left, right, equalityComparer) { if (equalityComparer === void 0) { equalityComparer = equateValues; } if (left === right) @@ -1118,6 +1241,9 @@ var ts; } } } + /** + * Tests whether a value is an array. + */ function isArray(value) { return Array.isArray ? Array.isArray(value) : value instanceof Array; } @@ -1126,6 +1252,9 @@ var ts; return isArray(value) ? value : [value]; } ts.toArray = toArray; + /** + * Tests whether a value is string + */ function isString(text) { return typeof text === "string"; } @@ -1140,16 +1269,22 @@ var ts; return Debug.fail("Invalid cast. The supplied value " + value + " did not pass the test '" + Debug.getFunctionName(test) + "'."); } ts.cast = cast; - function noop(_) { } + /** Does nothing. */ + function noop(_) { } // tslint:disable-line no-empty ts.noop = noop; + /** Do nothing and return false */ function returnFalse() { return false; } ts.returnFalse = returnFalse; + /** Do nothing and return true */ function returnTrue() { return true; } ts.returnTrue = returnTrue; + /** Returns its argument. */ function identity(x) { return x; } ts.identity = identity; + /** Returns lower case string */ function toLowerCase(x) { return x.toLowerCase(); } ts.toLowerCase = toLowerCase; + /** Throws an error because a function is not implemented. */ function notImplemented() { throw new Error("Not implemented"); } @@ -1224,7 +1359,7 @@ var ts; })(AssertionLevel = ts.AssertionLevel || (ts.AssertionLevel = {})); var Debug; (function (Debug) { - Debug.currentAssertionLevel = 0; + Debug.currentAssertionLevel = 0 /* None */; Debug.isDebugging = false; function shouldAssert(level) { return Debug.currentAssertionLevel >= level; @@ -1310,6 +1445,14 @@ var ts; return a === b; } ts.equateValues = equateValues; + /** + * Compare the equality of two strings using a case-sensitive ordinal comparison. + * + * Case-sensitive comparisons compare both strings one code-point at a time using the integer + * value of each code-point after applying `toUpperCase` to each string. We always map both + * strings to their upper-case form as some unicode characters do not properly round-trip to + * lowercase (such as `ẞ` (German sharp capital s)). + */ function equateStringsCaseInsensitive(a, b) { return a === b || a !== undefined @@ -1317,37 +1460,69 @@ var ts; && a.toUpperCase() === b.toUpperCase(); } ts.equateStringsCaseInsensitive = equateStringsCaseInsensitive; + /** + * Compare the equality of two strings using a case-sensitive ordinal comparison. + * + * Case-sensitive comparisons compare both strings one code-point at a time using the + * integer value of each code-point. + */ function equateStringsCaseSensitive(a, b) { return equateValues(a, b); } ts.equateStringsCaseSensitive = equateStringsCaseSensitive; function compareComparableValues(a, b) { - return a === b ? 0 : - a === undefined ? -1 : - b === undefined ? 1 : - a < b ? -1 : - 1; + return a === b ? 0 /* EqualTo */ : + a === undefined ? -1 /* LessThan */ : + b === undefined ? 1 /* GreaterThan */ : + a < b ? -1 /* LessThan */ : + 1 /* GreaterThan */; } + /** + * Compare two numeric values for their order relative to each other. + * To compare strings, use any of the `compareStrings` functions. + */ function compareValues(a, b) { return compareComparableValues(a, b); } ts.compareValues = compareValues; function min(a, b, compare) { - return compare(a, b) === -1 ? a : b; + return compare(a, b) === -1 /* LessThan */ ? a : b; } ts.min = min; + /** + * Compare two strings using a case-insensitive ordinal comparison. + * + * Ordinal comparisons are based on the difference between the unicode code points of both + * strings. Characters with multiple unicode representations are considered unequal. Ordinal + * comparisons provide predictable ordering, but place "a" after "B". + * + * Case-insensitive comparisons compare both strings one code-point at a time using the integer + * value of each code-point after applying `toUpperCase` to each string. We always map both + * strings to their upper-case form as some unicode characters do not properly round-trip to + * lowercase (such as `ẞ` (German sharp capital s)). + */ function compareStringsCaseInsensitive(a, b) { if (a === b) - return 0; + return 0 /* EqualTo */; if (a === undefined) - return -1; + return -1 /* LessThan */; if (b === undefined) - return 1; + return 1 /* GreaterThan */; a = a.toUpperCase(); b = b.toUpperCase(); - return a < b ? -1 : a > b ? 1 : 0; + return a < b ? -1 /* LessThan */ : a > b ? 1 /* GreaterThan */ : 0 /* EqualTo */; } ts.compareStringsCaseInsensitive = compareStringsCaseInsensitive; + /** + * Compare two strings using a case-sensitive ordinal comparison. + * + * Ordinal comparisons are based on the difference between the unicode code points of both + * strings. Characters with multiple unicode representations are considered unequal. Ordinal + * comparisons provide predictable ordering, but place "a" after "B". + * + * Case-sensitive comparisons compare both strings one code-point at a time using the integer + * value of each code-point. + */ function compareStringsCaseSensitive(a, b) { return compareComparableValues(a, b); } @@ -1356,6 +1531,9 @@ var ts; return ignoreCase ? compareStringsCaseInsensitive : compareStringsCaseSensitive; } ts.getStringComparer = getStringComparer; + /** + * Creates a string comparer for use with string collation in the UI. + */ var createUIStringComparer = (function () { var defaultComparer; var enUSComparer; @@ -1363,19 +1541,22 @@ var ts; return createStringComparer; function compareWithCallback(a, b, comparer) { if (a === b) - return 0; + return 0 /* EqualTo */; if (a === undefined) - return -1; + return -1 /* LessThan */; if (b === undefined) - return 1; + return 1 /* GreaterThan */; var value = comparer(a, b); - return value < 0 ? -1 : value > 0 ? 1 : 0; + return value < 0 ? -1 /* LessThan */ : value > 0 ? 1 /* GreaterThan */ : 0 /* EqualTo */; } function createIntlCollatorStringComparer(locale) { + // Intl.Collator.prototype.compare is bound to the collator. See NOTE in + // http://www.ecma-international.org/ecma-402/2.0/#sec-Intl.Collator.prototype.compare var comparer = new Intl.Collator(locale, { usage: "sort", sensitivity: "variant" }).compare; return function (a, b) { return compareWithCallback(a, b, comparer); }; } function createLocaleCompareStringComparer(locale) { + // if the locale is not the default locale (`undefined`), use the fallback comparer. if (locale !== undefined) return createFallbackStringComparer(); return function (a, b) { return compareWithCallback(a, b, compareStrings); }; @@ -1384,26 +1565,39 @@ var ts; } } function createFallbackStringComparer() { + // An ordinal comparison puts "A" after "b", but for the UI we want "A" before "b". + // We first sort case insensitively. So "Aaa" will come before "baa". + // Then we sort case sensitively, so "aaa" will come before "Aaa". + // + // For case insensitive comparisons we always map both strings to their + // upper-case form as some unicode characters do not properly round-trip to + // lowercase (such as `ẞ` (German sharp capital s)). return function (a, b) { return compareWithCallback(a, b, compareDictionaryOrder); }; function compareDictionaryOrder(a, b) { return compareStrings(a.toUpperCase(), b.toUpperCase()) || compareStrings(a, b); } function compareStrings(a, b) { - return a < b ? -1 : a > b ? 1 : 0; + return a < b ? -1 /* LessThan */ : a > b ? 1 /* GreaterThan */ : 0 /* EqualTo */; } } function getStringComparerFactory() { + // If the host supports Intl, we use it for comparisons using the default locale. if (typeof Intl === "object" && typeof Intl.Collator === "function") { return createIntlCollatorStringComparer; } + // If the host does not support Intl, we fall back to localeCompare. + // localeCompare in Node v0.10 is just an ordinal comparison, so don't use it. if (typeof String.prototype.localeCompare === "function" && typeof String.prototype.toLocaleUpperCase === "function" && "a".localeCompare("B") < 0) { return createLocaleCompareStringComparer; } + // Otherwise, fall back to ordinal comparison: return createFallbackStringComparer; } function createStringComparer(locale) { + // Hold onto common string comparers. This avoids constantly reallocating comparers during + // tests. if (locale === undefined) { return defaultComparer || (defaultComparer = stringComparerFactory(locale)); } @@ -1428,25 +1622,50 @@ var ts; } } ts.setUILocale = setUILocale; + /** + * Compare two strings in a using the case-sensitive sort behavior of the UI locale. + * + * Ordering is not predictable between different host locales, but is best for displaying + * ordered data for UI presentation. Characters with multiple unicode representations may + * be considered equal. + * + * Case-sensitive comparisons compare strings that differ in base characters, or + * accents/diacritic marks, or case as unequal. + */ function compareStringsCaseSensitiveUI(a, b) { var comparer = uiComparerCaseSensitive || (uiComparerCaseSensitive = createUIStringComparer(uiLocale)); return comparer(a, b); } ts.compareStringsCaseSensitiveUI = compareStringsCaseSensitiveUI; function compareProperties(a, b, key, comparer) { - return a === b ? 0 : - a === undefined ? -1 : - b === undefined ? 1 : + return a === b ? 0 /* EqualTo */ : + a === undefined ? -1 /* LessThan */ : + b === undefined ? 1 /* GreaterThan */ : comparer(a[key], b[key]); } ts.compareProperties = compareProperties; + /** True is greater than false. */ function compareBooleans(a, b) { return compareValues(a ? 1 : 0, b ? 1 : 0); } ts.compareBooleans = compareBooleans; + /** + * Given a name and a list of names that are *not* equal to the name, return a spelling suggestion if there is one that is close enough. + * Names less than length 3 only check for case-insensitive equality, not Levenshtein distance. + * + * If there is a candidate that's the same except for case, return that. + * If there is a candidate that's within one edit of the name, return that. + * Otherwise, return the candidate with the smallest Levenshtein distance, + * except for candidates: + * * With no name + * * Whose length differs from the target name by more than 0.34 of the length of the name. + * * Whose levenshtein distance is more than 0.4 of the length of the name + * (0.4 allows 1 substitution/transposition for every 5 characters, + * and 1 insertion/deletion at 3 characters) + */ function getSpellingSuggestion(name, candidates, getName) { var maximumLengthDifference = Math.min(2, Math.floor(name.length * 0.34)); - var bestDistance = Math.floor(name.length * 0.4) + 1; + var bestDistance = Math.floor(name.length * 0.4) + 1; // If the best result isn't better than this, don't bother. var bestCandidate; var justCheckExactMatches = false; var nameLowerCase = name.toLowerCase(); @@ -1462,8 +1681,10 @@ var ts; continue; } if (candidateName.length < 3) { + // Don't bother, user would have noticed a 2-character name having an extra character continue; } + // Only care about a result better than the best so far. var distance = levenshteinWithMax(nameLowerCase, candidateNameLowerCase, bestDistance - 1); if (distance === undefined) { continue; @@ -1473,7 +1694,7 @@ var ts; bestCandidate = candidate; } else { - Debug.assert(distance < bestDistance); + Debug.assert(distance < bestDistance); // Else `levenshteinWithMax` should return undefined bestDistance = distance; bestCandidate = candidate; } @@ -1485,6 +1706,7 @@ var ts; function levenshteinWithMax(s1, s2, max) { var previous = new Array(s2.length + 1); var current = new Array(s2.length + 1); + /** Represents any value > max. We don't care about the particular value. */ var big = max + 1; for (var i = 0; i <= s2.length; i++) { previous[i] = i; @@ -1494,6 +1716,7 @@ var ts; var minJ = i > max ? i - max : 1; var maxJ = s2.length > max + i ? max + i : s2.length; current[0] = i; + /** Smallest value of the matrix in the ith column. */ var colMin = i; for (var j = 1; j < minJ; j++) { current[j] = big; @@ -1501,7 +1724,7 @@ var ts; for (var j = minJ; j <= maxJ; j++) { var dist = c1 === s2.charCodeAt(j - 1) ? previous[j - 1] - : Math.min(previous[j] + 1, current[j - 1] + 1, previous[j - 1] + 2); + : Math.min(/*delete*/ previous[j] + 1, /*insert*/ current[j - 1] + 1, /*substitute*/ previous[j - 1] + 2); current[j] = dist; colMin = Math.min(colMin, dist); } @@ -1509,6 +1732,7 @@ var ts; current[j] = big; } if (colMin > max) { + // Give up -- everything in this column is > max and it can't get better in future columns. return undefined; } var temp = previous; @@ -1549,11 +1773,17 @@ var ts; return false; } ts.fileExtensionIsOneOf = fileExtensionIsOneOf; + /** + * Takes a string like "jquery-min.4.2.3" and returns "jquery" + */ function removeMinAndVersionNumbers(fileName) { + // Match a "." or "-" followed by a version number or 'min' at the end of the name var trailingMinOrVersion = /[.-]((min)|(\d+(\.\d+)*))$/; + // The "min" or version may both be present, in either order, so try applying the above twice. return fileName.replace(trailingMinOrVersion, "").replace(trailingMinOrVersion, ""); } ts.removeMinAndVersionNumbers = removeMinAndVersionNumbers; + /** Remove an item from an array, moving everything to its right one space left. */ function orderedRemoveItem(array, item) { for (var i = 0; i < array.length; i++) { if (array[i] === item) { @@ -1564,7 +1794,9 @@ var ts; return false; } ts.orderedRemoveItem = orderedRemoveItem; + /** Remove an item by index from an array, moving everything to its right one space left. */ function orderedRemoveItemAt(array, index) { + // This seems to be faster than either `array.splice(i, 1)` or `array.copyWithin(i, i+ 1)`. for (var i = index; i < array.length - 1; i++) { array[i] = array[i + 1]; } @@ -1572,14 +1804,17 @@ var ts; } ts.orderedRemoveItemAt = orderedRemoveItemAt; function unorderedRemoveItemAt(array, index) { + // Fill in the "hole" left at `index`. array[index] = array[array.length - 1]; array.pop(); } ts.unorderedRemoveItemAt = unorderedRemoveItemAt; + /** Remove the *first* occurrence of `item` from the array. */ function unorderedRemoveItem(array, item) { return unorderedRemoveFirstItemWhere(array, function (element) { return element === item; }); } ts.unorderedRemoveItem = unorderedRemoveItem; + /** Remove the *first* element satisfying `predicate`. */ function unorderedRemoveFirstItemWhere(array, predicate) { for (var i = 0; i < array.length; i++) { if (predicate(array[i])) { @@ -1598,13 +1833,19 @@ var ts; return prefix + "*" + suffix; } ts.patternText = patternText; + /** + * Given that candidate matches pattern, returns the text matching the '*'. + * E.g.: matchedText(tryParsePattern("foo*baz"), "foobarbaz") === "bar" + */ function matchedText(pattern, candidate) { Debug.assert(isPatternMatch(pattern, candidate)); return candidate.substring(pattern.prefix.length, candidate.length - pattern.suffix.length); } ts.matchedText = matchedText; + /** Return the object corresponding to the best pattern to match `candidate`. */ function findBestPatternMatch(values, getPattern, candidate) { var matchedValue; + // use length of prefix as betterness criteria var longestMatchPrefixLength = -1; for (var _i = 0, values_2 = values; _i < values_2.length; _i++) { var v = values_2[_i]; @@ -1643,7 +1884,7 @@ var ts; return function (arg) { return f(arg) || g(arg); }; } ts.or = or; - function assertTypeIsNever(_) { } + function assertTypeIsNever(_) { } // tslint:disable-line no-empty ts.assertTypeIsNever = assertTypeIsNever; function singleElementArray(t) { return t === undefined ? undefined : [t]; @@ -1659,11 +1900,11 @@ var ts; var newItem = newItems[newIndex]; var oldItem = oldItems[oldIndex]; var compareResult = comparer(newItem, oldItem); - if (compareResult === -1) { + if (compareResult === -1 /* LessThan */) { inserted(newItem); newIndex++; } - else if (compareResult === 1) { + else if (compareResult === 1 /* GreaterThan */) { deleted(oldItem); oldIndex++; } @@ -1682,19 +1923,29 @@ var ts; } ts.enumerateInsertsAndDeletes = enumerateInsertsAndDeletes; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { + /** Gets a timestamp with (at least) ms resolution */ ts.timestamp = typeof performance !== "undefined" && performance.now ? function () { return performance.now(); } : Date.now ? Date.now : function () { return +(new Date()); }; })(ts || (ts = {})); +/*@internal*/ +/** Performance measurements for the compiler. */ (function (ts) { var performance; (function (performance) { + // NOTE: cannot use ts.noop as core.ts loads after this var profilerEvent = typeof onProfilerEvent === "function" && onProfilerEvent.profiler === true ? onProfilerEvent : function () { }; var enabled = false; var profilerStart = 0; var counts; var marks; var measures; + /** + * Marks a performance event. + * + * @param markName The name of the mark. + */ function mark(markName) { if (enabled) { marks.set(markName, ts.timestamp()); @@ -1703,6 +1954,15 @@ var ts; } } performance.mark = mark; + /** + * Adds a performance measurement with the specified name. + * + * @param measureName The name of the performance measurement. + * @param startMarkName The name of the starting mark. If not supplied, the point at which the + * profiler was enabled is used. + * @param endMarkName The name of the ending mark. If not supplied, the current timestamp is + * used. + */ function measure(measureName, startMarkName, endMarkName) { if (enabled) { var end = endMarkName && marks.get(endMarkName) || ts.timestamp(); @@ -1711,20 +1971,36 @@ var ts; } } performance.measure = measure; + /** + * Gets the number of times a marker was encountered. + * + * @param markName The name of the mark. + */ function getCount(markName) { return counts && counts.get(markName) || 0; } performance.getCount = getCount; + /** + * Gets the total duration of all measurements with the supplied name. + * + * @param measureName The name of the measure whose durations should be accumulated. + */ function getDuration(measureName) { return measures && measures.get(measureName) || 0; } performance.getDuration = getDuration; + /** + * Iterate over each measure, performing some action + * + * @param cb The action to perform for each measure + */ function forEachMeasure(cb) { measures.forEach(function (measure, key) { cb(key, measure); }); } performance.forEachMeasure = forEachMeasure; + /** Enables (and resets) performance measurements for the compiler. */ function enable() { counts = ts.createMap(); marks = ts.createMap(); @@ -1733,6 +2009,7 @@ var ts; profilerStart = ts.timestamp(); } performance.enable = enable; + /** Disables performance measurements for the compiler. */ function disable() { enabled = false; } @@ -1741,6 +2018,8 @@ var ts; })(ts || (ts = {})); var ts; (function (ts) { + // token > SyntaxKind.Identifier => token is a keyword + // Also, If you add a new SyntaxKind be sure to keep the `Markers` section at the bottom in sync var SyntaxKind; (function (SyntaxKind) { SyntaxKind[SyntaxKind["Unknown"] = 0] = "Unknown"; @@ -1749,17 +2028,23 @@ var ts; SyntaxKind[SyntaxKind["MultiLineCommentTrivia"] = 3] = "MultiLineCommentTrivia"; SyntaxKind[SyntaxKind["NewLineTrivia"] = 4] = "NewLineTrivia"; SyntaxKind[SyntaxKind["WhitespaceTrivia"] = 5] = "WhitespaceTrivia"; + // We detect and preserve #! on the first line SyntaxKind[SyntaxKind["ShebangTrivia"] = 6] = "ShebangTrivia"; + // We detect and provide better error recovery when we encounter a git merge marker. This + // allows us to edit files with git-conflict markers in them in a much more pleasant manner. SyntaxKind[SyntaxKind["ConflictMarkerTrivia"] = 7] = "ConflictMarkerTrivia"; + // Literals SyntaxKind[SyntaxKind["NumericLiteral"] = 8] = "NumericLiteral"; SyntaxKind[SyntaxKind["StringLiteral"] = 9] = "StringLiteral"; SyntaxKind[SyntaxKind["JsxText"] = 10] = "JsxText"; SyntaxKind[SyntaxKind["JsxTextAllWhiteSpaces"] = 11] = "JsxTextAllWhiteSpaces"; SyntaxKind[SyntaxKind["RegularExpressionLiteral"] = 12] = "RegularExpressionLiteral"; SyntaxKind[SyntaxKind["NoSubstitutionTemplateLiteral"] = 13] = "NoSubstitutionTemplateLiteral"; + // Pseudo-literals SyntaxKind[SyntaxKind["TemplateHead"] = 14] = "TemplateHead"; SyntaxKind[SyntaxKind["TemplateMiddle"] = 15] = "TemplateMiddle"; SyntaxKind[SyntaxKind["TemplateTail"] = 16] = "TemplateTail"; + // Punctuation SyntaxKind[SyntaxKind["OpenBraceToken"] = 17] = "OpenBraceToken"; SyntaxKind[SyntaxKind["CloseBraceToken"] = 18] = "CloseBraceToken"; SyntaxKind[SyntaxKind["OpenParenToken"] = 19] = "OpenParenToken"; @@ -1801,6 +2086,7 @@ var ts; SyntaxKind[SyntaxKind["QuestionToken"] = 55] = "QuestionToken"; SyntaxKind[SyntaxKind["ColonToken"] = 56] = "ColonToken"; SyntaxKind[SyntaxKind["AtToken"] = 57] = "AtToken"; + // Assignments SyntaxKind[SyntaxKind["EqualsToken"] = 58] = "EqualsToken"; SyntaxKind[SyntaxKind["PlusEqualsToken"] = 59] = "PlusEqualsToken"; SyntaxKind[SyntaxKind["MinusEqualsToken"] = 60] = "MinusEqualsToken"; @@ -1814,7 +2100,9 @@ var ts; SyntaxKind[SyntaxKind["AmpersandEqualsToken"] = 68] = "AmpersandEqualsToken"; SyntaxKind[SyntaxKind["BarEqualsToken"] = 69] = "BarEqualsToken"; SyntaxKind[SyntaxKind["CaretEqualsToken"] = 70] = "CaretEqualsToken"; + // Identifiers SyntaxKind[SyntaxKind["Identifier"] = 71] = "Identifier"; + // Reserved words SyntaxKind[SyntaxKind["BreakKeyword"] = 72] = "BreakKeyword"; SyntaxKind[SyntaxKind["CaseKeyword"] = 73] = "CaseKeyword"; SyntaxKind[SyntaxKind["CatchKeyword"] = 74] = "CatchKeyword"; @@ -1851,6 +2139,7 @@ var ts; SyntaxKind[SyntaxKind["VoidKeyword"] = 105] = "VoidKeyword"; SyntaxKind[SyntaxKind["WhileKeyword"] = 106] = "WhileKeyword"; SyntaxKind[SyntaxKind["WithKeyword"] = 107] = "WithKeyword"; + // Strict mode reserved words SyntaxKind[SyntaxKind["ImplementsKeyword"] = 108] = "ImplementsKeyword"; SyntaxKind[SyntaxKind["InterfaceKeyword"] = 109] = "InterfaceKeyword"; SyntaxKind[SyntaxKind["LetKeyword"] = 110] = "LetKeyword"; @@ -1860,6 +2149,7 @@ var ts; SyntaxKind[SyntaxKind["PublicKeyword"] = 114] = "PublicKeyword"; SyntaxKind[SyntaxKind["StaticKeyword"] = 115] = "StaticKeyword"; SyntaxKind[SyntaxKind["YieldKeyword"] = 116] = "YieldKeyword"; + // Contextual keywords SyntaxKind[SyntaxKind["AbstractKeyword"] = 117] = "AbstractKeyword"; SyntaxKind[SyntaxKind["AsKeyword"] = 118] = "AsKeyword"; SyntaxKind[SyntaxKind["AnyKeyword"] = 119] = "AnyKeyword"; @@ -1889,11 +2179,15 @@ var ts; SyntaxKind[SyntaxKind["FromKeyword"] = 143] = "FromKeyword"; SyntaxKind[SyntaxKind["GlobalKeyword"] = 144] = "GlobalKeyword"; SyntaxKind[SyntaxKind["OfKeyword"] = 145] = "OfKeyword"; + // Parse tree nodes + // Names SyntaxKind[SyntaxKind["QualifiedName"] = 146] = "QualifiedName"; SyntaxKind[SyntaxKind["ComputedPropertyName"] = 147] = "ComputedPropertyName"; + // Signature elements SyntaxKind[SyntaxKind["TypeParameter"] = 148] = "TypeParameter"; SyntaxKind[SyntaxKind["Parameter"] = 149] = "Parameter"; SyntaxKind[SyntaxKind["Decorator"] = 150] = "Decorator"; + // TypeMember SyntaxKind[SyntaxKind["PropertySignature"] = 151] = "PropertySignature"; SyntaxKind[SyntaxKind["PropertyDeclaration"] = 152] = "PropertyDeclaration"; SyntaxKind[SyntaxKind["MethodSignature"] = 153] = "MethodSignature"; @@ -1904,6 +2198,7 @@ var ts; SyntaxKind[SyntaxKind["CallSignature"] = 158] = "CallSignature"; SyntaxKind[SyntaxKind["ConstructSignature"] = 159] = "ConstructSignature"; SyntaxKind[SyntaxKind["IndexSignature"] = 160] = "IndexSignature"; + // Type SyntaxKind[SyntaxKind["TypePredicate"] = 161] = "TypePredicate"; SyntaxKind[SyntaxKind["TypeReference"] = 162] = "TypeReference"; SyntaxKind[SyntaxKind["FunctionType"] = 163] = "FunctionType"; @@ -1923,9 +2218,11 @@ var ts; SyntaxKind[SyntaxKind["MappedType"] = 177] = "MappedType"; SyntaxKind[SyntaxKind["LiteralType"] = 178] = "LiteralType"; SyntaxKind[SyntaxKind["ImportType"] = 179] = "ImportType"; + // Binding patterns SyntaxKind[SyntaxKind["ObjectBindingPattern"] = 180] = "ObjectBindingPattern"; SyntaxKind[SyntaxKind["ArrayBindingPattern"] = 181] = "ArrayBindingPattern"; SyntaxKind[SyntaxKind["BindingElement"] = 182] = "BindingElement"; + // Expression SyntaxKind[SyntaxKind["ArrayLiteralExpression"] = 183] = "ArrayLiteralExpression"; SyntaxKind[SyntaxKind["ObjectLiteralExpression"] = 184] = "ObjectLiteralExpression"; SyntaxKind[SyntaxKind["PropertyAccessExpression"] = 185] = "PropertyAccessExpression"; @@ -1954,8 +2251,10 @@ var ts; SyntaxKind[SyntaxKind["AsExpression"] = 208] = "AsExpression"; SyntaxKind[SyntaxKind["NonNullExpression"] = 209] = "NonNullExpression"; SyntaxKind[SyntaxKind["MetaProperty"] = 210] = "MetaProperty"; + // Misc SyntaxKind[SyntaxKind["TemplateSpan"] = 211] = "TemplateSpan"; SyntaxKind[SyntaxKind["SemicolonClassElement"] = 212] = "SemicolonClassElement"; + // Element SyntaxKind[SyntaxKind["Block"] = 213] = "Block"; SyntaxKind[SyntaxKind["VariableStatement"] = 214] = "VariableStatement"; SyntaxKind[SyntaxKind["EmptyStatement"] = 215] = "EmptyStatement"; @@ -1997,7 +2296,9 @@ var ts; SyntaxKind[SyntaxKind["NamedExports"] = 251] = "NamedExports"; SyntaxKind[SyntaxKind["ExportSpecifier"] = 252] = "ExportSpecifier"; SyntaxKind[SyntaxKind["MissingDeclaration"] = 253] = "MissingDeclaration"; + // Module references SyntaxKind[SyntaxKind["ExternalModuleReference"] = 254] = "ExternalModuleReference"; + // JSX SyntaxKind[SyntaxKind["JsxElement"] = 255] = "JsxElement"; SyntaxKind[SyntaxKind["JsxSelfClosingElement"] = 256] = "JsxSelfClosingElement"; SyntaxKind[SyntaxKind["JsxOpeningElement"] = 257] = "JsxOpeningElement"; @@ -2009,20 +2310,27 @@ var ts; SyntaxKind[SyntaxKind["JsxAttributes"] = 263] = "JsxAttributes"; SyntaxKind[SyntaxKind["JsxSpreadAttribute"] = 264] = "JsxSpreadAttribute"; SyntaxKind[SyntaxKind["JsxExpression"] = 265] = "JsxExpression"; + // Clauses SyntaxKind[SyntaxKind["CaseClause"] = 266] = "CaseClause"; SyntaxKind[SyntaxKind["DefaultClause"] = 267] = "DefaultClause"; SyntaxKind[SyntaxKind["HeritageClause"] = 268] = "HeritageClause"; SyntaxKind[SyntaxKind["CatchClause"] = 269] = "CatchClause"; + // Property assignments SyntaxKind[SyntaxKind["PropertyAssignment"] = 270] = "PropertyAssignment"; SyntaxKind[SyntaxKind["ShorthandPropertyAssignment"] = 271] = "ShorthandPropertyAssignment"; SyntaxKind[SyntaxKind["SpreadAssignment"] = 272] = "SpreadAssignment"; + // Enum SyntaxKind[SyntaxKind["EnumMember"] = 273] = "EnumMember"; + // Top-level nodes SyntaxKind[SyntaxKind["SourceFile"] = 274] = "SourceFile"; SyntaxKind[SyntaxKind["Bundle"] = 275] = "Bundle"; SyntaxKind[SyntaxKind["UnparsedSource"] = 276] = "UnparsedSource"; SyntaxKind[SyntaxKind["InputFiles"] = 277] = "InputFiles"; + // JSDoc nodes SyntaxKind[SyntaxKind["JSDocTypeExpression"] = 278] = "JSDocTypeExpression"; + // The * type SyntaxKind[SyntaxKind["JSDocAllType"] = 279] = "JSDocAllType"; + // The ? type SyntaxKind[SyntaxKind["JSDocUnknownType"] = 280] = "JSDocUnknownType"; SyntaxKind[SyntaxKind["JSDocNullableType"] = 281] = "JSDocNullableType"; SyntaxKind[SyntaxKind["JSDocNonNullableType"] = 282] = "JSDocNonNullableType"; @@ -2043,13 +2351,17 @@ var ts; SyntaxKind[SyntaxKind["JSDocTemplateTag"] = 297] = "JSDocTemplateTag"; SyntaxKind[SyntaxKind["JSDocTypedefTag"] = 298] = "JSDocTypedefTag"; SyntaxKind[SyntaxKind["JSDocPropertyTag"] = 299] = "JSDocPropertyTag"; + // Synthesized list SyntaxKind[SyntaxKind["SyntaxList"] = 300] = "SyntaxList"; + // Transformation nodes SyntaxKind[SyntaxKind["NotEmittedStatement"] = 301] = "NotEmittedStatement"; SyntaxKind[SyntaxKind["PartiallyEmittedExpression"] = 302] = "PartiallyEmittedExpression"; SyntaxKind[SyntaxKind["CommaListExpression"] = 303] = "CommaListExpression"; SyntaxKind[SyntaxKind["MergeDeclarationMarker"] = 304] = "MergeDeclarationMarker"; SyntaxKind[SyntaxKind["EndOfDeclarationMarker"] = 305] = "EndOfDeclarationMarker"; + // Enum value count SyntaxKind[SyntaxKind["Count"] = 306] = "Count"; + // Markers SyntaxKind[SyntaxKind["FirstAssignment"] = 58] = "FirstAssignment"; SyntaxKind[SyntaxKind["LastAssignment"] = 70] = "LastAssignment"; SyntaxKind[SyntaxKind["FirstCompoundAssignment"] = 59] = "FirstCompoundAssignment"; @@ -2079,8 +2391,8 @@ var ts; SyntaxKind[SyntaxKind["LastJSDocNode"] = 299] = "LastJSDocNode"; SyntaxKind[SyntaxKind["FirstJSDocTagNode"] = 289] = "FirstJSDocTagNode"; SyntaxKind[SyntaxKind["LastJSDocTagNode"] = 299] = "LastJSDocTagNode"; - SyntaxKind[SyntaxKind["FirstContextualKeyword"] = 117] = "FirstContextualKeyword"; - SyntaxKind[SyntaxKind["LastContextualKeyword"] = 145] = "LastContextualKeyword"; + /* @internal */ SyntaxKind[SyntaxKind["FirstContextualKeyword"] = 117] = "FirstContextualKeyword"; + /* @internal */ SyntaxKind[SyntaxKind["LastContextualKeyword"] = 145] = "LastContextualKeyword"; })(SyntaxKind = ts.SyntaxKind || (ts.SyntaxKind = {})); var NodeFlags; (function (NodeFlags) { @@ -2104,18 +2416,32 @@ var ts; NodeFlags[NodeFlags["JavaScriptFile"] = 65536] = "JavaScriptFile"; NodeFlags[NodeFlags["ThisNodeOrAnySubNodesHasError"] = 131072] = "ThisNodeOrAnySubNodesHasError"; NodeFlags[NodeFlags["HasAggregatedChildData"] = 262144] = "HasAggregatedChildData"; - NodeFlags[NodeFlags["PossiblyContainsDynamicImport"] = 524288] = "PossiblyContainsDynamicImport"; - NodeFlags[NodeFlags["PossiblyContainsImportMeta"] = 1048576] = "PossiblyContainsImportMeta"; + // These flags will be set when the parser encounters a dynamic import expression or 'import.meta' to avoid + // walking the tree if the flags are not set. However, these flags are just a approximation + // (hence why it's named "PossiblyContainsDynamicImport") because once set, the flags never get cleared. + // During editing, if a dynamic import is removed, incremental parsing will *NOT* clear this flag. + // This means that the tree will always be traversed during module resolution, or when looking for external module indicators. + // However, the removal operation should not occur often and in the case of the + // removal, it is likely that users will add the import anyway. + // The advantage of this approach is its simplicity. For the case of batch compilation, + // we guarantee that users won't have to pay the price of walking the tree if a dynamic import isn't used. + /* @internal */ NodeFlags[NodeFlags["PossiblyContainsDynamicImport"] = 524288] = "PossiblyContainsDynamicImport"; + /* @internal */ NodeFlags[NodeFlags["PossiblyContainsImportMeta"] = 1048576] = "PossiblyContainsImportMeta"; NodeFlags[NodeFlags["JSDoc"] = 2097152] = "JSDoc"; - NodeFlags[NodeFlags["Ambient"] = 4194304] = "Ambient"; - NodeFlags[NodeFlags["InWithStatement"] = 8388608] = "InWithStatement"; + /* @internal */ NodeFlags[NodeFlags["Ambient"] = 4194304] = "Ambient"; + /* @internal */ NodeFlags[NodeFlags["InWithStatement"] = 8388608] = "InWithStatement"; NodeFlags[NodeFlags["JsonFile"] = 16777216] = "JsonFile"; NodeFlags[NodeFlags["BlockScoped"] = 3] = "BlockScoped"; NodeFlags[NodeFlags["ReachabilityCheckFlags"] = 384] = "ReachabilityCheckFlags"; NodeFlags[NodeFlags["ReachabilityAndEmitFlags"] = 1408] = "ReachabilityAndEmitFlags"; + // Parsing context flags NodeFlags[NodeFlags["ContextFlags"] = 12679168] = "ContextFlags"; + // Exclude these flags when parsing a Type NodeFlags[NodeFlags["TypeExcludesFlags"] = 20480] = "TypeExcludesFlags"; - NodeFlags[NodeFlags["PermanentlySetIncrementalFlags"] = 1572864] = "PermanentlySetIncrementalFlags"; + // Represents all flags that are potentially set once and + // never cleared on SourceFiles which get re-used in between incremental parses. + // See the comment above on `PossiblyContainsDynamicImport` and `PossiblyContainsImportMeta`. + /* @internal */ NodeFlags[NodeFlags["PermanentlySetIncrementalFlags"] = 1572864] = "PermanentlySetIncrementalFlags"; })(NodeFlags = ts.NodeFlags || (ts.NodeFlags = {})); var ModifierFlags; (function (ModifierFlags) { @@ -2133,6 +2459,7 @@ var ts; ModifierFlags[ModifierFlags["Const"] = 2048] = "Const"; ModifierFlags[ModifierFlags["HasComputedFlags"] = 536870912] = "HasComputedFlags"; ModifierFlags[ModifierFlags["AccessibilityModifier"] = 28] = "AccessibilityModifier"; + // Accessibility modifiers and 'readonly' can be attached to a parameter in a constructor to make it a property. ModifierFlags[ModifierFlags["ParameterPropertyModifier"] = 92] = "ParameterPropertyModifier"; ModifierFlags[ModifierFlags["NonPublicAccessibilityModifier"] = 24] = "NonPublicAccessibilityModifier"; ModifierFlags[ModifierFlags["TypeScriptModifier"] = 2270] = "TypeScriptModifier"; @@ -2142,28 +2469,35 @@ var ts; var JsxFlags; (function (JsxFlags) { JsxFlags[JsxFlags["None"] = 0] = "None"; + /** An element from a named property of the JSX.IntrinsicElements interface */ JsxFlags[JsxFlags["IntrinsicNamedElement"] = 1] = "IntrinsicNamedElement"; + /** An element inferred from the string index signature of the JSX.IntrinsicElements interface */ JsxFlags[JsxFlags["IntrinsicIndexedElement"] = 2] = "IntrinsicIndexedElement"; JsxFlags[JsxFlags["IntrinsicElement"] = 3] = "IntrinsicElement"; })(JsxFlags = ts.JsxFlags || (ts.JsxFlags = {})); + /* @internal */ var RelationComparisonResult; (function (RelationComparisonResult) { RelationComparisonResult[RelationComparisonResult["Succeeded"] = 1] = "Succeeded"; RelationComparisonResult[RelationComparisonResult["Failed"] = 2] = "Failed"; RelationComparisonResult[RelationComparisonResult["FailedAndReported"] = 3] = "FailedAndReported"; })(RelationComparisonResult = ts.RelationComparisonResult || (ts.RelationComparisonResult = {})); + /*@internal*/ var GeneratedIdentifierFlags; (function (GeneratedIdentifierFlags) { + // Kinds GeneratedIdentifierFlags[GeneratedIdentifierFlags["None"] = 0] = "None"; GeneratedIdentifierFlags[GeneratedIdentifierFlags["Auto"] = 1] = "Auto"; GeneratedIdentifierFlags[GeneratedIdentifierFlags["Loop"] = 2] = "Loop"; GeneratedIdentifierFlags[GeneratedIdentifierFlags["Unique"] = 3] = "Unique"; GeneratedIdentifierFlags[GeneratedIdentifierFlags["Node"] = 4] = "Node"; GeneratedIdentifierFlags[GeneratedIdentifierFlags["KindMask"] = 7] = "KindMask"; + // Flags GeneratedIdentifierFlags[GeneratedIdentifierFlags["ReservedInNestedScopes"] = 8] = "ReservedInNestedScopes"; GeneratedIdentifierFlags[GeneratedIdentifierFlags["Optimistic"] = 16] = "Optimistic"; GeneratedIdentifierFlags[GeneratedIdentifierFlags["FileLevel"] = 32] = "FileLevel"; })(GeneratedIdentifierFlags = ts.GeneratedIdentifierFlags || (ts.GeneratedIdentifierFlags = {})); + /* @internal */ var TokenFlags; (function (TokenFlags) { TokenFlags[TokenFlags["None"] = 0] = "None"; @@ -2198,24 +2532,32 @@ var ts; FlowFlags[FlowFlags["Label"] = 12] = "Label"; FlowFlags[FlowFlags["Condition"] = 96] = "Condition"; })(FlowFlags = ts.FlowFlags || (ts.FlowFlags = {})); - var OperationCanceledException = (function () { + var OperationCanceledException = /** @class */ (function () { function OperationCanceledException() { } return OperationCanceledException; }()); ts.OperationCanceledException = OperationCanceledException; + /* @internal */ var StructureIsReused; (function (StructureIsReused) { StructureIsReused[StructureIsReused["Not"] = 0] = "Not"; StructureIsReused[StructureIsReused["SafeModules"] = 1] = "SafeModules"; StructureIsReused[StructureIsReused["Completely"] = 2] = "Completely"; })(StructureIsReused = ts.StructureIsReused || (ts.StructureIsReused = {})); + /** Return code used by getEmitOutput function to indicate status of the function */ var ExitStatus; (function (ExitStatus) { + // Compiler ran successfully. Either this was a simple do-nothing compilation (for example, + // when -version or -help was provided, or this was a normal compilation, no diagnostics + // were produced, and all outputs were generated successfully. ExitStatus[ExitStatus["Success"] = 0] = "Success"; + // Diagnostics were produced and because of them no code was generated. ExitStatus[ExitStatus["DiagnosticsPresent_OutputsSkipped"] = 1] = "DiagnosticsPresent_OutputsSkipped"; + // Diagnostics were produced and outputs were generated in spite of them. ExitStatus[ExitStatus["DiagnosticsPresent_OutputsGenerated"] = 2] = "DiagnosticsPresent_OutputsGenerated"; })(ExitStatus = ts.ExitStatus || (ts.ExitStatus = {})); + /* @internal */ var UnionReduction; (function (UnionReduction) { UnionReduction[UnionReduction["None"] = 0] = "None"; @@ -2225,6 +2567,7 @@ var ts; var NodeBuilderFlags; (function (NodeBuilderFlags) { NodeBuilderFlags[NodeBuilderFlags["None"] = 0] = "None"; + // Options NodeBuilderFlags[NodeBuilderFlags["NoTruncation"] = 1] = "NoTruncation"; NodeBuilderFlags[NodeBuilderFlags["WriteArrayAsGenericType"] = 2] = "WriteArrayAsGenericType"; NodeBuilderFlags[NodeBuilderFlags["GenerateNamesForShadowedTypeParams"] = 4] = "GenerateNamesForShadowedTypeParams"; @@ -2240,6 +2583,7 @@ var ts; NodeBuilderFlags[NodeBuilderFlags["UseTypeOfFunction"] = 4096] = "UseTypeOfFunction"; NodeBuilderFlags[NodeBuilderFlags["OmitParameterModifiers"] = 8192] = "OmitParameterModifiers"; NodeBuilderFlags[NodeBuilderFlags["UseAliasDefinedOutsideCurrentScope"] = 16384] = "UseAliasDefinedOutsideCurrentScope"; + // Error handling NodeBuilderFlags[NodeBuilderFlags["AllowThisInObjectLiteral"] = 32768] = "AllowThisInObjectLiteral"; NodeBuilderFlags[NodeBuilderFlags["AllowQualifedNameInPlaceOfIdentifier"] = 65536] = "AllowQualifedNameInPlaceOfIdentifier"; NodeBuilderFlags[NodeBuilderFlags["AllowAnonymousIdentifier"] = 131072] = "AllowAnonymousIdentifier"; @@ -2248,49 +2592,70 @@ var ts; NodeBuilderFlags[NodeBuilderFlags["AllowUniqueESSymbolType"] = 1048576] = "AllowUniqueESSymbolType"; NodeBuilderFlags[NodeBuilderFlags["AllowEmptyIndexInfoType"] = 2097152] = "AllowEmptyIndexInfoType"; NodeBuilderFlags[NodeBuilderFlags["IgnoreErrors"] = 3112960] = "IgnoreErrors"; + // State NodeBuilderFlags[NodeBuilderFlags["InObjectTypeLiteral"] = 4194304] = "InObjectTypeLiteral"; NodeBuilderFlags[NodeBuilderFlags["InTypeAlias"] = 8388608] = "InTypeAlias"; NodeBuilderFlags[NodeBuilderFlags["InInitialEntityName"] = 16777216] = "InInitialEntityName"; NodeBuilderFlags[NodeBuilderFlags["InReverseMappedType"] = 33554432] = "InReverseMappedType"; })(NodeBuilderFlags = ts.NodeBuilderFlags || (ts.NodeBuilderFlags = {})); + // Ensure the shared flags between this and `NodeBuilderFlags` stay in alignment var TypeFormatFlags; (function (TypeFormatFlags) { TypeFormatFlags[TypeFormatFlags["None"] = 0] = "None"; TypeFormatFlags[TypeFormatFlags["NoTruncation"] = 1] = "NoTruncation"; TypeFormatFlags[TypeFormatFlags["WriteArrayAsGenericType"] = 2] = "WriteArrayAsGenericType"; + // hole because there's a hole in node builder flags TypeFormatFlags[TypeFormatFlags["UseStructuralFallback"] = 8] = "UseStructuralFallback"; + // hole because there's a hole in node builder flags TypeFormatFlags[TypeFormatFlags["WriteTypeArgumentsOfSignature"] = 32] = "WriteTypeArgumentsOfSignature"; TypeFormatFlags[TypeFormatFlags["UseFullyQualifiedType"] = 64] = "UseFullyQualifiedType"; + // hole because `UseOnlyExternalAliasing` is here in node builder flags, but functions which take old flags use `SymbolFormatFlags` instead TypeFormatFlags[TypeFormatFlags["SuppressAnyReturnType"] = 256] = "SuppressAnyReturnType"; + // hole because `WriteTypeParametersInQualifiedName` is here in node builder flags, but functions which take old flags use `SymbolFormatFlags` for this instead TypeFormatFlags[TypeFormatFlags["MultilineObjectLiterals"] = 1024] = "MultilineObjectLiterals"; TypeFormatFlags[TypeFormatFlags["WriteClassExpressionAsTypeLiteral"] = 2048] = "WriteClassExpressionAsTypeLiteral"; TypeFormatFlags[TypeFormatFlags["UseTypeOfFunction"] = 4096] = "UseTypeOfFunction"; TypeFormatFlags[TypeFormatFlags["OmitParameterModifiers"] = 8192] = "OmitParameterModifiers"; TypeFormatFlags[TypeFormatFlags["UseAliasDefinedOutsideCurrentScope"] = 16384] = "UseAliasDefinedOutsideCurrentScope"; + // even though `T` can't be accessed in the current scope. + // Error Handling TypeFormatFlags[TypeFormatFlags["AllowUniqueESSymbolType"] = 1048576] = "AllowUniqueESSymbolType"; + // TypeFormatFlags exclusive TypeFormatFlags[TypeFormatFlags["AddUndefined"] = 131072] = "AddUndefined"; TypeFormatFlags[TypeFormatFlags["WriteArrowStyleSignature"] = 262144] = "WriteArrowStyleSignature"; + // State TypeFormatFlags[TypeFormatFlags["InArrayType"] = 524288] = "InArrayType"; TypeFormatFlags[TypeFormatFlags["InElementType"] = 2097152] = "InElementType"; TypeFormatFlags[TypeFormatFlags["InFirstTypeArgument"] = 4194304] = "InFirstTypeArgument"; TypeFormatFlags[TypeFormatFlags["InTypeAlias"] = 8388608] = "InTypeAlias"; - TypeFormatFlags[TypeFormatFlags["WriteOwnNameForAnyLike"] = 0] = "WriteOwnNameForAnyLike"; + /** @deprecated */ TypeFormatFlags[TypeFormatFlags["WriteOwnNameForAnyLike"] = 0] = "WriteOwnNameForAnyLike"; TypeFormatFlags[TypeFormatFlags["NodeBuilderFlagsMask"] = 9469291] = "NodeBuilderFlagsMask"; })(TypeFormatFlags = ts.TypeFormatFlags || (ts.TypeFormatFlags = {})); var SymbolFormatFlags; (function (SymbolFormatFlags) { SymbolFormatFlags[SymbolFormatFlags["None"] = 0] = "None"; + // Write symbols's type argument if it is instantiated symbol + // eg. class C { p: T } <-- Show p as C.p here + // var a: C; + // var p = a.p; <--- Here p is property of C so show it as C.p instead of just C.p SymbolFormatFlags[SymbolFormatFlags["WriteTypeParametersOrArguments"] = 1] = "WriteTypeParametersOrArguments"; + // Use only external alias information to get the symbol name in the given context + // eg. module m { export class c { } } import x = m.c; + // When this flag is specified m.c will be used to refer to the class instead of alias symbol x SymbolFormatFlags[SymbolFormatFlags["UseOnlyExternalAliasing"] = 2] = "UseOnlyExternalAliasing"; + // Build symbol name using any nodes needed, instead of just components of an entity name SymbolFormatFlags[SymbolFormatFlags["AllowAnyNodeKind"] = 4] = "AllowAnyNodeKind"; + // Prefer aliases which are not directly visible SymbolFormatFlags[SymbolFormatFlags["UseAliasDefinedOutsideCurrentScope"] = 8] = "UseAliasDefinedOutsideCurrentScope"; })(SymbolFormatFlags = ts.SymbolFormatFlags || (ts.SymbolFormatFlags = {})); + /* @internal */ var SymbolAccessibility; (function (SymbolAccessibility) { SymbolAccessibility[SymbolAccessibility["Accessible"] = 0] = "Accessible"; SymbolAccessibility[SymbolAccessibility["NotAccessible"] = 1] = "NotAccessible"; SymbolAccessibility[SymbolAccessibility["CannotBeNamed"] = 2] = "CannotBeNamed"; })(SymbolAccessibility = ts.SymbolAccessibility || (ts.SymbolAccessibility = {})); + /* @internal */ var SyntheticSymbolKind; (function (SyntheticSymbolKind) { SyntheticSymbolKind[SyntheticSymbolKind["UnionOrIntersection"] = 0] = "UnionOrIntersection"; @@ -2301,10 +2666,16 @@ var ts; TypePredicateKind[TypePredicateKind["This"] = 0] = "This"; TypePredicateKind[TypePredicateKind["Identifier"] = 1] = "Identifier"; })(TypePredicateKind = ts.TypePredicateKind || (ts.TypePredicateKind = {})); + /** Indicates how to serialize the name for a TypeReferenceNode when emitting decorator metadata */ + /* @internal */ var TypeReferenceSerializationKind; (function (TypeReferenceSerializationKind) { TypeReferenceSerializationKind[TypeReferenceSerializationKind["Unknown"] = 0] = "Unknown"; + // should be emitted using a safe fallback. TypeReferenceSerializationKind[TypeReferenceSerializationKind["TypeWithConstructSignatureAndValue"] = 1] = "TypeWithConstructSignatureAndValue"; + // function that can be reached at runtime (e.g. a `class` + // declaration or a `var` declaration for the static side + // of a type, such as the global `Promise` type in lib.d.ts). TypeReferenceSerializationKind[TypeReferenceSerializationKind["VoidNullableOrNeverType"] = 2] = "VoidNullableOrNeverType"; TypeReferenceSerializationKind[TypeReferenceSerializationKind["NumberLikeType"] = 3] = "NumberLikeType"; TypeReferenceSerializationKind[TypeReferenceSerializationKind["StringLikeType"] = 4] = "StringLikeType"; @@ -2313,6 +2684,7 @@ var ts; TypeReferenceSerializationKind[TypeReferenceSerializationKind["ESSymbolType"] = 7] = "ESSymbolType"; TypeReferenceSerializationKind[TypeReferenceSerializationKind["Promise"] = 8] = "Promise"; TypeReferenceSerializationKind[TypeReferenceSerializationKind["TypeWithCallSignature"] = 9] = "TypeWithCallSignature"; + // with call signatures. TypeReferenceSerializationKind[TypeReferenceSerializationKind["ObjectType"] = 10] = "ObjectType"; })(TypeReferenceSerializationKind = ts.TypeReferenceSerializationKind || (ts.TypeReferenceSerializationKind = {})); var SymbolFlags; @@ -2345,6 +2717,7 @@ var ts; SymbolFlags[SymbolFlags["Optional"] = 16777216] = "Optional"; SymbolFlags[SymbolFlags["Transient"] = 33554432] = "Transient"; SymbolFlags[SymbolFlags["JSContainer"] = 67108864] = "JSContainer"; + /* @internal */ SymbolFlags[SymbolFlags["All"] = 67108863] = "All"; SymbolFlags[SymbolFlags["Enum"] = 384] = "Enum"; SymbolFlags[SymbolFlags["Variable"] = 3] = "Variable"; @@ -2353,7 +2726,11 @@ var ts; SymbolFlags[SymbolFlags["Namespace"] = 1920] = "Namespace"; SymbolFlags[SymbolFlags["Module"] = 1536] = "Module"; SymbolFlags[SymbolFlags["Accessor"] = 98304] = "Accessor"; + // Variables can be redeclared, but can not redeclare a block-scoped declaration with the + // same name, or any other value that is not a variable, e.g. ValueModule or Class SymbolFlags[SymbolFlags["FunctionScopedVariableExcludes"] = 67216318] = "FunctionScopedVariableExcludes"; + // Block-scoped declarations are not allowed to be re-declared + // they can not merge with anything in the value space SymbolFlags[SymbolFlags["BlockScopedVariableExcludes"] = 67216319] = "BlockScopedVariableExcludes"; SymbolFlags[SymbolFlags["ParameterExcludes"] = 67216319] = "ParameterExcludes"; SymbolFlags[SymbolFlags["PropertyExcludes"] = 0] = "PropertyExcludes"; @@ -2378,14 +2755,20 @@ var ts; SymbolFlags[SymbolFlags["BlockScoped"] = 418] = "BlockScoped"; SymbolFlags[SymbolFlags["PropertyOrAccessor"] = 98308] = "PropertyOrAccessor"; SymbolFlags[SymbolFlags["ClassMember"] = 106500] = "ClassMember"; + /* @internal */ + // The set of things we consider semantically classifiable. Used to speed up the LS during + // classification. SymbolFlags[SymbolFlags["Classifiable"] = 2885600] = "Classifiable"; + /* @internal */ SymbolFlags[SymbolFlags["LateBindingContainer"] = 6240] = "LateBindingContainer"; })(SymbolFlags = ts.SymbolFlags || (ts.SymbolFlags = {})); + /* @internal */ var EnumKind; (function (EnumKind) { EnumKind[EnumKind["Numeric"] = 0] = "Numeric"; - EnumKind[EnumKind["Literal"] = 1] = "Literal"; + EnumKind[EnumKind["Literal"] = 1] = "Literal"; // Literal enum (each member has a TypeFlags.EnumLiteral type) })(EnumKind = ts.EnumKind || (ts.EnumKind = {})); + /* @internal */ var CheckFlags; (function (CheckFlags) { CheckFlags[CheckFlags["Instantiated"] = 1] = "Instantiated"; @@ -2421,6 +2804,7 @@ var ts; InternalSymbolName["ExportEquals"] = "export="; InternalSymbolName["Default"] = "default"; })(InternalSymbolName = ts.InternalSymbolName || (ts.InternalSymbolName = {})); + /* @internal */ var NodeCheckFlags; (function (NodeCheckFlags) { NodeCheckFlags[NodeCheckFlags["TypeChecked"] = 1] = "TypeChecked"; @@ -2472,20 +2856,31 @@ var ts; TypeFlags[TypeFlags["Conditional"] = 4194304] = "Conditional"; TypeFlags[TypeFlags["Substitution"] = 8388608] = "Substitution"; TypeFlags[TypeFlags["NonPrimitive"] = 16777216] = "NonPrimitive"; + /* @internal */ TypeFlags[TypeFlags["FreshLiteral"] = 33554432] = "FreshLiteral"; + /* @internal */ TypeFlags[TypeFlags["UnionOfUnitTypes"] = 67108864] = "UnionOfUnitTypes"; + /* @internal */ TypeFlags[TypeFlags["ContainsWideningType"] = 134217728] = "ContainsWideningType"; + /* @internal */ TypeFlags[TypeFlags["ContainsObjectLiteral"] = 268435456] = "ContainsObjectLiteral"; + /* @internal */ TypeFlags[TypeFlags["ContainsAnyFunctionType"] = 536870912] = "ContainsAnyFunctionType"; + /* @internal */ TypeFlags[TypeFlags["AnyOrUnknown"] = 3] = "AnyOrUnknown"; + /* @internal */ TypeFlags[TypeFlags["Nullable"] = 24576] = "Nullable"; TypeFlags[TypeFlags["Literal"] = 448] = "Literal"; TypeFlags[TypeFlags["Unit"] = 27072] = "Unit"; TypeFlags[TypeFlags["StringOrNumberLiteral"] = 192] = "StringOrNumberLiteral"; + /* @internal */ TypeFlags[TypeFlags["StringOrNumberLiteralOrUnique"] = 2240] = "StringOrNumberLiteralOrUnique"; + /* @internal */ TypeFlags[TypeFlags["DefinitelyFalsy"] = 29120] = "DefinitelyFalsy"; TypeFlags[TypeFlags["PossiblyFalsy"] = 29148] = "PossiblyFalsy"; + /* @internal */ TypeFlags[TypeFlags["Intrinsic"] = 16839967] = "Intrinsic"; + /* @internal */ TypeFlags[TypeFlags["Primitive"] = 32764] = "Primitive"; TypeFlags[TypeFlags["StringLike"] = 68] = "StringLike"; TypeFlags[TypeFlags["NumberLike"] = 168] = "NumberLike"; @@ -2493,6 +2888,7 @@ var ts; TypeFlags[TypeFlags["EnumLike"] = 544] = "EnumLike"; TypeFlags[TypeFlags["ESSymbolLike"] = 3072] = "ESSymbolLike"; TypeFlags[TypeFlags["VoidLike"] = 12288] = "VoidLike"; + /* @internal */ TypeFlags[TypeFlags["DisjointDomains"] = 16809468] = "DisjointDomains"; TypeFlags[TypeFlags["UnionOrIntersection"] = 786432] = "UnionOrIntersection"; TypeFlags[TypeFlags["StructuredType"] = 917504] = "StructuredType"; @@ -2501,15 +2897,27 @@ var ts; TypeFlags[TypeFlags["InstantiablePrimitive"] = 1048576] = "InstantiablePrimitive"; TypeFlags[TypeFlags["Instantiable"] = 15794176] = "Instantiable"; TypeFlags[TypeFlags["StructuredOrInstantiable"] = 16711680] = "StructuredOrInstantiable"; + // 'Narrowable' types are types where narrowing actually narrows. + // This *should* be every type other than null, undefined, void, and never TypeFlags[TypeFlags["Narrowable"] = 33492479] = "Narrowable"; TypeFlags[TypeFlags["NotUnionOrUnit"] = 16909315] = "NotUnionOrUnit"; + /* @internal */ TypeFlags[TypeFlags["NotUnit"] = 16749629] = "NotUnit"; + /* @internal */ TypeFlags[TypeFlags["RequiresWidening"] = 402653184] = "RequiresWidening"; + /* @internal */ TypeFlags[TypeFlags["PropagatingFlags"] = 939524096] = "PropagatingFlags"; + // The following flags are used for different purposes during union and intersection type construction + /* @internal */ TypeFlags[TypeFlags["NonWideningType"] = 134217728] = "NonWideningType"; + /* @internal */ TypeFlags[TypeFlags["Wildcard"] = 268435456] = "Wildcard"; + /* @internal */ TypeFlags[TypeFlags["EmptyObject"] = 536870912] = "EmptyObject"; + /* @internal */ TypeFlags[TypeFlags["ConstructionFlags"] = 939524096] = "ConstructionFlags"; + // The following flag is used for different purposes by maybeTypeOfKind + /* @internal */ TypeFlags[TypeFlags["GenericMappedType"] = 134217728] = "GenericMappedType"; })(TypeFlags = ts.TypeFlags || (ts.TypeFlags = {})); var ObjectFlags; @@ -2530,6 +2938,7 @@ var ts; ObjectFlags[ObjectFlags["MarkerType"] = 8192] = "MarkerType"; ObjectFlags[ObjectFlags["ClassOrInterface"] = 3] = "ClassOrInterface"; })(ObjectFlags = ts.ObjectFlags || (ts.ObjectFlags = {})); + /* @internal */ var Variance; (function (Variance) { Variance[Variance["Invariant"] = 0] = "Invariant"; @@ -2559,6 +2968,7 @@ var ts; InferencePriority[InferencePriority["AlwaysStrict"] = 64] = "AlwaysStrict"; InferencePriority[InferencePriority["PriorityImpliesCombination"] = 28] = "PriorityImpliesCombination"; })(InferencePriority = ts.InferencePriority || (ts.InferencePriority = {})); + /* @internal */ var InferenceFlags; (function (InferenceFlags) { InferenceFlags[InferenceFlags["None"] = 0] = "None"; @@ -2566,20 +2976,37 @@ var ts; InferenceFlags[InferenceFlags["NoDefault"] = 2] = "NoDefault"; InferenceFlags[InferenceFlags["AnyDefault"] = 4] = "AnyDefault"; })(InferenceFlags = ts.InferenceFlags || (ts.InferenceFlags = {})); + /** + * Ternary values are defined such that + * x & y is False if either x or y is False. + * x & y is Maybe if either x or y is Maybe, but neither x or y is False. + * x & y is True if both x and y are True. + * x | y is False if both x and y are False. + * x | y is Maybe if either x or y is Maybe, but neither x or y is True. + * x | y is True if either x or y is True. + */ + /* @internal */ var Ternary; (function (Ternary) { Ternary[Ternary["False"] = 0] = "False"; Ternary[Ternary["Maybe"] = 1] = "Maybe"; Ternary[Ternary["True"] = -1] = "True"; })(Ternary = ts.Ternary || (ts.Ternary = {})); + /* @internal */ var SpecialPropertyAssignmentKind; (function (SpecialPropertyAssignmentKind) { SpecialPropertyAssignmentKind[SpecialPropertyAssignmentKind["None"] = 0] = "None"; + /// exports.name = expr SpecialPropertyAssignmentKind[SpecialPropertyAssignmentKind["ExportsProperty"] = 1] = "ExportsProperty"; + /// module.exports = expr SpecialPropertyAssignmentKind[SpecialPropertyAssignmentKind["ModuleExports"] = 2] = "ModuleExports"; + /// className.prototype.name = expr SpecialPropertyAssignmentKind[SpecialPropertyAssignmentKind["PrototypeProperty"] = 3] = "PrototypeProperty"; + /// this.name = expr SpecialPropertyAssignmentKind[SpecialPropertyAssignmentKind["ThisProperty"] = 4] = "ThisProperty"; + // F.name = expr SpecialPropertyAssignmentKind[SpecialPropertyAssignmentKind["Property"] = 5] = "Property"; + // F.prototype = { ... } SpecialPropertyAssignmentKind[SpecialPropertyAssignmentKind["Prototype"] = 6] = "Prototype"; })(SpecialPropertyAssignmentKind = ts.SpecialPropertyAssignmentKind || (ts.SpecialPropertyAssignmentKind = {})); var DiagnosticCategory; @@ -2589,6 +3016,7 @@ var ts; DiagnosticCategory[DiagnosticCategory["Suggestion"] = 2] = "Suggestion"; DiagnosticCategory[DiagnosticCategory["Message"] = 3] = "Message"; })(DiagnosticCategory = ts.DiagnosticCategory || (ts.DiagnosticCategory = {})); + /* @internal */ function diagnosticCategoryName(d, lowerCase) { if (lowerCase === void 0) { lowerCase = true; } var name = DiagnosticCategory[d.category]; @@ -2631,6 +3059,10 @@ var ts; ScriptKind[ScriptKind["TSX"] = 4] = "TSX"; ScriptKind[ScriptKind["External"] = 5] = "External"; ScriptKind[ScriptKind["JSON"] = 6] = "JSON"; + /** + * Used on extensions that doesn't define the ScriptKind but the content defines it. + * Deferred extensions are going to be included in all project contexts. + */ ScriptKind[ScriptKind["Deferred"] = 7] = "Deferred"; })(ScriptKind = ts.ScriptKind || (ts.ScriptKind = {})); var ScriptTarget; @@ -2655,6 +3087,7 @@ var ts; WatchDirectoryFlags[WatchDirectoryFlags["None"] = 0] = "None"; WatchDirectoryFlags[WatchDirectoryFlags["Recursive"] = 1] = "Recursive"; })(WatchDirectoryFlags = ts.WatchDirectoryFlags || (ts.WatchDirectoryFlags = {})); + /* @internal */ var CharacterCodes; (function (CharacterCodes) { CharacterCodes[CharacterCodes["nullCharacter"] = 0] = "nullCharacter"; @@ -2664,6 +3097,7 @@ var ts; CharacterCodes[CharacterCodes["lineSeparator"] = 8232] = "lineSeparator"; CharacterCodes[CharacterCodes["paragraphSeparator"] = 8233] = "paragraphSeparator"; CharacterCodes[CharacterCodes["nextLine"] = 133] = "nextLine"; + // Unicode 3.0 space characters CharacterCodes[CharacterCodes["space"] = 32] = "space"; CharacterCodes[CharacterCodes["nonBreakingSpace"] = 160] = "nonBreakingSpace"; CharacterCodes[CharacterCodes["enQuad"] = 8192] = "enQuad"; @@ -2791,9 +3225,12 @@ var ts; Extension["Jsx"] = ".jsx"; Extension["Json"] = ".json"; })(Extension = ts.Extension || (ts.Extension = {})); + /* @internal */ var TransformFlags; (function (TransformFlags) { TransformFlags[TransformFlags["None"] = 0] = "None"; + // Facts + // - Flags used to indicate that a node or subtree contains syntax that requires transformation. TransformFlags[TransformFlags["TypeScript"] = 1] = "TypeScript"; TransformFlags[TransformFlags["ContainsTypeScript"] = 2] = "ContainsTypeScript"; TransformFlags[TransformFlags["ContainsJsx"] = 4] = "ContainsJsx"; @@ -2806,6 +3243,8 @@ var ts; TransformFlags[TransformFlags["ContainsGenerator"] = 512] = "ContainsGenerator"; TransformFlags[TransformFlags["DestructuringAssignment"] = 1024] = "DestructuringAssignment"; TransformFlags[TransformFlags["ContainsDestructuringAssignment"] = 2048] = "ContainsDestructuringAssignment"; + // Markers + // - Flags used to indicate that a subtree contains a specific transformation. TransformFlags[TransformFlags["ContainsDecorators"] = 4096] = "ContainsDecorators"; TransformFlags[TransformFlags["ContainsPropertyInitializer"] = 8192] = "ContainsPropertyInitializer"; TransformFlags[TransformFlags["ContainsLexicalThis"] = 16384] = "ContainsLexicalThis"; @@ -2825,7 +3264,12 @@ var ts; TransformFlags[TransformFlags["ContainsDynamicImport"] = 67108864] = "ContainsDynamicImport"; TransformFlags[TransformFlags["Super"] = 134217728] = "Super"; TransformFlags[TransformFlags["ContainsSuper"] = 268435456] = "ContainsSuper"; + // Please leave this as 1 << 29. + // It is the maximum bit we can set before we outgrow the size of a v8 small integer (SMI) on an x86 system. + // It is a good reminder of how much room we have left TransformFlags[TransformFlags["HasComputedFlags"] = 536870912] = "HasComputedFlags"; + // Assertions + // - Bitmasks that are used to assert facts about the syntax of a node and its subtree. TransformFlags[TransformFlags["AssertTypeScript"] = 3] = "AssertTypeScript"; TransformFlags[TransformFlags["AssertJsx"] = 4] = "AssertJsx"; TransformFlags[TransformFlags["AssertESNext"] = 8] = "AssertESNext"; @@ -2834,6 +3278,9 @@ var ts; TransformFlags[TransformFlags["AssertES2015"] = 192] = "AssertES2015"; TransformFlags[TransformFlags["AssertGenerator"] = 768] = "AssertGenerator"; TransformFlags[TransformFlags["AssertDestructuringAssignment"] = 3072] = "AssertDestructuringAssignment"; + // Scope Exclusions + // - Bitmasks that exclude flags from propagating out of a specific context + // into the subtree flags of their container. TransformFlags[TransformFlags["OuterExpressionExcludes"] = 536872257] = "OuterExpressionExcludes"; TransformFlags[TransformFlags["PropertyAccessExcludes"] = 671089985] = "PropertyAccessExcludes"; TransformFlags[TransformFlags["NodeExcludes"] = 939525441] = "NodeExcludes"; @@ -2850,6 +3297,8 @@ var ts; TransformFlags[TransformFlags["ParameterExcludes"] = 939525441] = "ParameterExcludes"; TransformFlags[TransformFlags["CatchClauseExcludes"] = 940574017] = "CatchClauseExcludes"; TransformFlags[TransformFlags["BindingPatternExcludes"] = 940049729] = "BindingPatternExcludes"; + // Masks + // - Additional bitmasks TransformFlags[TransformFlags["TypeScriptClassSyntaxMask"] = 274432] = "TypeScriptClassSyntaxMask"; TransformFlags[TransformFlags["ES2015FunctionSyntaxMask"] = 163840] = "ES2015FunctionSyntaxMask"; })(TransformFlags = ts.TransformFlags || (ts.TransformFlags = {})); @@ -2884,9 +3333,14 @@ var ts; EmitFlags[EmitFlags["HasEndOfDeclarationMarker"] = 4194304] = "HasEndOfDeclarationMarker"; EmitFlags[EmitFlags["Iterator"] = 8388608] = "Iterator"; EmitFlags[EmitFlags["NoAsciiEscaping"] = 16777216] = "NoAsciiEscaping"; - EmitFlags[EmitFlags["TypeScriptClassWrapper"] = 33554432] = "TypeScriptClassWrapper"; - EmitFlags[EmitFlags["NeverApplyImportHelper"] = 67108864] = "NeverApplyImportHelper"; + /*@internal*/ EmitFlags[EmitFlags["TypeScriptClassWrapper"] = 33554432] = "TypeScriptClassWrapper"; + /*@internal*/ EmitFlags[EmitFlags["NeverApplyImportHelper"] = 67108864] = "NeverApplyImportHelper"; })(EmitFlags = ts.EmitFlags || (ts.EmitFlags = {})); + /** + * Used by the checker, this enum keeps track of external emit helpers that should be type + * checked. + */ + /* @internal */ var ExternalEmitHelpers; (function (ExternalEmitHelpers) { ExternalEmitHelpers[ExternalEmitHelpers["Extends"] = 1] = "Extends"; @@ -2908,10 +3362,15 @@ var ts; ExternalEmitHelpers[ExternalEmitHelpers["MakeTemplateObject"] = 65536] = "MakeTemplateObject"; ExternalEmitHelpers[ExternalEmitHelpers["FirstEmitHelper"] = 1] = "FirstEmitHelper"; ExternalEmitHelpers[ExternalEmitHelpers["LastEmitHelper"] = 65536] = "LastEmitHelper"; + // Helpers included by ES2015 for..of ExternalEmitHelpers[ExternalEmitHelpers["ForOfIncludes"] = 256] = "ForOfIncludes"; + // Helpers included by ES2017 for..await..of ExternalEmitHelpers[ExternalEmitHelpers["ForAwaitOfIncludes"] = 16384] = "ForAwaitOfIncludes"; + // Helpers included by ES2017 async generators ExternalEmitHelpers[ExternalEmitHelpers["AsyncGeneratorIncludes"] = 6144] = "AsyncGeneratorIncludes"; + // Helpers included by yield* in ES2017 async generators ExternalEmitHelpers[ExternalEmitHelpers["AsyncDelegatorIncludes"] = 26624] = "AsyncDelegatorIncludes"; + // Helpers included by ES2015 spread ExternalEmitHelpers[ExternalEmitHelpers["SpreadIncludes"] = 1536] = "SpreadIncludes"; })(ExternalEmitHelpers = ts.ExternalEmitHelpers || (ts.ExternalEmitHelpers = {})); var EmitHint; @@ -2925,19 +3384,23 @@ var ts; var ListFormat; (function (ListFormat) { ListFormat[ListFormat["None"] = 0] = "None"; + // Line separators ListFormat[ListFormat["SingleLine"] = 0] = "SingleLine"; ListFormat[ListFormat["MultiLine"] = 1] = "MultiLine"; ListFormat[ListFormat["PreserveLines"] = 2] = "PreserveLines"; ListFormat[ListFormat["LinesMask"] = 3] = "LinesMask"; + // Delimiters ListFormat[ListFormat["NotDelimited"] = 0] = "NotDelimited"; ListFormat[ListFormat["BarDelimited"] = 4] = "BarDelimited"; ListFormat[ListFormat["AmpersandDelimited"] = 8] = "AmpersandDelimited"; ListFormat[ListFormat["CommaDelimited"] = 16] = "CommaDelimited"; ListFormat[ListFormat["DelimitersMask"] = 28] = "DelimitersMask"; ListFormat[ListFormat["AllowTrailingComma"] = 32] = "AllowTrailingComma"; + // Whitespace ListFormat[ListFormat["Indented"] = 64] = "Indented"; ListFormat[ListFormat["SpaceBetweenBraces"] = 128] = "SpaceBetweenBraces"; ListFormat[ListFormat["SpaceBetweenSiblings"] = 256] = "SpaceBetweenSiblings"; + // Brackets/Braces ListFormat[ListFormat["Braces"] = 512] = "Braces"; ListFormat[ListFormat["Parenthesis"] = 1024] = "Parenthesis"; ListFormat[ListFormat["AngleBrackets"] = 2048] = "AngleBrackets"; @@ -2946,11 +3409,13 @@ var ts; ListFormat[ListFormat["OptionalIfUndefined"] = 8192] = "OptionalIfUndefined"; ListFormat[ListFormat["OptionalIfEmpty"] = 16384] = "OptionalIfEmpty"; ListFormat[ListFormat["Optional"] = 24576] = "Optional"; + // Other ListFormat[ListFormat["PreferNewLine"] = 32768] = "PreferNewLine"; ListFormat[ListFormat["NoTrailingNewLine"] = 65536] = "NoTrailingNewLine"; ListFormat[ListFormat["NoInterveningComments"] = 131072] = "NoInterveningComments"; ListFormat[ListFormat["NoSpaceIfEmpty"] = 262144] = "NoSpaceIfEmpty"; ListFormat[ListFormat["SingleElement"] = 524288] = "SingleElement"; + // Precomputed Formats ListFormat[ListFormat["Modifiers"] = 131328] = "Modifiers"; ListFormat[ListFormat["HeritageClauses"] = 256] = "HeritageClauses"; ListFormat[ListFormat["SingleLineTypeLiteralMembers"] = 384] = "SingleLineTypeLiteralMembers"; @@ -2988,18 +3453,40 @@ var ts; ListFormat[ListFormat["Parameters"] = 1296] = "Parameters"; ListFormat[ListFormat["IndexSignatureParameters"] = 4432] = "IndexSignatureParameters"; })(ListFormat = ts.ListFormat || (ts.ListFormat = {})); + /* @internal */ var PragmaKindFlags; (function (PragmaKindFlags) { PragmaKindFlags[PragmaKindFlags["None"] = 0] = "None"; + /** + * Triple slash comment of the form + * /// + */ PragmaKindFlags[PragmaKindFlags["TripleSlashXML"] = 1] = "TripleSlashXML"; + /** + * Single line comment of the form + * // @pragma-name argval1 argval2 + * or + * /// @pragma-name argval1 argval2 + */ PragmaKindFlags[PragmaKindFlags["SingleLine"] = 2] = "SingleLine"; + /** + * Multiline non-jsdoc pragma of the form + * /* @pragma-name argval1 argval2 * / + */ PragmaKindFlags[PragmaKindFlags["MultiLine"] = 4] = "MultiLine"; PragmaKindFlags[PragmaKindFlags["All"] = 7] = "All"; PragmaKindFlags[PragmaKindFlags["Default"] = 7] = "Default"; })(PragmaKindFlags = ts.PragmaKindFlags || (ts.PragmaKindFlags = {})); + /** + * This function only exists to cause exact types to be inferred for all the literals within `commentPragmas` + */ + /* @internal */ function _contextuallyTypePragmas(args) { return args; } + // While not strictly a type, this is here because `PragmaMap` needs to be here to be used with `SourceFile`, and we don't + // fancy effectively defining it twice, once in value-space and once in type-space + /* @internal */ ts.commentPragmas = _contextuallyTypePragmas({ "reference": { args: [ @@ -3008,32 +3495,38 @@ var ts; { name: "path", optional: true, captureSpan: true }, { name: "no-default-lib", optional: true } ], - kind: 1 + kind: 1 /* TripleSlashXML */ }, "amd-dependency": { args: [{ name: "path" }, { name: "name", optional: true }], - kind: 1 + kind: 1 /* TripleSlashXML */ }, "amd-module": { args: [{ name: "name" }], - kind: 1 + kind: 1 /* TripleSlashXML */ }, "ts-check": { - kind: 2 + kind: 2 /* SingleLine */ }, "ts-nocheck": { - kind: 2 + kind: 2 /* SingleLine */ }, "jsx": { args: [{ name: "factory" }], - kind: 4 + kind: 4 /* MultiLine */ }, }); })(ts || (ts = {})); var ts; (function (ts) { + /** + * Set a high stack trace limit to provide more information in case of an error. + * Called for command-line and server use cases. + * Not called if TypeScript is used as a library. + */ + /* @internal */ function setStackTraceLimit() { - if (Error.stackTraceLimit < 100) { + if (Error.stackTraceLimit < 100) { // Also tests that we won't set the property if it doesn't exist. Error.stackTraceLimit = 100; } } @@ -3044,6 +3537,7 @@ var ts; FileWatcherEventKind[FileWatcherEventKind["Changed"] = 1] = "Changed"; FileWatcherEventKind[FileWatcherEventKind["Deleted"] = 2] = "Deleted"; })(FileWatcherEventKind = ts.FileWatcherEventKind || (ts.FileWatcherEventKind = {})); + /* @internal */ var PollingInterval; (function (PollingInterval) { PollingInterval[PollingInterval["High"] = 2000] = "High"; @@ -3059,11 +3553,13 @@ var ts; return pollingIntervalsForPriority[watchPriority]; } var pollingIntervalsForPriority = getPriorityValues(250); + /* @internal */ function watchFileUsingPriorityPollingInterval(host, fileName, callback, watchPriority) { return host.watchFile(fileName, callback, pollingInterval(watchPriority)); } ts.watchFileUsingPriorityPollingInterval = watchFileUsingPriorityPollingInterval; - ts.missingFileModifiedTime = new Date(0); + /* @internal */ + ts.missingFileModifiedTime = new Date(0); // Any subsequent modification will occur after this time function createPollingIntervalBasedLevels(levels) { var _a; return _a = {}, @@ -3074,7 +3570,9 @@ var ts; } var defaultChunkLevels = { Low: 32, Medium: 64, High: 256 }; var pollingChunkSize = createPollingIntervalBasedLevels(defaultChunkLevels); + /* @internal */ ts.unchangedPollThresholds = createPollingIntervalBasedLevels(defaultChunkLevels); + /* @internal */ function setCustomPollingValues(system) { if (!system.getEnvironmentVariable) { return; @@ -3118,6 +3616,7 @@ var ts; } } ts.setCustomPollingValues = setCustomPollingValues; + /* @internal */ function createDynamicPriorityPollingWatchFile(host) { var watchedFiles = []; var changedFilesInLastPoll = []; @@ -3137,7 +3636,9 @@ var ts; return { close: function () { file.isClosed = true; + // Remove from watchedFiles ts.unorderedRemoveItem(watchedFiles, file); + // Do not update polling interval queue since that will happen as part of polling } }; } @@ -3150,6 +3651,7 @@ var ts; } function pollPollingIntervalQueue(queue) { queue.pollIndex = pollQueue(queue, queue.pollingInterval, queue.pollIndex, pollingChunkSize[queue.pollingInterval]); + // Set the next polling index and timeout if (queue.length) { scheduleNextPoll(queue.pollingInterval); } @@ -3159,13 +3661,18 @@ var ts; } } function pollLowPollingIntervalQueue(queue) { - pollQueue(changedFilesInLastPoll, PollingInterval.Low, 0, changedFilesInLastPoll.length); + // Always poll complete list of changedFilesInLastPoll + pollQueue(changedFilesInLastPoll, PollingInterval.Low, /*pollIndex*/ 0, changedFilesInLastPoll.length); + // Finally do the actual polling of the queue pollPollingIntervalQueue(queue); + // Schedule poll if there are files in changedFilesInLastPoll but no files in the actual queue + // as pollPollingIntervalQueue wont schedule for next poll if (!queue.pollScheduled && changedFilesInLastPoll.length) { scheduleNextPoll(PollingInterval.Low); } } function pollQueue(queue, pollingInterval, pollIndex, chunkSize) { + // Max visit would be all elements of the queue var needsVisit = queue.length; var definedValueCopyToIndex = pollIndex; for (var polled = 0; polled < chunkSize && needsVisit > 0; nextPollIndex(), needsVisit--) { @@ -3180,10 +3687,12 @@ var ts; polled++; var fileChanged = onWatchedFileStat(watchedFile, getModifiedTime(watchedFile.fileName)); if (watchedFile.isClosed) { + // Closed watcher as part of callback queue[pollIndex] = undefined; } else if (fileChanged) { watchedFile.unchangedPolls = 0; + // Changed files go to changedFilesInLastPoll queue if (queue !== changedFilesInLastPoll) { queue[pollIndex] = undefined; addChangedFileToLowPollingIntervalQueue(watchedFile); @@ -3193,6 +3702,7 @@ var ts; watchedFile.unchangedPolls++; } else if (queue === changedFilesInLastPoll) { + // Restart unchangedPollCount for unchanged file and move to low polling interval queue watchedFile.unchangedPolls = 1; queue[pollIndex] = undefined; addToPollingIntervalQueue(watchedFile, PollingInterval.Low); @@ -3203,6 +3713,7 @@ var ts; addToPollingIntervalQueue(watchedFile, pollingInterval === PollingInterval.Low ? PollingInterval.Medium : PollingInterval.High); } if (queue[pollIndex]) { + // Copy this file to the non hole location if (definedValueCopyToIndex < pollIndex) { queue[definedValueCopyToIndex] = watchedFile; queue[pollIndex] = undefined; @@ -3210,11 +3721,13 @@ var ts; definedValueCopyToIndex++; } } + // Return next poll index return pollIndex; function nextPollIndex() { pollIndex++; if (pollIndex === queue.length) { if (definedValueCopyToIndex < pollIndex) { + // There are holes from nextDefinedValueIndex to end of queue, change queue size queue.length = definedValueCopyToIndex; } pollIndex = 0; @@ -3253,6 +3766,10 @@ var ts; } } ts.createDynamicPriorityPollingWatchFile = createDynamicPriorityPollingWatchFile; + /** + * Returns true if file status changed + */ + /*@internal*/ function onWatchedFileStat(watchedFile, modifiedTime) { var oldTime = watchedFile.mtime.getTime(); var newTime = modifiedTime.getTime(); @@ -3269,11 +3786,22 @@ var ts; return false; } ts.onWatchedFileStat = onWatchedFileStat; + /** + * Watch the directory recursively using host provided method to watch child directories + * that means if this is recursive watcher, watch the children directories as well + * (eg on OS that dont support recursive watch using fs.watch use fs.watchFile) + */ + /*@internal*/ function createRecursiveDirectoryWatcher(host) { return createDirectoryWatcher; + /** + * Create the directory watcher for the dirPath. + */ function createDirectoryWatcher(dirName, callback) { var watcher = host.watchDirectory(dirName, function (fileName) { + // Call the actual callback callback(fileName); + // Iterate through existing children and update the watches if needed updateChildWatches(result, callback); }); var result = { @@ -3289,21 +3817,33 @@ var ts; return result; } function updateChildWatches(watcher, callback) { + // Iterate through existing children and update the watches if needed if (watcher) { watcher.childWatches = watchChildDirectories(watcher.dirName, watcher.childWatches, callback); } } + /** + * Watch the directories in the parentDir + */ function watchChildDirectories(parentDir, existingChildWatches, callback) { var newChildWatches; ts.enumerateInsertsAndDeletes(host.directoryExists(parentDir) ? ts.mapDefined(host.getAccessibleSortedChildDirectories(parentDir), function (child) { var childFullName = ts.getNormalizedAbsolutePath(child, parentDir); - return host.filePathComparer(childFullName, host.realpath(childFullName)) === 0 ? childFullName : undefined; + // Filter our the symbolic link directories since those arent included in recursive watch + // which is same behaviour when recursive: true is passed to fs.watch + return host.filePathComparer(childFullName, host.realpath(childFullName)) === 0 /* EqualTo */ ? childFullName : undefined; }) : ts.emptyArray, existingChildWatches, function (child, childWatcher) { return host.filePathComparer(child, childWatcher.dirName); }, createAndAddChildDirectoryWatcher, ts.closeFileWatcher, addChildDirectoryWatcher); return newChildWatches || ts.emptyArray; + /** + * Create new childDirectoryWatcher and add it to the new ChildDirectoryWatcher list + */ function createAndAddChildDirectoryWatcher(childName) { var result = createDirectoryWatcher(childName, callback); addChildDirectoryWatcher(result); } + /** + * Add child directory watcher to the new ChildDirectoryWatcher list + */ function addChildDirectoryWatcher(childWatcher) { (newChildWatches || (newChildWatches = [])).push(childWatcher); } @@ -3325,12 +3865,17 @@ var ts; return parseInt(version.substring(1, dot)); } ts.getNodeMajorVersion = getNodeMajorVersion; + // TODO: this is used as if it's certainly defined in many places. ts.sys = (function () { + // NodeJS detects "\uFEFF" at the start of the string and *replaces* it with the actual + // byte order mark from the specified encoding. Using any other byte order mark does + // not actually work. var byteOrderMarkIndicator = "\uFEFF"; function getNodeSystem() { var _fs = require("fs"); var _path = require("path"); var _os = require("os"); + // crypto can be absent on reduced node installations var _crypto; try { _crypto = require("crypto"); @@ -3403,7 +3948,7 @@ var ts; return stat.size; } } - catch (_a) { } + catch ( /*ignore*/_a) { /*ignore*/ } return 0; }, exit: function (exitCode) { @@ -3416,6 +3961,7 @@ var ts; require("source-map-support").install(); } catch (_a) { + // Could not enable source maps. } }, setTimeout: setTimeout, @@ -3441,11 +3987,14 @@ var ts; }; return nodeSystem; function isFileSystemCaseSensitive() { + // win32\win64 are case insensitive platforms if (platform === "win32" || platform === "win64") { return false; } + // If this file exists under a different case, we must be case-insensitve. return !fileExists(swapCase(__filename)); } + /** Convert all lowercase chars to uppercase, and vice-versa */ function swapCase(s) { return s.replace(/\w/g, function (ch) { var up = ch.toUpperCase(); @@ -3455,22 +4004,30 @@ var ts; function getWatchFile() { switch (tscWatchFile) { case "PriorityPollingInterval": + // Use polling interval based on priority when create watch using host.watchFile return fsWatchFile; case "DynamicPriorityPolling": + // Use polling interval but change the interval depending on file changes and their default polling interval return createDynamicPriorityPollingWatchFile({ getModifiedTime: getModifiedTime, setTimeout: setTimeout }); case "UseFsEvents": + // Use notifications from FS to watch with falling back to fs.watchFile return watchFileUsingFsWatch; case "UseFsEventsWithFallbackDynamicPolling": + // Use notifications from FS to watch with falling back to dynamic watch file dynamicPollingWatchFile = createDynamicPriorityPollingWatchFile({ getModifiedTime: getModifiedTime, setTimeout: setTimeout }); return createWatchFileUsingDynamicWatchFile(dynamicPollingWatchFile); case "UseFsEventsOnParentDirectory": + // Use notifications from FS to watch with falling back to fs.watchFile return createNonPollingWatchFile(); } return useNonPollingWatchers ? createNonPollingWatchFile() : + // Default to do not use polling interval as it is before this experiment branch function (fileName, callback) { return fsWatchFile(fileName, callback); }; } function getWatchDirectory() { + // Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows + // (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643) var fsSupportsRecursive = isNode4OrLater && (process.platform === "win32" || process.platform === "darwin"); if (fsSupportsRecursive) { return watchDirectoryUsingFsWatch; @@ -3492,10 +4049,11 @@ var ts; return watchDirectoryRecursively(directoryName, callback); } watchDirectory(directoryName, callback); - return undefined; + return undefined; // TODO: GH#18217 }; } function createNonPollingWatchFile() { + // One file can have multiple watchers var fileWatcherCallbacks = ts.createMultiMap(); var dirWatchers = ts.createMap(); var toCanonicalName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); @@ -3521,9 +4079,11 @@ var ts; } function createDirectoryWatcher(dirName, dirPath) { var watcher = fsWatchDirectory(dirName, function (_eventName, relativeFileName) { + // When files are deleted from disk, the triggered "rename" event would have a relativefileName of "undefined" var fileName = !ts.isString(relativeFileName) - ? undefined + ? undefined // TODO: GH#18217 : ts.getNormalizedAbsolutePath(relativeFileName, dirName); + // Some applications save a working file via rename operations var callbacks = fileWatcherCallbacks.get(toCanonicalName(fileName)); if (callbacks) { for (var _i = 0, callbacks_1 = callbacks; _i < callbacks_1.length; _i++) { @@ -3544,9 +4104,12 @@ var ts; close: function () { return _fs.unwatchFile(fileName, fileChanged); } }; function fileChanged(curr, prev) { + // previous event kind check is to ensure we recongnize the file as previously also missing when it is restored or renamed twice (that is it disappears and reappears) + // In such case, prevTime returned is same as prev time of event when file was deleted as per node documentation var isPreviouslyDeleted = +prev.mtime === 0 || eventKind === FileWatcherEventKind.Deleted; if (+curr.mtime === 0) { if (isPreviouslyDeleted) { + // Already deleted file, no need to callback again return; } eventKind = FileWatcherEventKind.Deleted; @@ -3554,10 +4117,12 @@ var ts; else if (isPreviouslyDeleted) { eventKind = FileWatcherEventKind.Created; } + // If there is no change in modified time, ignore the event else if (+curr.mtime === +prev.mtime) { return; } else { + // File changed eventKind = FileWatcherEventKind.Changed; } callback(fileName, eventKind); @@ -3572,36 +4137,55 @@ var ts; callback(fileName, fileExists(fileName) ? FileWatcherEventKind.Created : FileWatcherEventKind.Deleted); } else { + // Change callback(fileName, FileWatcherEventKind.Changed); } }; } function createFsWatchCallbackForDirectoryWatcherCallback(directoryName, callback) { return function (eventName, relativeFileName) { + // In watchDirectory we only care about adding and removing files (when event name is + // "rename"); changes made within files are handled by corresponding fileWatchers (when + // event name is "change") if (eventName === "rename") { + // When deleting a file, the passed baseFileName is null callback(!relativeFileName ? directoryName : ts.normalizePath(ts.combinePaths(directoryName, relativeFileName))); } }; } function fsWatch(fileOrDirectory, entryKind, callback, recursive, fallbackPollingWatchFile, pollingInterval) { var options; + /** Watcher for the file system entry depending on whether it is missing or present */ var watcher = !fileSystemEntryExists(fileOrDirectory, entryKind) ? watchMissingFileSystemEntry() : watchPresentFileSystemEntry(); return { close: function () { + // Close the watcher (either existing file system entry watcher or missing file system entry watcher) watcher.close(); watcher = undefined; } }; + /** + * Invoke the callback with rename and update the watcher if not closed + * @param createWatcher + */ function invokeCallbackAndUpdateWatcher(createWatcher) { + // Call the callback for current directory callback("rename", ""); + // If watcher is not closed, update it if (watcher) { watcher.close(); watcher = createWatcher(); } } + /** + * Watch the file or directory that is currently present + * and when the watched file or directory is deleted, switch to missing file system entry watcher + */ function watchPresentFileSystemEntry() { + // Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows + // (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643) if (options === undefined) { if (isNode4OrLater && (process.platform === "win32" || process.platform === "darwin")) { options = { persistent: true, recursive: !!recursive }; @@ -3612,32 +4196,47 @@ var ts; } try { var presentWatcher = _fs.watch(fileOrDirectory, options, callback); + // Watch the missing file or directory or error presentWatcher.on("error", function () { return invokeCallbackAndUpdateWatcher(watchMissingFileSystemEntry); }); return presentWatcher; } catch (e) { + // Catch the exception and use polling instead + // Eg. on linux the number of watches are limited and one could easily exhaust watches and the exception ENOSPC is thrown when creating watcher at that point + // so instead of throwing error, use fs.watchFile return watchPresentFileSystemEntryWithFsWatchFile(); } } + /** + * Watch the file or directory using fs.watchFile since fs.watch threw exception + * Eg. on linux the number of watches are limited and one could easily exhaust watches and the exception ENOSPC is thrown when creating watcher at that point + */ function watchPresentFileSystemEntryWithFsWatchFile() { return fallbackPollingWatchFile(fileOrDirectory, createFileWatcherCallback(callback), pollingInterval); } + /** + * Watch the file or directory that is missing + * and switch to existing file or directory when the missing filesystem entry is created + */ function watchMissingFileSystemEntry() { return fallbackPollingWatchFile(fileOrDirectory, function (_fileName, eventKind) { if (eventKind === FileWatcherEventKind.Created && fileSystemEntryExists(fileOrDirectory, entryKind)) { + // Call the callback for current file or directory + // For now it could be callback for the inner directory creation, + // but just return current directory, better than current no-op invokeCallbackAndUpdateWatcher(watchPresentFileSystemEntry); } }, pollingInterval); } } function watchFileUsingFsWatch(fileName, callback, pollingInterval) { - return fsWatch(fileName, 0, createFsWatchCallbackForFileWatcherCallback(fileName, callback), false, fsWatchFile, pollingInterval); + return fsWatch(fileName, 0 /* File */, createFsWatchCallbackForFileWatcherCallback(fileName, callback), /*recursive*/ false, fsWatchFile, pollingInterval); } function createWatchFileUsingDynamicWatchFile(watchFile) { - return function (fileName, callback, pollingInterval) { return fsWatch(fileName, 0, createFsWatchCallbackForFileWatcherCallback(fileName, callback), false, watchFile, pollingInterval); }; + return function (fileName, callback, pollingInterval) { return fsWatch(fileName, 0 /* File */, createFsWatchCallbackForFileWatcherCallback(fileName, callback), /*recursive*/ false, watchFile, pollingInterval); }; } function fsWatchDirectory(directoryName, callback, recursive) { - return fsWatch(directoryName, 1, callback, !!recursive, fsWatchFile); + return fsWatch(directoryName, 1 /* Directory */, callback, !!recursive, fsWatchFile); } function watchDirectoryUsingFsWatch(directoryName, callback, recursive) { return fsWatchDirectory(directoryName, createFsWatchCallbackForDirectoryWatcherCallback(directoryName, callback), recursive); @@ -3652,7 +4251,9 @@ var ts; var buffer = _fs.readFileSync(fileName); var len = buffer.length; if (len >= 2 && buffer[0] === 0xFE && buffer[1] === 0xFF) { - len &= ~1; + // Big endian UTF-16 byte order mark detected. Since big endian is not supported by node.js, + // flip all byte pairs and treat as little endian. + len &= ~1; // Round down to a multiple of 2 for (var i = 0; i < len; i += 2) { var temp = buffer[i]; buffer[i] = buffer[i + 1]; @@ -3661,21 +4262,25 @@ var ts; return buffer.toString("utf16le", 2); } if (len >= 2 && buffer[0] === 0xFF && buffer[1] === 0xFE) { + // Little endian UTF-16 byte order mark detected return buffer.toString("utf16le", 2); } if (len >= 3 && buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) { + // UTF-8 byte order mark detected return buffer.toString("utf8", 3); } + // Default is UTF-8 with no byte order mark return buffer.toString("utf8"); } function writeFile(fileName, data, writeByteOrderMark) { + // If a BOM is required, emit one if (writeByteOrderMark) { data = byteOrderMarkIndicator + data; } var fd; try { fd = _fs.openSync(fileName, "w"); - _fs.writeSync(fd, data, undefined, "utf8"); + _fs.writeSync(fd, data, /*position*/ undefined, "utf8"); } finally { if (fd !== undefined) { @@ -3690,6 +4295,8 @@ var ts; var directories = []; for (var _i = 0, entries_2 = entries; _i < entries_2.length; _i++) { var entry = entries_2[_i]; + // This is necessary because on some file system node fails to exclude + // "." and "..". See https://github.com/nodejs/node/issues/4002 if (entry === "." || entry === "..") { continue; } @@ -3721,8 +4328,8 @@ var ts; try { var stat = _fs.statSync(path); switch (entryKind) { - case 0: return stat.isFile(); - case 1: return stat.isDirectory(); + case 0 /* File */: return stat.isFile(); + case 1 /* Directory */: return stat.isDirectory(); default: return false; } } @@ -3731,13 +4338,13 @@ var ts; } } function fileExists(path) { - return fileSystemEntryExists(path, 0); + return fileSystemEntryExists(path, 0 /* File */); } function directoryExists(path) { - return fileSystemEntryExists(path, 1); + return fileSystemEntryExists(path, 1 /* Directory */); } function getDirectories(path) { - return ts.filter(_fs.readdirSync(path), function (dir) { return fileSystemEntryExists(ts.combinePaths(path, dir), 1); }); + return ts.filter(_fs.readdirSync(path), function (dir) { return fileSystemEntryExists(ts.combinePaths(path, dir), 1 /* Directory */); }); } function realpath(path) { try { @@ -3771,6 +4378,10 @@ var ts; return; } } + /** + * djb2 hashing algorithm + * http://www.cse.yorku.ca/~oz/hash.html + */ function generateDjb2Hash(data) { var chars = data.split("").map(function (str) { return str.charCodeAt(0); }); return "" + chars.reduce(function (prev, curr) { return ((prev << 5) + prev) + curr; }, 5381); @@ -3794,9 +4405,11 @@ var ts; useCaseSensitiveFileNames: !!ChakraHost.useCaseSensitiveFileNames, write: ChakraHost.echo, readFile: function (path, _encoding) { + // encoding is automatically handled by the implementation in ChakraHost return ChakraHost.readFile(path); }, writeFile: function (path, data, writeByteOrderMark) { + // If a BOM is required, emit one if (writeByteOrderMark) { data = byteOrderMarkIndicator + data; } @@ -3833,9 +4446,12 @@ var ts; sys = getChakraSystem(); } else if (typeof process !== "undefined" && process.nextTick && !process.browser && typeof require !== "undefined") { + // process and process.nextTick checks if current environment is node-like + // process.browser check excludes webpack and browserify sys = getNodeSystem(); } if (sys) { + // patch writefile to create folder before writing the file var originalWriteFile_1 = sys.writeFile; sys.writeFile = function (path, data, writeBom) { var directoryPath = ts.getDirectoryPath(ts.normalizeSlashes(path)); @@ -3850,18 +4466,22 @@ var ts; if (ts.sys && ts.sys.getEnvironmentVariable) { setCustomPollingValues(ts.sys); ts.Debug.currentAssertionLevel = /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV")) - ? 1 - : 0; + ? 1 /* Normal */ + : 0 /* None */; } if (ts.sys && ts.sys.debugMode) { ts.Debug.isDebugging = true; } })(ts || (ts = {})); +// +// generated from './diagnosticInformationMap.generated.ts' by 'src/compiler' +/* @internal */ var ts; (function (ts) { function diag(code, category, key, message, reportsUnnecessary) { return { code: code, category: category, key: key, message: message, reportsUnnecessary: reportsUnnecessary }; } + // tslint:disable-next-line variable-name ts.Diagnostics = { Unterminated_string_literal: diag(1002, ts.DiagnosticCategory.Error, "Unterminated_string_literal_1002", "Unterminated string literal."), Identifier_expected: diag(1003, ts.DiagnosticCategory.Error, "Identifier_expected_1003", "Identifier expected."), @@ -4424,7 +5044,7 @@ var ts; _0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible: diag(2692, ts.DiagnosticCategory.Error, "_0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible_2692", "'{0}' is a primitive, but '{1}' is a wrapper object. Prefer using '{0}' when possible."), _0_only_refers_to_a_type_but_is_being_used_as_a_value_here: diag(2693, ts.DiagnosticCategory.Error, "_0_only_refers_to_a_type_but_is_being_used_as_a_value_here_2693", "'{0}' only refers to a type, but is being used as a value here."), Namespace_0_has_no_exported_member_1: diag(2694, ts.DiagnosticCategory.Error, "Namespace_0_has_no_exported_member_1_2694", "Namespace '{0}' has no exported member '{1}'."), - Left_side_of_comma_operator_is_unused_and_has_no_side_effects: diag(2695, ts.DiagnosticCategory.Error, "Left_side_of_comma_operator_is_unused_and_has_no_side_effects_2695", "Left side of comma operator is unused and has no side effects.", true), + Left_side_of_comma_operator_is_unused_and_has_no_side_effects: diag(2695, ts.DiagnosticCategory.Error, "Left_side_of_comma_operator_is_unused_and_has_no_side_effects_2695", "Left side of comma operator is unused and has no side effects.", /*reportsUnnecessary*/ true), The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead: diag(2696, ts.DiagnosticCategory.Error, "The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead_2696", "The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead?"), An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option: diag(2697, ts.DiagnosticCategory.Error, "An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_in_2697", "An async function or method must return a 'Promise'. Make sure you have a declaration for 'Promise' or include 'ES2015' in your `--lib` option."), Spread_types_may_only_be_created_from_object_types: diag(2698, ts.DiagnosticCategory.Error, "Spread_types_may_only_be_created_from_object_types_2698", "Spread types may only be created from object types."), @@ -4690,12 +5310,12 @@ var ts; Resolving_real_path_for_0_result_1: diag(6130, ts.DiagnosticCategory.Message, "Resolving_real_path_for_0_result_1_6130", "Resolving real path for '{0}', result '{1}'."), Cannot_compile_modules_using_option_0_unless_the_module_flag_is_amd_or_system: diag(6131, ts.DiagnosticCategory.Error, "Cannot_compile_modules_using_option_0_unless_the_module_flag_is_amd_or_system_6131", "Cannot compile modules using option '{0}' unless the '--module' flag is 'amd' or 'system'."), File_name_0_has_a_1_extension_stripping_it: diag(6132, ts.DiagnosticCategory.Message, "File_name_0_has_a_1_extension_stripping_it_6132", "File name '{0}' has a '{1}' extension - stripping it."), - _0_is_declared_but_its_value_is_never_read: diag(6133, ts.DiagnosticCategory.Error, "_0_is_declared_but_its_value_is_never_read_6133", "'{0}' is declared but its value is never read.", true), + _0_is_declared_but_its_value_is_never_read: diag(6133, ts.DiagnosticCategory.Error, "_0_is_declared_but_its_value_is_never_read_6133", "'{0}' is declared but its value is never read.", /*reportsUnnecessary*/ true), Report_errors_on_unused_locals: diag(6134, ts.DiagnosticCategory.Message, "Report_errors_on_unused_locals_6134", "Report errors on unused locals."), Report_errors_on_unused_parameters: diag(6135, ts.DiagnosticCategory.Message, "Report_errors_on_unused_parameters_6135", "Report errors on unused parameters."), The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files: diag(6136, ts.DiagnosticCategory.Message, "The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files_6136", "The maximum dependency depth to search under node_modules and load JavaScript files."), Cannot_import_type_declaration_files_Consider_importing_0_instead_of_1: diag(6137, ts.DiagnosticCategory.Error, "Cannot_import_type_declaration_files_Consider_importing_0_instead_of_1_6137", "Cannot import type declaration files. Consider importing '{0}' instead of '{1}'."), - Property_0_is_declared_but_its_value_is_never_read: diag(6138, ts.DiagnosticCategory.Error, "Property_0_is_declared_but_its_value_is_never_read_6138", "Property '{0}' is declared but its value is never read.", true), + Property_0_is_declared_but_its_value_is_never_read: diag(6138, ts.DiagnosticCategory.Error, "Property_0_is_declared_but_its_value_is_never_read_6138", "Property '{0}' is declared but its value is never read.", /*reportsUnnecessary*/ true), Import_emit_helpers_from_tslib: diag(6139, ts.DiagnosticCategory.Message, "Import_emit_helpers_from_tslib_6139", "Import emit helpers from 'tslib'."), Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using_cache_location_2: diag(6140, ts.DiagnosticCategory.Error, "Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using__6140", "Auto discovery for typings is enabled in project '{0}'. Running extra resolution pass for module '{1}' using cache location '{2}'."), Parse_in_strict_mode_and_emit_use_strict_for_each_source_file: diag(6141, ts.DiagnosticCategory.Message, "Parse_in_strict_mode_and_emit_use_strict_for_each_source_file_6141", "Parse in strict mode and emit \"use strict\" for each source file."), @@ -4748,14 +5368,14 @@ var ts; Multiple_consecutive_numeric_separators_are_not_permitted: diag(6189, ts.DiagnosticCategory.Error, "Multiple_consecutive_numeric_separators_are_not_permitted_6189", "Multiple consecutive numeric separators are not permitted."), Found_package_json_at_0_Package_ID_is_1: diag(6190, ts.DiagnosticCategory.Message, "Found_package_json_at_0_Package_ID_is_1_6190", "Found 'package.json' at '{0}'. Package ID is '{1}'."), Whether_to_keep_outdated_console_output_in_watch_mode_instead_of_clearing_the_screen: diag(6191, ts.DiagnosticCategory.Message, "Whether_to_keep_outdated_console_output_in_watch_mode_instead_of_clearing_the_screen_6191", "Whether to keep outdated console output in watch mode instead of clearing the screen."), - All_imports_in_import_declaration_are_unused: diag(6192, ts.DiagnosticCategory.Error, "All_imports_in_import_declaration_are_unused_6192", "All imports in import declaration are unused.", true), + All_imports_in_import_declaration_are_unused: diag(6192, ts.DiagnosticCategory.Error, "All_imports_in_import_declaration_are_unused_6192", "All imports in import declaration are unused.", /*reportsUnnecessary*/ true), Found_1_error_Watching_for_file_changes: diag(6193, ts.DiagnosticCategory.Message, "Found_1_error_Watching_for_file_changes_6193", "Found 1 error. Watching for file changes."), Found_0_errors_Watching_for_file_changes: diag(6194, ts.DiagnosticCategory.Message, "Found_0_errors_Watching_for_file_changes_6194", "Found {0} errors. Watching for file changes."), Resolve_keyof_to_string_valued_property_names_only_no_numbers_or_symbols: diag(6195, ts.DiagnosticCategory.Message, "Resolve_keyof_to_string_valued_property_names_only_no_numbers_or_symbols_6195", "Resolve 'keyof' to string valued property names only (no numbers or symbols)."), - _0_is_declared_but_never_used: diag(6196, ts.DiagnosticCategory.Error, "_0_is_declared_but_never_used_6196", "'{0}' is declared but never used.", true), + _0_is_declared_but_never_used: diag(6196, ts.DiagnosticCategory.Error, "_0_is_declared_but_never_used_6196", "'{0}' is declared but never used.", /*reportsUnnecessary*/ true), Include_modules_imported_with_json_extension: diag(6197, ts.DiagnosticCategory.Message, "Include_modules_imported_with_json_extension_6197", "Include modules imported with '.json' extension"), - All_destructured_elements_are_unused: diag(6198, ts.DiagnosticCategory.Error, "All_destructured_elements_are_unused_6198", "All destructured elements are unused.", true), - All_variables_are_unused: diag(6199, ts.DiagnosticCategory.Error, "All_variables_are_unused_6199", "All variables are unused.", true), + All_destructured_elements_are_unused: diag(6198, ts.DiagnosticCategory.Error, "All_destructured_elements_are_unused_6198", "All destructured elements are unused.", /*reportsUnnecessary*/ true), + All_variables_are_unused: diag(6199, ts.DiagnosticCategory.Error, "All_variables_are_unused_6199", "All variables are unused.", /*reportsUnnecessary*/ true), Projects_to_reference: diag(6300, ts.DiagnosticCategory.Message, "Projects_to_reference_6300", "Projects to reference"), Enable_project_compilation: diag(6302, ts.DiagnosticCategory.Message, "Enable_project_compilation_6302", "Enable project compilation"), Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0: diag(6202, ts.DiagnosticCategory.Error, "Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0_6202", "Project references may not form a circular graph. Cycle detected: {0}"), @@ -4805,8 +5425,8 @@ var ts; Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions: diag(7024, ts.DiagnosticCategory.Error, "Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_ref_7024", "Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions."), Generator_implicitly_has_type_0_because_it_does_not_yield_any_values_Consider_supplying_a_return_type: diag(7025, ts.DiagnosticCategory.Error, "Generator_implicitly_has_type_0_because_it_does_not_yield_any_values_Consider_supplying_a_return_typ_7025", "Generator implicitly has type '{0}' because it does not yield any values. Consider supplying a return type."), JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists: diag(7026, ts.DiagnosticCategory.Error, "JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists_7026", "JSX element implicitly has type 'any' because no interface 'JSX.{0}' exists."), - Unreachable_code_detected: diag(7027, ts.DiagnosticCategory.Error, "Unreachable_code_detected_7027", "Unreachable code detected.", true), - Unused_label: diag(7028, ts.DiagnosticCategory.Error, "Unused_label_7028", "Unused label.", true), + Unreachable_code_detected: diag(7027, ts.DiagnosticCategory.Error, "Unreachable_code_detected_7027", "Unreachable code detected.", /*reportsUnnecessary*/ true), + Unused_label: diag(7028, ts.DiagnosticCategory.Error, "Unused_label_7028", "Unused label.", /*reportsUnnecessary*/ true), Fallthrough_case_in_switch: diag(7029, ts.DiagnosticCategory.Error, "Fallthrough_case_in_switch_7029", "Fallthrough case in switch."), Not_all_code_paths_return_a_value: diag(7030, ts.DiagnosticCategory.Error, "Not_all_code_paths_return_a_value_7030", "Not all code paths return a value."), Binding_element_0_implicitly_has_an_1_type: diag(7031, ts.DiagnosticCategory.Error, "Binding_element_0_implicitly_has_an_1_type_7031", "Binding element '{0}' implicitly has an '{1}' type."), @@ -4966,157 +5586,204 @@ var ts; })(ts || (ts = {})); var ts; (function (ts) { + /* @internal */ function tokenIsIdentifierOrKeyword(token) { - return token >= 71; + return token >= 71 /* Identifier */; } ts.tokenIsIdentifierOrKeyword = tokenIsIdentifierOrKeyword; + /* @internal */ function tokenIsIdentifierOrKeywordOrGreaterThan(token) { - return token === 29 || tokenIsIdentifierOrKeyword(token); + return token === 29 /* GreaterThanToken */ || tokenIsIdentifierOrKeyword(token); } ts.tokenIsIdentifierOrKeywordOrGreaterThan = tokenIsIdentifierOrKeywordOrGreaterThan; var textToToken = ts.createMapFromTemplate({ - "abstract": 117, - "any": 119, - "as": 118, - "boolean": 122, - "break": 72, - "case": 73, - "catch": 74, - "class": 75, - "continue": 77, - "const": 76, - "constructor": 123, - "debugger": 78, - "declare": 124, - "default": 79, - "delete": 80, - "do": 81, - "else": 82, - "enum": 83, - "export": 84, - "extends": 85, - "false": 86, - "finally": 87, - "for": 88, - "from": 143, - "function": 89, - "get": 125, - "if": 90, - "implements": 108, - "import": 91, - "in": 92, - "infer": 126, - "instanceof": 93, - "interface": 109, - "is": 127, - "keyof": 128, - "let": 110, - "module": 129, - "namespace": 130, - "never": 131, - "new": 94, - "null": 95, - "number": 134, - "object": 135, - "package": 111, - "private": 112, - "protected": 113, - "public": 114, - "readonly": 132, - "require": 133, - "global": 144, - "return": 96, - "set": 136, - "static": 115, - "string": 137, - "super": 97, - "switch": 98, - "symbol": 138, - "this": 99, - "throw": 100, - "true": 101, - "try": 102, - "type": 139, - "typeof": 103, - "undefined": 140, - "unique": 141, - "unknown": 142, - "var": 104, - "void": 105, - "while": 106, - "with": 107, - "yield": 116, - "async": 120, - "await": 121, - "of": 145, - "{": 17, - "}": 18, - "(": 19, - ")": 20, - "[": 21, - "]": 22, - ".": 23, - "...": 24, - ";": 25, - ",": 26, - "<": 27, - ">": 29, - "<=": 30, - ">=": 31, - "==": 32, - "!=": 33, - "===": 34, - "!==": 35, - "=>": 36, - "+": 37, - "-": 38, - "**": 40, - "*": 39, - "/": 41, - "%": 42, - "++": 43, - "--": 44, - "<<": 45, - ">": 46, - ">>>": 47, - "&": 48, - "|": 49, - "^": 50, - "!": 51, - "~": 52, - "&&": 53, - "||": 54, - "?": 55, - ":": 56, - "=": 58, - "+=": 59, - "-=": 60, - "*=": 61, - "**=": 62, - "/=": 63, - "%=": 64, - "<<=": 65, - ">>=": 66, - ">>>=": 67, - "&=": 68, - "|=": 69, - "^=": 70, - "@": 57, + "abstract": 117 /* AbstractKeyword */, + "any": 119 /* AnyKeyword */, + "as": 118 /* AsKeyword */, + "boolean": 122 /* BooleanKeyword */, + "break": 72 /* BreakKeyword */, + "case": 73 /* CaseKeyword */, + "catch": 74 /* CatchKeyword */, + "class": 75 /* ClassKeyword */, + "continue": 77 /* ContinueKeyword */, + "const": 76 /* ConstKeyword */, + "constructor": 123 /* ConstructorKeyword */, + "debugger": 78 /* DebuggerKeyword */, + "declare": 124 /* DeclareKeyword */, + "default": 79 /* DefaultKeyword */, + "delete": 80 /* DeleteKeyword */, + "do": 81 /* DoKeyword */, + "else": 82 /* ElseKeyword */, + "enum": 83 /* EnumKeyword */, + "export": 84 /* ExportKeyword */, + "extends": 85 /* ExtendsKeyword */, + "false": 86 /* FalseKeyword */, + "finally": 87 /* FinallyKeyword */, + "for": 88 /* ForKeyword */, + "from": 143 /* FromKeyword */, + "function": 89 /* FunctionKeyword */, + "get": 125 /* GetKeyword */, + "if": 90 /* IfKeyword */, + "implements": 108 /* ImplementsKeyword */, + "import": 91 /* ImportKeyword */, + "in": 92 /* InKeyword */, + "infer": 126 /* InferKeyword */, + "instanceof": 93 /* InstanceOfKeyword */, + "interface": 109 /* InterfaceKeyword */, + "is": 127 /* IsKeyword */, + "keyof": 128 /* KeyOfKeyword */, + "let": 110 /* LetKeyword */, + "module": 129 /* ModuleKeyword */, + "namespace": 130 /* NamespaceKeyword */, + "never": 131 /* NeverKeyword */, + "new": 94 /* NewKeyword */, + "null": 95 /* NullKeyword */, + "number": 134 /* NumberKeyword */, + "object": 135 /* ObjectKeyword */, + "package": 111 /* PackageKeyword */, + "private": 112 /* PrivateKeyword */, + "protected": 113 /* ProtectedKeyword */, + "public": 114 /* PublicKeyword */, + "readonly": 132 /* ReadonlyKeyword */, + "require": 133 /* RequireKeyword */, + "global": 144 /* GlobalKeyword */, + "return": 96 /* ReturnKeyword */, + "set": 136 /* SetKeyword */, + "static": 115 /* StaticKeyword */, + "string": 137 /* StringKeyword */, + "super": 97 /* SuperKeyword */, + "switch": 98 /* SwitchKeyword */, + "symbol": 138 /* SymbolKeyword */, + "this": 99 /* ThisKeyword */, + "throw": 100 /* ThrowKeyword */, + "true": 101 /* TrueKeyword */, + "try": 102 /* TryKeyword */, + "type": 139 /* TypeKeyword */, + "typeof": 103 /* TypeOfKeyword */, + "undefined": 140 /* UndefinedKeyword */, + "unique": 141 /* UniqueKeyword */, + "unknown": 142 /* UnknownKeyword */, + "var": 104 /* VarKeyword */, + "void": 105 /* VoidKeyword */, + "while": 106 /* WhileKeyword */, + "with": 107 /* WithKeyword */, + "yield": 116 /* YieldKeyword */, + "async": 120 /* AsyncKeyword */, + "await": 121 /* AwaitKeyword */, + "of": 145 /* OfKeyword */, + "{": 17 /* OpenBraceToken */, + "}": 18 /* CloseBraceToken */, + "(": 19 /* OpenParenToken */, + ")": 20 /* CloseParenToken */, + "[": 21 /* OpenBracketToken */, + "]": 22 /* CloseBracketToken */, + ".": 23 /* DotToken */, + "...": 24 /* DotDotDotToken */, + ";": 25 /* SemicolonToken */, + ",": 26 /* CommaToken */, + "<": 27 /* LessThanToken */, + ">": 29 /* GreaterThanToken */, + "<=": 30 /* LessThanEqualsToken */, + ">=": 31 /* GreaterThanEqualsToken */, + "==": 32 /* EqualsEqualsToken */, + "!=": 33 /* ExclamationEqualsToken */, + "===": 34 /* EqualsEqualsEqualsToken */, + "!==": 35 /* ExclamationEqualsEqualsToken */, + "=>": 36 /* EqualsGreaterThanToken */, + "+": 37 /* PlusToken */, + "-": 38 /* MinusToken */, + "**": 40 /* AsteriskAsteriskToken */, + "*": 39 /* AsteriskToken */, + "/": 41 /* SlashToken */, + "%": 42 /* PercentToken */, + "++": 43 /* PlusPlusToken */, + "--": 44 /* MinusMinusToken */, + "<<": 45 /* LessThanLessThanToken */, + ">": 46 /* GreaterThanGreaterThanToken */, + ">>>": 47 /* GreaterThanGreaterThanGreaterThanToken */, + "&": 48 /* AmpersandToken */, + "|": 49 /* BarToken */, + "^": 50 /* CaretToken */, + "!": 51 /* ExclamationToken */, + "~": 52 /* TildeToken */, + "&&": 53 /* AmpersandAmpersandToken */, + "||": 54 /* BarBarToken */, + "?": 55 /* QuestionToken */, + ":": 56 /* ColonToken */, + "=": 58 /* EqualsToken */, + "+=": 59 /* PlusEqualsToken */, + "-=": 60 /* MinusEqualsToken */, + "*=": 61 /* AsteriskEqualsToken */, + "**=": 62 /* AsteriskAsteriskEqualsToken */, + "/=": 63 /* SlashEqualsToken */, + "%=": 64 /* PercentEqualsToken */, + "<<=": 65 /* LessThanLessThanEqualsToken */, + ">>=": 66 /* GreaterThanGreaterThanEqualsToken */, + ">>>=": 67 /* GreaterThanGreaterThanGreaterThanEqualsToken */, + "&=": 68 /* AmpersandEqualsToken */, + "|=": 69 /* BarEqualsToken */, + "^=": 70 /* CaretEqualsToken */, + "@": 57 /* AtToken */, }); + /* + As per ECMAScript Language Specification 3th Edition, Section 7.6: Identifiers + IdentifierStart :: + Can contain Unicode 3.0.0 categories: + Uppercase letter (Lu), + Lowercase letter (Ll), + Titlecase letter (Lt), + Modifier letter (Lm), + Other letter (Lo), or + Letter number (Nl). + IdentifierPart :: = + Can contain IdentifierStart + Unicode 3.0.0 categories: + Non-spacing mark (Mn), + Combining spacing mark (Mc), + Decimal number (Nd), or + Connector punctuation (Pc). + + Codepoint ranges for ES3 Identifiers are extracted from the Unicode 3.0.0 specification at: + http://www.unicode.org/Public/3.0-Update/UnicodeData-3.0.0.txt + */ var unicodeES3IdentifierStart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, 740, 750, 750, 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1164, 1220, 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1610, 1649, 1747, 1749, 1749, 1765, 1766, 1786, 1788, 1808, 1808, 1810, 1836, 1920, 1957, 2309, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2784, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 2997, 2999, 3001, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3168, 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3294, 3294, 3296, 3297, 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3424, 3425, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805, 3840, 3840, 3904, 3911, 3913, 3946, 3976, 3979, 4096, 4129, 4131, 4135, 4137, 4138, 4176, 4181, 4256, 4293, 4304, 4342, 4352, 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4742, 4744, 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, 6067, 6176, 6263, 6272, 6312, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8319, 8319, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12346, 12353, 12436, 12445, 12446, 12449, 12538, 12540, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65138, 65140, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500,]; var unicodeES3IdentifierPart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, 740, 750, 750, 768, 846, 864, 866, 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1155, 1158, 1164, 1220, 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1441, 1443, 1465, 1467, 1469, 1471, 1471, 1473, 1474, 1476, 1476, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1621, 1632, 1641, 1648, 1747, 1749, 1756, 1759, 1768, 1770, 1773, 1776, 1788, 1808, 1836, 1840, 1866, 1920, 1968, 2305, 2307, 2309, 2361, 2364, 2381, 2384, 2388, 2392, 2403, 2406, 2415, 2433, 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2492, 2494, 2500, 2503, 2504, 2507, 2509, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2562, 2562, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2649, 2652, 2654, 2654, 2662, 2676, 2689, 2691, 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2784, 2790, 2799, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2876, 2883, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2913, 2918, 2927, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 2997, 2999, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3031, 3031, 3047, 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3134, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3168, 3169, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3262, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3297, 3302, 3311, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3390, 3395, 3398, 3400, 3402, 3405, 3415, 3415, 3424, 3425, 3430, 3439, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3805, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3946, 3953, 3972, 3974, 3979, 3984, 3991, 3993, 4028, 4038, 4038, 4096, 4129, 4131, 4135, 4137, 4138, 4140, 4146, 4150, 4153, 4160, 4169, 4176, 4185, 4256, 4293, 4304, 4342, 4352, 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4742, 4744, 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 4969, 4977, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, 6099, 6112, 6121, 6160, 6169, 6176, 6263, 6272, 6313, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8255, 8256, 8319, 8319, 8400, 8412, 8417, 8417, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12335, 12337, 12341, 12344, 12346, 12353, 12436, 12441, 12442, 12445, 12446, 12449, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65056, 65059, 65075, 65076, 65101, 65103, 65136, 65138, 65140, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65381, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500,]; + /* + As per ECMAScript Language Specification 5th Edition, Section 7.6: ISyntaxToken Names and Identifiers + IdentifierStart :: + Can contain Unicode 6.2 categories: + Uppercase letter (Lu), + Lowercase letter (Ll), + Titlecase letter (Lt), + Modifier letter (Lm), + Other letter (Lo), or + Letter number (Nl). + IdentifierPart :: + Can contain IdentifierStart + Unicode 6.2 categories: + Non-spacing mark (Mn), + Combining spacing mark (Mc), + Decimal number (Nd), + Connector punctuation (Pc), + , or + . + + Codepoint ranges for ES5 Identifiers are extracted from the Unicode 6.2 specification at: + http://www.unicode.org/Public/6.2.0/ucd/UnicodeData.txt + */ var unicodeES5IdentifierStart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 880, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1162, 1319, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1568, 1610, 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775, 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957, 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069, 2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2208, 2208, 2210, 2220, 2308, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2423, 2425, 2431, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929, 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261, 3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3807, 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138, 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198, 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000, 6016, 6067, 6103, 6103, 6108, 6108, 6176, 6263, 6272, 6312, 6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516, 6528, 6571, 6593, 6599, 6656, 6678, 6688, 6740, 6823, 6823, 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7098, 7141, 7168, 7203, 7245, 7247, 7258, 7293, 7401, 7404, 7406, 7409, 7413, 7414, 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, 11499, 11502, 11506, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, 19968, 40908, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539, 42560, 42606, 42623, 42647, 42656, 42735, 42775, 42783, 42786, 42888, 42891, 42894, 42896, 42899, 42912, 42922, 43000, 43009, 43011, 43013, 43015, 43018, 43020, 43042, 43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259, 43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442, 43471, 43471, 43520, 43560, 43584, 43586, 43588, 43595, 43616, 43638, 43642, 43642, 43648, 43695, 43697, 43697, 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714, 43739, 43741, 43744, 43754, 43762, 43764, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44002, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500,]; var unicodeES5IdentifierPart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 768, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1155, 1159, 1162, 1319, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1469, 1471, 1471, 1473, 1474, 1476, 1477, 1479, 1479, 1488, 1514, 1520, 1522, 1552, 1562, 1568, 1641, 1646, 1747, 1749, 1756, 1759, 1768, 1770, 1788, 1791, 1791, 1808, 1866, 1869, 1969, 1984, 2037, 2042, 2042, 2048, 2093, 2112, 2139, 2208, 2208, 2210, 2220, 2276, 2302, 2304, 2403, 2406, 2415, 2417, 2423, 2425, 2431, 2433, 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2500, 2503, 2504, 2507, 2510, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2561, 2563, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2641, 2641, 2649, 2652, 2654, 2654, 2662, 2677, 2689, 2691, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2787, 2790, 2799, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2876, 2884, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2915, 2918, 2927, 2929, 2929, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3024, 3024, 3031, 3031, 3046, 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3160, 3161, 3168, 3171, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3260, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3299, 3302, 3311, 3313, 3314, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3396, 3398, 3400, 3402, 3406, 3415, 3415, 3424, 3427, 3430, 3439, 3450, 3455, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3807, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3948, 3953, 3972, 3974, 3991, 3993, 4028, 4038, 4038, 4096, 4169, 4176, 4253, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4957, 4959, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5908, 5920, 5940, 5952, 5971, 5984, 5996, 5998, 6000, 6002, 6003, 6016, 6099, 6103, 6103, 6108, 6109, 6112, 6121, 6155, 6157, 6160, 6169, 6176, 6263, 6272, 6314, 6320, 6389, 6400, 6428, 6432, 6443, 6448, 6459, 6470, 6509, 6512, 6516, 6528, 6571, 6576, 6601, 6608, 6617, 6656, 6683, 6688, 6750, 6752, 6780, 6783, 6793, 6800, 6809, 6823, 6823, 6912, 6987, 6992, 7001, 7019, 7027, 7040, 7155, 7168, 7223, 7232, 7241, 7245, 7293, 7376, 7378, 7380, 7414, 7424, 7654, 7676, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8204, 8205, 8255, 8256, 8276, 8276, 8305, 8305, 8319, 8319, 8336, 8348, 8400, 8412, 8417, 8417, 8421, 8432, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, 11499, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11647, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11744, 11775, 11823, 11823, 12293, 12295, 12321, 12335, 12337, 12341, 12344, 12348, 12353, 12438, 12441, 12442, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, 19968, 40908, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42539, 42560, 42607, 42612, 42621, 42623, 42647, 42655, 42737, 42775, 42783, 42786, 42888, 42891, 42894, 42896, 42899, 42912, 42922, 43000, 43047, 43072, 43123, 43136, 43204, 43216, 43225, 43232, 43255, 43259, 43259, 43264, 43309, 43312, 43347, 43360, 43388, 43392, 43456, 43471, 43481, 43520, 43574, 43584, 43597, 43600, 43609, 43616, 43638, 43642, 43643, 43648, 43714, 43739, 43741, 43744, 43759, 43762, 43766, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44010, 44012, 44013, 44016, 44025, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65024, 65039, 65056, 65062, 65075, 65076, 65101, 65103, 65136, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500,]; function lookupInUnicodeMap(code, map) { + // Bail out quickly if it couldn't possibly be in the map. if (code < map[0]) { return false; } + // Perform binary search in one of the Unicode range maps var lo = 0; var hi = map.length; var mid; while (lo + 1 < hi) { mid = lo + (hi - lo) / 2; + // mid has to be even to catch a range's beginning mid -= mid % 2; if (map[mid] <= code && code <= map[mid + 1]) { return true; @@ -5130,14 +5797,14 @@ var ts; } return false; } - function isUnicodeIdentifierStart(code, languageVersion) { - return languageVersion >= 1 ? + /* @internal */ function isUnicodeIdentifierStart(code, languageVersion) { + return languageVersion >= 1 /* ES5 */ ? lookupInUnicodeMap(code, unicodeES5IdentifierStart) : lookupInUnicodeMap(code, unicodeES3IdentifierStart); } ts.isUnicodeIdentifierStart = isUnicodeIdentifierStart; function isUnicodeIdentifierPart(code, languageVersion) { - return languageVersion >= 1 ? + return languageVersion >= 1 /* ES5 */ ? lookupInUnicodeMap(code, unicodeES5IdentifierPart) : lookupInUnicodeMap(code, unicodeES3IdentifierPart); } @@ -5153,10 +5820,12 @@ var ts; return tokenStrings[t]; } ts.tokenToString = tokenToString; + /* @internal */ function stringToToken(s) { return textToToken.get(s); } ts.stringToToken = stringToToken; + /* @internal */ function computeLineStarts(text) { var result = new Array(); var pos = 0; @@ -5165,16 +5834,17 @@ var ts; var ch = text.charCodeAt(pos); pos++; switch (ch) { - case 13: - if (text.charCodeAt(pos) === 10) { + case 13 /* carriageReturn */: + if (text.charCodeAt(pos) === 10 /* lineFeed */) { pos++; } - case 10: + // falls through + case 10 /* lineFeed */: result.push(lineStart); lineStart = pos; break; default: - if (ch > 127 && isLineBreak(ch)) { + if (ch > 127 /* maxAsciiCharacter */ && isLineBreak(ch)) { result.push(lineStart); lineStart = pos; } @@ -5189,6 +5859,7 @@ var ts; return computePositionOfLineAndCharacter(getLineStarts(sourceFile), line, character, sourceFile.text); } ts.getPositionOfLineAndCharacter = getPositionOfLineAndCharacter; + /* @internal */ function computePositionOfLineAndCharacter(lineStarts, line, character, debugText) { if (line < 0 || line >= lineStarts.length) { ts.Debug.fail("Bad line number. Line: " + line + ", lineStarts.length: " + lineStarts.length + " , line map is correct? " + (debugText !== undefined ? ts.arraysEqual(lineStarts, computeLineStarts(debugText)) : "unknown")); @@ -5198,18 +5869,30 @@ var ts; ts.Debug.assert(res < lineStarts[line + 1]); } else if (debugText !== undefined) { - ts.Debug.assert(res <= debugText.length); + ts.Debug.assert(res <= debugText.length); // Allow single character overflow for trailing newline } return res; } ts.computePositionOfLineAndCharacter = computePositionOfLineAndCharacter; + /* @internal */ function getLineStarts(sourceFile) { return sourceFile.lineMap || (sourceFile.lineMap = computeLineStarts(sourceFile.text)); } ts.getLineStarts = getLineStarts; + /* @internal */ + /** + * We assume the first line starts at position 0 and 'position' is non-negative. + */ function computeLineAndCharacterOfPosition(lineStarts, position) { var lineNumber = ts.binarySearch(lineStarts, position, ts.identity, ts.compareValues); if (lineNumber < 0) { + // If the actual position was not found, + // the binary search returns the 2's-complement of the next line start + // e.g. if the line starts at [5, 10, 23, 80] and the position requested was 20 + // then the search will return -2. + // + // We want the index of the previous line start, so we subtract 1. + // Review 2's-complement if this is confusing. lineNumber = ~lineNumber - 1; ts.Debug.assert(lineNumber !== -1, "position cannot precede the beginning of the file"); } @@ -5227,86 +5910,107 @@ var ts; return isWhiteSpaceSingleLine(ch) || isLineBreak(ch); } ts.isWhiteSpaceLike = isWhiteSpaceLike; + /** Does not include line breaks. For that, see isWhiteSpaceLike. */ function isWhiteSpaceSingleLine(ch) { - return ch === 32 || - ch === 9 || - ch === 11 || - ch === 12 || - ch === 160 || - ch === 133 || - ch === 5760 || - ch >= 8192 && ch <= 8203 || - ch === 8239 || - ch === 8287 || - ch === 12288 || - ch === 65279; + // Note: nextLine is in the Zs space, and should be considered to be a whitespace. + // It is explicitly not a line-break as it isn't in the exact set specified by EcmaScript. + return ch === 32 /* space */ || + ch === 9 /* tab */ || + ch === 11 /* verticalTab */ || + ch === 12 /* formFeed */ || + ch === 160 /* nonBreakingSpace */ || + ch === 133 /* nextLine */ || + ch === 5760 /* ogham */ || + ch >= 8192 /* enQuad */ && ch <= 8203 /* zeroWidthSpace */ || + ch === 8239 /* narrowNoBreakSpace */ || + ch === 8287 /* mathematicalSpace */ || + ch === 12288 /* ideographicSpace */ || + ch === 65279 /* byteOrderMark */; } ts.isWhiteSpaceSingleLine = isWhiteSpaceSingleLine; function isLineBreak(ch) { - return ch === 10 || - ch === 13 || - ch === 8232 || - ch === 8233; + // ES5 7.3: + // The ECMAScript line terminator characters are listed in Table 3. + // Table 3: Line Terminator Characters + // Code Unit Value Name Formal Name + // \u000A Line Feed + // \u000D Carriage Return + // \u2028 Line separator + // \u2029 Paragraph separator + // Only the characters in Table 3 are treated as line terminators. Other new line or line + // breaking characters are treated as white space but not as line terminators. + return ch === 10 /* lineFeed */ || + ch === 13 /* carriageReturn */ || + ch === 8232 /* lineSeparator */ || + ch === 8233 /* paragraphSeparator */; } ts.isLineBreak = isLineBreak; function isDigit(ch) { - return ch >= 48 && ch <= 57; + return ch >= 48 /* _0 */ && ch <= 57 /* _9 */; } + /* @internal */ function isOctalDigit(ch) { - return ch >= 48 && ch <= 55; + return ch >= 48 /* _0 */ && ch <= 55 /* _7 */; } ts.isOctalDigit = isOctalDigit; function couldStartTrivia(text, pos) { + // Keep in sync with skipTrivia var ch = text.charCodeAt(pos); switch (ch) { - case 13: - case 10: - case 9: - case 11: - case 12: - case 32: - case 47: - case 60: - case 124: - case 61: - case 62: + case 13 /* carriageReturn */: + case 10 /* lineFeed */: + case 9 /* tab */: + case 11 /* verticalTab */: + case 12 /* formFeed */: + case 32 /* space */: + case 47 /* slash */: + // starts of normal trivia + case 60 /* lessThan */: + case 124 /* bar */: + case 61 /* equals */: + case 62 /* greaterThan */: + // Starts of conflict marker trivia return true; - case 35: + case 35 /* hash */: + // Only if its the beginning can we have #! trivia return pos === 0; default: - return ch > 127; + return ch > 127 /* maxAsciiCharacter */; } } ts.couldStartTrivia = couldStartTrivia; + /* @internal */ function skipTrivia(text, pos, stopAfterLineBreak, stopAtComments) { if (stopAtComments === void 0) { stopAtComments = false; } if (ts.positionIsSynthesized(pos)) { return pos; } + // Keep in sync with couldStartTrivia while (true) { var ch = text.charCodeAt(pos); switch (ch) { - case 13: - if (text.charCodeAt(pos + 1) === 10) { + case 13 /* carriageReturn */: + if (text.charCodeAt(pos + 1) === 10 /* lineFeed */) { pos++; } - case 10: + // falls through + case 10 /* lineFeed */: pos++; if (stopAfterLineBreak) { return pos; } continue; - case 9: - case 11: - case 12: - case 32: + case 9 /* tab */: + case 11 /* verticalTab */: + case 12 /* formFeed */: + case 32 /* space */: pos++; continue; - case 47: + case 47 /* slash */: if (stopAtComments) { break; } - if (text.charCodeAt(pos + 1) === 47) { + if (text.charCodeAt(pos + 1) === 47 /* slash */) { pos += 2; while (pos < text.length) { if (isLineBreak(text.charCodeAt(pos))) { @@ -5316,10 +6020,10 @@ var ts; } continue; } - if (text.charCodeAt(pos + 1) === 42) { + if (text.charCodeAt(pos + 1) === 42 /* asterisk */) { pos += 2; while (pos < text.length) { - if (text.charCodeAt(pos) === 42 && text.charCodeAt(pos + 1) === 47) { + if (text.charCodeAt(pos) === 42 /* asterisk */ && text.charCodeAt(pos + 1) === 47 /* slash */) { pos += 2; break; } @@ -5328,23 +6032,23 @@ var ts; continue; } break; - case 60: - case 124: - case 61: - case 62: + case 60 /* lessThan */: + case 124 /* bar */: + case 61 /* equals */: + case 62 /* greaterThan */: if (isConflictMarkerTrivia(text, pos)) { pos = scanConflictMarkerTrivia(text, pos); continue; } break; - case 35: + case 35 /* hash */: if (pos === 0 && isShebangTrivia(text, pos)) { pos = scanShebangTrivia(text, pos); continue; } break; default: - if (ch > 127 && (isWhiteSpaceLike(ch))) { + if (ch > 127 /* maxAsciiCharacter */ && (isWhiteSpaceLike(ch))) { pos++; continue; } @@ -5354,9 +6058,12 @@ var ts; } } ts.skipTrivia = skipTrivia; + // All conflict markers consist of the same character repeated seven times. If it is + // a <<<<<<< or >>>>>>> marker then it is also followed by a space. var mergeConflictMarkerLength = "<<<<<<<".length; function isConflictMarkerTrivia(text, pos) { ts.Debug.assert(pos >= 0); + // Conflict markers must be at the start of a line. if (pos === 0 || isLineBreak(text.charCodeAt(pos - 1))) { var ch = text.charCodeAt(pos); if ((pos + mergeConflictMarkerLength) < text.length) { @@ -5365,8 +6072,8 @@ var ts; return false; } } - return ch === 61 || - text.charCodeAt(pos + mergeConflictMarkerLength) === 32; + return ch === 61 /* equals */ || + text.charCodeAt(pos + mergeConflictMarkerLength) === 32 /* space */; } } return false; @@ -5377,16 +6084,18 @@ var ts; } var ch = text.charCodeAt(pos); var len = text.length; - if (ch === 60 || ch === 62) { + if (ch === 60 /* lessThan */ || ch === 62 /* greaterThan */) { while (pos < len && !isLineBreak(text.charCodeAt(pos))) { pos++; } } else { - ts.Debug.assert(ch === 124 || ch === 61); + ts.Debug.assert(ch === 124 /* bar */ || ch === 61 /* equals */); + // Consume everything from the start of a ||||||| or ======= marker to the start + // of the next ======= or >>>>>>> marker. while (pos < len) { var currentChar = text.charCodeAt(pos); - if ((currentChar === 61 || currentChar === 62) && currentChar !== ch && isConflictMarkerTrivia(text, pos)) { + if ((currentChar === 61 /* equals */ || currentChar === 62 /* greaterThan */) && currentChar !== ch && isConflictMarkerTrivia(text, pos)) { break; } pos++; @@ -5396,6 +6105,7 @@ var ts; } var shebangTriviaRegex = /^#!.*/; function isShebangTrivia(text, pos) { + // Shebangs check must only be done at the start of the file ts.Debug.assert(pos === 0); return shebangTriviaRegex.test(text); } @@ -5404,6 +6114,26 @@ var ts; pos = pos + shebang.length; return pos; } + /** + * Invokes a callback for each comment range following the provided position. + * + * Single-line comment ranges include the leading double-slash characters but not the ending + * line break. Multi-line comment ranges include the leading slash-asterisk and trailing + * asterisk-slash characters. + * + * @param reduce If true, accumulates the result of calling the callback in a fashion similar + * to reduceLeft. If false, iteration stops when the callback returns a truthy value. + * @param text The source text to scan. + * @param pos The position at which to start scanning. + * @param trailing If false, whitespace is skipped until the first line break and comments + * between that location and the next token are returned. If true, comments occurring + * between the given position and the next line break are returned. + * @param cb The callback to execute as each comment range is encountered. + * @param state A state value to pass to each iteration of the callback. + * @param initial An initial value to pass when accumulating results (when "reduce" is true). + * @returns If "reduce" is true, the accumulated value. If "reduce" is false, the first truthy + * return value of the callback. + */ function iterateCommentRanges(reduce, text, pos, trailing, cb, state, initial) { var pendingPos; var pendingEnd; @@ -5415,11 +6145,12 @@ var ts; scan: while (pos >= 0 && pos < text.length) { var ch = text.charCodeAt(pos); switch (ch) { - case 13: - if (text.charCodeAt(pos + 1) === 10) { + case 13 /* carriageReturn */: + if (text.charCodeAt(pos + 1) === 10 /* lineFeed */) { pos++; } - case 10: + // falls through + case 10 /* lineFeed */: pos++; if (trailing) { break scan; @@ -5429,20 +6160,20 @@ var ts; pendingHasTrailingNewLine = true; } continue; - case 9: - case 11: - case 12: - case 32: + case 9 /* tab */: + case 11 /* verticalTab */: + case 12 /* formFeed */: + case 32 /* space */: pos++; continue; - case 47: + case 47 /* slash */: var nextChar = text.charCodeAt(pos + 1); var hasTrailingNewLine = false; - if (nextChar === 47 || nextChar === 42) { - var kind = nextChar === 47 ? 2 : 3; + if (nextChar === 47 /* slash */ || nextChar === 42 /* asterisk */) { + var kind = nextChar === 47 /* slash */ ? 2 /* SingleLineCommentTrivia */ : 3 /* MultiLineCommentTrivia */; var startPos = pos; pos += 2; - if (nextChar === 47) { + if (nextChar === 47 /* slash */) { while (pos < text.length) { if (isLineBreak(text.charCodeAt(pos))) { hasTrailingNewLine = true; @@ -5453,7 +6184,7 @@ var ts; } else { while (pos < text.length) { - if (text.charCodeAt(pos) === 42 && text.charCodeAt(pos + 1) === 47) { + if (text.charCodeAt(pos) === 42 /* asterisk */ && text.charCodeAt(pos + 1) === 47 /* slash */) { pos += 2; break; } @@ -5464,6 +6195,7 @@ var ts; if (hasPendingCommentRange) { accumulator = cb(pendingPos, pendingEnd, pendingKind, pendingHasTrailingNewLine, state, accumulator); if (!reduce && accumulator) { + // If we are not reducing and we have a truthy result, return it. return accumulator; } } @@ -5477,7 +6209,7 @@ var ts; } break scan; default: - if (ch > 127 && (isWhiteSpaceLike(ch))) { + if (ch > 127 /* maxAsciiCharacter */ && (isWhiteSpaceLike(ch))) { if (hasPendingCommentRange && isLineBreak(ch)) { pendingHasTrailingNewLine = true; } @@ -5493,19 +6225,19 @@ var ts; return accumulator; } function forEachLeadingCommentRange(text, pos, cb, state) { - return iterateCommentRanges(false, text, pos, false, cb, state); + return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ false, cb, state); } ts.forEachLeadingCommentRange = forEachLeadingCommentRange; function forEachTrailingCommentRange(text, pos, cb, state) { - return iterateCommentRanges(false, text, pos, true, cb, state); + return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ true, cb, state); } ts.forEachTrailingCommentRange = forEachTrailingCommentRange; function reduceEachLeadingCommentRange(text, pos, cb, state, initial) { - return iterateCommentRanges(true, text, pos, false, cb, state, initial); + return iterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ false, cb, state, initial); } ts.reduceEachLeadingCommentRange = reduceEachLeadingCommentRange; function reduceEachTrailingCommentRange(text, pos, cb, state, initial) { - return iterateCommentRanges(true, text, pos, true, cb, state, initial); + return iterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ true, cb, state, initial); } ts.reduceEachTrailingCommentRange = reduceEachTrailingCommentRange; function appendCommentRange(pos, end, kind, hasTrailingNewLine, _state, comments) { @@ -5516,13 +6248,14 @@ var ts; return comments; } function getLeadingCommentRanges(text, pos) { - return reduceEachLeadingCommentRange(text, pos, appendCommentRange, undefined, undefined); + return reduceEachLeadingCommentRange(text, pos, appendCommentRange, /*state*/ undefined, /*initial*/ undefined); } ts.getLeadingCommentRanges = getLeadingCommentRanges; function getTrailingCommentRanges(text, pos) { - return reduceEachTrailingCommentRange(text, pos, appendCommentRange, undefined, undefined); + return reduceEachTrailingCommentRange(text, pos, appendCommentRange, /*state*/ undefined, /*initial*/ undefined); } ts.getTrailingCommentRanges = getTrailingCommentRanges; + /** Optionally, get the shebang */ function getShebang(text) { var match = shebangTriviaRegex.exec(text); if (match) { @@ -5531,17 +6264,18 @@ var ts; } ts.getShebang = getShebang; function isIdentifierStart(ch, languageVersion) { - return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || - ch === 36 || ch === 95 || - ch > 127 && isUnicodeIdentifierStart(ch, languageVersion); + return ch >= 65 /* A */ && ch <= 90 /* Z */ || ch >= 97 /* a */ && ch <= 122 /* z */ || + ch === 36 /* $ */ || ch === 95 /* _ */ || + ch > 127 /* maxAsciiCharacter */ && isUnicodeIdentifierStart(ch, languageVersion); } ts.isIdentifierStart = isIdentifierStart; function isIdentifierPart(ch, languageVersion) { - return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || - ch >= 48 && ch <= 57 || ch === 36 || ch === 95 || - ch > 127 && isUnicodeIdentifierPart(ch, languageVersion); + return ch >= 65 /* A */ && ch <= 90 /* Z */ || ch >= 97 /* a */ && ch <= 122 /* z */ || + ch >= 48 /* _0 */ && ch <= 57 /* _9 */ || ch === 36 /* $ */ || ch === 95 /* _ */ || + ch > 127 /* maxAsciiCharacter */ && isUnicodeIdentifierPart(ch, languageVersion); } ts.isIdentifierPart = isIdentifierPart; + /* @internal */ function isIdentifierText(name, languageVersion) { if (!isIdentifierStart(name.charCodeAt(0), languageVersion)) { return false; @@ -5554,12 +6288,17 @@ var ts; return true; } ts.isIdentifierText = isIdentifierText; + // Creates a scanner over a (possibly unspecified) range of a piece of text. function createScanner(languageVersion, skipTrivia, languageVariant, textInitial, onError, start, length) { - if (languageVariant === void 0) { languageVariant = 0; } + if (languageVariant === void 0) { languageVariant = 0 /* Standard */; } var text = textInitial; + // Current position (end position of text of current token) var pos; + // end of text var end; + // Start position of whitespace before current token var startPos; + // Start position of text of current token var tokenPos; var token; var tokenValue; @@ -5572,11 +6311,11 @@ var ts; getTokenPos: function () { return tokenPos; }, getTokenText: function () { return text.substring(tokenPos, pos); }, getTokenValue: function () { return tokenValue; }, - hasExtendedUnicodeEscape: function () { return (tokenFlags & 8) !== 0; }, - hasPrecedingLineBreak: function () { return (tokenFlags & 1) !== 0; }, - isIdentifier: function () { return token === 71 || token > 107; }, - isReservedWord: function () { return token >= 72 && token <= 107; }, - isUnterminated: function () { return (tokenFlags & 4) !== 0; }, + hasExtendedUnicodeEscape: function () { return (tokenFlags & 8 /* ExtendedUnicodeEscape */) !== 0; }, + hasPrecedingLineBreak: function () { return (tokenFlags & 1 /* PrecedingLineBreak */) !== 0; }, + isIdentifier: function () { return token === 71 /* Identifier */ || token > 107 /* LastReservedWord */; }, + isReservedWord: function () { return token >= 72 /* FirstReservedWord */ && token <= 107 /* LastReservedWord */; }, + isUnterminated: function () { return (tokenFlags & 4 /* Unterminated */) !== 0; }, getTokenFlags: function () { return tokenFlags; }, reScanGreaterToken: reScanGreaterToken, reScanSlashToken: reScanSlashToken, @@ -5613,8 +6352,8 @@ var ts; var result = ""; while (true) { var ch = text.charCodeAt(pos); - if (ch === 95) { - tokenFlags |= 512; + if (ch === 95 /* _ */) { + tokenFlags |= 512 /* ContainsSeparator */; if (allowSeparator) { allowSeparator = false; isPreviousTokenSeparator = true; @@ -5638,7 +6377,7 @@ var ts; } break; } - if (text.charCodeAt(pos - 1) === 95) { + if (text.charCodeAt(pos - 1) === 95 /* _ */) { error(ts.Diagnostics.Numeric_separators_are_not_allowed_here, pos - 1, 1); } return result + text.substring(start, pos); @@ -5648,15 +6387,15 @@ var ts; var mainFragment = scanNumberFragment(); var decimalFragment; var scientificFragment; - if (text.charCodeAt(pos) === 46) { + if (text.charCodeAt(pos) === 46 /* dot */) { pos++; decimalFragment = scanNumberFragment(); } var end = pos; - if (text.charCodeAt(pos) === 69 || text.charCodeAt(pos) === 101) { + if (text.charCodeAt(pos) === 69 /* E */ || text.charCodeAt(pos) === 101 /* e */) { pos++; - tokenFlags |= 16; - if (text.charCodeAt(pos) === 43 || text.charCodeAt(pos) === 45) + tokenFlags |= 16 /* Scientific */; + if (text.charCodeAt(pos) === 43 /* plus */ || text.charCodeAt(pos) === 45 /* minus */) pos++; var preNumericPart = pos; var finalFragment = scanNumberFragment(); @@ -5668,7 +6407,7 @@ var ts; end = pos; } } - if (tokenFlags & 512) { + if (tokenFlags & 512 /* ContainsSeparator */) { var result = mainFragment; if (decimalFragment) { result += "." + decimalFragment; @@ -5679,7 +6418,7 @@ var ts; return "" + +result; } else { - return "" + +(text.substring(start, end)); + return "" + +(text.substring(start, end)); // No need to use all the fragments; no _ removal needed } } function scanOctalDigits() { @@ -5689,11 +6428,19 @@ var ts; } return +(text.substring(start, pos)); } + /** + * Scans the given number of hexadecimal digits in the text, + * returning -1 if the given number is unavailable. + */ function scanExactNumberOfHexDigits(count, canHaveSeparators) { - return scanHexDigits(count, false, canHaveSeparators); + return scanHexDigits(/*minCount*/ count, /*scanAsManyAsPossible*/ false, canHaveSeparators); } + /** + * Scans as many hexadecimal digits as are available in the text, + * returning -1 if the given number of digits was unavailable. + */ function scanMinimumNumberOfHexDigits(count, canHaveSeparators) { - return scanHexDigits(count, true, canHaveSeparators); + return scanHexDigits(/*minCount*/ count, /*scanAsManyAsPossible*/ true, canHaveSeparators); } function scanHexDigits(minCount, scanAsManyAsPossible, canHaveSeparators) { var digits = 0; @@ -5702,8 +6449,8 @@ var ts; var isPreviousTokenSeparator = false; while (digits < minCount || scanAsManyAsPossible) { var ch = text.charCodeAt(pos); - if (canHaveSeparators && ch === 95) { - tokenFlags |= 512; + if (canHaveSeparators && ch === 95 /* _ */) { + tokenFlags |= 512 /* ContainsSeparator */; if (allowSeparator) { allowSeparator = false; isPreviousTokenSeparator = true; @@ -5718,14 +6465,14 @@ var ts; continue; } allowSeparator = canHaveSeparators; - if (ch >= 48 && ch <= 57) { - value = value * 16 + ch - 48; + if (ch >= 48 /* _0 */ && ch <= 57 /* _9 */) { + value = value * 16 + ch - 48 /* _0 */; } - else if (ch >= 65 && ch <= 70) { - value = value * 16 + ch - 65 + 10; + else if (ch >= 65 /* A */ && ch <= 70 /* F */) { + value = value * 16 + ch - 65 /* A */ + 10; } - else if (ch >= 97 && ch <= 102) { - value = value * 16 + ch - 97 + 10; + else if (ch >= 97 /* a */ && ch <= 102 /* f */) { + value = value * 16 + ch - 97 /* a */ + 10; } else { break; @@ -5737,7 +6484,7 @@ var ts; if (digits < minCount) { value = -1; } - if (text.charCodeAt(pos - 1) === 95) { + if (text.charCodeAt(pos - 1) === 95 /* _ */) { error(ts.Diagnostics.Numeric_separators_are_not_allowed_here, pos - 1, 1); } return value; @@ -5751,7 +6498,7 @@ var ts; while (true) { if (pos >= end) { result += text.substring(start, pos); - tokenFlags |= 4; + tokenFlags |= 4 /* Unterminated */; error(ts.Diagnostics.Unterminated_string_literal); break; } @@ -5761,7 +6508,7 @@ var ts; pos++; break; } - if (ch === 92 && !jsxAttributeString) { + if (ch === 92 /* backslash */ && !jsxAttributeString) { result += text.substring(start, pos); result += scanEscapeSequence(); start = pos; @@ -5769,7 +6516,7 @@ var ts; } if (isLineBreak(ch) && !jsxAttributeString) { result += text.substring(start, pos); - tokenFlags |= 4; + tokenFlags |= 4 /* Unterminated */; error(ts.Diagnostics.Unterminated_string_literal); break; } @@ -5777,8 +6524,12 @@ var ts; } return result; } + /** + * Sets the current 'tokenValue' and returns a NoSubstitutionTemplateLiteral or + * a literal component of a TemplateExpression. + */ function scanTemplateAndSetTokenValue() { - var startedWithBacktick = text.charCodeAt(pos) === 96; + var startedWithBacktick = text.charCodeAt(pos) === 96 /* backtick */; pos++; var start = pos; var contents = ""; @@ -5786,34 +6537,39 @@ var ts; while (true) { if (pos >= end) { contents += text.substring(start, pos); - tokenFlags |= 4; + tokenFlags |= 4 /* Unterminated */; error(ts.Diagnostics.Unterminated_template_literal); - resultingToken = startedWithBacktick ? 13 : 16; + resultingToken = startedWithBacktick ? 13 /* NoSubstitutionTemplateLiteral */ : 16 /* TemplateTail */; break; } var currChar = text.charCodeAt(pos); - if (currChar === 96) { + // '`' + if (currChar === 96 /* backtick */) { contents += text.substring(start, pos); pos++; - resultingToken = startedWithBacktick ? 13 : 16; + resultingToken = startedWithBacktick ? 13 /* NoSubstitutionTemplateLiteral */ : 16 /* TemplateTail */; break; } - if (currChar === 36 && pos + 1 < end && text.charCodeAt(pos + 1) === 123) { + // '${' + if (currChar === 36 /* $ */ && pos + 1 < end && text.charCodeAt(pos + 1) === 123 /* openBrace */) { contents += text.substring(start, pos); pos += 2; - resultingToken = startedWithBacktick ? 14 : 15; + resultingToken = startedWithBacktick ? 14 /* TemplateHead */ : 15 /* TemplateMiddle */; break; } - if (currChar === 92) { + // Escape character + if (currChar === 92 /* backslash */) { contents += text.substring(start, pos); contents += scanEscapeSequence(); start = pos; continue; } - if (currChar === 13) { + // Speculated ECMAScript 6 Spec 11.8.6.1: + // and LineTerminatorSequences are normalized to for Template Values + if (currChar === 13 /* carriageReturn */) { contents += text.substring(start, pos); pos++; - if (pos < end && text.charCodeAt(pos) === 10) { + if (pos < end && text.charCodeAt(pos) === 10 /* lineFeed */) { pos++; } contents += "\n"; @@ -5835,47 +6591,53 @@ var ts; var ch = text.charCodeAt(pos); pos++; switch (ch) { - case 48: + case 48 /* _0 */: return "\0"; - case 98: + case 98 /* b */: return "\b"; - case 116: + case 116 /* t */: return "\t"; - case 110: + case 110 /* n */: return "\n"; - case 118: + case 118 /* v */: return "\v"; - case 102: + case 102 /* f */: return "\f"; - case 114: + case 114 /* r */: return "\r"; - case 39: + case 39 /* singleQuote */: return "\'"; - case 34: + case 34 /* doubleQuote */: return "\""; - case 117: - if (pos < end && text.charCodeAt(pos) === 123) { - tokenFlags |= 8; + case 117 /* u */: + // '\u{DDDDDDDD}' + if (pos < end && text.charCodeAt(pos) === 123 /* openBrace */) { + tokenFlags |= 8 /* ExtendedUnicodeEscape */; pos++; return scanExtendedUnicodeEscape(); } - return scanHexadecimalEscape(4); - case 120: - return scanHexadecimalEscape(2); - case 13: - if (pos < end && text.charCodeAt(pos) === 10) { + // '\uDDDD' + return scanHexadecimalEscape(/*numDigits*/ 4); + case 120 /* x */: + // '\xDD' + return scanHexadecimalEscape(/*numDigits*/ 2); + // when encountering a LineContinuation (i.e. a backslash and a line terminator sequence), + // the line terminator is interpreted to be "the empty code unit sequence". + case 13 /* carriageReturn */: + if (pos < end && text.charCodeAt(pos) === 10 /* lineFeed */) { pos++; } - case 10: - case 8232: - case 8233: + // falls through + case 10 /* lineFeed */: + case 8232 /* lineSeparator */: + case 8233 /* paragraphSeparator */: return ""; default: return String.fromCharCode(ch); } } function scanHexadecimalEscape(numDigits) { - var escapedValue = scanExactNumberOfHexDigits(numDigits, false); + var escapedValue = scanExactNumberOfHexDigits(numDigits, /*canHaveSeparators*/ false); if (escapedValue >= 0) { return String.fromCharCode(escapedValue); } @@ -5885,8 +6647,9 @@ var ts; } } function scanExtendedUnicodeEscape() { - var escapedValue = scanMinimumNumberOfHexDigits(1, false); + var escapedValue = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ false); var isInvalidExtendedEscape = false; + // Validate the value of the digit if (escapedValue < 0) { error(ts.Diagnostics.Hexadecimal_digit_expected); isInvalidExtendedEscape = true; @@ -5899,7 +6662,8 @@ var ts; error(ts.Diagnostics.Unexpected_end_of_text); isInvalidExtendedEscape = true; } - else if (text.charCodeAt(pos) === 125) { + else if (text.charCodeAt(pos) === 125 /* closeBrace */) { + // Only swallow the following character up if it's a '}'. pos++; } else { @@ -5911,6 +6675,7 @@ var ts; } return utf16EncodeAsString(escapedValue); } + // Derived from the 10.1.1 UTF16Encoding of the ES6 Spec. function utf16EncodeAsString(codePoint) { ts.Debug.assert(0x0 <= codePoint && codePoint <= 0x10FFFF); if (codePoint <= 65535) { @@ -5920,11 +6685,13 @@ var ts; var codeUnit2 = ((codePoint - 65536) % 1024) + 0xDC00; return String.fromCharCode(codeUnit1, codeUnit2); } + // Current character is known to be a backslash. Check for Unicode escape of the form '\uXXXX' + // and return code point value if valid Unicode escape is found. Otherwise return -1. function peekUnicodeEscape() { - if (pos + 5 < end && text.charCodeAt(pos + 1) === 117) { + if (pos + 5 < end && text.charCodeAt(pos + 1) === 117 /* u */) { var start_1 = pos; pos += 2; - var value = scanExactNumberOfHexDigits(4, false); + var value = scanExactNumberOfHexDigits(4, /*canHaveSeparators*/ false); pos = start_1; return value; } @@ -5938,13 +6705,14 @@ var ts; if (isIdentifierPart(ch, languageVersion)) { pos++; } - else if (ch === 92) { + else if (ch === 92 /* backslash */) { ch = peekUnicodeEscape(); if (!(ch >= 0 && isIdentifierPart(ch, languageVersion))) { break; } result += text.substring(start, pos); result += String.fromCharCode(ch); + // Valid Unicode escape is always six characters pos += 6; start = pos; } @@ -5956,28 +6724,32 @@ var ts; return result; } function getIdentifierToken() { + // Reserved words are between 2 and 11 characters long and start with a lowercase letter var len = tokenValue.length; if (len >= 2 && len <= 11) { var ch = tokenValue.charCodeAt(0); - if (ch >= 97 && ch <= 122) { + if (ch >= 97 /* a */ && ch <= 122 /* z */) { token = textToToken.get(tokenValue); if (token !== undefined) { return token; } } } - return token = 71; + return token = 71 /* Identifier */; } function scanBinaryOrOctalDigits(base) { ts.Debug.assert(base === 2 || base === 8, "Expected either base 2 or base 8"); var value = 0; + // For counting number of digits; Valid binaryIntegerLiteral must have at least one binary digit following B or b. + // Similarly valid octalIntegerLiteral must have at least one octal digit following o or O. var numberOfDigits = 0; var separatorAllowed = false; var isPreviousTokenSeparator = false; while (true) { var ch = text.charCodeAt(pos); - if (ch === 95) { - tokenFlags |= 512; + // Numeric separators are allowed anywhere within a numeric literal, except not at the beginning, or following another separator + if (ch === 95 /* _ */) { + tokenFlags |= 512 /* ContainsSeparator */; if (separatorAllowed) { separatorAllowed = false; isPreviousTokenSeparator = true; @@ -5992,7 +6764,7 @@ var ts; continue; } separatorAllowed = true; - var valueOfCh = ch - 48; + var valueOfCh = ch - 48 /* _0 */; if (!isDigit(ch) || valueOfCh >= base) { break; } @@ -6001,10 +6773,12 @@ var ts; numberOfDigits++; isPreviousTokenSeparator = false; } + // Invalid binaryIntegerLiteral or octalIntegerLiteral if (numberOfDigits === 0) { return -1; } - if (text.charCodeAt(pos - 1) === 95) { + if (text.charCodeAt(pos - 1) === 95 /* _ */) { + // Literal ends with underscore - not allowed error(ts.Diagnostics.Numeric_separators_are_not_allowed_here, pos - 1, 1); return value; } @@ -6016,39 +6790,41 @@ var ts; while (true) { tokenPos = pos; if (pos >= end) { - return token = 1; + return token = 1 /* EndOfFileToken */; } var ch = text.charCodeAt(pos); - if (ch === 35 && pos === 0 && isShebangTrivia(text, pos)) { + // Special handling for shebang + if (ch === 35 /* hash */ && pos === 0 && isShebangTrivia(text, pos)) { pos = scanShebangTrivia(text, pos); if (skipTrivia) { continue; } else { - return token = 6; + return token = 6 /* ShebangTrivia */; } } switch (ch) { - case 10: - case 13: - tokenFlags |= 1; + case 10 /* lineFeed */: + case 13 /* carriageReturn */: + tokenFlags |= 1 /* PrecedingLineBreak */; if (skipTrivia) { pos++; continue; } else { - if (ch === 13 && pos + 1 < end && text.charCodeAt(pos + 1) === 10) { + if (ch === 13 /* carriageReturn */ && pos + 1 < end && text.charCodeAt(pos + 1) === 10 /* lineFeed */) { + // consume both CR and LF pos += 2; } else { pos++; } - return token = 4; + return token = 4 /* NewLineTrivia */; } - case 9: - case 11: - case 12: - case 32: + case 9 /* tab */: + case 11 /* verticalTab */: + case 12 /* formFeed */: + case 32 /* space */: if (skipTrivia) { pos++; continue; @@ -6057,89 +6833,90 @@ var ts; while (pos < end && isWhiteSpaceSingleLine(text.charCodeAt(pos))) { pos++; } - return token = 5; + return token = 5 /* WhitespaceTrivia */; } - case 33: - if (text.charCodeAt(pos + 1) === 61) { - if (text.charCodeAt(pos + 2) === 61) { - return pos += 3, token = 35; + case 33 /* exclamation */: + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + if (text.charCodeAt(pos + 2) === 61 /* equals */) { + return pos += 3, token = 35 /* ExclamationEqualsEqualsToken */; } - return pos += 2, token = 33; + return pos += 2, token = 33 /* ExclamationEqualsToken */; } pos++; - return token = 51; - case 34: - case 39: + return token = 51 /* ExclamationToken */; + case 34 /* doubleQuote */: + case 39 /* singleQuote */: tokenValue = scanString(); - return token = 9; - case 96: + return token = 9 /* StringLiteral */; + case 96 /* backtick */: return token = scanTemplateAndSetTokenValue(); - case 37: - if (text.charCodeAt(pos + 1) === 61) { - return pos += 2, token = 64; + case 37 /* percent */: + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + return pos += 2, token = 64 /* PercentEqualsToken */; } pos++; - return token = 42; - case 38: - if (text.charCodeAt(pos + 1) === 38) { - return pos += 2, token = 53; + return token = 42 /* PercentToken */; + case 38 /* ampersand */: + if (text.charCodeAt(pos + 1) === 38 /* ampersand */) { + return pos += 2, token = 53 /* AmpersandAmpersandToken */; } - if (text.charCodeAt(pos + 1) === 61) { - return pos += 2, token = 68; + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + return pos += 2, token = 68 /* AmpersandEqualsToken */; } pos++; - return token = 48; - case 40: + return token = 48 /* AmpersandToken */; + case 40 /* openParen */: pos++; - return token = 19; - case 41: + return token = 19 /* OpenParenToken */; + case 41 /* closeParen */: pos++; - return token = 20; - case 42: - if (text.charCodeAt(pos + 1) === 61) { - return pos += 2, token = 61; + return token = 20 /* CloseParenToken */; + case 42 /* asterisk */: + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + return pos += 2, token = 61 /* AsteriskEqualsToken */; } - if (text.charCodeAt(pos + 1) === 42) { - if (text.charCodeAt(pos + 2) === 61) { - return pos += 3, token = 62; + if (text.charCodeAt(pos + 1) === 42 /* asterisk */) { + if (text.charCodeAt(pos + 2) === 61 /* equals */) { + return pos += 3, token = 62 /* AsteriskAsteriskEqualsToken */; } - return pos += 2, token = 40; + return pos += 2, token = 40 /* AsteriskAsteriskToken */; } pos++; - return token = 39; - case 43: - if (text.charCodeAt(pos + 1) === 43) { - return pos += 2, token = 43; + return token = 39 /* AsteriskToken */; + case 43 /* plus */: + if (text.charCodeAt(pos + 1) === 43 /* plus */) { + return pos += 2, token = 43 /* PlusPlusToken */; } - if (text.charCodeAt(pos + 1) === 61) { - return pos += 2, token = 59; + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + return pos += 2, token = 59 /* PlusEqualsToken */; } pos++; - return token = 37; - case 44: + return token = 37 /* PlusToken */; + case 44 /* comma */: pos++; - return token = 26; - case 45: - if (text.charCodeAt(pos + 1) === 45) { - return pos += 2, token = 44; + return token = 26 /* CommaToken */; + case 45 /* minus */: + if (text.charCodeAt(pos + 1) === 45 /* minus */) { + return pos += 2, token = 44 /* MinusMinusToken */; } - if (text.charCodeAt(pos + 1) === 61) { - return pos += 2, token = 60; + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + return pos += 2, token = 60 /* MinusEqualsToken */; } pos++; - return token = 38; - case 46: + return token = 38 /* MinusToken */; + case 46 /* dot */: if (isDigit(text.charCodeAt(pos + 1))) { tokenValue = scanNumber(); - return token = 8; + return token = 8 /* NumericLiteral */; } - if (text.charCodeAt(pos + 1) === 46 && text.charCodeAt(pos + 2) === 46) { - return pos += 3, token = 24; + if (text.charCodeAt(pos + 1) === 46 /* dot */ && text.charCodeAt(pos + 2) === 46 /* dot */) { + return pos += 3, token = 24 /* DotDotDotToken */; } pos++; - return token = 23; - case 47: - if (text.charCodeAt(pos + 1) === 47) { + return token = 23 /* DotToken */; + case 47 /* slash */: + // Single-line comment + if (text.charCodeAt(pos + 1) === 47 /* slash */) { pos += 2; while (pos < end) { if (isLineBreak(text.charCodeAt(pos))) { @@ -6151,24 +6928,25 @@ var ts; continue; } else { - return token = 2; + return token = 2 /* SingleLineCommentTrivia */; } } - if (text.charCodeAt(pos + 1) === 42) { + // Multi-line comment + if (text.charCodeAt(pos + 1) === 42 /* asterisk */) { pos += 2; - if (text.charCodeAt(pos) === 42 && text.charCodeAt(pos + 1) !== 47) { - tokenFlags |= 2; + if (text.charCodeAt(pos) === 42 /* asterisk */ && text.charCodeAt(pos + 1) !== 47 /* slash */) { + tokenFlags |= 2 /* PrecedingJSDocComment */; } var commentClosed = false; while (pos < end) { var ch_1 = text.charCodeAt(pos); - if (ch_1 === 42 && text.charCodeAt(pos + 1) === 47) { + if (ch_1 === 42 /* asterisk */ && text.charCodeAt(pos + 1) === 47 /* slash */) { pos += 2; commentClosed = true; break; } if (isLineBreak(ch_1)) { - tokenFlags |= 1; + tokenFlags |= 1 /* PrecedingLineBreak */; } pos++; } @@ -6180,177 +6958,182 @@ var ts; } else { if (!commentClosed) { - tokenFlags |= 4; + tokenFlags |= 4 /* Unterminated */; } - return token = 3; + return token = 3 /* MultiLineCommentTrivia */; } } - if (text.charCodeAt(pos + 1) === 61) { - return pos += 2, token = 63; + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + return pos += 2, token = 63 /* SlashEqualsToken */; } pos++; - return token = 41; - case 48: - if (pos + 2 < end && (text.charCodeAt(pos + 1) === 88 || text.charCodeAt(pos + 1) === 120)) { + return token = 41 /* SlashToken */; + case 48 /* _0 */: + if (pos + 2 < end && (text.charCodeAt(pos + 1) === 88 /* X */ || text.charCodeAt(pos + 1) === 120 /* x */)) { pos += 2; - var value = scanMinimumNumberOfHexDigits(1, true); + var value = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ true); if (value < 0) { error(ts.Diagnostics.Hexadecimal_digit_expected); value = 0; } tokenValue = "" + value; - tokenFlags |= 64; - return token = 8; + tokenFlags |= 64 /* HexSpecifier */; + return token = 8 /* NumericLiteral */; } - else if (pos + 2 < end && (text.charCodeAt(pos + 1) === 66 || text.charCodeAt(pos + 1) === 98)) { + else if (pos + 2 < end && (text.charCodeAt(pos + 1) === 66 /* B */ || text.charCodeAt(pos + 1) === 98 /* b */)) { pos += 2; - var value = scanBinaryOrOctalDigits(2); + var value = scanBinaryOrOctalDigits(/* base */ 2); if (value < 0) { error(ts.Diagnostics.Binary_digit_expected); value = 0; } tokenValue = "" + value; - tokenFlags |= 128; - return token = 8; + tokenFlags |= 128 /* BinarySpecifier */; + return token = 8 /* NumericLiteral */; } - else if (pos + 2 < end && (text.charCodeAt(pos + 1) === 79 || text.charCodeAt(pos + 1) === 111)) { + else if (pos + 2 < end && (text.charCodeAt(pos + 1) === 79 /* O */ || text.charCodeAt(pos + 1) === 111 /* o */)) { pos += 2; - var value = scanBinaryOrOctalDigits(8); + var value = scanBinaryOrOctalDigits(/* base */ 8); if (value < 0) { error(ts.Diagnostics.Octal_digit_expected); value = 0; } tokenValue = "" + value; - tokenFlags |= 256; - return token = 8; + tokenFlags |= 256 /* OctalSpecifier */; + return token = 8 /* NumericLiteral */; } + // Try to parse as an octal if (pos + 1 < end && isOctalDigit(text.charCodeAt(pos + 1))) { tokenValue = "" + scanOctalDigits(); - tokenFlags |= 32; - return token = 8; + tokenFlags |= 32 /* Octal */; + return token = 8 /* NumericLiteral */; } - case 49: - case 50: - case 51: - case 52: - case 53: - case 54: - case 55: - case 56: - case 57: + // This fall-through is a deviation from the EcmaScript grammar. The grammar says that a leading zero + // can only be followed by an octal digit, a dot, or the end of the number literal. However, we are being + // permissive and allowing decimal digits of the form 08* and 09* (which many browsers also do). + // falls through + case 49 /* _1 */: + case 50 /* _2 */: + case 51 /* _3 */: + case 52 /* _4 */: + case 53 /* _5 */: + case 54 /* _6 */: + case 55 /* _7 */: + case 56 /* _8 */: + case 57 /* _9 */: tokenValue = scanNumber(); - return token = 8; - case 58: + return token = 8 /* NumericLiteral */; + case 58 /* colon */: pos++; - return token = 56; - case 59: + return token = 56 /* ColonToken */; + case 59 /* semicolon */: pos++; - return token = 25; - case 60: + return token = 25 /* SemicolonToken */; + case 60 /* lessThan */: if (isConflictMarkerTrivia(text, pos)) { pos = scanConflictMarkerTrivia(text, pos, error); if (skipTrivia) { continue; } else { - return token = 7; + return token = 7 /* ConflictMarkerTrivia */; } } - if (text.charCodeAt(pos + 1) === 60) { - if (text.charCodeAt(pos + 2) === 61) { - return pos += 3, token = 65; + if (text.charCodeAt(pos + 1) === 60 /* lessThan */) { + if (text.charCodeAt(pos + 2) === 61 /* equals */) { + return pos += 3, token = 65 /* LessThanLessThanEqualsToken */; } - return pos += 2, token = 45; + return pos += 2, token = 45 /* LessThanLessThanToken */; } - if (text.charCodeAt(pos + 1) === 61) { - return pos += 2, token = 30; + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + return pos += 2, token = 30 /* LessThanEqualsToken */; } - if (languageVariant === 1 && - text.charCodeAt(pos + 1) === 47 && - text.charCodeAt(pos + 2) !== 42) { - return pos += 2, token = 28; + if (languageVariant === 1 /* JSX */ && + text.charCodeAt(pos + 1) === 47 /* slash */ && + text.charCodeAt(pos + 2) !== 42 /* asterisk */) { + return pos += 2, token = 28 /* LessThanSlashToken */; } pos++; - return token = 27; - case 61: + return token = 27 /* LessThanToken */; + case 61 /* equals */: if (isConflictMarkerTrivia(text, pos)) { pos = scanConflictMarkerTrivia(text, pos, error); if (skipTrivia) { continue; } else { - return token = 7; + return token = 7 /* ConflictMarkerTrivia */; } } - if (text.charCodeAt(pos + 1) === 61) { - if (text.charCodeAt(pos + 2) === 61) { - return pos += 3, token = 34; + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + if (text.charCodeAt(pos + 2) === 61 /* equals */) { + return pos += 3, token = 34 /* EqualsEqualsEqualsToken */; } - return pos += 2, token = 32; + return pos += 2, token = 32 /* EqualsEqualsToken */; } - if (text.charCodeAt(pos + 1) === 62) { - return pos += 2, token = 36; + if (text.charCodeAt(pos + 1) === 62 /* greaterThan */) { + return pos += 2, token = 36 /* EqualsGreaterThanToken */; } pos++; - return token = 58; - case 62: + return token = 58 /* EqualsToken */; + case 62 /* greaterThan */: if (isConflictMarkerTrivia(text, pos)) { pos = scanConflictMarkerTrivia(text, pos, error); if (skipTrivia) { continue; } else { - return token = 7; + return token = 7 /* ConflictMarkerTrivia */; } } pos++; - return token = 29; - case 63: + return token = 29 /* GreaterThanToken */; + case 63 /* question */: pos++; - return token = 55; - case 91: + return token = 55 /* QuestionToken */; + case 91 /* openBracket */: pos++; - return token = 21; - case 93: + return token = 21 /* OpenBracketToken */; + case 93 /* closeBracket */: pos++; - return token = 22; - case 94: - if (text.charCodeAt(pos + 1) === 61) { - return pos += 2, token = 70; + return token = 22 /* CloseBracketToken */; + case 94 /* caret */: + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + return pos += 2, token = 70 /* CaretEqualsToken */; } pos++; - return token = 50; - case 123: + return token = 50 /* CaretToken */; + case 123 /* openBrace */: pos++; - return token = 17; - case 124: + return token = 17 /* OpenBraceToken */; + case 124 /* bar */: if (isConflictMarkerTrivia(text, pos)) { pos = scanConflictMarkerTrivia(text, pos, error); if (skipTrivia) { continue; } else { - return token = 7; + return token = 7 /* ConflictMarkerTrivia */; } } - if (text.charCodeAt(pos + 1) === 124) { - return pos += 2, token = 54; + if (text.charCodeAt(pos + 1) === 124 /* bar */) { + return pos += 2, token = 54 /* BarBarToken */; } - if (text.charCodeAt(pos + 1) === 61) { - return pos += 2, token = 69; + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + return pos += 2, token = 69 /* BarEqualsToken */; } pos++; - return token = 49; - case 125: + return token = 49 /* BarToken */; + case 125 /* closeBrace */: pos++; - return token = 18; - case 126: + return token = 18 /* CloseBraceToken */; + case 126 /* tilde */: pos++; - return token = 52; - case 64: + return token = 52 /* TildeToken */; + case 64 /* at */: pos++; - return token = 57; - case 92: + return token = 57 /* AtToken */; + case 92 /* backslash */: var cookedChar = peekUnicodeEscape(); if (cookedChar >= 0 && isIdentifierStart(cookedChar, languageVersion)) { pos += 6; @@ -6359,14 +7142,14 @@ var ts; } error(ts.Diagnostics.Invalid_character); pos++; - return token = 0; + return token = 0 /* Unknown */; default: if (isIdentifierStart(ch, languageVersion)) { pos++; while (pos < end && isIdentifierPart(ch = text.charCodeAt(pos), languageVersion)) pos++; tokenValue = text.substring(tokenPos, pos); - if (ch === 92) { + if (ch === 92 /* backslash */) { tokenValue += scanIdentifierParts(); } return token = getIdentifierToken(); @@ -6376,69 +7159,75 @@ var ts; continue; } else if (isLineBreak(ch)) { - tokenFlags |= 1; + tokenFlags |= 1 /* PrecedingLineBreak */; pos++; continue; } error(ts.Diagnostics.Invalid_character); pos++; - return token = 0; + return token = 0 /* Unknown */; } } } function reScanGreaterToken() { - if (token === 29) { - if (text.charCodeAt(pos) === 62) { - if (text.charCodeAt(pos + 1) === 62) { - if (text.charCodeAt(pos + 2) === 61) { - return pos += 3, token = 67; + if (token === 29 /* GreaterThanToken */) { + if (text.charCodeAt(pos) === 62 /* greaterThan */) { + if (text.charCodeAt(pos + 1) === 62 /* greaterThan */) { + if (text.charCodeAt(pos + 2) === 61 /* equals */) { + return pos += 3, token = 67 /* GreaterThanGreaterThanGreaterThanEqualsToken */; } - return pos += 2, token = 47; + return pos += 2, token = 47 /* GreaterThanGreaterThanGreaterThanToken */; } - if (text.charCodeAt(pos + 1) === 61) { - return pos += 2, token = 66; + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + return pos += 2, token = 66 /* GreaterThanGreaterThanEqualsToken */; } pos++; - return token = 46; + return token = 46 /* GreaterThanGreaterThanToken */; } - if (text.charCodeAt(pos) === 61) { + if (text.charCodeAt(pos) === 61 /* equals */) { pos++; - return token = 31; + return token = 31 /* GreaterThanEqualsToken */; } } return token; } function reScanSlashToken() { - if (token === 41 || token === 63) { + if (token === 41 /* SlashToken */ || token === 63 /* SlashEqualsToken */) { var p = tokenPos + 1; var inEscape = false; var inCharacterClass = false; while (true) { + // If we reach the end of a file, or hit a newline, then this is an unterminated + // regex. Report error and return what we have so far. if (p >= end) { - tokenFlags |= 4; + tokenFlags |= 4 /* Unterminated */; error(ts.Diagnostics.Unterminated_regular_expression_literal); break; } var ch = text.charCodeAt(p); if (isLineBreak(ch)) { - tokenFlags |= 4; + tokenFlags |= 4 /* Unterminated */; error(ts.Diagnostics.Unterminated_regular_expression_literal); break; } if (inEscape) { + // Parsing an escape character; + // reset the flag and just advance to the next char. inEscape = false; } - else if (ch === 47 && !inCharacterClass) { + else if (ch === 47 /* slash */ && !inCharacterClass) { + // A slash within a character class is permissible, + // but in general it signals the end of the regexp literal. p++; break; } - else if (ch === 91) { + else if (ch === 91 /* openBracket */) { inCharacterClass = true; } - else if (ch === 92) { + else if (ch === 92 /* backslash */) { inEscape = true; } - else if (ch === 93) { + else if (ch === 93 /* closeBracket */) { inCharacterClass = false; } p++; @@ -6448,12 +7237,15 @@ var ts; } pos = p; tokenValue = text.substring(tokenPos, pos); - token = 12; + token = 12 /* RegularExpressionLiteral */; } return token; } + /** + * Unconditionally back up and scan a template expression portion. + */ function reScanTemplateToken() { - ts.Debug.assert(token === 18, "'reScanTemplateToken' should only be called on a '}'"); + ts.Debug.assert(token === 18 /* CloseBraceToken */, "'reScanTemplateToken' should only be called on a '}'"); pos = tokenPos; return token = scanTemplateAndSetTokenValue(); } @@ -6464,34 +7256,43 @@ var ts; function scanJsxToken() { startPos = tokenPos = pos; if (pos >= end) { - return token = 1; + return token = 1 /* EndOfFileToken */; } var char = text.charCodeAt(pos); - if (char === 60) { - if (text.charCodeAt(pos + 1) === 47) { + if (char === 60 /* lessThan */) { + if (text.charCodeAt(pos + 1) === 47 /* slash */) { pos += 2; - return token = 28; + return token = 28 /* LessThanSlashToken */; } pos++; - return token = 27; + return token = 27 /* LessThanToken */; } - if (char === 123) { + if (char === 123 /* openBrace */) { pos++; - return token = 17; + return token = 17 /* OpenBraceToken */; } + // First non-whitespace character on this line. var firstNonWhitespace = 0; + // These initial values are special because the first line is: + // firstNonWhitespace = 0 to indicate that we want leading whitspace, while (pos < end) { char = text.charCodeAt(pos); - if (char === 123) { + if (char === 123 /* openBrace */) { break; } - if (char === 60) { + if (char === 60 /* lessThan */) { if (isConflictMarkerTrivia(text, pos)) { pos = scanConflictMarkerTrivia(text, pos, error); - return token = 7; + return token = 7 /* ConflictMarkerTrivia */; } break; } + // FirstNonWhitespace is 0, then we only see whitespaces so far. If we see a linebreak, we want to ignore that whitespaces. + // i.e (- : whitespace) + //
---- + //
becomes
+ // + //
----
becomes
----
if (isLineBreak(char) && firstNonWhitespace === 0) { firstNonWhitespace = -1; } @@ -6500,14 +7301,16 @@ var ts; } pos++; } - return firstNonWhitespace === -1 ? 11 : 10; + return firstNonWhitespace === -1 ? 11 /* JsxTextAllWhiteSpaces */ : 10 /* JsxText */; } + // Scans a JSX identifier; these differ from normal identifiers in that + // they allow dashes function scanJsxIdentifier() { if (tokenIsIdentifierOrKeyword(token)) { var firstCharPosition = pos; while (pos < end) { var ch = text.charCodeAt(pos); - if (ch === 45 || ((firstCharPosition === pos) ? isIdentifierStart(ch, languageVersion) : isIdentifierPart(ch, languageVersion))) { + if (ch === 45 /* minus */ || ((firstCharPosition === pos) ? isIdentifierStart(ch, languageVersion) : isIdentifierPart(ch, languageVersion))) { pos++; } else { @@ -6521,70 +7324,71 @@ var ts; function scanJsxAttributeValue() { startPos = pos; switch (text.charCodeAt(pos)) { - case 34: - case 39: - tokenValue = scanString(true); - return token = 9; + case 34 /* doubleQuote */: + case 39 /* singleQuote */: + tokenValue = scanString(/*jsxAttributeString*/ true); + return token = 9 /* StringLiteral */; default: + // If this scans anything other than `{`, it's a parse error. return scan(); } } function scanJSDocToken() { startPos = tokenPos = pos; if (pos >= end) { - return token = 1; + return token = 1 /* EndOfFileToken */; } var ch = text.charCodeAt(pos); pos++; switch (ch) { - case 9: - case 11: - case 12: - case 32: + case 9 /* tab */: + case 11 /* verticalTab */: + case 12 /* formFeed */: + case 32 /* space */: while (pos < end && isWhiteSpaceSingleLine(text.charCodeAt(pos))) { pos++; } - return token = 5; - case 64: - return token = 57; - case 10: - case 13: - return token = 4; - case 42: - return token = 39; - case 123: - return token = 17; - case 125: - return token = 18; - case 91: - return token = 21; - case 93: - return token = 22; - case 60: - return token = 27; - case 61: - return token = 58; - case 44: - return token = 26; - case 46: - return token = 23; - case 96: - while (pos < end && text.charCodeAt(pos) !== 96) { + return token = 5 /* WhitespaceTrivia */; + case 64 /* at */: + return token = 57 /* AtToken */; + case 10 /* lineFeed */: + case 13 /* carriageReturn */: + return token = 4 /* NewLineTrivia */; + case 42 /* asterisk */: + return token = 39 /* AsteriskToken */; + case 123 /* openBrace */: + return token = 17 /* OpenBraceToken */; + case 125 /* closeBrace */: + return token = 18 /* CloseBraceToken */; + case 91 /* openBracket */: + return token = 21 /* OpenBracketToken */; + case 93 /* closeBracket */: + return token = 22 /* CloseBracketToken */; + case 60 /* lessThan */: + return token = 27 /* LessThanToken */; + case 61 /* equals */: + return token = 58 /* EqualsToken */; + case 44 /* comma */: + return token = 26 /* CommaToken */; + case 46 /* dot */: + return token = 23 /* DotToken */; + case 96 /* backtick */: + while (pos < end && text.charCodeAt(pos) !== 96 /* backtick */) { pos++; } tokenValue = text.substring(tokenPos + 1, pos); pos++; - return token = 13; + return token = 13 /* NoSubstitutionTemplateLiteral */; } - if (isIdentifierStart(ch, 6)) { - while (isIdentifierPart(text.charCodeAt(pos), 6) && pos < end) { + if (isIdentifierStart(ch, 6 /* Latest */)) { + while (isIdentifierPart(text.charCodeAt(pos), 6 /* Latest */) && pos < end) { pos++; } tokenValue = text.substring(tokenPos, pos); - return token = 71; + return token = 71 /* Identifier */; } else { - return token = 0; + return token = 0 /* Unknown */; } } function speculationHelper(callback, isLookahead) { @@ -6595,6 +7399,8 @@ var ts; var saveTokenValue = tokenValue; var saveTokenFlags = tokenFlags; var result = callback(); + // If our callback returned something 'falsy' or we're just looking ahead, + // then unconditionally restore us to where we were. if (!result || isLookahead) { pos = savePos; startPos = saveStartPos; @@ -6625,10 +7431,10 @@ var ts; return result; } function lookAhead(callback) { - return speculationHelper(callback, true); + return speculationHelper(callback, /*isLookahead*/ true); } function tryScan(callback) { - return speculationHelper(callback, false); + return speculationHelper(callback, /*isLookahead*/ false); } function getText() { return text; @@ -6652,16 +7458,20 @@ var ts; pos = textPos; startPos = textPos; tokenPos = textPos; - token = 0; + token = 0 /* Unknown */; tokenValue = undefined; tokenFlags = 0; } } ts.createScanner = createScanner; })(ts || (ts = {})); +/** Non-internal stuff goes here */ var ts; (function (ts) { function isExternalModuleNameRelative(moduleName) { + // TypeScript 1.0 spec (April 2014): 11.2.1 + // An external module name is "relative" if the first term is "." or "..". + // Update: We also consider a path like `C:\foo.ts` "relative" because we do not search for it in `node_modules` or treat it as an ambient module. return ts.pathIsRelative(moduleName) || ts.isRootedDiskPath(moduleName); } ts.isExternalModuleNameRelative = isExternalModuleNameRelative; @@ -6670,6 +7480,7 @@ var ts; } ts.sortAndDeduplicateDiagnostics = sortAndDeduplicateDiagnostics; })(ts || (ts = {})); +/* @internal */ (function (ts) { ts.emptyArray = []; ts.resolvingEmptyArray = []; @@ -6689,6 +7500,7 @@ var ts; return undefined; } ts.getDeclarationOfKind = getDeclarationOfKind; + /** Create a new escaped identifier map. */ function createUnderscoreEscapedMap() { return new ts.MapCtr(); } @@ -6731,6 +7543,8 @@ var ts; getColumn: function () { return 0; }, getIndent: function () { return 0; }, isAtStartOfLine: function () { return false; }, + // Completely ignore indentation for string writers. And map newlines to + // a single space. writeLine: function () { return str += " "; }, increaseIndent: ts.noop, decreaseIndent: ts.noop, @@ -6892,23 +7706,31 @@ var ts; return false; } ts.hasChangesInResolutions = hasChangesInResolutions; + // Returns true if this node contains a parse error anywhere underneath it. function containsParseError(node) { aggregateChildData(node); - return (node.flags & 131072) !== 0; + return (node.flags & 131072 /* ThisNodeOrAnySubNodesHasError */) !== 0; } ts.containsParseError = containsParseError; function aggregateChildData(node) { - if (!(node.flags & 262144)) { - var thisNodeOrAnySubNodesHasError = ((node.flags & 32768) !== 0) || + if (!(node.flags & 262144 /* HasAggregatedChildData */)) { + // A node is considered to contain a parse error if: + // a) the parser explicitly marked that it had an error + // b) any of it's children reported that it had an error. + var thisNodeOrAnySubNodesHasError = ((node.flags & 32768 /* ThisNodeHasError */) !== 0) || ts.forEachChild(node, containsParseError); + // If so, mark ourselves accordingly. if (thisNodeOrAnySubNodesHasError) { - node.flags |= 131072; + node.flags |= 131072 /* ThisNodeOrAnySubNodesHasError */; } - node.flags |= 262144; + // Also mark that we've propagated the child information to this node. This way we can + // always consult the bit directly on this node without needing to check its children + // again. + node.flags |= 262144 /* HasAggregatedChildData */; } } function getSourceFileOfNode(node) { - while (node && node.kind !== 274) { + while (node && node.kind !== 274 /* SourceFile */) { node = node.parent; } return node; @@ -6916,11 +7738,11 @@ var ts; ts.getSourceFileOfNode = getSourceFileOfNode; function isStatementWithLocals(node) { switch (node.kind) { - case 213: - case 241: - case 220: - case 221: - case 222: + case 213 /* Block */: + case 241 /* CaseBlock */: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: return true; } return false; @@ -6931,6 +7753,7 @@ var ts; return ts.getLineStarts(sourceFile)[line]; } ts.getStartPositionOfLine = getStartPositionOfLine; + // This is a useful function for debugging purposes. function nodePosToString(node) { var file = getSourceFileOfNode(node); var loc = ts.getLineAndCharacterOfPosition(file, node.pos); @@ -6943,12 +7766,19 @@ var ts; var lineIndex = line; var sourceText = sourceFile.text; if (lineIndex + 1 === lineStarts.length) { + // last line - return EOF return sourceText.length - 1; } else { + // current line start var start = lineStarts[lineIndex]; + // take the start position of the next line - 1 = it should be some line break var pos = lineStarts[lineIndex + 1] - 1; ts.Debug.assert(ts.isLineBreak(sourceText.charCodeAt(pos))); + // walk backwards skipping line breaks, stop the the beginning of current line. + // i.e: + // + // $ <- end of line for this position should match the start position while (start <= pos && ts.isLineBreak(sourceText.charCodeAt(pos))) { pos--; } @@ -6956,21 +7786,45 @@ var ts; } } ts.getEndLinePosition = getEndLinePosition; + /** + * Returns a value indicating whether a name is unique globally or within the current file. + * Note: This does not consider whether a name appears as a free identifier or not, so at the expression `x.y` this includes both `x` and `y`. + */ function isFileLevelUniqueName(sourceFile, name, hasGlobalName) { return !(hasGlobalName && hasGlobalName(name)) && !sourceFile.identifiers.has(name); } ts.isFileLevelUniqueName = isFileLevelUniqueName; + // Returns true if this node is missing from the actual source code. A 'missing' node is different + // from 'undefined/defined'. When a node is undefined (which can happen for optional nodes + // in the tree), it is definitely missing. However, a node may be defined, but still be + // missing. This happens whenever the parser knows it needs to parse something, but can't + // get anything in the source code that it expects at that location. For example: + // + // let a: ; + // + // Here, the Type in the Type-Annotation is not-optional (as there is a colon in the source + // code). So the parser will attempt to parse out a type, and will create an actual node. + // However, this node will be 'missing' in the sense that no actual source-code/tokens are + // contained within it. function nodeIsMissing(node) { if (node === undefined) { return true; } - return node.pos === node.end && node.pos >= 0 && node.kind !== 1; + return node.pos === node.end && node.pos >= 0 && node.kind !== 1 /* EndOfFileToken */; } ts.nodeIsMissing = nodeIsMissing; function nodeIsPresent(node) { return !nodeIsMissing(node); } ts.nodeIsPresent = nodeIsPresent; + /** + * Appends a range of value to begin of an array, returning the array. + * + * @param to The array to which `value` is to be appended. If `to` is `undefined`, a new array + * is created if `value` was appended. + * @param from The values to append to the array. If `from` is `undefined`, nothing is + * appended. If an element of `from` is `undefined`, that element is not appended. + */ function prependStatements(to, from) { if (from === undefined || from.length === 0) return to; @@ -6984,10 +7838,17 @@ var ts; return to; } ts.prependStatements = prependStatements; + /** + * Determine if the given comment is a triple-slash + * + * @return true if the comment is a triple-slash comment else false + */ function isRecognizedTripleSlashComment(text, commentPos, commentEnd) { - if (text.charCodeAt(commentPos + 1) === 47 && + // Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text + // so that we don't end up computing comment string and doing match for all // comments + if (text.charCodeAt(commentPos + 1) === 47 /* slash */ && commentPos + 2 < commentEnd && - text.charCodeAt(commentPos + 2) === 47) { + text.charCodeAt(commentPos + 2) === 47 /* slash */) { var textSubStr = text.substring(commentPos, commentEnd); return textSubStr.match(ts.fullTripleSlashReferencePathRegEx) || textSubStr.match(ts.fullTripleSlashAMDReferencePathRegEx) || @@ -6999,21 +7860,27 @@ var ts; } ts.isRecognizedTripleSlashComment = isRecognizedTripleSlashComment; function isPinnedComment(text, start) { - return text.charCodeAt(start + 1) === 42 && - text.charCodeAt(start + 2) === 33; + return text.charCodeAt(start + 1) === 42 /* asterisk */ && + text.charCodeAt(start + 2) === 33 /* exclamation */; } ts.isPinnedComment = isPinnedComment; function getTokenPosOfNode(node, sourceFile, includeJsDoc) { + // With nodes that have no width (i.e. 'Missing' nodes), we actually *don't* + // want to skip trivia because this will launch us forward to the next token. if (nodeIsMissing(node)) { return node.pos; } if (ts.isJSDocNode(node)) { - return ts.skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos, false, true); + return ts.skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); } if (includeJsDoc && ts.hasJSDocNodes(node)) { return getTokenPosOfNode(node.jsDoc[0]); } - if (node.kind === 300 && node._children.length > 0) { + // For a syntax list, it is possible that one of its children has JSDocComment nodes, while + // the syntax list itself considers them as normal trivia. Therefore if we simply skip + // trivia for the list, we may have skipped the JSDocComment as well. So we should process its + // first child to determine the actual position of its first token. + if (node.kind === 300 /* SyntaxList */ && node._children.length > 0) { return getTokenPosOfNode(node._children[0], sourceFile, includeJsDoc); } return ts.skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos); @@ -7047,38 +7914,51 @@ var ts; function getPos(range) { return range.pos; } + /** + * Note: it is expected that the `nodeArray` and the `node` are within the same file. + * For example, searching for a `SourceFile` in a `SourceFile[]` wouldn't work. + */ function indexOfNode(nodeArray, node) { return ts.binarySearch(nodeArray, node, getPos, ts.compareValues); } ts.indexOfNode = indexOfNode; + /** + * Gets flags that control emit behavior of a node. + */ function getEmitFlags(node) { var emitNode = node.emitNode; return emitNode && emitNode.flags || 0; } ts.getEmitFlags = getEmitFlags; function getLiteralText(node, sourceFile) { - if (!nodeIsSynthesized(node) && node.parent && !(ts.isNumericLiteral(node) && node.numericLiteralFlags & 512)) { + // 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 && !(ts.isNumericLiteral(node) && node.numericLiteralFlags & 512 /* ContainsSeparator */)) { return getSourceTextOfNodeFromSourceFile(sourceFile, node); } - var escapeText = getEmitFlags(node) & 16777216 ? escapeString : escapeNonAsciiString; + var escapeText = getEmitFlags(node) & 16777216 /* NoAsciiEscaping */ ? escapeString : escapeNonAsciiString; + // If we can't reach the original source text, use the canonical form if it's a number, + // or a (possibly escaped) quoted form of the original text if it's string-like. switch (node.kind) { - case 9: + case 9 /* StringLiteral */: if (node.singleQuote) { - return "'" + escapeText(node.text, 39) + "'"; + return "'" + escapeText(node.text, 39 /* singleQuote */) + "'"; } else { - return '"' + escapeText(node.text, 34) + '"'; + return '"' + escapeText(node.text, 34 /* doubleQuote */) + '"'; } - case 13: - return "`" + escapeText(node.text, 96) + "`"; - case 14: - return "`" + escapeText(node.text, 96) + "${"; - case 15: - return "}" + escapeText(node.text, 96) + "${"; - case 16: - return "}" + escapeText(node.text, 96) + "`"; - case 8: - case 12: + case 13 /* NoSubstitutionTemplateLiteral */: + return "`" + escapeText(node.text, 96 /* backtick */) + "`"; + case 14 /* TemplateHead */: + // tslint:disable-next-line no-invalid-template-strings + return "`" + escapeText(node.text, 96 /* backtick */) + "${"; + case 15 /* TemplateMiddle */: + // tslint:disable-next-line no-invalid-template-strings + return "}" + escapeText(node.text, 96 /* backtick */) + "${"; + case 16 /* TemplateTail */: + return "}" + escapeText(node.text, 96 /* backtick */) + "`"; + case 8 /* NumericLiteral */: + case 12 /* RegularExpressionLiteral */: return node.text; } return ts.Debug.fail("Literal kind '" + node.kind + "' not accounted for."); @@ -7088,59 +7968,74 @@ var ts; return ts.isString(value) ? '"' + escapeNonAsciiString(value) + '"' : "" + value; } ts.getTextOfConstantValue = getTextOfConstantValue; + // Add an extra underscore to identifiers that start with two underscores to avoid issues with magic names like '__proto__' function escapeLeadingUnderscores(identifier) { - return (identifier.length >= 2 && identifier.charCodeAt(0) === 95 && identifier.charCodeAt(1) === 95 ? "_" + identifier : identifier); + return (identifier.length >= 2 && identifier.charCodeAt(0) === 95 /* _ */ && identifier.charCodeAt(1) === 95 /* _ */ ? "_" + identifier : identifier); } ts.escapeLeadingUnderscores = escapeLeadingUnderscores; + /** + * @deprecated Use `id.escapedText` to get the escaped text of an Identifier. + * @param identifier The identifier to escape + */ function escapeIdentifier(identifier) { return identifier; } ts.escapeIdentifier = escapeIdentifier; + // Make an identifier from an external module name by extracting the string after the last "/" and replacing + // all non-alphanumeric characters with underscores function makeIdentifierFromModuleName(moduleName) { return ts.getBaseFileName(moduleName).replace(/^(\d)/, "_$1").replace(/\W/g, "_"); } ts.makeIdentifierFromModuleName = makeIdentifierFromModuleName; function isBlockOrCatchScoped(declaration) { - return (ts.getCombinedNodeFlags(declaration) & 3) !== 0 || + return (ts.getCombinedNodeFlags(declaration) & 3 /* BlockScoped */) !== 0 || isCatchClauseVariableDeclarationOrBindingElement(declaration); } ts.isBlockOrCatchScoped = isBlockOrCatchScoped; function isCatchClauseVariableDeclarationOrBindingElement(declaration) { var node = getRootDeclaration(declaration); - return node.kind === 232 && node.parent.kind === 269; + return node.kind === 232 /* VariableDeclaration */ && node.parent.kind === 269 /* CatchClause */; } ts.isCatchClauseVariableDeclarationOrBindingElement = isCatchClauseVariableDeclarationOrBindingElement; function isAmbientModule(node) { - return ts.isModuleDeclaration(node) && (node.name.kind === 9 || isGlobalScopeAugmentation(node)); + return ts.isModuleDeclaration(node) && (node.name.kind === 9 /* StringLiteral */ || isGlobalScopeAugmentation(node)); } ts.isAmbientModule = isAmbientModule; function isModuleWithStringLiteralName(node) { - return ts.isModuleDeclaration(node) && node.name.kind === 9; + return ts.isModuleDeclaration(node) && node.name.kind === 9 /* StringLiteral */; } ts.isModuleWithStringLiteralName = isModuleWithStringLiteralName; function isNonGlobalAmbientModule(node) { return ts.isModuleDeclaration(node) && ts.isStringLiteral(node.name); } ts.isNonGlobalAmbientModule = isNonGlobalAmbientModule; + /** + * An effective module (namespace) declaration is either + * 1. An actual declaration: namespace X { ... } + * 2. A Javascript declaration, which is: + * An identifier in a nested property access expression: Y in `X.Y.Z = { ... }` + */ function isEffectiveModuleDeclaration(node) { return ts.isModuleDeclaration(node) || ts.isIdentifier(node); } ts.isEffectiveModuleDeclaration = isEffectiveModuleDeclaration; + /** Given a symbol for a module, checks that it is a shorthand ambient module. */ function isShorthandAmbientModuleSymbol(moduleSymbol) { return isShorthandAmbientModule(moduleSymbol.valueDeclaration); } ts.isShorthandAmbientModuleSymbol = isShorthandAmbientModuleSymbol; function isShorthandAmbientModule(node) { - return node && node.kind === 239 && (!node.body); + // The only kind of module that can be missing a body is a shorthand ambient module. + return node && node.kind === 239 /* ModuleDeclaration */ && (!node.body); } function isBlockScopedContainerTopLevel(node) { - return node.kind === 274 || - node.kind === 239 || + return node.kind === 274 /* SourceFile */ || + node.kind === 239 /* ModuleDeclaration */ || ts.isFunctionLike(node); } ts.isBlockScopedContainerTopLevel = isBlockScopedContainerTopLevel; function isGlobalScopeAugmentation(module) { - return !!(module.flags & 512); + return !!(module.flags & 512 /* GlobalAugmentation */); } ts.isGlobalScopeAugmentation = isGlobalScopeAugmentation; function isExternalModuleAugmentation(node) { @@ -7148,10 +8043,13 @@ var ts; } ts.isExternalModuleAugmentation = isExternalModuleAugmentation; function isModuleAugmentationExternal(node) { + // external module augmentation is a ambient module declaration that is either: + // - defined in the top level scope and source file is an external module + // - defined inside ambient module declaration located in the top level scope and source file not an external module switch (node.parent.kind) { - case 274: + case 274 /* SourceFile */: return ts.isExternalModule(node.parent); - case 240: + case 240 /* ModuleBlock */: return isAmbientModule(node.parent.parent) && ts.isSourceFile(node.parent.parent.parent) && !ts.isExternalModule(node.parent.parent.parent); } return false; @@ -7163,22 +8061,24 @@ var ts; ts.isEffectiveExternalModule = isEffectiveExternalModule; function isBlockScope(node, parentNode) { switch (node.kind) { - case 274: - case 241: - case 269: - case 239: - case 220: - case 221: - case 222: - case 155: - case 154: - case 156: - case 157: - case 234: - case 192: - case 193: + case 274 /* SourceFile */: + case 241 /* CaseBlock */: + case 269 /* CatchClause */: + case 239 /* ModuleDeclaration */: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 155 /* Constructor */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: return true; - case 213: + case 213 /* Block */: + // function block is not considered block-scope container + // see comment in binder.ts: bind(...), case for SyntaxKind.Block return !ts.isFunctionLike(parentNode); } return false; @@ -7186,28 +8086,28 @@ var ts; ts.isBlockScope = isBlockScope; function isDeclarationWithTypeParameters(node) { switch (node.kind) { - case 158: - case 159: - case 153: - case 160: - case 163: - case 164: - case 284: - case 235: - case 205: - case 236: - case 237: - case 297: - case 234: - case 154: - case 155: - case 156: - case 157: - case 192: - case 193: - case 292: - case 298: - case 288: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 153 /* MethodSignature */: + case 160 /* IndexSignature */: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 284 /* JSDocFunctionType */: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 297 /* JSDocTemplateTag */: + case 234 /* FunctionDeclaration */: + case 154 /* MethodDeclaration */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 292 /* JSDocCallbackTag */: + case 298 /* JSDocTypedefTag */: + case 288 /* JSDocSignature */: return true; default: ts.assertTypeIsNever(node); @@ -7217,8 +8117,8 @@ var ts; ts.isDeclarationWithTypeParameters = isDeclarationWithTypeParameters; function isAnyImportSyntax(node) { switch (node.kind) { - case 244: - case 243: + case 244 /* ImportDeclaration */: + case 243 /* ImportEqualsDeclaration */: return true; default: return false; @@ -7227,15 +8127,15 @@ var ts; ts.isAnyImportSyntax = isAnyImportSyntax; function isLateVisibilityPaintedStatement(node) { switch (node.kind) { - case 244: - case 243: - case 214: - case 235: - case 234: - case 239: - case 237: - case 236: - case 238: + case 244 /* ImportDeclaration */: + case 243 /* ImportEqualsDeclaration */: + case 214 /* VariableStatement */: + case 235 /* ClassDeclaration */: + case 234 /* FunctionDeclaration */: + case 239 /* ModuleDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 236 /* InterfaceDeclaration */: + case 238 /* EnumDeclaration */: return true; default: return false; @@ -7246,10 +8146,15 @@ var ts; return isAnyImportSyntax(node) || ts.isExportDeclaration(node); } ts.isAnyImportOrReExport = isAnyImportOrReExport; + // Gets the nearest enclosing block scope container that has the provided node + // as a descendant, that is not the provided node. function getEnclosingBlockScopeContainer(node) { return findAncestor(node.parent, function (current) { return isBlockScope(current, current.parent); }); } ts.getEnclosingBlockScopeContainer = getEnclosingBlockScopeContainer; + // Return display name of an identifier + // Computed property names will just be emitted as "[]", where is the source + // text of the expression in the computed property. function declarationNameToString(name) { return getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name); } @@ -7260,13 +8165,13 @@ var ts; ts.getNameFromIndexInfo = getNameFromIndexInfo; function getTextOfPropertyName(name) { switch (name.kind) { - case 71: + case 71 /* Identifier */: return name.escapedText; - case 9: - case 8: + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: return escapeLeadingUnderscores(name.text); - case 147: - return isStringOrNumericLiteral(name.expression) ? escapeLeadingUnderscores(name.expression.text) : undefined; + case 147 /* ComputedPropertyName */: + return isStringOrNumericLiteral(name.expression) ? escapeLeadingUnderscores(name.expression.text) : undefined; // TODO: GH#18217 Almost all uses of this assume the result to be defined! default: ts.Debug.assertNever(name); } @@ -7274,11 +8179,11 @@ var ts; ts.getTextOfPropertyName = getTextOfPropertyName; function entityNameToString(name) { switch (name.kind) { - case 71: + case 71 /* Identifier */: return getFullWidth(name) === 0 ? ts.idText(name) : getTextOfNode(name); - case 146: + case 146 /* QualifiedName */: return entityNameToString(name.left) + "." + entityNameToString(name.right); - case 185: + case 185 /* PropertyAccessExpression */: return entityNameToString(name.expression) + "." + entityNameToString(name.name); default: throw ts.Debug.assertNever(name); @@ -7315,7 +8220,7 @@ var ts; } ts.createDiagnosticForNodeFromMessageChain = createDiagnosticForNodeFromMessageChain; function getSpanOfTokenAtPosition(sourceFile, pos) { - var scanner = ts.createScanner(sourceFile.languageVersion, true, sourceFile.languageVariant, sourceFile.text, undefined, pos); + var scanner = ts.createScanner(sourceFile.languageVersion, /*skipTrivia*/ true, sourceFile.languageVariant, sourceFile.text, /*onError:*/ undefined, pos); scanner.scan(); var start = scanner.getTokenPos(); return ts.createTextSpanFromBounds(start, scanner.getTextPos()); @@ -7323,10 +8228,12 @@ var ts; ts.getSpanOfTokenAtPosition = getSpanOfTokenAtPosition; function getErrorSpanForArrowFunction(sourceFile, node) { var pos = ts.skipTrivia(sourceFile.text, node.pos); - if (node.body && node.body.kind === 213) { + if (node.body && node.body.kind === 213 /* Block */) { var startLine = ts.getLineAndCharacterOfPosition(sourceFile, node.body.pos).line; var endLine = ts.getLineAndCharacterOfPosition(sourceFile, node.body.end).line; if (startLine < endLine) { + // The arrow function spans multiple lines, + // make the error span be the first line, inclusive. return ts.createTextSpan(pos, getEndLinePosition(startLine, sourceFile) - pos + 1); } } @@ -7335,40 +8242,46 @@ var ts; function getErrorSpanForNode(sourceFile, node) { var errorNode = node; switch (node.kind) { - case 274: - var pos_1 = ts.skipTrivia(sourceFile.text, 0, false); + case 274 /* SourceFile */: + var pos_1 = ts.skipTrivia(sourceFile.text, 0, /*stopAfterLineBreak*/ false); if (pos_1 === sourceFile.text.length) { + // file is empty - return span for the beginning of the file return ts.createTextSpan(0, 0); } return getSpanOfTokenAtPosition(sourceFile, pos_1); - case 232: - case 182: - case 235: - case 205: - case 236: - case 239: - case 238: - case 273: - case 234: - case 192: - case 154: - case 156: - case 157: - case 237: - case 152: - case 151: + // This list is a work in progress. Add missing node kinds to improve their error + // spans. + case 232 /* VariableDeclaration */: + case 182 /* BindingElement */: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 236 /* InterfaceDeclaration */: + case 239 /* ModuleDeclaration */: + case 238 /* EnumDeclaration */: + case 273 /* EnumMember */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 237 /* TypeAliasDeclaration */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: errorNode = node.name; break; - case 193: + case 193 /* ArrowFunction */: return getErrorSpanForArrowFunction(sourceFile, node); } if (errorNode === undefined) { + // If we don't have a better node, then just set the error on the first token of + // construct. return getSpanOfTokenAtPosition(sourceFile, node.pos); } var isMissing = nodeIsMissing(errorNode); var pos = isMissing ? errorNode.pos : ts.skipTrivia(sourceFile.text, errorNode.pos); + // These asserts should all be satisfied for a properly constructed `errorNode`. if (isMissing) { ts.Debug.assert(pos === errorNode.pos, "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809"); ts.Debug.assert(pos === errorNode.end, "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809"); @@ -7385,57 +8298,58 @@ var ts; } ts.isExternalOrCommonJsModule = isExternalOrCommonJsModule; function isJsonSourceFile(file) { - return file.scriptKind === 6; + return file.scriptKind === 6 /* JSON */; } ts.isJsonSourceFile = isJsonSourceFile; function isConstEnumDeclaration(node) { - return node.kind === 238 && isConst(node); + return node.kind === 238 /* EnumDeclaration */ && isConst(node); } ts.isConstEnumDeclaration = isConstEnumDeclaration; function isConst(node) { - return !!(ts.getCombinedNodeFlags(node) & 2) - || !!(ts.getCombinedModifierFlags(node) & 2048); + return !!(ts.getCombinedNodeFlags(node) & 2 /* Const */) + || !!(ts.getCombinedModifierFlags(node) & 2048 /* Const */); } ts.isConst = isConst; function isLet(node) { - return !!(ts.getCombinedNodeFlags(node) & 1); + return !!(ts.getCombinedNodeFlags(node) & 1 /* Let */); } ts.isLet = isLet; function isSuperCall(n) { - return n.kind === 187 && n.expression.kind === 97; + return n.kind === 187 /* CallExpression */ && n.expression.kind === 97 /* SuperKeyword */; } ts.isSuperCall = isSuperCall; function isImportCall(n) { - return n.kind === 187 && n.expression.kind === 91; + return n.kind === 187 /* CallExpression */ && n.expression.kind === 91 /* ImportKeyword */; } ts.isImportCall = isImportCall; function isLiteralImportTypeNode(n) { - return n.kind === 179 && - n.argument.kind === 178 && + return n.kind === 179 /* ImportType */ && + n.argument.kind === 178 /* LiteralType */ && ts.isStringLiteral(n.argument.literal); } ts.isLiteralImportTypeNode = isLiteralImportTypeNode; function isPrologueDirective(node) { - return node.kind === 216 - && node.expression.kind === 9; + return node.kind === 216 /* ExpressionStatement */ + && node.expression.kind === 9 /* StringLiteral */; } ts.isPrologueDirective = isPrologueDirective; function getLeadingCommentRangesOfNode(node, sourceFileOfNode) { - return node.kind !== 10 ? ts.getLeadingCommentRanges(sourceFileOfNode.text, node.pos) : undefined; + return node.kind !== 10 /* JsxText */ ? ts.getLeadingCommentRanges(sourceFileOfNode.text, node.pos) : undefined; } ts.getLeadingCommentRangesOfNode = getLeadingCommentRangesOfNode; function getJSDocCommentRanges(node, text) { - var commentRanges = (node.kind === 149 || - node.kind === 148 || - node.kind === 192 || - node.kind === 193 || - node.kind === 191) ? + var commentRanges = (node.kind === 149 /* Parameter */ || + node.kind === 148 /* TypeParameter */ || + node.kind === 192 /* FunctionExpression */ || + node.kind === 193 /* ArrowFunction */ || + node.kind === 191 /* ParenthesizedExpression */) ? ts.concatenate(ts.getTrailingCommentRanges(text, node.pos), ts.getLeadingCommentRanges(text, node.pos)) : ts.getLeadingCommentRanges(text, node.pos); + // True if the comment starts with '/**' but not if it is '/**/' return ts.filter(commentRanges, function (comment) { - return text.charCodeAt(comment.pos + 1) === 42 && - text.charCodeAt(comment.pos + 2) === 42 && - text.charCodeAt(comment.pos + 3) !== 47; + return text.charCodeAt(comment.pos + 1) === 42 /* asterisk */ && + text.charCodeAt(comment.pos + 2) === 42 /* asterisk */ && + text.charCodeAt(comment.pos + 3) !== 47 /* slash */; }); } ts.getJSDocCommentRanges = getJSDocCommentRanges; @@ -7444,75 +8358,87 @@ var ts; ts.fullTripleSlashAMDReferencePathRegEx = /^(\/\/\/\s*/; var defaultLibReferenceRegEx = /^(\/\/\/\s*/; function isPartOfTypeNode(node) { - if (161 <= node.kind && node.kind <= 179) { + if (161 /* FirstTypeNode */ <= node.kind && node.kind <= 179 /* LastTypeNode */) { return true; } switch (node.kind) { - case 119: - case 142: - case 134: - case 137: - case 122: - case 138: - case 140: - case 131: + case 119 /* AnyKeyword */: + case 142 /* UnknownKeyword */: + case 134 /* NumberKeyword */: + case 137 /* StringKeyword */: + case 122 /* BooleanKeyword */: + case 138 /* SymbolKeyword */: + case 140 /* UndefinedKeyword */: + case 131 /* NeverKeyword */: return true; - case 105: - return node.parent.kind !== 196; - case 207: + case 105 /* VoidKeyword */: + return node.parent.kind !== 196 /* VoidExpression */; + case 207 /* ExpressionWithTypeArguments */: return !isExpressionWithTypeArgumentsInClassExtendsClause(node); - case 148: - return node.parent.kind === 177 || node.parent.kind === 172; - case 71: - if (node.parent.kind === 146 && node.parent.right === node) { + case 148 /* TypeParameter */: + return node.parent.kind === 177 /* MappedType */ || node.parent.kind === 172 /* InferType */; + // Identifiers and qualified names may be type nodes, depending on their context. Climb + // above them to find the lowest container + case 71 /* Identifier */: + // If the identifier is the RHS of a qualified name, then it's a type iff its parent is. + if (node.parent.kind === 146 /* QualifiedName */ && node.parent.right === node) { node = node.parent; } - else if (node.parent.kind === 185 && node.parent.name === node) { + else if (node.parent.kind === 185 /* PropertyAccessExpression */ && node.parent.name === node) { node = node.parent; } - ts.Debug.assert(node.kind === 71 || node.kind === 146 || node.kind === 185, "'node' was expected to be a qualified name, identifier or property access in 'isPartOfTypeNode'."); - case 146: - case 185: - case 99: { + // At this point, node is either a qualified name or an identifier + ts.Debug.assert(node.kind === 71 /* Identifier */ || node.kind === 146 /* QualifiedName */ || node.kind === 185 /* PropertyAccessExpression */, "'node' was expected to be a qualified name, identifier or property access in 'isPartOfTypeNode'."); + // falls through + case 146 /* QualifiedName */: + case 185 /* PropertyAccessExpression */: + case 99 /* ThisKeyword */: { var parent = node.parent; - if (parent.kind === 165) { + if (parent.kind === 165 /* TypeQuery */) { return false; } - if (parent.kind === 179) { + if (parent.kind === 179 /* ImportType */) { return !parent.isTypeOf; } - if (161 <= parent.kind && parent.kind <= 179) { + // Do not recursively call isPartOfTypeNode on the parent. In the example: + // + // let a: A.B.C; + // + // Calling isPartOfTypeNode would consider the qualified name A.B a type node. + // Only C and A.B.C are type nodes. + if (161 /* FirstTypeNode */ <= parent.kind && parent.kind <= 179 /* LastTypeNode */) { return true; } switch (parent.kind) { - case 207: + case 207 /* ExpressionWithTypeArguments */: return !isExpressionWithTypeArgumentsInClassExtendsClause(parent); - case 148: + case 148 /* TypeParameter */: return node === parent.constraint; - case 152: - case 151: - case 149: - case 232: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 149 /* Parameter */: + case 232 /* VariableDeclaration */: return node === parent.type; - case 234: - case 192: - case 193: - case 155: - case 154: - case 153: - case 156: - case 157: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 155 /* Constructor */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return node === parent.type; - case 158: - case 159: - case 160: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 160 /* IndexSignature */: return node === parent.type; - case 190: + case 190 /* TypeAssertionExpression */: return node === parent.type; - case 187: - case 188: + case 187 /* CallExpression */: + case 188 /* NewExpression */: return ts.contains(parent.typeArguments, node); - case 189: + case 189 /* TaggedTemplateExpression */: + // TODO (drosen): TaggedTemplateExpressions may eventually support type arguments. return false; } } @@ -7530,27 +8456,29 @@ var ts; return false; } ts.isChildOfNodeWithKind = isChildOfNodeWithKind; + // Warning: This has the same semantics as the forEach family of functions, + // in that traversal terminates in the event that 'visitor' supplies a truthy value. function forEachReturnStatement(body, visitor) { return traverse(body); function traverse(node) { switch (node.kind) { - case 225: + case 225 /* ReturnStatement */: return visitor(node); - case 241: - case 213: - case 217: - case 218: - case 219: - case 220: - case 221: - case 222: - case 226: - case 227: - case 266: - case 267: - case 228: - case 230: - case 269: + case 241 /* CaseBlock */: + case 213 /* Block */: + case 217 /* IfStatement */: + case 218 /* DoStatement */: + case 219 /* WhileStatement */: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 226 /* WithStatement */: + case 227 /* SwitchStatement */: + case 266 /* CaseClause */: + case 267 /* DefaultClause */: + case 228 /* LabeledStatement */: + case 230 /* TryStatement */: + case 269 /* CatchClause */: return ts.forEachChild(node, traverse); } } @@ -7560,39 +8488,52 @@ var ts; return traverse(body); function traverse(node) { switch (node.kind) { - case 203: + case 203 /* YieldExpression */: visitor(node); var operand = node.expression; if (operand) { traverse(operand); } return; - case 238: - case 236: - case 239: - case 237: - case 235: - case 205: + case 238 /* EnumDeclaration */: + case 236 /* InterfaceDeclaration */: + case 239 /* ModuleDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + // These are not allowed inside a generator now, but eventually they may be allowed + // as local types. Regardless, any yield statements contained within them should be + // skipped in this traversal. return; default: if (ts.isFunctionLike(node)) { - if (node.name && node.name.kind === 147) { + if (node.name && node.name.kind === 147 /* ComputedPropertyName */) { + // Note that we will not include methods/accessors of a class because they would require + // first descending into the class. This is by design. traverse(node.name.expression); return; } } else if (!isPartOfTypeNode(node)) { + // This is the general case, which should include mostly expressions and statements. + // Also includes NodeArrays. ts.forEachChild(node, traverse); } } } } ts.forEachYieldExpression = forEachYieldExpression; + /** + * Gets the most likely element type for a TypeNode. This is not an exhaustive test + * as it assumes a rest argument can only be an array type (either T[], or Array). + * + * @param node The type node. + */ function getRestParameterElementType(node) { - if (node && node.kind === 167) { + if (node && node.kind === 167 /* ArrayType */) { return node.elementType; } - else if (node && node.kind === 162) { + else if (node && node.kind === 162 /* TypeReference */) { return ts.singleOrUndefined(node.typeArguments); } else { @@ -7602,12 +8543,12 @@ var ts; ts.getRestParameterElementType = getRestParameterElementType; function getMembersOfDeclaration(node) { switch (node.kind) { - case 236: - case 235: - case 205: - case 166: + case 236 /* InterfaceDeclaration */: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 166 /* TypeLiteral */: return node.members; - case 184: + case 184 /* ObjectLiteralExpression */: return node.properties; } } @@ -7615,14 +8556,14 @@ var ts; function isVariableLike(node) { if (node) { switch (node.kind) { - case 182: - case 273: - case 149: - case 270: - case 152: - case 151: - case 271: - case 232: + case 182 /* BindingElement */: + case 273 /* EnumMember */: + case 149 /* Parameter */: + case 270 /* PropertyAssignment */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 271 /* ShorthandPropertyAssignment */: + case 232 /* VariableDeclaration */: return true; } } @@ -7634,8 +8575,8 @@ var ts; } ts.isVariableLikeOrAccessor = isVariableLikeOrAccessor; function isVariableDeclarationInVariableStatement(node) { - return node.parent.kind === 233 - && node.parent.parent.kind === 214; + return node.parent.kind === 233 /* VariableDeclarationList */ + && node.parent.parent.kind === 214 /* VariableStatement */; } ts.isVariableDeclarationInVariableStatement = isVariableDeclarationInVariableStatement; function isValidESSymbolDeclaration(node) { @@ -7646,13 +8587,13 @@ var ts; ts.isValidESSymbolDeclaration = isValidESSymbolDeclaration; function introducesArgumentsExoticObject(node) { switch (node.kind) { - case 154: - case 153: - case 155: - case 156: - case 157: - case 234: - case 192: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: return true; } return false; @@ -7663,7 +8604,7 @@ var ts; if (beforeUnwrapLabelCallback) { beforeUnwrapLabelCallback(node); } - if (node.statement.kind !== 228) { + if (node.statement.kind !== 228 /* LabeledStatement */) { return node.statement; } node = node.statement; @@ -7671,30 +8612,30 @@ var ts; } ts.unwrapInnermostStatementOfLabel = unwrapInnermostStatementOfLabel; function isFunctionBlock(node) { - return node && node.kind === 213 && ts.isFunctionLike(node.parent); + return node && node.kind === 213 /* Block */ && ts.isFunctionLike(node.parent); } ts.isFunctionBlock = isFunctionBlock; function isObjectLiteralMethod(node) { - return node && node.kind === 154 && node.parent.kind === 184; + return node && node.kind === 154 /* MethodDeclaration */ && node.parent.kind === 184 /* ObjectLiteralExpression */; } ts.isObjectLiteralMethod = isObjectLiteralMethod; function isObjectLiteralOrClassExpressionMethod(node) { - return node.kind === 154 && - (node.parent.kind === 184 || - node.parent.kind === 205); + return node.kind === 154 /* MethodDeclaration */ && + (node.parent.kind === 184 /* ObjectLiteralExpression */ || + node.parent.kind === 205 /* ClassExpression */); } ts.isObjectLiteralOrClassExpressionMethod = isObjectLiteralOrClassExpressionMethod; function isIdentifierTypePredicate(predicate) { - return predicate && predicate.kind === 1; + return predicate && predicate.kind === 1 /* Identifier */; } ts.isIdentifierTypePredicate = isIdentifierTypePredicate; function isThisTypePredicate(predicate) { - return predicate && predicate.kind === 0; + return predicate && predicate.kind === 0 /* This */; } ts.isThisTypePredicate = isThisTypePredicate; function getPropertyAssignment(objectLiteral, key, key2) { return objectLiteral.properties.filter(function (property) { - if (property.kind === 270) { + if (property.kind === 270 /* PropertyAssignment */) { var propName = getTextOfPropertyName(property.name); return key === propName || (!!key2 && key2 === propName); } @@ -7731,64 +8672,87 @@ var ts; } ts.getContainingClass = getContainingClass; function getThisContainer(node, includeArrowFunctions) { - ts.Debug.assert(node.kind !== 274); + ts.Debug.assert(node.kind !== 274 /* SourceFile */); while (true) { node = node.parent; if (!node) { - return ts.Debug.fail(); + return ts.Debug.fail(); // If we never pass in a SourceFile, this should be unreachable, since we'll stop when we reach that. } switch (node.kind) { - case 147: + case 147 /* ComputedPropertyName */: + // If the grandparent node is an object literal (as opposed to a class), + // then the computed property is not a 'this' container. + // A computed property name in a class needs to be a this container + // so that we can error on it. if (ts.isClassLike(node.parent.parent)) { return node; } + // If this is a computed property, then the parent should not + // make it a this container. The parent might be a property + // in an object literal, like a method or accessor. But in order for + // such a parent to be a this container, the reference must be in + // the *body* of the container. node = node.parent; break; - case 150: - if (node.parent.kind === 149 && ts.isClassElement(node.parent.parent)) { + case 150 /* Decorator */: + // Decorators are always applied outside of the body of a class or method. + if (node.parent.kind === 149 /* Parameter */ && ts.isClassElement(node.parent.parent)) { + // If the decorator's parent is a Parameter, we resolve the this container from + // the grandparent class declaration. node = node.parent.parent; } else if (ts.isClassElement(node.parent)) { + // If the decorator's parent is a class element, we resolve the 'this' container + // from the parent class declaration. node = node.parent; } break; - case 193: + case 193 /* ArrowFunction */: if (!includeArrowFunctions) { continue; } - case 234: - case 192: - case 239: - case 152: - case 151: - case 154: - case 153: - case 155: - case 156: - case 157: - case 158: - case 159: - case 160: - case 238: - case 274: + // falls through + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 239 /* ModuleDeclaration */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 160 /* IndexSignature */: + case 238 /* EnumDeclaration */: + case 274 /* SourceFile */: return node; } } } ts.getThisContainer = getThisContainer; function getNewTargetContainer(node) { - var container = getThisContainer(node, false); + var container = getThisContainer(node, /*includeArrowFunctions*/ false); if (container) { switch (container.kind) { - case 155: - case 234: - case 192: + case 155 /* Constructor */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: return container; } } return undefined; } ts.getNewTargetContainer = getNewTargetContainer; + /** + * Given an super call/property node, returns the closest node where + * - a super call/property access is legal in the node and not legal in the parent node the node. + * i.e. super call is legal in constructor but not legal in the class body. + * - the container is an arrow function (so caller might need to call getSuperContainer again in case it needs to climb higher) + * - a super call/property is definitely illegal in the container (but might be legal in some subnode) + * i.e. super property access is illegal in function declaration but can be legal in the statement list + */ function getSuperContainer(node, stopOnFunctions) { while (true) { node = node.parent; @@ -7796,28 +8760,34 @@ var ts; return node; } switch (node.kind) { - case 147: + case 147 /* ComputedPropertyName */: node = node.parent; break; - case 234: - case 192: - case 193: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: if (!stopOnFunctions) { continue; } - case 152: - case 151: - case 154: - case 153: - case 155: - case 156: - case 157: + // falls through + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return node; - case 150: - if (node.parent.kind === 149 && ts.isClassElement(node.parent.parent)) { + case 150 /* Decorator */: + // Decorators are always applied outside of the body of a class or method. + if (node.parent.kind === 149 /* Parameter */ && ts.isClassElement(node.parent.parent)) { + // If the decorator's parent is a Parameter, we resolve the this container from + // the grandparent class declaration. node = node.parent.parent; } else if (ts.isClassElement(node.parent)) { + // If the decorator's parent is a class element, we resolve the 'this' container + // from the parent class declaration. node = node.parent; } break; @@ -7826,41 +8796,47 @@ var ts; } ts.getSuperContainer = getSuperContainer; function getImmediatelyInvokedFunctionExpression(func) { - if (func.kind === 192 || func.kind === 193) { + if (func.kind === 192 /* FunctionExpression */ || func.kind === 193 /* ArrowFunction */) { var prev = func; var parent = func.parent; - while (parent.kind === 191) { + while (parent.kind === 191 /* ParenthesizedExpression */) { prev = parent; parent = parent.parent; } - if (parent.kind === 187 && parent.expression === prev) { + if (parent.kind === 187 /* CallExpression */ && parent.expression === prev) { return parent; } } } ts.getImmediatelyInvokedFunctionExpression = getImmediatelyInvokedFunctionExpression; + /** + * Determines whether a node is a property or element access expression for `super`. + */ function isSuperProperty(node) { var kind = node.kind; - return (kind === 185 || kind === 186) - && node.expression.kind === 97; + return (kind === 185 /* PropertyAccessExpression */ || kind === 186 /* ElementAccessExpression */) + && node.expression.kind === 97 /* SuperKeyword */; } ts.isSuperProperty = isSuperProperty; + /** + * Determines whether a node is a property or element access expression for `this`. + */ function isThisProperty(node) { var kind = node.kind; - return (kind === 185 || kind === 186) - && node.expression.kind === 99; + return (kind === 185 /* PropertyAccessExpression */ || kind === 186 /* ElementAccessExpression */) + && node.expression.kind === 99 /* ThisKeyword */; } ts.isThisProperty = isThisProperty; function getEntityNameFromTypeNode(node) { switch (node.kind) { - case 162: + case 162 /* TypeReference */: return node.typeName; - case 207: + case 207 /* ExpressionWithTypeArguments */: return isEntityNameExpression(node.expression) ? node.expression : undefined; - case 71: - case 146: + case 71 /* Identifier */: + case 146 /* QualifiedName */: return node; } return undefined; @@ -7868,10 +8844,10 @@ var ts; ts.getEntityNameFromTypeNode = getEntityNameFromTypeNode; function getInvokedExpression(node) { switch (node.kind) { - case 189: + case 189 /* TaggedTemplateExpression */: return node.tag; - case 257: - case 256: + case 257 /* JsxOpeningElement */: + case 256 /* JsxSelfClosingElement */: return node.tagName; default: return node.expression; @@ -7880,41 +8856,45 @@ var ts; ts.getInvokedExpression = getInvokedExpression; function nodeCanBeDecorated(node, parent, grandparent) { switch (node.kind) { - case 235: + case 235 /* ClassDeclaration */: + // classes are valid targets return true; - case 152: - return parent.kind === 235; - case 156: - case 157: - case 154: + case 152 /* PropertyDeclaration */: + // property declarations are valid if their parent is a class declaration. + return parent.kind === 235 /* ClassDeclaration */; + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 154 /* MethodDeclaration */: + // if this method has a body and its parent is a class declaration, this is a valid target. return node.body !== undefined - && parent.kind === 235; - case 149: + && parent.kind === 235 /* ClassDeclaration */; + case 149 /* Parameter */: + // if the parameter's parent has a body and its grandparent is a class declaration, this is a valid target; return parent.body !== undefined - && (parent.kind === 155 - || parent.kind === 154 - || parent.kind === 157) - && grandparent.kind === 235; + && (parent.kind === 155 /* Constructor */ + || parent.kind === 154 /* MethodDeclaration */ + || parent.kind === 157 /* SetAccessor */) + && grandparent.kind === 235 /* ClassDeclaration */; } return false; } ts.nodeCanBeDecorated = nodeCanBeDecorated; function nodeIsDecorated(node, parent, grandparent) { return node.decorators !== undefined - && nodeCanBeDecorated(node, parent, grandparent); + && nodeCanBeDecorated(node, parent, grandparent); // TODO: GH#18217 } ts.nodeIsDecorated = nodeIsDecorated; function nodeOrChildIsDecorated(node, parent, grandparent) { - return nodeIsDecorated(node, parent, grandparent) || childIsDecorated(node, parent); + return nodeIsDecorated(node, parent, grandparent) || childIsDecorated(node, parent); // TODO: GH#18217 } ts.nodeOrChildIsDecorated = nodeOrChildIsDecorated; function childIsDecorated(node, parent) { switch (node.kind) { - case 235: - return ts.some(node.members, function (m) { return nodeOrChildIsDecorated(m, node, parent); }); - case 154: - case 157: - return ts.some(node.parameters, function (p) { return nodeIsDecorated(p, node, parent); }); + case 235 /* ClassDeclaration */: + return ts.some(node.members, function (m) { return nodeOrChildIsDecorated(m, node, parent); }); // TODO: GH#18217 + case 154 /* MethodDeclaration */: + case 157 /* SetAccessor */: + return ts.some(node.parameters, function (p) { return nodeIsDecorated(p, node, parent); }); // TODO: GH#18217 default: return false; } @@ -7922,9 +8902,9 @@ var ts; ts.childIsDecorated = childIsDecorated; function isJSXTagName(node) { var parent = node.parent; - if (parent.kind === 257 || - parent.kind === 256 || - parent.kind === 258) { + if (parent.kind === 257 /* JsxOpeningElement */ || + parent.kind === 256 /* JsxSelfClosingElement */ || + parent.kind === 258 /* JsxClosingElement */) { return parent.tagName === node; } return false; @@ -7932,55 +8912,56 @@ var ts; ts.isJSXTagName = isJSXTagName; function isExpressionNode(node) { switch (node.kind) { - case 97: - case 95: - case 101: - case 86: - case 12: - case 183: - case 184: - case 185: - case 186: - case 187: - case 188: - case 189: - case 208: - case 190: - case 209: - case 191: - case 192: - case 205: - case 193: - case 196: - case 194: - case 195: - case 198: - case 199: - case 200: - case 201: - case 204: - case 202: - case 13: - case 206: - case 255: - case 256: - case 259: - case 203: - case 197: - case 210: + case 97 /* SuperKeyword */: + case 95 /* NullKeyword */: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: + case 12 /* RegularExpressionLiteral */: + case 183 /* ArrayLiteralExpression */: + case 184 /* ObjectLiteralExpression */: + case 185 /* PropertyAccessExpression */: + case 186 /* ElementAccessExpression */: + case 187 /* CallExpression */: + case 188 /* NewExpression */: + case 189 /* TaggedTemplateExpression */: + case 208 /* AsExpression */: + case 190 /* TypeAssertionExpression */: + case 209 /* NonNullExpression */: + case 191 /* ParenthesizedExpression */: + case 192 /* FunctionExpression */: + case 205 /* ClassExpression */: + case 193 /* ArrowFunction */: + case 196 /* VoidExpression */: + case 194 /* DeleteExpression */: + case 195 /* TypeOfExpression */: + case 198 /* PrefixUnaryExpression */: + case 199 /* PostfixUnaryExpression */: + case 200 /* BinaryExpression */: + case 201 /* ConditionalExpression */: + case 204 /* SpreadElement */: + case 202 /* TemplateExpression */: + case 13 /* NoSubstitutionTemplateLiteral */: + case 206 /* OmittedExpression */: + case 255 /* JsxElement */: + case 256 /* JsxSelfClosingElement */: + case 259 /* JsxFragment */: + case 203 /* YieldExpression */: + case 197 /* AwaitExpression */: + case 210 /* MetaProperty */: return true; - case 146: - while (node.parent.kind === 146) { + case 146 /* QualifiedName */: + while (node.parent.kind === 146 /* QualifiedName */) { node = node.parent; } - return node.parent.kind === 165 || isJSXTagName(node); - case 71: - if (node.parent.kind === 165 || isJSXTagName(node)) { + return node.parent.kind === 165 /* TypeQuery */ || isJSXTagName(node); + case 71 /* Identifier */: + if (node.parent.kind === 165 /* TypeQuery */ || isJSXTagName(node)) { return true; } - case 8: - case 9: - case 99: + // falls through + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: + case 99 /* ThisKeyword */: return isInExpressionContext(node); default: return false; @@ -7990,47 +8971,47 @@ var ts; function isInExpressionContext(node) { var parent = node.parent; switch (parent.kind) { - case 232: - case 149: - case 152: - case 151: - case 273: - case 270: - case 182: + case 232 /* VariableDeclaration */: + case 149 /* Parameter */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 273 /* EnumMember */: + case 270 /* PropertyAssignment */: + case 182 /* BindingElement */: return parent.initializer === node; - case 216: - case 217: - case 218: - case 219: - case 225: - case 226: - case 227: - case 266: - case 229: + case 216 /* ExpressionStatement */: + case 217 /* IfStatement */: + case 218 /* DoStatement */: + case 219 /* WhileStatement */: + case 225 /* ReturnStatement */: + case 226 /* WithStatement */: + case 227 /* SwitchStatement */: + case 266 /* CaseClause */: + case 229 /* ThrowStatement */: return parent.expression === node; - case 220: + case 220 /* ForStatement */: var forStatement = parent; - return (forStatement.initializer === node && forStatement.initializer.kind !== 233) || + return (forStatement.initializer === node && forStatement.initializer.kind !== 233 /* VariableDeclarationList */) || forStatement.condition === node || forStatement.incrementor === node; - case 221: - case 222: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: var forInStatement = parent; - return (forInStatement.initializer === node && forInStatement.initializer.kind !== 233) || + return (forInStatement.initializer === node && forInStatement.initializer.kind !== 233 /* VariableDeclarationList */) || forInStatement.expression === node; - case 190: - case 208: + case 190 /* TypeAssertionExpression */: + case 208 /* AsExpression */: return node === parent.expression; - case 211: + case 211 /* TemplateSpan */: return node === parent.expression; - case 147: + case 147 /* ComputedPropertyName */: return node === parent.expression; - case 150: - case 265: - case 264: - case 272: + case 150 /* Decorator */: + case 265 /* JsxExpression */: + case 264 /* JsxSpreadAttribute */: + case 272 /* SpreadAssignment */: return true; - case 207: + case 207 /* ExpressionWithTypeArguments */: return parent.expression === node && isExpressionWithTypeArgumentsInClassExtendsClause(parent); default: return isExpressionNode(parent); @@ -8038,7 +9019,7 @@ var ts; } ts.isInExpressionContext = isInExpressionContext; function isExternalModuleImportEqualsDeclaration(node) { - return node.kind === 243 && node.moduleReference.kind === 254; + return node.kind === 243 /* ImportEqualsDeclaration */ && node.moduleReference.kind === 254 /* ExternalModuleReference */; } ts.isExternalModuleImportEqualsDeclaration = isExternalModuleImportEqualsDeclaration; function getExternalModuleImportEqualsDeclarationExpression(node) { @@ -8047,7 +9028,7 @@ var ts; } ts.getExternalModuleImportEqualsDeclarationExpression = getExternalModuleImportEqualsDeclarationExpression; function isInternalModuleImportEqualsDeclaration(node) { - return node.kind === 243 && node.moduleReference.kind !== 254; + return node.kind === 243 /* ImportEqualsDeclaration */ && node.moduleReference.kind !== 254 /* ExternalModuleReference */; } ts.isInternalModuleImportEqualsDeclaration = isInternalModuleImportEqualsDeclaration; function isSourceFileJavaScript(file) { @@ -8059,15 +9040,15 @@ var ts; } ts.isSourceFileNotJavaScript = isSourceFileNotJavaScript; function isInJavaScriptFile(node) { - return !!node && !!(node.flags & 65536); + return !!node && !!(node.flags & 65536 /* JavaScriptFile */); } ts.isInJavaScriptFile = isInJavaScriptFile; function isInJsonFile(node) { - return !!node && !!(node.flags & 16777216); + return !!node && !!(node.flags & 16777216 /* JsonFile */); } ts.isInJsonFile = isInJsonFile; function isInJSDoc(node) { - return !!node && !!(node.flags & 2097152); + return !!node && !!(node.flags & 2097152 /* JSDoc */); } ts.isInJSDoc = isInJSDoc; function isJSDocIndexSignature(node) { @@ -8075,15 +9056,15 @@ var ts; ts.isIdentifier(node.typeName) && node.typeName.escapedText === "Object" && node.typeArguments && node.typeArguments.length === 2 && - (node.typeArguments[0].kind === 137 || node.typeArguments[0].kind === 134); + (node.typeArguments[0].kind === 137 /* StringKeyword */ || node.typeArguments[0].kind === 134 /* NumberKeyword */); } ts.isJSDocIndexSignature = isJSDocIndexSignature; function isRequireCall(callExpression, checkArgumentIsStringLiteralLike) { - if (callExpression.kind !== 187) { + if (callExpression.kind !== 187 /* CallExpression */) { return false; } var _a = callExpression, expression = _a.expression, args = _a.arguments; - if (expression.kind !== 71 || expression.escapedText !== "require") { + if (expression.kind !== 71 /* Identifier */ || expression.escapedText !== "require") { return false; } if (args.length !== 1) { @@ -8094,11 +9075,11 @@ var ts; } ts.isRequireCall = isRequireCall; function isSingleOrDoubleQuote(charCode) { - return charCode === 39 || charCode === 34; + return charCode === 39 /* singleQuote */ || charCode === 34 /* doubleQuote */; } ts.isSingleOrDoubleQuote = isSingleOrDoubleQuote; function isStringDoubleQuoted(str, sourceFile) { - return getSourceTextOfNodeFromSourceFile(sourceFile, str).charCodeAt(0) === 34; + return getSourceTextOfNodeFromSourceFile(sourceFile, str).charCodeAt(0) === 34 /* doubleQuote */; } ts.isStringDoubleQuoted = isStringDoubleQuoted; function getDeclarationOfJSInitializer(node) { @@ -8111,16 +9092,16 @@ var ts; name = node.parent.name; decl = node.parent; } - else if (ts.isBinaryExpression(node.parent) && node.parent.operatorToken.kind === 58 && node.parent.right === node) { + else if (ts.isBinaryExpression(node.parent) && node.parent.operatorToken.kind === 58 /* EqualsToken */ && node.parent.right === node) { name = node.parent.left; decl = name; } - else if (ts.isBinaryExpression(node.parent) && node.parent.operatorToken.kind === 54) { + else if (ts.isBinaryExpression(node.parent) && node.parent.operatorToken.kind === 54 /* BarBarToken */) { if (ts.isVariableDeclaration(node.parent.parent) && node.parent.parent.initializer === node.parent) { name = node.parent.parent.name; decl = node.parent.parent; } - else if (ts.isBinaryExpression(node.parent.parent) && node.parent.parent.operatorToken.kind === 58 && node.parent.parent.right === node.parent) { + else if (ts.isBinaryExpression(node.parent.parent) && node.parent.parent.operatorToken.kind === 58 /* EqualsToken */ && node.parent.parent.right === node.parent) { name = node.parent.parent.left; decl = name; } @@ -8134,36 +9115,52 @@ var ts; return decl; } ts.getDeclarationOfJSInitializer = getDeclarationOfJSInitializer; + /** Get the initializer, taking into account defaulted Javascript initializers */ function getEffectiveInitializer(node) { if (isInJavaScriptFile(node) && node.initializer && - ts.isBinaryExpression(node.initializer) && node.initializer.operatorToken.kind === 54 && + ts.isBinaryExpression(node.initializer) && node.initializer.operatorToken.kind === 54 /* BarBarToken */ && node.name && isEntityNameExpression(node.name) && isSameEntityName(node.name, node.initializer.left)) { return node.initializer.right; } return node.initializer; } ts.getEffectiveInitializer = getEffectiveInitializer; + /** Get the declaration initializer when it is container-like (See getJavascriptInitializer). */ function getDeclaredJavascriptInitializer(node) { var init = getEffectiveInitializer(node); return init && getJavascriptInitializer(init, isPrototypeAccess(node.name)); } ts.getDeclaredJavascriptInitializer = getDeclaredJavascriptInitializer; + /** + * Get the assignment 'initializer' -- the righthand side-- when the initializer is container-like (See getJavascriptInitializer). + * We treat the right hand side of assignments with container-like initalizers as declarations. + */ function getAssignedJavascriptInitializer(node) { - if (node && node.parent && ts.isBinaryExpression(node.parent) && node.parent.operatorToken.kind === 58) { + if (node && node.parent && ts.isBinaryExpression(node.parent) && node.parent.operatorToken.kind === 58 /* EqualsToken */) { var isPrototypeAssignment = isPrototypeAccess(node.parent.left); return getJavascriptInitializer(node.parent.right, isPrototypeAssignment) || getDefaultedJavascriptInitializer(node.parent.left, node.parent.right, isPrototypeAssignment); } } ts.getAssignedJavascriptInitializer = getAssignedJavascriptInitializer; + /** + * Recognized Javascript container-like initializers are: + * 1. (function() {})() -- IIFEs + * 2. function() { } -- Function expressions + * 3. class { } -- Class expressions + * 4. {} -- Empty object literals + * 5. { ... } -- Non-empty object literals, when used to initialize a prototype, like `C.prototype = { m() { } }` + * + * This function returns the provided initializer, or undefined if it is not valid. + */ function getJavascriptInitializer(initializer, isPrototypeAssignment) { if (ts.isCallExpression(initializer)) { var e = skipParentheses(initializer.expression); - return e.kind === 192 || e.kind === 193 ? initializer : undefined; + return e.kind === 192 /* FunctionExpression */ || e.kind === 193 /* ArrowFunction */ ? initializer : undefined; } - if (initializer.kind === 192 || - initializer.kind === 205 || - initializer.kind === 193) { + if (initializer.kind === 192 /* FunctionExpression */ || + initializer.kind === 205 /* ClassExpression */ || + initializer.kind === 193 /* ArrowFunction */) { return initializer; } if (ts.isObjectLiteralExpression(initializer) && (initializer.properties.length === 0 || isPrototypeAssignment)) { @@ -8171,23 +9168,32 @@ var ts; } } ts.getJavascriptInitializer = getJavascriptInitializer; + /** + * A defaulted Javascript initializer matches the pattern + * `Lhs = Lhs || JavascriptInitializer` + * or `var Lhs = Lhs || JavascriptInitializer` + * + * The second Lhs is required to be the same as the first except that it may be prefixed with + * 'window.', 'global.' or 'self.' The second Lhs is otherwise ignored by the binder and checker. + */ function getDefaultedJavascriptInitializer(name, initializer, isPrototypeAssignment) { - var e = ts.isBinaryExpression(initializer) && initializer.operatorToken.kind === 54 && getJavascriptInitializer(initializer.right, isPrototypeAssignment); + var e = ts.isBinaryExpression(initializer) && initializer.operatorToken.kind === 54 /* BarBarToken */ && getJavascriptInitializer(initializer.right, isPrototypeAssignment); if (e && isSameEntityName(name, initializer.left)) { return e; } } function isDefaultedJavascriptInitializer(node) { var name = ts.isVariableDeclaration(node.parent) ? node.parent.name : - ts.isBinaryExpression(node.parent) && node.parent.operatorToken.kind === 58 ? node.parent.left : + ts.isBinaryExpression(node.parent) && node.parent.operatorToken.kind === 58 /* EqualsToken */ ? node.parent.left : undefined; return name && getJavascriptInitializer(node.right, isPrototypeAccess(name)) && isEntityNameExpression(name) && isSameEntityName(name, node.left); } ts.isDefaultedJavascriptInitializer = isDefaultedJavascriptInitializer; + /** Given a Javascript initializer, return the outer name. That is, the lhs of the assignment or the declaration name. */ function getOuterNameOfJsInitializer(node) { if (ts.isBinaryExpression(node.parent)) { - var parent = (node.parent.operatorToken.kind === 54 && ts.isBinaryExpression(node.parent.parent)) ? node.parent.parent : node.parent; - if (parent.operatorToken.kind === 58 && ts.isIdentifier(parent.left)) { + var parent = (node.parent.operatorToken.kind === 54 /* BarBarToken */ && ts.isBinaryExpression(node.parent.parent)) ? node.parent.parent : node.parent; + if (parent.operatorToken.kind === 58 /* EqualsToken */ && ts.isIdentifier(parent.left)) { return parent.left; } } @@ -8196,12 +9202,21 @@ var ts; } } ts.getOuterNameOfJsInitializer = getOuterNameOfJsInitializer; + /** + * Is the 'declared' name the same as the one in the initializer? + * @return true for identical entity names, as well as ones where the initializer is prefixed with + * 'window', 'self' or 'global'. For example: + * + * var my = my || {} + * var min = window.min || {} + * my.app = self.my.app || class { } + */ function isSameEntityName(name, initializer) { if (ts.isIdentifier(name) && ts.isIdentifier(initializer)) { return name.escapedText === initializer.escapedText; } if (ts.isIdentifier(name) && ts.isPropertyAccessExpression(initializer)) { - return (initializer.expression.kind === 99 || + return (initializer.expression.kind === 99 /* ThisKeyword */ || ts.isIdentifier(initializer.expression) && (initializer.expression.escapedText === "window" || initializer.expression.escapedText === "self" || @@ -8214,7 +9229,7 @@ var ts; return false; } function getRightMostAssignedExpression(node) { - while (isAssignmentExpression(node, true)) { + while (isAssignmentExpression(node, /*excludeCompoundAssignements*/ true)) { node = node.right; } return node; @@ -8228,25 +9243,30 @@ var ts; return ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression) && node.expression.escapedText === "module" && node.name.escapedText === "exports"; } ts.isModuleExportsPropertyAccessExpression = isModuleExportsPropertyAccessExpression; + /// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property + /// assignments we treat as special in the binder function getSpecialPropertyAssignmentKind(expr) { if (!isInJavaScriptFile(expr) || - expr.operatorToken.kind !== 58 || + expr.operatorToken.kind !== 58 /* EqualsToken */ || !ts.isPropertyAccessExpression(expr.left)) { - return 0; + return 0 /* None */; } var lhs = expr.left; - if (lhs.expression.kind === 99) { - return 4; + if (lhs.expression.kind === 99 /* ThisKeyword */) { + return 4 /* ThisProperty */; } else if (ts.isIdentifier(lhs.expression) && lhs.expression.escapedText === "module" && lhs.name.escapedText === "exports") { - return 2; + // module.exports = expr + return 2 /* ModuleExports */; } else if (isEntityNameExpression(lhs.expression)) { if (lhs.name.escapedText === "prototype" && ts.isObjectLiteralExpression(getInitializerOfBinaryExpression(expr))) { - return 6; + // F.prototype = { ... } + return 6 /* Prototype */; } else if (isPrototypeAccess(lhs.expression)) { - return 3; + // F.G....prototype.x = expr + return 3 /* PrototypeProperty */; } var nextToLast = lhs; while (ts.isPropertyAccessExpression(nextToLast.expression)) { @@ -8256,11 +9276,13 @@ var ts; var id = nextToLast.expression; if (id.escapedText === "exports" || id.escapedText === "module" && nextToLast.name.escapedText === "exports") { - return 1; + // exports.name = expr OR module.exports.name = expr + return 1 /* ExportsProperty */; } - return 5; + // F.G...x = expr + return 5 /* Property */; } - return 0; + return 0 /* None */; } ts.getSpecialPropertyAssignmentKind = getSpecialPropertyAssignmentKind; function getInitializerOfBinaryExpression(expr) { @@ -8271,12 +9293,12 @@ var ts; } ts.getInitializerOfBinaryExpression = getInitializerOfBinaryExpression; function isPrototypePropertyAssignment(node) { - return ts.isBinaryExpression(node) && getSpecialPropertyAssignmentKind(node) === 3; + return ts.isBinaryExpression(node) && getSpecialPropertyAssignmentKind(node) === 3 /* PrototypeProperty */; } ts.isPrototypePropertyAssignment = isPrototypePropertyAssignment; function isSpecialPropertyDeclaration(expr) { return isInJavaScriptFile(expr) && - expr.parent && expr.parent.kind === 216 && + expr.parent && expr.parent.kind === 216 /* ExpressionStatement */ && !!ts.getJSDocTypeTag(expr.parent); } ts.isSpecialPropertyDeclaration = isSpecialPropertyDeclaration; @@ -8286,14 +9308,14 @@ var ts; ts.importFromModuleSpecifier = importFromModuleSpecifier; function tryGetImportFromModuleSpecifier(node) { switch (node.parent.kind) { - case 244: - case 250: + case 244 /* ImportDeclaration */: + case 250 /* ExportDeclaration */: return node.parent; - case 254: + case 254 /* ExternalModuleReference */: return node.parent.parent; - case 187: + case 187 /* CallExpression */: return node.parent; - case 178: + case 178 /* LiteralType */: ts.Debug.assert(ts.isStringLiteral(node)); return ts.tryCast(node.parent.parent, ts.isImportTypeNode); default: @@ -8303,12 +9325,12 @@ var ts; ts.tryGetImportFromModuleSpecifier = tryGetImportFromModuleSpecifier; function getExternalModuleName(node) { switch (node.kind) { - case 244: - case 250: + case 244 /* ImportDeclaration */: + case 250 /* ExportDeclaration */: return node.moduleSpecifier; - case 243: - return node.moduleReference.kind === 254 ? node.moduleReference.expression : undefined; - case 179: + case 243 /* ImportEqualsDeclaration */: + return node.moduleReference.kind === 254 /* ExternalModuleReference */ ? node.moduleReference.expression : undefined; + case 179 /* ImportType */: return isLiteralImportTypeNode(node) ? node.argument.literal : undefined; default: return ts.Debug.assertNever(node); @@ -8317,11 +9339,11 @@ var ts; ts.getExternalModuleName = getExternalModuleName; function getNamespaceDeclarationNode(node) { switch (node.kind) { - case 244: + case 244 /* ImportDeclaration */: return node.importClause && ts.tryCast(node.importClause.namedBindings, ts.isNamespaceImport); - case 243: + case 243 /* ImportEqualsDeclaration */: return node; - case 250: + case 250 /* ExportDeclaration */: return undefined; default: return ts.Debug.assertNever(node); @@ -8329,19 +9351,19 @@ var ts; } ts.getNamespaceDeclarationNode = getNamespaceDeclarationNode; function isDefaultImport(node) { - return node.kind === 244 && !!node.importClause && !!node.importClause.name; + return node.kind === 244 /* ImportDeclaration */ && !!node.importClause && !!node.importClause.name; } ts.isDefaultImport = isDefaultImport; function hasQuestionToken(node) { if (node) { switch (node.kind) { - case 149: - case 154: - case 153: - case 271: - case 270: - case 152: - case 151: + case 149 /* Parameter */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 271 /* ShorthandPropertyAssignment */: + case 270 /* PropertyAssignment */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: return node.questionToken !== undefined; } } @@ -8349,14 +9371,14 @@ var ts; } ts.hasQuestionToken = hasQuestionToken; function isJSDocConstructSignature(node) { - return node.kind === 284 && + return node.kind === 284 /* JSDocFunctionType */ && node.parameters.length > 0 && node.parameters[0].name && node.parameters[0].name.escapedText === "new"; } ts.isJSDocConstructSignature = isJSDocConstructSignature; function isJSDocTypeAlias(node) { - return node.kind === 298 || node.kind === 292; + return node.kind === 298 /* JSDocTypedefTag */ || node.kind === 292 /* JSDocCallbackTag */; } ts.isJSDocTypeAlias = isJSDocTypeAlias; function isTypeAlias(node) { @@ -8366,27 +9388,27 @@ var ts; function getSourceOfAssignment(node) { return ts.isExpressionStatement(node) && node.expression && ts.isBinaryExpression(node.expression) && - node.expression.operatorToken.kind === 58 + node.expression.operatorToken.kind === 58 /* EqualsToken */ ? node.expression.right : undefined; } function getSourceOfDefaultedAssignment(node) { return ts.isExpressionStatement(node) && ts.isBinaryExpression(node.expression) && - getSpecialPropertyAssignmentKind(node.expression) !== 0 && + getSpecialPropertyAssignmentKind(node.expression) !== 0 /* None */ && ts.isBinaryExpression(node.expression.right) && - node.expression.right.operatorToken.kind === 54 + node.expression.right.operatorToken.kind === 54 /* BarBarToken */ ? node.expression.right.right : undefined; } function getSingleInitializerOfVariableStatementOrPropertyDeclaration(node) { switch (node.kind) { - case 214: + case 214 /* VariableStatement */: var v = getSingleVariableOfVariableStatement(node); return v && v.initializer; - case 152: + case 152 /* PropertyDeclaration */: return node.initializer; - case 270: + case 270 /* PropertyAssignment */: return node.initializer; } } @@ -8396,7 +9418,7 @@ var ts; function getNestedModuleDeclaration(node) { return ts.isModuleDeclaration(node) && node.body && - node.body.kind === 239 + node.body.kind === 239 /* ModuleDeclaration */ ? node.body : undefined; } @@ -8408,9 +9430,15 @@ var ts; var parent = node.parent; if (!parent) return; - if (parent.kind === 270 || parent.kind === 152 || getNestedModuleDeclaration(parent)) { + if (parent.kind === 270 /* PropertyAssignment */ || parent.kind === 152 /* PropertyDeclaration */ || getNestedModuleDeclaration(parent)) { getJSDocCommentsAndTagsWorker(parent); } + // Try to recognize this pattern when node is initializer of variable declaration and JSDoc comments are on containing variable statement. + // /** + // * @param {number} name + // * @returns {number} + // */ + // var x = function(name) { return name.length; } if (parent.parent && (getSingleVariableOfVariableStatement(parent.parent) === node)) { getJSDocCommentsAndTagsWorker(parent.parent); } @@ -8420,9 +9448,9 @@ var ts; getSourceOfDefaultedAssignment(parent.parent.parent))) { getJSDocCommentsAndTagsWorker(parent.parent.parent); } - if (ts.isBinaryExpression(node) && node.operatorToken.kind === 58 || - ts.isBinaryExpression(parent) && parent.operatorToken.kind === 58 || - node.kind === 185 && node.parent && node.parent.kind === 216) { + if (ts.isBinaryExpression(node) && node.operatorToken.kind === 58 /* EqualsToken */ || + ts.isBinaryExpression(parent) && parent.operatorToken.kind === 58 /* EqualsToken */ || + node.kind === 185 /* PropertyAccessExpression */ && node.parent && node.parent.kind === 216 /* ExpressionStatement */) { if (ts.isBinaryExpression(parent)) { getJSDocCommentsAndTagsWorker(parent.parent); } @@ -8430,7 +9458,8 @@ var ts; getJSDocCommentsAndTagsWorker(parent); } } - if (node.kind === 149) { + // Pull parameter comments from declaring function as well + if (node.kind === 149 /* Parameter */) { result = ts.addRange(result, ts.getJSDocParameterTags(node)); } if (isVariableLike(node) && ts.hasInitializer(node) && node.initializer !== hostNode && ts.hasJSDocNodes(node.initializer)) { @@ -8442,6 +9471,7 @@ var ts; } } ts.getJSDocCommentsAndTags = getJSDocCommentsAndTags; + /** Does the opposite of `getJSDocParameterTags`: given a JSDoc parameter, finds the parameter corresponding to it. */ function getParameterSymbolFromJSDoc(node) { if (node.symbol) { return node.symbol; @@ -8454,7 +9484,7 @@ var ts; if (!decl) { return undefined; } - var parameter = ts.find(decl.parameters, function (p) { return p.name.kind === 71 && p.name.escapedText === name; }); + var parameter = ts.find(decl.parameters, function (p) { return p.name.kind === 71 /* Identifier */ && p.name.escapedText === name; }); return parameter && parameter.symbol; } ts.getParameterSymbolFromJSDoc = getParameterSymbolFromJSDoc; @@ -8489,7 +9519,7 @@ var ts; ts.hasRestParameter = hasRestParameter; function isRestParameter(node) { var type = ts.isJSDocParameterTag(node) ? (node.typeExpression && node.typeExpression.type) : node.type; - return node.dotDotDotToken !== undefined || !!type && type.kind === 285; + return node.dotDotDotToken !== undefined || !!type && type.kind === 285 /* JSDocVariadicType */; } ts.isRestParameter = isRestParameter; var AssignmentKind; @@ -8502,65 +9532,73 @@ var ts; var parent = node.parent; while (true) { switch (parent.kind) { - case 200: + case 200 /* BinaryExpression */: var binaryOperator = parent.operatorToken.kind; return isAssignmentOperator(binaryOperator) && parent.left === node ? - binaryOperator === 58 ? 1 : 2 : - 0; - case 198: - case 199: + binaryOperator === 58 /* EqualsToken */ ? 1 /* Definite */ : 2 /* Compound */ : + 0 /* None */; + case 198 /* PrefixUnaryExpression */: + case 199 /* PostfixUnaryExpression */: var unaryOperator = parent.operator; - return unaryOperator === 43 || unaryOperator === 44 ? 2 : 0; - case 221: - case 222: - return parent.initializer === node ? 1 : 0; - case 191: - case 183: - case 204: - case 209: + return unaryOperator === 43 /* PlusPlusToken */ || unaryOperator === 44 /* MinusMinusToken */ ? 2 /* Compound */ : 0 /* None */; + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + return parent.initializer === node ? 1 /* Definite */ : 0 /* None */; + case 191 /* ParenthesizedExpression */: + case 183 /* ArrayLiteralExpression */: + case 204 /* SpreadElement */: + case 209 /* NonNullExpression */: node = parent; break; - case 271: + case 271 /* ShorthandPropertyAssignment */: if (parent.name !== node) { - return 0; + return 0 /* None */; } node = parent.parent; break; - case 270: + case 270 /* PropertyAssignment */: if (parent.name === node) { - return 0; + return 0 /* None */; } node = parent.parent; break; default: - return 0; + return 0 /* None */; } parent = node.parent; } } ts.getAssignmentTargetKind = getAssignmentTargetKind; + // A node is an assignment target if it is on the left hand side of an '=' token, if it is parented by a property + // assignment in an object literal that is an assignment target, or if it is parented by an array literal that is + // an assignment target. Examples include 'a = xxx', '{ p: a } = xxx', '[{ a }] = xxx'. + // (Note that `p` is not a target in the above examples, only `a`.) function isAssignmentTarget(node) { - return getAssignmentTargetKind(node) !== 0; + return getAssignmentTargetKind(node) !== 0 /* None */; } ts.isAssignmentTarget = isAssignmentTarget; + /** + * Indicates whether a node could contain a `var` VariableDeclarationList that contributes to + * the same `var` declaration scope as the node's parent. + */ function isNodeWithPossibleHoistedDeclaration(node) { switch (node.kind) { - case 213: - case 214: - case 226: - case 217: - case 227: - case 241: - case 266: - case 267: - case 228: - case 220: - case 221: - case 222: - case 218: - case 219: - case 230: - case 269: + case 213 /* Block */: + case 214 /* VariableStatement */: + case 226 /* WithStatement */: + case 217 /* IfStatement */: + case 227 /* SwitchStatement */: + case 241 /* CaseBlock */: + case 266 /* CaseClause */: + case 267 /* DefaultClause */: + case 228 /* LabeledStatement */: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 218 /* DoStatement */: + case 219 /* WhileStatement */: + case 230 /* TryStatement */: + case 269 /* CatchClause */: return true; } return false; @@ -8577,26 +9615,27 @@ var ts; return node; } function walkUpParenthesizedTypes(node) { - return walkUp(node, 173); + return walkUp(node, 173 /* ParenthesizedType */); } ts.walkUpParenthesizedTypes = walkUpParenthesizedTypes; function walkUpParenthesizedExpressions(node) { - return walkUp(node, 191); + return walkUp(node, 191 /* ParenthesizedExpression */); } ts.walkUpParenthesizedExpressions = walkUpParenthesizedExpressions; function skipParentheses(node) { - while (node.kind === 191) { + while (node.kind === 191 /* ParenthesizedExpression */) { node = node.expression; } return node; } ts.skipParentheses = skipParentheses; + // a node is delete target iff. it is PropertyAccessExpression/ElementAccessExpression with parentheses skipped function isDeleteTarget(node) { - if (node.kind !== 185 && node.kind !== 186) { + if (node.kind !== 185 /* PropertyAccessExpression */ && node.kind !== 186 /* ElementAccessExpression */) { return false; } node = walkUpParenthesizedExpressions(node.parent); - return node && node.kind === 194; + return node && node.kind === 194 /* DeleteExpression */; } ts.isDeleteTarget = isDeleteTarget; function isNodeDescendantOf(node, ancestor) { @@ -8608,15 +9647,17 @@ var ts; return false; } ts.isNodeDescendantOf = isNodeDescendantOf; + // True if `name` is the name of a declaration node function isDeclarationName(name) { return !ts.isSourceFile(name) && !ts.isBindingPattern(name) && ts.isDeclaration(name.parent) && name.parent.name === name; } ts.isDeclarationName = isDeclarationName; + // See GH#16030 function isAnyDeclarationName(name) { switch (name.kind) { - case 71: - case 9: - case 8: { + case 71 /* Identifier */: + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: { var parent = name.parent; if (ts.isDeclaration(parent)) { return parent.name === name; @@ -8627,7 +9668,7 @@ var ts; } else { var binExp = name.parent.parent; - return ts.isBinaryExpression(binExp) && getSpecialPropertyAssignmentKind(binExp) !== 0 && ts.getNameOfDeclaration(binExp) === name; + return ts.isBinaryExpression(binExp) && getSpecialPropertyAssignmentKind(binExp) !== 0 /* None */ && ts.getNameOfDeclaration(binExp) === name; } } default: @@ -8636,51 +9677,64 @@ var ts; } ts.isAnyDeclarationName = isAnyDeclarationName; function isLiteralComputedPropertyDeclarationName(node) { - return (node.kind === 9 || node.kind === 8) && - node.parent.kind === 147 && + return (node.kind === 9 /* StringLiteral */ || node.kind === 8 /* NumericLiteral */) && + node.parent.kind === 147 /* ComputedPropertyName */ && ts.isDeclaration(node.parent.parent); } ts.isLiteralComputedPropertyDeclarationName = isLiteralComputedPropertyDeclarationName; + // Return true if the given identifier is classified as an IdentifierName function isIdentifierName(node) { var parent = node.parent; switch (parent.kind) { - case 152: - case 151: - case 154: - case 153: - case 156: - case 157: - case 273: - case 270: - case 185: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 273 /* EnumMember */: + case 270 /* PropertyAssignment */: + case 185 /* PropertyAccessExpression */: + // Name in member declaration or property name in property access return parent.name === node; - case 146: + case 146 /* QualifiedName */: + // Name on right hand side of dot in a type query or type reference if (parent.right === node) { - while (parent.kind === 146) { + while (parent.kind === 146 /* QualifiedName */) { parent = parent.parent; } - return parent.kind === 165 || parent.kind === 162; + return parent.kind === 165 /* TypeQuery */ || parent.kind === 162 /* TypeReference */; } return false; - case 182: - case 248: + case 182 /* BindingElement */: + case 248 /* ImportSpecifier */: + // Property name in binding element or import specifier return parent.propertyName === node; - case 252: - case 262: + case 252 /* ExportSpecifier */: + case 262 /* JsxAttribute */: + // Any name in an export specifier or JSX Attribute return true; } return false; } ts.isIdentifierName = isIdentifierName; + // An alias symbol is created by one of the following declarations: + // import = ... + // import from ... + // import * as from ... + // import { x as } from ... + // export { x as } from ... + // export = + // export default function isAliasSymbolDeclaration(node) { - return node.kind === 243 || - node.kind === 242 || - node.kind === 245 && !!node.name || - node.kind === 246 || - node.kind === 248 || - node.kind === 252 || - node.kind === 249 && exportAssignmentIsAlias(node) || - ts.isBinaryExpression(node) && getSpecialPropertyAssignmentKind(node) === 2; + return node.kind === 243 /* ImportEqualsDeclaration */ || + node.kind === 242 /* NamespaceExportDeclaration */ || + node.kind === 245 /* ImportClause */ && !!node.name || + node.kind === 246 /* NamespaceImport */ || + node.kind === 248 /* ImportSpecifier */ || + node.kind === 252 /* ExportSpecifier */ || + node.kind === 249 /* ExportAssignment */ && exportAssignmentIsAlias(node) || + ts.isBinaryExpression(node) && getSpecialPropertyAssignmentKind(node) === 2 /* ModuleExports */; } ts.isAliasSymbolDeclaration = isAliasSymbolDeclaration; function exportAssignmentIsAlias(node) { @@ -8689,15 +9743,16 @@ var ts; } ts.exportAssignmentIsAlias = exportAssignmentIsAlias; function getClassExtendsHeritageClauseElement(node) { - var heritageClause = getHeritageClause(node.heritageClauses, 85); + var heritageClause = getHeritageClause(node.heritageClauses, 85 /* ExtendsKeyword */); return heritageClause && heritageClause.types.length > 0 ? heritageClause.types[0] : undefined; } ts.getClassExtendsHeritageClauseElement = getClassExtendsHeritageClauseElement; function getClassImplementsHeritageClauseElements(node) { - var heritageClause = getHeritageClause(node.heritageClauses, 108); + var heritageClause = getHeritageClause(node.heritageClauses, 108 /* ImplementsKeyword */); return heritageClause ? heritageClause.types : undefined; } ts.getClassImplementsHeritageClauseElements = getClassImplementsHeritageClauseElements; + /** Returns the node in an `extends` or `implements` clause of a class or interface. */ function getAllSuperTypeNodes(node) { return ts.isInterfaceDeclaration(node) ? getInterfaceBaseTypeNodes(node) || ts.emptyArray : ts.isClassLike(node) ? ts.concatenate(ts.singleElementArray(getClassExtendsHeritageClauseElement(node)), getClassImplementsHeritageClauseElements(node)) || ts.emptyArray @@ -8705,7 +9760,7 @@ var ts; } ts.getAllSuperTypeNodes = getAllSuperTypeNodes; function getInterfaceBaseTypeNodes(node) { - var heritageClause = getHeritageClause(node.heritageClauses, 85); + var heritageClause = getHeritageClause(node.heritageClauses, 85 /* ExtendsKeyword */); return heritageClause ? heritageClause.types : undefined; } ts.getInterfaceBaseTypeNodes = getInterfaceBaseTypeNodes; @@ -8739,11 +9794,11 @@ var ts; } ts.getAncestor = getAncestor; function isKeyword(token) { - return 72 <= token && token <= 145; + return 72 /* FirstKeyword */ <= token && token <= 145 /* LastKeyword */; } ts.isKeyword = isKeyword; function isContextualKeyword(token) { - return 117 <= token && token <= 145; + return 117 /* FirstContextualKeyword */ <= token && token <= 145 /* LastContextualKeyword */; } ts.isContextualKeyword = isContextualKeyword; function isNonContextualKeyword(token) { @@ -8756,7 +9811,7 @@ var ts; } ts.isStringANonContextualKeyword = isStringANonContextualKeyword; function isTrivia(token) { - return 2 <= token && token <= 7; + return 2 /* FirstTriviaToken */ <= token && token <= 7 /* LastTriviaToken */; } ts.isTrivia = isTrivia; var FunctionFlags; @@ -8769,75 +9824,88 @@ var ts; })(FunctionFlags = ts.FunctionFlags || (ts.FunctionFlags = {})); function getFunctionFlags(node) { if (!node) { - return 4; + return 4 /* Invalid */; } - var flags = 0; + var flags = 0 /* Normal */; switch (node.kind) { - case 234: - case 192: - case 154: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 154 /* MethodDeclaration */: if (node.asteriskToken) { - flags |= 1; + flags |= 1 /* Generator */; } - case 193: - if (hasModifier(node, 256)) { - flags |= 2; + // falls through + case 193 /* ArrowFunction */: + if (hasModifier(node, 256 /* Async */)) { + flags |= 2 /* Async */; } break; } if (!node.body) { - flags |= 4; + flags |= 4 /* Invalid */; } return flags; } ts.getFunctionFlags = getFunctionFlags; function isAsyncFunction(node) { switch (node.kind) { - case 234: - case 192: - case 193: - case 154: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 154 /* MethodDeclaration */: return node.body !== undefined && node.asteriskToken === undefined - && hasModifier(node, 256); + && hasModifier(node, 256 /* Async */); } return false; } ts.isAsyncFunction = isAsyncFunction; function isStringOrNumericLiteral(node) { var kind = node.kind; - return kind === 9 - || kind === 8; + return kind === 9 /* StringLiteral */ + || kind === 8 /* NumericLiteral */; } ts.isStringOrNumericLiteral = isStringOrNumericLiteral; + /** + * A declaration has a dynamic name if both of the following are true: + * 1. The declaration has a computed property name + * 2. The computed name is *not* expressed as Symbol., where name + * is a property of the Symbol constructor that denotes a built in + * Symbol. + */ function hasDynamicName(declaration) { var name = ts.getNameOfDeclaration(declaration); return !!name && isDynamicName(name); } ts.hasDynamicName = hasDynamicName; function isDynamicName(name) { - return name.kind === 147 && + return name.kind === 147 /* ComputedPropertyName */ && !isStringOrNumericLiteral(name.expression) && !isWellKnownSymbolSyntactically(name.expression); } ts.isDynamicName = isDynamicName; + /** + * Checks if the expression is of the form: + * Symbol.name + * where Symbol is literally the word "Symbol", and name is any identifierName + */ function isWellKnownSymbolSyntactically(node) { return ts.isPropertyAccessExpression(node) && isESSymbolIdentifier(node.expression); } ts.isWellKnownSymbolSyntactically = isWellKnownSymbolSyntactically; function getPropertyNameForPropertyNameNode(name) { - if (name.kind === 71) { + if (name.kind === 71 /* Identifier */) { return name.escapedText; } - if (name.kind === 9 || name.kind === 8) { + if (name.kind === 9 /* StringLiteral */ || name.kind === 8 /* NumericLiteral */) { return escapeLeadingUnderscores(name.text); } - if (name.kind === 147) { + if (name.kind === 147 /* ComputedPropertyName */) { var nameExpression = name.expression; if (isWellKnownSymbolSyntactically(nameExpression)) { return getPropertyNameForKnownSymbolName(ts.idText(nameExpression.name)); } - else if (nameExpression.kind === 9 || nameExpression.kind === 8) { + else if (nameExpression.kind === 9 /* StringLiteral */ || nameExpression.kind === 8 /* NumericLiteral */) { return escapeLeadingUnderscores(nameExpression.text); } } @@ -8846,10 +9914,10 @@ var ts; ts.getPropertyNameForPropertyNameNode = getPropertyNameForPropertyNameNode; function isPropertyNameLiteral(node) { switch (node.kind) { - case 71: - case 9: - case 13: - case 8: + case 71 /* Identifier */: + case 9 /* StringLiteral */: + case 13 /* NoSubstitutionTemplateLiteral */: + case 8 /* NumericLiteral */: return true; default: return false; @@ -8857,11 +9925,11 @@ var ts; } ts.isPropertyNameLiteral = isPropertyNameLiteral; function getTextOfIdentifierOrLiteral(node) { - return node.kind === 71 ? ts.idText(node) : node.text; + return node.kind === 71 /* Identifier */ ? ts.idText(node) : node.text; } ts.getTextOfIdentifierOrLiteral = getTextOfIdentifierOrLiteral; function getEscapedTextOfIdentifierOrLiteral(node) { - return node.kind === 71 ? node.escapedText : escapeLeadingUnderscores(node.text); + return node.kind === 71 /* Identifier */ ? node.escapedText : escapeLeadingUnderscores(node.text); } ts.getEscapedTextOfIdentifierOrLiteral = getEscapedTextOfIdentifierOrLiteral; function getPropertyNameForKnownSymbolName(symbolName) { @@ -8872,8 +9940,11 @@ var ts; return ts.startsWith(symbol.escapedName, "__@"); } ts.isKnownSymbol = isKnownSymbol; + /** + * Includes the word "Symbol" with unicode escapes + */ function isESSymbolIdentifier(node) { - return node.kind === 71 && node.escapedText === "Symbol"; + return node.kind === 71 /* Identifier */ && node.escapedText === "Symbol"; } ts.isESSymbolIdentifier = isESSymbolIdentifier; function isPushOrUnshiftIdentifier(node) { @@ -8882,11 +9953,11 @@ var ts; ts.isPushOrUnshiftIdentifier = isPushOrUnshiftIdentifier; function isParameterDeclaration(node) { var root = getRootDeclaration(node); - return root.kind === 149; + return root.kind === 149 /* Parameter */; } ts.isParameterDeclaration = isParameterDeclaration; function getRootDeclaration(node) { - while (node.kind === 182) { + while (node.kind === 182 /* BindingElement */) { node = node.parent.parent; } return node; @@ -8894,15 +9965,15 @@ var ts; ts.getRootDeclaration = getRootDeclaration; function nodeStartsNewLexicalEnvironment(node) { var kind = node.kind; - return kind === 155 - || kind === 192 - || kind === 234 - || kind === 193 - || kind === 154 - || kind === 156 - || kind === 157 - || kind === 239 - || kind === 274; + return kind === 155 /* Constructor */ + || kind === 192 /* FunctionExpression */ + || kind === 234 /* FunctionDeclaration */ + || kind === 193 /* ArrowFunction */ + || kind === 154 /* MethodDeclaration */ + || kind === 156 /* GetAccessor */ + || kind === 157 /* SetAccessor */ + || kind === 239 /* ModuleDeclaration */ + || kind === 274 /* SourceFile */; } ts.nodeStartsNewLexicalEnvironment = nodeStartsNewLexicalEnvironment; function nodeIsSynthesized(range) { @@ -8921,55 +9992,55 @@ var ts; })(Associativity = ts.Associativity || (ts.Associativity = {})); function getExpressionAssociativity(expression) { var operator = getOperator(expression); - var hasArguments = expression.kind === 188 && expression.arguments !== undefined; + var hasArguments = expression.kind === 188 /* NewExpression */ && expression.arguments !== undefined; return getOperatorAssociativity(expression.kind, operator, hasArguments); } ts.getExpressionAssociativity = getExpressionAssociativity; function getOperatorAssociativity(kind, operator, hasArguments) { switch (kind) { - case 188: - return hasArguments ? 0 : 1; - case 198: - case 195: - case 196: - case 194: - case 197: - case 201: - case 203: - return 1; - case 200: + case 188 /* NewExpression */: + return hasArguments ? 0 /* Left */ : 1 /* Right */; + case 198 /* PrefixUnaryExpression */: + case 195 /* TypeOfExpression */: + case 196 /* VoidExpression */: + case 194 /* DeleteExpression */: + case 197 /* AwaitExpression */: + case 201 /* ConditionalExpression */: + case 203 /* YieldExpression */: + return 1 /* Right */; + case 200 /* BinaryExpression */: switch (operator) { - case 40: - case 58: - case 59: - case 60: - case 62: - case 61: - case 63: - case 64: - case 65: - case 66: - case 67: - case 68: - case 70: - case 69: - return 1; + case 40 /* AsteriskAsteriskToken */: + case 58 /* EqualsToken */: + case 59 /* PlusEqualsToken */: + case 60 /* MinusEqualsToken */: + case 62 /* AsteriskAsteriskEqualsToken */: + case 61 /* AsteriskEqualsToken */: + case 63 /* SlashEqualsToken */: + case 64 /* PercentEqualsToken */: + case 65 /* LessThanLessThanEqualsToken */: + case 66 /* GreaterThanGreaterThanEqualsToken */: + case 67 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + case 68 /* AmpersandEqualsToken */: + case 70 /* CaretEqualsToken */: + case 69 /* BarEqualsToken */: + return 1 /* Right */; } } - return 0; + return 0 /* Left */; } ts.getOperatorAssociativity = getOperatorAssociativity; function getExpressionPrecedence(expression) { var operator = getOperator(expression); - var hasArguments = expression.kind === 188 && expression.arguments !== undefined; + var hasArguments = expression.kind === 188 /* NewExpression */ && expression.arguments !== undefined; return getOperatorPrecedence(expression.kind, operator, hasArguments); } ts.getExpressionPrecedence = getExpressionPrecedence; function getOperator(expression) { - if (expression.kind === 200) { + if (expression.kind === 200 /* BinaryExpression */) { return expression.operatorToken.kind; } - else if (expression.kind === 198 || expression.kind === 199) { + else if (expression.kind === 198 /* PrefixUnaryExpression */ || expression.kind === 199 /* PostfixUnaryExpression */) { return expression.operator; } else { @@ -8979,122 +10050,125 @@ var ts; ts.getOperator = getOperator; function getOperatorPrecedence(nodeKind, operatorKind, hasArguments) { switch (nodeKind) { - case 303: + case 303 /* CommaListExpression */: return 0; - case 204: + case 204 /* SpreadElement */: return 1; - case 203: + case 203 /* YieldExpression */: return 2; - case 201: + case 201 /* ConditionalExpression */: return 4; - case 200: + case 200 /* BinaryExpression */: switch (operatorKind) { - case 26: + case 26 /* CommaToken */: return 0; - case 58: - case 59: - case 60: - case 62: - case 61: - case 63: - case 64: - case 65: - case 66: - case 67: - case 68: - case 70: - case 69: + case 58 /* EqualsToken */: + case 59 /* PlusEqualsToken */: + case 60 /* MinusEqualsToken */: + case 62 /* AsteriskAsteriskEqualsToken */: + case 61 /* AsteriskEqualsToken */: + case 63 /* SlashEqualsToken */: + case 64 /* PercentEqualsToken */: + case 65 /* LessThanLessThanEqualsToken */: + case 66 /* GreaterThanGreaterThanEqualsToken */: + case 67 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + case 68 /* AmpersandEqualsToken */: + case 70 /* CaretEqualsToken */: + case 69 /* BarEqualsToken */: return 3; default: return getBinaryOperatorPrecedence(operatorKind); } - case 198: - case 195: - case 196: - case 194: - case 197: + case 198 /* PrefixUnaryExpression */: + case 195 /* TypeOfExpression */: + case 196 /* VoidExpression */: + case 194 /* DeleteExpression */: + case 197 /* AwaitExpression */: return 16; - case 199: + case 199 /* PostfixUnaryExpression */: return 17; - case 187: + case 187 /* CallExpression */: return 18; - case 188: + case 188 /* NewExpression */: return hasArguments ? 19 : 18; - case 189: - case 185: - case 186: + case 189 /* TaggedTemplateExpression */: + case 185 /* PropertyAccessExpression */: + case 186 /* ElementAccessExpression */: return 19; - case 99: - case 97: - case 71: - case 95: - case 101: - case 86: - case 8: - case 9: - case 183: - case 184: - case 192: - case 193: - case 205: - case 255: - case 256: - case 259: - case 12: - case 13: - case 202: - case 191: - case 206: + case 99 /* ThisKeyword */: + case 97 /* SuperKeyword */: + case 71 /* Identifier */: + case 95 /* NullKeyword */: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: + case 183 /* ArrayLiteralExpression */: + case 184 /* ObjectLiteralExpression */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 205 /* ClassExpression */: + case 255 /* JsxElement */: + case 256 /* JsxSelfClosingElement */: + case 259 /* JsxFragment */: + case 12 /* RegularExpressionLiteral */: + case 13 /* NoSubstitutionTemplateLiteral */: + case 202 /* TemplateExpression */: + case 191 /* ParenthesizedExpression */: + case 206 /* OmittedExpression */: return 20; default: return -1; } } ts.getOperatorPrecedence = getOperatorPrecedence; + /* @internal */ function getBinaryOperatorPrecedence(kind) { switch (kind) { - case 54: + case 54 /* BarBarToken */: return 5; - case 53: + case 53 /* AmpersandAmpersandToken */: return 6; - case 49: + case 49 /* BarToken */: return 7; - case 50: + case 50 /* CaretToken */: return 8; - case 48: + case 48 /* AmpersandToken */: return 9; - case 32: - case 33: - case 34: - case 35: + case 32 /* EqualsEqualsToken */: + case 33 /* ExclamationEqualsToken */: + case 34 /* EqualsEqualsEqualsToken */: + case 35 /* ExclamationEqualsEqualsToken */: return 10; - case 27: - case 29: - case 30: - case 31: - case 93: - case 92: - case 118: + case 27 /* LessThanToken */: + case 29 /* GreaterThanToken */: + case 30 /* LessThanEqualsToken */: + case 31 /* GreaterThanEqualsToken */: + case 93 /* InstanceOfKeyword */: + case 92 /* InKeyword */: + case 118 /* AsKeyword */: return 11; - case 45: - case 46: - case 47: + case 45 /* LessThanLessThanToken */: + case 46 /* GreaterThanGreaterThanToken */: + case 47 /* GreaterThanGreaterThanGreaterThanToken */: return 12; - case 37: - case 38: + case 37 /* PlusToken */: + case 38 /* MinusToken */: return 13; - case 39: - case 41: - case 42: + case 39 /* AsteriskToken */: + case 41 /* SlashToken */: + case 42 /* PercentToken */: return 14; - case 40: + case 40 /* AsteriskAsteriskToken */: return 15; } + // -1 is lower than all other precedences. Returning it will cause binary expression + // parsing to stop. return -1; } ts.getBinaryOperatorPrecedence = getBinaryOperatorPrecedence; function createDiagnosticCollection() { - var nonFileDiagnostics = []; + var nonFileDiagnostics = []; // See GH#19873 var filesWithDiagnostics = []; var fileDiagnostics = ts.createMap(); var hasReadNonFileDiagnostics = false; @@ -9112,12 +10186,13 @@ var ts; if (diagnostic.file) { diagnostics = fileDiagnostics.get(diagnostic.file.fileName); if (!diagnostics) { - diagnostics = []; + diagnostics = []; // See GH#19873 fileDiagnostics.set(diagnostic.file.fileName, diagnostics); ts.insertSorted(filesWithDiagnostics, diagnostic.file.fileName, ts.compareStringsCaseSensitive); } } else { + // If we've already read the non-file diagnostics, do not modify the existing array. if (hasReadNonFileDiagnostics) { hasReadNonFileDiagnostics = false; nonFileDiagnostics = nonFileDiagnostics.slice(); @@ -9143,6 +10218,11 @@ var ts; } } ts.createDiagnosticCollection = createDiagnosticCollection; + // This consists of the first 19 unprintable ASCII characters, canonical escapes, lineSeparator, + // paragraphSeparator, and nextLine. The latter three are just desirable to suppress new lines in + // the language service. These characters should be escaped when printing, and if any characters are added, + // the map below must be updated. Note that this regexp *does not* include the 'delete' character. + // There is no reason for this other than that JSON.stringify does not handle it either. var doubleQuoteEscapedCharsRegExp = /[\\\"\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g; var singleQuoteEscapedCharsRegExp = /[\\\'\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g; var backtickQuoteEscapedCharsRegExp = /[\\\`\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g; @@ -9159,28 +10239,35 @@ var ts; "\`": "\\\`", "\u2028": "\\u2028", "\u2029": "\\u2029", - "\u0085": "\\u0085" + "\u0085": "\\u0085" // nextLine }); + /** + * Based heavily on the abstract 'Quote'/'QuoteJSONString' operation from ECMA-262 (24.3.2.2), + * but augmented for a few select characters (e.g. lineSeparator, paragraphSeparator, nextLine) + * Note that this doesn't actually wrap the input in double quotes. + */ function escapeString(s, quoteChar) { - var escapedCharsRegExp = quoteChar === 96 ? backtickQuoteEscapedCharsRegExp : - quoteChar === 39 ? singleQuoteEscapedCharsRegExp : + var escapedCharsRegExp = quoteChar === 96 /* backtick */ ? backtickQuoteEscapedCharsRegExp : + quoteChar === 39 /* singleQuote */ ? singleQuoteEscapedCharsRegExp : doubleQuoteEscapedCharsRegExp; return s.replace(escapedCharsRegExp, getReplacement); } ts.escapeString = escapeString; function getReplacement(c, offset, input) { - if (c.charCodeAt(0) === 0) { + if (c.charCodeAt(0) === 0 /* nullCharacter */) { var lookAhead = input.charCodeAt(offset + c.length); - if (lookAhead >= 48 && lookAhead <= 57) { + if (lookAhead >= 48 /* _0 */ && lookAhead <= 57 /* _9 */) { + // If the null character is followed by digits, print as a hex escape to prevent the result from parsing as an octal (which is forbidden in strict mode) return "\\x00"; } + // Otherwise, keep printing a literal \0 for the null character return "\\0"; } return escapedCharsMap.get(c) || get16BitUnicodeEscapeSequence(c.charCodeAt(0)); } function isIntrinsicJsxName(name) { var ch = name.charCodeAt(0); - return (ch >= 97 && ch <= 122) || name.indexOf("-") > -1; + return (ch >= 97 /* a */ && ch <= 122 /* z */) || name.indexOf("-") > -1; } ts.isIntrinsicJsxName = isIntrinsicJsxName; function get16BitUnicodeEscapeSequence(charCode) { @@ -9191,6 +10278,8 @@ var ts; var nonAsciiCharacters = /[^\u0000-\u007F]/g; function escapeNonAsciiString(s, quoteChar) { s = escapeString(s, quoteChar); + // Replace non-ASCII characters with '\uNNNN' escapes if any exist. + // Otherwise just return the original string. return nonAsciiCharacters.test(s) ? s.replace(nonAsciiCharacters, function (c) { return get16BitUnicodeEscapeSequence(c.charCodeAt(0)); }) : s; @@ -9309,11 +10398,14 @@ var ts; return getResolvedExternalModuleName(host, file); } ts.getExternalModuleNameFromDeclaration = getExternalModuleNameFromDeclaration; + /** + * Resolves a local path to a path which is absolute to the base of the emit + */ function getExternalModuleNameFromPath(host, fileName, referencePath) { var getCanonicalFileName = function (f) { return host.getCanonicalFileName(f); }; var dir = toPath(referencePath ? ts.getDirectoryPath(referencePath) : host.getCommonSourceDirectory(), host.getCurrentDirectory(), getCanonicalFileName); var filePath = ts.getNormalizedAbsolutePath(fileName, host.getCurrentDirectory()); - var relativePath = ts.getRelativePathToDirectoryOrUrl(dir, filePath, dir, getCanonicalFileName, false); + var relativePath = ts.getRelativePathToDirectoryOrUrl(dir, filePath, dir, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); var extensionless = ts.removeFileExtension(relativePath); return referencePath ? ts.ensurePathIsNonModuleName(extensionless) : extensionless; } @@ -9332,19 +10424,29 @@ var ts; ts.getOwnEmitOutputFilePath = getOwnEmitOutputFilePath; function getDeclarationEmitOutputFilePath(sourceFile, host) { var options = host.getCompilerOptions(); - var outputDir = options.declarationDir || options.outDir; + var outputDir = options.declarationDir || options.outDir; // Prefer declaration folder if specified var path = outputDir ? getSourceFilePathInNewDir(sourceFile, host, outputDir) : sourceFile.fileName; - return ts.removeFileExtension(path) + ".d.ts"; + return ts.removeFileExtension(path) + ".d.ts" /* Dts */; } ts.getDeclarationEmitOutputFilePath = getDeclarationEmitOutputFilePath; + /** + * Gets the source files that are expected to have an emit output. + * + * Originally part of `forEachExpectedEmitFile`, this functionality was extracted to support + * transformations. + * + * @param host An EmitHost. + * @param targetSourceFile An optional target source file to emit. + */ function getSourceFilesToEmit(host, targetSourceFile) { var options = host.getCompilerOptions(); var isSourceFileFromExternalLibrary = function (file) { return host.isSourceFileFromExternalLibrary(file); }; if (options.outFile || options.out) { var moduleKind = ts.getEmitModuleKind(options); var moduleEmitEnabled_1 = moduleKind === ts.ModuleKind.AMD || moduleKind === ts.ModuleKind.System; + // Can emit only sources that are not declaration file and are either non module code or module with --module or --target es6 specified return ts.filter(host.getSourceFiles(), function (sourceFile) { return (moduleEmitEnabled_1 || !ts.isExternalModule(sourceFile)) && sourceFileMayBeEmitted(sourceFile, options, isSourceFileFromExternalLibrary); }); @@ -9355,6 +10457,7 @@ var ts; } } ts.getSourceFilesToEmit = getSourceFilesToEmit; + /** Don't call this for `--outFile`, just for `--outDir` or plain emit. `--outFile` needs additional checks. */ function sourceFileMayBeEmitted(sourceFile, options, isSourceFileFromExternalLibrary) { return !(options.noEmitForJsFiles && isSourceFileJavaScript(sourceFile)) && !sourceFile.isDeclarationFile && !isSourceFileFromExternalLibrary(sourceFile); } @@ -9391,12 +10494,14 @@ var ts; return accessor.parameters[hasThis ? 1 : 0]; } } + /** Get the type annotation for the value parameter. */ function getSetAccessorTypeAnnotationNode(accessor) { var parameter = getSetAccessorValueParameter(accessor); return parameter && parameter.type; } ts.getSetAccessorTypeAnnotationNode = getSetAccessorTypeAnnotationNode; function getThisParameter(signature) { + // callback tags do not currently support this parameters if (signature.parameters.length && !ts.isJSDocSignature(signature)) { var thisParameter = signature.parameters[0]; if (parameterIsThisKeyword(thisParameter)) { @@ -9410,24 +10515,25 @@ var ts; } ts.parameterIsThisKeyword = parameterIsThisKeyword; function isThisIdentifier(node) { - return !!node && node.kind === 71 && identifierIsThisKeyword(node); + return !!node && node.kind === 71 /* Identifier */ && identifierIsThisKeyword(node); } ts.isThisIdentifier = isThisIdentifier; function identifierIsThisKeyword(id) { - return id.originalKeywordKind === 99; + return id.originalKeywordKind === 99 /* ThisKeyword */; } ts.identifierIsThisKeyword = identifierIsThisKeyword; function getAllAccessorDeclarations(declarations, accessor) { + // TODO: GH#18217 var firstAccessor; var secondAccessor; var getAccessor; var setAccessor; if (hasDynamicName(accessor)) { firstAccessor = accessor; - if (accessor.kind === 156) { + if (accessor.kind === 156 /* GetAccessor */) { getAccessor = accessor; } - else if (accessor.kind === 157) { + else if (accessor.kind === 157 /* SetAccessor */) { setAccessor = accessor; } else { @@ -9436,8 +10542,8 @@ var ts; } else { ts.forEach(declarations, function (member) { - if ((member.kind === 156 || member.kind === 157) - && hasModifier(member, 32) === hasModifier(accessor, 32)) { + if ((member.kind === 156 /* GetAccessor */ || member.kind === 157 /* SetAccessor */) + && hasModifier(member, 32 /* Static */) === hasModifier(accessor, 32 /* Static */)) { var memberName = getPropertyNameForPropertyNameNode(member.name); var accessorName = getPropertyNameForPropertyNameNode(accessor.name); if (memberName === accessorName) { @@ -9447,10 +10553,10 @@ var ts; else if (!secondAccessor) { secondAccessor = member; } - if (member.kind === 156 && !getAccessor) { + if (member.kind === 156 /* GetAccessor */ && !getAccessor) { getAccessor = member; } - if (member.kind === 157 && !setAccessor) { + if (member.kind === 157 /* SetAccessor */ && !setAccessor) { setAccessor = member; } } @@ -9465,6 +10571,10 @@ var ts; }; } ts.getAllAccessorDeclarations = getAllAccessorDeclarations; + /** + * Gets the effective type annotation of a variable, parameter, or property. If the node was + * parsed in a JavaScript file, gets the type annotation from JSDoc. + */ function getEffectiveTypeAnnotationNode(node) { return node.type || (isInJavaScriptFile(node) ? ts.getJSDocType(node) : undefined); } @@ -9473,6 +10583,10 @@ var ts; return node.type; } ts.getTypeAnnotationNode = getTypeAnnotationNode; + /** + * Gets the effective return type annotation of a signature. If the node was parsed in a + * JavaScript file, gets the return type annotation from JSDoc. + */ function getEffectiveReturnTypeNode(node) { if (ts.isJSDocSignature(node)) { return node.type && node.type.typeExpression && node.type.typeExpression.type; @@ -9480,12 +10594,16 @@ var ts; return node.type || (isInJavaScriptFile(node) ? ts.getJSDocReturnType(node) : undefined); } ts.getEffectiveReturnTypeNode = getEffectiveReturnTypeNode; + /** + * Gets the effective type parameters. If the node was parsed in a + * JavaScript file, gets the type parameters from the `@template` tag from JSDoc. + */ function getEffectiveTypeParameterDeclarations(node) { if (ts.isJSDocSignature(node)) { return ts.emptyArray; } if (isJSDocTypeAlias(node)) { - ts.Debug.assert(node.parent.kind === 286); + ts.Debug.assert(node.parent.kind === 286 /* JSDocComment */); return ts.flatMap(node.parent.tags, function (tag) { return ts.isJSDocTemplateTag(tag) ? tag.typeParameters : undefined; }); } return node.typeParameters || (isInJavaScriptFile(node) ? getJSDocTypeParameterDeclarations(node) : ts.emptyArray); @@ -9495,9 +10613,14 @@ var ts; return ts.flatMap(ts.getJSDocTags(node), function (tag) { return isNonTypeAliasTemplate(tag) ? tag.typeParameters : undefined; }); } ts.getJSDocTypeParameterDeclarations = getJSDocTypeParameterDeclarations; + /** template tags are only available when a typedef isn't already using them */ function isNonTypeAliasTemplate(tag) { - return ts.isJSDocTemplateTag(tag) && !(tag.parent.kind === 286 && tag.parent.tags.some(isJSDocTypeAlias)); + return ts.isJSDocTemplateTag(tag) && !(tag.parent.kind === 286 /* JSDocComment */ && tag.parent.tags.some(isJSDocTypeAlias)); } + /** + * Gets the effective type annotation of the value parameter of a set accessor. If the node + * was parsed in a JavaScript file, gets the type annotation from JSDoc. + */ function getEffectiveSetAccessorTypeAnnotationNode(node) { var parameter = getSetAccessorValueParameter(node); return parameter && getEffectiveTypeAnnotationNode(parameter); @@ -9508,6 +10631,7 @@ var ts; } ts.emitNewLineBeforeLeadingComments = emitNewLineBeforeLeadingComments; function emitNewLineBeforeLeadingCommentsOfPosition(lineMap, writer, pos, leadingComments) { + // If the leading comments start on different line than the start of node, write new line if (leadingComments && leadingComments.length && pos !== leadingComments[0].pos && getLineOfLocalPositionFromLineMap(lineMap, pos) !== getLineOfLocalPositionFromLineMap(lineMap, leadingComments[0].pos)) { writer.writeLine(); @@ -9515,6 +10639,7 @@ var ts; } ts.emitNewLineBeforeLeadingCommentsOfPosition = emitNewLineBeforeLeadingCommentsOfPosition; function emitNewLineBeforeLeadingCommentOfPosition(lineMap, writer, pos, commentPos) { + // If the leading comments start on different line than the start of node, write new line if (pos !== commentPos && getLineOfLocalPositionFromLineMap(lineMap, pos) !== getLineOfLocalPositionFromLineMap(lineMap, commentPos)) { writer.writeLine(); @@ -9547,15 +10672,25 @@ var ts; } } ts.emitComments = emitComments; + /** + * Detached comment is a comment at the top of file or function body that is separated from + * the next statement by space. + */ function emitDetachedComments(text, lineMap, writer, writeComment, node, newLine, removeComments) { var leadingComments; var currentDetachedCommentInfo; if (removeComments) { + // removeComments is true, only reserve pinned comment at the top of file + // For example: + // /*! Pinned Comment */ + // + // var x = 10; if (node.pos === 0) { leadingComments = ts.filter(ts.getLeadingCommentRanges(text, node.pos), isPinnedCommentLocal); } } else { + // removeComments is false, just get detached as normal and bypass the process to filter comment leadingComments = ts.getLeadingCommentRanges(text, node.pos); } if (leadingComments) { @@ -9567,6 +10702,9 @@ var ts; var lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, lastComment.end); var commentLine = getLineOfLocalPositionFromLineMap(lineMap, comment.pos); if (commentLine >= lastCommentLine + 2) { + // There was a blank line between the last comment and this comment. This + // comment is not part of the copyright comments. Return what we have so + // far. break; } } @@ -9574,11 +10712,15 @@ var ts; lastComment = comment; } if (detachedComments.length) { + // All comments look like they could have been part of the copyright header. Make + // sure there is at least one blank line between it and the node. If not, it's not + // a copyright header. var lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, ts.last(detachedComments).end); var nodeLine = getLineOfLocalPositionFromLineMap(lineMap, ts.skipTrivia(text, node.pos)); if (nodeLine >= lastCommentLine + 2) { + // Valid detachedComments emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments); - emitComments(text, lineMap, writer, detachedComments, false, true, newLine, writeComment); + emitComments(text, lineMap, writer, detachedComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment); currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: ts.last(detachedComments).end }; } } @@ -9590,7 +10732,7 @@ var ts; } ts.emitDetachedComments = emitDetachedComments; function writeCommentRange(text, lineMap, writer, commentPos, commentEnd, newLine) { - if (text.charCodeAt(commentPos + 1) === 42) { + if (text.charCodeAt(commentPos + 1) === 42 /* asterisk */) { var firstCommentLineAndCharacter = ts.computeLineAndCharacterOfPosition(lineMap, commentPos); var lineCount = lineMap.length; var firstCommentLineIndent = void 0; @@ -9599,29 +10741,50 @@ var ts; ? text.length + 1 : lineMap[currentLine + 1]; if (pos !== commentPos) { + // If we are not emitting first line, we need to write the spaces to adjust the alignment if (firstCommentLineIndent === undefined) { firstCommentLineIndent = calculateIndent(text, lineMap[firstCommentLineAndCharacter.line], commentPos); } + // These are number of spaces writer is going to write at current indent var currentWriterIndentSpacing = writer.getIndent() * getIndentSize(); + // Number of spaces we want to be writing + // eg: Assume writer indent + // module m { + // /* starts at character 9 this is line 1 + // * starts at character pos 4 line --1 = 8 - 8 + 3 + // More left indented comment */ --2 = 8 - 8 + 2 + // class c { } + // } + // module m { + // /* this is line 1 -- Assume current writer indent 8 + // * line --3 = 8 - 4 + 5 + // More right indented comment */ --4 = 8 - 4 + 11 + // class c { } + // } var spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(text, pos, nextLineStart); if (spacesToEmit > 0) { var numberOfSingleSpacesToEmit = spacesToEmit % getIndentSize(); var indentSizeSpaceString = getIndentString((spacesToEmit - numberOfSingleSpacesToEmit) / getIndentSize()); + // Write indent size string ( in eg 1: = "", 2: "" , 3: string with 8 spaces 4: string with 12 spaces writer.rawWrite(indentSizeSpaceString); + // Emit the single spaces (in eg: 1: 3 spaces, 2: 2 spaces, 3: 1 space, 4: 3 spaces) while (numberOfSingleSpacesToEmit) { writer.rawWrite(" "); numberOfSingleSpacesToEmit--; } } else { + // No spaces to emit write empty string writer.rawWrite(""); } } + // Write the comment line text writeTrimmedCurrentLine(text, commentEnd, writer, newLine, pos, nextLineStart); pos = nextLineStart; } } else { + // Single line comment of style //.... writer.write(text.substring(commentPos, commentEnd)); } } @@ -9630,29 +10793,33 @@ var ts; var end = Math.min(commentEnd, nextLineStart - 1); var currentLineText = text.substring(pos, end).replace(/^\s+|\s+$/g, ""); if (currentLineText) { + // trimmed forward and ending spaces text writer.write(currentLineText); if (end !== commentEnd) { writer.writeLine(); } } else { + // Empty string - make sure we write empty line writer.writeLiteral(newLine); } } function calculateIndent(text, pos, end) { var currentLineIndent = 0; for (; pos < end && ts.isWhiteSpaceSingleLine(text.charCodeAt(pos)); pos++) { - if (text.charCodeAt(pos) === 9) { + if (text.charCodeAt(pos) === 9 /* tab */) { + // Tabs = TabSize = indent size and go to next tabStop currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize()); } else { + // Single space currentLineIndent++; } } return currentLineIndent; } function hasModifiers(node) { - return getModifierFlags(node) !== 0; + return getModifierFlags(node) !== 0 /* None */; } ts.hasModifiers = hasModifiers; function hasModifier(node, flags) { @@ -9660,11 +10827,11 @@ var ts; } ts.hasModifier = hasModifier; function hasStaticModifier(node) { - return hasModifier(node, 32); + return hasModifier(node, 32 /* Static */); } ts.hasStaticModifier = hasStaticModifier; function hasReadonlyModifier(node) { - return hasModifier(node, 64); + return hasModifier(node, 64 /* Readonly */); } ts.hasReadonlyModifier = hasReadonlyModifier; function getSelectedModifierFlags(node, flags) { @@ -9672,58 +10839,59 @@ var ts; } ts.getSelectedModifierFlags = getSelectedModifierFlags; function getModifierFlags(node) { - if (node.modifierFlagsCache & 536870912) { - return node.modifierFlagsCache & ~536870912; + if (node.modifierFlagsCache & 536870912 /* HasComputedFlags */) { + return node.modifierFlagsCache & ~536870912 /* HasComputedFlags */; } var flags = getModifierFlagsNoCache(node); - node.modifierFlagsCache = flags | 536870912; + node.modifierFlagsCache = flags | 536870912 /* HasComputedFlags */; return flags; } ts.getModifierFlags = getModifierFlags; function getModifierFlagsNoCache(node) { - var flags = 0; + var flags = 0 /* None */; if (node.modifiers) { for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { var modifier = _a[_i]; flags |= modifierToFlag(modifier.kind); } } - if (node.flags & 4 || (node.kind === 71 && node.isInJSDocNamespace)) { - flags |= 1; + if (node.flags & 4 /* NestedNamespace */ || (node.kind === 71 /* Identifier */ && node.isInJSDocNamespace)) { + flags |= 1 /* Export */; } return flags; } ts.getModifierFlagsNoCache = getModifierFlagsNoCache; function modifierToFlag(token) { switch (token) { - case 115: return 32; - case 114: return 4; - case 113: return 16; - case 112: return 8; - case 117: return 128; - case 84: return 1; - case 124: return 2; - case 76: return 2048; - case 79: return 512; - case 120: return 256; - case 132: return 64; + case 115 /* StaticKeyword */: return 32 /* Static */; + case 114 /* PublicKeyword */: return 4 /* Public */; + case 113 /* ProtectedKeyword */: return 16 /* Protected */; + case 112 /* PrivateKeyword */: return 8 /* Private */; + case 117 /* AbstractKeyword */: return 128 /* Abstract */; + case 84 /* ExportKeyword */: return 1 /* Export */; + case 124 /* DeclareKeyword */: return 2 /* Ambient */; + case 76 /* ConstKeyword */: return 2048 /* Const */; + case 79 /* DefaultKeyword */: return 512 /* Default */; + case 120 /* AsyncKeyword */: return 256 /* Async */; + case 132 /* ReadonlyKeyword */: return 64 /* Readonly */; } - return 0; + return 0 /* None */; } ts.modifierToFlag = modifierToFlag; function isLogicalOperator(token) { - return token === 54 - || token === 53 - || token === 51; + return token === 54 /* BarBarToken */ + || token === 53 /* AmpersandAmpersandToken */ + || token === 51 /* ExclamationToken */; } ts.isLogicalOperator = isLogicalOperator; function isAssignmentOperator(token) { - return token >= 58 && token <= 70; + return token >= 58 /* FirstAssignment */ && token <= 70 /* LastAssignment */; } ts.isAssignmentOperator = isAssignmentOperator; + /** Get `C` given `N` if `N` is in the position `class C extends N` where `N` is an ExpressionWithTypeArguments. */ function tryGetClassExtendingExpressionWithTypeArguments(node) { if (ts.isExpressionWithTypeArguments(node) && - node.parent.token === 85 && + node.parent.token === 85 /* ExtendsKeyword */ && ts.isClassLike(node.parent.parent)) { return node.parent.parent; } @@ -9732,16 +10900,16 @@ var ts; function isAssignmentExpression(node, excludeCompoundAssignment) { return ts.isBinaryExpression(node) && (excludeCompoundAssignment - ? node.operatorToken.kind === 58 + ? node.operatorToken.kind === 58 /* EqualsToken */ : isAssignmentOperator(node.operatorToken.kind)) && ts.isLeftHandSideExpression(node.left); } ts.isAssignmentExpression = isAssignmentExpression; function isDestructuringAssignment(node) { - if (isAssignmentExpression(node, true)) { + if (isAssignmentExpression(node, /*excludeCompoundAssignment*/ true)) { var kind = node.left.kind; - return kind === 184 - || kind === 183; + return kind === 184 /* ObjectLiteralExpression */ + || kind === 183 /* ArrayLiteralExpression */; } return false; } @@ -9751,16 +10919,16 @@ var ts; } ts.isExpressionWithTypeArgumentsInClassExtendsClause = isExpressionWithTypeArgumentsInClassExtendsClause; function isExpressionWithTypeArgumentsInClassImplementsClause(node) { - return node.kind === 207 + return node.kind === 207 /* ExpressionWithTypeArguments */ && isEntityNameExpression(node.expression) && node.parent - && node.parent.token === 108 + && node.parent.token === 108 /* ImplementsKeyword */ && node.parent.parent && ts.isClassLike(node.parent.parent); } ts.isExpressionWithTypeArgumentsInClassImplementsClause = isExpressionWithTypeArgumentsInClassImplementsClause; function isEntityNameExpression(node) { - return node.kind === 71 || isPropertyAccessEntityNameExpression(node); + return node.kind === 71 /* Identifier */ || isPropertyAccessEntityNameExpression(node); } ts.isEntityNameExpression = isEntityNameExpression; function isPropertyAccessEntityNameExpression(node) { @@ -9772,17 +10940,17 @@ var ts; } ts.isPrototypeAccess = isPrototypeAccess; function isRightSideOfQualifiedNameOrPropertyAccess(node) { - return (node.parent.kind === 146 && node.parent.right === node) || - (node.parent.kind === 185 && node.parent.name === node); + return (node.parent.kind === 146 /* QualifiedName */ && node.parent.right === node) || + (node.parent.kind === 185 /* PropertyAccessExpression */ && node.parent.name === node); } ts.isRightSideOfQualifiedNameOrPropertyAccess = isRightSideOfQualifiedNameOrPropertyAccess; function isEmptyObjectLiteral(expression) { - return expression.kind === 184 && + return expression.kind === 184 /* ObjectLiteralExpression */ && expression.properties.length === 0; } ts.isEmptyObjectLiteral = isEmptyObjectLiteral; function isEmptyArrayLiteral(expression) { - return expression.kind === 183 && + return expression.kind === 183 /* ArrayLiteralExpression */ && expression.elements.length === 0; } ts.isEmptyArrayLiteral = isEmptyArrayLiteral; @@ -9791,17 +10959,23 @@ var ts; } ts.getLocalSymbolForExportDefault = getLocalSymbolForExportDefault; function isExportDefaultSymbol(symbol) { - return symbol && ts.length(symbol.declarations) > 0 && hasModifier(symbol.declarations[0], 512); + return symbol && ts.length(symbol.declarations) > 0 && hasModifier(symbol.declarations[0], 512 /* Default */); } + /** Return ".ts", ".d.ts", or ".tsx", if that is the extension. */ function tryExtractTypeScriptExtension(fileName) { return ts.find(ts.supportedTypescriptExtensionsForExtractExtension, function (extension) { return ts.fileExtensionIs(fileName, extension); }); } ts.tryExtractTypeScriptExtension = tryExtractTypeScriptExtension; + /** + * Replace each instance of non-ascii characters by one, two, three, or four escape sequences + * representing the UTF-8 encoding of the character, and return the expanded char code list. + */ function getExpandedCharCodes(input) { var output = []; var length = input.length; for (var i = 0; i < length; i++) { var charCode = input.charCodeAt(i); + // handle utf8 if (charCode < 0x80) { output.push(charCode); } @@ -9827,6 +11001,9 @@ var ts; return output; } var base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + /** + * Converts a string to a base-64 encoded ASCII string. + */ function convertToBase64(input) { var result = ""; var charCodes = getExpandedCharCodes(input); @@ -9834,16 +11011,21 @@ var ts; var length = charCodes.length; var byte1, byte2, byte3, byte4; while (i < length) { + // Convert every 6-bits in the input 3 character points + // into a base64 digit byte1 = charCodes[i] >> 2; byte2 = (charCodes[i] & 3) << 4 | charCodes[i + 1] >> 4; byte3 = (charCodes[i + 1] & 15) << 2 | charCodes[i + 2] >> 6; byte4 = charCodes[i + 2] & 63; + // We are out of characters in the input, set the extra + // digits to 64 (padding character). if (i + 1 >= length) { byte3 = byte4 = 64; } else if (i + 2 >= length) { byte4 = 64; } + // Write to the output result += base64Digits.charAt(byte1) + base64Digits.charAt(byte2) + base64Digits.charAt(byte3) + base64Digits.charAt(byte4); i += 3; } @@ -9869,9 +11051,12 @@ var ts; i++; nextCode = codes[i]; } + // `value` may be greater than 10FFFF (the maximum unicode codepoint) - JS will just make this into an invalid character for us output += String.fromCharCode(value); } else { + // We don't want to kill the process when decoding fails (due to a following char byte not + // following a leading char), so we just print the (bad) value output += String.fromCharCode(charCode); i++; } @@ -9893,9 +11078,11 @@ var ts; var expandedCharCodes = []; var i = 0; while (i < length) { + // Stop decoding once padding characters are present if (input.charCodeAt(i) === base64Digits.charCodeAt(64)) { break; } + // convert 4 input digits into three characters, ignoring padding characters at the end var ch1 = base64Digits.indexOf(input[i]); var ch2 = base64Digits.indexOf(input[i + 1]); var ch3 = base64Digits.indexOf(input[i + 2]); @@ -9903,10 +11090,10 @@ var ts; var code1 = ((ch1 & 63) << 2) | ((ch2 >> 4) & 3); var code2 = ((ch2 & 15) << 4) | ((ch3 >> 2) & 15); var code3 = ((ch3 & 3) << 6) | (ch4 & 63); - if (code2 === 0 && ch3 !== 0) { + if (code2 === 0 && ch3 !== 0) { // code2 decoded to zero, but ch3 was padding - elide code2 and code3 expandedCharCodes.push(code1); } - else if (code3 === 0 && ch4 !== 0) { + else if (code3 === 0 && ch4 !== 0) { // code3 decoded to zero, but ch4 was padding, elide code3 expandedCharCodes.push(code1, code2); } else { @@ -9921,14 +11108,17 @@ var ts; var lineFeed = "\n"; function getNewLineCharacter(options, getNewLine) { switch (options.newLine) { - case 0: + case 0 /* CarriageReturnLineFeed */: return carriageReturnLineFeed; - case 1: + case 1 /* LineFeed */: return lineFeed; } return getNewLine ? getNewLine() : ts.sys ? ts.sys.newLine : carriageReturnLineFeed; } ts.getNewLineCharacter = getNewLineCharacter; + /** + * Formats an enum value as a string for debugging and debug assertions. + */ function formatEnum(value, enumObject, isFlags) { if (value === void 0) { value = 0; } var members = getEnumMembers(enumObject); @@ -9970,61 +11160,96 @@ var ts; return ts.stableSort(result, function (x, y) { return ts.compareValues(x[0], y[0]); }); } function formatSyntaxKind(kind) { - return formatEnum(kind, ts.SyntaxKind, false); + return formatEnum(kind, ts.SyntaxKind, /*isFlags*/ false); } ts.formatSyntaxKind = formatSyntaxKind; function formatModifierFlags(flags) { - return formatEnum(flags, ts.ModifierFlags, true); + return formatEnum(flags, ts.ModifierFlags, /*isFlags*/ true); } ts.formatModifierFlags = formatModifierFlags; function formatTransformFlags(flags) { - return formatEnum(flags, ts.TransformFlags, true); + return formatEnum(flags, ts.TransformFlags, /*isFlags*/ true); } ts.formatTransformFlags = formatTransformFlags; function formatEmitFlags(flags) { - return formatEnum(flags, ts.EmitFlags, true); + return formatEnum(flags, ts.EmitFlags, /*isFlags*/ true); } ts.formatEmitFlags = formatEmitFlags; function formatSymbolFlags(flags) { - return formatEnum(flags, ts.SymbolFlags, true); + return formatEnum(flags, ts.SymbolFlags, /*isFlags*/ true); } ts.formatSymbolFlags = formatSymbolFlags; function formatTypeFlags(flags) { - return formatEnum(flags, ts.TypeFlags, true); + return formatEnum(flags, ts.TypeFlags, /*isFlags*/ true); } ts.formatTypeFlags = formatTypeFlags; function formatObjectFlags(flags) { - return formatEnum(flags, ts.ObjectFlags, true); + return formatEnum(flags, ts.ObjectFlags, /*isFlags*/ true); } ts.formatObjectFlags = formatObjectFlags; + /** + * Creates a new TextRange from the provided pos and end. + * + * @param pos The start position. + * @param end The end position. + */ function createRange(pos, end) { return { pos: pos, end: end }; } ts.createRange = createRange; + /** + * Creates a new TextRange from a provided range with a new end position. + * + * @param range A TextRange. + * @param end The new end position. + */ function moveRangeEnd(range, end) { return createRange(range.pos, end); } ts.moveRangeEnd = moveRangeEnd; + /** + * Creates a new TextRange from a provided range with a new start position. + * + * @param range A TextRange. + * @param pos The new Start position. + */ function moveRangePos(range, pos) { return createRange(pos, range.end); } ts.moveRangePos = moveRangePos; + /** + * Moves the start position of a range past any decorators. + */ function moveRangePastDecorators(node) { return node.decorators && node.decorators.length > 0 ? moveRangePos(node, node.decorators.end) : node; } ts.moveRangePastDecorators = moveRangePastDecorators; + /** + * Moves the start position of a range past any decorators or modifiers. + */ function moveRangePastModifiers(node) { return node.modifiers && node.modifiers.length > 0 ? moveRangePos(node, node.modifiers.end) : moveRangePastDecorators(node); } ts.moveRangePastModifiers = moveRangePastModifiers; + /** + * Determines whether a TextRange has the same start and end positions. + * + * @param range A TextRange. + */ function isCollapsedRange(range) { return range.pos === range.end; } ts.isCollapsedRange = isCollapsedRange; + /** + * Creates a new TextRange for a token at the provides start position. + * + * @param pos The start position. + * @param token The token. + */ function createTokenRange(pos, token) { return createRange(pos, pos + ts.tokenToString(token).length); } @@ -10058,12 +11283,16 @@ var ts; return ts.positionIsSynthesized(range.pos) ? -1 : ts.skipTrivia(sourceFile.text, range.pos); } ts.getStartPositionOfRange = getStartPositionOfRange; + /** + * Determines whether a name was originally the declaration name of an enum or namespace + * declaration. + */ function isDeclarationNameOfEnumOrNamespace(node) { var parseNode = ts.getParseTreeNode(node); if (parseNode) { switch (parseNode.parent.kind) { - case 238: - case 239: + case 238 /* EnumDeclaration */: + case 239 /* ModuleDeclaration */: return parseNode === parseNode.parent.name; } } @@ -10078,6 +11307,7 @@ var ts; return node.initializer !== undefined; } function isWatchSet(options) { + // Firefox has Object.prototype.watch return options.watch && options.hasOwnProperty("watch"); } ts.isWatchSet = isWatchSet; @@ -10086,69 +11316,74 @@ var ts; } ts.closeFileWatcher = closeFileWatcher; function getCheckFlags(symbol) { - return symbol.flags & 33554432 ? symbol.checkFlags : 0; + return symbol.flags & 33554432 /* Transient */ ? symbol.checkFlags : 0; } ts.getCheckFlags = getCheckFlags; function getDeclarationModifierFlagsFromSymbol(s) { if (s.valueDeclaration) { var flags = ts.getCombinedModifierFlags(s.valueDeclaration); - return s.parent && s.parent.flags & 32 ? flags : flags & ~28; + return s.parent && s.parent.flags & 32 /* Class */ ? flags : flags & ~28 /* AccessibilityModifier */; } - if (getCheckFlags(s) & 6) { + if (getCheckFlags(s) & 6 /* Synthetic */) { var checkFlags = s.checkFlags; - var accessModifier = checkFlags & 256 ? 8 : - checkFlags & 64 ? 4 : - 16; - var staticModifier = checkFlags & 512 ? 32 : 0; + var accessModifier = checkFlags & 256 /* ContainsPrivate */ ? 8 /* Private */ : + checkFlags & 64 /* ContainsPublic */ ? 4 /* Public */ : + 16 /* Protected */; + var staticModifier = checkFlags & 512 /* ContainsStatic */ ? 32 /* Static */ : 0; return accessModifier | staticModifier; } - if (s.flags & 4194304) { - return 4 | 32; + if (s.flags & 4194304 /* Prototype */) { + return 4 /* Public */ | 32 /* Static */; } return 0; } ts.getDeclarationModifierFlagsFromSymbol = getDeclarationModifierFlagsFromSymbol; function skipAlias(symbol, checker) { - return symbol.flags & 2097152 ? checker.getAliasedSymbol(symbol) : symbol; + return symbol.flags & 2097152 /* Alias */ ? checker.getAliasedSymbol(symbol) : symbol; } ts.skipAlias = skipAlias; + /** See comment on `declareModuleMember` in `binder.ts`. */ function getCombinedLocalAndExportSymbolFlags(symbol) { return symbol.exportSymbol ? symbol.exportSymbol.flags | symbol.flags : symbol.flags; } ts.getCombinedLocalAndExportSymbolFlags = getCombinedLocalAndExportSymbolFlags; function isWriteOnlyAccess(node) { - return accessKind(node) === 1; + return accessKind(node) === 1 /* Write */; } ts.isWriteOnlyAccess = isWriteOnlyAccess; function isWriteAccess(node) { - return accessKind(node) !== 0; + return accessKind(node) !== 0 /* Read */; } ts.isWriteAccess = isWriteAccess; var AccessKind; (function (AccessKind) { + /** Only reads from a variable. */ AccessKind[AccessKind["Read"] = 0] = "Read"; + /** Only writes to a variable without using the result. E.g.: `x++;`. */ AccessKind[AccessKind["Write"] = 1] = "Write"; + /** Writes to a variable and uses the result as an expression. E.g.: `f(x++);`. */ AccessKind[AccessKind["ReadWrite"] = 2] = "ReadWrite"; })(AccessKind || (AccessKind = {})); function accessKind(node) { var parent = node.parent; if (!parent) - return 0; + return 0 /* Read */; switch (parent.kind) { - case 199: - case 198: + case 199 /* PostfixUnaryExpression */: + case 198 /* PrefixUnaryExpression */: var operator = parent.operator; - return operator === 43 || operator === 44 ? writeOrReadWrite() : 0; - case 200: + return operator === 43 /* PlusPlusToken */ || operator === 44 /* MinusMinusToken */ ? writeOrReadWrite() : 0 /* Read */; + case 200 /* BinaryExpression */: var _a = parent, left = _a.left, operatorToken = _a.operatorToken; - return left === node && isAssignmentOperator(operatorToken.kind) ? writeOrReadWrite() : 0; - case 185: - return parent.name !== node ? 0 : accessKind(parent); + return left === node && isAssignmentOperator(operatorToken.kind) ? writeOrReadWrite() : 0 /* Read */; + case 185 /* PropertyAccessExpression */: + return parent.name !== node ? 0 /* Read */ : accessKind(parent); default: - return 0; + return 0 /* Read */; } function writeOrReadWrite() { - return parent.parent && parent.parent.kind === 216 ? 1 : 2; + // If grandparent is not an ExpressionStatement, this is used as an expression in addition to having a side effect. + return parent.parent && parent.parent.kind === 216 /* ExpressionStatement */ ? 1 /* Write */ : 2 /* ReadWrite */; } } function compareDataObjects(dst, src) { @@ -10170,30 +11405,43 @@ var ts; return true; } ts.compareDataObjects = compareDataObjects; + /** + * clears already present map by calling onDeleteExistingValue callback before deleting that key/value + */ function clearMap(map, onDeleteValue) { + // Remove all map.forEach(onDeleteValue); map.clear(); } ts.clearMap = clearMap; + /** + * Mutates the map with newMap such that keys in map will be same as newMap. + */ function mutateMap(map, newMap, options) { var createNewValue = options.createNewValue, onDeleteValue = options.onDeleteValue, onExistingValue = options.onExistingValue; + // Needs update map.forEach(function (existingValue, key) { var valueInNewMap = newMap.get(key); + // Not present any more in new map, remove it if (valueInNewMap === undefined) { map.delete(key); onDeleteValue(existingValue, key); } + // If present notify about existing values else if (onExistingValue) { onExistingValue(existingValue, valueInNewMap, key); } }); + // Add new values that are not already present newMap.forEach(function (valueInNewMap, key) { if (!map.has(key)) { + // New values map.set(key, createNewValue(key, valueInNewMap)); } }); } ts.mutateMap = mutateMap; + /** Calls `callback` on `directory` and every ancestor directory it has, returning the first defined result. */ function forEachAncestorDirectory(directory, callback) { while (true) { var result = callback(directory); @@ -10208,14 +11456,15 @@ var ts; } } ts.forEachAncestorDirectory = forEachAncestorDirectory; + // Return true if the given type is the constructor type for an abstract class function isAbstractConstructorType(type) { - return !!(getObjectFlags(type) & 16) && !!type.symbol && isAbstractConstructorSymbol(type.symbol); + return !!(getObjectFlags(type) & 16 /* Anonymous */) && !!type.symbol && isAbstractConstructorSymbol(type.symbol); } ts.isAbstractConstructorType = isAbstractConstructorType; function isAbstractConstructorSymbol(symbol) { - if (symbol.flags & 32) { + if (symbol.flags & 32 /* Class */) { var declaration = getClassLikeDeclarationOfSymbol(symbol); - return !!declaration && hasModifier(declaration, 128); + return !!declaration && hasModifier(declaration, 128 /* Abstract */); } return false; } @@ -10225,11 +11474,11 @@ var ts; } ts.getClassLikeDeclarationOfSymbol = getClassLikeDeclarationOfSymbol; function getObjectFlags(type) { - return type.flags & 131072 ? type.objectFlags : 0; + return type.flags & 131072 /* Object */ ? type.objectFlags : 0; } ts.getObjectFlags = getObjectFlags; function typeHasCallOrConstructSignatures(type, checker) { - return checker.getSignaturesOfType(type, 0).length !== 0 || checker.getSignaturesOfType(type, 1).length !== 0; + return checker.getSignaturesOfType(type, 0 /* Call */).length !== 0 || checker.getSignaturesOfType(type, 1 /* Construct */).length !== 0; } ts.typeHasCallOrConstructSignatures = typeHasCallOrConstructSignatures; function forSomeAncestorDirectory(directory, callback) { @@ -10251,6 +11500,7 @@ var ts; if (nodeIsPresent(child)) lastChild = child; }, function (children) { + // As an optimization, jump straight to the end of the list. for (var i = children.length - 1; i >= 0; i--) { if (nodeIsPresent(children[i])) { lastChild = children[i]; @@ -10279,16 +11529,16 @@ var ts; (function (ts) { function getDefaultLibFileName(options) { switch (options.target) { - case 6: + case 6 /* ESNext */: return "lib.esnext.full.d.ts"; - case 5: + case 5 /* ES2018 */: return "lib.es2018.full.d.ts"; - case 4: + case 4 /* ES2017 */: return "lib.es2017.full.d.ts"; - case 3: + case 3 /* ES2016 */: return "lib.es2016.full.d.ts"; - case 2: - return "lib.es6.d.ts"; + case 2 /* ES2015 */: + return "lib.es6.d.ts"; // We don't use lib.es2015.full.d.ts due to breaking change. default: return "lib.d.ts"; } @@ -10306,6 +11556,7 @@ var ts; return position >= span.start && position < textSpanEnd(span); } ts.textSpanContainsPosition = textSpanContainsPosition; + // Returns true if 'span' contains 'other'. function textSpanContainsTextSpan(span, other) { return other.start >= span.start && textSpanEnd(other) <= textSpanEnd(span); } @@ -10353,6 +11604,7 @@ var ts; return { start: start, length: length }; } ts.createTextSpan = createTextSpan; + /* @internal */ function createTextRange(pos, end) { if (end === void 0) { end = pos; } ts.Debug.assert(end >= pos); @@ -10379,6 +11631,14 @@ var ts; } ts.createTextChangeRange = createTextChangeRange; ts.unchangedTextChangeRange = createTextChangeRange(createTextSpan(0, 0), 0); + /** + * Called to merge all the changes that occurred across several versions of a script snapshot + * into a single change. i.e. if a user keeps making successive edits to a script we will + * have a text change from V1 to V2, V2 to V3, ..., Vn. + * + * This function will then merge those changes into a single change range valid between V1 and + * Vn. + */ function collapseTextChangeRangesAcrossMultipleVersions(changes) { if (changes.length === 0) { return ts.unchangedTextChangeRange; @@ -10386,12 +11646,93 @@ var ts; if (changes.length === 1) { return changes[0]; } + // We change from talking about { { oldStart, oldLength }, newLength } to { oldStart, oldEnd, newEnd } + // as it makes things much easier to reason about. var change0 = changes[0]; var oldStartN = change0.span.start; var oldEndN = textSpanEnd(change0.span); var newEndN = oldStartN + change0.newLength; for (var i = 1; i < changes.length; i++) { var nextChange = changes[i]; + // Consider the following case: + // i.e. two edits. The first represents the text change range { { 10, 50 }, 30 }. i.e. The span starting + // at 10, with length 50 is reduced to length 30. The second represents the text change range { { 30, 30 }, 40 }. + // i.e. the span starting at 30 with length 30 is increased to length 40. + // + // 0 10 20 30 40 50 60 70 80 90 100 + // ------------------------------------------------------------------------------------------------------- + // | / + // | /---- + // T1 | /---- + // | /---- + // | /---- + // ------------------------------------------------------------------------------------------------------- + // | \ + // | \ + // T2 | \ + // | \ + // | \ + // ------------------------------------------------------------------------------------------------------- + // + // Merging these turns out to not be too difficult. First, determining the new start of the change is trivial + // it's just the min of the old and new starts. i.e.: + // + // 0 10 20 30 40 50 60 70 80 90 100 + // ------------------------------------------------------------*------------------------------------------ + // | / + // | /---- + // T1 | /---- + // | /---- + // | /---- + // ----------------------------------------$-------------------$------------------------------------------ + // . | \ + // . | \ + // T2 . | \ + // . | \ + // . | \ + // ----------------------------------------------------------------------*-------------------------------- + // + // (Note the dots represent the newly inferred start. + // Determining the new and old end is also pretty simple. Basically it boils down to paying attention to the + // absolute positions at the asterisks, and the relative change between the dollar signs. Basically, we see + // which if the two $'s precedes the other, and we move that one forward until they line up. in this case that + // means: + // + // 0 10 20 30 40 50 60 70 80 90 100 + // --------------------------------------------------------------------------------*---------------------- + // | / + // | /---- + // T1 | /---- + // | /---- + // | /---- + // ------------------------------------------------------------$------------------------------------------ + // . | \ + // . | \ + // T2 . | \ + // . | \ + // . | \ + // ----------------------------------------------------------------------*-------------------------------- + // + // In other words (in this case), we're recognizing that the second edit happened after where the first edit + // ended with a delta of 20 characters (60 - 40). Thus, if we go back in time to where the first edit started + // that's the same as if we started at char 80 instead of 60. + // + // As it so happens, the same logic applies if the second edit precedes the first edit. In that case rather + // than pushing the first edit forward to match the second, we'll push the second edit forward to match the + // first. + // + // In this case that means we have { oldStart: 10, oldEnd: 80, newEnd: 70 } or, in TextChangeRange + // semantics: { { start: 10, length: 70 }, newLength: 60 } + // + // The math then works out as follows. + // If we have { oldStart1, oldEnd1, newEnd1 } and { oldStart2, oldEnd2, newEnd2 } then we can compute the + // final result like so: + // + // { + // oldStart3: Min(oldStart1, oldStart2), + // oldEnd3: Max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1)), + // newEnd3: Max(newEnd2, newEnd2 + (newEnd1 - oldEnd2)) + // } var oldStart1 = oldStartN; var oldEnd1 = oldEndN; var newEnd1 = newEndN; @@ -10402,13 +11743,13 @@ var ts; oldEndN = Math.max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1)); newEndN = Math.max(newEnd2, newEnd2 + (newEnd1 - oldEnd2)); } - return createTextChangeRange(createTextSpanFromBounds(oldStartN, oldEndN), newEndN - oldStartN); + return createTextChangeRange(createTextSpanFromBounds(oldStartN, oldEndN), /*newLength*/ newEndN - oldStartN); } ts.collapseTextChangeRangesAcrossMultipleVersions = collapseTextChangeRangesAcrossMultipleVersions; function getTypeParameterOwner(d) { - if (d && d.kind === 148) { + if (d && d.kind === 148 /* TypeParameter */) { for (var current = d; current; current = current.parent) { - if (ts.isFunctionLike(current) || ts.isClassLike(current) || current.kind === 236) { + if (ts.isFunctionLike(current) || ts.isClassLike(current) || current.kind === 236 /* InterfaceDeclaration */) { return current; } } @@ -10416,7 +11757,7 @@ var ts; } ts.getTypeParameterOwner = getTypeParameterOwner; function isParameterPropertyDeclaration(node) { - return ts.hasModifier(node, 92) && node.parent.kind === 155; + return ts.hasModifier(node, 92 /* ParameterPropertyModifier */) && node.parent.kind === 155 /* Constructor */; } ts.isParameterPropertyDeclaration = isParameterPropertyDeclaration; function isEmptyBindingPattern(node) { @@ -10434,7 +11775,7 @@ var ts; } ts.isEmptyBindingElement = isEmptyBindingElement; function walkUpBindingElementsAndPatterns(node) { - while (node && (node.kind === 182 || ts.isBindingPattern(node))) { + while (node && (node.kind === 182 /* BindingElement */ || ts.isBindingPattern(node))) { node = node.parent; } return node; @@ -10442,35 +11783,46 @@ var ts; function getCombinedModifierFlags(node) { node = walkUpBindingElementsAndPatterns(node); var flags = ts.getModifierFlags(node); - if (node.kind === 232) { + if (node.kind === 232 /* VariableDeclaration */) { node = node.parent; } - if (node && node.kind === 233) { + if (node && node.kind === 233 /* VariableDeclarationList */) { flags |= ts.getModifierFlags(node); node = node.parent; } - if (node && node.kind === 214) { + if (node && node.kind === 214 /* VariableStatement */) { flags |= ts.getModifierFlags(node); } return flags; } ts.getCombinedModifierFlags = getCombinedModifierFlags; + // Returns the node flags for this node and all relevant parent nodes. This is done so that + // nodes like variable declarations and binding elements can returned a view of their flags + // that includes the modifiers from their container. i.e. flags like export/declare aren't + // stored on the variable declaration directly, but on the containing variable statement + // (if it has one). Similarly, flags for let/const are store on the variable declaration + // list. By calling this function, all those flags are combined so that the client can treat + // the node as if it actually had those flags. function getCombinedNodeFlags(node) { node = walkUpBindingElementsAndPatterns(node); var flags = node.flags; - if (node.kind === 232) { + if (node.kind === 232 /* VariableDeclaration */) { node = node.parent; } - if (node && node.kind === 233) { + if (node && node.kind === 233 /* VariableDeclarationList */) { flags |= node.flags; node = node.parent; } - if (node && node.kind === 214) { + if (node && node.kind === 214 /* VariableStatement */) { flags |= node.flags; } return flags; } ts.getCombinedNodeFlags = getCombinedNodeFlags; + /** + * Checks to see if the locale is in the appropriate format, + * and if it is, attempts to set the appropriate language. + */ function validateLocaleAndSetLanguage(locale, sys, errors) { var matchResult = /^([a-z]+)([_\-]([a-z]+))?$/.exec(locale.toLowerCase()); if (!matchResult) { @@ -10481,9 +11833,12 @@ var ts; } var language = matchResult[1]; var territory = matchResult[3]; + // First try the entire locale, then fall back to just language if that's all we have. + // Either ways do not fail, and fallback to the English diagnostic strings. if (!trySetLanguageAndTerritory(language, territory, errors)) { - trySetLanguageAndTerritory(language, undefined, errors); + trySetLanguageAndTerritory(language, /*territory*/ undefined, errors); } + // Set the UI locale for string collation ts.setUILocale(locale); function trySetLanguageAndTerritory(language, territory, errors) { var compilerFilePath = ts.normalizePath(sys.getExecutingFilePath()); @@ -10496,6 +11851,7 @@ var ts; if (!sys.fileExists(filePath)) { return false; } + // TODO: Add codePage support for readFile? var fileContents = ""; try { fileContents = sys.readFile(filePath); @@ -10507,6 +11863,7 @@ var ts; return false; } try { + // tslint:disable-next-line no-unnecessary-qualifier (making clear this is a global mutation!) ts.localizedDiagnosticMessages = JSON.parse(fileContents); } catch (_a) { @@ -10528,8 +11885,13 @@ var ts; return !nodeTest || nodeTest(node) ? node : undefined; } ts.getOriginalNode = getOriginalNode; + /** + * Gets a value indicating whether a node originated in the parse tree. + * + * @param node The node to test. + */ function isParseTreeNode(node) { - return (node.flags & 8) === 0; + return (node.flags & 8 /* Synthesized */) === 0; } ts.isParseTreeNode = isParseTreeNode; function getParseTreeNode(node, nodeTest) { @@ -10543,9 +11905,15 @@ var ts; return undefined; } ts.getParseTreeNode = getParseTreeNode; + /** + * Remove extra underscore from escaped identifier text content. + * + * @param identifier The escaped identifier text. + * @returns The unescaped identifier text. + */ function unescapeLeadingUnderscores(identifier) { var id = identifier; - return id.length >= 3 && id.charCodeAt(0) === 95 && id.charCodeAt(1) === 95 && id.charCodeAt(2) === 95 ? id.substr(1) : id; + return id.length >= 3 && id.charCodeAt(0) === 95 /* _ */ && id.charCodeAt(1) === 95 /* _ */ && id.charCodeAt(2) === 95 /* _ */ ? id.substr(1) : id; } ts.unescapeLeadingUnderscores = unescapeLeadingUnderscores; function idText(identifier) { @@ -10556,42 +11924,55 @@ var ts; return unescapeLeadingUnderscores(symbol.escapedName); } ts.symbolName = symbolName; + /** + * Remove extra underscore from escaped identifier text content. + * @deprecated Use `id.text` for the unescaped text. + * @param identifier The escaped identifier text. + * @returns The unescaped identifier text. + */ function unescapeIdentifier(id) { return id; } ts.unescapeIdentifier = unescapeIdentifier; + /** + * A JSDocTypedef tag has an _optional_ name field - if a name is not directly present, we should + * attempt to draw the name from the node the declaration is on (as that declaration is what its' symbol + * will be merged with) + */ function nameForNamelessJSDocTypedef(declaration) { var hostNode = declaration.parent.parent; if (!hostNode) { return undefined; } + // Covers classes, functions - any named declaration host node if (ts.isDeclaration(hostNode)) { return getDeclarationIdentifier(hostNode); } + // Covers remaining cases switch (hostNode.kind) { - case 214: + case 214 /* VariableStatement */: if (hostNode.declarationList && hostNode.declarationList.declarations[0]) { return getDeclarationIdentifier(hostNode.declarationList.declarations[0]); } return undefined; - case 216: + case 216 /* ExpressionStatement */: var expr = hostNode.expression; switch (expr.kind) { - case 185: + case 185 /* PropertyAccessExpression */: return expr.name; - case 186: + case 186 /* ElementAccessExpression */: var arg = expr.argumentExpression; if (ts.isIdentifier(arg)) { return arg; } } return undefined; - case 1: + case 1 /* EndOfFileToken */: return undefined; - case 191: { + case 191 /* ParenthesizedExpression */: { return getDeclarationIdentifier(hostNode.expression); } - case 228: { + case 228 /* LabeledStatement */: { if (ts.isDeclaration(hostNode.statement) || ts.isExpression(hostNode.statement)) { return getDeclarationIdentifier(hostNode.statement); } @@ -10609,48 +11990,50 @@ var ts; return declaration.name || nameForNamelessJSDocTypedef(declaration); } ts.getNameOfJSDocTypedef = getNameOfJSDocTypedef; + /** @internal */ function isNamedDeclaration(node) { - return !!node.name; + return !!node.name; // A 'name' property should always be a DeclarationName. } ts.isNamedDeclaration = isNamedDeclaration; + // TODO: GH#18217 This is often used as if it returns a defined result function getNameOfDeclaration(declaration) { if (!declaration) { return undefined; } switch (declaration.kind) { - case 205: - case 192: + case 205 /* ClassExpression */: + case 192 /* FunctionExpression */: if (!declaration.name) { return getAssignedName(declaration); } break; - case 71: + case 71 /* Identifier */: return declaration; - case 299: - case 293: { + case 299 /* JSDocPropertyTag */: + case 293 /* JSDocParameterTag */: { var name = declaration.name; - if (name.kind === 146) { + if (name.kind === 146 /* QualifiedName */) { return name.right; } break; } - case 200: { + case 200 /* BinaryExpression */: { var expr = declaration; switch (ts.getSpecialPropertyAssignmentKind(expr)) { - case 1: - case 4: - case 5: - case 3: + case 1 /* ExportsProperty */: + case 4 /* ThisProperty */: + case 5 /* Property */: + case 3 /* PrototypeProperty */: return expr.left.name; default: return undefined; } } - case 292: + case 292 /* JSDocCallbackTag */: return declaration.name; - case 298: + case 298 /* JSDocTypedefTag */: return getNameOfJSDocTypedef(declaration); - case 249: { + case 249 /* ExportAssignment */: { var expression = declaration.expression; return ts.isIdentifier(expression) ? expression : undefined; } @@ -10674,6 +12057,19 @@ var ts; } } } + /** + * Gets the JSDoc parameter tags for the node if present. + * + * @remarks Returns any JSDoc param tag that matches the provided + * parameter, whether a param tag on a containing function + * expression, or a param tag on a variable declaration whose + * initializer is the containing function. The tags closest to the + * node are returned first, so in the previous example, the param + * tag on the containing function expression would be first. + * + * Does not return tags for binding patterns, because JSDoc matches + * parameters by name and binding patterns do not have a name. + */ function getJSDocParameterTags(param) { if (param.name) { if (ts.isIdentifier(param.name)) { @@ -10689,34 +12085,48 @@ var ts; } } } + // return empty array for: out-of-order binding patterns and JSDoc function syntax, which has un-named parameters return ts.emptyArray; } ts.getJSDocParameterTags = getJSDocParameterTags; + /** + * Return true if the node has JSDoc parameter tags. + * + * @remarks Includes parameter tags that are not directly on the node, + * for example on a variable declaration whose initializer is a function expression. + */ function hasJSDocParameterTags(node) { return !!getFirstJSDocTag(node, ts.isJSDocParameterTag); } ts.hasJSDocParameterTags = hasJSDocParameterTags; + /** Gets the JSDoc augments tag for the node if present */ function getJSDocAugmentsTag(node) { return getFirstJSDocTag(node, ts.isJSDocAugmentsTag); } ts.getJSDocAugmentsTag = getJSDocAugmentsTag; + /** Gets the JSDoc class tag for the node if present */ function getJSDocClassTag(node) { return getFirstJSDocTag(node, ts.isJSDocClassTag); } ts.getJSDocClassTag = getJSDocClassTag; + /** Gets the JSDoc this tag for the node if present */ function getJSDocThisTag(node) { return getFirstJSDocTag(node, ts.isJSDocThisTag); } ts.getJSDocThisTag = getJSDocThisTag; + /** Gets the JSDoc return tag for the node if present */ function getJSDocReturnTag(node) { return getFirstJSDocTag(node, ts.isJSDocReturnTag); } ts.getJSDocReturnTag = getJSDocReturnTag; + /** Gets the JSDoc template tag for the node if present */ function getJSDocTemplateTag(node) { return getFirstJSDocTag(node, ts.isJSDocTemplateTag); } ts.getJSDocTemplateTag = getJSDocTemplateTag; + /** Gets the JSDoc type tag for the node if present and valid */ function getJSDocTypeTag(node) { + // We should have already issued an error if there were multiple type jsdocs, so just use the first one. var tag = getFirstJSDocTag(node, ts.isJSDocTypeTag); if (tag && tag.typeExpression && tag.typeExpression.type) { return tag; @@ -10724,6 +12134,17 @@ var ts; return undefined; } ts.getJSDocTypeTag = getJSDocTypeTag; + /** + * Gets the type node for the node if provided via JSDoc. + * + * @remarks The search includes any JSDoc param tag that relates + * to the provided parameter, for example a type tag on the + * parameter itself, or a param tag on a containing function + * expression, or a param tag on a variable declaration whose + * initializer is the containing function. The tags closest to the + * node are examined first, so in the previous example, the type + * tag directly on the node would be returned. + */ function getJSDocType(node) { var tag = getFirstJSDocTag(node, ts.isJSDocTypeTag); if (!tag && ts.isParameter(node)) { @@ -10732,13 +12153,21 @@ var ts; return tag && tag.typeExpression && tag.typeExpression.type; } ts.getJSDocType = getJSDocType; + /** + * Gets the return type node for the node if provided via JSDoc's return tag. + * + * @remarks `getJSDocReturnTag` just gets the whole JSDoc tag. This function + * gets the type from inside the braces. + */ function getJSDocReturnType(node) { var returnTag = getJSDocReturnTag(node); return returnTag && returnTag.typeExpression && returnTag.typeExpression.type; } ts.getJSDocReturnType = getJSDocReturnType; + /** Get all JSDoc tags related to a node, including those on parent nodes. */ function getJSDocTags(node) { var tags = node.jsDocCache; + // If cache is 'null', that means we did the work of searching for JSDoc tags and came up with nothing. if (tags === undefined) { var comments = ts.getJSDocCommentsAndTags(node); ts.Debug.assert(comments.length < 2 || comments[0] !== comments[1]); @@ -10747,710 +12176,749 @@ var ts; return tags; } ts.getJSDocTags = getJSDocTags; + /** Get the first JSDoc tag of a specified kind, or undefined if not present. */ function getFirstJSDocTag(node, predicate) { return ts.find(getJSDocTags(node), predicate); } + /** Gets all JSDoc tags of a specified kind, or undefined if not present. */ function getAllJSDocTagsOfKind(node, kind) { return getJSDocTags(node).filter(function (doc) { return doc.kind === kind; }); } ts.getAllJSDocTagsOfKind = getAllJSDocTagsOfKind; })(ts || (ts = {})); +// Simple node tests of the form `node.kind === SyntaxKind.Foo`. (function (ts) { + // Literals function isNumericLiteral(node) { - return node.kind === 8; + return node.kind === 8 /* NumericLiteral */; } ts.isNumericLiteral = isNumericLiteral; function isStringLiteral(node) { - return node.kind === 9; + return node.kind === 9 /* StringLiteral */; } ts.isStringLiteral = isStringLiteral; function isJsxText(node) { - return node.kind === 10; + return node.kind === 10 /* JsxText */; } ts.isJsxText = isJsxText; function isRegularExpressionLiteral(node) { - return node.kind === 12; + return node.kind === 12 /* RegularExpressionLiteral */; } ts.isRegularExpressionLiteral = isRegularExpressionLiteral; function isNoSubstitutionTemplateLiteral(node) { - return node.kind === 13; + return node.kind === 13 /* NoSubstitutionTemplateLiteral */; } ts.isNoSubstitutionTemplateLiteral = isNoSubstitutionTemplateLiteral; + // Pseudo-literals function isTemplateHead(node) { - return node.kind === 14; + return node.kind === 14 /* TemplateHead */; } ts.isTemplateHead = isTemplateHead; function isTemplateMiddle(node) { - return node.kind === 15; + return node.kind === 15 /* TemplateMiddle */; } ts.isTemplateMiddle = isTemplateMiddle; function isTemplateTail(node) { - return node.kind === 16; + return node.kind === 16 /* TemplateTail */; } ts.isTemplateTail = isTemplateTail; function isIdentifier(node) { - return node.kind === 71; + return node.kind === 71 /* Identifier */; } ts.isIdentifier = isIdentifier; + // Names function isQualifiedName(node) { - return node.kind === 146; + return node.kind === 146 /* QualifiedName */; } ts.isQualifiedName = isQualifiedName; function isComputedPropertyName(node) { - return node.kind === 147; + return node.kind === 147 /* ComputedPropertyName */; } ts.isComputedPropertyName = isComputedPropertyName; + // Signature elements function isTypeParameterDeclaration(node) { - return node.kind === 148; + return node.kind === 148 /* TypeParameter */; } ts.isTypeParameterDeclaration = isTypeParameterDeclaration; function isParameter(node) { - return node.kind === 149; + return node.kind === 149 /* Parameter */; } ts.isParameter = isParameter; function isDecorator(node) { - return node.kind === 150; + return node.kind === 150 /* Decorator */; } ts.isDecorator = isDecorator; + // TypeMember function isPropertySignature(node) { - return node.kind === 151; + return node.kind === 151 /* PropertySignature */; } ts.isPropertySignature = isPropertySignature; function isPropertyDeclaration(node) { - return node.kind === 152; + return node.kind === 152 /* PropertyDeclaration */; } ts.isPropertyDeclaration = isPropertyDeclaration; function isMethodSignature(node) { - return node.kind === 153; + return node.kind === 153 /* MethodSignature */; } ts.isMethodSignature = isMethodSignature; function isMethodDeclaration(node) { - return node.kind === 154; + return node.kind === 154 /* MethodDeclaration */; } ts.isMethodDeclaration = isMethodDeclaration; function isConstructorDeclaration(node) { - return node.kind === 155; + return node.kind === 155 /* Constructor */; } ts.isConstructorDeclaration = isConstructorDeclaration; function isGetAccessorDeclaration(node) { - return node.kind === 156; + return node.kind === 156 /* GetAccessor */; } ts.isGetAccessorDeclaration = isGetAccessorDeclaration; function isSetAccessorDeclaration(node) { - return node.kind === 157; + return node.kind === 157 /* SetAccessor */; } ts.isSetAccessorDeclaration = isSetAccessorDeclaration; function isCallSignatureDeclaration(node) { - return node.kind === 158; + return node.kind === 158 /* CallSignature */; } ts.isCallSignatureDeclaration = isCallSignatureDeclaration; function isConstructSignatureDeclaration(node) { - return node.kind === 159; + return node.kind === 159 /* ConstructSignature */; } ts.isConstructSignatureDeclaration = isConstructSignatureDeclaration; function isIndexSignatureDeclaration(node) { - return node.kind === 160; + return node.kind === 160 /* IndexSignature */; } ts.isIndexSignatureDeclaration = isIndexSignatureDeclaration; + /* @internal */ function isGetOrSetAccessorDeclaration(node) { - return node.kind === 157 || node.kind === 156; + return node.kind === 157 /* SetAccessor */ || node.kind === 156 /* GetAccessor */; } ts.isGetOrSetAccessorDeclaration = isGetOrSetAccessorDeclaration; + // Type function isTypePredicateNode(node) { - return node.kind === 161; + return node.kind === 161 /* TypePredicate */; } ts.isTypePredicateNode = isTypePredicateNode; function isTypeReferenceNode(node) { - return node.kind === 162; + return node.kind === 162 /* TypeReference */; } ts.isTypeReferenceNode = isTypeReferenceNode; function isFunctionTypeNode(node) { - return node.kind === 163; + return node.kind === 163 /* FunctionType */; } ts.isFunctionTypeNode = isFunctionTypeNode; function isConstructorTypeNode(node) { - return node.kind === 164; + return node.kind === 164 /* ConstructorType */; } ts.isConstructorTypeNode = isConstructorTypeNode; function isTypeQueryNode(node) { - return node.kind === 165; + return node.kind === 165 /* TypeQuery */; } ts.isTypeQueryNode = isTypeQueryNode; function isTypeLiteralNode(node) { - return node.kind === 166; + return node.kind === 166 /* TypeLiteral */; } ts.isTypeLiteralNode = isTypeLiteralNode; function isArrayTypeNode(node) { - return node.kind === 167; + return node.kind === 167 /* ArrayType */; } ts.isArrayTypeNode = isArrayTypeNode; function isTupleTypeNode(node) { - return node.kind === 168; + return node.kind === 168 /* TupleType */; } ts.isTupleTypeNode = isTupleTypeNode; function isUnionTypeNode(node) { - return node.kind === 169; + return node.kind === 169 /* UnionType */; } ts.isUnionTypeNode = isUnionTypeNode; function isIntersectionTypeNode(node) { - return node.kind === 170; + return node.kind === 170 /* IntersectionType */; } ts.isIntersectionTypeNode = isIntersectionTypeNode; function isConditionalTypeNode(node) { - return node.kind === 171; + return node.kind === 171 /* ConditionalType */; } ts.isConditionalTypeNode = isConditionalTypeNode; function isInferTypeNode(node) { - return node.kind === 172; + return node.kind === 172 /* InferType */; } ts.isInferTypeNode = isInferTypeNode; function isParenthesizedTypeNode(node) { - return node.kind === 173; + return node.kind === 173 /* ParenthesizedType */; } ts.isParenthesizedTypeNode = isParenthesizedTypeNode; function isThisTypeNode(node) { - return node.kind === 174; + return node.kind === 174 /* ThisType */; } ts.isThisTypeNode = isThisTypeNode; function isTypeOperatorNode(node) { - return node.kind === 175; + return node.kind === 175 /* TypeOperator */; } ts.isTypeOperatorNode = isTypeOperatorNode; function isIndexedAccessTypeNode(node) { - return node.kind === 176; + return node.kind === 176 /* IndexedAccessType */; } ts.isIndexedAccessTypeNode = isIndexedAccessTypeNode; function isMappedTypeNode(node) { - return node.kind === 177; + return node.kind === 177 /* MappedType */; } ts.isMappedTypeNode = isMappedTypeNode; function isLiteralTypeNode(node) { - return node.kind === 178; + return node.kind === 178 /* LiteralType */; } ts.isLiteralTypeNode = isLiteralTypeNode; function isImportTypeNode(node) { - return node.kind === 179; + return node.kind === 179 /* ImportType */; } ts.isImportTypeNode = isImportTypeNode; + // Binding patterns function isObjectBindingPattern(node) { - return node.kind === 180; + return node.kind === 180 /* ObjectBindingPattern */; } ts.isObjectBindingPattern = isObjectBindingPattern; function isArrayBindingPattern(node) { - return node.kind === 181; + return node.kind === 181 /* ArrayBindingPattern */; } ts.isArrayBindingPattern = isArrayBindingPattern; function isBindingElement(node) { - return node.kind === 182; + return node.kind === 182 /* BindingElement */; } ts.isBindingElement = isBindingElement; + // Expression function isArrayLiteralExpression(node) { - return node.kind === 183; + return node.kind === 183 /* ArrayLiteralExpression */; } ts.isArrayLiteralExpression = isArrayLiteralExpression; function isObjectLiteralExpression(node) { - return node.kind === 184; + return node.kind === 184 /* ObjectLiteralExpression */; } ts.isObjectLiteralExpression = isObjectLiteralExpression; function isPropertyAccessExpression(node) { - return node.kind === 185; + return node.kind === 185 /* PropertyAccessExpression */; } ts.isPropertyAccessExpression = isPropertyAccessExpression; function isElementAccessExpression(node) { - return node.kind === 186; + return node.kind === 186 /* ElementAccessExpression */; } ts.isElementAccessExpression = isElementAccessExpression; function isCallExpression(node) { - return node.kind === 187; + return node.kind === 187 /* CallExpression */; } ts.isCallExpression = isCallExpression; function isNewExpression(node) { - return node.kind === 188; + return node.kind === 188 /* NewExpression */; } ts.isNewExpression = isNewExpression; function isTaggedTemplateExpression(node) { - return node.kind === 189; + return node.kind === 189 /* TaggedTemplateExpression */; } ts.isTaggedTemplateExpression = isTaggedTemplateExpression; function isTypeAssertion(node) { - return node.kind === 190; + return node.kind === 190 /* TypeAssertionExpression */; } ts.isTypeAssertion = isTypeAssertion; function isParenthesizedExpression(node) { - return node.kind === 191; + return node.kind === 191 /* ParenthesizedExpression */; } ts.isParenthesizedExpression = isParenthesizedExpression; function skipPartiallyEmittedExpressions(node) { - while (node.kind === 302) { + while (node.kind === 302 /* PartiallyEmittedExpression */) { node = node.expression; } return node; } ts.skipPartiallyEmittedExpressions = skipPartiallyEmittedExpressions; function isFunctionExpression(node) { - return node.kind === 192; + return node.kind === 192 /* FunctionExpression */; } ts.isFunctionExpression = isFunctionExpression; function isArrowFunction(node) { - return node.kind === 193; + return node.kind === 193 /* ArrowFunction */; } ts.isArrowFunction = isArrowFunction; function isDeleteExpression(node) { - return node.kind === 194; + return node.kind === 194 /* DeleteExpression */; } ts.isDeleteExpression = isDeleteExpression; function isTypeOfExpression(node) { - return node.kind === 195; + return node.kind === 195 /* TypeOfExpression */; } ts.isTypeOfExpression = isTypeOfExpression; function isVoidExpression(node) { - return node.kind === 196; + return node.kind === 196 /* VoidExpression */; } ts.isVoidExpression = isVoidExpression; function isAwaitExpression(node) { - return node.kind === 197; + return node.kind === 197 /* AwaitExpression */; } ts.isAwaitExpression = isAwaitExpression; function isPrefixUnaryExpression(node) { - return node.kind === 198; + return node.kind === 198 /* PrefixUnaryExpression */; } ts.isPrefixUnaryExpression = isPrefixUnaryExpression; function isPostfixUnaryExpression(node) { - return node.kind === 199; + return node.kind === 199 /* PostfixUnaryExpression */; } ts.isPostfixUnaryExpression = isPostfixUnaryExpression; function isBinaryExpression(node) { - return node.kind === 200; + return node.kind === 200 /* BinaryExpression */; } ts.isBinaryExpression = isBinaryExpression; function isConditionalExpression(node) { - return node.kind === 201; + return node.kind === 201 /* ConditionalExpression */; } ts.isConditionalExpression = isConditionalExpression; function isTemplateExpression(node) { - return node.kind === 202; + return node.kind === 202 /* TemplateExpression */; } ts.isTemplateExpression = isTemplateExpression; function isYieldExpression(node) { - return node.kind === 203; + return node.kind === 203 /* YieldExpression */; } ts.isYieldExpression = isYieldExpression; function isSpreadElement(node) { - return node.kind === 204; + return node.kind === 204 /* SpreadElement */; } ts.isSpreadElement = isSpreadElement; function isClassExpression(node) { - return node.kind === 205; + return node.kind === 205 /* ClassExpression */; } ts.isClassExpression = isClassExpression; function isOmittedExpression(node) { - return node.kind === 206; + return node.kind === 206 /* OmittedExpression */; } ts.isOmittedExpression = isOmittedExpression; function isExpressionWithTypeArguments(node) { - return node.kind === 207; + return node.kind === 207 /* ExpressionWithTypeArguments */; } ts.isExpressionWithTypeArguments = isExpressionWithTypeArguments; function isAsExpression(node) { - return node.kind === 208; + return node.kind === 208 /* AsExpression */; } ts.isAsExpression = isAsExpression; function isNonNullExpression(node) { - return node.kind === 209; + return node.kind === 209 /* NonNullExpression */; } ts.isNonNullExpression = isNonNullExpression; function isMetaProperty(node) { - return node.kind === 210; + return node.kind === 210 /* MetaProperty */; } ts.isMetaProperty = isMetaProperty; + // Misc function isTemplateSpan(node) { - return node.kind === 211; + return node.kind === 211 /* TemplateSpan */; } ts.isTemplateSpan = isTemplateSpan; function isSemicolonClassElement(node) { - return node.kind === 212; + return node.kind === 212 /* SemicolonClassElement */; } ts.isSemicolonClassElement = isSemicolonClassElement; + // Block function isBlock(node) { - return node.kind === 213; + return node.kind === 213 /* Block */; } ts.isBlock = isBlock; function isVariableStatement(node) { - return node.kind === 214; + return node.kind === 214 /* VariableStatement */; } ts.isVariableStatement = isVariableStatement; function isEmptyStatement(node) { - return node.kind === 215; + return node.kind === 215 /* EmptyStatement */; } ts.isEmptyStatement = isEmptyStatement; function isExpressionStatement(node) { - return node.kind === 216; + return node.kind === 216 /* ExpressionStatement */; } ts.isExpressionStatement = isExpressionStatement; function isIfStatement(node) { - return node.kind === 217; + return node.kind === 217 /* IfStatement */; } ts.isIfStatement = isIfStatement; function isDoStatement(node) { - return node.kind === 218; + return node.kind === 218 /* DoStatement */; } ts.isDoStatement = isDoStatement; function isWhileStatement(node) { - return node.kind === 219; + return node.kind === 219 /* WhileStatement */; } ts.isWhileStatement = isWhileStatement; function isForStatement(node) { - return node.kind === 220; + return node.kind === 220 /* ForStatement */; } ts.isForStatement = isForStatement; function isForInStatement(node) { - return node.kind === 221; + return node.kind === 221 /* ForInStatement */; } ts.isForInStatement = isForInStatement; function isForOfStatement(node) { - return node.kind === 222; + return node.kind === 222 /* ForOfStatement */; } ts.isForOfStatement = isForOfStatement; function isContinueStatement(node) { - return node.kind === 223; + return node.kind === 223 /* ContinueStatement */; } ts.isContinueStatement = isContinueStatement; function isBreakStatement(node) { - return node.kind === 224; + return node.kind === 224 /* BreakStatement */; } ts.isBreakStatement = isBreakStatement; function isBreakOrContinueStatement(node) { - return node.kind === 224 || node.kind === 223; + return node.kind === 224 /* BreakStatement */ || node.kind === 223 /* ContinueStatement */; } ts.isBreakOrContinueStatement = isBreakOrContinueStatement; function isReturnStatement(node) { - return node.kind === 225; + return node.kind === 225 /* ReturnStatement */; } ts.isReturnStatement = isReturnStatement; function isWithStatement(node) { - return node.kind === 226; + return node.kind === 226 /* WithStatement */; } ts.isWithStatement = isWithStatement; function isSwitchStatement(node) { - return node.kind === 227; + return node.kind === 227 /* SwitchStatement */; } ts.isSwitchStatement = isSwitchStatement; function isLabeledStatement(node) { - return node.kind === 228; + return node.kind === 228 /* LabeledStatement */; } ts.isLabeledStatement = isLabeledStatement; function isThrowStatement(node) { - return node.kind === 229; + return node.kind === 229 /* ThrowStatement */; } ts.isThrowStatement = isThrowStatement; function isTryStatement(node) { - return node.kind === 230; + return node.kind === 230 /* TryStatement */; } ts.isTryStatement = isTryStatement; function isDebuggerStatement(node) { - return node.kind === 231; + return node.kind === 231 /* DebuggerStatement */; } ts.isDebuggerStatement = isDebuggerStatement; function isVariableDeclaration(node) { - return node.kind === 232; + return node.kind === 232 /* VariableDeclaration */; } ts.isVariableDeclaration = isVariableDeclaration; function isVariableDeclarationList(node) { - return node.kind === 233; + return node.kind === 233 /* VariableDeclarationList */; } ts.isVariableDeclarationList = isVariableDeclarationList; function isFunctionDeclaration(node) { - return node.kind === 234; + return node.kind === 234 /* FunctionDeclaration */; } ts.isFunctionDeclaration = isFunctionDeclaration; function isClassDeclaration(node) { - return node.kind === 235; + return node.kind === 235 /* ClassDeclaration */; } ts.isClassDeclaration = isClassDeclaration; function isInterfaceDeclaration(node) { - return node.kind === 236; + return node.kind === 236 /* InterfaceDeclaration */; } ts.isInterfaceDeclaration = isInterfaceDeclaration; function isTypeAliasDeclaration(node) { - return node.kind === 237; + return node.kind === 237 /* TypeAliasDeclaration */; } ts.isTypeAliasDeclaration = isTypeAliasDeclaration; function isEnumDeclaration(node) { - return node.kind === 238; + return node.kind === 238 /* EnumDeclaration */; } ts.isEnumDeclaration = isEnumDeclaration; function isModuleDeclaration(node) { - return node.kind === 239; + return node.kind === 239 /* ModuleDeclaration */; } ts.isModuleDeclaration = isModuleDeclaration; function isModuleBlock(node) { - return node.kind === 240; + return node.kind === 240 /* ModuleBlock */; } ts.isModuleBlock = isModuleBlock; function isCaseBlock(node) { - return node.kind === 241; + return node.kind === 241 /* CaseBlock */; } ts.isCaseBlock = isCaseBlock; function isNamespaceExportDeclaration(node) { - return node.kind === 242; + return node.kind === 242 /* NamespaceExportDeclaration */; } ts.isNamespaceExportDeclaration = isNamespaceExportDeclaration; function isImportEqualsDeclaration(node) { - return node.kind === 243; + return node.kind === 243 /* ImportEqualsDeclaration */; } ts.isImportEqualsDeclaration = isImportEqualsDeclaration; function isImportDeclaration(node) { - return node.kind === 244; + return node.kind === 244 /* ImportDeclaration */; } ts.isImportDeclaration = isImportDeclaration; function isImportClause(node) { - return node.kind === 245; + return node.kind === 245 /* ImportClause */; } ts.isImportClause = isImportClause; function isNamespaceImport(node) { - return node.kind === 246; + return node.kind === 246 /* NamespaceImport */; } ts.isNamespaceImport = isNamespaceImport; function isNamedImports(node) { - return node.kind === 247; + return node.kind === 247 /* NamedImports */; } ts.isNamedImports = isNamedImports; function isImportSpecifier(node) { - return node.kind === 248; + return node.kind === 248 /* ImportSpecifier */; } ts.isImportSpecifier = isImportSpecifier; function isExportAssignment(node) { - return node.kind === 249; + return node.kind === 249 /* ExportAssignment */; } ts.isExportAssignment = isExportAssignment; function isExportDeclaration(node) { - return node.kind === 250; + return node.kind === 250 /* ExportDeclaration */; } ts.isExportDeclaration = isExportDeclaration; function isNamedExports(node) { - return node.kind === 251; + return node.kind === 251 /* NamedExports */; } ts.isNamedExports = isNamedExports; function isExportSpecifier(node) { - return node.kind === 252; + return node.kind === 252 /* ExportSpecifier */; } ts.isExportSpecifier = isExportSpecifier; function isMissingDeclaration(node) { - return node.kind === 253; + return node.kind === 253 /* MissingDeclaration */; } ts.isMissingDeclaration = isMissingDeclaration; + // Module References function isExternalModuleReference(node) { - return node.kind === 254; + return node.kind === 254 /* ExternalModuleReference */; } ts.isExternalModuleReference = isExternalModuleReference; + // JSX function isJsxElement(node) { - return node.kind === 255; + return node.kind === 255 /* JsxElement */; } ts.isJsxElement = isJsxElement; function isJsxSelfClosingElement(node) { - return node.kind === 256; + return node.kind === 256 /* JsxSelfClosingElement */; } ts.isJsxSelfClosingElement = isJsxSelfClosingElement; function isJsxOpeningElement(node) { - return node.kind === 257; + return node.kind === 257 /* JsxOpeningElement */; } ts.isJsxOpeningElement = isJsxOpeningElement; function isJsxClosingElement(node) { - return node.kind === 258; + return node.kind === 258 /* JsxClosingElement */; } ts.isJsxClosingElement = isJsxClosingElement; function isJsxFragment(node) { - return node.kind === 259; + return node.kind === 259 /* JsxFragment */; } ts.isJsxFragment = isJsxFragment; function isJsxOpeningFragment(node) { - return node.kind === 260; + return node.kind === 260 /* JsxOpeningFragment */; } ts.isJsxOpeningFragment = isJsxOpeningFragment; function isJsxClosingFragment(node) { - return node.kind === 261; + return node.kind === 261 /* JsxClosingFragment */; } ts.isJsxClosingFragment = isJsxClosingFragment; function isJsxAttribute(node) { - return node.kind === 262; + return node.kind === 262 /* JsxAttribute */; } ts.isJsxAttribute = isJsxAttribute; function isJsxAttributes(node) { - return node.kind === 263; + return node.kind === 263 /* JsxAttributes */; } ts.isJsxAttributes = isJsxAttributes; function isJsxSpreadAttribute(node) { - return node.kind === 264; + return node.kind === 264 /* JsxSpreadAttribute */; } ts.isJsxSpreadAttribute = isJsxSpreadAttribute; function isJsxExpression(node) { - return node.kind === 265; + return node.kind === 265 /* JsxExpression */; } ts.isJsxExpression = isJsxExpression; + // Clauses function isCaseClause(node) { - return node.kind === 266; + return node.kind === 266 /* CaseClause */; } ts.isCaseClause = isCaseClause; function isDefaultClause(node) { - return node.kind === 267; + return node.kind === 267 /* DefaultClause */; } ts.isDefaultClause = isDefaultClause; function isHeritageClause(node) { - return node.kind === 268; + return node.kind === 268 /* HeritageClause */; } ts.isHeritageClause = isHeritageClause; function isCatchClause(node) { - return node.kind === 269; + return node.kind === 269 /* CatchClause */; } ts.isCatchClause = isCatchClause; + // Property assignments function isPropertyAssignment(node) { - return node.kind === 270; + return node.kind === 270 /* PropertyAssignment */; } ts.isPropertyAssignment = isPropertyAssignment; function isShorthandPropertyAssignment(node) { - return node.kind === 271; + return node.kind === 271 /* ShorthandPropertyAssignment */; } ts.isShorthandPropertyAssignment = isShorthandPropertyAssignment; function isSpreadAssignment(node) { - return node.kind === 272; + return node.kind === 272 /* SpreadAssignment */; } ts.isSpreadAssignment = isSpreadAssignment; + // Enum function isEnumMember(node) { - return node.kind === 273; + return node.kind === 273 /* EnumMember */; } ts.isEnumMember = isEnumMember; + // Top-level nodes function isSourceFile(node) { - return node.kind === 274; + return node.kind === 274 /* SourceFile */; } ts.isSourceFile = isSourceFile; function isBundle(node) { - return node.kind === 275; + return node.kind === 275 /* Bundle */; } ts.isBundle = isBundle; function isUnparsedSource(node) { - return node.kind === 276; + return node.kind === 276 /* UnparsedSource */; } ts.isUnparsedSource = isUnparsedSource; + // JSDoc function isJSDocTypeExpression(node) { - return node.kind === 278; + return node.kind === 278 /* JSDocTypeExpression */; } ts.isJSDocTypeExpression = isJSDocTypeExpression; function isJSDocAllType(node) { - return node.kind === 279; + return node.kind === 279 /* JSDocAllType */; } ts.isJSDocAllType = isJSDocAllType; function isJSDocUnknownType(node) { - return node.kind === 280; + return node.kind === 280 /* JSDocUnknownType */; } ts.isJSDocUnknownType = isJSDocUnknownType; function isJSDocNullableType(node) { - return node.kind === 281; + return node.kind === 281 /* JSDocNullableType */; } ts.isJSDocNullableType = isJSDocNullableType; function isJSDocNonNullableType(node) { - return node.kind === 282; + return node.kind === 282 /* JSDocNonNullableType */; } ts.isJSDocNonNullableType = isJSDocNonNullableType; function isJSDocOptionalType(node) { - return node.kind === 283; + return node.kind === 283 /* JSDocOptionalType */; } ts.isJSDocOptionalType = isJSDocOptionalType; function isJSDocFunctionType(node) { - return node.kind === 284; + return node.kind === 284 /* JSDocFunctionType */; } ts.isJSDocFunctionType = isJSDocFunctionType; function isJSDocVariadicType(node) { - return node.kind === 285; + return node.kind === 285 /* JSDocVariadicType */; } ts.isJSDocVariadicType = isJSDocVariadicType; function isJSDoc(node) { - return node.kind === 286; + return node.kind === 286 /* JSDocComment */; } ts.isJSDoc = isJSDoc; function isJSDocAugmentsTag(node) { - return node.kind === 290; + return node.kind === 290 /* JSDocAugmentsTag */; } ts.isJSDocAugmentsTag = isJSDocAugmentsTag; function isJSDocClassTag(node) { - return node.kind === 291; + return node.kind === 291 /* JSDocClassTag */; } ts.isJSDocClassTag = isJSDocClassTag; function isJSDocThisTag(node) { - return node.kind === 295; + return node.kind === 295 /* JSDocThisTag */; } ts.isJSDocThisTag = isJSDocThisTag; function isJSDocParameterTag(node) { - return node.kind === 293; + return node.kind === 293 /* JSDocParameterTag */; } ts.isJSDocParameterTag = isJSDocParameterTag; function isJSDocReturnTag(node) { - return node.kind === 294; + return node.kind === 294 /* JSDocReturnTag */; } ts.isJSDocReturnTag = isJSDocReturnTag; function isJSDocTypeTag(node) { - return node.kind === 296; + return node.kind === 296 /* JSDocTypeTag */; } ts.isJSDocTypeTag = isJSDocTypeTag; function isJSDocTemplateTag(node) { - return node.kind === 297; + return node.kind === 297 /* JSDocTemplateTag */; } ts.isJSDocTemplateTag = isJSDocTemplateTag; function isJSDocTypedefTag(node) { - return node.kind === 298; + return node.kind === 298 /* JSDocTypedefTag */; } ts.isJSDocTypedefTag = isJSDocTypedefTag; function isJSDocPropertyTag(node) { - return node.kind === 299; + return node.kind === 299 /* JSDocPropertyTag */; } ts.isJSDocPropertyTag = isJSDocPropertyTag; function isJSDocPropertyLikeTag(node) { - return node.kind === 299 || node.kind === 293; + return node.kind === 299 /* JSDocPropertyTag */ || node.kind === 293 /* JSDocParameterTag */; } ts.isJSDocPropertyLikeTag = isJSDocPropertyLikeTag; function isJSDocTypeLiteral(node) { - return node.kind === 287; + return node.kind === 287 /* JSDocTypeLiteral */; } ts.isJSDocTypeLiteral = isJSDocTypeLiteral; function isJSDocCallbackTag(node) { - return node.kind === 292; + return node.kind === 292 /* JSDocCallbackTag */; } ts.isJSDocCallbackTag = isJSDocCallbackTag; function isJSDocSignature(node) { - return node.kind === 288; + return node.kind === 288 /* JSDocSignature */; } ts.isJSDocSignature = isJSDocSignature; })(ts || (ts = {})); +// Node tests +// +// All node tests in the following list should *not* reference parent pointers so that +// they may be used with transformations. (function (ts) { + /* @internal */ function isSyntaxList(n) { - return n.kind === 300; + return n.kind === 300 /* SyntaxList */; } ts.isSyntaxList = isSyntaxList; + /* @internal */ function isNode(node) { return isNodeKind(node.kind); } ts.isNode = isNode; + /* @internal */ function isNodeKind(kind) { - return kind >= 146; + return kind >= 146 /* FirstNode */; } ts.isNodeKind = isNodeKind; + /** + * True if node is of some token syntax kind. + * For example, this is true for an IfKeyword but not for an IfStatement. + * Literals are considered tokens, except TemplateLiteral, but does include TemplateHead/Middle/Tail. + */ function isToken(n) { - return n.kind >= 0 && n.kind <= 145; + return n.kind >= 0 /* FirstToken */ && n.kind <= 145 /* LastToken */; } ts.isToken = isToken; + // Node Arrays + /* @internal */ function isNodeArray(array) { return array.hasOwnProperty("pos") && array.hasOwnProperty("end"); } ts.isNodeArray = isNodeArray; + // Literals + /* @internal */ function isLiteralKind(kind) { - return 8 <= kind && kind <= 13; + return 8 /* FirstLiteralToken */ <= kind && kind <= 13 /* LastLiteralToken */; } ts.isLiteralKind = isLiteralKind; function isLiteralExpression(node) { return isLiteralKind(node.kind); } ts.isLiteralExpression = isLiteralExpression; + // Pseudo-literals + /* @internal */ function isTemplateLiteralKind(kind) { - return 13 <= kind && kind <= 16; + return 13 /* FirstTemplateToken */ <= kind && kind <= 16 /* LastTemplateToken */; } ts.isTemplateLiteralKind = isTemplateLiteralKind; function isTemplateLiteralToken(node) { @@ -11459,42 +12927,48 @@ var ts; ts.isTemplateLiteralToken = isTemplateLiteralToken; function isTemplateMiddleOrTemplateTail(node) { var kind = node.kind; - return kind === 15 - || kind === 16; + return kind === 15 /* TemplateMiddle */ + || kind === 16 /* TemplateTail */; } ts.isTemplateMiddleOrTemplateTail = isTemplateMiddleOrTemplateTail; function isStringTextContainingNode(node) { - return node.kind === 9 || isTemplateLiteralKind(node.kind); + return node.kind === 9 /* StringLiteral */ || isTemplateLiteralKind(node.kind); } ts.isStringTextContainingNode = isStringTextContainingNode; + // Identifiers + /* @internal */ function isGeneratedIdentifier(node) { - return ts.isIdentifier(node) && (node.autoGenerateFlags & 7) > 0; + return ts.isIdentifier(node) && (node.autoGenerateFlags & 7 /* KindMask */) > 0 /* None */; } ts.isGeneratedIdentifier = isGeneratedIdentifier; + // Keywords + /* @internal */ function isModifierKind(token) { switch (token) { - case 117: - case 120: - case 76: - case 124: - case 79: - case 84: - case 114: - case 112: - case 113: - case 132: - case 115: + case 117 /* AbstractKeyword */: + case 120 /* AsyncKeyword */: + case 76 /* ConstKeyword */: + case 124 /* DeclareKeyword */: + case 79 /* DefaultKeyword */: + case 84 /* ExportKeyword */: + case 114 /* PublicKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: + case 132 /* ReadonlyKeyword */: + case 115 /* StaticKeyword */: return true; } return false; } ts.isModifierKind = isModifierKind; + /* @internal */ function isParameterPropertyModifier(kind) { - return !!(ts.modifierToFlag(kind) & 92); + return !!(ts.modifierToFlag(kind) & 92 /* ParameterPropertyModifier */); } ts.isParameterPropertyModifier = isParameterPropertyModifier; + /* @internal */ function isClassMemberModifier(idToken) { - return isParameterPropertyModifier(idToken) || idToken === 115; + return isParameterPropertyModifier(idToken) || idToken === 115 /* StaticKeyword */; } ts.isClassMemberModifier = isClassMemberModifier; function isModifier(node) { @@ -11503,104 +12977,111 @@ var ts; ts.isModifier = isModifier; function isEntityName(node) { var kind = node.kind; - return kind === 146 - || kind === 71; + return kind === 146 /* QualifiedName */ + || kind === 71 /* Identifier */; } ts.isEntityName = isEntityName; function isPropertyName(node) { var kind = node.kind; - return kind === 71 - || kind === 9 - || kind === 8 - || kind === 147; + return kind === 71 /* Identifier */ + || kind === 9 /* StringLiteral */ + || kind === 8 /* NumericLiteral */ + || kind === 147 /* ComputedPropertyName */; } ts.isPropertyName = isPropertyName; function isBindingName(node) { var kind = node.kind; - return kind === 71 - || kind === 180 - || kind === 181; + return kind === 71 /* Identifier */ + || kind === 180 /* ObjectBindingPattern */ + || kind === 181 /* ArrayBindingPattern */; } ts.isBindingName = isBindingName; + // Functions function isFunctionLike(node) { return node && isFunctionLikeKind(node.kind); } ts.isFunctionLike = isFunctionLike; + /* @internal */ function isFunctionLikeDeclaration(node) { return node && isFunctionLikeDeclarationKind(node.kind); } ts.isFunctionLikeDeclaration = isFunctionLikeDeclaration; function isFunctionLikeDeclarationKind(kind) { switch (kind) { - case 234: - case 154: - case 155: - case 156: - case 157: - case 192: - case 193: + case 234 /* FunctionDeclaration */: + case 154 /* MethodDeclaration */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: return true; default: return false; } } + /* @internal */ function isFunctionLikeKind(kind) { switch (kind) { - case 153: - case 158: - case 288: - case 159: - case 160: - case 163: - case 284: - case 164: + case 153 /* MethodSignature */: + case 158 /* CallSignature */: + case 288 /* JSDocSignature */: + case 159 /* ConstructSignature */: + case 160 /* IndexSignature */: + case 163 /* FunctionType */: + case 284 /* JSDocFunctionType */: + case 164 /* ConstructorType */: return true; default: return isFunctionLikeDeclarationKind(kind); } } ts.isFunctionLikeKind = isFunctionLikeKind; + /* @internal */ function isFunctionOrModuleBlock(node) { return ts.isSourceFile(node) || ts.isModuleBlock(node) || ts.isBlock(node) && isFunctionLike(node.parent); } ts.isFunctionOrModuleBlock = isFunctionOrModuleBlock; + // Classes function isClassElement(node) { var kind = node.kind; - return kind === 155 - || kind === 152 - || kind === 154 - || kind === 156 - || kind === 157 - || kind === 160 - || kind === 212; + return kind === 155 /* Constructor */ + || kind === 152 /* PropertyDeclaration */ + || kind === 154 /* MethodDeclaration */ + || kind === 156 /* GetAccessor */ + || kind === 157 /* SetAccessor */ + || kind === 160 /* IndexSignature */ + || kind === 212 /* SemicolonClassElement */; } ts.isClassElement = isClassElement; function isClassLike(node) { - return node && (node.kind === 235 || node.kind === 205); + return node && (node.kind === 235 /* ClassDeclaration */ || node.kind === 205 /* ClassExpression */); } ts.isClassLike = isClassLike; function isAccessor(node) { - return node && (node.kind === 156 || node.kind === 157); + return node && (node.kind === 156 /* GetAccessor */ || node.kind === 157 /* SetAccessor */); } ts.isAccessor = isAccessor; + /* @internal */ function isMethodOrAccessor(node) { switch (node.kind) { - case 154: - case 156: - case 157: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return true; default: return false; } } ts.isMethodOrAccessor = isMethodOrAccessor; + // Type members function isTypeElement(node) { var kind = node.kind; - return kind === 159 - || kind === 158 - || kind === 151 - || kind === 153 - || kind === 160; + return kind === 159 /* ConstructSignature */ + || kind === 158 /* CallSignature */ + || kind === 151 /* PropertySignature */ + || kind === 153 /* MethodSignature */ + || kind === 160 /* IndexSignature */; } ts.isTypeElement = isTypeElement; function isClassOrTypeElement(node) { @@ -11609,125 +13090,153 @@ var ts; ts.isClassOrTypeElement = isClassOrTypeElement; function isObjectLiteralElementLike(node) { var kind = node.kind; - return kind === 270 - || kind === 271 - || kind === 272 - || kind === 154 - || kind === 156 - || kind === 157; + return kind === 270 /* PropertyAssignment */ + || kind === 271 /* ShorthandPropertyAssignment */ + || kind === 272 /* SpreadAssignment */ + || kind === 154 /* MethodDeclaration */ + || kind === 156 /* GetAccessor */ + || kind === 157 /* SetAccessor */; } ts.isObjectLiteralElementLike = isObjectLiteralElementLike; + // Type function isTypeNodeKind(kind) { - return (kind >= 161 && kind <= 179) - || kind === 119 - || kind === 142 - || kind === 134 - || kind === 135 - || kind === 122 - || kind === 137 - || kind === 138 - || kind === 99 - || kind === 105 - || kind === 140 - || kind === 95 - || kind === 131 - || kind === 207 - || kind === 279 - || kind === 280 - || kind === 281 - || kind === 282 - || kind === 283 - || kind === 284 - || kind === 285; + return (kind >= 161 /* FirstTypeNode */ && kind <= 179 /* LastTypeNode */) + || kind === 119 /* AnyKeyword */ + || kind === 142 /* UnknownKeyword */ + || kind === 134 /* NumberKeyword */ + || kind === 135 /* ObjectKeyword */ + || kind === 122 /* BooleanKeyword */ + || kind === 137 /* StringKeyword */ + || kind === 138 /* SymbolKeyword */ + || kind === 99 /* ThisKeyword */ + || kind === 105 /* VoidKeyword */ + || kind === 140 /* UndefinedKeyword */ + || kind === 95 /* NullKeyword */ + || kind === 131 /* NeverKeyword */ + || kind === 207 /* ExpressionWithTypeArguments */ + || kind === 279 /* JSDocAllType */ + || kind === 280 /* JSDocUnknownType */ + || kind === 281 /* JSDocNullableType */ + || kind === 282 /* JSDocNonNullableType */ + || kind === 283 /* JSDocOptionalType */ + || kind === 284 /* JSDocFunctionType */ + || kind === 285 /* JSDocVariadicType */; } + /** + * Node test that determines whether a node is a valid type node. + * This differs from the `isPartOfTypeNode` function which determines whether a node is *part* + * of a TypeNode. + */ function isTypeNode(node) { return isTypeNodeKind(node.kind); } ts.isTypeNode = isTypeNode; function isFunctionOrConstructorTypeNode(node) { switch (node.kind) { - case 163: - case 164: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: return true; } return false; } ts.isFunctionOrConstructorTypeNode = isFunctionOrConstructorTypeNode; + // Binding patterns + /* @internal */ function isBindingPattern(node) { if (node) { var kind = node.kind; - return kind === 181 - || kind === 180; + return kind === 181 /* ArrayBindingPattern */ + || kind === 180 /* ObjectBindingPattern */; } return false; } ts.isBindingPattern = isBindingPattern; + /* @internal */ function isAssignmentPattern(node) { var kind = node.kind; - return kind === 183 - || kind === 184; + return kind === 183 /* ArrayLiteralExpression */ + || kind === 184 /* ObjectLiteralExpression */; } ts.isAssignmentPattern = isAssignmentPattern; + /* @internal */ function isArrayBindingElement(node) { var kind = node.kind; - return kind === 182 - || kind === 206; + return kind === 182 /* BindingElement */ + || kind === 206 /* OmittedExpression */; } ts.isArrayBindingElement = isArrayBindingElement; + /** + * Determines whether the BindingOrAssignmentElement is a BindingElement-like declaration + */ + /* @internal */ function isDeclarationBindingElement(bindingElement) { switch (bindingElement.kind) { - case 232: - case 149: - case 182: + case 232 /* VariableDeclaration */: + case 149 /* Parameter */: + case 182 /* BindingElement */: return true; } return false; } ts.isDeclarationBindingElement = isDeclarationBindingElement; + /** + * Determines whether a node is a BindingOrAssignmentPattern + */ + /* @internal */ function isBindingOrAssignmentPattern(node) { return isObjectBindingOrAssignmentPattern(node) || isArrayBindingOrAssignmentPattern(node); } ts.isBindingOrAssignmentPattern = isBindingOrAssignmentPattern; + /** + * Determines whether a node is an ObjectBindingOrAssignmentPattern + */ + /* @internal */ function isObjectBindingOrAssignmentPattern(node) { switch (node.kind) { - case 180: - case 184: + case 180 /* ObjectBindingPattern */: + case 184 /* ObjectLiteralExpression */: return true; } return false; } ts.isObjectBindingOrAssignmentPattern = isObjectBindingOrAssignmentPattern; + /** + * Determines whether a node is an ArrayBindingOrAssignmentPattern + */ + /* @internal */ function isArrayBindingOrAssignmentPattern(node) { switch (node.kind) { - case 181: - case 183: + case 181 /* ArrayBindingPattern */: + case 183 /* ArrayLiteralExpression */: return true; } return false; } ts.isArrayBindingOrAssignmentPattern = isArrayBindingOrAssignmentPattern; + /* @internal */ function isPropertyAccessOrQualifiedNameOrImportTypeNode(node) { var kind = node.kind; - return kind === 185 - || kind === 146 - || kind === 179; + return kind === 185 /* PropertyAccessExpression */ + || kind === 146 /* QualifiedName */ + || kind === 179 /* ImportType */; } ts.isPropertyAccessOrQualifiedNameOrImportTypeNode = isPropertyAccessOrQualifiedNameOrImportTypeNode; + // Expression function isPropertyAccessOrQualifiedName(node) { var kind = node.kind; - return kind === 185 - || kind === 146; + return kind === 185 /* PropertyAccessExpression */ + || kind === 146 /* QualifiedName */; } ts.isPropertyAccessOrQualifiedName = isPropertyAccessOrQualifiedName; function isCallLikeExpression(node) { switch (node.kind) { - case 257: - case 256: - case 187: - case 188: - case 189: - case 150: + case 257 /* JsxOpeningElement */: + case 256 /* JsxSelfClosingElement */: + case 187 /* CallExpression */: + case 188 /* NewExpression */: + case 189 /* TaggedTemplateExpression */: + case 150 /* Decorator */: return true; default: return false; @@ -11735,98 +13244,106 @@ var ts; } ts.isCallLikeExpression = isCallLikeExpression; function isCallOrNewExpression(node) { - return node.kind === 187 || node.kind === 188; + return node.kind === 187 /* CallExpression */ || node.kind === 188 /* NewExpression */; } ts.isCallOrNewExpression = isCallOrNewExpression; function isTemplateLiteral(node) { var kind = node.kind; - return kind === 202 - || kind === 13; + return kind === 202 /* TemplateExpression */ + || kind === 13 /* NoSubstitutionTemplateLiteral */; } ts.isTemplateLiteral = isTemplateLiteral; + /* @internal */ function isLeftHandSideExpression(node) { return isLeftHandSideExpressionKind(ts.skipPartiallyEmittedExpressions(node).kind); } ts.isLeftHandSideExpression = isLeftHandSideExpression; function isLeftHandSideExpressionKind(kind) { switch (kind) { - case 185: - case 186: - case 188: - case 187: - case 255: - case 256: - case 259: - case 189: - case 183: - case 191: - case 184: - case 205: - case 192: - case 71: - case 12: - case 8: - case 9: - case 13: - case 202: - case 86: - case 95: - case 99: - case 101: - case 97: - case 209: - case 210: - case 91: + case 185 /* PropertyAccessExpression */: + case 186 /* ElementAccessExpression */: + case 188 /* NewExpression */: + case 187 /* CallExpression */: + case 255 /* JsxElement */: + case 256 /* JsxSelfClosingElement */: + case 259 /* JsxFragment */: + case 189 /* TaggedTemplateExpression */: + case 183 /* ArrayLiteralExpression */: + case 191 /* ParenthesizedExpression */: + case 184 /* ObjectLiteralExpression */: + case 205 /* ClassExpression */: + case 192 /* FunctionExpression */: + case 71 /* Identifier */: + case 12 /* RegularExpressionLiteral */: + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: + case 13 /* NoSubstitutionTemplateLiteral */: + case 202 /* TemplateExpression */: + case 86 /* FalseKeyword */: + case 95 /* NullKeyword */: + case 99 /* ThisKeyword */: + case 101 /* TrueKeyword */: + case 97 /* SuperKeyword */: + case 209 /* NonNullExpression */: + case 210 /* MetaProperty */: + case 91 /* ImportKeyword */: // technically this is only an Expression if it's in a CallExpression return true; default: return false; } } + /* @internal */ function isUnaryExpression(node) { return isUnaryExpressionKind(ts.skipPartiallyEmittedExpressions(node).kind); } ts.isUnaryExpression = isUnaryExpression; function isUnaryExpressionKind(kind) { switch (kind) { - case 198: - case 199: - case 194: - case 195: - case 196: - case 197: - case 190: + case 198 /* PrefixUnaryExpression */: + case 199 /* PostfixUnaryExpression */: + case 194 /* DeleteExpression */: + case 195 /* TypeOfExpression */: + case 196 /* VoidExpression */: + case 197 /* AwaitExpression */: + case 190 /* TypeAssertionExpression */: return true; default: return isLeftHandSideExpressionKind(kind); } } + /* @internal */ function isUnaryExpressionWithWrite(expr) { switch (expr.kind) { - case 199: + case 199 /* PostfixUnaryExpression */: return true; - case 198: - return expr.operator === 43 || - expr.operator === 44; + case 198 /* PrefixUnaryExpression */: + return expr.operator === 43 /* PlusPlusToken */ || + expr.operator === 44 /* MinusMinusToken */; default: return false; } } ts.isUnaryExpressionWithWrite = isUnaryExpressionWithWrite; + /* @internal */ + /** + * Determines whether a node is an expression based only on its kind. + * Use `isExpressionNode` if not in transforms. + */ function isExpression(node) { return isExpressionKind(ts.skipPartiallyEmittedExpressions(node).kind); } ts.isExpression = isExpression; function isExpressionKind(kind) { switch (kind) { - case 201: - case 203: - case 193: - case 200: - case 204: - case 208: - case 206: - case 303: - case 302: + case 201 /* ConditionalExpression */: + case 203 /* YieldExpression */: + case 193 /* ArrowFunction */: + case 200 /* BinaryExpression */: + case 204 /* SpreadElement */: + case 208 /* AsExpression */: + case 206 /* OmittedExpression */: + case 303 /* CommaListExpression */: + case 302 /* PartiallyEmittedExpression */: return true; default: return isUnaryExpressionKind(kind); @@ -11834,18 +13351,21 @@ var ts; } function isAssertionExpression(node) { var kind = node.kind; - return kind === 190 - || kind === 208; + return kind === 190 /* TypeAssertionExpression */ + || kind === 208 /* AsExpression */; } ts.isAssertionExpression = isAssertionExpression; + /* @internal */ function isPartiallyEmittedExpression(node) { - return node.kind === 302; + return node.kind === 302 /* PartiallyEmittedExpression */; } ts.isPartiallyEmittedExpression = isPartiallyEmittedExpression; + /* @internal */ function isNotEmittedStatement(node) { - return node.kind === 301; + return node.kind === 301 /* NotEmittedStatement */; } ts.isNotEmittedStatement = isNotEmittedStatement; + /* @internal */ function isNotEmittedOrPartiallyEmittedNode(node) { return isNotEmittedStatement(node) || isPartiallyEmittedExpression(node); @@ -11853,152 +13373,169 @@ var ts; ts.isNotEmittedOrPartiallyEmittedNode = isNotEmittedOrPartiallyEmittedNode; function isIterationStatement(node, lookInLabeledStatements) { switch (node.kind) { - case 220: - case 221: - case 222: - case 218: - case 219: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 218 /* DoStatement */: + case 219 /* WhileStatement */: return true; - case 228: + case 228 /* LabeledStatement */: return lookInLabeledStatements && isIterationStatement(node.statement, lookInLabeledStatements); } return false; } ts.isIterationStatement = isIterationStatement; + /* @internal */ function isForInOrOfStatement(node) { - return node.kind === 221 || node.kind === 222; + return node.kind === 221 /* ForInStatement */ || node.kind === 222 /* ForOfStatement */; } ts.isForInOrOfStatement = isForInOrOfStatement; + // Element + /* @internal */ function isConciseBody(node) { return ts.isBlock(node) || isExpression(node); } ts.isConciseBody = isConciseBody; + /* @internal */ function isFunctionBody(node) { return ts.isBlock(node); } ts.isFunctionBody = isFunctionBody; + /* @internal */ function isForInitializer(node) { return ts.isVariableDeclarationList(node) || isExpression(node); } ts.isForInitializer = isForInitializer; + /* @internal */ function isModuleBody(node) { var kind = node.kind; - return kind === 240 - || kind === 239 - || kind === 71; + return kind === 240 /* ModuleBlock */ + || kind === 239 /* ModuleDeclaration */ + || kind === 71 /* Identifier */; } ts.isModuleBody = isModuleBody; + /* @internal */ function isNamespaceBody(node) { var kind = node.kind; - return kind === 240 - || kind === 239; + return kind === 240 /* ModuleBlock */ + || kind === 239 /* ModuleDeclaration */; } ts.isNamespaceBody = isNamespaceBody; + /* @internal */ function isJSDocNamespaceBody(node) { var kind = node.kind; - return kind === 71 - || kind === 239; + return kind === 71 /* Identifier */ + || kind === 239 /* ModuleDeclaration */; } ts.isJSDocNamespaceBody = isJSDocNamespaceBody; + /* @internal */ function isNamedImportBindings(node) { var kind = node.kind; - return kind === 247 - || kind === 246; + return kind === 247 /* NamedImports */ + || kind === 246 /* NamespaceImport */; } ts.isNamedImportBindings = isNamedImportBindings; + /* @internal */ function isModuleOrEnumDeclaration(node) { - return node.kind === 239 || node.kind === 238; + return node.kind === 239 /* ModuleDeclaration */ || node.kind === 238 /* EnumDeclaration */; } ts.isModuleOrEnumDeclaration = isModuleOrEnumDeclaration; function isDeclarationKind(kind) { - return kind === 193 - || kind === 182 - || kind === 235 - || kind === 205 - || kind === 155 - || kind === 238 - || kind === 273 - || kind === 252 - || kind === 234 - || kind === 192 - || kind === 156 - || kind === 245 - || kind === 243 - || kind === 248 - || kind === 236 - || kind === 262 - || kind === 154 - || kind === 153 - || kind === 239 - || kind === 242 - || kind === 246 - || kind === 149 - || kind === 270 - || kind === 152 - || kind === 151 - || kind === 157 - || kind === 271 - || kind === 237 - || kind === 148 - || kind === 232 - || kind === 298 - || kind === 292 - || kind === 299; + return kind === 193 /* ArrowFunction */ + || kind === 182 /* BindingElement */ + || kind === 235 /* ClassDeclaration */ + || kind === 205 /* ClassExpression */ + || kind === 155 /* Constructor */ + || kind === 238 /* EnumDeclaration */ + || kind === 273 /* EnumMember */ + || kind === 252 /* ExportSpecifier */ + || kind === 234 /* FunctionDeclaration */ + || kind === 192 /* FunctionExpression */ + || kind === 156 /* GetAccessor */ + || kind === 245 /* ImportClause */ + || kind === 243 /* ImportEqualsDeclaration */ + || kind === 248 /* ImportSpecifier */ + || kind === 236 /* InterfaceDeclaration */ + || kind === 262 /* JsxAttribute */ + || kind === 154 /* MethodDeclaration */ + || kind === 153 /* MethodSignature */ + || kind === 239 /* ModuleDeclaration */ + || kind === 242 /* NamespaceExportDeclaration */ + || kind === 246 /* NamespaceImport */ + || kind === 149 /* Parameter */ + || kind === 270 /* PropertyAssignment */ + || kind === 152 /* PropertyDeclaration */ + || kind === 151 /* PropertySignature */ + || kind === 157 /* SetAccessor */ + || kind === 271 /* ShorthandPropertyAssignment */ + || kind === 237 /* TypeAliasDeclaration */ + || kind === 148 /* TypeParameter */ + || kind === 232 /* VariableDeclaration */ + || kind === 298 /* JSDocTypedefTag */ + || kind === 292 /* JSDocCallbackTag */ + || kind === 299 /* JSDocPropertyTag */; } function isDeclarationStatementKind(kind) { - return kind === 234 - || kind === 253 - || kind === 235 - || kind === 236 - || kind === 237 - || kind === 238 - || kind === 239 - || kind === 244 - || kind === 243 - || kind === 250 - || kind === 249 - || kind === 242; + return kind === 234 /* FunctionDeclaration */ + || kind === 253 /* MissingDeclaration */ + || kind === 235 /* ClassDeclaration */ + || kind === 236 /* InterfaceDeclaration */ + || kind === 237 /* TypeAliasDeclaration */ + || kind === 238 /* EnumDeclaration */ + || kind === 239 /* ModuleDeclaration */ + || kind === 244 /* ImportDeclaration */ + || kind === 243 /* ImportEqualsDeclaration */ + || kind === 250 /* ExportDeclaration */ + || kind === 249 /* ExportAssignment */ + || kind === 242 /* NamespaceExportDeclaration */; } function isStatementKindButNotDeclarationKind(kind) { - return kind === 224 - || kind === 223 - || kind === 231 - || kind === 218 - || kind === 216 - || kind === 215 - || kind === 221 - || kind === 222 - || kind === 220 - || kind === 217 - || kind === 228 - || kind === 225 - || kind === 227 - || kind === 229 - || kind === 230 - || kind === 214 - || kind === 219 - || kind === 226 - || kind === 301 - || kind === 305 - || kind === 304; + return kind === 224 /* BreakStatement */ + || kind === 223 /* ContinueStatement */ + || kind === 231 /* DebuggerStatement */ + || kind === 218 /* DoStatement */ + || kind === 216 /* ExpressionStatement */ + || kind === 215 /* EmptyStatement */ + || kind === 221 /* ForInStatement */ + || kind === 222 /* ForOfStatement */ + || kind === 220 /* ForStatement */ + || kind === 217 /* IfStatement */ + || kind === 228 /* LabeledStatement */ + || kind === 225 /* ReturnStatement */ + || kind === 227 /* SwitchStatement */ + || kind === 229 /* ThrowStatement */ + || kind === 230 /* TryStatement */ + || kind === 214 /* VariableStatement */ + || kind === 219 /* WhileStatement */ + || kind === 226 /* WithStatement */ + || kind === 301 /* NotEmittedStatement */ + || kind === 305 /* EndOfDeclarationMarker */ + || kind === 304 /* MergeDeclarationMarker */; } + /* @internal */ function isDeclaration(node) { - if (node.kind === 148) { - return node.parent.kind !== 297 || ts.isInJavaScriptFile(node); + if (node.kind === 148 /* TypeParameter */) { + return node.parent.kind !== 297 /* JSDocTemplateTag */ || ts.isInJavaScriptFile(node); } return isDeclarationKind(node.kind); } ts.isDeclaration = isDeclaration; + /* @internal */ function isDeclarationStatement(node) { return isDeclarationStatementKind(node.kind); } ts.isDeclarationStatement = isDeclarationStatement; + /** + * Determines whether the node is a statement that is not also a declaration + */ + /* @internal */ function isStatementButNotDeclaration(node) { return isStatementKindButNotDeclarationKind(node.kind); } ts.isStatementButNotDeclaration = isStatementButNotDeclaration; + /* @internal */ function isStatement(node) { var kind = node.kind; return isStatementKindButNotDeclarationKind(kind) @@ -12007,156 +13544,183 @@ var ts; } ts.isStatement = isStatement; function isBlockStatement(node) { - if (node.kind !== 213) + if (node.kind !== 213 /* Block */) return false; if (node.parent !== undefined) { - if (node.parent.kind === 230 || node.parent.kind === 269) { + if (node.parent.kind === 230 /* TryStatement */ || node.parent.kind === 269 /* CatchClause */) { return false; } } return !ts.isFunctionBlock(node); } + // Module references + /* @internal */ function isModuleReference(node) { var kind = node.kind; - return kind === 254 - || kind === 146 - || kind === 71; + return kind === 254 /* ExternalModuleReference */ + || kind === 146 /* QualifiedName */ + || kind === 71 /* Identifier */; } ts.isModuleReference = isModuleReference; + // JSX + /* @internal */ function isJsxTagNameExpression(node) { var kind = node.kind; - return kind === 99 - || kind === 71 - || kind === 185; + return kind === 99 /* ThisKeyword */ + || kind === 71 /* Identifier */ + || kind === 185 /* PropertyAccessExpression */; } ts.isJsxTagNameExpression = isJsxTagNameExpression; + /* @internal */ function isJsxChild(node) { var kind = node.kind; - return kind === 255 - || kind === 265 - || kind === 256 - || kind === 10 - || kind === 259; + return kind === 255 /* JsxElement */ + || kind === 265 /* JsxExpression */ + || kind === 256 /* JsxSelfClosingElement */ + || kind === 10 /* JsxText */ + || kind === 259 /* JsxFragment */; } ts.isJsxChild = isJsxChild; + /* @internal */ function isJsxAttributeLike(node) { var kind = node.kind; - return kind === 262 - || kind === 264; + return kind === 262 /* JsxAttribute */ + || kind === 264 /* JsxSpreadAttribute */; } ts.isJsxAttributeLike = isJsxAttributeLike; + /* @internal */ function isStringLiteralOrJsxExpression(node) { var kind = node.kind; - return kind === 9 - || kind === 265; + return kind === 9 /* StringLiteral */ + || kind === 265 /* JsxExpression */; } ts.isStringLiteralOrJsxExpression = isStringLiteralOrJsxExpression; function isJsxOpeningLikeElement(node) { var kind = node.kind; - return kind === 257 - || kind === 256; + return kind === 257 /* JsxOpeningElement */ + || kind === 256 /* JsxSelfClosingElement */; } ts.isJsxOpeningLikeElement = isJsxOpeningLikeElement; + // Clauses function isCaseOrDefaultClause(node) { var kind = node.kind; - return kind === 266 - || kind === 267; + return kind === 266 /* CaseClause */ + || kind === 267 /* DefaultClause */; } ts.isCaseOrDefaultClause = isCaseOrDefaultClause; + // JSDoc + /** True if node is of some JSDoc syntax kind. */ + /* @internal */ function isJSDocNode(node) { - return node.kind >= 278 && node.kind <= 299; + return node.kind >= 278 /* FirstJSDocNode */ && node.kind <= 299 /* LastJSDocNode */; } ts.isJSDocNode = isJSDocNode; + /** True if node is of a kind that may contain comment text. */ function isJSDocCommentContainingNode(node) { - return node.kind === 286 || isJSDocTag(node) || ts.isJSDocTypeLiteral(node) || ts.isJSDocSignature(node); + return node.kind === 286 /* JSDocComment */ || isJSDocTag(node) || ts.isJSDocTypeLiteral(node) || ts.isJSDocSignature(node); } ts.isJSDocCommentContainingNode = isJSDocCommentContainingNode; + // TODO: determine what this does before making it public. + /* @internal */ function isJSDocTag(node) { - return node.kind >= 289 && node.kind <= 299; + return node.kind >= 289 /* FirstJSDocTagNode */ && node.kind <= 299 /* LastJSDocTagNode */; } ts.isJSDocTag = isJSDocTag; function isSetAccessor(node) { - return node.kind === 157; + return node.kind === 157 /* SetAccessor */; } ts.isSetAccessor = isSetAccessor; function isGetAccessor(node) { - return node.kind === 156; + return node.kind === 156 /* GetAccessor */; } ts.isGetAccessor = isGetAccessor; + /** True if has jsdoc nodes attached to it. */ + /* @internal */ + // TODO: GH#19856 Would like to return `node is Node & { jsDoc: JSDoc[] }` but it causes long compile times function hasJSDocNodes(node) { var jsDoc = node.jsDoc; return !!jsDoc && jsDoc.length > 0; } ts.hasJSDocNodes = hasJSDocNodes; + /** True if has type node attached to it. */ + /* @internal */ function hasType(node) { return !!node.type; } ts.hasType = hasType; + /* True if the node could have a type node a `.type` */ + /* @internal */ function couldHaveType(node) { switch (node.kind) { - case 149: - case 151: - case 152: - case 153: - case 154: - case 155: - case 156: - case 157: - case 158: - case 159: - case 160: - case 161: - case 163: - case 164: - case 173: - case 175: - case 177: - case 190: - case 192: - case 193: - case 208: - case 232: - case 234: - case 237: - case 278: - case 281: - case 282: - case 283: - case 284: - case 285: + case 149 /* Parameter */: + case 151 /* PropertySignature */: + case 152 /* PropertyDeclaration */: + case 153 /* MethodSignature */: + case 154 /* MethodDeclaration */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 160 /* IndexSignature */: + case 161 /* TypePredicate */: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 173 /* ParenthesizedType */: + case 175 /* TypeOperator */: + case 177 /* MappedType */: + case 190 /* TypeAssertionExpression */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 208 /* AsExpression */: + case 232 /* VariableDeclaration */: + case 234 /* FunctionDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 278 /* JSDocTypeExpression */: + case 281 /* JSDocNullableType */: + case 282 /* JSDocNonNullableType */: + case 283 /* JSDocOptionalType */: + case 284 /* JSDocFunctionType */: + case 285 /* JSDocVariadicType */: return true; } return false; } ts.couldHaveType = couldHaveType; + /** True if has initializer node attached to it. */ + /* @internal */ function hasInitializer(node) { return !!node.initializer; } ts.hasInitializer = hasInitializer; + /** True if has initializer node attached to it. */ + /* @internal */ function hasOnlyExpressionInitializer(node) { return hasInitializer(node) && !ts.isForStatement(node) && !ts.isForInStatement(node) && !ts.isForOfStatement(node) && !ts.isJsxAttribute(node); } ts.hasOnlyExpressionInitializer = hasOnlyExpressionInitializer; function isObjectLiteralElement(node) { switch (node.kind) { - case 262: - case 264: - case 270: - case 271: - case 154: - case 156: - case 157: + case 262 /* JsxAttribute */: + case 264 /* JsxSpreadAttribute */: + case 270 /* PropertyAssignment */: + case 271 /* ShorthandPropertyAssignment */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return true; default: return false; } } ts.isObjectLiteralElement = isObjectLiteralElement; + /* @internal */ function isTypeReferenceType(node) { - return node.kind === 162 || node.kind === 207; + return node.kind === 162 /* TypeReference */ || node.kind === 207 /* ExpressionWithTypeArguments */; } ts.isTypeReferenceType = isTypeReferenceType; var MAX_SMI_X86 = 1073741823; + /* @internal */ function guessIndentation(lines) { var indentation = MAX_SMI_X86; for (var _i = 0, lines_1 = lines; _i < lines_1.length; _i++) { @@ -12181,13 +13745,15 @@ var ts; } ts.guessIndentation = guessIndentation; function isStringLiteralLike(node) { - return node.kind === 9 || node.kind === 13; + return node.kind === 9 /* StringLiteral */ || node.kind === 13 /* NoSubstitutionTemplateLiteral */; } ts.isStringLiteralLike = isStringLiteralLike; })(ts || (ts = {})); +/* @internal */ (function (ts) { + /** @internal */ function isNamedImportsOrExports(node) { - return node.kind === 247 || node.kind === 251; + return node.kind === 247 /* NamedImports */ || node.kind === 251 /* NamedExports */; } ts.isNamedImportsOrExports = isNamedImportsOrExports; function Symbol(flags, name) { @@ -12205,15 +13771,15 @@ var ts; this.checker = checker; } } - function Signature() { } + function Signature() { } // tslint:disable-line no-empty function Node(kind, pos, end) { this.pos = pos; this.end = end; this.kind = kind; this.id = 0; - this.flags = 0; - this.modifierFlagsCache = 0; - this.transformFlags = 0; + this.flags = 0 /* None */; + this.modifierFlagsCache = 0 /* None */; + this.transformFlags = 0 /* None */; this.parent = undefined; this.original = undefined; } @@ -12232,6 +13798,7 @@ var ts; getSignatureConstructor: function () { return Signature; }, getSourceMapSourceConstructor: function () { return SourceMapSource; }, }; + /* @internal */ function formatStringFromArgs(text, args, baseIndex) { if (baseIndex === void 0) { baseIndex = 0; } return text.replace(/{(\d+)}/g, function (_match, index) { return ts.Debug.assertDefined(args[+index + baseIndex]); }); @@ -12263,6 +13830,7 @@ var ts; }; } ts.createFileDiagnostic = createFileDiagnostic; + /* @internal */ function formatMessage(_dummy, message) { var text = getLocaleSpecificMessage(message); if (arguments.length > 2) { @@ -12287,6 +13855,7 @@ var ts; }; } ts.createCompilerDiagnostic = createCompilerDiagnostic; + /* @internal */ function createCompilerDiagnosticFromMessageChain(chain) { return { file: undefined, @@ -12323,19 +13892,21 @@ var ts; function getDiagnosticFilePath(diagnostic) { return diagnostic.file ? diagnostic.file.path : undefined; } + /* @internal */ function compareDiagnostics(d1, d2) { return ts.compareStringsCaseSensitive(getDiagnosticFilePath(d1), getDiagnosticFilePath(d2)) || ts.compareValues(d1.start, d2.start) || ts.compareValues(d1.length, d2.length) || ts.compareValues(d1.code, d2.code) || compareMessageText(d1.messageText, d2.messageText) || - 0; + 0 /* EqualTo */; } ts.compareDiagnostics = compareDiagnostics; function compareMessageText(t1, t2) { var text1 = t1; var text2 = t2; while (text1 && text2) { + // We still have both chains. var string1 = ts.isString(text1) ? text1 : text1.messageText; var string2 = ts.isString(text2) ? text2 : text2.messageText; var res = ts.compareStringsCaseSensitive(string1, string2); @@ -12346,18 +13917,20 @@ var ts; text2 = ts.isString(text2) ? undefined : text2.next; } if (!text1 && !text2) { - return 0; + // if the chains are done, then these messages are the same. + return 0 /* EqualTo */; } - return text1 ? 1 : -1; + // We still have one chain remaining. The shorter chain should come first. + return text1 ? 1 /* GreaterThan */ : -1 /* LessThan */; } function getEmitScriptTarget(compilerOptions) { - return compilerOptions.target || 0; + return compilerOptions.target || 0 /* ES3 */; } ts.getEmitScriptTarget = getEmitScriptTarget; function getEmitModuleKind(compilerOptions) { return typeof compilerOptions.module === "number" ? compilerOptions.module : - getEmitScriptTarget(compilerOptions) >= 2 ? ts.ModuleKind.ES2015 : ts.ModuleKind.CommonJS; + getEmitScriptTarget(compilerOptions) >= 2 /* ES2015 */ ? ts.ModuleKind.ES2015 : ts.ModuleKind.CommonJS; } ts.getEmitModuleKind = getEmitModuleKind; function getEmitModuleResolutionKind(compilerOptions) { @@ -12400,11 +13973,12 @@ var ts; function hasZeroOrOneAsteriskCharacter(str) { var seenAsterisk = false; for (var i = 0; i < str.length; i++) { - if (str.charCodeAt(i) === 42) { + if (str.charCodeAt(i) === 42 /* asterisk */) { if (!seenAsterisk) { seenAsterisk = true; } else { + // have already seen asterisk return false; } } @@ -12412,78 +13986,126 @@ var ts; return true; } ts.hasZeroOrOneAsteriskCharacter = hasZeroOrOneAsteriskCharacter; + /** + * Internally, we represent paths as strings with '/' as the directory separator. + * When we make system calls (eg: LanguageServiceHost.getDirectory()), + * we expect the host to correctly handle paths in our specified format. + */ ts.directorySeparator = "/"; var altDirectorySeparator = "\\"; var urlSchemeSeparator = "://"; var backslashRegExp = /\\/g; + /** + * Normalize path separators. + */ function normalizeSlashes(path) { return path.replace(backslashRegExp, ts.directorySeparator); } ts.normalizeSlashes = normalizeSlashes; function isVolumeCharacter(charCode) { - return (charCode >= 97 && charCode <= 122) || - (charCode >= 65 && charCode <= 90); + return (charCode >= 97 /* a */ && charCode <= 122 /* z */) || + (charCode >= 65 /* A */ && charCode <= 90 /* Z */); } function getFileUrlVolumeSeparatorEnd(url, start) { var ch0 = url.charCodeAt(start); - if (ch0 === 58) + if (ch0 === 58 /* colon */) return start + 1; - if (ch0 === 37 && url.charCodeAt(start + 1) === 51) { + if (ch0 === 37 /* percent */ && url.charCodeAt(start + 1) === 51 /* _3 */) { var ch2 = url.charCodeAt(start + 2); - if (ch2 === 97 || ch2 === 65) + if (ch2 === 97 /* a */ || ch2 === 65 /* A */) return start + 3; } return -1; } + /** + * Returns length of the root part of a path or URL (i.e. length of "/", "x:/", "//server/share/, file:///user/files"). + * If the root is part of a URL, the twos-complement of the root length is returned. + */ function getEncodedRootLength(path) { if (!path) return 0; var ch0 = path.charCodeAt(0); - if (ch0 === 47 || ch0 === 92) { + // POSIX or UNC + if (ch0 === 47 /* slash */ || ch0 === 92 /* backslash */) { if (path.charCodeAt(1) !== ch0) - return 1; - var p1 = path.indexOf(ch0 === 47 ? ts.directorySeparator : altDirectorySeparator, 2); + return 1; // POSIX: "/" (or non-normalized "\") + var p1 = path.indexOf(ch0 === 47 /* slash */ ? ts.directorySeparator : altDirectorySeparator, 2); if (p1 < 0) - return path.length; - return p1 + 1; + return path.length; // UNC: "//server" or "\\server" + return p1 + 1; // UNC: "//server/" or "\\server\" } - if (isVolumeCharacter(ch0) && path.charCodeAt(1) === 58) { + // DOS + if (isVolumeCharacter(ch0) && path.charCodeAt(1) === 58 /* colon */) { var ch2 = path.charCodeAt(2); - if (ch2 === 47 || ch2 === 92) - return 3; + if (ch2 === 47 /* slash */ || ch2 === 92 /* backslash */) + return 3; // DOS: "c:/" or "c:\" if (path.length === 2) - return 2; + return 2; // DOS: "c:" (but not "c:d") } + // URL var schemeEnd = path.indexOf(urlSchemeSeparator); if (schemeEnd !== -1) { var authorityStart = schemeEnd + urlSchemeSeparator.length; var authorityEnd = path.indexOf(ts.directorySeparator, authorityStart); - if (authorityEnd !== -1) { + if (authorityEnd !== -1) { // URL: "file:///", "file://server/", "file://server/path" + // For local "file" URLs, include the leading DOS volume (if present). + // Per https://www.ietf.org/rfc/rfc1738.txt, a host of "" or "localhost" is a + // special case interpreted as "the machine from which the URL is being interpreted". var scheme = path.slice(0, schemeEnd); var authority = path.slice(authorityStart, authorityEnd); if (scheme === "file" && (authority === "" || authority === "localhost") && isVolumeCharacter(path.charCodeAt(authorityEnd + 1))) { var volumeSeparatorEnd = getFileUrlVolumeSeparatorEnd(path, authorityEnd + 2); if (volumeSeparatorEnd !== -1) { - if (path.charCodeAt(volumeSeparatorEnd) === 47) { + if (path.charCodeAt(volumeSeparatorEnd) === 47 /* slash */) { + // URL: "file:///c:/", "file://localhost/c:/", "file:///c%3a/", "file://localhost/c%3a/" return ~(volumeSeparatorEnd + 1); } if (volumeSeparatorEnd === path.length) { + // URL: "file:///c:", "file://localhost/c:", "file:///c$3a", "file://localhost/c%3a" + // but not "file:///c:d" or "file:///c%3ad" return ~volumeSeparatorEnd; } } } - return ~(authorityEnd + 1); + return ~(authorityEnd + 1); // URL: "file://server/", "http://server/" } - return ~path.length; + return ~path.length; // URL: "file://server", "http://server" } + // relative return 0; } + /** + * Returns length of the root part of a path or URL (i.e. length of "/", "x:/", "//server/share/, file:///user/files"). + * + * For example: + * ```ts + * getRootLength("a") === 0 // "" + * getRootLength("/") === 1 // "/" + * getRootLength("c:") === 2 // "c:" + * getRootLength("c:d") === 0 // "" + * getRootLength("c:/") === 3 // "c:/" + * getRootLength("c:\\") === 3 // "c:\\" + * getRootLength("//server") === 7 // "//server" + * getRootLength("//server/share") === 8 // "//server/" + * getRootLength("\\\\server") === 7 // "\\\\server" + * getRootLength("\\\\server\\share") === 8 // "\\\\server\\" + * getRootLength("file:///path") === 8 // "file:///" + * getRootLength("file:///c:") === 10 // "file:///c:" + * getRootLength("file:///c:d") === 8 // "file:///" + * getRootLength("file:///c:/path") === 11 // "file:///c:/" + * getRootLength("file://server") === 13 // "file://server" + * getRootLength("file://server/path") === 14 // "file://server/" + * getRootLength("http://server") === 13 // "http://server" + * getRootLength("http://server/path") === 14 // "http://server/" + * ``` + */ function getRootLength(path) { var rootLength = getEncodedRootLength(path); return rootLength < 0 ? ~rootLength : rootLength; } ts.getRootLength = getRootLength; + // TODO(rbuckton): replace references with `resolvePath` function normalizePath(path) { return ts.resolvePath(path); } @@ -12502,9 +14124,12 @@ var ts; ts.normalizePathAndParts = normalizePathAndParts; function getDirectoryPath(path) { path = normalizeSlashes(path); + // If the path provided is itself the root, then return it. var rootLength = getRootLength(path); if (rootLength === path.length) return path; + // return the leading portion of the path up to the last (non-terminal) directory separator + // but not including any trailing directory separator. path = ts.removeTrailingDirectorySeparator(path); return path.slice(0, Math.max(rootLength, path.lastIndexOf(ts.directorySeparator))); } @@ -12517,19 +14142,27 @@ var ts; return /^\.\.?($|[\\/])/.test(path); } ts.pathIsRelative = pathIsRelative; + /** + * Determines whether a path is an absolute path (e.g. starts with `/`, or a dos path + * like `c:`, `c:\` or `c:/`). + */ function isRootedDiskPath(path) { return getEncodedRootLength(path) > 0; } ts.isRootedDiskPath = isRootedDiskPath; + /** + * Determines whether a path consists only of a path root. + */ function isDiskPathRoot(path) { var rootLength = getEncodedRootLength(path); return rootLength > 0 && rootLength === path.length; } ts.isDiskPathRoot = isDiskPathRoot; + /* @internal */ function convertToRelativePath(absoluteOrRelativePath, basePath, getCanonicalFileName) { return !isRootedDiskPath(absoluteOrRelativePath) ? absoluteOrRelativePath - : ts.getRelativePathToDirectoryOrUrl(basePath, absoluteOrRelativePath, basePath, getCanonicalFileName, false); + : ts.getRelativePathToDirectoryOrUrl(basePath, absoluteOrRelativePath, basePath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); } ts.convertToRelativePath = convertToRelativePath; function pathComponents(path, rootLength) { @@ -12539,6 +14172,12 @@ var ts; rest.pop(); return [root].concat(rest); } + /** + * Parse a path into an array containing a root component (at index 0) and zero or more path + * components (at indices > 0). The result is not normalized. + * If the path is relative, the root component is `""`. + * If the path is absolute, the root component includes the first path separator (`/`). + */ function getPathComponents(path, currentDirectory) { if (currentDirectory === void 0) { currentDirectory = ""; } path = ts.combinePaths(currentDirectory, path); @@ -12546,6 +14185,10 @@ var ts; return pathComponents(path, rootLength); } ts.getPathComponents = getPathComponents; + /** + * Reduce an array of path components to a more simplified path by navigating any + * `"."` or `".."` entries in the path. + */ function reducePathComponents(components) { if (!ts.some(components)) return []; @@ -12571,6 +14214,12 @@ var ts; return reduced; } ts.reducePathComponents = reducePathComponents; + /** + * Parse a path into an array containing a root component (at index 0) and zero or more path + * components (at indices > 0). The result is normalized. + * If the path is relative, the root component is `""`. + * If the path is absolute, the root component includes the first path separator (`/`). + */ function getNormalizedPathComponents(path, currentDirectory) { return reducePathComponents(getPathComponents(path, currentDirectory)); } @@ -12579,6 +14228,10 @@ var ts; return getPathFromPathComponents(getNormalizedPathComponents(fileName, currentDirectory)); } ts.getNormalizedAbsolutePath = getNormalizedAbsolutePath; + /** + * Formats a parsed path consisting of a root component (at index 0) and zero or more path + * segments (at indices > 0). + */ function getPathFromPathComponents(pathComponents) { if (pathComponents.length === 0) return ""; @@ -12589,6 +14242,7 @@ var ts; } ts.getPathFromPathComponents = getPathFromPathComponents; })(ts || (ts = {})); +/* @internal */ (function (ts) { function getPathComponentsRelativeTo(from, to, stringEqualityComparer, getCanonicalFileName) { var fromComponents = ts.reducePathComponents(ts.getPathComponents(from)); @@ -12634,21 +14288,31 @@ var ts; return ts.getPathFromPathComponents(pathComponents); } ts.getRelativePathToDirectoryOrUrl = getRelativePathToDirectoryOrUrl; + /** + * Ensures a path is either absolute (prefixed with `/` or `c:`) or dot-relative (prefixed + * with `./` or `../`) so as not to be confused with an unprefixed module name. + */ function ensurePathIsNonModuleName(path) { return ts.getRootLength(path) === 0 && !ts.pathIsRelative(path) ? "./" + path : path; } ts.ensurePathIsNonModuleName = ensurePathIsNonModuleName; function getBaseFileName(path, extensions, ignoreCase) { path = ts.normalizeSlashes(path); + // if the path provided is itself the root, then it has not file name. var rootLength = ts.getRootLength(path); if (rootLength === path.length) return ""; + // return the trailing portion of the path starting after the last (non-terminal) directory + // separator but not including any trailing directory separator. path = removeTrailingDirectorySeparator(path); var name = path.slice(Math.max(ts.getRootLength(path), path.lastIndexOf(ts.directorySeparator) + 1)); var extension = extensions !== undefined && ignoreCase !== undefined ? getAnyExtensionFromPath(name, extensions, ignoreCase) : undefined; return extension ? name.slice(0, name.length - extension.length) : name; } ts.getBaseFileName = getBaseFileName; + /** + * Combines paths. If a path is absolute, it replaces any previous path. + */ function combinePaths(path) { var paths = []; for (var _i = 1; _i < arguments.length; _i++) { @@ -12671,6 +14335,10 @@ var ts; return path; } ts.combinePaths = combinePaths; + /** + * Combines and resolves paths. If a path is absolute, it replaces any previous path. Any + * `.` and `..` path components are resolved. + */ function resolvePath(path) { var paths = []; for (var _i = 1; _i < arguments.length; _i++) { @@ -12681,11 +14349,14 @@ var ts; return normalized && hasTrailingDirectorySeparator(combined) ? ensureTrailingDirectorySeparator(normalized) : normalized; } ts.resolvePath = resolvePath; + /** + * Determines whether a path has a trailing separator (`/` or `\\`). + */ function hasTrailingDirectorySeparator(path) { if (path.length === 0) return false; var ch = path.charCodeAt(path.length - 1); - return ch === 47 || ch === 92; + return ch === 47 /* slash */ || ch === 92 /* backslash */; } ts.hasTrailingDirectorySeparator = hasTrailingDirectorySeparator; function removeTrailingDirectorySeparator(path) { @@ -12704,27 +14375,33 @@ var ts; ts.ensureTrailingDirectorySeparator = ensureTrailingDirectorySeparator; function comparePathsWorker(a, b, componentComparer) { if (a === b) - return 0; + return 0 /* EqualTo */; if (a === undefined) - return -1; + return -1 /* LessThan */; if (b === undefined) - return 1; + return 1 /* GreaterThan */; var aComponents = ts.reducePathComponents(ts.getPathComponents(a)); var bComponents = ts.reducePathComponents(ts.getPathComponents(b)); var sharedLength = Math.min(aComponents.length, bComponents.length); for (var i = 0; i < sharedLength; i++) { var stringComparer = i === 0 ? ts.compareStringsCaseInsensitive : componentComparer; var result = stringComparer(aComponents[i], bComponents[i]); - if (result !== 0) { + if (result !== 0 /* EqualTo */) { return result; } } return ts.compareValues(aComponents.length, bComponents.length); } + /** + * Performs a case-sensitive comparison of two paths. + */ function comparePathsCaseSensitive(a, b) { return comparePathsWorker(a, b, ts.compareStringsCaseSensitive); } ts.comparePathsCaseSensitive = comparePathsCaseSensitive; + /** + * Performs a case-insensitive comparison of two paths. + */ function comparePathsCaseInsensitive(a, b) { return comparePathsWorker(a, b, ts.compareStringsCaseInsensitive); } @@ -12772,16 +14449,19 @@ var ts; if (a === undefined) return undefined; switch (a.charCodeAt(0)) { - case 47: - case 92: + case 47 /* slash */: + case 92 /* backslash */: return a.slice(1); default: return undefined; } } ts.tryRemoveDirectoryPrefix = tryRemoveDirectoryPrefix; + // Reserved characters, forces escaping of any non-word (or digit), non-whitespace character. + // It may be inefficient (we could just match (/[-[\]{}()*+?.,\\^$|#\s]/g), but this is future + // proof. var reservedCharacterPattern = /[^\w\s\/]/g; - var wildcardCharCodes = [42, 63]; + var wildcardCharCodes = [42 /* asterisk */, 63 /* question */]; function hasExtension(fileName) { return ts.stringContains(getBaseFileName(fileName), "."); } @@ -12789,12 +14469,26 @@ var ts; ts.commonPackageFolders = ["node_modules", "bower_components", "jspm_packages"]; var implicitExcludePathRegexPattern = "(?!(" + ts.commonPackageFolders.join("|") + ")(/|$))"; var filesMatcher = { + /** + * Matches any single directory segment unless it is the last segment and a .min.js file + * Breakdown: + * [^./] # matches everything up to the first . character (excluding directory separators) + * (\\.(?!min\\.js$))? # matches . characters but not if they are part of the .min.js file extension + */ singleAsteriskRegexFragment: "([^./]|(\\.(?!min\\.js$))?)*", + /** + * Regex for the ** wildcard. Matches any number of subdirectories. When used for including + * files or directories, does not match subdirectories that start with a . character + */ doubleAsteriskRegexFragment: "(/" + implicitExcludePathRegexPattern + "[^/.][^/]*)*?", replaceWildcardCharacter: function (match) { return replaceWildcardCharacter(match, filesMatcher.singleAsteriskRegexFragment); } }; var directoriesMatcher = { singleAsteriskRegexFragment: "[^/]*", + /** + * Regex for the ** wildcard. Matches any number of subdirectories. When used for including + * files or directories, does not match subdirectories that start with a . character + */ doubleAsteriskRegexFragment: "(/" + implicitExcludePathRegexPattern + "[^/.][^/]*)*?", replaceWildcardCharacter: function (match) { return replaceWildcardCharacter(match, directoriesMatcher.singleAsteriskRegexFragment); } }; @@ -12814,6 +14508,7 @@ var ts; return undefined; } var pattern = patterns.map(function (pattern) { return "(" + pattern + ")"; }).join("|"); + // If excluding, match "foo/bar/baz...", but if including, only allow "foo". var terminator = usage === "exclude" ? "($|/)" : "$"; return "^(" + pattern + ")" + terminator; } @@ -12826,6 +14521,10 @@ var ts; return spec && getSubPatternFromSpec(spec, basePath, usage, wildcardMatchers[usage]); }); } + /** + * An "includes" path "foo" is implicitly a glob "foo/** /*" (without the space) if its last component has no extension, + * and does not contain any glob characters itself. + */ function isImplicitGlob(lastPathComponent) { return !/[.*?]/.test(lastPathComponent); } @@ -12839,6 +14538,8 @@ var ts; if (usage !== "exclude" && lastComponent === "**") { return undefined; } + // getNormalizedPathComponents includes the separator for the root component. + // We need to remove to create our regex correctly. components[0] = removeTrailingDirectorySeparator(components[0]); if (isImplicitGlob(lastComponent)) { components.push("**", "*"); @@ -12859,15 +14560,24 @@ var ts; } if (usage !== "exclude") { var componentPattern = ""; - if (component.charCodeAt(0) === 42) { + // The * and ? wildcards should not match directories or files that start with . if they + // appear first in a component. Dotted directories and files can be included explicitly + // like so: **/.*/.* + if (component.charCodeAt(0) === 42 /* asterisk */) { componentPattern += "([^./]" + singleAsteriskRegexFragment + ")?"; component = component.substr(1); } - else if (component.charCodeAt(0) === 63) { + else if (component.charCodeAt(0) === 63 /* question */) { componentPattern += "[^./]"; component = component.substr(1); } componentPattern += component.replace(reservedCharacterPattern, replaceWildcardCharacter); + // Patterns should not include subfolders like node_modules unless they are + // explicitly included as part of the path. + // + // As an optimization, if the component pattern is the same as the component, + // then there definitely were no wildcard characters and we do not need to + // add the exclusion pattern. if (componentPattern !== component) { subpattern += implicitExcludePathRegexPattern; } @@ -12888,6 +14598,7 @@ var ts; function replaceWildcardCharacter(match, singleAsteriskRegexFragment) { return match === "*" ? singleAsteriskRegexFragment : match === "?" ? "[^/]" : "\\" + match; } + /** @param path directory of the tsconfig.json */ function getFileMatcherPatterns(path, excludes, includes, useCaseSensitiveFileNames, currentDirectory) { path = ts.normalizePath(path); currentDirectory = ts.normalizePath(currentDirectory); @@ -12905,6 +14616,7 @@ var ts; return new RegExp(pattern, useCaseSensitiveFileNames ? "" : "i"); } ts.getRegexFromPattern = getRegexFromPattern; + /** @param path directory of the tsconfig.json */ function matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, currentDirectory, depth, getFileSystemEntries) { path = ts.normalizePath(path); currentDirectory = ts.normalizePath(currentDirectory); @@ -12912,6 +14624,8 @@ var ts; var includeFileRegexes = patterns.includeFilePatterns && patterns.includeFilePatterns.map(function (pattern) { return getRegexFromPattern(pattern, useCaseSensitiveFileNames); }); var includeDirectoryRegex = patterns.includeDirectoryPattern && getRegexFromPattern(patterns.includeDirectoryPattern, useCaseSensitiveFileNames); var excludeRegex = patterns.excludePattern && getRegexFromPattern(patterns.excludePattern, useCaseSensitiveFileNames); + // Associate an array of results with each include regex. This keeps results in order of the "include" order. + // If there are no "includes", then just put everything in results[0]. var results = includeFileRegexes ? includeFileRegexes.map(function () { return []; }) : [[]]; for (var _i = 0, _a = patterns.basePaths; _i < _a.length; _i++) { var basePath = _a[_i]; @@ -12959,21 +14673,32 @@ var ts; } } ts.matchFiles = matchFiles; + /** + * Computes the unique non-wildcard base paths amongst the provided include patterns. + */ function getBasePaths(path, includes, useCaseSensitiveFileNames) { + // Storage for our results in the form of literal paths (e.g. the paths as written by the user). var basePaths = [path]; if (includes) { + // Storage for literal base paths amongst the include patterns. var includeBasePaths = []; for (var _i = 0, includes_1 = includes; _i < includes_1.length; _i++) { var include = includes_1[_i]; + // We also need to check the relative paths by converting them to absolute and normalizing + // in case they escape the base path (e.g "..\somedirectory") var absolute = ts.isRootedDiskPath(include) ? include : ts.normalizePath(combinePaths(path, include)); + // Append the literal and canonical candidate base paths. includeBasePaths.push(getIncludeBasePath(absolute)); } + // Sort the offsets array using either the literal or canonical path representations. includeBasePaths.sort(ts.getStringComparer(!useCaseSensitiveFileNames)); var _loop_2 = function (includeBasePath) { if (ts.every(basePaths, function (basePath) { return !containsPath(basePath, includeBasePath, path, !useCaseSensitiveFileNames); })) { basePaths.push(includeBasePath); } }; + // Iterate over each include base path and include unique base paths that are not a + // subpath of an existing base path for (var _a = 0, includeBasePaths_1 = includeBasePaths; _a < includeBasePaths_1.length; _a++) { var includeBasePath = includeBasePaths_1[_a]; _loop_2(includeBasePath); @@ -12984,6 +14709,7 @@ var ts; function getIncludeBasePath(absolute) { var wildcardOffset = ts.indexOfAnyCharCode(absolute, wildcardCharCodes); if (wildcardOffset < 0) { + // No "*" or "?" in the path return !hasExtension(absolute) ? absolute : removeTrailingDirectorySeparator(ts.getDirectoryPath(absolute)); @@ -12991,42 +14717,52 @@ var ts; return absolute.substring(0, absolute.lastIndexOf(ts.directorySeparator, wildcardOffset)); } function ensureScriptKind(fileName, scriptKind) { - return scriptKind || getScriptKindFromFileName(fileName) || 3; + // Using scriptKind as a condition handles both: + // - 'scriptKind' is unspecified and thus it is `undefined` + // - 'scriptKind' is set and it is `Unknown` (0) + // If the 'scriptKind' is 'undefined' or 'Unknown' then we attempt + // to get the ScriptKind from the file name. If it cannot be resolved + // from the file name then the default 'TS' script kind is returned. + return scriptKind || getScriptKindFromFileName(fileName) || 3 /* TS */; } ts.ensureScriptKind = ensureScriptKind; function getScriptKindFromFileName(fileName) { var ext = fileName.substr(fileName.lastIndexOf(".")); switch (ext.toLowerCase()) { - case ".js": - return 1; - case ".jsx": - return 2; - case ".ts": - return 3; - case ".tsx": - return 4; - case ".json": - return 6; + case ".js" /* Js */: + return 1 /* JS */; + case ".jsx" /* Jsx */: + return 2 /* JSX */; + case ".ts" /* Ts */: + return 3 /* TS */; + case ".tsx" /* Tsx */: + return 4 /* TSX */; + case ".json" /* Json */: + return 6 /* JSON */; default: - return 0; + return 0 /* Unknown */; } } ts.getScriptKindFromFileName = getScriptKindFromFileName; - ts.supportedTypeScriptExtensions = [".ts", ".tsx", ".d.ts"]; - ts.supportedTypescriptExtensionsForExtractExtension = [".d.ts", ".ts", ".tsx"]; - ts.supportedJavascriptExtensions = [".js", ".jsx"]; + /** + * List of supported extensions in order of file resolution precedence. + */ + ts.supportedTypeScriptExtensions = [".ts" /* Ts */, ".tsx" /* Tsx */, ".d.ts" /* Dts */]; + /** Must have ".d.ts" first because if ".ts" goes first, that will be detected as the extension instead of ".d.ts". */ + ts.supportedTypescriptExtensionsForExtractExtension = [".d.ts" /* Dts */, ".ts" /* Ts */, ".tsx" /* Tsx */]; + ts.supportedJavascriptExtensions = [".js" /* Js */, ".jsx" /* Jsx */]; var allSupportedExtensions = ts.supportedTypeScriptExtensions.concat(ts.supportedJavascriptExtensions); function getSupportedExtensions(options, extraFileExtensions) { var needJsExtensions = options && options.allowJs; if (!extraFileExtensions || extraFileExtensions.length === 0) { return needJsExtensions ? allSupportedExtensions : ts.supportedTypeScriptExtensions; } - var extensions = (needJsExtensions ? allSupportedExtensions : ts.supportedTypeScriptExtensions).concat(ts.mapDefined(extraFileExtensions, function (x) { return x.scriptKind === 7 || needJsExtensions && isJavaScriptLike(x.scriptKind) ? x.extension : undefined; })); + var extensions = (needJsExtensions ? allSupportedExtensions : ts.supportedTypeScriptExtensions).concat(ts.mapDefined(extraFileExtensions, function (x) { return x.scriptKind === 7 /* Deferred */ || needJsExtensions && isJavaScriptLike(x.scriptKind) ? x.extension : undefined; })); return ts.deduplicate(extensions, ts.equateStringsCaseSensitive, ts.compareStringsCaseSensitive); } ts.getSupportedExtensions = getSupportedExtensions; function isJavaScriptLike(scriptKind) { - return scriptKind === 1 || scriptKind === 2; + return scriptKind === 1 /* JS */ || scriptKind === 2 /* JSX */; } function hasJavaScriptFileExtension(fileName) { return ts.some(ts.supportedJavascriptExtensions, function (extension) { return ts.fileExtensionIs(fileName, extension); }); @@ -13049,6 +14785,11 @@ var ts; return false; } ts.isSupportedSourceFileName = isSupportedSourceFileName; + /** + * Extension boundaries by priority. Lower numbers indicate higher priorities, and are + * aligned to the offset of the highest priority extension in the + * allSupportedExtensions array. + */ var ExtensionPriority; (function (ExtensionPriority) { ExtensionPriority[ExtensionPriority["TypeScriptFiles"] = 0] = "TypeScriptFiles"; @@ -13062,31 +14803,39 @@ var ts; return adjustExtensionPriority(i, supportedExtensions); } } - return 0; + // If its not in the list of supported extensions, this is likely a + // TypeScript file with a non-ts extension + return 0 /* Highest */; } ts.getExtensionPriority = getExtensionPriority; + /** + * Adjusts an extension priority to be the highest priority within the same range. + */ function adjustExtensionPriority(extensionPriority, supportedExtensions) { - if (extensionPriority < 2) { - return 0; + if (extensionPriority < 2 /* DeclarationAndJavaScriptFiles */) { + return 0 /* TypeScriptFiles */; } else if (extensionPriority < supportedExtensions.length) { - return 2; + return 2 /* DeclarationAndJavaScriptFiles */; } else { return supportedExtensions.length; } } ts.adjustExtensionPriority = adjustExtensionPriority; + /** + * Gets the next lowest extension priority for a given priority. + */ function getNextLowestExtensionPriority(extensionPriority, supportedExtensions) { - if (extensionPriority < 2) { - return 2; + if (extensionPriority < 2 /* DeclarationAndJavaScriptFiles */) { + return 2 /* DeclarationAndJavaScriptFiles */; } else { return supportedExtensions.length; } } ts.getNextLowestExtensionPriority = getNextLowestExtensionPriority; - var extensionsToRemove = [".d.ts", ".ts", ".js", ".tsx", ".jsx", ".json"]; + var extensionsToRemove = [".d.ts" /* Dts */, ".ts" /* Ts */, ".js" /* Js */, ".tsx" /* Tsx */, ".jsx" /* Jsx */, ".json" /* Json */]; function removeFileExtension(path) { for (var _i = 0, extensionsToRemove_1 = extensionsToRemove; _i < extensionsToRemove_1.length; _i++) { var ext = extensionsToRemove_1[_i]; @@ -13107,7 +14856,7 @@ var ts; } ts.removeExtension = removeExtension; function changeExtension(path, newExtension) { - return changeAnyExtension(path, newExtension, extensionsToRemove, false); + return changeAnyExtension(path, newExtension, extensionsToRemove, /*ignoreCase*/ false); } ts.changeExtension = changeExtension; function changeAnyExtension(path, ext, extensions, ignoreCase) { @@ -13139,6 +14888,7 @@ var ts; Debug.showSyntaxKind = showSyntaxKind; })(Debug = ts.Debug || (ts.Debug = {})); function tryParsePattern(pattern) { + // This should be verified outside of here and a proper error thrown. Debug.assert(ts.hasZeroOrOneAsteriskCharacter(pattern)); var indexOfStar = pattern.indexOf("*"); return indexOfStar === -1 ? undefined : { @@ -13148,17 +14898,24 @@ var ts; } ts.tryParsePattern = tryParsePattern; function positionIsSynthesized(pos) { + // This is a fast way of testing the following conditions: + // pos === undefined || pos === null || isNaN(pos) || pos < 0; return !(pos >= 0); } ts.positionIsSynthesized = positionIsSynthesized; + /** True if an extension is one of the supported TypeScript extensions. */ function extensionIsTypeScript(ext) { - return ext === ".ts" || ext === ".tsx" || ext === ".d.ts"; + return ext === ".ts" /* Ts */ || ext === ".tsx" /* Tsx */ || ext === ".d.ts" /* Dts */; } ts.extensionIsTypeScript = extensionIsTypeScript; function resolutionExtensionIsTypeScriptOrJson(ext) { - return extensionIsTypeScript(ext) || ext === ".json"; + return extensionIsTypeScript(ext) || ext === ".json" /* Json */; } ts.resolutionExtensionIsTypeScriptOrJson = resolutionExtensionIsTypeScriptOrJson; + /** + * Gets the extension from a path. + * Path must have a valid extension. + */ function extensionFromPath(path) { var ext = tryGetExtensionFromPath(path); return ext !== undefined ? ext : Debug.fail("File " + path + " has unknown extension."); @@ -13189,6 +14946,8 @@ var ts; return ""; } function getAnyExtensionFromPath(path, extensions, ignoreCase) { + // Retrieves any string from the final "." onwards from a base file name. + // Unlike extensionFromPath, which throws an exception on unrecognized extensions. if (extensions) { return getAnyExtensionFromPathWorker(path, extensions, ignoreCase ? ts.equateStringsCaseInsensitive : ts.equateStringsCaseSensitive); } @@ -13208,6 +14967,11 @@ var ts; files: ts.emptyArray, directories: ts.emptyArray }; + /** + * patternStrings contains both pattern strings (containing "*") and regular strings. + * Return an exact match if possible, or a pattern match, or undefined. + * (These are verified by verifyCompilerOptions to have 0 or 1 "*" characters.) + */ function matchPatternOrExact(patternStrings, candidate) { var patterns = []; for (var _i = 0, patternStrings_1 = patternStrings; _i < patternStrings_1.length; _i++) { @@ -13217,6 +14981,7 @@ var ts; patterns.push(pattern); } else if (patternString === candidate) { + // pattern was matched as is - no need to search further return patternString; } } @@ -13235,15 +15000,17 @@ var ts; SignatureFlags[SignatureFlags["IgnoreMissingOpenBrace"] = 16] = "IgnoreMissingOpenBrace"; SignatureFlags[SignatureFlags["JSDoc"] = 32] = "JSDoc"; })(SignatureFlags || (SignatureFlags = {})); + // tslint:disable variable-name var NodeConstructor; var TokenConstructor; var IdentifierConstructor; var SourceFileConstructor; + // tslint:enable variable-name function createNode(kind, pos, end) { - if (kind === 274) { + if (kind === 274 /* SourceFile */) { return new (SourceFileConstructor || (SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor()))(kind, pos, end); } - else if (kind === 71) { + else if (kind === 71 /* Identifier */) { return new (IdentifierConstructor || (IdentifierConstructor = ts.objectAllocator.getIdentifierConstructor()))(kind, pos, end); } else if (!ts.isNodeKind(kind)) { @@ -13271,35 +15038,49 @@ var ts; } } } + /*@internal*/ function isJSDocLikeText(text, start) { - return text.charCodeAt(start + 1) === 42 && - text.charCodeAt(start + 2) === 42 && - text.charCodeAt(start + 3) !== 47; + return text.charCodeAt(start + 1) === 42 /* asterisk */ && + text.charCodeAt(start + 2) === 42 /* asterisk */ && + text.charCodeAt(start + 3) !== 47 /* slash */; } ts.isJSDocLikeText = isJSDocLikeText; + /** + * Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes + * stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise, + * embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns + * a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned. + * + * @param node a given node to visit its children + * @param cbNode a callback to be invoked for all child nodes + * @param cbNodes a callback to be invoked for embedded array + * + * @remarks `forEachChild` must visit the children of a node in the order + * that they appear in the source code. The language service depends on this property to locate nodes by position. + */ function forEachChild(node, cbNode, cbNodes) { - if (!node || node.kind <= 145) { + if (!node || node.kind <= 145 /* LastToken */) { return; } switch (node.kind) { - case 146: + case 146 /* QualifiedName */: return visitNode(cbNode, node.left) || visitNode(cbNode, node.right); - case 148: + case 148 /* TypeParameter */: return visitNode(cbNode, node.name) || visitNode(cbNode, node.constraint) || visitNode(cbNode, node.default) || visitNode(cbNode, node.expression); - case 271: + case 271 /* ShorthandPropertyAssignment */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.equalsToken) || visitNode(cbNode, node.objectAssignmentInitializer); - case 272: + case 272 /* SpreadAssignment */: return visitNode(cbNode, node.expression); - case 149: + case 149 /* Parameter */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.dotDotDotToken) || @@ -13307,7 +15088,7 @@ var ts; visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.type) || visitNode(cbNode, node.initializer); - case 152: + case 152 /* PropertyDeclaration */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || @@ -13315,51 +15096,51 @@ var ts; visitNode(cbNode, node.exclamationToken) || visitNode(cbNode, node.type) || visitNode(cbNode, node.initializer); - case 151: + case 151 /* PropertySignature */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.type) || visitNode(cbNode, node.initializer); - case 270: + case 270 /* PropertyAssignment */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.initializer); - case 232: + case 232 /* VariableDeclaration */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.exclamationToken) || visitNode(cbNode, node.type) || visitNode(cbNode, node.initializer); - case 182: + case 182 /* BindingElement */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.dotDotDotToken) || visitNode(cbNode, node.propertyName) || visitNode(cbNode, node.name) || visitNode(cbNode, node.initializer); - case 163: - case 164: - case 158: - case 159: - case 160: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 160 /* IndexSignature */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type); - case 154: - case 153: - case 155: - case 156: - case 157: - case 192: - case 234: - case 193: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 192 /* FunctionExpression */: + case 234 /* FunctionDeclaration */: + case 193 /* ArrowFunction */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.asteriskToken) || @@ -13370,304 +15151,304 @@ var ts; visitNode(cbNode, node.type) || visitNode(cbNode, node.equalsGreaterThanToken) || visitNode(cbNode, node.body); - case 162: + case 162 /* TypeReference */: return visitNode(cbNode, node.typeName) || visitNodes(cbNode, cbNodes, node.typeArguments); - case 161: + case 161 /* TypePredicate */: return visitNode(cbNode, node.parameterName) || visitNode(cbNode, node.type); - case 165: + case 165 /* TypeQuery */: return visitNode(cbNode, node.exprName); - case 166: + case 166 /* TypeLiteral */: return visitNodes(cbNode, cbNodes, node.members); - case 167: + case 167 /* ArrayType */: return visitNode(cbNode, node.elementType); - case 168: + case 168 /* TupleType */: return visitNodes(cbNode, cbNodes, node.elementTypes); - case 169: - case 170: + case 169 /* UnionType */: + case 170 /* IntersectionType */: return visitNodes(cbNode, cbNodes, node.types); - case 171: + case 171 /* ConditionalType */: return visitNode(cbNode, node.checkType) || visitNode(cbNode, node.extendsType) || visitNode(cbNode, node.trueType) || visitNode(cbNode, node.falseType); - case 172: + case 172 /* InferType */: return visitNode(cbNode, node.typeParameter); - case 179: + case 179 /* ImportType */: return visitNode(cbNode, node.argument) || visitNode(cbNode, node.qualifier) || visitNodes(cbNode, cbNodes, node.typeArguments); - case 173: - case 175: + case 173 /* ParenthesizedType */: + case 175 /* TypeOperator */: return visitNode(cbNode, node.type); - case 176: + case 176 /* IndexedAccessType */: return visitNode(cbNode, node.objectType) || visitNode(cbNode, node.indexType); - case 177: + case 177 /* MappedType */: return visitNode(cbNode, node.readonlyToken) || visitNode(cbNode, node.typeParameter) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.type); - case 178: + case 178 /* LiteralType */: return visitNode(cbNode, node.literal); - case 180: - case 181: + case 180 /* ObjectBindingPattern */: + case 181 /* ArrayBindingPattern */: return visitNodes(cbNode, cbNodes, node.elements); - case 183: + case 183 /* ArrayLiteralExpression */: return visitNodes(cbNode, cbNodes, node.elements); - case 184: + case 184 /* ObjectLiteralExpression */: return visitNodes(cbNode, cbNodes, node.properties); - case 185: + case 185 /* PropertyAccessExpression */: return visitNode(cbNode, node.expression) || visitNode(cbNode, node.name); - case 186: + case 186 /* ElementAccessExpression */: return visitNode(cbNode, node.expression) || visitNode(cbNode, node.argumentExpression); - case 187: - case 188: + case 187 /* CallExpression */: + case 188 /* NewExpression */: return visitNode(cbNode, node.expression) || visitNodes(cbNode, cbNodes, node.typeArguments) || visitNodes(cbNode, cbNodes, node.arguments); - case 189: + case 189 /* TaggedTemplateExpression */: return visitNode(cbNode, node.tag) || visitNodes(cbNode, cbNodes, node.typeArguments) || visitNode(cbNode, node.template); - case 190: + case 190 /* TypeAssertionExpression */: return visitNode(cbNode, node.type) || visitNode(cbNode, node.expression); - case 191: + case 191 /* ParenthesizedExpression */: return visitNode(cbNode, node.expression); - case 194: + case 194 /* DeleteExpression */: return visitNode(cbNode, node.expression); - case 195: + case 195 /* TypeOfExpression */: return visitNode(cbNode, node.expression); - case 196: + case 196 /* VoidExpression */: return visitNode(cbNode, node.expression); - case 198: + case 198 /* PrefixUnaryExpression */: return visitNode(cbNode, node.operand); - case 203: + case 203 /* YieldExpression */: return visitNode(cbNode, node.asteriskToken) || visitNode(cbNode, node.expression); - case 197: + case 197 /* AwaitExpression */: return visitNode(cbNode, node.expression); - case 199: + case 199 /* PostfixUnaryExpression */: return visitNode(cbNode, node.operand); - case 200: + case 200 /* BinaryExpression */: return visitNode(cbNode, node.left) || visitNode(cbNode, node.operatorToken) || visitNode(cbNode, node.right); - case 208: + case 208 /* AsExpression */: return visitNode(cbNode, node.expression) || visitNode(cbNode, node.type); - case 209: + case 209 /* NonNullExpression */: return visitNode(cbNode, node.expression); - case 210: + case 210 /* MetaProperty */: return visitNode(cbNode, node.name); - case 201: + case 201 /* ConditionalExpression */: return visitNode(cbNode, node.condition) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.whenTrue) || visitNode(cbNode, node.colonToken) || visitNode(cbNode, node.whenFalse); - case 204: + case 204 /* SpreadElement */: return visitNode(cbNode, node.expression); - case 213: - case 240: + case 213 /* Block */: + case 240 /* ModuleBlock */: return visitNodes(cbNode, cbNodes, node.statements); - case 274: + case 274 /* SourceFile */: return visitNodes(cbNode, cbNodes, node.statements) || visitNode(cbNode, node.endOfFileToken); - case 214: + case 214 /* VariableStatement */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.declarationList); - case 233: + case 233 /* VariableDeclarationList */: return visitNodes(cbNode, cbNodes, node.declarations); - case 216: + case 216 /* ExpressionStatement */: return visitNode(cbNode, node.expression); - case 217: + case 217 /* IfStatement */: return visitNode(cbNode, node.expression) || visitNode(cbNode, node.thenStatement) || visitNode(cbNode, node.elseStatement); - case 218: + case 218 /* DoStatement */: return visitNode(cbNode, node.statement) || visitNode(cbNode, node.expression); - case 219: + case 219 /* WhileStatement */: return visitNode(cbNode, node.expression) || visitNode(cbNode, node.statement); - case 220: + case 220 /* ForStatement */: return visitNode(cbNode, node.initializer) || visitNode(cbNode, node.condition) || visitNode(cbNode, node.incrementor) || visitNode(cbNode, node.statement); - case 221: + case 221 /* ForInStatement */: return visitNode(cbNode, node.initializer) || visitNode(cbNode, node.expression) || visitNode(cbNode, node.statement); - case 222: + case 222 /* ForOfStatement */: return visitNode(cbNode, node.awaitModifier) || visitNode(cbNode, node.initializer) || visitNode(cbNode, node.expression) || visitNode(cbNode, node.statement); - case 223: - case 224: + case 223 /* ContinueStatement */: + case 224 /* BreakStatement */: return visitNode(cbNode, node.label); - case 225: + case 225 /* ReturnStatement */: return visitNode(cbNode, node.expression); - case 226: + case 226 /* WithStatement */: return visitNode(cbNode, node.expression) || visitNode(cbNode, node.statement); - case 227: + case 227 /* SwitchStatement */: return visitNode(cbNode, node.expression) || visitNode(cbNode, node.caseBlock); - case 241: + case 241 /* CaseBlock */: return visitNodes(cbNode, cbNodes, node.clauses); - case 266: + case 266 /* CaseClause */: return visitNode(cbNode, node.expression) || visitNodes(cbNode, cbNodes, node.statements); - case 267: + case 267 /* DefaultClause */: return visitNodes(cbNode, cbNodes, node.statements); - case 228: + case 228 /* LabeledStatement */: return visitNode(cbNode, node.label) || visitNode(cbNode, node.statement); - case 229: + case 229 /* ThrowStatement */: return visitNode(cbNode, node.expression); - case 230: + case 230 /* TryStatement */: return visitNode(cbNode, node.tryBlock) || visitNode(cbNode, node.catchClause) || visitNode(cbNode, node.finallyBlock); - case 269: + case 269 /* CatchClause */: return visitNode(cbNode, node.variableDeclaration) || visitNode(cbNode, node.block); - case 150: + case 150 /* Decorator */: return visitNode(cbNode, node.expression); - case 235: - case 205: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.heritageClauses) || visitNodes(cbNode, cbNodes, node.members); - case 236: + case 236 /* InterfaceDeclaration */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.heritageClauses) || visitNodes(cbNode, cbNodes, node.members); - case 237: + case 237 /* TypeAliasDeclaration */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNode(cbNode, node.type); - case 238: + case 238 /* EnumDeclaration */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.members); - case 273: + case 273 /* EnumMember */: return visitNode(cbNode, node.name) || visitNode(cbNode, node.initializer); - case 239: + case 239 /* ModuleDeclaration */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.body); - case 243: + case 243 /* ImportEqualsDeclaration */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.moduleReference); - case 244: + case 244 /* ImportDeclaration */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.importClause) || visitNode(cbNode, node.moduleSpecifier); - case 245: + case 245 /* ImportClause */: return visitNode(cbNode, node.name) || visitNode(cbNode, node.namedBindings); - case 242: + case 242 /* NamespaceExportDeclaration */: return visitNode(cbNode, node.name); - case 246: + case 246 /* NamespaceImport */: return visitNode(cbNode, node.name); - case 247: - case 251: + case 247 /* NamedImports */: + case 251 /* NamedExports */: return visitNodes(cbNode, cbNodes, node.elements); - case 250: + case 250 /* ExportDeclaration */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.exportClause) || visitNode(cbNode, node.moduleSpecifier); - case 248: - case 252: + case 248 /* ImportSpecifier */: + case 252 /* ExportSpecifier */: return visitNode(cbNode, node.propertyName) || visitNode(cbNode, node.name); - case 249: + case 249 /* ExportAssignment */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.expression); - case 202: + case 202 /* TemplateExpression */: return visitNode(cbNode, node.head) || visitNodes(cbNode, cbNodes, node.templateSpans); - case 211: + case 211 /* TemplateSpan */: return visitNode(cbNode, node.expression) || visitNode(cbNode, node.literal); - case 147: + case 147 /* ComputedPropertyName */: return visitNode(cbNode, node.expression); - case 268: + case 268 /* HeritageClause */: return visitNodes(cbNode, cbNodes, node.types); - case 207: + case 207 /* ExpressionWithTypeArguments */: return visitNode(cbNode, node.expression) || visitNodes(cbNode, cbNodes, node.typeArguments); - case 254: + case 254 /* ExternalModuleReference */: return visitNode(cbNode, node.expression); - case 253: + case 253 /* MissingDeclaration */: return visitNodes(cbNode, cbNodes, node.decorators); - case 303: + case 303 /* CommaListExpression */: return visitNodes(cbNode, cbNodes, node.elements); - case 255: + case 255 /* JsxElement */: return visitNode(cbNode, node.openingElement) || visitNodes(cbNode, cbNodes, node.children) || visitNode(cbNode, node.closingElement); - case 259: + case 259 /* JsxFragment */: return visitNode(cbNode, node.openingFragment) || visitNodes(cbNode, cbNodes, node.children) || visitNode(cbNode, node.closingFragment); - case 256: - case 257: + case 256 /* JsxSelfClosingElement */: + case 257 /* JsxOpeningElement */: return visitNode(cbNode, node.tagName) || visitNodes(cbNode, cbNodes, node.typeArguments) || visitNode(cbNode, node.attributes); - case 263: + case 263 /* JsxAttributes */: return visitNodes(cbNode, cbNodes, node.properties); - case 262: + case 262 /* JsxAttribute */: return visitNode(cbNode, node.name) || visitNode(cbNode, node.initializer); - case 264: + case 264 /* JsxSpreadAttribute */: return visitNode(cbNode, node.expression); - case 265: + case 265 /* JsxExpression */: return visitNode(cbNode, node.dotDotDotToken) || visitNode(cbNode, node.expression); - case 258: + case 258 /* JsxClosingElement */: return visitNode(cbNode, node.tagName); - case 278: + case 278 /* JSDocTypeExpression */: return visitNode(cbNode, node.type); - case 282: + case 282 /* JSDocNonNullableType */: return visitNode(cbNode, node.type); - case 281: + case 281 /* JSDocNullableType */: return visitNode(cbNode, node.type); - case 283: + case 283 /* JSDocOptionalType */: return visitNode(cbNode, node.type); - case 284: + case 284 /* JSDocFunctionType */: return visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type); - case 285: + case 285 /* JSDocVariadicType */: return visitNode(cbNode, node.type); - case 286: + case 286 /* JSDocComment */: return visitNodes(cbNode, cbNodes, node.tags); - case 293: - case 299: + case 293 /* JSDocParameterTag */: + case 299 /* JSDocPropertyTag */: if (node.isNameFirst) { return visitNode(cbNode, node.name) || visitNode(cbNode, node.typeExpression); @@ -13676,17 +15457,17 @@ var ts; return visitNode(cbNode, node.typeExpression) || visitNode(cbNode, node.name); } - case 294: + case 294 /* JSDocReturnTag */: return visitNode(cbNode, node.typeExpression); - case 296: + case 296 /* JSDocTypeTag */: return visitNode(cbNode, node.typeExpression); - case 290: + case 290 /* JSDocAugmentsTag */: return visitNode(cbNode, node.class); - case 297: + case 297 /* JSDocTemplateTag */: return visitNodes(cbNode, cbNodes, node.typeParameters); - case 298: + case 298 /* JSDocTypedefTag */: if (node.typeExpression && - node.typeExpression.kind === 278) { + node.typeExpression.kind === 278 /* JSDocTypeExpression */) { return visitNode(cbNode, node.typeExpression) || visitNode(cbNode, node.fullName); } @@ -13694,18 +15475,18 @@ var ts; return visitNode(cbNode, node.fullName) || visitNode(cbNode, node.typeExpression); } - case 292: + case 292 /* JSDocCallbackTag */: return visitNode(cbNode, node.fullName) || visitNode(cbNode, node.typeExpression); - case 295: + case 295 /* JSDocThisTag */: return visitNode(cbNode, node.typeExpression); - case 288: + case 288 /* JSDocSignature */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type); - case 287: + case 287 /* JSDocTypeLiteral */: if (node.jsDocPropertyTags) { for (var _i = 0, _a = node.jsDocPropertyTags; _i < _a.length; _i++) { var tag = _a[_i]; @@ -13713,7 +15494,7 @@ var ts; } } return; - case 302: + case 302 /* PartiallyEmittedExpression */: return visitNode(cbNode, node.expression); } } @@ -13722,11 +15503,11 @@ var ts; if (setParentNodes === void 0) { setParentNodes = false; } ts.performance.mark("beforeParse"); var result; - if (languageVersion === 100) { - result = Parser.parseJsonText(fileName, sourceText, languageVersion, undefined, setParentNodes); + if (languageVersion === 100 /* JSON */) { + result = Parser.parseJsonText(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes); } else { - result = Parser.parseSourceFile(fileName, sourceText, languageVersion, undefined, setParentNodes, scriptKind); + result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind); } ts.performance.mark("afterParse"); ts.performance.measure("Parse", "beforeParse", "afterParse"); @@ -13737,41 +15518,71 @@ var ts; return Parser.parseIsolatedEntityName(text, languageVersion); } ts.parseIsolatedEntityName = parseIsolatedEntityName; + /** + * Parse json text into SyntaxTree and return node and parse errors if any + * @param fileName + * @param sourceText + */ function parseJsonText(fileName, sourceText) { return Parser.parseJsonText(fileName, sourceText); } ts.parseJsonText = parseJsonText; + // See also `isExternalOrCommonJsModule` in utilities.ts function isExternalModule(file) { return file.externalModuleIndicator !== undefined; } ts.isExternalModule = isExternalModule; + // Produces a new SourceFile for the 'newText' provided. The 'textChangeRange' parameter + // indicates what changed between the 'text' that this SourceFile has and the 'newText'. + // The SourceFile will be created with the compiler attempting to reuse as many nodes from + // this file as possible. + // + // Note: this function mutates nodes from this SourceFile. That means any existing nodes + // from this SourceFile that are being held onto may change as a result (including + // becoming detached from any SourceFile). It is recommended that this SourceFile not + // be used once 'update' is called on it. function updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks) { if (aggressiveChecks === void 0) { aggressiveChecks = false; } var newSourceFile = IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); - newSourceFile.flags |= (sourceFile.flags & 1572864); + // Because new source file node is created, it may not have the flag PossiblyContainDynamicImport. This is the case if there is no new edit to add dynamic import. + // We will manually port the flag to the new source file. + newSourceFile.flags |= (sourceFile.flags & 1572864 /* PermanentlySetIncrementalFlags */); return newSourceFile; } ts.updateSourceFile = updateSourceFile; + /* @internal */ function parseIsolatedJSDocComment(content, start, length) { var result = Parser.JSDocParser.parseIsolatedJSDocComment(content, start, length); if (result && result.jsDoc) { + // because the jsDocComment was parsed out of the source file, it might + // not be covered by the fixupParentReferences. Parser.fixupParentReferences(result.jsDoc); } return result; } ts.parseIsolatedJSDocComment = parseIsolatedJSDocComment; + /* @internal */ + // Exposed only for testing. function parseJSDocTypeExpressionForTests(content, start, length) { return Parser.JSDocParser.parseJSDocTypeExpressionForTests(content, start, length); } ts.parseJSDocTypeExpressionForTests = parseJSDocTypeExpressionForTests; + // Implement the parser as a singleton module. We do this for perf reasons because creating + // parser instances can actually be expensive enough to impact us on projects with many source + // files. var Parser; (function (Parser) { - var scanner = ts.createScanner(6, true); - var disallowInAndDecoratorContext = 2048 | 8192; + // Share a single scanner across all calls to parse a source file. This helps speed things + // up by avoiding the cost of creating/compiling scanners over and over again. + var scanner = ts.createScanner(6 /* Latest */, /*skipTrivia*/ true); + var disallowInAndDecoratorContext = 2048 /* DisallowInContext */ | 8192 /* DecoratorContext */; + // capture constructors in 'initializeState' to avoid null checks + // tslint:disable variable-name var NodeConstructor; var TokenConstructor; var IdentifierConstructor; var SourceFileConstructor; + // tslint:enable variable-name var sourceFile; var parseDiagnostics; var syntaxCursor; @@ -13781,14 +15592,87 @@ var ts; var identifiers; var identifierCount; var parsingContext; + // Flags that dictate what parsing context we're in. For example: + // Whether or not we are in strict parsing mode. All that changes in strict parsing mode is + // that some tokens that would be considered identifiers may be considered keywords. + // + // When adding more parser context flags, consider which is the more common case that the + // flag will be in. This should be the 'false' state for that flag. The reason for this is + // that we don't store data in our nodes unless the value is in the *non-default* state. So, + // for example, more often than code 'allows-in' (or doesn't 'disallow-in'). We opt for + // 'disallow-in' set to 'false'. Otherwise, if we had 'allowsIn' set to 'true', then almost + // all nodes would need extra state on them to store this info. + // + // Note: 'allowIn' and 'allowYield' track 1:1 with the [in] and [yield] concepts in the ES6 + // grammar specification. + // + // An important thing about these context concepts. By default they are effectively inherited + // while parsing through every grammar production. i.e. if you don't change them, then when + // you parse a sub-production, it will have the same context values as the parent production. + // This is great most of the time. After all, consider all the 'expression' grammar productions + // and how nearly all of them pass along the 'in' and 'yield' context values: + // + // EqualityExpression[In, Yield] : + // RelationalExpression[?In, ?Yield] + // EqualityExpression[?In, ?Yield] == RelationalExpression[?In, ?Yield] + // EqualityExpression[?In, ?Yield] != RelationalExpression[?In, ?Yield] + // EqualityExpression[?In, ?Yield] === RelationalExpression[?In, ?Yield] + // EqualityExpression[?In, ?Yield] !== RelationalExpression[?In, ?Yield] + // + // Where you have to be careful is then understanding what the points are in the grammar + // where the values are *not* passed along. For example: + // + // SingleNameBinding[Yield,GeneratorParameter] + // [+GeneratorParameter]BindingIdentifier[Yield] Initializer[In]opt + // [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt + // + // Here this is saying that if the GeneratorParameter context flag is set, that we should + // explicitly set the 'yield' context flag to false before calling into the BindingIdentifier + // and we should explicitly unset the 'yield' context flag before calling into the Initializer. + // production. Conversely, if the GeneratorParameter context flag is not set, then we + // should leave the 'yield' context flag alone. + // + // Getting this all correct is tricky and requires careful reading of the grammar to + // understand when these values should be changed versus when they should be inherited. + // + // Note: it should not be necessary to save/restore these flags during speculative/lookahead + // parsing. These context flags are naturally stored and restored through normal recursive + // descent parsing and unwinding. var contextFlags; + // Whether or not we've had a parse error since creating the last AST node. If we have + // encountered an error, it will be stored on the next AST node we create. Parse errors + // can be broken down into three categories: + // + // 1) An error that occurred during scanning. For example, an unterminated literal, or a + // character that was completely not understood. + // + // 2) A token was expected, but was not present. This type of error is commonly produced + // by the 'parseExpected' function. + // + // 3) A token was present that no parsing function was able to consume. This type of error + // only occurs in the 'abortParsingListOrMoveToNextToken' function when the parser + // decides to skip the token. + // + // In all of these cases, we want to mark the next node as having had an error before it. + // With this mark, we can know in incremental settings if this node can be reused, or if + // we have to reparse it. If we don't keep this information around, we may just reuse the + // node. in that event we would then not produce the same errors as we did before, causing + // significant confusion problems. + // + // Note: it is necessary that this value be saved/restored during speculative/lookahead + // parsing. During lookahead parsing, we will often create a node. That node will have + // this value attached, and then this value will be set back to 'false'. If we decide to + // rewind, we must get back to the same value we had prior to the lookahead. + // + // Note: any errors at the end of the file that do not precede a regular node, should get + // attached to the EOF token. var parseErrorBeforeNextFinishedNode = false; function parseSourceFile(fileName, sourceText, languageVersion, syntaxCursor, setParentNodes, scriptKind) { if (setParentNodes === void 0) { setParentNodes = false; } scriptKind = ts.ensureScriptKind(fileName, scriptKind); - if (scriptKind === 6) { + if (scriptKind === 6 /* JSON */) { var result_1 = parseJsonText(fileName, sourceText, languageVersion, syntaxCursor, setParentNodes); - ts.convertToObjectWorker(result_1, result_1.parseDiagnostics, false, undefined, undefined); + ts.convertToObjectWorker(result_1, result_1.parseDiagnostics, /*returnValue*/ false, /*knownRootOptions*/ undefined, /*jsonConversionNotifier*/ undefined); result_1.typeReferenceDirectives = ts.emptyArray; result_1.amdDependencies = ts.emptyArray; return result_1; @@ -13800,57 +15684,62 @@ var ts; } Parser.parseSourceFile = parseSourceFile; function parseIsolatedEntityName(content, languageVersion) { - initializeState(content, languageVersion, undefined, 1); + // Choice of `isDeclarationFile` should be arbitrary + initializeState(content, languageVersion, /*syntaxCursor*/ undefined, 1 /* JS */); + // Prime the scanner. nextToken(); - var entityName = parseEntityName(true); - var isInvalid = token() === 1 && !parseDiagnostics.length; + var entityName = parseEntityName(/*allowReservedWords*/ true); + var isInvalid = token() === 1 /* EndOfFileToken */ && !parseDiagnostics.length; clearState(); return isInvalid ? entityName : undefined; } Parser.parseIsolatedEntityName = parseIsolatedEntityName; function parseJsonText(fileName, sourceText, languageVersion, syntaxCursor, setParentNodes) { - if (languageVersion === void 0) { languageVersion = 2; } - initializeState(sourceText, languageVersion, syntaxCursor, 6); - sourceFile = createSourceFile(fileName, 2, 6, false); + if (languageVersion === void 0) { languageVersion = 2 /* ES2015 */; } + initializeState(sourceText, languageVersion, syntaxCursor, 6 /* JSON */); + // Set source file so that errors will be reported with this file name + sourceFile = createSourceFile(fileName, 2 /* ES2015 */, 6 /* JSON */, /*isDeclaration*/ false); sourceFile.flags = contextFlags; + // Prime the scanner. nextToken(); var pos = getNodePos(); - if (token() === 1) { + if (token() === 1 /* EndOfFileToken */) { sourceFile.statements = createNodeArray([], pos, pos); sourceFile.endOfFileToken = parseTokenNode(); } else { - var statement = createNode(216); + var statement = createNode(216 /* ExpressionStatement */); switch (token()) { - case 21: + case 21 /* OpenBracketToken */: statement.expression = parseArrayLiteralExpression(); break; - case 101: - case 86: - case 95: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: + case 95 /* NullKeyword */: statement.expression = parseTokenNode(); break; - case 38: - if (lookAhead(function () { return nextToken() === 8 && nextToken() !== 56; })) { + case 38 /* MinusToken */: + if (lookAhead(function () { return nextToken() === 8 /* NumericLiteral */ && nextToken() !== 56 /* ColonToken */; })) { statement.expression = parsePrefixUnaryExpression(); } else { statement.expression = parseObjectLiteralExpression(); } break; - case 8: - case 9: - if (lookAhead(function () { return nextToken() !== 56; })) { + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: + if (lookAhead(function () { return nextToken() !== 56 /* ColonToken */; })) { statement.expression = parseLiteralNode(); break; } + // falls through default: statement.expression = parseObjectLiteralExpression(); break; } finishNode(statement); sourceFile.statements = createNodeArray([statement], pos); - sourceFile.endOfFileToken = parseExpectedToken(1, ts.Diagnostics.Unexpected_token); + sourceFile.endOfFileToken = parseExpectedToken(1 /* EndOfFileToken */, ts.Diagnostics.Unexpected_token); } if (setParentNodes) { fixupParentReferences(sourceFile); @@ -13862,7 +15751,8 @@ var ts; } Parser.parseJsonText = parseJsonText; function getLanguageVariant(scriptKind) { - return scriptKind === 4 || scriptKind === 2 || scriptKind === 1 || scriptKind === 6 ? 1 : 0; + // .tsx and .jsx files are treated as jsx language variant. + return scriptKind === 4 /* TSX */ || scriptKind === 2 /* JSX */ || scriptKind === 1 /* JS */ || scriptKind === 6 /* JSON */ ? 1 /* JSX */ : 0 /* Standard */; } function initializeState(_sourceText, languageVersion, _syntaxCursor, scriptKind) { NodeConstructor = ts.objectAllocator.getNodeConstructor(); @@ -13877,26 +15767,29 @@ var ts; identifierCount = 0; nodeCount = 0; switch (scriptKind) { - case 1: - case 2: - contextFlags = 65536; + case 1 /* JS */: + case 2 /* JSX */: + contextFlags = 65536 /* JavaScriptFile */; break; - case 6: - contextFlags = 65536 | 16777216; + case 6 /* JSON */: + contextFlags = 65536 /* JavaScriptFile */ | 16777216 /* JsonFile */; break; default: - contextFlags = 0; + contextFlags = 0 /* None */; break; } parseErrorBeforeNextFinishedNode = false; + // Initialize and prime the scanner before parsing the source elements. scanner.setText(sourceText); scanner.setOnError(scanError); scanner.setScriptTarget(languageVersion); scanner.setLanguageVariant(getLanguageVariant(scriptKind)); } function clearState() { + // Clear out the text the scanner is pointing at, so it doesn't keep anything alive unnecessarily. scanner.setText(""); scanner.setOnError(undefined); + // Clear any data. We don't want to accidentally hold onto it for too long. parseDiagnostics = undefined; sourceFile = undefined; identifiers = undefined; @@ -13906,15 +15799,17 @@ var ts; function parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind) { var isDeclarationFile = isDeclarationFileName(fileName); if (isDeclarationFile) { - contextFlags |= 4194304; + contextFlags |= 4194304 /* Ambient */; } sourceFile = createSourceFile(fileName, languageVersion, scriptKind, isDeclarationFile); sourceFile.flags = contextFlags; + // Prime the scanner. nextToken(); + // A member of ReadonlyArray isn't assignable to a member of T[] (and prevents a direct cast) - but this is where we set up those members so they can be readonly in the future processCommentPragmas(sourceFile, sourceText); processPragmasIntoFields(sourceFile, reportPragmaDiagnostic); - sourceFile.statements = parseList(0, parseStatement); - ts.Debug.assert(token() === 1); + sourceFile.statements = parseList(0 /* SourceElements */, parseStatement); + ts.Debug.assert(token() === 1 /* EndOfFileToken */); sourceFile.endOfFileToken = addJSDocComment(parseTokenNode()); setExternalModuleIndicator(sourceFile); sourceFile.nodeCount = nodeCount; @@ -13940,10 +15835,17 @@ var ts; return node; } function fixupParentReferences(rootNode) { + // normally parent references are set during binding. However, for clients that only need + // a syntax tree, and no semantic features, then the binding process is an unnecessary + // overhead. This functions allows us to set all the parents, without all the expense of + // binding. var parent = rootNode; forEachChild(rootNode, visitNode); return; function visitNode(n) { + // walk down setting parents that differ from the parent we think it should be. This + // allows us to quickly bail out of setting parents for subtrees during incremental + // parsing if (n.parent !== parent) { n.parent = parent; var saveParent = parent; @@ -13963,7 +15865,9 @@ var ts; } Parser.fixupParentReferences = fixupParentReferences; function createSourceFile(fileName, languageVersion, scriptKind, isDeclarationFile) { - var sourceFile = new SourceFileConstructor(274, 0, sourceText.length); + // code from createNode is inlined here so createNode won't have to deal with special case of creating source files + // this is quite rare comparing to other nodes and createNode should be as fast as possible + var sourceFile = new SourceFileConstructor(274 /* SourceFile */, /*pos*/ 0, /* end */ sourceText.length); nodeCount++; sourceFile.text = sourceText; sourceFile.bindDiagnostics = []; @@ -13984,81 +15888,102 @@ var ts; } } function setDisallowInContext(val) { - setContextFlag(val, 2048); + setContextFlag(val, 2048 /* DisallowInContext */); } function setYieldContext(val) { - setContextFlag(val, 4096); + setContextFlag(val, 4096 /* YieldContext */); } function setDecoratorContext(val) { - setContextFlag(val, 8192); + setContextFlag(val, 8192 /* DecoratorContext */); } function setAwaitContext(val) { - setContextFlag(val, 16384); + setContextFlag(val, 16384 /* AwaitContext */); } function doOutsideOfContext(context, func) { + // contextFlagsToClear will contain only the context flags that are + // currently set that we need to temporarily clear + // We don't just blindly reset to the previous flags to ensure + // that we do not mutate cached flags for the incremental + // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and + // HasAggregatedChildData). var contextFlagsToClear = context & contextFlags; if (contextFlagsToClear) { - setContextFlag(false, contextFlagsToClear); + // clear the requested context flags + setContextFlag(/*val*/ false, contextFlagsToClear); var result = func(); - setContextFlag(true, contextFlagsToClear); + // restore the context flags we just cleared + setContextFlag(/*val*/ true, contextFlagsToClear); return result; } + // no need to do anything special as we are not in any of the requested contexts return func(); } function doInsideOfContext(context, func) { + // contextFlagsToSet will contain only the context flags that + // are not currently set that we need to temporarily enable. + // We don't just blindly reset to the previous flags to ensure + // that we do not mutate cached flags for the incremental + // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and + // HasAggregatedChildData). var contextFlagsToSet = context & ~contextFlags; if (contextFlagsToSet) { - setContextFlag(true, contextFlagsToSet); + // set the requested context flags + setContextFlag(/*val*/ true, contextFlagsToSet); var result = func(); - setContextFlag(false, contextFlagsToSet); + // reset the context flags we just set + setContextFlag(/*val*/ false, contextFlagsToSet); return result; } + // no need to do anything special as we are already in all of the requested contexts return func(); } function allowInAnd(func) { - return doOutsideOfContext(2048, func); + return doOutsideOfContext(2048 /* DisallowInContext */, func); } function disallowInAnd(func) { - return doInsideOfContext(2048, func); + return doInsideOfContext(2048 /* DisallowInContext */, func); } function doInYieldContext(func) { - return doInsideOfContext(4096, func); + return doInsideOfContext(4096 /* YieldContext */, func); } function doInDecoratorContext(func) { - return doInsideOfContext(8192, func); + return doInsideOfContext(8192 /* DecoratorContext */, func); } function doInAwaitContext(func) { - return doInsideOfContext(16384, func); + return doInsideOfContext(16384 /* AwaitContext */, func); } function doOutsideOfAwaitContext(func) { - return doOutsideOfContext(16384, func); + return doOutsideOfContext(16384 /* AwaitContext */, func); } function doInYieldAndAwaitContext(func) { - return doInsideOfContext(4096 | 16384, func); + return doInsideOfContext(4096 /* YieldContext */ | 16384 /* AwaitContext */, func); } function inContext(flags) { return (contextFlags & flags) !== 0; } function inYieldContext() { - return inContext(4096); + return inContext(4096 /* YieldContext */); } function inDisallowInContext() { - return inContext(2048); + return inContext(2048 /* DisallowInContext */); } function inDecoratorContext() { - return inContext(8192); + return inContext(8192 /* DecoratorContext */); } function inAwaitContext() { - return inContext(16384); + return inContext(16384 /* AwaitContext */); } function parseErrorAtCurrentToken(message, arg0) { parseErrorAt(scanner.getTokenPos(), scanner.getTextPos(), message, arg0); } function parseErrorAtPosition(start, length, message, arg0) { + // Don't report another error if it would just be at the same position as the last error. var lastError = ts.lastOrUndefined(parseDiagnostics); if (!lastError || start !== lastError.start) { parseDiagnostics.push(ts.createFileDiagnostic(sourceFile, start, length, message, arg0)); } + // Mark that we've encountered an error. We'll set an appropriate bit on the next + // node we finish so that it can't be reused incrementally. parseErrorBeforeNextFinishedNode = true; } function parseErrorAt(start, end, message, arg0) { @@ -14073,6 +15998,12 @@ var ts; function getNodePos() { return scanner.getStartPos(); } + // Use this function to access the current token instead of reading the currentToken + // variable. Since function results aren't narrowed in control flow analysis, this ensures + // that the type checker doesn't make wrong assumptions about the type of the current + // token (e.g. a call to nextToken() changes the current token but the checker doesn't + // reason about this side effect). Mainstream VMs inline simple functions like this, so + // there is no performance penalty. function token() { return currentToken; } @@ -14098,14 +16029,25 @@ var ts; return currentToken = scanner.scanJsxAttributeValue(); } function speculationHelper(callback, isLookAhead) { + // Keep track of the state we'll need to rollback to if lookahead fails (or if the + // caller asked us to always reset our state). var saveToken = currentToken; var saveParseDiagnosticsLength = parseDiagnostics.length; var saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode; + // Note: it is not actually necessary to save/restore the context flags here. That's + // because the saving/restoring of these flags happens naturally through the recursive + // descent nature of our parser. However, we still store this here just so we can + // assert that invariant holds. var saveContextFlags = contextFlags; + // If we're only looking ahead, then tell the scanner to only lookahead as well. + // Otherwise, if we're actually speculatively parsing, then tell the scanner to do the + // same. var result = isLookAhead ? scanner.lookAhead(callback) : scanner.tryScan(callback); ts.Debug.assert(saveContextFlags === contextFlags); + // If our callback returned something 'falsy' or we're just looking ahead, + // then unconditionally restore us to where we were. if (!result || isLookAhead) { currentToken = saveToken; parseDiagnostics.length = saveParseDiagnosticsLength; @@ -14113,23 +16055,37 @@ var ts; } return result; } + /** Invokes the provided callback then unconditionally restores the parser to the state it + * was in immediately prior to invoking the callback. The result of invoking the callback + * is returned from this function. + */ function lookAhead(callback) { - return speculationHelper(callback, true); + return speculationHelper(callback, /*isLookAhead*/ true); } + /** Invokes the provided callback. If the callback returns something falsy, then it restores + * the parser to the state it was in immediately prior to invoking the callback. If the + * callback returns something truthy, then the parser state is not rolled back. The result + * of invoking the callback is returned from this function. + */ function tryParse(callback) { - return speculationHelper(callback, false); + return speculationHelper(callback, /*isLookAhead*/ false); } + // Ignore strict mode flag because we will report an error in type checker instead. function isIdentifier() { - if (token() === 71) { + if (token() === 71 /* Identifier */) { return true; } - if (token() === 116 && inYieldContext()) { + // If we have a 'yield' keyword, and we're in the [yield] context, then 'yield' is + // considered a keyword and is not an identifier. + if (token() === 116 /* YieldKeyword */ && inYieldContext()) { return false; } - if (token() === 121 && inAwaitContext()) { + // If we have a 'await' keyword, and we're in the [Await] context, then 'await' is + // considered a keyword and is not an identifier. + if (token() === 121 /* AwaitKeyword */ && inAwaitContext()) { return false; } - return token() > 107; + return token() > 107 /* LastReservedWord */; } function parseExpected(kind, diagnosticMessage, shouldAdvance) { if (shouldAdvance === void 0) { shouldAdvance = true; } @@ -14139,6 +16095,7 @@ var ts; } return true; } + // Report specific message if provided with one. Otherwise, report generic fallback message. if (diagnosticMessage) { parseErrorAtCurrentToken(diagnosticMessage); } @@ -14162,7 +16119,7 @@ var ts; } function parseExpectedToken(t, diagnosticMessage, arg0) { return parseOptionalToken(t) || - createMissingNode(t, false, diagnosticMessage || ts.Diagnostics._0_expected, arg0 || ts.tokenToString(t)); + createMissingNode(t, /*reportAtCurrentPosition*/ false, diagnosticMessage || ts.Diagnostics._0_expected, arg0 || ts.tokenToString(t)); } function parseTokenNode() { var node = createNode(token()); @@ -14170,37 +16127,43 @@ var ts; return finishNode(node); } function canParseSemicolon() { - if (token() === 25) { + // If there's a real semicolon, then we can always parse it out. + if (token() === 25 /* SemicolonToken */) { return true; } - return token() === 18 || token() === 1 || scanner.hasPrecedingLineBreak(); + // We can parse out an optional semicolon in ASI cases in the following cases. + return token() === 18 /* CloseBraceToken */ || token() === 1 /* EndOfFileToken */ || scanner.hasPrecedingLineBreak(); } function parseSemicolon() { if (canParseSemicolon()) { - if (token() === 25) { + if (token() === 25 /* SemicolonToken */) { + // consume the semicolon if it was explicitly provided. nextToken(); } return true; } else { - return parseExpected(25); + return parseExpected(25 /* SemicolonToken */); } } function createNode(kind, pos) { nodeCount++; var p = pos >= 0 ? pos : scanner.getStartPos(); - return ts.isNodeKind(kind) || kind === 0 ? new NodeConstructor(kind, p, p) : - kind === 71 ? new IdentifierConstructor(kind, p, p) : + return ts.isNodeKind(kind) || kind === 0 /* Unknown */ ? new NodeConstructor(kind, p, p) : + kind === 71 /* Identifier */ ? new IdentifierConstructor(kind, p, p) : new TokenConstructor(kind, p, p); } function createNodeWithJSDoc(kind, pos) { var node = createNode(kind, pos); - if (scanner.getTokenFlags() & 2) { + if (scanner.getTokenFlags() & 2 /* PrecedingJSDocComment */) { addJSDocComment(node); } return node; } function createNodeArray(elements, pos, end) { + // Since the element list of a node array is typically created by starting with an empty array and + // repeatedly calling push(), the list may not have the optimal memory layout. We invoke slice() for + // small arrays (1 to 4 elements) to give the VM a chance to allocate an optimal representation. var length = elements.length; var array = (length >= 1 && length <= 4 ? elements.slice() : elements); array.pos = pos; @@ -14212,9 +16175,12 @@ var ts; if (contextFlags) { node.flags |= contextFlags; } + // Keep track on the node if we encountered an error while parsing it. If we did, then + // we cannot reuse the node incrementally. Once we've marked this node, clear out the + // flag so that we don't mark any subsequent nodes. if (parseErrorBeforeNextFinishedNode) { parseErrorBeforeNextFinishedNode = false; - node.flags |= 32768; + node.flags |= 32768 /* ThisNodeHasError */; } return node; } @@ -14226,7 +16192,7 @@ var ts; parseErrorAtCurrentToken(diagnosticMessage, arg0); } var result = createNode(kind); - if (kind === 71) { + if (kind === 71 /* Identifier */) { result.escapedText = ""; } else if (ts.isLiteralKind(kind) || ts.isTemplateLiteralKind(kind)) { @@ -14241,19 +16207,24 @@ var ts; } return identifier; } + // An identifier that starts with two underscores has an extra underscore character prepended to it to avoid issues + // with magic property names like '__proto__'. The 'identifiers' object is used to share a single string instance for + // each identifier in order to reduce memory consumption. function createIdentifier(isIdentifier, diagnosticMessage) { identifierCount++; if (isIdentifier) { - var node = createNode(71); - if (token() !== 71) { + var node = createNode(71 /* Identifier */); + // Store original token kind if it is not just an Identifier so we can report appropriate error later in type checker + if (token() !== 71 /* Identifier */) { node.originalKeywordKind = token(); } node.escapedText = ts.escapeLeadingUnderscores(internIdentifier(scanner.getTokenValue())); nextToken(); return finishNode(node); } - var reportAtCurrentPosition = token() === 1; - return createMissingNode(71, reportAtCurrentPosition, diagnosticMessage || ts.Diagnostics.Identifier_expected); + // Only for end of file because the error gets reported incorrectly on embedded script tags. + var reportAtCurrentPosition = token() === 1 /* EndOfFileToken */; + return createMissingNode(71 /* Identifier */, reportAtCurrentPosition, diagnosticMessage || ts.Diagnostics.Identifier_expected); } function parseIdentifier(diagnosticMessage) { return createIdentifier(isIdentifier(), diagnosticMessage); @@ -14263,28 +16234,34 @@ var ts; } function isLiteralPropertyName() { return ts.tokenIsIdentifierOrKeyword(token()) || - token() === 9 || - token() === 8; + token() === 9 /* StringLiteral */ || + token() === 8 /* NumericLiteral */; } function parsePropertyNameWorker(allowComputedPropertyNames) { - if (token() === 9 || token() === 8) { + if (token() === 9 /* StringLiteral */ || token() === 8 /* NumericLiteral */) { var node = parseLiteralNode(); node.text = internIdentifier(node.text); return node; } - if (allowComputedPropertyNames && token() === 21) { + if (allowComputedPropertyNames && token() === 21 /* OpenBracketToken */) { return parseComputedPropertyName(); } return parseIdentifierName(); } function parsePropertyName() { - return parsePropertyNameWorker(true); + return parsePropertyNameWorker(/*allowComputedPropertyNames*/ true); } function parseComputedPropertyName() { - var node = createNode(147); - parseExpected(21); + // PropertyName [Yield]: + // LiteralPropertyName + // ComputedPropertyName[?Yield] + var node = createNode(147 /* ComputedPropertyName */); + parseExpected(21 /* OpenBracketToken */); + // We parse any expression (including a comma expression). But the grammar + // says that only an assignment expression is allowed, so the grammar checker + // will error if it sees a comma expression. node.expression = allowInAnd(parseExpression); - parseExpected(22); + parseExpected(22 /* CloseBracketToken */); return finishNode(node); } function parseContextualModifier(t) { @@ -14299,19 +16276,20 @@ var ts; } function nextTokenCanFollowModifier() { switch (token()) { - case 76: - return nextToken() === 83; - case 84: + case 76 /* ConstKeyword */: + // 'const' is only a modifier if followed by 'enum'. + return nextToken() === 83 /* EnumKeyword */; + case 84 /* ExportKeyword */: nextToken(); - if (token() === 79) { + if (token() === 79 /* DefaultKeyword */) { return lookAhead(nextTokenCanFollowDefaultKeyword); } - return token() !== 39 && token() !== 118 && token() !== 17 && canFollowModifier(); - case 79: + return token() !== 39 /* AsteriskToken */ && token() !== 118 /* AsKeyword */ && token() !== 17 /* OpenBraceToken */ && canFollowModifier(); + case 79 /* DefaultKeyword */: return nextTokenCanFollowDefaultKeyword(); - case 115: - case 125: - case 136: + case 115 /* StaticKeyword */: + case 125 /* GetKeyword */: + case 136 /* SetKeyword */: nextToken(); return canFollowModifier(); default: @@ -14322,86 +16300,112 @@ var ts; return ts.isModifierKind(token()) && tryParse(nextTokenCanFollowModifier); } function canFollowModifier() { - return token() === 21 - || token() === 17 - || token() === 39 - || token() === 24 + return token() === 21 /* OpenBracketToken */ + || token() === 17 /* OpenBraceToken */ + || token() === 39 /* AsteriskToken */ + || token() === 24 /* DotDotDotToken */ || isLiteralPropertyName(); } function nextTokenCanFollowDefaultKeyword() { nextToken(); - return token() === 75 || token() === 89 || - token() === 109 || - (token() === 117 && lookAhead(nextTokenIsClassKeywordOnSameLine)) || - (token() === 120 && lookAhead(nextTokenIsFunctionKeywordOnSameLine)); + return token() === 75 /* ClassKeyword */ || token() === 89 /* FunctionKeyword */ || + token() === 109 /* InterfaceKeyword */ || + (token() === 117 /* AbstractKeyword */ && lookAhead(nextTokenIsClassKeywordOnSameLine)) || + (token() === 120 /* AsyncKeyword */ && lookAhead(nextTokenIsFunctionKeywordOnSameLine)); } + // True if positioned at the start of a list element function isListElement(parsingContext, inErrorRecovery) { var node = currentNode(parsingContext); if (node) { return true; } switch (parsingContext) { - case 0: - case 1: - case 3: - return !(token() === 25 && inErrorRecovery) && isStartOfStatement(); - case 2: - return token() === 73 || token() === 79; - case 4: + case 0 /* SourceElements */: + case 1 /* BlockStatements */: + case 3 /* SwitchClauseStatements */: + // If we're in error recovery, then we don't want to treat ';' as an empty statement. + // The problem is that ';' can show up in far too many contexts, and if we see one + // and assume it's a statement, then we may bail out inappropriately from whatever + // we're parsing. For example, if we have a semicolon in the middle of a class, then + // we really don't want to assume the class is over and we're on a statement in the + // outer module. We just want to consume and move on. + return !(token() === 25 /* SemicolonToken */ && inErrorRecovery) && isStartOfStatement(); + case 2 /* SwitchClauses */: + return token() === 73 /* CaseKeyword */ || token() === 79 /* DefaultKeyword */; + case 4 /* TypeMembers */: return lookAhead(isTypeMemberStart); - case 5: - return lookAhead(isClassMemberStart) || (token() === 25 && !inErrorRecovery); - case 6: - return token() === 21 || isLiteralPropertyName(); - case 12: - return token() === 21 || token() === 39 || token() === 24 || isLiteralPropertyName(); - case 17: + case 5 /* ClassMembers */: + // We allow semicolons as class elements (as specified by ES6) as long as we're + // not in error recovery. If we're in error recovery, we don't want an errant + // semicolon to be treated as a class member (since they're almost always used + // for statements. + return lookAhead(isClassMemberStart) || (token() === 25 /* SemicolonToken */ && !inErrorRecovery); + case 6 /* EnumMembers */: + // Include open bracket computed properties. This technically also lets in indexers, + // which would be a candidate for improved error reporting. + return token() === 21 /* OpenBracketToken */ || isLiteralPropertyName(); + case 12 /* ObjectLiteralMembers */: + return token() === 21 /* OpenBracketToken */ || token() === 39 /* AsteriskToken */ || token() === 24 /* DotDotDotToken */ || isLiteralPropertyName(); + case 17 /* RestProperties */: return isLiteralPropertyName(); - case 9: - return token() === 21 || token() === 24 || isLiteralPropertyName(); - case 7: - if (token() === 17) { + case 9 /* ObjectBindingElements */: + return token() === 21 /* OpenBracketToken */ || token() === 24 /* DotDotDotToken */ || isLiteralPropertyName(); + case 7 /* HeritageClauseElement */: + // If we see `{ ... }` then only consume it as an expression if it is followed by `,` or `{` + // That way we won't consume the body of a class in its heritage clause. + if (token() === 17 /* OpenBraceToken */) { return lookAhead(isValidHeritageClauseObjectLiteral); } if (!inErrorRecovery) { return isStartOfLeftHandSideExpression() && !isHeritageClauseExtendsOrImplementsKeyword(); } else { + // If we're in error recovery we tighten up what we're willing to match. + // That way we don't treat something like "this" as a valid heritage clause + // element during recovery. return isIdentifier() && !isHeritageClauseExtendsOrImplementsKeyword(); } - case 8: + case 8 /* VariableDeclarations */: return isIdentifierOrPattern(); - case 10: - return token() === 26 || token() === 24 || isIdentifierOrPattern(); - case 18: + case 10 /* ArrayBindingElements */: + return token() === 26 /* CommaToken */ || token() === 24 /* DotDotDotToken */ || isIdentifierOrPattern(); + case 18 /* TypeParameters */: return isIdentifier(); - case 15: - if (token() === 26) { + case 15 /* ArrayLiteralMembers */: + if (token() === 26 /* CommaToken */) { return true; } - case 11: - return token() === 24 || isStartOfExpression(); - case 16: + // falls through + case 11 /* ArgumentExpressions */: + return token() === 24 /* DotDotDotToken */ || isStartOfExpression(); + case 16 /* Parameters */: return isStartOfParameter(); - case 19: - case 20: - return token() === 26 || isStartOfType(); - case 21: + case 19 /* TypeArguments */: + case 20 /* TupleElementTypes */: + return token() === 26 /* CommaToken */ || isStartOfType(); + case 21 /* HeritageClauses */: return isHeritageClause(); - case 22: + case 22 /* ImportOrExportSpecifiers */: return ts.tokenIsIdentifierOrKeyword(token()); - case 13: - return ts.tokenIsIdentifierOrKeyword(token()) || token() === 17; - case 14: + case 13 /* JsxAttributes */: + return ts.tokenIsIdentifierOrKeyword(token()) || token() === 17 /* OpenBraceToken */; + case 14 /* JsxChildren */: return true; } return ts.Debug.fail("Non-exhaustive case in 'isListElement'."); } function isValidHeritageClauseObjectLiteral() { - ts.Debug.assert(token() === 17); - if (nextToken() === 18) { + ts.Debug.assert(token() === 17 /* OpenBraceToken */); + if (nextToken() === 18 /* CloseBraceToken */) { + // if we see "extends {}" then only treat the {} as what we're extending (and not + // the class body) if we have: + // + // extends {} { + // extends {}, + // extends {} extends + // extends {} implements var next = nextToken(); - return next === 26 || next === 17 || next === 85 || next === 108; + return next === 26 /* CommaToken */ || next === 17 /* OpenBraceToken */ || next === 85 /* ExtendsKeyword */ || next === 108 /* ImplementsKeyword */; } return true; } @@ -14418,8 +16422,8 @@ var ts; return ts.tokenIsIdentifierOrKeywordOrGreaterThan(token()); } function isHeritageClauseExtendsOrImplementsKeyword() { - if (token() === 108 || - token() === 85) { + if (token() === 108 /* ImplementsKeyword */ || + token() === 85 /* ExtendsKeyword */) { return lookAhead(nextTokenIsStartOfExpression); } return false; @@ -14432,78 +16436,95 @@ var ts; nextToken(); return isStartOfType(); } + // True if positioned at a list terminator function isListTerminator(kind) { - if (token() === 1) { + if (token() === 1 /* EndOfFileToken */) { + // Being at the end of the file ends all lists. return true; } switch (kind) { - case 1: - case 2: - case 4: - case 5: - case 6: - case 12: - case 9: - case 22: - return token() === 18; - case 3: - return token() === 18 || token() === 73 || token() === 79; - case 7: - return token() === 17 || token() === 85 || token() === 108; - case 8: + case 1 /* BlockStatements */: + case 2 /* SwitchClauses */: + case 4 /* TypeMembers */: + case 5 /* ClassMembers */: + case 6 /* EnumMembers */: + case 12 /* ObjectLiteralMembers */: + case 9 /* ObjectBindingElements */: + case 22 /* ImportOrExportSpecifiers */: + return token() === 18 /* CloseBraceToken */; + case 3 /* SwitchClauseStatements */: + return token() === 18 /* CloseBraceToken */ || token() === 73 /* CaseKeyword */ || token() === 79 /* DefaultKeyword */; + case 7 /* HeritageClauseElement */: + return token() === 17 /* OpenBraceToken */ || token() === 85 /* ExtendsKeyword */ || token() === 108 /* ImplementsKeyword */; + case 8 /* VariableDeclarations */: return isVariableDeclaratorListTerminator(); - case 18: - return token() === 29 || token() === 19 || token() === 17 || token() === 85 || token() === 108; - case 11: - return token() === 20 || token() === 25; - case 15: - case 20: - case 10: - return token() === 22; - case 16: - case 17: - return token() === 20 || token() === 22; - case 19: - return token() !== 26; - case 21: - return token() === 17 || token() === 18; - case 13: - return token() === 29 || token() === 41; - case 14: - return token() === 27 && lookAhead(nextTokenIsSlash); + case 18 /* TypeParameters */: + // Tokens other than '>' are here for better error recovery + return token() === 29 /* GreaterThanToken */ || token() === 19 /* OpenParenToken */ || token() === 17 /* OpenBraceToken */ || token() === 85 /* ExtendsKeyword */ || token() === 108 /* ImplementsKeyword */; + case 11 /* ArgumentExpressions */: + // Tokens other than ')' are here for better error recovery + return token() === 20 /* CloseParenToken */ || token() === 25 /* SemicolonToken */; + case 15 /* ArrayLiteralMembers */: + case 20 /* TupleElementTypes */: + case 10 /* ArrayBindingElements */: + return token() === 22 /* CloseBracketToken */; + case 16 /* Parameters */: + case 17 /* RestProperties */: + // Tokens other than ')' and ']' (the latter for index signatures) are here for better error recovery + return token() === 20 /* CloseParenToken */ || token() === 22 /* CloseBracketToken */ /*|| token === SyntaxKind.OpenBraceToken*/; + case 19 /* TypeArguments */: + // All other tokens should cause the type-argument to terminate except comma token + return token() !== 26 /* CommaToken */; + case 21 /* HeritageClauses */: + return token() === 17 /* OpenBraceToken */ || token() === 18 /* CloseBraceToken */; + case 13 /* JsxAttributes */: + return token() === 29 /* GreaterThanToken */ || token() === 41 /* SlashToken */; + case 14 /* JsxChildren */: + return token() === 27 /* LessThanToken */ && lookAhead(nextTokenIsSlash); default: return false; } } function isVariableDeclaratorListTerminator() { + // If we can consume a semicolon (either explicitly, or with ASI), then consider us done + // with parsing the list of variable declarators. if (canParseSemicolon()) { return true; } + // in the case where we're parsing the variable declarator of a 'for-in' statement, we + // are done if we see an 'in' keyword in front of us. Same with for-of if (isInOrOfKeyword(token())) { return true; } - if (token() === 36) { + // ERROR RECOVERY TWEAK: + // For better error recovery, if we see an '=>' then we just stop immediately. We've got an + // arrow function here and it's going to be very unlikely that we'll resynchronize and get + // another variable declaration. + if (token() === 36 /* EqualsGreaterThanToken */) { return true; } + // Keep trying to parse out variable declarators. return false; } + // True if positioned at element or terminator of the current list or any enclosing list function isInSomeParsingContext() { - for (var kind = 0; kind < 23; kind++) { + for (var kind = 0; kind < 23 /* Count */; kind++) { if (parsingContext & (1 << kind)) { - if (isListElement(kind, true) || isListTerminator(kind)) { + if (isListElement(kind, /*inErrorRecovery*/ true) || isListTerminator(kind)) { return true; } } } return false; } + // Parses a list of elements function parseList(kind, parseElement) { var saveParsingContext = parsingContext; parsingContext |= 1 << kind; var list = []; var listPos = getNodePos(); while (!isListTerminator(kind)) { - if (isListElement(kind, false)) { + if (isListElement(kind, /*inErrorRecovery*/ false)) { var element = parseListElement(kind, parseElement); list.push(element); continue; @@ -14523,85 +16544,145 @@ var ts; return parseElement(); } function currentNode(parsingContext) { + // If there is an outstanding parse error that we've encountered, but not attached to + // some node, then we cannot get a node from the old source tree. This is because we + // want to mark the next node we encounter as being unusable. + // + // Note: This may be too conservative. Perhaps we could reuse the node and set the bit + // on it (or its leftmost child) as having the error. For now though, being conservative + // is nice and likely won't ever affect perf. if (parseErrorBeforeNextFinishedNode) { return undefined; } if (!syntaxCursor) { + // if we don't have a cursor, we could never return a node from the old tree. return undefined; } var node = syntaxCursor.currentNode(scanner.getStartPos()); + // Can't reuse a missing node. if (ts.nodeIsMissing(node)) { return undefined; } + // Can't reuse a node that intersected the change range. if (node.intersectsChange) { return undefined; } + // Can't reuse a node that contains a parse error. This is necessary so that we + // produce the same set of errors again. if (ts.containsParseError(node)) { return undefined; } - var nodeContextFlags = node.flags & 12679168; + // We can only reuse a node if it was parsed under the same strict mode that we're + // currently in. i.e. if we originally parsed a node in non-strict mode, but then + // the user added 'using strict' at the top of the file, then we can't use that node + // again as the presence of strict mode may cause us to parse the tokens in the file + // differently. + // + // Note: we *can* reuse tokens when the strict mode changes. That's because tokens + // are unaffected by strict mode. It's just the parser will decide what to do with it + // differently depending on what mode it is in. + // + // This also applies to all our other context flags as well. + var nodeContextFlags = node.flags & 12679168 /* ContextFlags */; if (nodeContextFlags !== contextFlags) { return undefined; } + // Ok, we have a node that looks like it could be reused. Now verify that it is valid + // in the current list parsing context that we're currently at. if (!canReuseNode(node, parsingContext)) { return undefined; } if (node.jsDocCache) { + // jsDocCache may include tags from parent nodes, which might have been modified. node.jsDocCache = undefined; } return node; } function consumeNode(node) { + // Move the scanner so it is after the node we just consumed. scanner.setTextPos(node.end); nextToken(); return node; } function canReuseNode(node, parsingContext) { switch (parsingContext) { - case 5: + case 5 /* ClassMembers */: return isReusableClassMember(node); - case 2: + case 2 /* SwitchClauses */: return isReusableSwitchClause(node); - case 0: - case 1: - case 3: + case 0 /* SourceElements */: + case 1 /* BlockStatements */: + case 3 /* SwitchClauseStatements */: return isReusableStatement(node); - case 6: + case 6 /* EnumMembers */: return isReusableEnumMember(node); - case 4: + case 4 /* TypeMembers */: return isReusableTypeMember(node); - case 8: + case 8 /* VariableDeclarations */: return isReusableVariableDeclaration(node); - case 16: + case 16 /* Parameters */: return isReusableParameter(node); - case 17: + case 17 /* RestProperties */: return false; - case 21: - case 18: - case 20: - case 19: - case 11: - case 12: - case 7: - case 13: - case 14: + // Any other lists we do not care about reusing nodes in. But feel free to add if + // you can do so safely. Danger areas involve nodes that may involve speculative + // parsing. If speculative parsing is involved with the node, then the range the + // parser reached while looking ahead might be in the edited range (see the example + // in canReuseVariableDeclaratorNode for a good case of this). + case 21 /* HeritageClauses */: + // This would probably be safe to reuse. There is no speculative parsing with + // heritage clauses. + case 18 /* TypeParameters */: + // This would probably be safe to reuse. There is no speculative parsing with + // type parameters. Note that that's because type *parameters* only occur in + // unambiguous *type* contexts. While type *arguments* occur in very ambiguous + // *expression* contexts. + case 20 /* TupleElementTypes */: + // This would probably be safe to reuse. There is no speculative parsing with + // tuple types. + // Technically, type argument list types are probably safe to reuse. While + // speculative parsing is involved with them (since type argument lists are only + // produced from speculative parsing a < as a type argument list), we only have + // the types because speculative parsing succeeded. Thus, the lookahead never + // went past the end of the list and rewound. + case 19 /* TypeArguments */: + // Note: these are almost certainly not safe to ever reuse. Expressions commonly + // need a large amount of lookahead, and we should not reuse them as they may + // have actually intersected the edit. + case 11 /* ArgumentExpressions */: + // This is not safe to reuse for the same reason as the 'AssignmentExpression' + // cases. i.e. a property assignment may end with an expression, and thus might + // have lookahead far beyond it's old node. + case 12 /* ObjectLiteralMembers */: + // This is probably not safe to reuse. There can be speculative parsing with + // type names in a heritage clause. There can be generic names in the type + // name list, and there can be left hand side expressions (which can have type + // arguments.) + case 7 /* HeritageClauseElement */: + // Perhaps safe to reuse, but it's unlikely we'd see more than a dozen attributes + // on any given element. Same for children. + case 13 /* JsxAttributes */: + case 14 /* JsxChildren */: } return false; } function isReusableClassMember(node) { if (node) { switch (node.kind) { - case 155: - case 160: - case 156: - case 157: - case 152: - case 212: + case 155 /* Constructor */: + case 160 /* IndexSignature */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 152 /* PropertyDeclaration */: + case 212 /* SemicolonClassElement */: return true; - case 154: + case 154 /* MethodDeclaration */: + // Method declarations are not necessarily reusable. An object-literal + // may have a method calls "constructor(...)" and we must reparse that + // into an actual .ConstructorDeclaration. var methodDeclaration = node; - var nameIsConstructor = methodDeclaration.name.kind === 71 && - methodDeclaration.name.originalKeywordKind === 123; + var nameIsConstructor = methodDeclaration.name.kind === 71 /* Identifier */ && + methodDeclaration.name.originalKeywordKind === 123 /* ConstructorKeyword */; return !nameIsConstructor; } } @@ -14610,8 +16691,8 @@ var ts; function isReusableSwitchClause(node) { if (node) { switch (node.kind) { - case 266: - case 267: + case 266 /* CaseClause */: + case 267 /* DefaultClause */: return true; } } @@ -14620,70 +16701,86 @@ var ts; function isReusableStatement(node) { if (node) { switch (node.kind) { - case 234: - case 214: - case 213: - case 217: - case 216: - case 229: - case 225: - case 227: - case 224: - case 223: - case 221: - case 222: - case 220: - case 219: - case 226: - case 215: - case 230: - case 228: - case 218: - case 231: - case 244: - case 243: - case 250: - case 249: - case 239: - case 235: - case 236: - case 238: - case 237: + case 234 /* FunctionDeclaration */: + case 214 /* VariableStatement */: + case 213 /* Block */: + case 217 /* IfStatement */: + case 216 /* ExpressionStatement */: + case 229 /* ThrowStatement */: + case 225 /* ReturnStatement */: + case 227 /* SwitchStatement */: + case 224 /* BreakStatement */: + case 223 /* ContinueStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 220 /* ForStatement */: + case 219 /* WhileStatement */: + case 226 /* WithStatement */: + case 215 /* EmptyStatement */: + case 230 /* TryStatement */: + case 228 /* LabeledStatement */: + case 218 /* DoStatement */: + case 231 /* DebuggerStatement */: + case 244 /* ImportDeclaration */: + case 243 /* ImportEqualsDeclaration */: + case 250 /* ExportDeclaration */: + case 249 /* ExportAssignment */: + case 239 /* ModuleDeclaration */: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + case 238 /* EnumDeclaration */: + case 237 /* TypeAliasDeclaration */: return true; } } return false; } function isReusableEnumMember(node) { - return node.kind === 273; + return node.kind === 273 /* EnumMember */; } function isReusableTypeMember(node) { if (node) { switch (node.kind) { - case 159: - case 153: - case 160: - case 151: - case 158: + case 159 /* ConstructSignature */: + case 153 /* MethodSignature */: + case 160 /* IndexSignature */: + case 151 /* PropertySignature */: + case 158 /* CallSignature */: return true; } } return false; } function isReusableVariableDeclaration(node) { - if (node.kind !== 232) { + if (node.kind !== 232 /* VariableDeclaration */) { return false; } + // Very subtle incremental parsing bug. Consider the following code: + // + // let v = new List < A, B + // + // This is actually legal code. It's a list of variable declarators "v = new List() + // + // then we have a problem. "v = new List= 0) { + // Always preserve a trailing comma by marking it on the NodeArray result.hasTrailingComma = true; } return result; @@ -14775,8 +16891,9 @@ var ts; function parseEntityName(allowReservedWords, diagnosticMessage) { var entity = allowReservedWords ? parseIdentifierName(diagnosticMessage) : parseIdentifier(diagnosticMessage); var dotPos = scanner.getStartPos(); - while (parseOptional(23)) { - if (token() === 27) { + while (parseOptional(23 /* DotToken */)) { + if (token() === 27 /* LessThanToken */) { + // the entity is part of a JSDoc-style generic, so record the trailing dot for later error reporting entity.jsdocDotPos = dotPos; break; } @@ -14786,42 +16903,64 @@ var ts; return entity; } function createQualifiedName(entity, name) { - var node = createNode(146, entity.pos); + var node = createNode(146 /* QualifiedName */, entity.pos); node.left = entity; node.right = name; return finishNode(node); } function parseRightSideOfDot(allowIdentifierNames) { + // Technically a keyword is valid here as all identifiers and keywords are identifier names. + // However, often we'll encounter this in error situations when the identifier or keyword + // is actually starting another valid construct. + // + // So, we check for the following specific case: + // + // name. + // identifierOrKeyword identifierNameOrKeyword + // + // Note: the newlines are important here. For example, if that above code + // were rewritten into: + // + // name.identifierOrKeyword + // identifierNameOrKeyword + // + // Then we would consider it valid. That's because ASI would take effect and + // the code would be implicitly: "name.identifierOrKeyword; identifierNameOrKeyword". + // In the first case though, ASI will not take effect because there is not a + // line terminator after the identifier or keyword. if (scanner.hasPrecedingLineBreak() && ts.tokenIsIdentifierOrKeyword(token())) { var matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine); if (matchesPattern) { - return createMissingNode(71, true, ts.Diagnostics.Identifier_expected); + // Report that we need an identifier. However, report it right after the dot, + // and not on the next token. This is because the next token might actually + // be an identifier and the error would be quite confusing. + return createMissingNode(71 /* Identifier */, /*reportAtCurrentPosition*/ true, ts.Diagnostics.Identifier_expected); } } return allowIdentifierNames ? parseIdentifierName() : parseIdentifier(); } function parseTemplateExpression() { - var template = createNode(202); + var template = createNode(202 /* TemplateExpression */); template.head = parseTemplateHead(); - ts.Debug.assert(template.head.kind === 14, "Template head has wrong token kind"); + ts.Debug.assert(template.head.kind === 14 /* TemplateHead */, "Template head has wrong token kind"); var list = []; var listPos = getNodePos(); do { list.push(parseTemplateSpan()); - } while (ts.last(list).literal.kind === 15); + } while (ts.last(list).literal.kind === 15 /* TemplateMiddle */); template.templateSpans = createNodeArray(list, listPos); return finishNode(template); } function parseTemplateSpan() { - var span = createNode(211); + var span = createNode(211 /* TemplateSpan */); span.expression = allowInAnd(parseExpression); var literal; - if (token() === 18) { + if (token() === 18 /* CloseBraceToken */) { reScanTemplateToken(); literal = parseTemplateMiddleOrTemplateTail(); } else { - literal = parseExpectedToken(16, ts.Diagnostics._0_expected, ts.tokenToString(18)); + literal = parseExpectedToken(16 /* TemplateTail */, ts.Diagnostics._0_expected, ts.tokenToString(18 /* CloseBraceToken */)); } span.literal = literal; return finishNode(span); @@ -14831,12 +16970,12 @@ var ts; } function parseTemplateHead() { var fragment = parseLiteralLikeNode(token()); - ts.Debug.assert(fragment.kind === 14, "Template head has wrong token kind"); + ts.Debug.assert(fragment.kind === 14 /* TemplateHead */, "Template head has wrong token kind"); return fragment; } function parseTemplateMiddleOrTemplateTail() { var fragment = parseLiteralLikeNode(token()); - ts.Debug.assert(fragment.kind === 15 || fragment.kind === 16, "Template fragment has wrong token kind"); + ts.Debug.assert(fragment.kind === 15 /* TemplateMiddle */ || fragment.kind === 16 /* TemplateTail */, "Template fragment has wrong token kind"); return fragment; } function parseLiteralLikeNode(kind) { @@ -14849,31 +16988,40 @@ var ts; if (scanner.isUnterminated()) { node.isUnterminated = true; } - if (node.kind === 8) { - node.numericLiteralFlags = scanner.getTokenFlags() & 1008; + // Octal literals are not allowed in strict mode or ES5 + // Note that theoretically the following condition would hold true literals like 009, + // which is not octal.But because of how the scanner separates the tokens, we would + // never get a token like this. Instead, we would get 00 and 9 as two separate tokens. + // We also do not need to check for negatives because any prefix operator would be part of a + // parent unary expression. + if (node.kind === 8 /* NumericLiteral */) { + node.numericLiteralFlags = scanner.getTokenFlags() & 1008 /* NumericLiteralFlags */; } nextToken(); finishNode(node); return node; } + // TYPES function parseTypeReference() { - var node = createNode(162); - node.typeName = parseEntityName(true, ts.Diagnostics.Type_expected); - if (!scanner.hasPrecedingLineBreak() && token() === 27) { - node.typeArguments = parseBracketedList(19, parseType, 27, 29); + var node = createNode(162 /* TypeReference */); + node.typeName = parseEntityName(/*allowReservedWords*/ true, ts.Diagnostics.Type_expected); + if (!scanner.hasPrecedingLineBreak() && token() === 27 /* LessThanToken */) { + node.typeArguments = parseBracketedList(19 /* TypeArguments */, parseType, 27 /* LessThanToken */, 29 /* GreaterThanToken */); } return finishNode(node); } + // If true, we should abort parsing an error function. function typeHasArrowFunctionBlockingParseError(node) { switch (node.kind) { - case 162: + case 162 /* TypeReference */: return ts.nodeIsMissing(node.typeName); - case 163: - case 164: { + case 163 /* FunctionType */: + case 164 /* ConstructorType */: { var _a = node, parameters = _a.parameters, type = _a.type; + // parameters.pos === parameters.end only if we used parseMissingList, else should contain at least `()` return parameters.pos === parameters.end || typeHasArrowFunctionBlockingParseError(type); } - case 173: + case 173 /* ParenthesizedType */: return typeHasArrowFunctionBlockingParseError(node.type); default: return false; @@ -14881,20 +17029,20 @@ var ts; } function parseThisTypePredicate(lhs) { nextToken(); - var node = createNode(161, lhs.pos); + var node = createNode(161 /* TypePredicate */, lhs.pos); node.parameterName = lhs; node.type = parseType(); return finishNode(node); } function parseThisTypeNode() { - var node = createNode(174); + var node = createNode(174 /* ThisType */); nextToken(); return finishNode(node); } function parseJSDocAllType(postFixEquals) { - var result = createNode(279); + var result = createNode(279 /* JSDocAllType */); if (postFixEquals) { - return createJSDocPostfixType(283, result); + return createJSDocPostfixType(283 /* JSDocOptionalType */, result); } else { nextToken(); @@ -14902,127 +17050,162 @@ var ts; return finishNode(result); } function parseJSDocNonNullableType() { - var result = createNode(282); + var result = createNode(282 /* JSDocNonNullableType */); nextToken(); result.type = parseNonArrayType(); return finishNode(result); } function parseJSDocUnknownOrNullableType() { var pos = scanner.getStartPos(); + // skip the ? nextToken(); - if (token() === 26 || - token() === 18 || - token() === 20 || - token() === 29 || - token() === 58 || - token() === 49) { - var result = createNode(280, pos); + // Need to lookahead to decide if this is a nullable or unknown type. + // Here are cases where we'll pick the unknown type: + // + // Foo(?, + // { a: ? } + // Foo(?) + // Foo + // Foo(?= + // (?| + if (token() === 26 /* CommaToken */ || + token() === 18 /* CloseBraceToken */ || + token() === 20 /* CloseParenToken */ || + token() === 29 /* GreaterThanToken */ || + token() === 58 /* EqualsToken */ || + token() === 49 /* BarToken */) { + var result = createNode(280 /* JSDocUnknownType */, pos); return finishNode(result); } else { - var result = createNode(281, pos); + var result = createNode(281 /* JSDocNullableType */, pos); result.type = parseType(); return finishNode(result); } } function parseJSDocFunctionType() { if (lookAhead(nextTokenIsOpenParen)) { - var result = createNodeWithJSDoc(284); + var result = createNodeWithJSDoc(284 /* JSDocFunctionType */); nextToken(); - fillSignature(56, 4 | 32, result); + fillSignature(56 /* ColonToken */, 4 /* Type */ | 32 /* JSDoc */, result); return finishNode(result); } - var node = createNode(162); + var node = createNode(162 /* TypeReference */); node.typeName = parseIdentifierName(); return finishNode(node); } function parseJSDocParameter() { - var parameter = createNode(149); - if (token() === 99 || token() === 94) { + var parameter = createNode(149 /* Parameter */); + if (token() === 99 /* ThisKeyword */ || token() === 94 /* NewKeyword */) { parameter.name = parseIdentifierName(); - parseExpected(56); + parseExpected(56 /* ColonToken */); } parameter.type = parseJSDocType(); return finishNode(parameter); } function parseJSDocType() { - var dotdotdot = parseOptionalToken(24); + var dotdotdot = parseOptionalToken(24 /* DotDotDotToken */); var type = parseType(); if (dotdotdot) { - var variadic = createNode(285, dotdotdot.pos); + var variadic = createNode(285 /* JSDocVariadicType */, dotdotdot.pos); variadic.type = type; type = finishNode(variadic); } - if (token() === 58) { - return createJSDocPostfixType(283, type); + if (token() === 58 /* EqualsToken */) { + return createJSDocPostfixType(283 /* JSDocOptionalType */, type); } return type; } function parseTypeQuery() { - var node = createNode(165); - parseExpected(103); - node.exprName = parseEntityName(true); + var node = createNode(165 /* TypeQuery */); + parseExpected(103 /* TypeOfKeyword */); + node.exprName = parseEntityName(/*allowReservedWords*/ true); return finishNode(node); } function parseTypeParameter() { - var node = createNode(148); + var node = createNode(148 /* TypeParameter */); node.name = parseIdentifier(); - if (parseOptional(85)) { + if (parseOptional(85 /* ExtendsKeyword */)) { + // It's not uncommon for people to write improper constraints to a generic. If the + // user writes a constraint that is an expression and not an actual type, then parse + // it out as an expression (so we can recover well), but report that a type is needed + // instead. if (isStartOfType() || !isStartOfExpression()) { node.constraint = parseType(); } else { + // It was not a type, and it looked like an expression. Parse out an expression + // here so we recover well. Note: it is important that we call parseUnaryExpression + // and not parseExpression here. If the user has: + // + // + // + // We do *not* want to consume the `>` as we're consuming the expression for "". node.expression = parseUnaryExpressionOrHigher(); } } - if (parseOptional(58)) { + if (parseOptional(58 /* EqualsToken */)) { node.default = parseType(); } return finishNode(node); } function parseTypeParameters() { - if (token() === 27) { - return parseBracketedList(18, parseTypeParameter, 27, 29); + if (token() === 27 /* LessThanToken */) { + return parseBracketedList(18 /* TypeParameters */, parseTypeParameter, 27 /* LessThanToken */, 29 /* GreaterThanToken */); } } function parseParameterType() { - if (parseOptional(56)) { + if (parseOptional(56 /* ColonToken */)) { return parseType(); } return undefined; } function isStartOfParameter() { - return token() === 24 || + return token() === 24 /* DotDotDotToken */ || isIdentifierOrPattern() || ts.isModifierKind(token()) || - token() === 57 || - isStartOfType(true); + token() === 57 /* AtToken */ || + isStartOfType(/*inStartOfParameter*/ true); } function parseParameter() { - var node = createNodeWithJSDoc(149); - if (token() === 99) { - node.name = createIdentifier(true); + var node = createNodeWithJSDoc(149 /* Parameter */); + if (token() === 99 /* ThisKeyword */) { + node.name = createIdentifier(/*isIdentifier*/ true); node.type = parseParameterType(); return finishNode(node); } node.decorators = parseDecorators(); node.modifiers = parseModifiers(); - node.dotDotDotToken = parseOptionalToken(24); + node.dotDotDotToken = parseOptionalToken(24 /* DotDotDotToken */); + // FormalParameter [Yield,Await]: + // BindingElement[?Yield,?Await] node.name = parseIdentifierOrPattern(); if (ts.getFullWidth(node.name) === 0 && !ts.hasModifiers(node) && ts.isModifierKind(token())) { + // in cases like + // 'use strict' + // function foo(static) + // isParameter('static') === true, because of isModifier('static') + // however 'static' is not a legal identifier in a strict mode. + // so result of this function will be ParameterDeclaration (flags = 0, name = missing, type = undefined, initializer = undefined) + // and current token will not change => parsing of the enclosing parameter list will last till the end of time (or OOM) + // to avoid this we'll advance cursor to the next token. nextToken(); } - node.questionToken = parseOptionalToken(55); + node.questionToken = parseOptionalToken(55 /* QuestionToken */); node.type = parseParameterType(); node.initializer = parseInitializer(); return finishNode(node); } + /** + * Note: If returnToken is EqualsGreaterThanToken, `signature.type` will always be defined. + * @returns If return type parsing succeeds + */ function fillSignature(returnToken, flags, signature) { - if (!(flags & 32)) { + if (!(flags & 32 /* JSDoc */)) { signature.typeParameters = parseTypeParameters(); } var parametersParsedSuccessfully = parseParameterList(signature, flags); - if (shouldParseReturnType(returnToken, !!(flags & 4))) { + if (shouldParseReturnType(returnToken, !!(flags & 4 /* Type */))) { signature.type = parseTypeOrTypePredicate(); if (typeHasArrowFunctionBlockingParseError(signature.type)) return false; @@ -15030,55 +17213,89 @@ var ts; return parametersParsedSuccessfully; } function shouldParseReturnType(returnToken, isType) { - if (returnToken === 36) { + if (returnToken === 36 /* EqualsGreaterThanToken */) { parseExpected(returnToken); return true; } - else if (parseOptional(56)) { + else if (parseOptional(56 /* ColonToken */)) { return true; } - else if (isType && token() === 36) { - parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(56)); + else if (isType && token() === 36 /* EqualsGreaterThanToken */) { + // This is easy to get backward, especially in type contexts, so parse the type anyway + parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(56 /* ColonToken */)); nextToken(); return true; } return false; } + // Returns true on success. function parseParameterList(signature, flags) { - if (!parseExpected(19)) { + // FormalParameters [Yield,Await]: (modified) + // [empty] + // FormalParameterList[?Yield,Await] + // + // FormalParameter[Yield,Await]: (modified) + // BindingElement[?Yield,Await] + // + // BindingElement [Yield,Await]: (modified) + // SingleNameBinding[?Yield,?Await] + // BindingPattern[?Yield,?Await]Initializer [In, ?Yield,?Await] opt + // + // SingleNameBinding [Yield,Await]: + // BindingIdentifier[?Yield,?Await]Initializer [In, ?Yield,?Await] opt + if (!parseExpected(19 /* OpenParenToken */)) { signature.parameters = createMissingList(); return false; } var savedYieldContext = inYieldContext(); var savedAwaitContext = inAwaitContext(); - setYieldContext(!!(flags & 1)); - setAwaitContext(!!(flags & 2)); - signature.parameters = parseDelimitedList(16, flags & 32 ? parseJSDocParameter : parseParameter); + setYieldContext(!!(flags & 1 /* Yield */)); + setAwaitContext(!!(flags & 2 /* Await */)); + signature.parameters = parseDelimitedList(16 /* Parameters */, flags & 32 /* JSDoc */ ? parseJSDocParameter : parseParameter); setYieldContext(savedYieldContext); setAwaitContext(savedAwaitContext); - return parseExpected(20); + return parseExpected(20 /* CloseParenToken */); } function parseTypeMemberSemicolon() { - if (parseOptional(26)) { + // We allow type members to be separated by commas or (possibly ASI) semicolons. + // First check if it was a comma. If so, we're done with the member. + if (parseOptional(26 /* CommaToken */)) { return; } + // Didn't have a comma. We must have a (possible ASI) semicolon. parseSemicolon(); } function parseSignatureMember(kind) { var node = createNodeWithJSDoc(kind); - if (kind === 159) { - parseExpected(94); + if (kind === 159 /* ConstructSignature */) { + parseExpected(94 /* NewKeyword */); } - fillSignature(56, 4, node); + fillSignature(56 /* ColonToken */, 4 /* Type */, node); parseTypeMemberSemicolon(); return finishNode(node); } function isIndexSignature() { - return token() === 21 && lookAhead(isUnambiguouslyIndexSignature); + return token() === 21 /* OpenBracketToken */ && lookAhead(isUnambiguouslyIndexSignature); } function isUnambiguouslyIndexSignature() { + // The only allowed sequence is: + // + // [id: + // + // However, for error recovery, we also check the following cases: + // + // [... + // [id, + // [id?, + // [id?: + // [id?] + // [public id + // [private id + // [protected id + // [] + // nextToken(); - if (token() === 24 || token() === 22) { + if (token() === 24 /* DotDotDotToken */ || token() === 22 /* CloseBracketToken */) { return true; } if (ts.isModifierKind(token())) { @@ -15091,35 +17308,48 @@ var ts; return false; } else { + // Skip the identifier nextToken(); } - if (token() === 56 || token() === 26) { + // A colon signifies a well formed indexer + // A comma should be a badly formed indexer because comma expressions are not allowed + // in computed properties. + if (token() === 56 /* ColonToken */ || token() === 26 /* CommaToken */) { return true; } - if (token() !== 55) { + // Question mark could be an indexer with an optional property, + // or it could be a conditional expression in a computed property. + if (token() !== 55 /* QuestionToken */) { return false; } + // If any of the following tokens are after the question mark, it cannot + // be a conditional expression, so treat it as an indexer. nextToken(); - return token() === 56 || token() === 26 || token() === 22; + return token() === 56 /* ColonToken */ || token() === 26 /* CommaToken */ || token() === 22 /* CloseBracketToken */; } function parseIndexSignatureDeclaration(node) { - node.kind = 160; - node.parameters = parseBracketedList(16, parseParameter, 21, 22); + node.kind = 160 /* IndexSignature */; + node.parameters = parseBracketedList(16 /* Parameters */, parseParameter, 21 /* OpenBracketToken */, 22 /* CloseBracketToken */); node.type = parseTypeAnnotation(); parseTypeMemberSemicolon(); return finishNode(node); } function parsePropertyOrMethodSignature(node) { node.name = parsePropertyName(); - node.questionToken = parseOptionalToken(55); - if (token() === 19 || token() === 27) { - node.kind = 153; - fillSignature(56, 4, node); + node.questionToken = parseOptionalToken(55 /* QuestionToken */); + if (token() === 19 /* OpenParenToken */ || token() === 27 /* LessThanToken */) { + node.kind = 153 /* MethodSignature */; + // Method signatures don't exist in expression contexts. So they have neither + // [Yield] nor [Await] + fillSignature(56 /* ColonToken */, 4 /* Type */, node); } else { - node.kind = 151; + node.kind = 151 /* PropertySignature */; node.type = parseTypeAnnotation(); - if (token() === 58) { + if (token() === 58 /* EqualsToken */) { + // Although type literal properties cannot not have initializers, we attempt + // to parse an initializer so we can report in the checker that an interface + // property or type literal property cannot have an initializer. node.initializer = parseInitializer(); } } @@ -15127,39 +17357,45 @@ var ts; return finishNode(node); } function isTypeMemberStart() { - if (token() === 19 || token() === 27) { + // Return true if we have the start of a signature member + if (token() === 19 /* OpenParenToken */ || token() === 27 /* LessThanToken */) { return true; } var idToken = false; + // Eat up all modifiers, but hold on to the last one in case it is actually an identifier while (ts.isModifierKind(token())) { idToken = true; nextToken(); } - if (token() === 21) { + // Index signatures and computed property names are type members + if (token() === 21 /* OpenBracketToken */) { return true; } + // Try to get the first property-like token following all modifiers if (isLiteralPropertyName()) { idToken = true; nextToken(); } + // If we were able to get any potential identifier, check that it is + // the start of a member declaration if (idToken) { - return token() === 19 || - token() === 27 || - token() === 55 || - token() === 56 || - token() === 26 || + return token() === 19 /* OpenParenToken */ || + token() === 27 /* LessThanToken */ || + token() === 55 /* QuestionToken */ || + token() === 56 /* ColonToken */ || + token() === 26 /* CommaToken */ || canParseSemicolon(); } return false; } function parseTypeMember() { - if (token() === 19 || token() === 27) { - return parseSignatureMember(158); + if (token() === 19 /* OpenParenToken */ || token() === 27 /* LessThanToken */) { + return parseSignatureMember(158 /* CallSignature */); } - if (token() === 94 && lookAhead(nextTokenIsOpenParenOrLessThan)) { - return parseSignatureMember(159); + if (token() === 94 /* NewKeyword */ && lookAhead(nextTokenIsOpenParenOrLessThan)) { + return parseSignatureMember(159 /* ConstructSignature */); } - var node = createNodeWithJSDoc(0); + var node = createNodeWithJSDoc(0 /* Unknown */); node.modifiers = parseModifiers(); if (isIndexSignature()) { return parseIndexSignatureDeclaration(node); @@ -15168,30 +17404,30 @@ var ts; } function nextTokenIsOpenParenOrLessThan() { nextToken(); - return token() === 19 || token() === 27; + return token() === 19 /* OpenParenToken */ || token() === 27 /* LessThanToken */; } function nextTokenIsDot() { - return nextToken() === 23; + return nextToken() === 23 /* DotToken */; } function nextTokenIsOpenParenOrLessThanOrDot() { switch (nextToken()) { - case 19: - case 27: - case 23: + case 19 /* OpenParenToken */: + case 27 /* LessThanToken */: + case 23 /* DotToken */: return true; } return false; } function parseTypeLiteral() { - var node = createNode(166); + var node = createNode(166 /* TypeLiteral */); node.members = parseObjectTypeMembers(); return finishNode(node); } function parseObjectTypeMembers() { var members; - if (parseExpected(17)) { - members = parseList(4, parseTypeMember); - parseExpected(18); + if (parseExpected(17 /* OpenBraceToken */)) { + members = parseList(4 /* TypeMembers */, parseTypeMember); + parseExpected(18 /* CloseBraceToken */); } else { members = createMissingList(); @@ -15200,76 +17436,76 @@ var ts; } function isStartOfMappedType() { nextToken(); - if (token() === 37 || token() === 38) { - return nextToken() === 132; + if (token() === 37 /* PlusToken */ || token() === 38 /* MinusToken */) { + return nextToken() === 132 /* ReadonlyKeyword */; } - if (token() === 132) { + if (token() === 132 /* ReadonlyKeyword */) { nextToken(); } - return token() === 21 && nextTokenIsIdentifier() && nextToken() === 92; + return token() === 21 /* OpenBracketToken */ && nextTokenIsIdentifier() && nextToken() === 92 /* InKeyword */; } function parseMappedTypeParameter() { - var node = createNode(148); + var node = createNode(148 /* TypeParameter */); node.name = parseIdentifier(); - parseExpected(92); + parseExpected(92 /* InKeyword */); node.constraint = parseType(); return finishNode(node); } function parseMappedType() { - var node = createNode(177); - parseExpected(17); - if (token() === 132 || token() === 37 || token() === 38) { + var node = createNode(177 /* MappedType */); + parseExpected(17 /* OpenBraceToken */); + if (token() === 132 /* ReadonlyKeyword */ || token() === 37 /* PlusToken */ || token() === 38 /* MinusToken */) { node.readonlyToken = parseTokenNode(); - if (node.readonlyToken.kind !== 132) { - parseExpectedToken(132); + if (node.readonlyToken.kind !== 132 /* ReadonlyKeyword */) { + parseExpectedToken(132 /* ReadonlyKeyword */); } } - parseExpected(21); + parseExpected(21 /* OpenBracketToken */); node.typeParameter = parseMappedTypeParameter(); - parseExpected(22); - if (token() === 55 || token() === 37 || token() === 38) { + parseExpected(22 /* CloseBracketToken */); + if (token() === 55 /* QuestionToken */ || token() === 37 /* PlusToken */ || token() === 38 /* MinusToken */) { node.questionToken = parseTokenNode(); - if (node.questionToken.kind !== 55) { - parseExpectedToken(55); + if (node.questionToken.kind !== 55 /* QuestionToken */) { + parseExpectedToken(55 /* QuestionToken */); } } node.type = parseTypeAnnotation(); parseSemicolon(); - parseExpected(18); + parseExpected(18 /* CloseBraceToken */); return finishNode(node); } function parseTupleType() { - var node = createNode(168); - node.elementTypes = parseBracketedList(20, parseType, 21, 22); + var node = createNode(168 /* TupleType */); + node.elementTypes = parseBracketedList(20 /* TupleElementTypes */, parseType, 21 /* OpenBracketToken */, 22 /* CloseBracketToken */); return finishNode(node); } function parseParenthesizedType() { - var node = createNode(173); - parseExpected(19); + var node = createNode(173 /* ParenthesizedType */); + parseExpected(19 /* OpenParenToken */); node.type = parseType(); - parseExpected(20); + parseExpected(20 /* CloseParenToken */); return finishNode(node); } function parseFunctionOrConstructorType() { var pos = getNodePos(); - var kind = parseOptional(94) ? 164 : 163; + var kind = parseOptional(94 /* NewKeyword */) ? 164 /* ConstructorType */ : 163 /* FunctionType */; var node = createNodeWithJSDoc(kind, pos); - fillSignature(36, 4, node); + fillSignature(36 /* EqualsGreaterThanToken */, 4 /* Type */, node); return finishNode(node); } function parseKeywordAndNoDot() { var node = parseTokenNode(); - return token() === 23 ? undefined : node; + return token() === 23 /* DotToken */ ? undefined : node; } function parseLiteralTypeNode(negative) { - var node = createNode(178); + var node = createNode(178 /* LiteralType */); var unaryMinusExpression; if (negative) { - unaryMinusExpression = createNode(198); - unaryMinusExpression.operator = 38; + unaryMinusExpression = createNode(198 /* PrefixUnaryExpression */); + unaryMinusExpression.operator = 38 /* MinusToken */; nextToken(); } - var expression = token() === 101 || token() === 86 + var expression = token() === 101 /* TrueKeyword */ || token() === 86 /* FalseKeyword */ ? parseTokenNode() : parseLiteralLikeNode(token()); if (negative) { @@ -15282,78 +17518,79 @@ var ts; } function isStartOfTypeOfImportType() { nextToken(); - return token() === 91; + return token() === 91 /* ImportKeyword */; } function parseImportType() { - sourceFile.flags |= 524288; - var node = createNode(179); - if (parseOptional(103)) { + sourceFile.flags |= 524288 /* PossiblyContainsDynamicImport */; + var node = createNode(179 /* ImportType */); + if (parseOptional(103 /* TypeOfKeyword */)) { node.isTypeOf = true; } - parseExpected(91); - parseExpected(19); + parseExpected(91 /* ImportKeyword */); + parseExpected(19 /* OpenParenToken */); node.argument = parseType(); - parseExpected(20); - if (parseOptional(23)) { - node.qualifier = parseEntityName(true, ts.Diagnostics.Type_expected); + parseExpected(20 /* CloseParenToken */); + if (parseOptional(23 /* DotToken */)) { + node.qualifier = parseEntityName(/*allowReservedWords*/ true, ts.Diagnostics.Type_expected); } node.typeArguments = tryParseTypeArguments(); return finishNode(node); } function nextTokenIsNumericLiteral() { - return nextToken() === 8; + return nextToken() === 8 /* NumericLiteral */; } function parseNonArrayType() { switch (token()) { - case 119: - case 142: - case 137: - case 134: - case 138: - case 122: - case 140: - case 131: - case 135: + case 119 /* AnyKeyword */: + case 142 /* UnknownKeyword */: + case 137 /* StringKeyword */: + case 134 /* NumberKeyword */: + case 138 /* SymbolKeyword */: + case 122 /* BooleanKeyword */: + case 140 /* UndefinedKeyword */: + case 131 /* NeverKeyword */: + case 135 /* ObjectKeyword */: + // If these are followed by a dot, then parse these out as a dotted type reference instead. return tryParse(parseKeywordAndNoDot) || parseTypeReference(); - case 39: - return parseJSDocAllType(false); - case 61: - return parseJSDocAllType(true); - case 55: + case 39 /* AsteriskToken */: + return parseJSDocAllType(/*postfixEquals*/ false); + case 61 /* AsteriskEqualsToken */: + return parseJSDocAllType(/*postfixEquals*/ true); + case 55 /* QuestionToken */: return parseJSDocUnknownOrNullableType(); - case 89: + case 89 /* FunctionKeyword */: return parseJSDocFunctionType(); - case 51: + case 51 /* ExclamationToken */: return parseJSDocNonNullableType(); - case 13: - case 9: - case 8: - case 101: - case 86: + case 13 /* NoSubstitutionTemplateLiteral */: + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: return parseLiteralTypeNode(); - case 38: - return lookAhead(nextTokenIsNumericLiteral) ? parseLiteralTypeNode(true) : parseTypeReference(); - case 105: - case 95: + case 38 /* MinusToken */: + return lookAhead(nextTokenIsNumericLiteral) ? parseLiteralTypeNode(/*negative*/ true) : parseTypeReference(); + case 105 /* VoidKeyword */: + case 95 /* NullKeyword */: return parseTokenNode(); - case 99: { + case 99 /* ThisKeyword */: { var thisKeyword = parseThisTypeNode(); - if (token() === 127 && !scanner.hasPrecedingLineBreak()) { + if (token() === 127 /* IsKeyword */ && !scanner.hasPrecedingLineBreak()) { return parseThisTypePredicate(thisKeyword); } else { return thisKeyword; } } - case 103: + case 103 /* TypeOfKeyword */: return lookAhead(isStartOfTypeOfImportType) ? parseImportType() : parseTypeQuery(); - case 17: + case 17 /* OpenBraceToken */: return lookAhead(isStartOfMappedType) ? parseMappedType() : parseTypeLiteral(); - case 21: + case 21 /* OpenBracketToken */: return parseTupleType(); - case 19: + case 19 /* OpenParenToken */: return parseParenthesizedType(); - case 91: + case 91 /* ImportKeyword */: return parseImportType(); default: return parseTypeReference(); @@ -15361,40 +17598,42 @@ var ts; } function isStartOfType(inStartOfParameter) { switch (token()) { - case 119: - case 142: - case 137: - case 134: - case 122: - case 138: - case 141: - case 105: - case 140: - case 95: - case 99: - case 103: - case 131: - case 17: - case 21: - case 27: - case 49: - case 48: - case 94: - case 9: - case 8: - case 101: - case 86: - case 135: - case 39: - case 55: - case 51: - case 24: - case 126: - case 91: + case 119 /* AnyKeyword */: + case 142 /* UnknownKeyword */: + case 137 /* StringKeyword */: + case 134 /* NumberKeyword */: + case 122 /* BooleanKeyword */: + case 138 /* SymbolKeyword */: + case 141 /* UniqueKeyword */: + case 105 /* VoidKeyword */: + case 140 /* UndefinedKeyword */: + case 95 /* NullKeyword */: + case 99 /* ThisKeyword */: + case 103 /* TypeOfKeyword */: + case 131 /* NeverKeyword */: + case 17 /* OpenBraceToken */: + case 21 /* OpenBracketToken */: + case 27 /* LessThanToken */: + case 49 /* BarToken */: + case 48 /* AmpersandToken */: + case 94 /* NewKeyword */: + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: + case 135 /* ObjectKeyword */: + case 39 /* AsteriskToken */: + case 55 /* QuestionToken */: + case 51 /* ExclamationToken */: + case 24 /* DotDotDotToken */: + case 126 /* InferKeyword */: + case 91 /* ImportKeyword */: return true; - case 38: + case 38 /* MinusToken */: return !inStartOfParameter && lookAhead(nextTokenIsNumericLiteral); - case 19: + case 19 /* OpenParenToken */: + // Only consider '(' the start of a type if followed by ')', '...', an identifier, a modifier, + // or something that starts a type. We don't want to consider things like '(1)' a type. return !inStartOfParameter && lookAhead(isStartOfParenthesizedOrFunctionType); default: return isIdentifier(); @@ -15402,34 +17641,35 @@ var ts; } function isStartOfParenthesizedOrFunctionType() { nextToken(); - return token() === 20 || isStartOfParameter() || isStartOfType(); + return token() === 20 /* CloseParenToken */ || isStartOfParameter() || isStartOfType(); } function parsePostfixTypeOrHigher() { var type = parseNonArrayType(); while (!scanner.hasPrecedingLineBreak()) { switch (token()) { - case 51: - type = createJSDocPostfixType(282, type); + case 51 /* ExclamationToken */: + type = createJSDocPostfixType(282 /* JSDocNonNullableType */, type); break; - case 55: - if (!(contextFlags & 2097152) && lookAhead(nextTokenIsStartOfType)) { + case 55 /* QuestionToken */: + // If not in JSDoc and next token is start of a type we have a conditional type + if (!(contextFlags & 2097152 /* JSDoc */) && lookAhead(nextTokenIsStartOfType)) { return type; } - type = createJSDocPostfixType(281, type); + type = createJSDocPostfixType(281 /* JSDocNullableType */, type); break; - case 21: - parseExpected(21); + case 21 /* OpenBracketToken */: + parseExpected(21 /* OpenBracketToken */); if (isStartOfType()) { - var node = createNode(176, type.pos); + var node = createNode(176 /* IndexedAccessType */, type.pos); node.objectType = type; node.indexType = parseType(); - parseExpected(22); + parseExpected(22 /* CloseBracketToken */); type = finishNode(node); } else { - var node = createNode(167, type.pos); + var node = createNode(167 /* ArrayType */, type.pos); node.elementType = type; - parseExpected(22); + parseExpected(22 /* CloseBracketToken */); type = finishNode(node); } break; @@ -15446,16 +17686,16 @@ var ts; return finishNode(postfix); } function parseTypeOperator(operator) { - var node = createNode(175); + var node = createNode(175 /* TypeOperator */); parseExpected(operator); node.operator = operator; node.type = parseTypeOperatorOrHigher(); return finishNode(node); } function parseInferType() { - var node = createNode(172); - parseExpected(126); - var typeParameter = createNode(148); + var node = createNode(172 /* InferType */); + parseExpected(126 /* InferKeyword */); + var typeParameter = createNode(148 /* TypeParameter */); typeParameter.name = parseIdentifier(); node.typeParameter = finishNode(typeParameter); return finishNode(node); @@ -15463,10 +17703,10 @@ var ts; function parseTypeOperatorOrHigher() { var operator = token(); switch (operator) { - case 128: - case 141: + case 128 /* KeyOfKeyword */: + case 141 /* UniqueKeyword */: return parseTypeOperator(operator); - case 126: + case 126 /* InferKeyword */: return parseInferType(); } return parsePostfixTypeOrHigher(); @@ -15486,26 +17726,28 @@ var ts; return type; } function parseIntersectionTypeOrHigher() { - return parseUnionOrIntersectionType(170, parseTypeOperatorOrHigher, 48); + return parseUnionOrIntersectionType(170 /* IntersectionType */, parseTypeOperatorOrHigher, 48 /* AmpersandToken */); } function parseUnionTypeOrHigher() { - return parseUnionOrIntersectionType(169, parseIntersectionTypeOrHigher, 49); + return parseUnionOrIntersectionType(169 /* UnionType */, parseIntersectionTypeOrHigher, 49 /* BarToken */); } function isStartOfFunctionType() { - if (token() === 27) { + if (token() === 27 /* LessThanToken */) { return true; } - return token() === 19 && lookAhead(isUnambiguouslyStartOfFunctionType); + return token() === 19 /* OpenParenToken */ && lookAhead(isUnambiguouslyStartOfFunctionType); } function skipParameterStart() { if (ts.isModifierKind(token())) { + // Skip modifiers parseModifiers(); } - if (isIdentifier() || token() === 99) { + if (isIdentifier() || token() === 99 /* ThisKeyword */) { nextToken(); return true; } - if (token() === 21 || token() === 17) { + if (token() === 21 /* OpenBracketToken */ || token() === 17 /* OpenBraceToken */) { + // Return true if we can parse an array or object binding pattern with no errors var previousErrorCount = parseDiagnostics.length; parseIdentifierOrPattern(); return previousErrorCount === parseDiagnostics.length; @@ -15514,17 +17756,26 @@ var ts; } function isUnambiguouslyStartOfFunctionType() { nextToken(); - if (token() === 20 || token() === 24) { + if (token() === 20 /* CloseParenToken */ || token() === 24 /* DotDotDotToken */) { + // ( ) + // ( ... return true; } if (skipParameterStart()) { - if (token() === 56 || token() === 26 || - token() === 55 || token() === 58) { + // We successfully skipped modifiers (if any) and an identifier or binding pattern, + // now see if we have something that indicates a parameter declaration + if (token() === 56 /* ColonToken */ || token() === 26 /* CommaToken */ || + token() === 55 /* QuestionToken */ || token() === 58 /* EqualsToken */) { + // ( xxx : + // ( xxx , + // ( xxx ? + // ( xxx = return true; } - if (token() === 20) { + if (token() === 20 /* CloseParenToken */) { nextToken(); - if (token() === 36) { + if (token() === 36 /* EqualsGreaterThanToken */) { + // ( xxx ) => return true; } } @@ -15535,7 +17786,7 @@ var ts; var typePredicateVariable = isIdentifier() && tryParse(parseTypePredicatePrefix); var type = parseType(); if (typePredicateVariable) { - var node = createNode(161, typePredicateVariable.pos); + var node = createNode(161 /* TypePredicate */, typePredicateVariable.pos); node.parameterName = typePredicateVariable; node.type = type; return finishNode(node); @@ -15546,56 +17797,60 @@ var ts; } function parseTypePredicatePrefix() { var id = parseIdentifier(); - if (token() === 127 && !scanner.hasPrecedingLineBreak()) { + if (token() === 127 /* IsKeyword */ && !scanner.hasPrecedingLineBreak()) { nextToken(); return id; } } function parseType() { - return doOutsideOfContext(20480, parseTypeWorker); + // The rules about 'yield' only apply to actual code/expression contexts. They don't + // apply to 'type' contexts. So we disable these parameters here before moving on. + return doOutsideOfContext(20480 /* TypeExcludesFlags */, parseTypeWorker); } function parseTypeWorker(noConditionalTypes) { - if (isStartOfFunctionType() || token() === 94) { + if (isStartOfFunctionType() || token() === 94 /* NewKeyword */) { return parseFunctionOrConstructorType(); } var type = parseUnionTypeOrHigher(); - if (!noConditionalTypes && !scanner.hasPrecedingLineBreak() && parseOptional(85)) { - var node = createNode(171, type.pos); + if (!noConditionalTypes && !scanner.hasPrecedingLineBreak() && parseOptional(85 /* ExtendsKeyword */)) { + var node = createNode(171 /* ConditionalType */, type.pos); node.checkType = type; - node.extendsType = parseTypeWorker(true); - parseExpected(55); + // The type following 'extends' is not permitted to be another conditional type + node.extendsType = parseTypeWorker(/*noConditionalTypes*/ true); + parseExpected(55 /* QuestionToken */); node.trueType = parseTypeWorker(); - parseExpected(56); + parseExpected(56 /* ColonToken */); node.falseType = parseTypeWorker(); return finishNode(node); } return type; } function parseTypeAnnotation() { - return parseOptional(56) ? parseType() : undefined; + return parseOptional(56 /* ColonToken */) ? parseType() : undefined; } + // EXPRESSIONS function isStartOfLeftHandSideExpression() { switch (token()) { - case 99: - case 97: - case 95: - case 101: - case 86: - case 8: - case 9: - case 13: - case 14: - case 19: - case 21: - case 17: - case 89: - case 75: - case 94: - case 41: - case 63: - case 71: + case 99 /* ThisKeyword */: + case 97 /* SuperKeyword */: + case 95 /* NullKeyword */: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: + case 13 /* NoSubstitutionTemplateLiteral */: + case 14 /* TemplateHead */: + case 19 /* OpenParenToken */: + case 21 /* OpenBracketToken */: + case 17 /* OpenBraceToken */: + case 89 /* FunctionKeyword */: + case 75 /* ClassKeyword */: + case 94 /* NewKeyword */: + case 41 /* SlashToken */: + case 63 /* SlashEqualsToken */: + case 71 /* Identifier */: return true; - case 91: + case 91 /* ImportKeyword */: return lookAhead(nextTokenIsOpenParenOrLessThanOrDot); default: return isIdentifier(); @@ -15606,20 +17861,27 @@ var ts; return true; } switch (token()) { - case 37: - case 38: - case 52: - case 51: - case 80: - case 103: - case 105: - case 43: - case 44: - case 27: - case 121: - case 116: + case 37 /* PlusToken */: + case 38 /* MinusToken */: + case 52 /* TildeToken */: + case 51 /* ExclamationToken */: + case 80 /* DeleteKeyword */: + case 103 /* TypeOfKeyword */: + case 105 /* VoidKeyword */: + case 43 /* PlusPlusToken */: + case 44 /* MinusMinusToken */: + case 27 /* LessThanToken */: + case 121 /* AwaitKeyword */: + case 116 /* YieldKeyword */: + // Yield/await always starts an expression. Either it is an identifier (in which case + // it is definitely an expression). Or it's a keyword (either because we're in + // a generator or async function, or in strict mode (or both)) and it started a yield or await expression. return true; default: + // Error tolerance. If we see the start of some binary operator, we consider + // that the start of an expression. That way we'll parse out a missing identifier, + // give a good message about an identifier being missing, and then consume the + // rest of the binary expression. if (isBinaryOperator()) { return true; } @@ -15627,52 +17889,114 @@ var ts; } } function isStartOfExpressionStatement() { - return token() !== 17 && - token() !== 89 && - token() !== 75 && - token() !== 57 && + // As per the grammar, none of '{' or 'function' or 'class' can start an expression statement. + return token() !== 17 /* OpenBraceToken */ && + token() !== 89 /* FunctionKeyword */ && + token() !== 75 /* ClassKeyword */ && + token() !== 57 /* AtToken */ && isStartOfExpression(); } function parseExpression() { + // Expression[in]: + // AssignmentExpression[in] + // Expression[in] , AssignmentExpression[in] + // clear the decorator context when parsing Expression, as it should be unambiguous when parsing a decorator var saveDecoratorContext = inDecoratorContext(); if (saveDecoratorContext) { - setDecoratorContext(false); + setDecoratorContext(/*val*/ false); } var expr = parseAssignmentExpressionOrHigher(); var operatorToken; - while ((operatorToken = parseOptionalToken(26))) { + while ((operatorToken = parseOptionalToken(26 /* CommaToken */))) { expr = makeBinaryExpression(expr, operatorToken, parseAssignmentExpressionOrHigher()); } if (saveDecoratorContext) { - setDecoratorContext(true); + setDecoratorContext(/*val*/ true); } return expr; } function parseInitializer() { - return parseOptional(58) ? parseAssignmentExpressionOrHigher() : undefined; + return parseOptional(58 /* EqualsToken */) ? parseAssignmentExpressionOrHigher() : undefined; } function parseAssignmentExpressionOrHigher() { + // AssignmentExpression[in,yield]: + // 1) ConditionalExpression[?in,?yield] + // 2) LeftHandSideExpression = AssignmentExpression[?in,?yield] + // 3) LeftHandSideExpression AssignmentOperator AssignmentExpression[?in,?yield] + // 4) ArrowFunctionExpression[?in,?yield] + // 5) AsyncArrowFunctionExpression[in,yield,await] + // 6) [+Yield] YieldExpression[?In] + // + // Note: for ease of implementation we treat productions '2' and '3' as the same thing. + // (i.e. they're both BinaryExpressions with an assignment operator in it). + // First, do the simple check if we have a YieldExpression (production '6'). if (isYieldExpression()) { return parseYieldExpression(); } + // Then, check if we have an arrow function (production '4' and '5') that starts with a parenthesized + // parameter list or is an async arrow function. + // AsyncArrowFunctionExpression: + // 1) async[no LineTerminator here]AsyncArrowBindingIdentifier[?Yield][no LineTerminator here]=>AsyncConciseBody[?In] + // 2) CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await][no LineTerminator here]=>AsyncConciseBody[?In] + // Production (1) of AsyncArrowFunctionExpression is parsed in "tryParseAsyncSimpleArrowFunctionExpression". + // And production (2) is parsed in "tryParseParenthesizedArrowFunctionExpression". + // + // If we do successfully parse arrow-function, we must *not* recurse for productions 1, 2 or 3. An ArrowFunction is + // not a LeftHandSideExpression, nor does it start a ConditionalExpression. So we are done + // with AssignmentExpression if we see one. var arrowExpression = tryParseParenthesizedArrowFunctionExpression() || tryParseAsyncSimpleArrowFunctionExpression(); if (arrowExpression) { return arrowExpression; } - var expr = parseBinaryExpressionOrHigher(0); - if (expr.kind === 71 && token() === 36) { + // Now try to see if we're in production '1', '2' or '3'. A conditional expression can + // start with a LogicalOrExpression, while the assignment productions can only start with + // LeftHandSideExpressions. + // + // So, first, we try to just parse out a BinaryExpression. If we get something that is a + // LeftHandSide or higher, then we can try to parse out the assignment expression part. + // Otherwise, we try to parse out the conditional expression bit. We want to allow any + // binary expression here, so we pass in the 'lowest' precedence here so that it matches + // and consumes anything. + var expr = parseBinaryExpressionOrHigher(/*precedence*/ 0); + // To avoid a look-ahead, we did not handle the case of an arrow function with a single un-parenthesized + // parameter ('x => ...') above. We handle it here by checking if the parsed expression was a single + // identifier and the current token is an arrow. + if (expr.kind === 71 /* Identifier */ && token() === 36 /* EqualsGreaterThanToken */) { return parseSimpleArrowFunctionExpression(expr); } + // Now see if we might be in cases '2' or '3'. + // If the expression was a LHS expression, and we have an assignment operator, then + // we're in '2' or '3'. Consume the assignment and return. + // + // Note: we call reScanGreaterToken so that we get an appropriately merged token + // for cases like `> > =` becoming `>>=` if (ts.isLeftHandSideExpression(expr) && ts.isAssignmentOperator(reScanGreaterToken())) { return makeBinaryExpression(expr, parseTokenNode(), parseAssignmentExpressionOrHigher()); } + // It wasn't an assignment or a lambda. This is a conditional expression: return parseConditionalExpressionRest(expr); } function isYieldExpression() { - if (token() === 116) { + if (token() === 116 /* YieldKeyword */) { + // If we have a 'yield' keyword, and this is a context where yield expressions are + // allowed, then definitely parse out a yield expression. if (inYieldContext()) { return true; } + // We're in a context where 'yield expr' is not allowed. However, if we can + // definitely tell that the user was trying to parse a 'yield expr' and not + // just a normal expr that start with a 'yield' identifier, then parse out + // a 'yield expr'. We can then report an error later that they are only + // allowed in generator expressions. + // + // for example, if we see 'yield(foo)', then we'll have to treat that as an + // invocation expression of something called 'yield'. However, if we have + // 'yield foo' then that is not legal as a normal expression, so we can + // definitely recognize this as a yield expression. + // + // for now we just check if the next token is an identifier. More heuristics + // can be added here later as necessary. We just need to make sure that we + // don't accidentally consume something legal. return lookAhead(nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine); } return false; @@ -15682,213 +18006,302 @@ var ts; return !scanner.hasPrecedingLineBreak() && isIdentifier(); } function parseYieldExpression() { - var node = createNode(203); + var node = createNode(203 /* YieldExpression */); + // YieldExpression[In] : + // yield + // yield [no LineTerminator here] [Lexical goal InputElementRegExp]AssignmentExpression[?In, Yield] + // yield [no LineTerminator here] * [Lexical goal InputElementRegExp]AssignmentExpression[?In, Yield] nextToken(); if (!scanner.hasPrecedingLineBreak() && - (token() === 39 || isStartOfExpression())) { - node.asteriskToken = parseOptionalToken(39); + (token() === 39 /* AsteriskToken */ || isStartOfExpression())) { + node.asteriskToken = parseOptionalToken(39 /* AsteriskToken */); node.expression = parseAssignmentExpressionOrHigher(); return finishNode(node); } else { + // if the next token is not on the same line as yield. or we don't have an '*' or + // the start of an expression, then this is just a simple "yield" expression. return finishNode(node); } } function parseSimpleArrowFunctionExpression(identifier, asyncModifier) { - ts.Debug.assert(token() === 36, "parseSimpleArrowFunctionExpression should only have been called if we had a =>"); + ts.Debug.assert(token() === 36 /* EqualsGreaterThanToken */, "parseSimpleArrowFunctionExpression should only have been called if we had a =>"); var node; if (asyncModifier) { - node = createNode(193, asyncModifier.pos); + node = createNode(193 /* ArrowFunction */, asyncModifier.pos); node.modifiers = asyncModifier; } else { - node = createNode(193, identifier.pos); + node = createNode(193 /* ArrowFunction */, identifier.pos); } - var parameter = createNode(149, identifier.pos); + var parameter = createNode(149 /* Parameter */, identifier.pos); parameter.name = identifier; finishNode(parameter); node.parameters = createNodeArray([parameter], parameter.pos, parameter.end); - node.equalsGreaterThanToken = parseExpectedToken(36); - node.body = parseArrowFunctionExpressionBody(!!asyncModifier); + node.equalsGreaterThanToken = parseExpectedToken(36 /* EqualsGreaterThanToken */); + node.body = parseArrowFunctionExpressionBody(/*isAsync*/ !!asyncModifier); return addJSDocComment(finishNode(node)); } function tryParseParenthesizedArrowFunctionExpression() { var triState = isParenthesizedArrowFunctionExpression(); - if (triState === 0) { + if (triState === 0 /* False */) { + // It's definitely not a parenthesized arrow function expression. return undefined; } - var arrowFunction = triState === 1 - ? parseParenthesizedArrowFunctionExpressionHead(true) + // If we definitely have an arrow function, then we can just parse one, not requiring a + // following => or { token. Otherwise, we *might* have an arrow function. Try to parse + // it out, but don't allow any ambiguity, and return 'undefined' if this could be an + // expression instead. + var arrowFunction = triState === 1 /* True */ + ? parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity*/ true) : tryParse(parsePossibleParenthesizedArrowFunctionExpressionHead); if (!arrowFunction) { + // Didn't appear to actually be a parenthesized arrow function. Just bail out. return undefined; } - var isAsync = ts.hasModifier(arrowFunction, 256); + var isAsync = ts.hasModifier(arrowFunction, 256 /* Async */); + // If we have an arrow, then try to parse the body. Even if not, try to parse if we + // have an opening brace, just in case we're in an error state. var lastToken = token(); - arrowFunction.equalsGreaterThanToken = parseExpectedToken(36); - arrowFunction.body = (lastToken === 36 || lastToken === 17) + arrowFunction.equalsGreaterThanToken = parseExpectedToken(36 /* EqualsGreaterThanToken */); + arrowFunction.body = (lastToken === 36 /* EqualsGreaterThanToken */ || lastToken === 17 /* OpenBraceToken */) ? parseArrowFunctionExpressionBody(isAsync) : parseIdentifier(); return finishNode(arrowFunction); } + // True -> We definitely expect a parenthesized arrow function here. + // False -> There *cannot* be a parenthesized arrow function here. + // Unknown -> There *might* be a parenthesized arrow function here. + // Speculatively look ahead to be sure, and rollback if not. function isParenthesizedArrowFunctionExpression() { - if (token() === 19 || token() === 27 || token() === 120) { + if (token() === 19 /* OpenParenToken */ || token() === 27 /* LessThanToken */ || token() === 120 /* AsyncKeyword */) { return lookAhead(isParenthesizedArrowFunctionExpressionWorker); } - if (token() === 36) { - return 1; + if (token() === 36 /* EqualsGreaterThanToken */) { + // ERROR RECOVERY TWEAK: + // If we see a standalone => try to parse it as an arrow function expression as that's + // likely what the user intended to write. + return 1 /* True */; } - return 0; + // Definitely not a parenthesized arrow function. + return 0 /* False */; } function isParenthesizedArrowFunctionExpressionWorker() { - if (token() === 120) { + if (token() === 120 /* AsyncKeyword */) { nextToken(); if (scanner.hasPrecedingLineBreak()) { - return 0; + return 0 /* False */; } - if (token() !== 19 && token() !== 27) { - return 0; + if (token() !== 19 /* OpenParenToken */ && token() !== 27 /* LessThanToken */) { + return 0 /* False */; } } var first = token(); var second = nextToken(); - if (first === 19) { - if (second === 20) { + if (first === 19 /* OpenParenToken */) { + if (second === 20 /* CloseParenToken */) { + // Simple cases: "() =>", "(): ", and "() {". + // This is an arrow function with no parameters. + // The last one is not actually an arrow function, + // but this is probably what the user intended. var third = nextToken(); switch (third) { - case 36: - case 56: - case 17: - return 1; + case 36 /* EqualsGreaterThanToken */: + case 56 /* ColonToken */: + case 17 /* OpenBraceToken */: + return 1 /* True */; default: - return 0; + return 0 /* False */; } } - if (second === 21 || second === 17) { - return 2; + // If encounter "([" or "({", this could be the start of a binding pattern. + // Examples: + // ([ x ]) => { } + // ({ x }) => { } + // ([ x ]) + // ({ x }) + if (second === 21 /* OpenBracketToken */ || second === 17 /* OpenBraceToken */) { + return 2 /* Unknown */; } - if (second === 24) { - return 1; + // Simple case: "(..." + // This is an arrow function with a rest parameter. + if (second === 24 /* DotDotDotToken */) { + return 1 /* True */; } - if (ts.isModifierKind(second) && second !== 120 && lookAhead(nextTokenIsIdentifier)) { - return 1; + // Check for "(xxx yyy", where xxx is a modifier and yyy is an identifier. This + // isn't actually allowed, but we want to treat it as a lambda so we can provide + // a good error message. + if (ts.isModifierKind(second) && second !== 120 /* AsyncKeyword */ && lookAhead(nextTokenIsIdentifier)) { + return 1 /* True */; } + // If we had "(" followed by something that's not an identifier, + // then this definitely doesn't look like a lambda. if (!isIdentifier()) { - return 0; + return 0 /* False */; } switch (nextToken()) { - case 56: - return 1; - case 55: + case 56 /* ColonToken */: + // If we have something like "(a:", then we must have a + // type-annotated parameter in an arrow function expression. + return 1 /* True */; + case 55 /* QuestionToken */: nextToken(); - if (token() === 56 || token() === 26 || token() === 58 || token() === 20) { - return 1; + // If we have "(a?:" or "(a?," or "(a?=" or "(a?)" then it is definitely a lambda. + if (token() === 56 /* ColonToken */ || token() === 26 /* CommaToken */ || token() === 58 /* EqualsToken */ || token() === 20 /* CloseParenToken */) { + return 1 /* True */; } - return 0; - case 26: - case 58: - case 20: - return 2; + // Otherwise it is definitely not a lambda. + return 0 /* False */; + case 26 /* CommaToken */: + case 58 /* EqualsToken */: + case 20 /* CloseParenToken */: + // If we have "(a," or "(a=" or "(a)" this *could* be an arrow function + return 2 /* Unknown */; } - return 0; + // It is definitely not an arrow function + return 0 /* False */; } else { - ts.Debug.assert(first === 27); + ts.Debug.assert(first === 27 /* LessThanToken */); + // If we have "<" not followed by an identifier, + // then this definitely is not an arrow function. if (!isIdentifier()) { - return 0; + return 0 /* False */; } - if (sourceFile.languageVariant === 1) { + // JSX overrides + if (sourceFile.languageVariant === 1 /* JSX */) { var isArrowFunctionInJsx = lookAhead(function () { var third = nextToken(); - if (third === 85) { + if (third === 85 /* ExtendsKeyword */) { var fourth = nextToken(); switch (fourth) { - case 58: - case 29: + case 58 /* EqualsToken */: + case 29 /* GreaterThanToken */: return false; default: return true; } } - else if (third === 26) { + else if (third === 26 /* CommaToken */) { return true; } return false; }); if (isArrowFunctionInJsx) { - return 1; + return 1 /* True */; } - return 0; + return 0 /* False */; } - return 2; + // This *could* be a parenthesized arrow function. + return 2 /* Unknown */; } } function parsePossibleParenthesizedArrowFunctionExpressionHead() { - return parseParenthesizedArrowFunctionExpressionHead(false); + return parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity*/ false); } function tryParseAsyncSimpleArrowFunctionExpression() { - if (token() === 120) { - if (lookAhead(isUnParenthesizedAsyncArrowFunctionWorker) === 1) { + // We do a check here so that we won't be doing unnecessarily call to "lookAhead" + if (token() === 120 /* AsyncKeyword */) { + if (lookAhead(isUnParenthesizedAsyncArrowFunctionWorker) === 1 /* True */) { var asyncModifier = parseModifiersForArrowFunction(); - var expr = parseBinaryExpressionOrHigher(0); + var expr = parseBinaryExpressionOrHigher(/*precedence*/ 0); return parseSimpleArrowFunctionExpression(expr, asyncModifier); } } return undefined; } function isUnParenthesizedAsyncArrowFunctionWorker() { - if (token() === 120) { + // AsyncArrowFunctionExpression: + // 1) async[no LineTerminator here]AsyncArrowBindingIdentifier[?Yield][no LineTerminator here]=>AsyncConciseBody[?In] + // 2) CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await][no LineTerminator here]=>AsyncConciseBody[?In] + if (token() === 120 /* AsyncKeyword */) { nextToken(); - if (scanner.hasPrecedingLineBreak() || token() === 36) { - return 0; + // If the "async" is followed by "=>" token then it is not a beginning of an async arrow-function + // but instead a simple arrow-function which will be parsed inside "parseAssignmentExpressionOrHigher" + if (scanner.hasPrecedingLineBreak() || token() === 36 /* EqualsGreaterThanToken */) { + return 0 /* False */; } - var expr = parseBinaryExpressionOrHigher(0); - if (!scanner.hasPrecedingLineBreak() && expr.kind === 71 && token() === 36) { - return 1; + // Check for un-parenthesized AsyncArrowFunction + var expr = parseBinaryExpressionOrHigher(/*precedence*/ 0); + if (!scanner.hasPrecedingLineBreak() && expr.kind === 71 /* Identifier */ && token() === 36 /* EqualsGreaterThanToken */) { + return 1 /* True */; } } - return 0; + return 0 /* False */; } function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity) { - var node = createNodeWithJSDoc(193); + var node = createNodeWithJSDoc(193 /* ArrowFunction */); node.modifiers = parseModifiersForArrowFunction(); - var isAsync = ts.hasModifier(node, 256) ? 2 : 0; - if (!fillSignature(56, isAsync, node) && !allowAmbiguity) { + var isAsync = ts.hasModifier(node, 256 /* Async */) ? 2 /* Await */ : 0 /* None */; + // Arrow functions are never generators. + // + // If we're speculatively parsing a signature for a parenthesized arrow function, then + // we have to have a complete parameter list. Otherwise we might see something like + // a => (b => c) + // And think that "(b =>" was actually a parenthesized arrow function with a missing + // close paren. + if (!fillSignature(56 /* ColonToken */, isAsync, node) && !allowAmbiguity) { return undefined; } - if (!allowAmbiguity && token() !== 36 && token() !== 17) { + // Parsing a signature isn't enough. + // Parenthesized arrow signatures often look like other valid expressions. + // For instance: + // - "(x = 10)" is an assignment expression parsed as a signature with a default parameter value. + // - "(x,y)" is a comma expression parsed as a signature with two parameters. + // - "a ? (b): c" will have "(b):" parsed as a signature with a return type annotation. + // + // So we need just a bit of lookahead to ensure that it can only be a signature. + if (!allowAmbiguity && token() !== 36 /* EqualsGreaterThanToken */ && token() !== 17 /* OpenBraceToken */) { + // Returning undefined here will cause our caller to rewind to where we started from. return undefined; } return node; } function parseArrowFunctionExpressionBody(isAsync) { - if (token() === 17) { - return parseFunctionBlock(isAsync ? 2 : 0); + if (token() === 17 /* OpenBraceToken */) { + return parseFunctionBlock(isAsync ? 2 /* Await */ : 0 /* None */); } - if (token() !== 25 && - token() !== 89 && - token() !== 75 && + if (token() !== 25 /* SemicolonToken */ && + token() !== 89 /* FunctionKeyword */ && + token() !== 75 /* ClassKeyword */ && isStartOfStatement() && !isStartOfExpressionStatement()) { - return parseFunctionBlock(16 | (isAsync ? 2 : 0)); + // Check if we got a plain statement (i.e. no expression-statements, no function/class expressions/declarations) + // + // Here we try to recover from a potential error situation in the case where the + // user meant to supply a block. For example, if the user wrote: + // + // a => + // let v = 0; + // } + // + // they may be missing an open brace. Check to see if that's the case so we can + // try to recover better. If we don't do this, then the next close curly we see may end + // up preemptively closing the containing construct. + // + // Note: even when 'IgnoreMissingOpenBrace' is passed, parseBody will still error. + return parseFunctionBlock(16 /* IgnoreMissingOpenBrace */ | (isAsync ? 2 /* Await */ : 0 /* None */)); } return isAsync ? doInAwaitContext(parseAssignmentExpressionOrHigher) : doOutsideOfAwaitContext(parseAssignmentExpressionOrHigher); } function parseConditionalExpressionRest(leftOperand) { - var questionToken = parseOptionalToken(55); + // Note: we are passed in an expression which was produced from parseBinaryExpressionOrHigher. + var questionToken = parseOptionalToken(55 /* QuestionToken */); if (!questionToken) { return leftOperand; } - var node = createNode(201, leftOperand.pos); + // Note: we explicitly 'allowIn' in the whenTrue part of the condition expression, and + // we do not that for the 'whenFalse' part. + var node = createNode(201 /* ConditionalExpression */, leftOperand.pos); node.condition = leftOperand; node.questionToken = questionToken; node.whenTrue = doOutsideOfContext(disallowInAndDecoratorContext, parseAssignmentExpressionOrHigher); - node.colonToken = parseExpectedToken(56); + node.colonToken = parseExpectedToken(56 /* ColonToken */); node.whenFalse = ts.nodeIsPresent(node.colonToken) ? parseAssignmentExpressionOrHigher() - : createMissingNode(71, false, ts.Diagnostics._0_expected, ts.tokenToString(56)); + : createMissingNode(71 /* Identifier */, /*reportAtCurrentPosition*/ false, ts.Diagnostics._0_expected, ts.tokenToString(56 /* ColonToken */)); return finishNode(node); } function parseBinaryExpressionOrHigher(precedence) { @@ -15896,22 +18309,50 @@ var ts; return parseBinaryExpressionRest(precedence, leftOperand); } function isInOrOfKeyword(t) { - return t === 92 || t === 145; + return t === 92 /* InKeyword */ || t === 145 /* OfKeyword */; } function parseBinaryExpressionRest(precedence, leftOperand) { while (true) { + // We either have a binary operator here, or we're finished. We call + // reScanGreaterToken so that we merge token sequences like > and = into >= reScanGreaterToken(); var newPrecedence = ts.getBinaryOperatorPrecedence(token()); - var consumeCurrentOperator = token() === 40 ? + // Check the precedence to see if we should "take" this operator + // - For left associative operator (all operator but **), consume the operator, + // recursively call the function below, and parse binaryExpression as a rightOperand + // of the caller if the new precedence of the operator is greater then or equal to the current precedence. + // For example: + // a - b - c; + // ^token; leftOperand = b. Return b to the caller as a rightOperand + // a * b - c + // ^token; leftOperand = b. Return b to the caller as a rightOperand + // a - b * c; + // ^token; leftOperand = b. Return b * c to the caller as a rightOperand + // - For right associative operator (**), consume the operator, recursively call the function + // and parse binaryExpression as a rightOperand of the caller if the new precedence of + // the operator is strictly grater than the current precedence + // For example: + // a ** b ** c; + // ^^token; leftOperand = b. Return b ** c to the caller as a rightOperand + // a - b ** c; + // ^^token; leftOperand = b. Return b ** c to the caller as a rightOperand + // a ** b - c + // ^token; leftOperand = b. Return b to the caller as a rightOperand + var consumeCurrentOperator = token() === 40 /* AsteriskAsteriskToken */ ? newPrecedence >= precedence : newPrecedence > precedence; if (!consumeCurrentOperator) { break; } - if (token() === 92 && inDisallowInContext()) { + if (token() === 92 /* InKeyword */ && inDisallowInContext()) { break; } - if (token() === 118) { + if (token() === 118 /* AsKeyword */) { + // Make sure we *do* perform ASI for constructs like this: + // var x = foo + // as (Bar) + // This should be parsed as an initialized variable, followed + // by a function call to 'as' with the argument 'Bar' if (scanner.hasPrecedingLineBreak()) { break; } @@ -15927,77 +18368,105 @@ var ts; return leftOperand; } function isBinaryOperator() { - if (inDisallowInContext() && token() === 92) { + if (inDisallowInContext() && token() === 92 /* InKeyword */) { return false; } return ts.getBinaryOperatorPrecedence(token()) > 0; } function makeBinaryExpression(left, operatorToken, right) { - var node = createNode(200, left.pos); + var node = createNode(200 /* BinaryExpression */, left.pos); node.left = left; node.operatorToken = operatorToken; node.right = right; return finishNode(node); } function makeAsExpression(left, right) { - var node = createNode(208, left.pos); + var node = createNode(208 /* AsExpression */, left.pos); node.expression = left; node.type = right; return finishNode(node); } function parsePrefixUnaryExpression() { - var node = createNode(198); + var node = createNode(198 /* PrefixUnaryExpression */); node.operator = token(); nextToken(); node.operand = parseSimpleUnaryExpression(); return finishNode(node); } function parseDeleteExpression() { - var node = createNode(194); + var node = createNode(194 /* DeleteExpression */); nextToken(); node.expression = parseSimpleUnaryExpression(); return finishNode(node); } function parseTypeOfExpression() { - var node = createNode(195); + var node = createNode(195 /* TypeOfExpression */); nextToken(); node.expression = parseSimpleUnaryExpression(); return finishNode(node); } function parseVoidExpression() { - var node = createNode(196); + var node = createNode(196 /* VoidExpression */); nextToken(); node.expression = parseSimpleUnaryExpression(); return finishNode(node); } function isAwaitExpression() { - if (token() === 121) { + if (token() === 121 /* AwaitKeyword */) { if (inAwaitContext()) { return true; } + // here we are using similar heuristics as 'isYieldExpression' return lookAhead(nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine); } return false; } function parseAwaitExpression() { - var node = createNode(197); + var node = createNode(197 /* AwaitExpression */); nextToken(); node.expression = parseSimpleUnaryExpression(); return finishNode(node); } + /** + * Parse ES7 exponential expression and await expression + * + * ES7 ExponentiationExpression: + * 1) UnaryExpression[?Yield] + * 2) UpdateExpression[?Yield] ** ExponentiationExpression[?Yield] + * + */ function parseUnaryExpressionOrHigher() { + /** + * ES7 UpdateExpression: + * 1) LeftHandSideExpression[?Yield] + * 2) LeftHandSideExpression[?Yield][no LineTerminator here]++ + * 3) LeftHandSideExpression[?Yield][no LineTerminator here]-- + * 4) ++UnaryExpression[?Yield] + * 5) --UnaryExpression[?Yield] + */ if (isUpdateExpression()) { var updateExpression = parseUpdateExpression(); - return token() === 40 ? + return token() === 40 /* AsteriskAsteriskToken */ ? parseBinaryExpressionRest(ts.getBinaryOperatorPrecedence(token()), updateExpression) : updateExpression; } + /** + * ES7 UnaryExpression: + * 1) UpdateExpression[?yield] + * 2) delete UpdateExpression[?yield] + * 3) void UpdateExpression[?yield] + * 4) typeof UpdateExpression[?yield] + * 5) + UpdateExpression[?yield] + * 6) - UpdateExpression[?yield] + * 7) ~ UpdateExpression[?yield] + * 8) ! UpdateExpression[?yield] + */ var unaryOperator = token(); var simpleUnaryExpression = parseSimpleUnaryExpression(); - if (token() === 40) { + if (token() === 40 /* AsteriskAsteriskToken */) { var pos = ts.skipTrivia(sourceText, simpleUnaryExpression.pos); var end = simpleUnaryExpression.end; - if (simpleUnaryExpression.kind === 190) { + if (simpleUnaryExpression.kind === 190 /* TypeAssertionExpression */) { parseErrorAt(pos, end, ts.Diagnostics.A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses); } else { @@ -16006,63 +18475,108 @@ var ts; } return simpleUnaryExpression; } + /** + * Parse ES7 simple-unary expression or higher: + * + * ES7 UnaryExpression: + * 1) UpdateExpression[?yield] + * 2) delete UnaryExpression[?yield] + * 3) void UnaryExpression[?yield] + * 4) typeof UnaryExpression[?yield] + * 5) + UnaryExpression[?yield] + * 6) - UnaryExpression[?yield] + * 7) ~ UnaryExpression[?yield] + * 8) ! UnaryExpression[?yield] + * 9) [+Await] await UnaryExpression[?yield] + */ function parseSimpleUnaryExpression() { switch (token()) { - case 37: - case 38: - case 52: - case 51: + case 37 /* PlusToken */: + case 38 /* MinusToken */: + case 52 /* TildeToken */: + case 51 /* ExclamationToken */: return parsePrefixUnaryExpression(); - case 80: + case 80 /* DeleteKeyword */: return parseDeleteExpression(); - case 103: + case 103 /* TypeOfKeyword */: return parseTypeOfExpression(); - case 105: + case 105 /* VoidKeyword */: return parseVoidExpression(); - case 27: + case 27 /* LessThanToken */: + // This is modified UnaryExpression grammar in TypeScript + // UnaryExpression (modified): + // < type > UnaryExpression return parseTypeAssertion(); - case 121: + case 121 /* AwaitKeyword */: if (isAwaitExpression()) { return parseAwaitExpression(); } + // falls through default: return parseUpdateExpression(); } } + /** + * Check if the current token can possibly be an ES7 increment expression. + * + * ES7 UpdateExpression: + * LeftHandSideExpression[?Yield] + * LeftHandSideExpression[?Yield][no LineTerminator here]++ + * LeftHandSideExpression[?Yield][no LineTerminator here]-- + * ++LeftHandSideExpression[?Yield] + * --LeftHandSideExpression[?Yield] + */ function isUpdateExpression() { + // This function is called inside parseUnaryExpression to decide + // whether to call parseSimpleUnaryExpression or call parseUpdateExpression directly switch (token()) { - case 37: - case 38: - case 52: - case 51: - case 80: - case 103: - case 105: - case 121: + case 37 /* PlusToken */: + case 38 /* MinusToken */: + case 52 /* TildeToken */: + case 51 /* ExclamationToken */: + case 80 /* DeleteKeyword */: + case 103 /* TypeOfKeyword */: + case 105 /* VoidKeyword */: + case 121 /* AwaitKeyword */: return false; - case 27: - if (sourceFile.languageVariant !== 1) { + case 27 /* LessThanToken */: + // If we are not in JSX context, we are parsing TypeAssertion which is an UnaryExpression + if (sourceFile.languageVariant !== 1 /* JSX */) { return false; } + // We are in JSX context and the token is part of JSXElement. + // falls through default: return true; } } + /** + * Parse ES7 UpdateExpression. UpdateExpression is used instead of ES6's PostFixExpression. + * + * ES7 UpdateExpression[yield]: + * 1) LeftHandSideExpression[?yield] + * 2) LeftHandSideExpression[?yield] [[no LineTerminator here]]++ + * 3) LeftHandSideExpression[?yield] [[no LineTerminator here]]-- + * 4) ++LeftHandSideExpression[?yield] + * 5) --LeftHandSideExpression[?yield] + * In TypeScript (2), (3) are parsed as PostfixUnaryExpression. (4), (5) are parsed as PrefixUnaryExpression + */ function parseUpdateExpression() { - if (token() === 43 || token() === 44) { - var node = createNode(198); + if (token() === 43 /* PlusPlusToken */ || token() === 44 /* MinusMinusToken */) { + var node = createNode(198 /* PrefixUnaryExpression */); node.operator = token(); nextToken(); node.operand = parseLeftHandSideExpressionOrHigher(); return finishNode(node); } - else if (sourceFile.languageVariant === 1 && token() === 27 && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) { - return parseJsxElementOrSelfClosingElementOrFragment(true); + else if (sourceFile.languageVariant === 1 /* JSX */ && token() === 27 /* LessThanToken */ && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) { + // JSXElement is part of primaryExpression + return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true); } var expression = parseLeftHandSideExpressionOrHigher(); ts.Debug.assert(ts.isLeftHandSideExpression(expression)); - if ((token() === 43 || token() === 44) && !scanner.hasPrecedingLineBreak()) { - var node = createNode(199, expression.pos); + if ((token() === 43 /* PlusPlusToken */ || token() === 44 /* MinusMinusToken */) && !scanner.hasPrecedingLineBreak()) { + var node = createNode(199 /* PostfixUnaryExpression */, expression.pos); node.operand = expression; node.operator = token(); nextToken(); @@ -16071,51 +18585,139 @@ var ts; return expression; } function parseLeftHandSideExpressionOrHigher() { + // Original Ecma: + // LeftHandSideExpression: See 11.2 + // NewExpression + // CallExpression + // + // Our simplification: + // + // LeftHandSideExpression: See 11.2 + // MemberExpression + // CallExpression + // + // See comment in parseMemberExpressionOrHigher on how we replaced NewExpression with + // MemberExpression to make our lives easier. + // + // to best understand the below code, it's important to see how CallExpression expands + // out into its own productions: + // + // CallExpression: + // MemberExpression Arguments + // CallExpression Arguments + // CallExpression[Expression] + // CallExpression.IdentifierName + // import (AssignmentExpression) + // super Arguments + // super.IdentifierName + // + // Because of the recursion in these calls, we need to bottom out first. There are three + // bottom out states we can run into: 1) We see 'super' which must start either of + // the last two CallExpression productions. 2) We see 'import' which must start import call. + // 3)we have a MemberExpression which either completes the LeftHandSideExpression, + // or starts the beginning of the first four CallExpression productions. var expression; - if (token() === 91) { + if (token() === 91 /* ImportKeyword */) { if (lookAhead(nextTokenIsOpenParenOrLessThan)) { - sourceFile.flags |= 524288; + // We don't want to eagerly consume all import keyword as import call expression so we look ahead to find "(" + // For example: + // var foo3 = require("subfolder + // import * as foo1 from "module-from-node + // We want this import to be a statement rather than import call expression + sourceFile.flags |= 524288 /* PossiblyContainsDynamicImport */; expression = parseTokenNode(); } else if (lookAhead(nextTokenIsDot)) { + // This is an 'import.*' metaproperty (i.e. 'import.meta') var fullStart = scanner.getStartPos(); - nextToken(); - nextToken(); - var node = createNode(210, fullStart); - node.keywordToken = 91; + nextToken(); // advance past the 'import' + nextToken(); // advance past the dot + var node = createNode(210 /* MetaProperty */, fullStart); + node.keywordToken = 91 /* ImportKeyword */; node.name = parseIdentifierName(); expression = finishNode(node); - sourceFile.flags |= 1048576; + sourceFile.flags |= 1048576 /* PossiblyContainsImportMeta */; } else { expression = parseMemberExpressionOrHigher(); } } else { - expression = token() === 97 ? parseSuperExpression() : parseMemberExpressionOrHigher(); + expression = token() === 97 /* SuperKeyword */ ? parseSuperExpression() : parseMemberExpressionOrHigher(); } + // Now, we *may* be complete. However, we might have consumed the start of a + // CallExpression. As such, we need to consume the rest of it here to be complete. return parseCallExpressionRest(expression); } function parseMemberExpressionOrHigher() { + // Note: to make our lives simpler, we decompose the NewExpression productions and + // place ObjectCreationExpression and FunctionExpression into PrimaryExpression. + // like so: + // + // PrimaryExpression : See 11.1 + // this + // Identifier + // Literal + // ArrayLiteral + // ObjectLiteral + // (Expression) + // FunctionExpression + // new MemberExpression Arguments? + // + // MemberExpression : See 11.2 + // PrimaryExpression + // MemberExpression[Expression] + // MemberExpression.IdentifierName + // + // CallExpression : See 11.2 + // MemberExpression + // CallExpression Arguments + // CallExpression[Expression] + // CallExpression.IdentifierName + // + // Technically this is ambiguous. i.e. CallExpression defines: + // + // CallExpression: + // CallExpression Arguments + // + // If you see: "new Foo()" + // + // Then that could be treated as a single ObjectCreationExpression, or it could be + // treated as the invocation of "new Foo". We disambiguate that in code (to match + // the original grammar) by making sure that if we see an ObjectCreationExpression + // we always consume arguments if they are there. So we treat "new Foo()" as an + // object creation only, and not at all as an invocation. Another way to think + // about this is that for every "new" that we see, we will consume an argument list if + // it is there as part of the *associated* object creation node. Any additional + // argument lists we see, will become invocation expressions. + // + // Because there are no other places in the grammar now that refer to FunctionExpression + // or ObjectCreationExpression, it is safe to push down into the PrimaryExpression + // production. + // + // Because CallExpression and MemberExpression are left recursive, we need to bottom out + // of the recursion immediately. So we parse out a primary expression to start with. var expression = parsePrimaryExpression(); return parseMemberExpressionRest(expression); } function parseSuperExpression() { var expression = parseTokenNode(); - if (token() === 19 || token() === 23 || token() === 21) { + if (token() === 19 /* OpenParenToken */ || token() === 23 /* DotToken */ || token() === 21 /* OpenBracketToken */) { return expression; } - var node = createNode(185, expression.pos); + // If we have seen "super" it must be followed by '(' or '.'. + // If it wasn't then just try to parse out a '.' and report an error. + var node = createNode(185 /* PropertyAccessExpression */, expression.pos); node.expression = expression; - parseExpectedToken(23, ts.Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access); - node.name = parseRightSideOfDot(true); + parseExpectedToken(23 /* DotToken */, ts.Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access); + node.name = parseRightSideOfDot(/*allowIdentifierNames*/ true); return finishNode(node); } function parseJsxElementOrSelfClosingElementOrFragment(inExpressionContext) { var opening = parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext); var result; - if (opening.kind === 257) { - var node = createNode(255, opening.pos); + if (opening.kind === 257 /* JsxOpeningElement */) { + var node = createNode(255 /* JsxElement */, opening.pos); node.openingElement = opening; node.children = parseJsxChildren(node.openingElement); node.closingElement = parseJsxClosingElement(inExpressionContext); @@ -16124,26 +18726,34 @@ var ts; } result = finishNode(node); } - else if (opening.kind === 260) { - var node = createNode(259, opening.pos); + else if (opening.kind === 260 /* JsxOpeningFragment */) { + var node = createNode(259 /* JsxFragment */, opening.pos); node.openingFragment = opening; node.children = parseJsxChildren(node.openingFragment); node.closingFragment = parseJsxClosingFragment(inExpressionContext); result = finishNode(node); } else { - ts.Debug.assert(opening.kind === 256); + ts.Debug.assert(opening.kind === 256 /* JsxSelfClosingElement */); + // Nothing else to do for self-closing elements result = opening; } - if (inExpressionContext && token() === 27) { - var invalidElement = tryParse(function () { return parseJsxElementOrSelfClosingElementOrFragment(true); }); + // If the user writes the invalid code '
' in an expression context (i.e. not wrapped in + // an enclosing tag), we'll naively try to parse ^ this as a 'less than' operator and the remainder of the tag + // as garbage, which will cause the formatter to badly mangle the JSX. Perform a speculative parse of a JSX + // element if we see a < token so that we can wrap it in a synthetic binary expression so the formatter + // does less damage and we can report a better error. + // Since JSX elements are invalid < operands anyway, this lookahead parse will only occur in error scenarios + // of one sort or another. + if (inExpressionContext && token() === 27 /* LessThanToken */) { + var invalidElement = tryParse(function () { return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true); }); if (invalidElement) { parseErrorAtCurrentToken(ts.Diagnostics.JSX_expressions_must_have_one_parent_element); - var badNode = createNode(200, result.pos); + var badNode = createNode(200 /* BinaryExpression */, result.pos); badNode.end = invalidElement.end; badNode.left = result; badNode.right = invalidElement; - badNode.operatorToken = createMissingNode(26, false, undefined); + badNode.operatorToken = createMissingNode(26 /* CommaToken */, /*reportAtCurrentPosition*/ false, /*diagnosticMessage*/ undefined); // TODO: GH#18217 badNode.operatorToken.pos = badNode.operatorToken.end = badNode.right.pos; return badNode; } @@ -16151,14 +18761,16 @@ var ts; return result; } function parseJsxText() { - var node = createNode(10); - node.containsOnlyWhiteSpaces = currentToken === 11; + var node = createNode(10 /* JsxText */); + node.containsOnlyWhiteSpaces = currentToken === 11 /* JsxTextAllWhiteSpaces */; currentToken = scanner.scanJsxToken(); return finishNode(node); } function parseJsxChild(openingTag, token) { switch (token) { - case 1: + case 1 /* EndOfFileToken */: + // If we hit EOF, issue the error at the tag that lacks the closing element + // rather than at the end of the file (which is useless) if (ts.isJsxOpeningFragment(openingTag)) { parseErrorAtRange(openingTag, ts.Diagnostics.JSX_fragment_has_no_corresponding_closing_tag); } @@ -16166,16 +18778,16 @@ var ts; parseErrorAtRange(openingTag.tagName, ts.Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, ts.getTextOfNodeFromSourceText(sourceText, openingTag.tagName)); } return undefined; - case 28: - case 7: + case 28 /* LessThanSlashToken */: + case 7 /* ConflictMarkerTrivia */: return undefined; - case 10: - case 11: + case 10 /* JsxText */: + case 11 /* JsxTextAllWhiteSpaces */: return parseJsxText(); - case 17: - return parseJsxExpression(false); - case 27: - return parseJsxElementOrSelfClosingElementOrFragment(false); + case 17 /* OpenBraceToken */: + return parseJsxExpression(/*inExpressionContext*/ false); + case 27 /* LessThanToken */: + return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ false); default: return ts.Debug.assertNever(token); } @@ -16184,7 +18796,7 @@ var ts; var list = []; var listPos = getNodePos(); var saveParsingContext = parsingContext; - parsingContext |= 1 << 14; + parsingContext |= 1 << 14 /* JsxChildren */; while (true) { var child = parseJsxChild(openingTag, currentToken = scanner.reScanJsxToken()); if (!child) @@ -16195,15 +18807,16 @@ var ts; return createNodeArray(list, listPos); } function parseJsxAttributes() { - var jsxAttributes = createNode(263); - jsxAttributes.properties = parseList(13, parseJsxAttribute); + var jsxAttributes = createNode(263 /* JsxAttributes */); + jsxAttributes.properties = parseList(13 /* JsxAttributes */, parseJsxAttribute); return finishNode(jsxAttributes); } function parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext) { var fullStart = scanner.getStartPos(); - parseExpected(27); - if (token() === 29) { - var node_1 = createNode(260, fullStart); + parseExpected(27 /* LessThanToken */); + if (token() === 29 /* GreaterThanToken */) { + // See below for explanation of scanJsxText + var node_1 = createNode(260 /* JsxOpeningFragment */, fullStart); scanJsxText(); return finishNode(node_1); } @@ -16211,20 +18824,23 @@ var ts; var typeArguments = tryParseTypeArguments(); var attributes = parseJsxAttributes(); var node; - if (token() === 29) { - node = createNode(257, fullStart); + if (token() === 29 /* GreaterThanToken */) { + // Closing tag, so scan the immediately-following text with the JSX scanning instead + // of regular scanning to avoid treating illegal characters (e.g. '#') as immediate + // scanning errors + node = createNode(257 /* JsxOpeningElement */, fullStart); scanJsxText(); } else { - parseExpected(41); + parseExpected(41 /* SlashToken */); if (inExpressionContext) { - parseExpected(29); + parseExpected(29 /* GreaterThanToken */); } else { - parseExpected(29, undefined, false); + parseExpected(29 /* GreaterThanToken */, /*diagnostic*/ undefined, /*shouldAdvance*/ false); scanJsxText(); } - node = createNode(256, fullStart); + node = createNode(256 /* JsxSelfClosingElement */, fullStart); } node.tagName = tagName; node.typeArguments = typeArguments; @@ -16233,119 +18849,125 @@ var ts; } function parseJsxElementName() { scanJsxIdentifier(); - var expression = token() === 99 ? + // JsxElement can have name in the form of + // propertyAccessExpression + // primaryExpression in the form of an identifier and "this" keyword + // We can't just simply use parseLeftHandSideExpressionOrHigher because then we will start consider class,function etc as a keyword + // We only want to consider "this" as a primaryExpression + var expression = token() === 99 /* ThisKeyword */ ? parseTokenNode() : parseIdentifierName(); - while (parseOptional(23)) { - var propertyAccess = createNode(185, expression.pos); + while (parseOptional(23 /* DotToken */)) { + var propertyAccess = createNode(185 /* PropertyAccessExpression */, expression.pos); propertyAccess.expression = expression; - propertyAccess.name = parseRightSideOfDot(true); + propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true); expression = finishNode(propertyAccess); } return expression; } function parseJsxExpression(inExpressionContext) { - var node = createNode(265); - if (!parseExpected(17)) { + var node = createNode(265 /* JsxExpression */); + if (!parseExpected(17 /* OpenBraceToken */)) { return undefined; } - if (token() !== 18) { - node.dotDotDotToken = parseOptionalToken(24); + if (token() !== 18 /* CloseBraceToken */) { + node.dotDotDotToken = parseOptionalToken(24 /* DotDotDotToken */); node.expression = parseAssignmentExpressionOrHigher(); } if (inExpressionContext) { - parseExpected(18); + parseExpected(18 /* CloseBraceToken */); } else { - parseExpected(18, undefined, false); + parseExpected(18 /* CloseBraceToken */, /*message*/ undefined, /*shouldAdvance*/ false); scanJsxText(); } return finishNode(node); } function parseJsxAttribute() { - if (token() === 17) { + if (token() === 17 /* OpenBraceToken */) { return parseJsxSpreadAttribute(); } scanJsxIdentifier(); - var node = createNode(262); + var node = createNode(262 /* JsxAttribute */); node.name = parseIdentifierName(); - if (token() === 58) { + if (token() === 58 /* EqualsToken */) { switch (scanJsxAttributeValue()) { - case 9: + case 9 /* StringLiteral */: node.initializer = parseLiteralNode(); break; default: - node.initializer = parseJsxExpression(true); + node.initializer = parseJsxExpression(/*inExpressionContext*/ true); break; } } return finishNode(node); } function parseJsxSpreadAttribute() { - var node = createNode(264); - parseExpected(17); - parseExpected(24); + var node = createNode(264 /* JsxSpreadAttribute */); + parseExpected(17 /* OpenBraceToken */); + parseExpected(24 /* DotDotDotToken */); node.expression = parseExpression(); - parseExpected(18); + parseExpected(18 /* CloseBraceToken */); return finishNode(node); } function parseJsxClosingElement(inExpressionContext) { - var node = createNode(258); - parseExpected(28); + var node = createNode(258 /* JsxClosingElement */); + parseExpected(28 /* LessThanSlashToken */); node.tagName = parseJsxElementName(); if (inExpressionContext) { - parseExpected(29); + parseExpected(29 /* GreaterThanToken */); } else { - parseExpected(29, undefined, false); + parseExpected(29 /* GreaterThanToken */, /*diagnostic*/ undefined, /*shouldAdvance*/ false); scanJsxText(); } return finishNode(node); } function parseJsxClosingFragment(inExpressionContext) { - var node = createNode(261); - parseExpected(28); + var node = createNode(261 /* JsxClosingFragment */); + parseExpected(28 /* LessThanSlashToken */); if (ts.tokenIsIdentifierOrKeyword(token())) { parseErrorAtRange(parseJsxElementName(), ts.Diagnostics.Expected_corresponding_closing_tag_for_JSX_fragment); } if (inExpressionContext) { - parseExpected(29); + parseExpected(29 /* GreaterThanToken */); } else { - parseExpected(29, undefined, false); + parseExpected(29 /* GreaterThanToken */, /*diagnostic*/ undefined, /*shouldAdvance*/ false); scanJsxText(); } return finishNode(node); } function parseTypeAssertion() { - var node = createNode(190); - parseExpected(27); + var node = createNode(190 /* TypeAssertionExpression */); + parseExpected(27 /* LessThanToken */); node.type = parseType(); - parseExpected(29); + parseExpected(29 /* GreaterThanToken */); node.expression = parseSimpleUnaryExpression(); return finishNode(node); } function parseMemberExpressionRest(expression) { while (true) { - var dotToken = parseOptionalToken(23); + var dotToken = parseOptionalToken(23 /* DotToken */); if (dotToken) { - var propertyAccess = createNode(185, expression.pos); + var propertyAccess = createNode(185 /* PropertyAccessExpression */, expression.pos); propertyAccess.expression = expression; - propertyAccess.name = parseRightSideOfDot(true); + propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true); expression = finishNode(propertyAccess); continue; } - if (token() === 51 && !scanner.hasPrecedingLineBreak()) { + if (token() === 51 /* ExclamationToken */ && !scanner.hasPrecedingLineBreak()) { nextToken(); - var nonNullExpression = createNode(209, expression.pos); + var nonNullExpression = createNode(209 /* NonNullExpression */, expression.pos); nonNullExpression.expression = expression; expression = finishNode(nonNullExpression); continue; } - if (!inDecoratorContext() && parseOptional(21)) { - var indexedAccess = createNode(186, expression.pos); + // when in the [Decorator] context, we do not parse ElementAccess as it could be part of a ComputedPropertyName + if (!inDecoratorContext() && parseOptional(21 /* OpenBracketToken */)) { + var indexedAccess = createNode(186 /* ElementAccessExpression */, expression.pos); indexedAccess.expression = expression; - if (token() === 22) { - indexedAccess.argumentExpression = createMissingNode(71, true, ts.Diagnostics.An_element_access_expression_should_take_an_argument); + if (token() === 22 /* CloseBracketToken */) { + indexedAccess.argumentExpression = createMissingNode(71 /* Identifier */, /*reportAtCurrentPosition*/ true, ts.Diagnostics.An_element_access_expression_should_take_an_argument); } else { var argument = allowInAnd(parseExpression); @@ -16354,25 +18976,25 @@ var ts; } indexedAccess.argumentExpression = argument; } - parseExpected(22); + parseExpected(22 /* CloseBracketToken */); expression = finishNode(indexedAccess); continue; } if (isTemplateStartOfTaggedTemplate()) { - expression = parseTaggedTemplateRest(expression, undefined); + expression = parseTaggedTemplateRest(expression, /*typeArguments*/ undefined); continue; } return expression; } } function isTemplateStartOfTaggedTemplate() { - return token() === 13 || token() === 14; + return token() === 13 /* NoSubstitutionTemplateLiteral */ || token() === 14 /* TemplateHead */; } function parseTaggedTemplateRest(tag, typeArguments) { - var tagExpression = createNode(189, tag.pos); + var tagExpression = createNode(189 /* TaggedTemplateExpression */, tag.pos); tagExpression.tag = tag; tagExpression.typeArguments = typeArguments; - tagExpression.template = token() === 13 + tagExpression.template = token() === 13 /* NoSubstitutionTemplateLiteral */ ? parseLiteralNode() : parseTemplateExpression(); return finishNode(tagExpression); @@ -16380,7 +19002,11 @@ var ts; function parseCallExpressionRest(expression) { while (true) { expression = parseMemberExpressionRest(expression); - if (token() === 27) { + if (token() === 27 /* LessThanToken */) { + // See if this is the start of a generic invocation. If so, consume it and + // keep checking for postfix expressions. Otherwise, it's just a '<' that's + // part of an arithmetic expression. Break out so we consume it higher in the + // stack. var typeArguments = tryParse(parseTypeArgumentsInExpression); if (!typeArguments) { return expression; @@ -16389,15 +19015,15 @@ var ts; expression = parseTaggedTemplateRest(expression, typeArguments); continue; } - var callExpr = createNode(187, expression.pos); + var callExpr = createNode(187 /* CallExpression */, expression.pos); callExpr.expression = expression; callExpr.typeArguments = typeArguments; callExpr.arguments = parseArgumentList(); expression = finishNode(callExpr); continue; } - else if (token() === 19) { - var callExpr = createNode(187, expression.pos); + else if (token() === 19 /* OpenParenToken */) { + var callExpr = createNode(187 /* CallExpression */, expression.pos); callExpr.expression = expression; callExpr.arguments = parseArgumentList(); expression = finishNode(callExpr); @@ -16407,191 +19033,217 @@ var ts; } } function parseArgumentList() { - parseExpected(19); - var result = parseDelimitedList(11, parseArgumentExpression); - parseExpected(20); + parseExpected(19 /* OpenParenToken */); + var result = parseDelimitedList(11 /* ArgumentExpressions */, parseArgumentExpression); + parseExpected(20 /* CloseParenToken */); return result; } function parseTypeArgumentsInExpression() { - if (!parseOptional(27)) { + if (!parseOptional(27 /* LessThanToken */)) { return undefined; } - var typeArguments = parseDelimitedList(19, parseType); - if (!parseExpected(29)) { + var typeArguments = parseDelimitedList(19 /* TypeArguments */, parseType); + if (!parseExpected(29 /* GreaterThanToken */)) { + // If it doesn't have the closing `>` then it's definitely not an type argument list. return undefined; } + // If we have a '<', then only parse this as a argument list if the type arguments + // are complete and we have an open paren. if we don't, rewind and return nothing. return typeArguments && canFollowTypeArgumentsInExpression() ? typeArguments : undefined; } function canFollowTypeArgumentsInExpression() { switch (token()) { - case 19: - case 13: - case 14: - case 23: - case 20: - case 22: - case 56: - case 25: - case 55: - case 32: - case 34: - case 33: - case 35: - case 53: - case 54: - case 50: - case 48: - case 49: - case 18: - case 1: + case 19 /* OpenParenToken */: // foo( + case 13 /* NoSubstitutionTemplateLiteral */: // foo `...` + case 14 /* TemplateHead */: // foo `...${100}...` + // these are the only tokens can legally follow a type argument + // list. So we definitely want to treat them as type arg lists. + case 23 /* DotToken */: // foo. + case 20 /* CloseParenToken */: // foo) + case 22 /* CloseBracketToken */: // foo] + case 56 /* ColonToken */: // foo: + case 25 /* SemicolonToken */: // foo; + case 55 /* QuestionToken */: // foo? + case 32 /* EqualsEqualsToken */: // foo == + case 34 /* EqualsEqualsEqualsToken */: // foo === + case 33 /* ExclamationEqualsToken */: // foo != + case 35 /* ExclamationEqualsEqualsToken */: // foo !== + case 53 /* AmpersandAmpersandToken */: // foo && + case 54 /* BarBarToken */: // foo || + case 50 /* CaretToken */: // foo ^ + case 48 /* AmpersandToken */: // foo & + case 49 /* BarToken */: // foo | + case 18 /* CloseBraceToken */: // foo } + case 1 /* EndOfFileToken */: // foo + // these cases can't legally follow a type arg list. However, they're not legal + // expressions either. The user is probably in the middle of a generic type. So + // treat it as such. return true; - case 26: - case 17: + case 26 /* CommaToken */: // foo, + case 17 /* OpenBraceToken */: // foo { + // We don't want to treat these as type arguments. Otherwise we'll parse this + // as an invocation expression. Instead, we want to parse out the expression + // in isolation from the type arguments. default: + // Anything else treat as an expression. return false; } } function parsePrimaryExpression() { switch (token()) { - case 8: - case 9: - case 13: + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: + case 13 /* NoSubstitutionTemplateLiteral */: return parseLiteralNode(); - case 99: - case 97: - case 95: - case 101: - case 86: + case 99 /* ThisKeyword */: + case 97 /* SuperKeyword */: + case 95 /* NullKeyword */: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: return parseTokenNode(); - case 19: + case 19 /* OpenParenToken */: return parseParenthesizedExpression(); - case 21: + case 21 /* OpenBracketToken */: return parseArrayLiteralExpression(); - case 17: + case 17 /* OpenBraceToken */: return parseObjectLiteralExpression(); - case 120: + case 120 /* AsyncKeyword */: + // Async arrow functions are parsed earlier in parseAssignmentExpressionOrHigher. + // If we encounter `async [no LineTerminator here] function` then this is an async + // function; otherwise, its an identifier. if (!lookAhead(nextTokenIsFunctionKeywordOnSameLine)) { break; } return parseFunctionExpression(); - case 75: + case 75 /* ClassKeyword */: return parseClassExpression(); - case 89: + case 89 /* FunctionKeyword */: return parseFunctionExpression(); - case 94: + case 94 /* NewKeyword */: return parseNewExpressionOrNewDotTarget(); - case 41: - case 63: - if (reScanSlashToken() === 12) { + case 41 /* SlashToken */: + case 63 /* SlashEqualsToken */: + if (reScanSlashToken() === 12 /* RegularExpressionLiteral */) { return parseLiteralNode(); } break; - case 14: + case 14 /* TemplateHead */: return parseTemplateExpression(); } return parseIdentifier(ts.Diagnostics.Expression_expected); } function parseParenthesizedExpression() { - var node = createNodeWithJSDoc(191); - parseExpected(19); + var node = createNodeWithJSDoc(191 /* ParenthesizedExpression */); + parseExpected(19 /* OpenParenToken */); node.expression = allowInAnd(parseExpression); - parseExpected(20); + parseExpected(20 /* CloseParenToken */); return finishNode(node); } function parseSpreadElement() { - var node = createNode(204); - parseExpected(24); + var node = createNode(204 /* SpreadElement */); + parseExpected(24 /* DotDotDotToken */); node.expression = parseAssignmentExpressionOrHigher(); return finishNode(node); } function parseArgumentOrArrayLiteralElement() { - return token() === 24 ? parseSpreadElement() : - token() === 26 ? createNode(206) : + return token() === 24 /* DotDotDotToken */ ? parseSpreadElement() : + token() === 26 /* CommaToken */ ? createNode(206 /* OmittedExpression */) : parseAssignmentExpressionOrHigher(); } function parseArgumentExpression() { return doOutsideOfContext(disallowInAndDecoratorContext, parseArgumentOrArrayLiteralElement); } function parseArrayLiteralExpression() { - var node = createNode(183); - parseExpected(21); + var node = createNode(183 /* ArrayLiteralExpression */); + parseExpected(21 /* OpenBracketToken */); if (scanner.hasPrecedingLineBreak()) { node.multiLine = true; } - node.elements = parseDelimitedList(15, parseArgumentOrArrayLiteralElement); - parseExpected(22); + node.elements = parseDelimitedList(15 /* ArrayLiteralMembers */, parseArgumentOrArrayLiteralElement); + parseExpected(22 /* CloseBracketToken */); return finishNode(node); } function parseObjectLiteralElement() { - var node = createNodeWithJSDoc(0); - if (parseOptionalToken(24)) { - node.kind = 272; + var node = createNodeWithJSDoc(0 /* Unknown */); + if (parseOptionalToken(24 /* DotDotDotToken */)) { + node.kind = 272 /* SpreadAssignment */; node.expression = parseAssignmentExpressionOrHigher(); return finishNode(node); } node.decorators = parseDecorators(); node.modifiers = parseModifiers(); - if (parseContextualModifier(125)) { - return parseAccessorDeclaration(node, 156); + if (parseContextualModifier(125 /* GetKeyword */)) { + return parseAccessorDeclaration(node, 156 /* GetAccessor */); } - if (parseContextualModifier(136)) { - return parseAccessorDeclaration(node, 157); + if (parseContextualModifier(136 /* SetKeyword */)) { + return parseAccessorDeclaration(node, 157 /* SetAccessor */); } - var asteriskToken = parseOptionalToken(39); + var asteriskToken = parseOptionalToken(39 /* AsteriskToken */); var tokenIsIdentifier = isIdentifier(); node.name = parsePropertyName(); - node.questionToken = parseOptionalToken(55); - if (asteriskToken || token() === 19 || token() === 27) { + // Disallowing of optional property assignments happens in the grammar checker. + node.questionToken = parseOptionalToken(55 /* QuestionToken */); + if (asteriskToken || token() === 19 /* OpenParenToken */ || token() === 27 /* LessThanToken */) { return parseMethodDeclaration(node, asteriskToken); } - var isShorthandPropertyAssignment = tokenIsIdentifier && (token() === 26 || token() === 18 || token() === 58); + // check if it is short-hand property assignment or normal property assignment + // NOTE: if token is EqualsToken it is interpreted as CoverInitializedName production + // CoverInitializedName[Yield] : + // IdentifierReference[?Yield] Initializer[In, ?Yield] + // this is necessary because ObjectLiteral productions are also used to cover grammar for ObjectAssignmentPattern + var isShorthandPropertyAssignment = tokenIsIdentifier && (token() === 26 /* CommaToken */ || token() === 18 /* CloseBraceToken */ || token() === 58 /* EqualsToken */); if (isShorthandPropertyAssignment) { - node.kind = 271; - var equalsToken = parseOptionalToken(58); + node.kind = 271 /* ShorthandPropertyAssignment */; + var equalsToken = parseOptionalToken(58 /* EqualsToken */); if (equalsToken) { node.equalsToken = equalsToken; node.objectAssignmentInitializer = allowInAnd(parseAssignmentExpressionOrHigher); } } else { - node.kind = 270; - parseExpected(56); + node.kind = 270 /* PropertyAssignment */; + parseExpected(56 /* ColonToken */); node.initializer = allowInAnd(parseAssignmentExpressionOrHigher); } return finishNode(node); } function parseObjectLiteralExpression() { - var node = createNode(184); - parseExpected(17); + var node = createNode(184 /* ObjectLiteralExpression */); + parseExpected(17 /* OpenBraceToken */); if (scanner.hasPrecedingLineBreak()) { node.multiLine = true; } - node.properties = parseDelimitedList(12, parseObjectLiteralElement, true); - parseExpected(18); + node.properties = parseDelimitedList(12 /* ObjectLiteralMembers */, parseObjectLiteralElement, /*considerSemicolonAsDelimiter*/ true); + parseExpected(18 /* CloseBraceToken */); return finishNode(node); } function parseFunctionExpression() { + // GeneratorExpression: + // function* BindingIdentifier [Yield][opt](FormalParameters[Yield]){ GeneratorBody } + // + // FunctionExpression: + // function BindingIdentifier[opt](FormalParameters){ FunctionBody } var saveDecoratorContext = inDecoratorContext(); if (saveDecoratorContext) { - setDecoratorContext(false); + setDecoratorContext(/*val*/ false); } - var node = createNodeWithJSDoc(192); + var node = createNodeWithJSDoc(192 /* FunctionExpression */); node.modifiers = parseModifiers(); - parseExpected(89); - node.asteriskToken = parseOptionalToken(39); - var isGenerator = node.asteriskToken ? 1 : 0; - var isAsync = ts.hasModifier(node, 256) ? 2 : 0; + parseExpected(89 /* FunctionKeyword */); + node.asteriskToken = parseOptionalToken(39 /* AsteriskToken */); + var isGenerator = node.asteriskToken ? 1 /* Yield */ : 0 /* None */; + var isAsync = ts.hasModifier(node, 256 /* Async */) ? 2 /* Await */ : 0 /* None */; node.name = isGenerator && isAsync ? doInYieldAndAwaitContext(parseOptionalIdentifier) : isGenerator ? doInYieldContext(parseOptionalIdentifier) : isAsync ? doInAwaitContext(parseOptionalIdentifier) : parseOptionalIdentifier(); - fillSignature(56, isGenerator | isAsync, node); + fillSignature(56 /* ColonToken */, isGenerator | isAsync, node); node.body = parseFunctionBlock(isGenerator | isAsync); if (saveDecoratorContext) { - setDecoratorContext(true); + setDecoratorContext(/*val*/ true); } return finishNode(node); } @@ -16600,10 +19252,10 @@ var ts; } function parseNewExpressionOrNewDotTarget() { var fullStart = scanner.getStartPos(); - parseExpected(94); - if (parseOptional(23)) { - var node_2 = createNode(210, fullStart); - node_2.keywordToken = 94; + parseExpected(94 /* NewKeyword */); + if (parseOptional(23 /* DotToken */)) { + var node_2 = createNode(210 /* MetaProperty */, fullStart); + node_2.keywordToken = 94 /* NewKeyword */; node_2.name = parseIdentifierName(); return finishNode(node_2); } @@ -16619,22 +19271,23 @@ var ts; } break; } - var node = createNode(188, fullStart); + var node = createNode(188 /* NewExpression */, fullStart); node.expression = expression; node.typeArguments = typeArguments; - if (node.typeArguments || token() === 19) { + if (node.typeArguments || token() === 19 /* OpenParenToken */) { node.arguments = parseArgumentList(); } return finishNode(node); } + // STATEMENTS function parseBlock(ignoreMissingOpenBrace, diagnosticMessage) { - var node = createNode(213); - if (parseExpected(17, diagnosticMessage) || ignoreMissingOpenBrace) { + var node = createNode(213 /* Block */); + if (parseExpected(17 /* OpenBraceToken */, diagnosticMessage) || ignoreMissingOpenBrace) { if (scanner.hasPrecedingLineBreak()) { node.multiLine = true; } - node.statements = parseList(1, parseStatement); - parseExpected(18); + node.statements = parseList(1 /* BlockStatements */, parseStatement); + parseExpected(18 /* CloseBraceToken */); } else { node.statements = createMissingList(); @@ -16643,98 +19296,104 @@ var ts; } function parseFunctionBlock(flags, diagnosticMessage) { var savedYieldContext = inYieldContext(); - setYieldContext(!!(flags & 1)); + setYieldContext(!!(flags & 1 /* Yield */)); var savedAwaitContext = inAwaitContext(); - setAwaitContext(!!(flags & 2)); + setAwaitContext(!!(flags & 2 /* Await */)); + // We may be in a [Decorator] context when parsing a function expression or + // arrow function. The body of the function is not in [Decorator] context. var saveDecoratorContext = inDecoratorContext(); if (saveDecoratorContext) { - setDecoratorContext(false); + setDecoratorContext(/*val*/ false); } - var block = parseBlock(!!(flags & 16), diagnosticMessage); + var block = parseBlock(!!(flags & 16 /* IgnoreMissingOpenBrace */), diagnosticMessage); if (saveDecoratorContext) { - setDecoratorContext(true); + setDecoratorContext(/*val*/ true); } setYieldContext(savedYieldContext); setAwaitContext(savedAwaitContext); return block; } function parseEmptyStatement() { - var node = createNode(215); - parseExpected(25); + var node = createNode(215 /* EmptyStatement */); + parseExpected(25 /* SemicolonToken */); return finishNode(node); } function parseIfStatement() { - var node = createNode(217); - parseExpected(90); - parseExpected(19); + var node = createNode(217 /* IfStatement */); + parseExpected(90 /* IfKeyword */); + parseExpected(19 /* OpenParenToken */); node.expression = allowInAnd(parseExpression); - parseExpected(20); + parseExpected(20 /* CloseParenToken */); node.thenStatement = parseStatement(); - node.elseStatement = parseOptional(82) ? parseStatement() : undefined; + node.elseStatement = parseOptional(82 /* ElseKeyword */) ? parseStatement() : undefined; return finishNode(node); } function parseDoStatement() { - var node = createNode(218); - parseExpected(81); + var node = createNode(218 /* DoStatement */); + parseExpected(81 /* DoKeyword */); node.statement = parseStatement(); - parseExpected(106); - parseExpected(19); + parseExpected(106 /* WhileKeyword */); + parseExpected(19 /* OpenParenToken */); node.expression = allowInAnd(parseExpression); - parseExpected(20); - parseOptional(25); + parseExpected(20 /* CloseParenToken */); + // From: https://mail.mozilla.org/pipermail/es-discuss/2011-August/016188.html + // 157 min --- All allen at wirfs-brock.com CONF --- "do{;}while(false)false" prohibited in + // spec but allowed in consensus reality. Approved -- this is the de-facto standard whereby + // do;while(0)x will have a semicolon inserted before x. + parseOptional(25 /* SemicolonToken */); return finishNode(node); } function parseWhileStatement() { - var node = createNode(219); - parseExpected(106); - parseExpected(19); + var node = createNode(219 /* WhileStatement */); + parseExpected(106 /* WhileKeyword */); + parseExpected(19 /* OpenParenToken */); node.expression = allowInAnd(parseExpression); - parseExpected(20); + parseExpected(20 /* CloseParenToken */); node.statement = parseStatement(); return finishNode(node); } function parseForOrForInOrForOfStatement() { var pos = getNodePos(); - parseExpected(88); - var awaitToken = parseOptionalToken(121); - parseExpected(19); + parseExpected(88 /* ForKeyword */); + var awaitToken = parseOptionalToken(121 /* AwaitKeyword */); + parseExpected(19 /* OpenParenToken */); var initializer; - if (token() !== 25) { - if (token() === 104 || token() === 110 || token() === 76) { - initializer = parseVariableDeclarationList(true); + if (token() !== 25 /* SemicolonToken */) { + if (token() === 104 /* VarKeyword */ || token() === 110 /* LetKeyword */ || token() === 76 /* ConstKeyword */) { + initializer = parseVariableDeclarationList(/*inForStatementInitializer*/ true); } else { initializer = disallowInAnd(parseExpression); } } var forOrForInOrForOfStatement; - if (awaitToken ? parseExpected(145) : parseOptional(145)) { - var forOfStatement = createNode(222, pos); + if (awaitToken ? parseExpected(145 /* OfKeyword */) : parseOptional(145 /* OfKeyword */)) { + var forOfStatement = createNode(222 /* ForOfStatement */, pos); forOfStatement.awaitModifier = awaitToken; forOfStatement.initializer = initializer; forOfStatement.expression = allowInAnd(parseAssignmentExpressionOrHigher); - parseExpected(20); + parseExpected(20 /* CloseParenToken */); forOrForInOrForOfStatement = forOfStatement; } - else if (parseOptional(92)) { - var forInStatement = createNode(221, pos); + else if (parseOptional(92 /* InKeyword */)) { + var forInStatement = createNode(221 /* ForInStatement */, pos); forInStatement.initializer = initializer; forInStatement.expression = allowInAnd(parseExpression); - parseExpected(20); + parseExpected(20 /* CloseParenToken */); forOrForInOrForOfStatement = forInStatement; } else { - var forStatement = createNode(220, pos); + var forStatement = createNode(220 /* ForStatement */, pos); forStatement.initializer = initializer; - parseExpected(25); - if (token() !== 25 && token() !== 20) { + parseExpected(25 /* SemicolonToken */); + if (token() !== 25 /* SemicolonToken */ && token() !== 20 /* CloseParenToken */) { forStatement.condition = allowInAnd(parseExpression); } - parseExpected(25); - if (token() !== 20) { + parseExpected(25 /* SemicolonToken */); + if (token() !== 20 /* CloseParenToken */) { forStatement.incrementor = allowInAnd(parseExpression); } - parseExpected(20); + parseExpected(20 /* CloseParenToken */); forOrForInOrForOfStatement = forStatement; } forOrForInOrForOfStatement.statement = parseStatement(); @@ -16742,7 +19401,7 @@ var ts; } function parseBreakOrContinueStatement(kind) { var node = createNode(kind); - parseExpected(kind === 224 ? 72 : 77); + parseExpected(kind === 224 /* BreakStatement */ ? 72 /* BreakKeyword */ : 77 /* ContinueKeyword */); if (!canParseSemicolon()) { node.label = parseIdentifier(); } @@ -16750,8 +19409,8 @@ var ts; return finishNode(node); } function parseReturnStatement() { - var node = createNode(225); - parseExpected(96); + var node = createNode(225 /* ReturnStatement */); + parseExpected(96 /* ReturnKeyword */); if (!canParseSemicolon()) { node.expression = allowInAnd(parseExpression); } @@ -16759,92 +19418,106 @@ var ts; return finishNode(node); } function parseWithStatement() { - var node = createNode(226); - parseExpected(107); - parseExpected(19); + var node = createNode(226 /* WithStatement */); + parseExpected(107 /* WithKeyword */); + parseExpected(19 /* OpenParenToken */); node.expression = allowInAnd(parseExpression); - parseExpected(20); - node.statement = doInsideOfContext(8388608, parseStatement); + parseExpected(20 /* CloseParenToken */); + node.statement = doInsideOfContext(8388608 /* InWithStatement */, parseStatement); return finishNode(node); } function parseCaseClause() { - var node = createNode(266); - parseExpected(73); + var node = createNode(266 /* CaseClause */); + parseExpected(73 /* CaseKeyword */); node.expression = allowInAnd(parseExpression); - parseExpected(56); - node.statements = parseList(3, parseStatement); + parseExpected(56 /* ColonToken */); + node.statements = parseList(3 /* SwitchClauseStatements */, parseStatement); return finishNode(node); } function parseDefaultClause() { - var node = createNode(267); - parseExpected(79); - parseExpected(56); - node.statements = parseList(3, parseStatement); + var node = createNode(267 /* DefaultClause */); + parseExpected(79 /* DefaultKeyword */); + parseExpected(56 /* ColonToken */); + node.statements = parseList(3 /* SwitchClauseStatements */, parseStatement); return finishNode(node); } function parseCaseOrDefaultClause() { - return token() === 73 ? parseCaseClause() : parseDefaultClause(); + return token() === 73 /* CaseKeyword */ ? parseCaseClause() : parseDefaultClause(); } function parseSwitchStatement() { - var node = createNode(227); - parseExpected(98); - parseExpected(19); + var node = createNode(227 /* SwitchStatement */); + parseExpected(98 /* SwitchKeyword */); + parseExpected(19 /* OpenParenToken */); node.expression = allowInAnd(parseExpression); - parseExpected(20); - var caseBlock = createNode(241); - parseExpected(17); - caseBlock.clauses = parseList(2, parseCaseOrDefaultClause); - parseExpected(18); + parseExpected(20 /* CloseParenToken */); + var caseBlock = createNode(241 /* CaseBlock */); + parseExpected(17 /* OpenBraceToken */); + caseBlock.clauses = parseList(2 /* SwitchClauses */, parseCaseOrDefaultClause); + parseExpected(18 /* CloseBraceToken */); node.caseBlock = finishNode(caseBlock); return finishNode(node); } function parseThrowStatement() { - var node = createNode(229); - parseExpected(100); + // ThrowStatement[Yield] : + // throw [no LineTerminator here]Expression[In, ?Yield]; + // Because of automatic semicolon insertion, we need to report error if this + // throw could be terminated with a semicolon. Note: we can't call 'parseExpression' + // directly as that might consume an expression on the following line. + // We just return 'undefined' in that case. The actual error will be reported in the + // grammar walker. + var node = createNode(229 /* ThrowStatement */); + parseExpected(100 /* ThrowKeyword */); node.expression = scanner.hasPrecedingLineBreak() ? undefined : allowInAnd(parseExpression); parseSemicolon(); return finishNode(node); } + // TODO: Review for error recovery function parseTryStatement() { - var node = createNode(230); - parseExpected(102); - node.tryBlock = parseBlock(false); - node.catchClause = token() === 74 ? parseCatchClause() : undefined; - if (!node.catchClause || token() === 87) { - parseExpected(87); - node.finallyBlock = parseBlock(false); + var node = createNode(230 /* TryStatement */); + parseExpected(102 /* TryKeyword */); + node.tryBlock = parseBlock(/*ignoreMissingOpenBrace*/ false); + node.catchClause = token() === 74 /* CatchKeyword */ ? parseCatchClause() : undefined; + // If we don't have a catch clause, then we must have a finally clause. Try to parse + // one out no matter what. + if (!node.catchClause || token() === 87 /* FinallyKeyword */) { + parseExpected(87 /* FinallyKeyword */); + node.finallyBlock = parseBlock(/*ignoreMissingOpenBrace*/ false); } return finishNode(node); } function parseCatchClause() { - var result = createNode(269); - parseExpected(74); - if (parseOptional(19)) { + var result = createNode(269 /* CatchClause */); + parseExpected(74 /* CatchKeyword */); + if (parseOptional(19 /* OpenParenToken */)) { result.variableDeclaration = parseVariableDeclaration(); - parseExpected(20); + parseExpected(20 /* CloseParenToken */); } else { + // Keep shape of node to avoid degrading performance. result.variableDeclaration = undefined; } - result.block = parseBlock(false); + result.block = parseBlock(/*ignoreMissingOpenBrace*/ false); return finishNode(result); } function parseDebuggerStatement() { - var node = createNode(231); - parseExpected(78); + var node = createNode(231 /* DebuggerStatement */); + parseExpected(78 /* DebuggerKeyword */); parseSemicolon(); return finishNode(node); } function parseExpressionOrLabeledStatement() { - var node = createNodeWithJSDoc(0); + // Avoiding having to do the lookahead for a labeled statement by just trying to parse + // out an expression, seeing if it is identifier and then seeing if it is followed by + // a colon. + var node = createNodeWithJSDoc(0 /* Unknown */); var expression = allowInAnd(parseExpression); - if (expression.kind === 71 && parseOptional(56)) { - node.kind = 228; + if (expression.kind === 71 /* Identifier */ && parseOptional(56 /* ColonToken */)) { + node.kind = 228 /* LabeledStatement */; node.label = expression; node.statement = parseStatement(); } else { - node.kind = 216; + node.kind = 216 /* ExpressionStatement */; node.expression = expression; parseSemicolon(); } @@ -16856,60 +19529,82 @@ var ts; } function nextTokenIsClassKeywordOnSameLine() { nextToken(); - return token() === 75 && !scanner.hasPrecedingLineBreak(); + return token() === 75 /* ClassKeyword */ && !scanner.hasPrecedingLineBreak(); } function nextTokenIsFunctionKeywordOnSameLine() { nextToken(); - return token() === 89 && !scanner.hasPrecedingLineBreak(); + return token() === 89 /* FunctionKeyword */ && !scanner.hasPrecedingLineBreak(); } function nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine() { nextToken(); - return (ts.tokenIsIdentifierOrKeyword(token()) || token() === 8 || token() === 9) && !scanner.hasPrecedingLineBreak(); + return (ts.tokenIsIdentifierOrKeyword(token()) || token() === 8 /* NumericLiteral */ || token() === 9 /* StringLiteral */) && !scanner.hasPrecedingLineBreak(); } function isDeclaration() { while (true) { switch (token()) { - case 104: - case 110: - case 76: - case 89: - case 75: - case 83: + case 104 /* VarKeyword */: + case 110 /* LetKeyword */: + case 76 /* ConstKeyword */: + case 89 /* FunctionKeyword */: + case 75 /* ClassKeyword */: + case 83 /* EnumKeyword */: return true; - case 109: - case 139: + // 'declare', 'module', 'namespace', 'interface'* and 'type' are all legal JavaScript identifiers; + // however, an identifier cannot be followed by another identifier on the same line. This is what we + // count on to parse out the respective declarations. For instance, we exploit this to say that + // + // namespace n + // + // can be none other than the beginning of a namespace declaration, but need to respect that JavaScript sees + // + // namespace + // n + // + // as the identifier 'namespace' on one line followed by the identifier 'n' on another. + // We need to look one token ahead to see if it permissible to try parsing a declaration. + // + // *Note*: 'interface' is actually a strict mode reserved word. So while + // + // "use strict" + // interface + // I {} + // + // could be legal, it would add complexity for very little gain. + case 109 /* InterfaceKeyword */: + case 139 /* TypeKeyword */: return nextTokenIsIdentifierOnSameLine(); - case 129: - case 130: + case 129 /* ModuleKeyword */: + case 130 /* NamespaceKeyword */: return nextTokenIsIdentifierOrStringLiteralOnSameLine(); - case 117: - case 120: - case 124: - case 112: - case 113: - case 114: - case 132: + case 117 /* AbstractKeyword */: + case 120 /* AsyncKeyword */: + case 124 /* DeclareKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: + case 114 /* PublicKeyword */: + case 132 /* ReadonlyKeyword */: nextToken(); + // ASI takes effect for this modifier. if (scanner.hasPrecedingLineBreak()) { return false; } continue; - case 144: + case 144 /* GlobalKeyword */: nextToken(); - return token() === 17 || token() === 71 || token() === 84; - case 91: + return token() === 17 /* OpenBraceToken */ || token() === 71 /* Identifier */ || token() === 84 /* ExportKeyword */; + case 91 /* ImportKeyword */: nextToken(); - return token() === 9 || token() === 39 || - token() === 17 || ts.tokenIsIdentifierOrKeyword(token()); - case 84: + return token() === 9 /* StringLiteral */ || token() === 39 /* AsteriskToken */ || + token() === 17 /* OpenBraceToken */ || ts.tokenIsIdentifierOrKeyword(token()); + case 84 /* ExportKeyword */: nextToken(); - if (token() === 58 || token() === 39 || - token() === 17 || token() === 79 || - token() === 118) { + if (token() === 58 /* EqualsToken */ || token() === 39 /* AsteriskToken */ || + token() === 17 /* OpenBraceToken */ || token() === 79 /* DefaultKeyword */ || + token() === 118 /* AsKeyword */) { return true; } continue; - case 115: + case 115 /* StaticKeyword */: nextToken(); continue; default: @@ -16922,47 +19617,52 @@ var ts; } function isStartOfStatement() { switch (token()) { - case 57: - case 25: - case 17: - case 104: - case 110: - case 89: - case 75: - case 83: - case 90: - case 81: - case 106: - case 88: - case 77: - case 72: - case 96: - case 107: - case 98: - case 100: - case 102: - case 78: - case 74: - case 87: + case 57 /* AtToken */: + case 25 /* SemicolonToken */: + case 17 /* OpenBraceToken */: + case 104 /* VarKeyword */: + case 110 /* LetKeyword */: + case 89 /* FunctionKeyword */: + case 75 /* ClassKeyword */: + case 83 /* EnumKeyword */: + case 90 /* IfKeyword */: + case 81 /* DoKeyword */: + case 106 /* WhileKeyword */: + case 88 /* ForKeyword */: + case 77 /* ContinueKeyword */: + case 72 /* BreakKeyword */: + case 96 /* ReturnKeyword */: + case 107 /* WithKeyword */: + case 98 /* SwitchKeyword */: + case 100 /* ThrowKeyword */: + case 102 /* TryKeyword */: + case 78 /* DebuggerKeyword */: + // 'catch' and 'finally' do not actually indicate that the code is part of a statement, + // however, we say they are here so that we may gracefully parse them and error later. + case 74 /* CatchKeyword */: + case 87 /* FinallyKeyword */: return true; - case 91: + case 91 /* ImportKeyword */: return isStartOfDeclaration() || lookAhead(nextTokenIsOpenParenOrLessThanOrDot); - case 76: - case 84: + case 76 /* ConstKeyword */: + case 84 /* ExportKeyword */: return isStartOfDeclaration(); - case 120: - case 124: - case 109: - case 129: - case 130: - case 139: - case 144: + case 120 /* AsyncKeyword */: + case 124 /* DeclareKeyword */: + case 109 /* InterfaceKeyword */: + case 129 /* ModuleKeyword */: + case 130 /* NamespaceKeyword */: + case 139 /* TypeKeyword */: + case 144 /* GlobalKeyword */: + // When these don't start a declaration, they're an identifier in an expression statement return true; - case 114: - case 112: - case 113: - case 115: - case 132: + case 114 /* PublicKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: + case 115 /* StaticKeyword */: + case 132 /* ReadonlyKeyword */: + // When these don't start a declaration, they may be the start of a class member if an identifier + // immediately follows. Otherwise they're an identifier in an expression statement. return isStartOfDeclaration() || !lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine); default: return isStartOfExpression(); @@ -16970,73 +19670,76 @@ var ts; } function nextTokenIsIdentifierOrStartOfDestructuring() { nextToken(); - return isIdentifier() || token() === 17 || token() === 21; + return isIdentifier() || token() === 17 /* OpenBraceToken */ || token() === 21 /* OpenBracketToken */; } function isLetDeclaration() { + // In ES6 'let' always starts a lexical declaration if followed by an identifier or { + // or [. return lookAhead(nextTokenIsIdentifierOrStartOfDestructuring); } function parseStatement() { switch (token()) { - case 25: + case 25 /* SemicolonToken */: return parseEmptyStatement(); - case 17: - return parseBlock(false); - case 104: - return parseVariableStatement(createNodeWithJSDoc(232)); - case 110: + case 17 /* OpenBraceToken */: + return parseBlock(/*ignoreMissingOpenBrace*/ false); + case 104 /* VarKeyword */: + return parseVariableStatement(createNodeWithJSDoc(232 /* VariableDeclaration */)); + case 110 /* LetKeyword */: if (isLetDeclaration()) { - return parseVariableStatement(createNodeWithJSDoc(232)); + return parseVariableStatement(createNodeWithJSDoc(232 /* VariableDeclaration */)); } break; - case 89: - return parseFunctionDeclaration(createNodeWithJSDoc(234)); - case 75: - return parseClassDeclaration(createNodeWithJSDoc(235)); - case 90: + case 89 /* FunctionKeyword */: + return parseFunctionDeclaration(createNodeWithJSDoc(234 /* FunctionDeclaration */)); + case 75 /* ClassKeyword */: + return parseClassDeclaration(createNodeWithJSDoc(235 /* ClassDeclaration */)); + case 90 /* IfKeyword */: return parseIfStatement(); - case 81: + case 81 /* DoKeyword */: return parseDoStatement(); - case 106: + case 106 /* WhileKeyword */: return parseWhileStatement(); - case 88: + case 88 /* ForKeyword */: return parseForOrForInOrForOfStatement(); - case 77: - return parseBreakOrContinueStatement(223); - case 72: - return parseBreakOrContinueStatement(224); - case 96: + case 77 /* ContinueKeyword */: + return parseBreakOrContinueStatement(223 /* ContinueStatement */); + case 72 /* BreakKeyword */: + return parseBreakOrContinueStatement(224 /* BreakStatement */); + case 96 /* ReturnKeyword */: return parseReturnStatement(); - case 107: + case 107 /* WithKeyword */: return parseWithStatement(); - case 98: + case 98 /* SwitchKeyword */: return parseSwitchStatement(); - case 100: + case 100 /* ThrowKeyword */: return parseThrowStatement(); - case 102: - case 74: - case 87: + case 102 /* TryKeyword */: + // Include 'catch' and 'finally' for error recovery. + case 74 /* CatchKeyword */: + case 87 /* FinallyKeyword */: return parseTryStatement(); - case 78: + case 78 /* DebuggerKeyword */: return parseDebuggerStatement(); - case 57: + case 57 /* AtToken */: return parseDeclaration(); - case 120: - case 109: - case 139: - case 129: - case 130: - case 124: - case 76: - case 83: - case 84: - case 91: - case 112: - case 113: - case 114: - case 117: - case 115: - case 132: - case 144: + case 120 /* AsyncKeyword */: + case 109 /* InterfaceKeyword */: + case 139 /* TypeKeyword */: + case 129 /* ModuleKeyword */: + case 130 /* NamespaceKeyword */: + case 124 /* DeclareKeyword */: + case 76 /* ConstKeyword */: + case 83 /* EnumKeyword */: + case 84 /* ExportKeyword */: + case 91 /* ImportKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: + case 114 /* PublicKeyword */: + case 117 /* AbstractKeyword */: + case 115 /* StaticKeyword */: + case 132 /* ReadonlyKeyword */: + case 144 /* GlobalKeyword */: if (isStartOfDeclaration()) { return parseDeclaration(); } @@ -17045,18 +19748,18 @@ var ts; return parseExpressionOrLabeledStatement(); } function isDeclareModifier(modifier) { - return modifier.kind === 124; + return modifier.kind === 124 /* DeclareKeyword */; } function parseDeclaration() { - var node = createNodeWithJSDoc(0); + var node = createNodeWithJSDoc(0 /* Unknown */); node.decorators = parseDecorators(); node.modifiers = parseModifiers(); if (ts.some(node.modifiers, isDeclareModifier)) { for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { var m = _a[_i]; - m.flags |= 4194304; + m.flags |= 4194304 /* Ambient */; } - return doInsideOfContext(4194304, function () { return parseDeclarationWorker(node); }); + return doInsideOfContext(4194304 /* Ambient */, function () { return parseDeclarationWorker(node); }); } else { return parseDeclarationWorker(node); @@ -17064,79 +19767,82 @@ var ts; } function parseDeclarationWorker(node) { switch (token()) { - case 104: - case 110: - case 76: + case 104 /* VarKeyword */: + case 110 /* LetKeyword */: + case 76 /* ConstKeyword */: return parseVariableStatement(node); - case 89: + case 89 /* FunctionKeyword */: return parseFunctionDeclaration(node); - case 75: + case 75 /* ClassKeyword */: return parseClassDeclaration(node); - case 109: + case 109 /* InterfaceKeyword */: return parseInterfaceDeclaration(node); - case 139: + case 139 /* TypeKeyword */: return parseTypeAliasDeclaration(node); - case 83: + case 83 /* EnumKeyword */: return parseEnumDeclaration(node); - case 144: - case 129: - case 130: + case 144 /* GlobalKeyword */: + case 129 /* ModuleKeyword */: + case 130 /* NamespaceKeyword */: return parseModuleDeclaration(node); - case 91: + case 91 /* ImportKeyword */: return parseImportDeclarationOrImportEqualsDeclaration(node); - case 84: + case 84 /* ExportKeyword */: nextToken(); switch (token()) { - case 79: - case 58: + case 79 /* DefaultKeyword */: + case 58 /* EqualsToken */: return parseExportAssignment(node); - case 118: + case 118 /* AsKeyword */: return parseNamespaceExportDeclaration(node); default: return parseExportDeclaration(node); } default: if (node.decorators || node.modifiers) { - var missing = createMissingNode(253, true, ts.Diagnostics.Declaration_expected); + // We reached this point because we encountered decorators and/or modifiers and assumed a declaration + // would follow. For recovery and error reporting purposes, return an incomplete declaration. + var missing = createMissingNode(253 /* MissingDeclaration */, /*reportAtCurrentPosition*/ true, ts.Diagnostics.Declaration_expected); missing.pos = node.pos; missing.decorators = node.decorators; missing.modifiers = node.modifiers; return finishNode(missing); } - return undefined; + return undefined; // TODO: GH#18217 } } function nextTokenIsIdentifierOrStringLiteralOnSameLine() { nextToken(); - return !scanner.hasPrecedingLineBreak() && (isIdentifier() || token() === 9); + return !scanner.hasPrecedingLineBreak() && (isIdentifier() || token() === 9 /* StringLiteral */); } function parseFunctionBlockOrSemicolon(flags, diagnosticMessage) { - if (token() !== 17 && canParseSemicolon()) { + if (token() !== 17 /* OpenBraceToken */ && canParseSemicolon()) { parseSemicolon(); return; } return parseFunctionBlock(flags, diagnosticMessage); } + // DECLARATIONS function parseArrayBindingElement() { - if (token() === 26) { - return createNode(206); + if (token() === 26 /* CommaToken */) { + return createNode(206 /* OmittedExpression */); } - var node = createNode(182); - node.dotDotDotToken = parseOptionalToken(24); + var node = createNode(182 /* BindingElement */); + node.dotDotDotToken = parseOptionalToken(24 /* DotDotDotToken */); node.name = parseIdentifierOrPattern(); node.initializer = parseInitializer(); return finishNode(node); } function parseObjectBindingElement() { - var node = createNode(182); - node.dotDotDotToken = parseOptionalToken(24); + var node = createNode(182 /* BindingElement */); + node.dotDotDotToken = parseOptionalToken(24 /* DotDotDotToken */); var tokenIsIdentifier = isIdentifier(); var propertyName = parsePropertyName(); - if (tokenIsIdentifier && token() !== 56) { + if (tokenIsIdentifier && token() !== 56 /* ColonToken */) { node.name = propertyName; } else { - parseExpected(56); + parseExpected(56 /* ColonToken */); node.propertyName = propertyName; node.name = parseIdentifierOrPattern(); } @@ -17144,39 +19850,39 @@ var ts; return finishNode(node); } function parseObjectBindingPattern() { - var node = createNode(180); - parseExpected(17); - node.elements = parseDelimitedList(9, parseObjectBindingElement); - parseExpected(18); + var node = createNode(180 /* ObjectBindingPattern */); + parseExpected(17 /* OpenBraceToken */); + node.elements = parseDelimitedList(9 /* ObjectBindingElements */, parseObjectBindingElement); + parseExpected(18 /* CloseBraceToken */); return finishNode(node); } function parseArrayBindingPattern() { - var node = createNode(181); - parseExpected(21); - node.elements = parseDelimitedList(10, parseArrayBindingElement); - parseExpected(22); + var node = createNode(181 /* ArrayBindingPattern */); + parseExpected(21 /* OpenBracketToken */); + node.elements = parseDelimitedList(10 /* ArrayBindingElements */, parseArrayBindingElement); + parseExpected(22 /* CloseBracketToken */); return finishNode(node); } function isIdentifierOrPattern() { - return token() === 17 || token() === 21 || isIdentifier(); + return token() === 17 /* OpenBraceToken */ || token() === 21 /* OpenBracketToken */ || isIdentifier(); } function parseIdentifierOrPattern() { - if (token() === 21) { + if (token() === 21 /* OpenBracketToken */) { return parseArrayBindingPattern(); } - if (token() === 17) { + if (token() === 17 /* OpenBraceToken */) { return parseObjectBindingPattern(); } return parseIdentifier(); } function parseVariableDeclarationAllowExclamation() { - return parseVariableDeclaration(true); + return parseVariableDeclaration(/*allowExclamation*/ true); } function parseVariableDeclaration(allowExclamation) { - var node = createNode(232); + var node = createNode(232 /* VariableDeclaration */); node.name = parseIdentifierOrPattern(); - if (allowExclamation && node.name.kind === 71 && - token() === 51 && !scanner.hasPrecedingLineBreak()) { + if (allowExclamation && node.name.kind === 71 /* Identifier */ && + token() === 51 /* ExclamationToken */ && !scanner.hasPrecedingLineBreak()) { node.exclamationToken = parseTokenNode(); } node.type = parseTypeAnnotation(); @@ -17186,84 +19892,104 @@ var ts; return finishNode(node); } function parseVariableDeclarationList(inForStatementInitializer) { - var node = createNode(233); + var node = createNode(233 /* VariableDeclarationList */); switch (token()) { - case 104: + case 104 /* VarKeyword */: break; - case 110: - node.flags |= 1; + case 110 /* LetKeyword */: + node.flags |= 1 /* Let */; break; - case 76: - node.flags |= 2; + case 76 /* ConstKeyword */: + node.flags |= 2 /* Const */; break; default: ts.Debug.fail(); } nextToken(); - if (token() === 145 && lookAhead(canFollowContextualOfKeyword)) { + // The user may have written the following: + // + // for (let of X) { } + // + // In this case, we want to parse an empty declaration list, and then parse 'of' + // as a keyword. The reason this is not automatic is that 'of' is a valid identifier. + // So we need to look ahead to determine if 'of' should be treated as a keyword in + // this context. + // The checker will then give an error that there is an empty declaration list. + if (token() === 145 /* OfKeyword */ && lookAhead(canFollowContextualOfKeyword)) { node.declarations = createMissingList(); } else { var savedDisallowIn = inDisallowInContext(); setDisallowInContext(inForStatementInitializer); - node.declarations = parseDelimitedList(8, inForStatementInitializer ? parseVariableDeclaration : parseVariableDeclarationAllowExclamation); + node.declarations = parseDelimitedList(8 /* VariableDeclarations */, inForStatementInitializer ? parseVariableDeclaration : parseVariableDeclarationAllowExclamation); setDisallowInContext(savedDisallowIn); } return finishNode(node); } function canFollowContextualOfKeyword() { - return nextTokenIsIdentifier() && nextToken() === 20; + return nextTokenIsIdentifier() && nextToken() === 20 /* CloseParenToken */; } function parseVariableStatement(node) { - node.kind = 214; - node.declarationList = parseVariableDeclarationList(false); + node.kind = 214 /* VariableStatement */; + node.declarationList = parseVariableDeclarationList(/*inForStatementInitializer*/ false); parseSemicolon(); return finishNode(node); } function parseFunctionDeclaration(node) { - node.kind = 234; - parseExpected(89); - node.asteriskToken = parseOptionalToken(39); - node.name = ts.hasModifier(node, 512) ? parseOptionalIdentifier() : parseIdentifier(); - var isGenerator = node.asteriskToken ? 1 : 0; - var isAsync = ts.hasModifier(node, 256) ? 2 : 0; - fillSignature(56, isGenerator | isAsync, node); + node.kind = 234 /* FunctionDeclaration */; + parseExpected(89 /* FunctionKeyword */); + node.asteriskToken = parseOptionalToken(39 /* AsteriskToken */); + node.name = ts.hasModifier(node, 512 /* Default */) ? parseOptionalIdentifier() : parseIdentifier(); + var isGenerator = node.asteriskToken ? 1 /* Yield */ : 0 /* None */; + var isAsync = ts.hasModifier(node, 256 /* Async */) ? 2 /* Await */ : 0 /* None */; + fillSignature(56 /* ColonToken */, isGenerator | isAsync, node); node.body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, ts.Diagnostics.or_expected); return finishNode(node); } function parseConstructorDeclaration(node) { - node.kind = 155; - parseExpected(123); - fillSignature(56, 0, node); - node.body = parseFunctionBlockOrSemicolon(0, ts.Diagnostics.or_expected); + node.kind = 155 /* Constructor */; + parseExpected(123 /* ConstructorKeyword */); + fillSignature(56 /* ColonToken */, 0 /* None */, node); + node.body = parseFunctionBlockOrSemicolon(0 /* None */, ts.Diagnostics.or_expected); return finishNode(node); } function parseMethodDeclaration(node, asteriskToken, diagnosticMessage) { - node.kind = 154; + node.kind = 154 /* MethodDeclaration */; node.asteriskToken = asteriskToken; - var isGenerator = asteriskToken ? 1 : 0; - var isAsync = ts.hasModifier(node, 256) ? 2 : 0; - fillSignature(56, isGenerator | isAsync, node); + var isGenerator = asteriskToken ? 1 /* Yield */ : 0 /* None */; + var isAsync = ts.hasModifier(node, 256 /* Async */) ? 2 /* Await */ : 0 /* None */; + fillSignature(56 /* ColonToken */, isGenerator | isAsync, node); node.body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, diagnosticMessage); return finishNode(node); } function parsePropertyDeclaration(node) { - node.kind = 152; - if (!node.questionToken && token() === 51 && !scanner.hasPrecedingLineBreak()) { + node.kind = 152 /* PropertyDeclaration */; + if (!node.questionToken && token() === 51 /* ExclamationToken */ && !scanner.hasPrecedingLineBreak()) { node.exclamationToken = parseTokenNode(); } node.type = parseTypeAnnotation(); - node.initializer = ts.hasModifier(node, 32) + // For instance properties specifically, since they are evaluated inside the constructor, + // we do *not * want to parse yield expressions, so we specifically turn the yield context + // off. The grammar would look something like this: + // + // MemberVariableDeclaration[Yield]: + // AccessibilityModifier_opt PropertyName TypeAnnotation_opt Initializer_opt[In]; + // AccessibilityModifier_opt static_opt PropertyName TypeAnnotation_opt Initializer_opt[In, ?Yield]; + // + // The checker may still error in the static case to explicitly disallow the yield expression. + node.initializer = ts.hasModifier(node, 32 /* Static */) ? allowInAnd(parseInitializer) - : doOutsideOfContext(4096 | 2048, parseInitializer); + : doOutsideOfContext(4096 /* YieldContext */ | 2048 /* DisallowInContext */, parseInitializer); parseSemicolon(); return finishNode(node); } function parsePropertyOrMethodDeclaration(node) { - var asteriskToken = parseOptionalToken(39); + var asteriskToken = parseOptionalToken(39 /* AsteriskToken */); node.name = parsePropertyName(); - node.questionToken = parseOptionalToken(55); - if (asteriskToken || token() === 19 || token() === 27) { + // Note: this is not legal as per the grammar. But we allow it in the parser and + // report an error in the grammar checker. + node.questionToken = parseOptionalToken(55 /* QuestionToken */); + if (asteriskToken || token() === 19 /* OpenParenToken */ || token() === 27 /* LessThanToken */) { return parseMethodDeclaration(node, asteriskToken, ts.Diagnostics.or_expected); } return parsePropertyDeclaration(node); @@ -17271,45 +19997,64 @@ var ts; function parseAccessorDeclaration(node, kind) { node.kind = kind; node.name = parsePropertyName(); - fillSignature(56, 0, node); - node.body = parseFunctionBlockOrSemicolon(0); + fillSignature(56 /* ColonToken */, 0 /* None */, node); + node.body = parseFunctionBlockOrSemicolon(0 /* None */); return finishNode(node); } function isClassMemberStart() { var idToken; - if (token() === 57) { + if (token() === 57 /* AtToken */) { return true; } + // Eat up all modifiers, but hold on to the last one in case it is actually an identifier. while (ts.isModifierKind(token())) { idToken = token(); + // If the idToken is a class modifier (protected, private, public, and static), it is + // certain that we are starting to parse class member. This allows better error recovery + // Example: + // public foo() ... // true + // public @dec blah ... // true; we will then report an error later + // export public ... // true; we will then report an error later if (ts.isClassMemberModifier(idToken)) { return true; } nextToken(); } - if (token() === 39) { + if (token() === 39 /* AsteriskToken */) { return true; } + // Try to get the first property-like token following all modifiers. + // This can either be an identifier or the 'get' or 'set' keywords. if (isLiteralPropertyName()) { idToken = token(); nextToken(); } - if (token() === 21) { + // Index signatures and computed properties are class members; we can parse. + if (token() === 21 /* OpenBracketToken */) { return true; } + // If we were able to get any potential identifier... if (idToken !== undefined) { - if (!ts.isKeyword(idToken) || idToken === 136 || idToken === 125) { + // If we have a non-keyword identifier, or if we have an accessor, then it's safe to parse. + if (!ts.isKeyword(idToken) || idToken === 136 /* SetKeyword */ || idToken === 125 /* GetKeyword */) { return true; } + // If it *is* a keyword, but not an accessor, check a little farther along + // to see if it should actually be parsed as a class member. switch (token()) { - case 19: - case 27: - case 51: - case 56: - case 58: - case 55: + case 19 /* OpenParenToken */: // Method declaration + case 27 /* LessThanToken */: // Generic Method declaration + case 51 /* ExclamationToken */: // Non-null assertion on property name + case 56 /* ColonToken */: // Type Annotation for declaration + case 58 /* EqualsToken */: // Initializer for declaration + case 55 /* QuestionToken */: // Not valid, but permitted so that it gets caught later on. return true; default: + // Covers + // - Semicolons (declaration termination) + // - Closing braces (end-of-class, must be declaration) + // - End-of-files (not valid, but permitted so that it gets caught later on) + // - Line-breaks (enabling *automatic semicolon insertion*) return canParseSemicolon(); } } @@ -17320,23 +20065,32 @@ var ts; var listPos = getNodePos(); while (true) { var decoratorStart = getNodePos(); - if (!parseOptional(57)) { + if (!parseOptional(57 /* AtToken */)) { break; } - var decorator = createNode(150, decoratorStart); + var decorator = createNode(150 /* Decorator */, decoratorStart); decorator.expression = doInDecoratorContext(parseLeftHandSideExpressionOrHigher); finishNode(decorator); (list || (list = [])).push(decorator); } return list && createNodeArray(list, listPos); } + /* + * There are situations in which a modifier like 'const' will appear unexpectedly, such as on a class member. + * In those situations, if we are entirely sure that 'const' is not valid on its own (such as when ASI takes effect + * and turns it into a standalone declaration), then it is better to parse it and report an error later. + * + * In such situations, 'permitInvalidConstAsModifier' should be set to true. + */ function parseModifiers(permitInvalidConstAsModifier) { var list; var listPos = getNodePos(); while (true) { var modifierStart = scanner.getStartPos(); var modifierKind = token(); - if (token() === 76 && permitInvalidConstAsModifier) { + if (token() === 76 /* ConstKeyword */ && permitInvalidConstAsModifier) { + // We need to ensure that any subsequent modifiers appear on the same line + // so that when 'const' is a standalone declaration, we don't issue an error. if (!tryParse(nextTokenIsOnSameLineAndCanFollowModifier)) { break; } @@ -17353,7 +20107,7 @@ var ts; } function parseModifiersForArrowFunction() { var modifiers; - if (token() === 120) { + if (token() === 120 /* AsyncKeyword */) { var modifierStart = scanner.getStartPos(); var modifierKind = token(); nextToken(); @@ -17363,54 +20117,60 @@ var ts; return modifiers; } function parseClassElement() { - if (token() === 25) { - var result = createNode(212); + if (token() === 25 /* SemicolonToken */) { + var result = createNode(212 /* SemicolonClassElement */); nextToken(); return finishNode(result); } - var node = createNodeWithJSDoc(0); + var node = createNodeWithJSDoc(0 /* Unknown */); node.decorators = parseDecorators(); - node.modifiers = parseModifiers(true); - if (parseContextualModifier(125)) { - return parseAccessorDeclaration(node, 156); + node.modifiers = parseModifiers(/*permitInvalidConstAsModifier*/ true); + if (parseContextualModifier(125 /* GetKeyword */)) { + return parseAccessorDeclaration(node, 156 /* GetAccessor */); } - if (parseContextualModifier(136)) { - return parseAccessorDeclaration(node, 157); + if (parseContextualModifier(136 /* SetKeyword */)) { + return parseAccessorDeclaration(node, 157 /* SetAccessor */); } - if (token() === 123) { + if (token() === 123 /* ConstructorKeyword */) { return parseConstructorDeclaration(node); } if (isIndexSignature()) { return parseIndexSignatureDeclaration(node); } + // It is very important that we check this *after* checking indexers because + // the [ token can start an index signature or a computed property name if (ts.tokenIsIdentifierOrKeyword(token()) || - token() === 9 || - token() === 8 || - token() === 39 || - token() === 21) { + token() === 9 /* StringLiteral */ || + token() === 8 /* NumericLiteral */ || + token() === 39 /* AsteriskToken */ || + token() === 21 /* OpenBracketToken */) { return parsePropertyOrMethodDeclaration(node); } if (node.decorators || node.modifiers) { - node.name = createMissingNode(71, true, ts.Diagnostics.Declaration_expected); + // treat this as a property declaration with a missing name. + node.name = createMissingNode(71 /* Identifier */, /*reportAtCurrentPosition*/ true, ts.Diagnostics.Declaration_expected); return parsePropertyDeclaration(node); } + // 'isClassMemberStart' should have hinted not to attempt parsing. return ts.Debug.fail("Should not have attempted to parse class member declaration."); } function parseClassExpression() { - return parseClassDeclarationOrExpression(createNodeWithJSDoc(0), 205); + return parseClassDeclarationOrExpression(createNodeWithJSDoc(0 /* Unknown */), 205 /* ClassExpression */); } function parseClassDeclaration(node) { - return parseClassDeclarationOrExpression(node, 235); + return parseClassDeclarationOrExpression(node, 235 /* ClassDeclaration */); } function parseClassDeclarationOrExpression(node, kind) { node.kind = kind; - parseExpected(75); + parseExpected(75 /* ClassKeyword */); node.name = parseNameOfClassDeclarationOrExpression(); node.typeParameters = parseTypeParameters(); node.heritageClauses = parseHeritageClauses(); - if (parseExpected(17)) { + if (parseExpected(17 /* OpenBraceToken */)) { + // ClassTail[Yield,Await] : (Modified) See 14.5 + // ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt } node.members = parseClassMembers(); - parseExpected(18); + parseExpected(18 /* CloseBraceToken */); } else { node.members = createMissingList(); @@ -17418,48 +20178,55 @@ var ts; return finishNode(node); } function parseNameOfClassDeclarationOrExpression() { + // implements is a future reserved word so + // 'class implements' might mean either + // - class expression with omitted name, 'implements' starts heritage clause + // - class with name 'implements' + // 'isImplementsClause' helps to disambiguate between these two cases return isIdentifier() && !isImplementsClause() ? parseIdentifier() : undefined; } function isImplementsClause() { - return token() === 108 && lookAhead(nextTokenIsIdentifierOrKeyword); + return token() === 108 /* ImplementsKeyword */ && lookAhead(nextTokenIsIdentifierOrKeyword); } function parseHeritageClauses() { + // ClassTail[Yield,Await] : (Modified) See 14.5 + // ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt } if (isHeritageClause()) { - return parseList(21, parseHeritageClause); + return parseList(21 /* HeritageClauses */, parseHeritageClause); } return undefined; } function parseHeritageClause() { var tok = token(); - ts.Debug.assert(tok === 85 || tok === 108); - var node = createNode(268); + ts.Debug.assert(tok === 85 /* ExtendsKeyword */ || tok === 108 /* ImplementsKeyword */); // isListElement() should ensure this. + var node = createNode(268 /* HeritageClause */); node.token = tok; nextToken(); - node.types = parseDelimitedList(7, parseExpressionWithTypeArguments); + node.types = parseDelimitedList(7 /* HeritageClauseElement */, parseExpressionWithTypeArguments); return finishNode(node); } function parseExpressionWithTypeArguments() { - var node = createNode(207); + var node = createNode(207 /* ExpressionWithTypeArguments */); node.expression = parseLeftHandSideExpressionOrHigher(); node.typeArguments = tryParseTypeArguments(); return finishNode(node); } function tryParseTypeArguments() { - return token() === 27 - ? parseBracketedList(19, parseType, 27, 29) + return token() === 27 /* LessThanToken */ + ? parseBracketedList(19 /* TypeArguments */, parseType, 27 /* LessThanToken */, 29 /* GreaterThanToken */) : undefined; } function isHeritageClause() { - return token() === 85 || token() === 108; + return token() === 85 /* ExtendsKeyword */ || token() === 108 /* ImplementsKeyword */; } function parseClassMembers() { - return parseList(5, parseClassElement); + return parseList(5 /* ClassMembers */, parseClassElement); } function parseInterfaceDeclaration(node) { - node.kind = 236; - parseExpected(109); + node.kind = 236 /* InterfaceDeclaration */; + parseExpected(109 /* InterfaceKeyword */); node.name = parseIdentifier(); node.typeParameters = parseTypeParameters(); node.heritageClauses = parseHeritageClauses(); @@ -17467,28 +20234,32 @@ var ts; return finishNode(node); } function parseTypeAliasDeclaration(node) { - node.kind = 237; - parseExpected(139); + node.kind = 237 /* TypeAliasDeclaration */; + parseExpected(139 /* TypeKeyword */); node.name = parseIdentifier(); node.typeParameters = parseTypeParameters(); - parseExpected(58); + parseExpected(58 /* EqualsToken */); node.type = parseType(); parseSemicolon(); return finishNode(node); } + // In an ambient declaration, the grammar only allows integer literals as initializers. + // In a non-ambient declaration, the grammar allows uninitialized members only in a + // ConstantEnumMemberSection, which starts at the beginning of an enum declaration + // or any time an integer literal initializer is encountered. function parseEnumMember() { - var node = createNodeWithJSDoc(273); + var node = createNodeWithJSDoc(273 /* EnumMember */); node.name = parsePropertyName(); node.initializer = allowInAnd(parseInitializer); return finishNode(node); } function parseEnumDeclaration(node) { - node.kind = 238; - parseExpected(83); + node.kind = 238 /* EnumDeclaration */; + parseExpected(83 /* EnumKeyword */); node.name = parseIdentifier(); - if (parseExpected(17)) { - node.members = parseDelimitedList(6, parseEnumMember); - parseExpected(18); + if (parseExpected(17 /* OpenBraceToken */)) { + node.members = parseDelimitedList(6 /* EnumMembers */, parseEnumMember); + parseExpected(18 /* CloseBraceToken */); } else { node.members = createMissingList(); @@ -17496,10 +20267,10 @@ var ts; return finishNode(node); } function parseModuleBlock() { - var node = createNode(240); - if (parseExpected(17)) { - node.statements = parseList(1, parseStatement); - parseExpected(18); + var node = createNode(240 /* ModuleBlock */); + if (parseExpected(17 /* OpenBraceToken */)) { + node.statements = parseList(1 /* BlockStatements */, parseStatement); + parseExpected(18 /* CloseBraceToken */); } else { node.statements = createMissingList(); @@ -17507,26 +20278,29 @@ var ts; return finishNode(node); } function parseModuleOrNamespaceDeclaration(node, flags) { - node.kind = 239; - var namespaceFlag = flags & 16; + node.kind = 239 /* ModuleDeclaration */; + // If we are parsing a dotted namespace name, we want to + // propagate the 'Namespace' flag across the names if set. + var namespaceFlag = flags & 16 /* Namespace */; node.flags |= flags; node.name = parseIdentifier(); - node.body = parseOptional(23) - ? parseModuleOrNamespaceDeclaration(createNode(0), 4 | namespaceFlag) + node.body = parseOptional(23 /* DotToken */) + ? parseModuleOrNamespaceDeclaration(createNode(0 /* Unknown */), 4 /* NestedNamespace */ | namespaceFlag) : parseModuleBlock(); return finishNode(node); } function parseAmbientExternalModuleDeclaration(node) { - node.kind = 239; - if (token() === 144) { + node.kind = 239 /* ModuleDeclaration */; + if (token() === 144 /* GlobalKeyword */) { + // parse 'global' as name of global scope augmentation node.name = parseIdentifier(); - node.flags |= 512; + node.flags |= 512 /* GlobalAugmentation */; } else { node.name = parseLiteralNode(); node.name.text = internIdentifier(node.name.text); } - if (token() === 17) { + if (token() === 17 /* OpenBraceToken */) { node.body = parseModuleBlock(); } else { @@ -17536,128 +20310,161 @@ var ts; } function parseModuleDeclaration(node) { var flags = 0; - if (token() === 144) { + if (token() === 144 /* GlobalKeyword */) { + // global augmentation return parseAmbientExternalModuleDeclaration(node); } - else if (parseOptional(130)) { - flags |= 16; + else if (parseOptional(130 /* NamespaceKeyword */)) { + flags |= 16 /* Namespace */; } else { - parseExpected(129); - if (token() === 9) { + parseExpected(129 /* ModuleKeyword */); + if (token() === 9 /* StringLiteral */) { return parseAmbientExternalModuleDeclaration(node); } } return parseModuleOrNamespaceDeclaration(node, flags); } function isExternalModuleReference() { - return token() === 133 && + return token() === 133 /* RequireKeyword */ && lookAhead(nextTokenIsOpenParen); } function nextTokenIsOpenParen() { - return nextToken() === 19; + return nextToken() === 19 /* OpenParenToken */; } function nextTokenIsSlash() { - return nextToken() === 41; + return nextToken() === 41 /* SlashToken */; } function parseNamespaceExportDeclaration(node) { - node.kind = 242; - parseExpected(118); - parseExpected(130); + node.kind = 242 /* NamespaceExportDeclaration */; + parseExpected(118 /* AsKeyword */); + parseExpected(130 /* NamespaceKeyword */); node.name = parseIdentifier(); parseSemicolon(); return finishNode(node); } function parseImportDeclarationOrImportEqualsDeclaration(node) { - parseExpected(91); + parseExpected(91 /* ImportKeyword */); var afterImportPos = scanner.getStartPos(); var identifier; if (isIdentifier()) { identifier = parseIdentifier(); - if (token() !== 26 && token() !== 143) { + if (token() !== 26 /* CommaToken */ && token() !== 143 /* FromKeyword */) { return parseImportEqualsDeclaration(node, identifier); } } - node.kind = 244; - if (identifier || - token() === 39 || - token() === 17) { + // Import statement + node.kind = 244 /* ImportDeclaration */; + // ImportDeclaration: + // import ImportClause from ModuleSpecifier ; + // import ModuleSpecifier; + if (identifier || // import id + token() === 39 /* AsteriskToken */ || // import * + token() === 17 /* OpenBraceToken */) { // import { node.importClause = parseImportClause(identifier, afterImportPos); - parseExpected(143); + parseExpected(143 /* FromKeyword */); } node.moduleSpecifier = parseModuleSpecifier(); parseSemicolon(); return finishNode(node); } function parseImportEqualsDeclaration(node, identifier) { - node.kind = 243; + node.kind = 243 /* ImportEqualsDeclaration */; node.name = identifier; - parseExpected(58); + parseExpected(58 /* EqualsToken */); node.moduleReference = parseModuleReference(); parseSemicolon(); return finishNode(node); } function parseImportClause(identifier, fullStart) { - var importClause = createNode(245, fullStart); + // ImportClause: + // ImportedDefaultBinding + // NameSpaceImport + // NamedImports + // ImportedDefaultBinding, NameSpaceImport + // ImportedDefaultBinding, NamedImports + var importClause = createNode(245 /* ImportClause */, fullStart); if (identifier) { + // ImportedDefaultBinding: + // ImportedBinding importClause.name = identifier; } + // If there was no default import or if there is comma token after default import + // parse namespace or named imports if (!importClause.name || - parseOptional(26)) { - importClause.namedBindings = token() === 39 ? parseNamespaceImport() : parseNamedImportsOrExports(247); + parseOptional(26 /* CommaToken */)) { + importClause.namedBindings = token() === 39 /* AsteriskToken */ ? parseNamespaceImport() : parseNamedImportsOrExports(247 /* NamedImports */); } return finishNode(importClause); } function parseModuleReference() { return isExternalModuleReference() ? parseExternalModuleReference() - : parseEntityName(false); + : parseEntityName(/*allowReservedWords*/ false); } function parseExternalModuleReference() { - var node = createNode(254); - parseExpected(133); - parseExpected(19); + var node = createNode(254 /* ExternalModuleReference */); + parseExpected(133 /* RequireKeyword */); + parseExpected(19 /* OpenParenToken */); node.expression = parseModuleSpecifier(); - parseExpected(20); + parseExpected(20 /* CloseParenToken */); return finishNode(node); } function parseModuleSpecifier() { - if (token() === 9) { + if (token() === 9 /* StringLiteral */) { var result = parseLiteralNode(); result.text = internIdentifier(result.text); return result; } else { + // We allow arbitrary expressions here, even though the grammar only allows string + // literals. We check to ensure that it is only a string literal later in the grammar + // check pass. return parseExpression(); } } function parseNamespaceImport() { - var namespaceImport = createNode(246); - parseExpected(39); - parseExpected(118); + // NameSpaceImport: + // * as ImportedBinding + var namespaceImport = createNode(246 /* NamespaceImport */); + parseExpected(39 /* AsteriskToken */); + parseExpected(118 /* AsKeyword */); namespaceImport.name = parseIdentifier(); return finishNode(namespaceImport); } function parseNamedImportsOrExports(kind) { var node = createNode(kind); - node.elements = parseBracketedList(22, kind === 247 ? parseImportSpecifier : parseExportSpecifier, 17, 18); + // NamedImports: + // { } + // { ImportsList } + // { ImportsList, } + // ImportsList: + // ImportSpecifier + // ImportsList, ImportSpecifier + node.elements = parseBracketedList(22 /* ImportOrExportSpecifiers */, kind === 247 /* NamedImports */ ? parseImportSpecifier : parseExportSpecifier, 17 /* OpenBraceToken */, 18 /* CloseBraceToken */); return finishNode(node); } function parseExportSpecifier() { - return parseImportOrExportSpecifier(252); + return parseImportOrExportSpecifier(252 /* ExportSpecifier */); } function parseImportSpecifier() { - return parseImportOrExportSpecifier(248); + return parseImportOrExportSpecifier(248 /* ImportSpecifier */); } function parseImportOrExportSpecifier(kind) { var node = createNode(kind); + // ImportSpecifier: + // BindingIdentifier + // IdentifierName as BindingIdentifier + // ExportSpecifier: + // IdentifierName + // IdentifierName as IdentifierName var checkIdentifierIsKeyword = ts.isKeyword(token()) && !isIdentifier(); var checkIdentifierStart = scanner.getTokenPos(); var checkIdentifierEnd = scanner.getTextPos(); var identifierName = parseIdentifierName(); - if (token() === 118) { + if (token() === 118 /* AsKeyword */) { node.propertyName = identifierName; - parseExpected(118); + parseExpected(118 /* AsKeyword */); checkIdentifierIsKeyword = ts.isKeyword(token()) && !isIdentifier(); checkIdentifierStart = scanner.getTokenPos(); checkIdentifierEnd = scanner.getTextPos(); @@ -17666,21 +20473,24 @@ var ts; else { node.name = identifierName; } - if (kind === 248 && checkIdentifierIsKeyword) { + if (kind === 248 /* ImportSpecifier */ && checkIdentifierIsKeyword) { parseErrorAt(checkIdentifierStart, checkIdentifierEnd, ts.Diagnostics.Identifier_expected); } return finishNode(node); } function parseExportDeclaration(node) { - node.kind = 250; - if (parseOptional(39)) { - parseExpected(143); + node.kind = 250 /* ExportDeclaration */; + if (parseOptional(39 /* AsteriskToken */)) { + parseExpected(143 /* FromKeyword */); node.moduleSpecifier = parseModuleSpecifier(); } else { - node.exportClause = parseNamedImportsOrExports(251); - if (token() === 143 || (token() === 9 && !scanner.hasPrecedingLineBreak())) { - parseExpected(143); + node.exportClause = parseNamedImportsOrExports(251 /* NamedExports */); + // It is not uncommon to accidentally omit the 'from' keyword. Additionally, in editing scenarios, + // the 'from' keyword can be parsed as a named export when the export clause is unterminated (i.e. `export { from "moduleName";`) + // If we don't have a 'from' keyword, see if we have a string literal such that ASI won't take effect. + if (token() === 143 /* FromKeyword */ || (token() === 9 /* StringLiteral */ && !scanner.hasPrecedingLineBreak())) { + parseExpected(143 /* FromKeyword */); node.moduleSpecifier = parseModuleSpecifier(); } } @@ -17688,33 +20498,35 @@ var ts; return finishNode(node); } function parseExportAssignment(node) { - node.kind = 249; - if (parseOptional(58)) { + node.kind = 249 /* ExportAssignment */; + if (parseOptional(58 /* EqualsToken */)) { node.isExportEquals = true; } else { - parseExpected(79); + parseExpected(79 /* DefaultKeyword */); } node.expression = parseAssignmentExpressionOrHigher(); parseSemicolon(); return finishNode(node); } function setExternalModuleIndicator(sourceFile) { + // Try to use the first top-level import/export when available, then + // fall back to looking for an 'import.meta' somewhere in the tree if necessary. sourceFile.externalModuleIndicator = ts.forEach(sourceFile.statements, isAnExternalModuleIndicatorNode) || getImportMetaIfNecessary(sourceFile); } function isAnExternalModuleIndicatorNode(node) { - return ts.hasModifier(node, 1) - || node.kind === 243 && node.moduleReference.kind === 254 - || node.kind === 244 - || node.kind === 249 - || node.kind === 250 + return ts.hasModifier(node, 1 /* Export */) + || node.kind === 243 /* ImportEqualsDeclaration */ && node.moduleReference.kind === 254 /* ExternalModuleReference */ + || node.kind === 244 /* ImportDeclaration */ + || node.kind === 249 /* ExportAssignment */ + || node.kind === 250 /* ExportDeclaration */ ? node : undefined; } function getImportMetaIfNecessary(sourceFile) { - return sourceFile.flags & 1048576 ? + return sourceFile.flags & 1048576 /* PossiblyContainsImportMeta */ ? walkTreeForExternalModuleIndicators(sourceFile) : undefined; } @@ -17722,7 +20534,7 @@ var ts; return isImportMeta(node) ? node : forEachChild(node, walkTreeForExternalModuleIndicators); } function isImportMeta(node) { - return ts.isMetaProperty(node) && node.keywordToken === 91 && node.name.escapedText === "meta"; + return ts.isMetaProperty(node) && node.keywordToken === 91 /* ImportKeyword */ && node.name.escapedText === "meta"; } var ParsingContext; (function (ParsingContext) { @@ -17749,7 +20561,7 @@ var ts; ParsingContext[ParsingContext["TupleElementTypes"] = 20] = "TupleElementTypes"; ParsingContext[ParsingContext["HeritageClauses"] = 21] = "HeritageClauses"; ParsingContext[ParsingContext["ImportOrExportSpecifiers"] = 22] = "ImportOrExportSpecifiers"; - ParsingContext[ParsingContext["Count"] = 23] = "Count"; + ParsingContext[ParsingContext["Count"] = 23] = "Count"; // Number of parsing contexts })(ParsingContext || (ParsingContext = {})); var Tristate; (function (Tristate) { @@ -17760,8 +20572,8 @@ var ts; var JSDocParser; (function (JSDocParser) { function parseJSDocTypeExpressionForTests(content, start, length) { - initializeState(content, 6, undefined, 1); - sourceFile = createSourceFile("file.js", 6, 1, false); + initializeState(content, 6 /* Latest */, /*_syntaxCursor:*/ undefined, 1 /* JS */); + sourceFile = createSourceFile("file.js", 6 /* Latest */, 1 /* JS */, /*isDeclarationFile*/ false); scanner.setText(content, start, length); currentToken = scanner.scan(); var jsDocTypeExpression = parseJSDocTypeExpression(); @@ -17770,20 +20582,21 @@ var ts; return jsDocTypeExpression ? { jsDocTypeExpression: jsDocTypeExpression, diagnostics: diagnostics } : undefined; } JSDocParser.parseJSDocTypeExpressionForTests = parseJSDocTypeExpressionForTests; + // Parses out a JSDoc type expression. function parseJSDocTypeExpression(mayOmitBraces) { - var result = createNode(278, scanner.getTokenPos()); - var hasBrace = (mayOmitBraces ? parseOptional : parseExpected)(17); - result.type = doInsideOfContext(2097152, parseJSDocType); + var result = createNode(278 /* JSDocTypeExpression */, scanner.getTokenPos()); + var hasBrace = (mayOmitBraces ? parseOptional : parseExpected)(17 /* OpenBraceToken */); + result.type = doInsideOfContext(2097152 /* JSDoc */, parseJSDocType); if (!mayOmitBraces || hasBrace) { - parseExpected(18); + parseExpected(18 /* CloseBraceToken */); } fixupParentReferences(result); return finishNode(result); } JSDocParser.parseJSDocTypeExpression = parseJSDocTypeExpression; function parseIsolatedJSDocComment(content, start, length) { - initializeState(content, 6, undefined, 1); - sourceFile = { languageVariant: 0, text: content }; + initializeState(content, 6 /* Latest */, /*_syntaxCursor:*/ undefined, 1 /* JS */); + sourceFile = { languageVariant: 0 /* Standard */, text: content }; // tslint:disable-line no-object-literal-type-assertion var jsDoc = parseJSDocCommentWorker(start, length); var diagnostics = parseDiagnostics; clearState(); @@ -17799,7 +20612,7 @@ var ts; if (comment) { comment.parent = parent; } - if (contextFlags & 65536) { + if (contextFlags & 65536 /* JavaScriptFile */) { if (!sourceFile.jsDocDiagnostics) { sourceFile.jsDocDiagnostics = []; } @@ -17836,12 +20649,17 @@ var ts; var tagsEnd; var comments = []; var result; + // Check for /** (JSDoc opening part) if (!isJSDocLikeText(content, start)) { return result; } + // + 3 for leading /**, - 5 in total for /** */ scanner.scanRange(start + 3, length - 5, function () { - var state = 1; + // Initially we can parse out a tag. We also have seen a starting asterisk. + // This is so that /** * @type */ doesn't parse. + var state = 1 /* SawAsterisk */; var margin; + // + 4 for leading '/** ' var indent = start - Math.max(content.lastIndexOf("\n", start), 0) + 4; function pushComment(text) { if (!margin) { @@ -17851,19 +20669,22 @@ var ts; indent += text.length; } nextJSDocToken(); - while (parseOptionalJsdoc(5)) + while (parseOptionalJsdoc(5 /* WhitespaceTrivia */)) ; - if (parseOptionalJsdoc(4)) { - state = 0; + if (parseOptionalJsdoc(4 /* NewLineTrivia */)) { + state = 0 /* BeginningOfLine */; indent = 0; } loop: while (true) { switch (token()) { - case 57: - if (state === 0 || state === 1) { + case 57 /* AtToken */: + if (state === 0 /* BeginningOfLine */ || state === 1 /* SawAsterisk */) { removeTrailingNewlines(comments); addTag(parseTag(indent)); - state = 0; + // NOTE: According to usejsdoc.org, a tag goes to end of line, except the last tag. + // Real-world comments may break this rule, so "BeginningOfLine" will not be a real line beginning + // for malformed examples like `/** @param {string} x @returns {number} the length */` + state = 0 /* BeginningOfLine */; margin = undefined; indent++; } @@ -17871,29 +20692,35 @@ var ts; pushComment(scanner.getTokenText()); } break; - case 4: + case 4 /* NewLineTrivia */: comments.push(scanner.getTokenText()); - state = 0; + state = 0 /* BeginningOfLine */; indent = 0; break; - case 39: + case 39 /* AsteriskToken */: var asterisk = scanner.getTokenText(); - if (state === 1 || state === 2) { - state = 2; + if (state === 1 /* SawAsterisk */ || state === 2 /* SavingComments */) { + // If we've already seen an asterisk, then we can no longer parse a tag on this line + state = 2 /* SavingComments */; pushComment(asterisk); } else { - state = 1; + // Ignore the first asterisk on a line + state = 1 /* SawAsterisk */; indent += asterisk.length; } break; - case 71: + case 71 /* Identifier */: + // Anything else is doc comment text. We just save it. Because it + // wasn't a tag, we can no longer parse a tag on this line until we hit the next + // line break. pushComment(scanner.getTokenText()); - state = 2; + state = 2 /* SavingComments */; break; - case 5: + case 5 /* WhitespaceTrivia */: + // only collect whitespace if we're already saving comments or have just crossed the comment indent margin var whitespace = scanner.getTokenText(); - if (state === 2) { + if (state === 2 /* SavingComments */) { comments.push(whitespace); } else if (margin !== undefined && indent + whitespace.length > margin) { @@ -17901,10 +20728,11 @@ var ts; } indent += whitespace.length; break; - case 1: + case 1 /* EndOfFileToken */: break loop; default: - state = 2; + // anything other than whitespace or asterisk at the beginning of the line starts the comment text + state = 2 /* SavingComments */; pushComment(scanner.getTokenText()); break; } @@ -17926,35 +20754,36 @@ var ts; } } function createJSDocComment() { - var result = createNode(286, start); + var result = createNode(286 /* JSDocComment */, start); result.tags = tags && createNodeArray(tags, tagsPos, tagsEnd); result.comment = comments.length ? comments.join("") : undefined; return finishNode(result, end); } function isNextNonwhitespaceTokenEndOfFile() { + // We must use infinite lookahead, as there could be any number of newlines :( while (true) { nextJSDocToken(); - if (token() === 1) { + if (token() === 1 /* EndOfFileToken */) { return true; } - if (!(token() === 5 || token() === 4)) { + if (!(token() === 5 /* WhitespaceTrivia */ || token() === 4 /* NewLineTrivia */)) { return false; } } } function skipWhitespace() { - if (token() === 5 || token() === 4) { + if (token() === 5 /* WhitespaceTrivia */ || token() === 4 /* NewLineTrivia */) { if (lookAhead(isNextNonwhitespaceTokenEndOfFile)) { - return; + return; // Don't skip whitespace prior to EoF (or end of comment) - that shouldn't be included in any node's range } } - while (token() === 5 || token() === 4) { + while (token() === 5 /* WhitespaceTrivia */ || token() === 4 /* NewLineTrivia */) { nextJSDocToken(); } } function parseTag(indent) { - ts.Debug.assert(token() === 57); - var atToken = createNode(57, scanner.getTokenPos()); + ts.Debug.assert(token() === 57 /* AtToken */); + var atToken = createNode(57 /* AtToken */, scanner.getTokenPos()); atToken.end = scanner.getTextPos(); nextJSDocToken(); var tagName = parseJSDocIdentifierName(); @@ -17975,7 +20804,7 @@ var ts; case "arg": case "argument": case "param": - return parseParameterOrPropertyTag(atToken, tagName, 2, indent); + return parseParameterOrPropertyTag(atToken, tagName, 2 /* Parameter */, indent); case "return": case "returns": tag = parseReturnTag(atToken, tagName); @@ -17997,13 +20826,14 @@ var ts; break; } if (!tag.comment) { + // some tags, like typedef and callback, have already parsed their comments earlier tag.comment = parseTagComments(indent + tag.end - tag.pos); } return tag; } function parseTagComments(indent) { var comments = []; - var state = 0; + var state = 0 /* BeginningOfLine */; var margin; function pushComment(text) { if (!margin) { @@ -18015,37 +20845,43 @@ var ts; var tok = token(); loop: while (true) { switch (tok) { - case 4: - if (state >= 1) { - state = 0; + case 4 /* NewLineTrivia */: + if (state >= 1 /* SawAsterisk */) { + state = 0 /* BeginningOfLine */; comments.push(scanner.getTokenText()); } indent = 0; break; - case 57: + case 57 /* AtToken */: scanner.setTextPos(scanner.getTextPos() - 1); - case 1: + // falls through + case 1 /* EndOfFileToken */: + // Done break loop; - case 5: - if (state === 2) { + case 5 /* WhitespaceTrivia */: + if (state === 2 /* SavingComments */) { pushComment(scanner.getTokenText()); } else { var whitespace = scanner.getTokenText(); + // if the whitespace crosses the margin, take only the whitespace that passes the margin if (margin !== undefined && indent + whitespace.length > margin) { comments.push(whitespace.slice(margin - indent - 1)); } indent += whitespace.length; } break; - case 39: - if (state === 0) { - state = 1; + case 39 /* AsteriskToken */: + if (state === 0 /* BeginningOfLine */) { + // leading asterisks start recording on the *next* (non-whitespace) token + state = 1 /* SawAsterisk */; indent += 1; break; } + // record the * as a comment + // falls through default: - state = 2; + state = 2 /* SavingComments */; // leading identifiers start recording as well pushComment(scanner.getTokenText()); break; } @@ -18056,7 +20892,7 @@ var ts; return comments.length === 0 ? undefined : comments.join(""); } function parseUnknownTag(atToken, tagName) { - var result = createNode(289, atToken.pos); + var result = createNode(289 /* JSDocTag */, atToken.pos); result.atToken = atToken; result.tagName = tagName; return finishNode(result); @@ -18076,28 +20912,31 @@ var ts; } function tryParseTypeExpression() { skipWhitespace(); - return token() === 17 ? parseJSDocTypeExpression() : undefined; + return token() === 17 /* OpenBraceToken */ ? parseJSDocTypeExpression() : undefined; } function parseBracketNameInPropertyAndParamTag() { - if (token() === 13) { - return { name: createIdentifier(true), isBracketed: false }; + if (token() === 13 /* NoSubstitutionTemplateLiteral */) { + // a markdown-quoted name: `arg` is not legal jsdoc, but occurs in the wild + return { name: createIdentifier(/*isIdentifier*/ true), isBracketed: false }; } - var isBracketed = parseOptional(21); + // Looking for something like '[foo]', 'foo', '[foo.bar]' or 'foo.bar' + var isBracketed = parseOptional(21 /* OpenBracketToken */); var name = parseJSDocEntityName(); if (isBracketed) { skipWhitespace(); - if (parseOptionalToken(58)) { + // May have an optional default, e.g. '[foo = 42]' + if (parseOptionalToken(58 /* EqualsToken */)) { parseExpression(); } - parseExpected(22); + parseExpected(22 /* CloseBracketToken */); } return { name: name, isBracketed: isBracketed }; } function isObjectOrObjectArrayTypeReference(node) { switch (node.kind) { - case 135: + case 135 /* ObjectKeyword */: return true; - case 167: + case 167 /* ArrayType */: return isObjectOrObjectArrayTypeReference(node.elementType); default: return ts.isTypeReferenceNode(node) && ts.isIdentifier(node.typeName) && node.typeName.escapedText === "Object"; @@ -18112,13 +20951,13 @@ var ts; if (isNameFirst) { typeExpression = tryParseTypeExpression(); } - var result = target === 1 ? - createNode(299, atToken.pos) : - createNode(293, atToken.pos); + var result = target === 1 /* Property */ ? + createNode(299 /* JSDocPropertyTag */, atToken.pos) : + createNode(293 /* JSDocParameterTag */, atToken.pos); var comment; if (indent !== undefined) comment = parseTagComments(indent + scanner.getStartPos() - atToken.pos); - var nestedTypeLiteral = target !== 4 && parseNestedTypeLiteral(typeExpression, name, target); + var nestedTypeLiteral = target !== 4 /* CallbackParameter */ && parseNestedTypeLiteral(typeExpression, name, target); if (nestedTypeLiteral) { typeExpression = nestedTypeLiteral; isNameFirst = true; @@ -18134,20 +20973,20 @@ var ts; } function parseNestedTypeLiteral(typeExpression, name, target) { if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.type)) { - var typeLiteralExpression = createNode(278, scanner.getTokenPos()); + var typeLiteralExpression = createNode(278 /* JSDocTypeExpression */, scanner.getTokenPos()); var child = void 0; var jsdocTypeLiteral = void 0; var start_2 = scanner.getStartPos(); var children = void 0; while (child = tryParse(function () { return parseChildParameterOrPropertyTag(target, name); })) { - if (child.kind === 293 || child.kind === 299) { + if (child.kind === 293 /* JSDocParameterTag */ || child.kind === 299 /* JSDocPropertyTag */) { children = ts.append(children, child); } } if (children) { - jsdocTypeLiteral = createNode(287, start_2); + jsdocTypeLiteral = createNode(287 /* JSDocTypeLiteral */, start_2); jsdocTypeLiteral.jsDocPropertyTags = children; - if (typeExpression.type.kind === 167) { + if (typeExpression.type.kind === 167 /* ArrayType */) { jsdocTypeLiteral.isArrayType = true; } typeLiteralExpression.type = finishNode(jsdocTypeLiteral); @@ -18156,47 +20995,47 @@ var ts; } } function parseReturnTag(atToken, tagName) { - if (ts.forEach(tags, function (t) { return t.kind === 294; })) { + if (ts.forEach(tags, function (t) { return t.kind === 294 /* JSDocReturnTag */; })) { parseErrorAt(tagName.pos, scanner.getTokenPos(), ts.Diagnostics._0_tag_already_specified, tagName.escapedText); } - var result = createNode(294, atToken.pos); + var result = createNode(294 /* JSDocReturnTag */, atToken.pos); result.atToken = atToken; result.tagName = tagName; result.typeExpression = tryParseTypeExpression(); return finishNode(result); } function parseTypeTag(atToken, tagName) { - if (ts.forEach(tags, function (t) { return t.kind === 296; })) { + if (ts.forEach(tags, function (t) { return t.kind === 296 /* JSDocTypeTag */; })) { parseErrorAt(tagName.pos, scanner.getTokenPos(), ts.Diagnostics._0_tag_already_specified, tagName.escapedText); } - var result = createNode(296, atToken.pos); + var result = createNode(296 /* JSDocTypeTag */, atToken.pos); result.atToken = atToken; result.tagName = tagName; - result.typeExpression = parseJSDocTypeExpression(true); + result.typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); return finishNode(result); } function parseAugmentsTag(atToken, tagName) { - var result = createNode(290, atToken.pos); + var result = createNode(290 /* JSDocAugmentsTag */, atToken.pos); result.atToken = atToken; result.tagName = tagName; result.class = parseExpressionWithTypeArgumentsForAugments(); return finishNode(result); } function parseExpressionWithTypeArgumentsForAugments() { - var usedBrace = parseOptional(17); - var node = createNode(207); + var usedBrace = parseOptional(17 /* OpenBraceToken */); + var node = createNode(207 /* ExpressionWithTypeArguments */); node.expression = parsePropertyAccessEntityNameExpression(); node.typeArguments = tryParseTypeArguments(); var res = finishNode(node); if (usedBrace) { - parseExpected(18); + parseExpected(18 /* CloseBraceToken */); } return res; } function parsePropertyAccessEntityNameExpression() { var node = parseJSDocIdentifierName(); - while (parseOptional(23)) { - var prop = createNode(185, node.pos); + while (parseOptional(23 /* DotToken */)) { + var prop = createNode(185 /* PropertyAccessExpression */, node.pos); prop.expression = node; prop.name = parseJSDocIdentifierName(); node = finishNode(prop); @@ -18204,23 +21043,23 @@ var ts; return node; } function parseClassTag(atToken, tagName) { - var tag = createNode(291, atToken.pos); + var tag = createNode(291 /* JSDocClassTag */, atToken.pos); tag.atToken = atToken; tag.tagName = tagName; return finishNode(tag); } function parseThisTag(atToken, tagName) { - var tag = createNode(295, atToken.pos); + var tag = createNode(295 /* JSDocThisTag */, atToken.pos); tag.atToken = atToken; tag.tagName = tagName; - tag.typeExpression = parseJSDocTypeExpression(true); + tag.typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); skipWhitespace(); return finishNode(tag); } function parseTypedefTag(atToken, tagName, indent) { var typeExpression = tryParseTypeExpression(); skipWhitespace(); - var typedefTag = createNode(298, atToken.pos); + var typedefTag = createNode(298 /* JSDocTypedefTag */, atToken.pos); typedefTag.atToken = atToken; typedefTag.tagName = tagName; typedefTag.fullName = parseJSDocTypeNameWithNamespace(); @@ -18236,9 +21075,9 @@ var ts; var start_3 = scanner.getStartPos(); while (child = tryParse(function () { return parseChildPropertyTag(); })) { if (!jsdocTypeLiteral) { - jsdocTypeLiteral = createNode(287, start_3); + jsdocTypeLiteral = createNode(287 /* JSDocTypeLiteral */, start_3); } - if (child.kind === 296) { + if (child.kind === 296 /* JSDocTypeTag */) { if (childTypeTag) { break; } @@ -18251,7 +21090,7 @@ var ts; } } if (jsdocTypeLiteral) { - if (typeExpression && typeExpression.type.kind === 167) { + if (typeExpression && typeExpression.type.kind === 167 /* ArrayType */) { jsdocTypeLiteral.isArrayType = true; } typedefTag.typeExpression = childTypeTag && childTypeTag.typeExpression && !isObjectOrObjectArrayTypeReference(childTypeTag.typeExpression.type) ? @@ -18260,6 +21099,7 @@ var ts; end = typedefTag.typeExpression.end; } } + // Only include the characters between the name end and the next token if a comment was actually parsed out - otherwise it's just whitespace return finishNode(typedefTag, end || typedefTag.comment !== undefined ? scanner.getStartPos() : (typedefTag.fullName || typedefTag.typeExpression || typedefTag.tagName).end); } function parseJSDocTypeNameWithNamespace(nested) { @@ -18268,13 +21108,13 @@ var ts; return undefined; } var typeNameOrNamespaceName = parseJSDocIdentifierName(); - if (parseOptional(23)) { - var jsDocNamespaceNode = createNode(239, pos); + if (parseOptional(23 /* DotToken */)) { + var jsDocNamespaceNode = createNode(239 /* ModuleDeclaration */, pos); if (nested) { - jsDocNamespaceNode.flags |= 4; + jsDocNamespaceNode.flags |= 4 /* NestedNamespace */; } jsDocNamespaceNode.name = typeNameOrNamespaceName; - jsDocNamespaceNode.body = parseJSDocTypeNameWithNamespace(true); + jsDocNamespaceNode.body = parseJSDocTypeNameWithNamespace(/*nested*/ true); return finishNode(jsDocNamespaceNode); } if (nested) { @@ -18283,7 +21123,7 @@ var ts; return typeNameOrNamespaceName; } function parseCallbackTag(atToken, tagName, indent) { - var callbackTag = createNode(292, atToken.pos); + var callbackTag = createNode(292 /* JSDocCallbackTag */, atToken.pos); callbackTag.atToken = atToken; callbackTag.tagName = tagName; callbackTag.fullName = parseJSDocTypeNameWithNamespace(); @@ -18292,15 +21132,15 @@ var ts; callbackTag.comment = parseTagComments(indent); var child; var start = scanner.getStartPos(); - var jsdocSignature = createNode(288, start); + var jsdocSignature = createNode(288 /* JSDocSignature */, start); jsdocSignature.parameters = []; - while (child = tryParse(function () { return parseChildParameterOrPropertyTag(4); })) { + while (child = tryParse(function () { return parseChildParameterOrPropertyTag(4 /* CallbackParameter */); })) { jsdocSignature.parameters = ts.append(jsdocSignature.parameters, child); } var returnTag = tryParse(function () { - if (parseOptionalJsdoc(57)) { + if (parseOptionalJsdoc(57 /* AtToken */)) { var tag = parseTag(indent); - if (tag && tag.kind === 294) { + if (tag && tag.kind === 294 /* JSDocReturnTag */) { return tag; } } @@ -18335,46 +21175,46 @@ var ts; return a.escapedText === b.escapedText; } function parseChildPropertyTag() { - return parseChildParameterOrPropertyTag(1); + return parseChildParameterOrPropertyTag(1 /* Property */); } function parseChildParameterOrPropertyTag(target, name) { var canParseTag = true; var seenAsterisk = false; while (true) { switch (nextJSDocToken()) { - case 57: + case 57 /* AtToken */: if (canParseTag) { var child = tryParseChildTag(target); - if (child && child.kind === 293 && - target !== 4 && - (ts.isIdentifier(child.name) || !escapedTextsEqual(name, child.name.left))) { + if (child && child.kind === 293 /* JSDocParameterTag */ && + target !== 4 /* CallbackParameter */ && + (ts.isIdentifier(child.name) || !escapedTextsEqual(name, child.name.left))) { // TODO: GH#18217 return false; } return child; } seenAsterisk = false; break; - case 4: + case 4 /* NewLineTrivia */: canParseTag = true; seenAsterisk = false; break; - case 39: + case 39 /* AsteriskToken */: if (seenAsterisk) { canParseTag = false; } seenAsterisk = true; break; - case 71: + case 71 /* Identifier */: canParseTag = false; break; - case 1: + case 1 /* EndOfFileToken */: return false; } } } function tryParseChildTag(target) { - ts.Debug.assert(token() === 57); - var atToken = createNode(57); + ts.Debug.assert(token() === 57 /* AtToken */); + var atToken = createNode(57 /* AtToken */); atToken.end = scanner.getTextPos(); nextJSDocToken(); var tagName = parseJSDocIdentifierName(); @@ -18382,15 +21222,15 @@ var ts; var t; switch (tagName.escapedText) { case "type": - return target === 1 && parseTypeTag(atToken, tagName); + return target === 1 /* Property */ && parseTypeTag(atToken, tagName); case "prop": case "property": - t = 1; + t = 1 /* Property */; break; case "arg": case "argument": case "param": - t = 2 | 4; + t = 2 /* Parameter */ | 4 /* CallbackParameter */; break; default: return false; @@ -18398,29 +21238,30 @@ var ts; if (!(target & t)) { return false; } - var tag = parseParameterOrPropertyTag(atToken, tagName, target, undefined); + var tag = parseParameterOrPropertyTag(atToken, tagName, target, /*indent*/ undefined); tag.comment = parseTagComments(tag.end - tag.pos); return tag; } function parseTemplateTag(atToken, tagName) { + // the template tag looks like '@template {Constraint} T,U,V' var constraint; - if (token() === 17) { + if (token() === 17 /* OpenBraceToken */) { constraint = parseJSDocTypeExpression(); } var typeParameters = []; var typeParametersPos = getNodePos(); do { skipWhitespace(); - var typeParameter = createNode(148); + var typeParameter = createNode(148 /* TypeParameter */); typeParameter.name = parseJSDocIdentifierName(ts.Diagnostics.Unexpected_token_A_type_parameter_name_was_expected_without_curly_braces); skipWhitespace(); finishNode(typeParameter); typeParameters.push(typeParameter); - } while (parseOptionalJsdoc(26)); + } while (parseOptionalJsdoc(26 /* CommaToken */)); if (constraint) { ts.first(typeParameters).constraint = constraint.type; } - var result = createNode(297, atToken.pos); + var result = createNode(297 /* JSDocTemplateTag */, atToken.pos); result.atToken = atToken; result.tagName = tagName; result.typeParameters = createNodeArray(typeParameters, typeParametersPos); @@ -18439,13 +21280,16 @@ var ts; } function parseJSDocEntityName() { var entity = parseJSDocIdentifierName(); - if (parseOptional(21)) { - parseExpected(22); + if (parseOptional(21 /* OpenBracketToken */)) { + parseExpected(22 /* CloseBracketToken */); + // Note that y[] is accepted as an entity name, but the postfix brackets are not saved for checking. + // Technically usejsdoc.org requires them for specifying a property of a type equivalent to Array<{ x: ...}> + // but it's not worth it to enforce that restriction. } - while (parseOptional(23)) { + while (parseOptional(23 /* DotToken */)) { var name = parseJSDocIdentifierName(); - if (parseOptional(21)) { - parseExpected(22); + if (parseOptional(21 /* OpenBracketToken */)) { + parseExpected(22 /* CloseBracketToken */); } entity = createQualifiedName(entity, name); } @@ -18453,11 +21297,11 @@ var ts; } function parseJSDocIdentifierName(message) { if (!ts.tokenIsIdentifierOrKeyword(token())) { - return createMissingNode(71, !message, message || ts.Diagnostics.Identifier_expected); + return createMissingNode(71 /* Identifier */, /*reportAtCurrentPosition*/ !message, message || ts.Diagnostics.Identifier_expected); } var pos = scanner.getTokenPos(); var end = scanner.getTextPos(); - var result = createNode(71, pos); + var result = createNode(71 /* Identifier */, pos); result.escapedText = ts.escapeLeadingUnderscores(scanner.getTokenText()); finishNode(result, end); nextJSDocToken(); @@ -18470,27 +21314,72 @@ var ts; var IncrementalParser; (function (IncrementalParser) { function updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks) { - aggressiveChecks = aggressiveChecks || ts.Debug.shouldAssert(2); + aggressiveChecks = aggressiveChecks || ts.Debug.shouldAssert(2 /* Aggressive */); checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks); if (ts.textChangeRangeIsUnchanged(textChangeRange)) { + // if the text didn't change, then we can just return our current source file as-is. return sourceFile; } if (sourceFile.statements.length === 0) { - return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, undefined, true, sourceFile.scriptKind); + // If we don't have any statements in the current source file, then there's no real + // way to incrementally parse. So just do a full parse instead. + return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true, sourceFile.scriptKind); } + // Make sure we're not trying to incrementally update a source file more than once. Once + // we do an update the original source file is considered unusable from that point onwards. + // + // This is because we do incremental parsing in-place. i.e. we take nodes from the old + // tree and give them new positions and parents. From that point on, trusting the old + // tree at all is not possible as far too much of it may violate invariants. var incrementalSourceFile = sourceFile; ts.Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed); incrementalSourceFile.hasBeenIncrementallyParsed = true; var oldText = sourceFile.text; var syntaxCursor = createSyntaxCursor(sourceFile); + // Make the actual change larger so that we know to reparse anything whose lookahead + // might have intersected the change. var changeRange = extendToAffectedRange(sourceFile, textChangeRange); checkChangeRange(sourceFile, newText, changeRange, aggressiveChecks); + // Ensure that extending the affected range only moved the start of the change range + // earlier in the file. ts.Debug.assert(changeRange.span.start <= textChangeRange.span.start); ts.Debug.assert(ts.textSpanEnd(changeRange.span) === ts.textSpanEnd(textChangeRange.span)); ts.Debug.assert(ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)) === ts.textSpanEnd(ts.textChangeRangeNewSpan(textChangeRange))); + // The is the amount the nodes after the edit range need to be adjusted. It can be + // positive (if the edit added characters), negative (if the edit deleted characters) + // or zero (if this was a pure overwrite with nothing added/removed). var delta = ts.textChangeRangeNewSpan(changeRange).length - changeRange.span.length; + // If we added or removed characters during the edit, then we need to go and adjust all + // the nodes after the edit. Those nodes may move forward (if we inserted chars) or they + // may move backward (if we deleted chars). + // + // Doing this helps us out in two ways. First, it means that any nodes/tokens we want + // to reuse are already at the appropriate position in the new text. That way when we + // reuse them, we don't have to figure out if they need to be adjusted. Second, it makes + // it very easy to determine if we can reuse a node. If the node's position is at where + // we are in the text, then we can reuse it. Otherwise we can't. If the node's position + // is ahead of us, then we'll need to rescan tokens. If the node's position is behind + // us, then we'll need to skip it or crumble it as appropriate + // + // We will also adjust the positions of nodes that intersect the change range as well. + // By doing this, we ensure that all the positions in the old tree are consistent, not + // just the positions of nodes entirely before/after the change range. By being + // consistent, we can then easily map from positions to nodes in the old tree easily. + // + // Also, mark any syntax elements that intersect the changed span. We know, up front, + // that we cannot reuse these elements. updateTokenPositionsAndMarkElements(incrementalSourceFile, changeRange.span.start, ts.textSpanEnd(changeRange.span), ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks); - var result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, true, sourceFile.scriptKind); + // Now that we've set up our internal incremental state just proceed and parse the + // source file in the normal fashion. When possible the parser will retrieve and + // reuse nodes from the old tree. + // + // Note: passing in 'true' for setNodeParents is very important. When incrementally + // parsing, we will be reusing nodes from the old tree, and placing it into new + // parents. If we don't set the parents now, we'll end up with an observably + // inconsistent tree. Setting the parents on the new tree should be very fast. We + // will immediately bail out of walking any subtrees when we can see that their parents + // are already correct. + var result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true, sourceFile.scriptKind); return result; } IncrementalParser.updateSourceFile = updateSourceFile; @@ -18507,6 +21396,8 @@ var ts; if (aggressiveChecks && shouldCheckNode(node)) { text = oldText.substring(node.pos, node.end); } + // Ditch any existing LS children we may have created. This way we can avoid + // moving them forward. if (node._children) { node._children = undefined; } @@ -18536,9 +21427,9 @@ var ts; } function shouldCheckNode(node) { switch (node.kind) { - case 9: - case 8: - case 71: + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: + case 71 /* Identifier */: return true; } return false; @@ -18547,11 +21438,63 @@ var ts; ts.Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range"); ts.Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range"); ts.Debug.assert(element.pos <= element.end); + // We have an element that intersects the change range in some way. It may have its + // start, or its end (or both) in the changed range. We want to adjust any part + // that intersects such that the final tree is in a consistent state. i.e. all + // children have spans within the span of their parent, and all siblings are ordered + // properly. + // We may need to update both the 'pos' and the 'end' of the element. + // If the 'pos' is before the start of the change, then we don't need to touch it. + // If it isn't, then the 'pos' must be inside the change. How we update it will + // depend if delta is positive or negative. If delta is positive then we have + // something like: + // + // -------------------AAA----------------- + // -------------------BBBCCCCCCC----------------- + // + // In this case, we consider any node that started in the change range to still be + // starting at the same position. + // + // however, if the delta is negative, then we instead have something like this: + // + // -------------------XXXYYYYYYY----------------- + // -------------------ZZZ----------------- + // + // In this case, any element that started in the 'X' range will keep its position. + // However any element that started after that will have their pos adjusted to be + // at the end of the new range. i.e. any node that started in the 'Y' range will + // be adjusted to have their start at the end of the 'Z' range. + // + // The element will keep its position if possible. Or Move backward to the new-end + // if it's in the 'Y' range. element.pos = Math.min(element.pos, changeRangeNewEnd); + // If the 'end' is after the change range, then we always adjust it by the delta + // amount. However, if the end is in the change range, then how we adjust it + // will depend on if delta is positive or negative. If delta is positive then we + // have something like: + // + // -------------------AAA----------------- + // -------------------BBBCCCCCCC----------------- + // + // In this case, we consider any node that ended inside the change range to keep its + // end position. + // + // however, if the delta is negative, then we instead have something like this: + // + // -------------------XXXYYYYYYY----------------- + // -------------------ZZZ----------------- + // + // In this case, any element that ended in the 'X' range will keep its position. + // However any element that ended after that will have their pos adjusted to be + // at the end of the new range. i.e. any node that ended in the 'Y' range will + // be adjusted to have their end at the end of the 'Z' range. if (element.end >= changeRangeOldEnd) { + // Element ends after the change range. Always adjust the end pos. element.end += delta; } else { + // Element ends in the change range. The element will keep its position if + // possible. Or Move backward to the new-end if it's in the 'Y' range. element.end = Math.min(element.end, changeRangeNewEnd); } ts.Debug.assert(element.pos <= element.end); @@ -18583,13 +21526,19 @@ var ts; function visitNode(child) { ts.Debug.assert(child.pos <= child.end); if (child.pos > changeRangeOldEnd) { - moveElementEntirelyPastChangeRange(child, false, delta, oldText, newText, aggressiveChecks); + // Node is entirely past the change range. We need to move both its pos and + // end, forward or backward appropriately. + moveElementEntirelyPastChangeRange(child, /*isArray*/ false, delta, oldText, newText, aggressiveChecks); return; } + // Check if the element intersects the change range. If it does, then it is not + // reusable. Also, we'll need to recurse to see what constituent portions we may + // be able to use. var fullEnd = child.end; if (fullEnd >= changeStart) { child.intersectsChange = true; child._children = undefined; + // Adjust the pos or end (or both) of the intersecting element accordingly. adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); forEachChild(child, visitNode, visitArray); if (ts.hasJSDocNodes(child)) { @@ -18601,18 +21550,25 @@ var ts; checkNodePositions(child, aggressiveChecks); return; } + // Otherwise, the node is entirely before the change range. No need to do anything with it. ts.Debug.assert(fullEnd < changeStart); } function visitArray(array) { ts.Debug.assert(array.pos <= array.end); if (array.pos > changeRangeOldEnd) { - moveElementEntirelyPastChangeRange(array, true, delta, oldText, newText, aggressiveChecks); + // Array is entirely after the change range. We need to move it, and move any of + // its children. + moveElementEntirelyPastChangeRange(array, /*isArray*/ true, delta, oldText, newText, aggressiveChecks); return; } + // Check if the element intersects the change range. If it does, then it is not + // reusable. Also, we'll need to recurse to see what constituent portions we may + // be able to use. var fullEnd = array.end; if (fullEnd >= changeStart) { array.intersectsChange = true; array._children = undefined; + // Adjust the pos or end (or both) of the intersecting array accordingly. adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); for (var _i = 0, array_9 = array; _i < array_9.length; _i++) { var node = array_9[_i]; @@ -18620,12 +21576,26 @@ var ts; } return; } + // Otherwise, the array is entirely before the change range. No need to do anything with it. ts.Debug.assert(fullEnd < changeStart); } } function extendToAffectedRange(sourceFile, changeRange) { + // Consider the following code: + // void foo() { /; } + // + // If the text changes with an insertion of / just before the semicolon then we end up with: + // void foo() { //; } + // + // If we were to just use the changeRange a is, then we would not rescan the { token + // (as it does not intersect the actual original change range). Because an edit may + // change the token touching it, we actually need to look back *at least* one token so + // that the prior token sees that change. var maxLookahead = 1; var start = changeRange.span.start; + // the first iteration aligns us with the change start. subsequent iteration move us to + // the left by maxLookahead tokens. We only need to do this as long as we're not at the + // start of the tree. for (var i = 0; start > 0 && i <= maxLookahead; i++) { var nearestNode = findNearestNodeStartingBeforeOrAtPosition(sourceFile, start); ts.Debug.assert(nearestNode.pos <= start); @@ -18660,23 +21630,54 @@ var ts; } function visit(child) { if (ts.nodeIsMissing(child)) { + // Missing nodes are effectively invisible to us. We never even consider them + // When trying to find the nearest node before us. return; } + // If the child intersects this position, then this node is currently the nearest + // node that starts before the position. if (child.pos <= position) { if (child.pos >= bestResult.pos) { + // This node starts before the position, and is closer to the position than + // the previous best node we found. It is now the new best node. bestResult = child; } + // Now, the node may overlap the position, or it may end entirely before the + // position. If it overlaps with the position, then either it, or one of its + // children must be the nearest node before the position. So we can just + // recurse into this child to see if we can find something better. if (position < child.end) { + // The nearest node is either this child, or one of the children inside + // of it. We've already marked this child as the best so far. Recurse + // in case one of the children is better. forEachChild(child, visit); + // Once we look at the children of this node, then there's no need to + // continue any further. return true; } else { ts.Debug.assert(child.end <= position); + // The child ends entirely before this position. Say you have the following + // (where $ is the position) + // + // ? $ : <...> <...> + // + // We would want to find the nearest preceding node in "complex expr 2". + // To support that, we keep track of this node, and once we're done searching + // for a best node, we recurse down this node to see if we can find a good + // result in it. + // + // This approach allows us to quickly skip over nodes that are entirely + // before the position, while still allowing us to find any nodes in the + // last one that might be what we want. lastNodeEntirelyBeforePosition = child; } } else { ts.Debug.assert(child.pos > position); + // We're now at a node that is entirely past the position we're searching for. + // This node (and all following nodes) could never contribute to the result, + // so just skip them by returning 'true' here. return true; } } @@ -18685,7 +21686,7 @@ var ts; var oldText = sourceFile.text; if (textChangeRange) { ts.Debug.assert((oldText.length - textChangeRange.span.length + textChangeRange.newLength) === newText.length); - if (aggressiveChecks || ts.Debug.shouldAssert(3)) { + if (aggressiveChecks || ts.Debug.shouldAssert(3 /* VeryAggressive */)) { var oldTextPrefix = oldText.substr(0, textChangeRange.span.start); var newTextPrefix = newText.substr(0, textChangeRange.span.start); ts.Debug.assert(oldTextPrefix === newTextPrefix); @@ -18700,42 +21701,68 @@ var ts; var currentArrayIndex = 0; ts.Debug.assert(currentArrayIndex < currentArray.length); var current = currentArray[currentArrayIndex]; - var lastQueriedPosition = -1; + var lastQueriedPosition = -1 /* Value */; return { currentNode: function (position) { + // Only compute the current node if the position is different than the last time + // we were asked. The parser commonly asks for the node at the same position + // twice. Once to know if can read an appropriate list element at a certain point, + // and then to actually read and consume the node. if (position !== lastQueriedPosition) { + // Much of the time the parser will need the very next node in the array that + // we just returned a node from.So just simply check for that case and move + // forward in the array instead of searching for the node again. if (current && current.end === position && currentArrayIndex < (currentArray.length - 1)) { currentArrayIndex++; current = currentArray[currentArrayIndex]; } + // If we don't have a node, or the node we have isn't in the right position, + // then try to find a viable node at the position requested. if (!current || current.pos !== position) { findHighestListElementThatStartsAtPosition(position); } } + // Cache this query so that we don't do any extra work if the parser calls back + // into us. Note: this is very common as the parser will make pairs of calls like + // 'isListElement -> parseListElement'. If we were unable to find a node when + // called with 'isListElement', we don't want to redo the work when parseListElement + // is called immediately after. lastQueriedPosition = position; + // Either we don'd have a node, or we have a node at the position being asked for. ts.Debug.assert(!current || current.pos === position); return current; } }; + // Finds the highest element in the tree we can find that starts at the provided position. + // The element must be a direct child of some node list in the tree. This way after we + // return it, we can easily return its next sibling in the list. function findHighestListElementThatStartsAtPosition(position) { + // Clear out any cached state about the last node we found. currentArray = undefined; - currentArrayIndex = -1; + currentArrayIndex = -1 /* Value */; current = undefined; + // Recurse into the source file to find the highest node at this position. forEachChild(sourceFile, visitNode, visitArray); return; function visitNode(node) { if (position >= node.pos && position < node.end) { + // Position was within this node. Keep searching deeper to find the node. forEachChild(node, visitNode, visitArray); + // don't proceed any further in the search. return true; } + // position wasn't in this node, have to keep searching. return false; } function visitArray(array) { if (position >= array.pos && position < array.end) { + // position was in this array. Search through this array to see if we find a + // viable element. for (var i = 0; i < array.length; i++) { var child = array[i]; if (child) { if (child.pos === position) { + // Found the right node. We're done. currentArray = array; currentArrayIndex = i; current = child; @@ -18743,6 +21770,8 @@ var ts; } else { if (child.pos < position && position < child.end) { + // Position in somewhere within this child. Search in it and + // stop searching in this array. forEachChild(child, visitNode, visitArray); return true; } @@ -18750,6 +21779,7 @@ var ts; } } } + // position wasn't in this array, have to keep searching. return false; } } @@ -18760,11 +21790,15 @@ var ts; })(InvalidPosition || (InvalidPosition = {})); })(IncrementalParser || (IncrementalParser = {})); function isDeclarationFileName(fileName) { - return ts.fileExtensionIs(fileName, ".d.ts"); + return ts.fileExtensionIs(fileName, ".d.ts" /* Dts */); } + /*@internal*/ function processCommentPragmas(context, sourceText) { - var triviaScanner = ts.createScanner(context.languageVersion, false, 0, sourceText); + var triviaScanner = ts.createScanner(context.languageVersion, /*skipTrivia*/ false, 0 /* Standard */, sourceText); var pragmas = []; + // Keep scanning all the leading trivia in the file until we get to something that + // isn't trivia. Any single line comment will be analyzed to see if it is a + // reference comment. while (true) { var kind = triviaScanner.scan(); if (!ts.isTrivia(kind)) { @@ -18781,7 +21815,7 @@ var ts; context.pragmas = ts.createMap(); for (var _i = 0, pragmas_1 = pragmas; _i < pragmas_1.length; _i++) { var pragma = pragmas_1[_i]; - if (context.pragmas.has(pragma.name)) { + if (context.pragmas.has(pragma.name)) { // TODO: GH#18217 var currentValue = context.pragmas.get(pragma.name); if (currentValue instanceof Array) { currentValue.push(pragma.args); @@ -18795,6 +21829,7 @@ var ts; } } ts.processCommentPragmas = processCommentPragmas; + /*@internal*/ function processPragmasIntoFields(context, reportDiagnostic) { context.checkJsDirective = undefined; context.referencedFiles = []; @@ -18803,12 +21838,15 @@ var ts; context.amdDependencies = []; context.hasNoDefaultLib = false; context.pragmas.forEach(function (entryOrList, key) { + // TODO: The below should be strongly type-guarded and not need casts/explicit annotations, since entryOrList is related to + // key and key is constrained to a union; but it's not (see GH#21483 for at least partial fix) :( switch (key) { case "reference": { var referencedFiles_1 = context.referencedFiles; var typeReferenceDirectives_1 = context.typeReferenceDirectives; var libReferenceDirectives_1 = context.libReferenceDirectives; ts.forEach(ts.toArray(entryOrList), function (arg) { + // TODO: GH#18217 if (arg.arguments["no-default-lib"]) { context.hasNoDefaultLib = true; } @@ -18828,7 +21866,7 @@ var ts; break; } case "amd-dependency": { - context.amdDependencies = ts.map(ts.toArray(entryOrList), function (x) { return ({ name: x.arguments.name, path: x.arguments.path }); }); + context.amdDependencies = ts.map(ts.toArray(entryOrList), function (x) { return ({ name: x.arguments.name, path: x.arguments.path }); }); // TODO: GH#18217 break; } case "amd-module": { @@ -18836,6 +21874,7 @@ var ts; for (var _i = 0, entryOrList_1 = entryOrList; _i < entryOrList_1.length; _i++) { var entry = entryOrList_1[_i]; if (context.moduleName) { + // TODO: It's probably fine to issue this diagnostic on all instances of the pragma reportDiagnostic(entry.range.pos, entry.range.end - entry.range.pos, ts.Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments); } context.moduleName = entry.arguments.name; @@ -18848,8 +21887,9 @@ var ts; } case "ts-nocheck": case "ts-check": { + // _last_ of either nocheck or check in a file is the "winner" ts.forEach(ts.toArray(entryOrList), function (entry) { - if (!context.checkJsDirective || entry.range.pos > context.checkJsDirective.pos) { + if (!context.checkJsDirective || entry.range.pos > context.checkJsDirective.pos) { // TODO: GH#18217 context.checkJsDirective = { enabled: key === "ts-check", end: entry.range.end, @@ -18859,8 +21899,8 @@ var ts; }); break; } - case "jsx": return; - default: ts.Debug.fail("Unhandled pragma kind"); + case "jsx": return; // Accessed directly + default: ts.Debug.fail("Unhandled pragma kind"); // Can this be made into an assertNever in the future? } }); } @@ -18877,11 +21917,11 @@ var ts; var tripleSlashXMLCommentStartRegEx = /^\/\/\/\s*<(\S+)\s.*?\/>/im; var singleLinePragmaRegEx = /^\/\/\/?\s*@(\S+)\s*(.*)\s*$/im; function extractPragmas(pragmas, range, text) { - var tripleSlash = range.kind === 2 && tripleSlashXMLCommentStartRegEx.exec(text); + var tripleSlash = range.kind === 2 /* SingleLineCommentTrivia */ && tripleSlashXMLCommentStartRegEx.exec(text); if (tripleSlash) { - var name = tripleSlash[1].toLowerCase(); + var name = tripleSlash[1].toLowerCase(); // Technically unsafe cast, but we do it so the below check to make it safe typechecks var pragma = ts.commentPragmas[name]; - if (!pragma || !(pragma.kind & 1)) { + if (!pragma || !(pragma.kind & 1 /* TripleSlashXML */)) { return; } if (pragma.args) { @@ -18891,7 +21931,7 @@ var ts; var matcher = getNamedArgRegEx(arg.name); var matchResult = matcher.exec(text); if (!matchResult && !arg.optional) { - return; + return; // Missing required argument, don't parse } else if (matchResult) { if (arg.captureSpan) { @@ -18914,30 +21954,30 @@ var ts; } return; } - var singleLine = range.kind === 2 && singleLinePragmaRegEx.exec(text); + var singleLine = range.kind === 2 /* SingleLineCommentTrivia */ && singleLinePragmaRegEx.exec(text); if (singleLine) { - return addPragmaForMatch(pragmas, range, 2, singleLine); + return addPragmaForMatch(pragmas, range, 2 /* SingleLine */, singleLine); } - if (range.kind === 3) { - var multiLinePragmaRegEx = /\s*@(\S+)\s*(.*)\s*$/gim; + if (range.kind === 3 /* MultiLineCommentTrivia */) { + var multiLinePragmaRegEx = /\s*@(\S+)\s*(.*)\s*$/gim; // Defined inline since it uses the "g" flag, which keeps a persistent index (for iterating) var multiLineMatch = void 0; while (multiLineMatch = multiLinePragmaRegEx.exec(text)) { - addPragmaForMatch(pragmas, range, 4, multiLineMatch); + addPragmaForMatch(pragmas, range, 4 /* MultiLine */, multiLineMatch); } } } function addPragmaForMatch(pragmas, range, kind, match) { if (!match) return; - var name = match[1].toLowerCase(); + var name = match[1].toLowerCase(); // Technically unsafe cast, but we do it so they below check to make it safe typechecks var pragma = ts.commentPragmas[name]; if (!pragma || !(pragma.kind & kind)) { return; } - var args = match[2]; + var args = match[2]; // Split on spaces and match up positionally with definition var argument = getNamedPragmaArguments(pragma, args); if (argument === "fail") - return; + return; // Missing required argument, fail to parse it pragmas.push({ name: name, args: { arguments: argument, range: range } }); return; } @@ -18960,16 +22000,20 @@ var ts; } return argMap; } + /** @internal */ function tagNamesAreEquivalent(lhs, rhs) { if (lhs.kind !== rhs.kind) { return false; } - if (lhs.kind === 71) { + if (lhs.kind === 71 /* Identifier */) { return lhs.escapedText === rhs.escapedText; } - if (lhs.kind === 99) { + if (lhs.kind === 99 /* ThisKeyword */) { return true; } + // If we are at this statement then we must have PropertyAccessExpression and because tag name in Jsx element can only + // take forms of JsxTagNameExpression which includes an identifier, "this" expression, or another propertyAccessExpression + // it is safe to case the expression property as such. See parseJsxElementName for how we parse tag name in Jsx element return lhs.name.escapedText === rhs.name.escapedText && tagNamesAreEquivalent(lhs.expression, rhs.expression); } @@ -18977,8 +22021,14 @@ var ts; })(ts || (ts = {})); var ts; (function (ts) { + /* @internal */ ts.compileOnSaveCommandLineOption = { name: "compileOnSave", type: "boolean" }; + // NOTE: The order here is important to default lib ordering as entries will have the same + // order in the generated program (see `getDefaultLibPriority` in program.ts). This + // order also affects overload resolution when a type declared in one lib is + // augmented in another lib. var libEntries = [ + // JavaScript only ["es5", "lib.es5.d.ts"], ["es6", "lib.es2015.d.ts"], ["es2015", "lib.es2015.d.ts"], @@ -18987,11 +22037,13 @@ var ts; ["es2017", "lib.es2017.d.ts"], ["es2018", "lib.es2018.d.ts"], ["esnext", "lib.esnext.d.ts"], + // Host only ["dom", "lib.dom.d.ts"], ["dom.iterable", "lib.dom.iterable.d.ts"], ["webworker", "lib.webworker.d.ts"], ["webworker.importscripts", "lib.webworker.importscripts.d.ts"], ["scripthost", "lib.scripthost.d.ts"], + // ES2015 Or ESNext By-feature options ["es2015.core", "lib.es2015.core.d.ts"], ["es2015.collection", "lib.es2015.collection.d.ts"], ["es2015.generator", "lib.es2015.generator.d.ts"], @@ -19014,9 +22066,22 @@ var ts; ["esnext.symbol", "lib.esnext.symbol.d.ts"], ["esnext.asynciterable", "lib.esnext.asynciterable.d.ts"], ]; + /** + * An array of supported "lib" reference file names used to determine the order for inclusion + * when referenced, as well as for spelling suggestions. This ensures the correct ordering for + * overload resolution when a type declared in one lib is extended by another. + */ + /* @internal */ ts.libs = libEntries.map(function (entry) { return entry[0]; }); + /** + * A map of lib names to lib files. This map is used both for parsing the "lib" command line + * option as well as for resolving lib reference directives. + */ + /* @internal */ ts.libMap = ts.createMapFromEntries(libEntries); + /* @internal */ ts.optionDeclarations = [ + // CommandLine only options { name: "help", shortName: "h", @@ -19092,18 +22157,19 @@ var ts; category: ts.Diagnostics.Command_line_Options, description: ts.Diagnostics.Watch_input_files, }, + // Basic { name: "target", shortName: "t", type: ts.createMapFromTemplate({ - es3: 0, - es5: 1, - es6: 2, - es2015: 2, - es2016: 3, - es2017: 4, - es2018: 5, - esnext: 6, + es3: 0 /* ES3 */, + es5: 1 /* ES5 */, + es6: 2 /* ES2015 */, + es2015: 2 /* ES2015 */, + es2016: 3 /* ES2016 */, + es2017: 4 /* ES2017 */, + es2018: 5 /* ES2018 */, + esnext: 6 /* ESNext */, }), paramType: ts.Diagnostics.VERSION, showInSimplifiedHelpView: true, @@ -19155,9 +22221,9 @@ var ts; { name: "jsx", type: ts.createMapFromTemplate({ - "preserve": 1, - "react-native": 3, - "react": 2 + "preserve": 1 /* Preserve */, + "react-native": 3 /* ReactNative */, + "react": 2 /* React */ }), paramType: ts.Diagnostics.KIND, showInSimplifiedHelpView: true, @@ -19257,6 +22323,7 @@ var ts; category: ts.Diagnostics.Basic_Options, description: ts.Diagnostics.Transpile_each_file_as_a_separate_module_similar_to_ts_transpileModule }, + // Strict Type Checks { name: "strict", type: "boolean", @@ -19306,6 +22373,7 @@ var ts; category: ts.Diagnostics.Strict_Type_Checking_Options, description: ts.Diagnostics.Parse_in_strict_mode_and_emit_use_strict_for_each_source_file }, + // Additional Checks { name: "noUnusedLocals", type: "boolean", @@ -19334,6 +22402,7 @@ var ts; category: ts.Diagnostics.Additional_Checks, description: ts.Diagnostics.Report_errors_for_fallthrough_cases_in_switch_statement }, + // Module Resolution { name: "moduleResolution", type: ts.createMapFromTemplate({ @@ -19352,6 +22421,8 @@ var ts; description: ts.Diagnostics.Base_directory_to_resolve_non_absolute_module_names }, { + // this option can only be specified in tsconfig.json + // use type = object to copy the value as-is name: "paths", type: "object", isTSConfigOnly: true, @@ -19359,6 +22430,8 @@ var ts; description: ts.Diagnostics.A_series_of_entries_which_re_map_imports_to_lookup_locations_relative_to_the_baseUrl }, { + // this option can only be specified in tsconfig.json + // use type = object to copy the value as-is name: "rootDirs", type: "list", isTSConfigOnly: true, @@ -19411,6 +22484,7 @@ var ts; category: ts.Diagnostics.Module_Resolution_Options, description: ts.Diagnostics.Do_not_resolve_the_real_path_of_symlinks, }, + // Source Maps { name: "sourceRoot", type: "string", @@ -19437,6 +22511,7 @@ var ts; category: ts.Diagnostics.Source_Map_Options, description: ts.Diagnostics.Emit_the_source_alongside_the_sourcemaps_within_a_single_file_requires_inlineSourceMap_or_sourceMap_to_be_set }, + // Experimental { name: "experimentalDecorators", type: "boolean", @@ -19449,6 +22524,7 @@ var ts; category: ts.Diagnostics.Experimental_Options, description: ts.Diagnostics.Enables_experimental_support_for_emitting_type_metadata_for_decorators }, + // Advanced { name: "jsxFactory", type: "string", @@ -19495,6 +22571,7 @@ var ts; name: "out", type: "string", isFilePath: false, + // for correct behaviour, please use outFile category: ts.Diagnostics.Advanced_Options, paramType: ts.Diagnostics.FILE, description: ts.Diagnostics.Deprecated_Use_outFile_instead_Concatenate_and_emit_output_to_single_file, @@ -19532,8 +22609,8 @@ var ts; { name: "newLine", type: ts.createMapFromTemplate({ - crlf: 0, - lf: 1 + crlf: 0 /* CarriageReturnLineFeed */, + lf: 1 /* LineFeed */ }), paramType: ts.Diagnostics.NEWLINE, category: ts.Diagnostics.Advanced_Options, @@ -19656,6 +22733,7 @@ var ts; description: ts.Diagnostics.Resolve_keyof_to_string_valued_property_names_only_no_numbers_or_symbols, }, { + // A list of plugins to load in the language service name: "plugins", type: "list", isTSConfigOnly: true, @@ -19666,8 +22744,12 @@ var ts; description: ts.Diagnostics.List_of_language_service_plugins } ]; + /* @internal */ ts.typeAcquisitionDeclarations = [ { + /* @deprecated typingOptions.enableAutoDiscovery + * Use typeAcquisition.enable instead. + */ name: "enableAutoDiscovery", type: "boolean", }, @@ -19692,14 +22774,17 @@ var ts; } } ]; + /* @internal */ ts.defaultInitCompilerOptions = { module: ts.ModuleKind.CommonJS, - target: 1, + target: 1 /* ES5 */, strict: true, esModuleInterop: true }; var optionNameMapCache; + /* @internal */ function convertEnableAutoDiscoveryToEnable(typeAcquisition) { + // Convert deprecated typingOptions.enableAutoDiscovery to typeAcquisition.enable if (typeAcquisition && typeAcquisition.enableAutoDiscovery !== undefined && typeAcquisition.enable === undefined) { return { enable: typeAcquisition.enableAutoDiscovery, @@ -19725,6 +22810,7 @@ var ts; optionNameMapCache = { optionNameMap: optionNameMap, shortOptionNames: shortOptionNames }; return optionNameMapCache; } + /* @internal */ function createCompilerDiagnosticForInvalidCustomType(opt) { return createDiagnosticForInvalidCustomType(opt, ts.createCompilerDiagnostic); } @@ -19733,10 +22819,12 @@ var ts; var namesOfType = ts.arrayFrom(opt.type.keys()).map(function (key) { return "'" + key + "'"; }).join(", "); return createDiagnostic(ts.Diagnostics.Argument_for_0_option_must_be_Colon_1, "--" + opt.name, namesOfType); } + /* @internal */ function parseCustomTypeOption(opt, value, errors) { return convertJsonOptionOfCustomType(opt, trimString(value || ""), errors); } ts.parseCustomTypeOption = parseCustomTypeOption; + /* @internal */ function parseListTypeOption(opt, value, errors) { if (value === void 0) { value = ""; } value = trimString(value); @@ -19774,16 +22862,17 @@ var ts; while (i < args.length) { var s = args[i]; i++; - if (s.charCodeAt(0) === 64) { + if (s.charCodeAt(0) === 64 /* at */) { parseResponseFile(s.slice(1)); } - else if (s.charCodeAt(0) === 45) { - var opt = getOptionFromName(s.slice(s.charCodeAt(1) === 45 ? 2 : 1), true); + else if (s.charCodeAt(0) === 45 /* minus */) { + var opt = getOptionFromName(s.slice(s.charCodeAt(1) === 45 /* minus */ ? 2 : 1), /*allowShort*/ true); if (opt) { if (opt.isTSConfigOnly) { errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file, opt.name)); } else { + // Check to see if no argument was provided (e.g. "--locale" is the last command-line argument). if (!args[i] && opt.type !== "boolean") { errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Compiler_option_0_expects_an_argument, opt.name)); } @@ -19793,8 +22882,10 @@ var ts; i++; break; case "boolean": + // boolean flag has optional value true, false, others var optValue = args[i]; options[opt.name] = optValue !== "false"; + // consume next argument as boolean flag value if (optValue === "false" || optValue === "true") { i++; } @@ -19810,6 +22901,7 @@ var ts; i++; } break; + // If not a primitive, the possible types are specified in what is effectively a map of options. default: options[opt.name] = parseCustomTypeOption(opt, args[i], errors); i++; @@ -19835,14 +22927,14 @@ var ts; var args = []; var pos = 0; while (true) { - while (pos < text.length && text.charCodeAt(pos) <= 32) + while (pos < text.length && text.charCodeAt(pos) <= 32 /* space */) pos++; if (pos >= text.length) break; var start = pos; - if (text.charCodeAt(start) === 34) { + if (text.charCodeAt(start) === 34 /* doubleQuote */) { pos++; - while (pos < text.length && text.charCodeAt(pos) !== 34) + while (pos < text.length && text.charCodeAt(pos) !== 34 /* doubleQuote */) pos++; if (pos < text.length) { args.push(text.substring(start + 1, pos)); @@ -19853,7 +22945,7 @@ var ts; } } else { - while (text.charCodeAt(pos) > 32) + while (text.charCodeAt(pos) > 32 /* space */) pos++; args.push(text.substring(start, pos)); } @@ -19862,10 +22954,12 @@ var ts; } } ts.parseCommandLine = parseCommandLine; + /** @internal */ function getOptionFromName(optionName, allowShort) { if (allowShort === void 0) { allowShort = false; } optionName = optionName.toLowerCase(); var _a = getOptionNameMap(), optionNameMap = _a.optionNameMap, shortOptionNames = _a.shortOptionNames; + // Try to translate short option names to their full equivalents. if (allowShort) { var short = shortOptionNames.get(optionName); if (short !== undefined) { @@ -19883,20 +22977,25 @@ var ts; var diagnostic = ts.createCompilerDiagnostic.apply(undefined, arguments); return diagnostic.messageText; } + /* @internal */ function printVersion() { ts.sys.write(getDiagnosticText(ts.Diagnostics.Version_0, ts.version) + ts.sys.newLine); } ts.printVersion = printVersion; + /* @internal */ function printHelp(optionsList, syntaxPrefix) { if (syntaxPrefix === void 0) { syntaxPrefix = ""; } var output = []; + // We want to align our "syntax" and "examples" commands to a certain margin. var syntaxLength = getDiagnosticText(ts.Diagnostics.Syntax_Colon_0, "").length; var examplesLength = getDiagnosticText(ts.Diagnostics.Examples_Colon_0, "").length; var marginLength = Math.max(syntaxLength, examplesLength); + // Build up the syntactic skeleton. var syntax = makePadding(marginLength - syntaxLength); syntax += "tsc " + syntaxPrefix + "[" + getDiagnosticText(ts.Diagnostics.options) + "] [" + getDiagnosticText(ts.Diagnostics.file) + "...]"; output.push(getDiagnosticText(ts.Diagnostics.Syntax_Colon_0, syntax)); output.push(ts.sys.newLine + ts.sys.newLine); + // Build up the list of examples. var padding = makePadding(marginLength); output.push(getDiagnosticText(ts.Diagnostics.Examples_Colon_0, makePadding(marginLength - examplesLength) + "tsc hello.ts") + ts.sys.newLine); output.push(padding + "tsc --outFile file.js file.ts" + ts.sys.newLine); @@ -19904,12 +23003,16 @@ var ts; output.push(padding + "tsc --build tsconfig.json" + ts.sys.newLine); output.push(ts.sys.newLine); output.push(getDiagnosticText(ts.Diagnostics.Options_Colon) + ts.sys.newLine); + // We want our descriptions to align at the same column in our output, + // so we keep track of the longest option usage string. marginLength = 0; - var usageColumn = []; + var usageColumn = []; // Things like "-d, --declaration" go in here. var descriptionColumn = []; - var optionsDescriptionMap = ts.createMap(); + var optionsDescriptionMap = ts.createMap(); // Map between option.description and list of option.type if it is a kind for (var _i = 0, optionsList_1 = optionsList; _i < optionsList_1.length; _i++) { var option = optionsList_1[_i]; + // If an option lacks a description, + // it is not officially supported. if (!option.description) { continue; } @@ -19933,12 +23036,15 @@ var ts; description = getDiagnosticText(option.description); } descriptionColumn.push(description); + // Set the new margin for the description column if necessary. marginLength = Math.max(usageText_1.length, marginLength); } + // Special case that can't fit in the loop. var usageText = " @<" + getDiagnosticText(ts.Diagnostics.file) + ">"; usageColumn.push(usageText); descriptionColumn.push(getDiagnosticText(ts.Diagnostics.Insert_command_line_options_and_files_from_a_file)); marginLength = Math.max(usageText.length, marginLength); + // Print out each row, aligning all the descriptions on the same column. for (var i = 0; i < usageColumn.length; i++) { var usage = usageColumn[i]; var description = descriptionColumn[i]; @@ -19969,6 +23075,9 @@ var ts; } } ts.printHelp = printHelp; + /** + * Reads the config file, reports errors if any and exits if the config file cannot be found + */ function getParsedCommandLineOfConfigFile(configFileName, optionsToExtend, host) { var configFileText; try { @@ -19989,11 +23098,20 @@ var ts; return parseJsonSourceFileConfigFileContent(result, host, ts.getNormalizedAbsolutePath(ts.getDirectoryPath(configFileName), cwd), optionsToExtend, ts.getNormalizedAbsolutePath(configFileName, cwd)); } ts.getParsedCommandLineOfConfigFile = getParsedCommandLineOfConfigFile; + /** + * Read tsconfig.json file + * @param fileName The path to the config file + */ function readConfigFile(fileName, readFile) { var textOrDiagnostic = tryReadFile(fileName, readFile); return ts.isString(textOrDiagnostic) ? parseConfigFileTextToJson(fileName, textOrDiagnostic) : { config: {}, error: textOrDiagnostic }; } ts.readConfigFile = readConfigFile; + /** + * Parse the text of the tsconfig.json file + * @param fileName The path to the config file + * @param jsonText The text of the config file + */ function parseConfigFileTextToJson(fileName, jsonText) { var jsonSourceFile = ts.parseJsonText(fileName, jsonText); return { @@ -20002,6 +23120,10 @@ var ts; }; } ts.parseConfigFileTextToJson = parseConfigFileTextToJson; + /** + * Read tsconfig.json file + * @param fileName The path to the config file + */ function readJsonConfigFile(fileName, readFile) { var textOrDiagnostic = tryReadFile(fileName, readFile); return ts.isString(textOrDiagnostic) ? ts.parseJsonText(fileName, textOrDiagnostic) : { parseDiagnostics: [textOrDiagnostic] }; @@ -20087,10 +23209,19 @@ var ts; } return _tsconfigRootOptions; } + /** + * Convert the json syntax tree into the json value + */ function convertToObject(sourceFile, errors) { - return convertToObjectWorker(sourceFile, errors, true, undefined, undefined); + return convertToObjectWorker(sourceFile, errors, /*returnValue*/ true, /*knownRootOptions*/ undefined, /*jsonConversionNotifier*/ undefined); } ts.convertToObject = convertToObject; + /** + * Convert the json syntax tree into the json value and report errors + * This returns the json value (apart from checking errors) only if returnValue provided is true. + * Otherwise it just checks the errors and returns undefined + */ + /*@internal*/ function convertToObjectWorker(sourceFile, errors, returnValue, knownRootOptions, jsonConversionNotifier) { if (!sourceFile.statements.length) { return returnValue ? {} : undefined; @@ -20103,7 +23234,7 @@ var ts; var result = returnValue ? {} : undefined; for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { var element = _a[_i]; - if (element.kind !== 270) { + if (element.kind !== 270 /* PropertyAssignment */) { errors.push(ts.createDiagnosticForNodeInSourceFile(sourceFile, element, ts.Diagnostics.Property_assignment_expected)); continue; } @@ -20123,19 +23254,24 @@ var ts; if (returnValue) { result[keyText] = value; } + // Notify key value set, if user asked for it if (jsonConversionNotifier && + // Current callbacks are only on known parent option or if we are setting values in the root (parentOption || isRootOptionMap(knownOptions))) { var isValidOptionValue = isCompilerOptionsValue(option, value); if (parentOption) { if (isValidOptionValue) { + // Notify option set in the parent if its a valid option value jsonConversionNotifier.onSetValidOptionKeyValueInParent(parentOption, option, value); } } else if (isRootOptionMap(knownOptions)) { if (isValidOptionValue) { + // Notify about the valid root key value being set jsonConversionNotifier.onSetValidOptionKeyValueInRoot(keyText, element.name, value, element.initializer); } else if (!option) { + // Notify about the unknown root key value being set jsonConversionNotifier.onSetUnknownOptionKeyValueInRoot(keyText, element.name, value, element.initializer); } } @@ -20149,16 +23285,16 @@ var ts; } function convertPropertyValueToJson(valueExpression, option) { switch (valueExpression.kind) { - case 101: + case 101 /* TrueKeyword */: reportInvalidOptionValue(option && option.type !== "boolean"); return true; - case 86: + case 86 /* FalseKeyword */: reportInvalidOptionValue(option && option.type !== "boolean"); return false; - case 95: - reportInvalidOptionValue(option && option.name === "extends"); - return null; - case 9: + case 95 /* NullKeyword */: + reportInvalidOptionValue(option && option.name === "extends"); // "extends" is the only option we don't allow null/undefined for + return null; // tslint:disable-line:no-null-keyword + case 9 /* StringLiteral */: if (!isDoubleQuotedString(valueExpression)) { errors.push(ts.createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, ts.Diagnostics.String_literal_with_double_quotes_expected)); } @@ -20166,36 +23302,45 @@ var ts; var text = valueExpression.text; if (option && !ts.isString(option.type)) { var customOption = option; + // Validate custom option type if (!customOption.type.has(text.toLowerCase())) { errors.push(createDiagnosticForInvalidCustomType(customOption, function (message, arg0, arg1) { return ts.createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, message, arg0, arg1); })); } } return text; - case 8: + case 8 /* NumericLiteral */: reportInvalidOptionValue(option && option.type !== "number"); return Number(valueExpression.text); - case 198: - if (valueExpression.operator !== 38 || valueExpression.operand.kind !== 8) { - break; + case 198 /* PrefixUnaryExpression */: + if (valueExpression.operator !== 38 /* MinusToken */ || valueExpression.operand.kind !== 8 /* NumericLiteral */) { + break; // not valid JSON syntax } reportInvalidOptionValue(option && option.type !== "number"); return -Number(valueExpression.operand.text); - case 184: + case 184 /* ObjectLiteralExpression */: reportInvalidOptionValue(option && option.type !== "object"); var objectLiteralExpression = valueExpression; + // Currently having element option declaration in the tsconfig with type "object" + // determines if it needs onSetValidOptionKeyValueInParent callback or not + // At moment there are only "compilerOptions", "typeAcquisition" and "typingOptions" + // that satifies it and need it to modify options set in them (for normalizing file paths) + // vs what we set in the json + // If need arises, we can modify this interface and callbacks as needed if (option) { var _a = option, elementOptions = _a.elementOptions, extraKeyDiagnosticMessage = _a.extraKeyDiagnosticMessage, optionName = _a.name; return convertObjectLiteralExpressionToJson(objectLiteralExpression, elementOptions, extraKeyDiagnosticMessage, optionName); } else { - return convertObjectLiteralExpressionToJson(objectLiteralExpression, undefined, undefined, undefined); + return convertObjectLiteralExpressionToJson(objectLiteralExpression, /* knownOptions*/ undefined, + /*extraKeyDiagnosticMessage */ undefined, /*parentOption*/ undefined); } - case 183: + case 183 /* ArrayLiteralExpression */: reportInvalidOptionValue(option && option.type !== "list"); return convertArrayLiteralExpressionToJson(valueExpression.elements, option && option.element); } + // Not in expected format if (option) { - reportInvalidOptionValue(true); + reportInvalidOptionValue(/*isError*/ true); } else { errors.push(ts.createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, ts.Diagnostics.Property_value_can_only_be_string_literal_numeric_literal_true_false_null_object_literal_or_array_literal)); @@ -20220,7 +23365,7 @@ var ts; function isCompilerOptionsValue(option, value) { if (option) { if (isNullOrUndefined(value)) - return true; + return true; // All options are undefinable/nullable if (option.type === "list") { return ts.isArray(value); } @@ -20229,12 +23374,19 @@ var ts; } return false; } + /** + * Generate tsconfig configuration when running command line "--init" + * @param options commandlineOptions to be generated into tsconfig.json + * @param fileNames array of filenames to be generated into tsconfig.json + */ + /* @internal */ function generateTSConfig(options, fileNames, newLine) { var compilerOptions = ts.extend(options, ts.defaultInitCompilerOptions); var compilerOptionsMap = serializeCompilerOptions(compilerOptions); return writeConfigurations(); function getCustomTypeMapOfCommandLineOption(optionDefinition) { if (optionDefinition.type === "string" || optionDefinition.type === "number" || optionDefinition.type === "boolean") { + // this is of a type CommandLineOptionOfPrimitiveType return undefined; } else if (optionDefinition.type === "list") { @@ -20245,6 +23397,7 @@ var ts; } } function getNameOfCompilerOptionValue(value, customTypeMap) { + // There is a typeMap associated with this command-line option so use it to map value back to its name return ts.forEachEntry(customTypeMap, function (mapValue, key) { if (mapValue === value) { return key; @@ -20256,6 +23409,8 @@ var ts; var optionsNameMap = getOptionNameMap().optionNameMap; var _loop_3 = function (name) { if (ts.hasProperty(options, name)) { + // tsconfig only options cannot be specified via command line, + // so we can assume that only types that can appear here string | number | boolean if (optionsNameMap.has(name) && optionsNameMap.get(name).category === ts.Diagnostics.Command_line_Options) { return "continue"; } @@ -20264,13 +23419,16 @@ var ts; if (optionDefinition) { var customTypeMap_1 = getCustomTypeMapOfCommandLineOption(optionDefinition); if (!customTypeMap_1) { + // There is no map associated with this compiler option then use the value as-is + // This is the case if the value is expect to be string, number, boolean or list of string result.set(name, value); } else { if (optionDefinition.type === "list") { - result.set(name, value.map(function (element) { return getNameOfCompilerOptionValue(element, customTypeMap_1); })); + result.set(name, value.map(function (element) { return getNameOfCompilerOptionValue(element, customTypeMap_1); })); // TODO: GH#18217 } else { + // There is a typeMap associated with this command-line option so use it to map value back to its name result.set(name, getNameOfCompilerOptionValue(value, customTypeMap_1)); } } @@ -20303,11 +23461,14 @@ var ts; } function isAllowedOption(_a) { var category = _a.category, name = _a.name; + // Skip options which do not have a category or have category `Command_line_Options` + // Exclude all possible `Advanced_Options` in tsconfig.json which were NOT defined in command line return category !== undefined && category !== ts.Diagnostics.Command_line_Options && (category !== ts.Diagnostics.Advanced_Options || compilerOptionsMap.has(name)); } function writeConfigurations() { + // Filter applicable options to place in the file var categorizedOptions = ts.createMultiMap(); for (var _i = 0, optionDeclarations_1 = ts.optionDeclarations; _i < optionDeclarations_1.length; _i++) { var option = optionDeclarations_1[_i]; @@ -20316,6 +23477,7 @@ var ts; categorizedOptions.add(ts.getLocaleSpecificMessage(category), option); } } + // Serialize all options and their descriptions var marginLength = 0; var seenKnownKeys = 0; var nameColumn = []; @@ -20341,10 +23503,12 @@ var ts; marginLength = Math.max(optionName.length, marginLength); } }); + // Write the output var tab = makePadding(2); var result = []; result.push("{"); result.push(tab + "\"compilerOptions\": {"); + // Print out each row, aligning all the descriptions on the same column. for (var i = 0; i < nameColumn.length; i++) { var optionName = nameColumn[i]; var description = descriptionColumn[i]; @@ -20366,14 +23530,29 @@ var ts; } } ts.generateTSConfig = generateTSConfig; + /** + * Parse the contents of a config file (tsconfig.json). + * @param json The contents of the config file to parse + * @param host Instance of ParseConfigHost used to enumerate files in folder. + * @param basePath A root directory to resolve relative path entries in the config + * file to. e.g. outDir + */ function parseJsonConfigFileContent(json, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions) { - return parseJsonConfigFileContentWorker(json, undefined, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions); + return parseJsonConfigFileContentWorker(json, /*sourceFile*/ undefined, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions); } ts.parseJsonConfigFileContent = parseJsonConfigFileContent; + /** + * Parse the contents of a config file (tsconfig.json). + * @param jsonNode The contents of the config file to parse + * @param host Instance of ParseConfigHost used to enumerate files in folder. + * @param basePath A root directory to resolve relative path entries in the config + * file to. e.g. outDir + */ function parseJsonSourceFileConfigFileContent(sourceFile, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions) { - return parseJsonConfigFileContentWorker(undefined, sourceFile, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions); + return parseJsonConfigFileContentWorker(/*json*/ undefined, sourceFile, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions); } ts.parseJsonSourceFileConfigFileContent = parseJsonSourceFileConfigFileContent; + /*@internal*/ function setConfigFileInOptions(options, configFile) { if (configFile) { Object.defineProperty(options, "configFile", { enumerable: false, writable: false, value: configFile }); @@ -20381,11 +23560,23 @@ var ts; } ts.setConfigFileInOptions = setConfigFileInOptions; function isNullOrUndefined(x) { + // tslint:disable-next-line:no-null-keyword return x === undefined || x === null; } function directoryOfCombinedPath(fileName, basePath) { + // Use the `getNormalizedAbsolutePath` function to avoid canonicalizing the path, as it must remain noncanonical + // until consistient casing errors are reported return ts.getDirectoryPath(ts.getNormalizedAbsolutePath(fileName, basePath)); } + /** + * Parse the contents of a config file from json or json source file (tsconfig.json). + * @param json The contents of the config file to parse + * @param sourceFile sourceFile corresponding to the Json + * @param host Instance of ParseConfigHost used to enumerate files in folder. + * @param basePath A root directory to resolve relative path entries in the config + * file to. e.g. outDir + * @param resolutionStack Only present for backwards-compatibility. Should be empty. + */ function parseJsonConfigFileContentWorker(json, sourceFile, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions) { if (existingOptions === void 0) { existingOptions = {}; } if (resolutionStack === void 0) { resolutionStack = []; } @@ -20485,10 +23676,12 @@ var ts; } } } + /*@internal*/ function isErrorNoInputFiles(error) { return error.code === ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code; } ts.isErrorNoInputFiles = isErrorNoInputFiles; + /*@internal*/ function getErrorForNoInputFiles(_a, configFileName) { var includeSpecs = _a.includeSpecs, excludeSpecs = _a.excludeSpecs; return ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, configFileName || "tsconfig.json", JSON.stringify(includeSpecs || []), JSON.stringify(excludeSpecs || [])); @@ -20497,6 +23690,10 @@ var ts; function isSuccessfulParsedTsconfig(value) { return !!value.options; } + /** + * This *just* extracts options/include/exclude/files out of a config file. + * It does *not* resolve the included files. + */ function parseConfig(json, sourceFile, host, basePath, configFileName, resolutionStack, errors) { basePath = ts.normalizeSlashes(basePath); var resolvedPath = ts.getNormalizedAbsolutePath(configFileName || "", basePath); @@ -20508,6 +23705,7 @@ var ts; parseOwnConfigOfJson(json, host, basePath, configFileName, errors) : parseOwnConfigOfJsonSourceFile(sourceFile, host, basePath, configFileName, errors); if (ownConfig.extendedConfigPath) { + // copy the resolution stack so it is never reused between branches in potential diamond-problem scenarios. resolutionStack = resolutionStack.concat([resolvedPath]); var extendedConfig = getExtendedConfig(sourceFile, ownConfig.extendedConfigPath, host, basePath, resolutionStack, errors); if (extendedConfig && isSuccessfulParsedTsconfig(extendedConfig)) { @@ -20526,6 +23724,7 @@ var ts; raw_1.compileOnSave = baseRaw_1.compileOnSave; } ownConfig.options = ts.assign({}, extendedConfig.options, ownConfig.options); + // TODO extend type typeAcquisition } } return ownConfig; @@ -20535,6 +23734,8 @@ var ts; errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unknown_option_excludes_Did_you_mean_exclude)); } var options = convertCompilerOptionsFromJsonWorker(json.compilerOptions, basePath, errors, configFileName); + // typingOptions has been deprecated and is only supported for backward compatibility purposes. + // It should be removed in future releases - use typeAcquisition instead. var typeAcquisition = convertTypeAcquisitionFromJsonWorker(json.typeAcquisition || json.typingOptions, basePath, errors, configFileName); json.compileOnSave = convertCompileOnSaveOptionFromJson(json, basePath, errors); var extendedConfigPath; @@ -20584,7 +23785,7 @@ var ts; } } }; - var json = convertToObjectWorker(sourceFile, errors, true, getTsconfigRootOptionsMap(), optionsIterator); + var json = convertToObjectWorker(sourceFile, errors, /*returnValue*/ true, getTsconfigRootOptionsMap(), optionsIterator); if (!typeAcquisition) { if (typingOptionstypeAcquisition) { typeAcquisition = (typingOptionstypeAcquisition.enableAutoDiscovery !== undefined) ? @@ -20603,12 +23804,13 @@ var ts; } function getExtendsConfigPath(extendedConfig, host, basePath, errors, createDiagnostic) { extendedConfig = ts.normalizeSlashes(extendedConfig); + // If the path isn't a rooted or relative path, don't try to resolve it (we reserve the right to special case module-id like paths in the future) if (!(ts.isRootedDiskPath(extendedConfig) || ts.startsWith(extendedConfig, "./") || ts.startsWith(extendedConfig, "../"))) { errors.push(createDiagnostic(ts.Diagnostics.A_path_in_an_extends_option_must_be_relative_or_rooted_but_0_is_not, extendedConfig)); return undefined; } var extendedConfigPath = ts.getNormalizedAbsolutePath(extendedConfig, basePath); - if (!host.fileExists(extendedConfigPath) && !ts.endsWith(extendedConfigPath, ".json")) { + if (!host.fileExists(extendedConfigPath) && !ts.endsWith(extendedConfigPath, ".json" /* Json */)) { extendedConfigPath = extendedConfigPath + ".json"; if (!host.fileExists(extendedConfigPath)) { errors.push(createDiagnostic(ts.Diagnostics.File_0_does_not_exist, extendedConfig)); @@ -20628,11 +23830,12 @@ var ts; return undefined; } var extendedDirname = ts.getDirectoryPath(extendedConfigPath); - var extendedConfig = parseConfig(undefined, extendedResult, host, extendedDirname, ts.getBaseFileName(extendedConfigPath), resolutionStack, errors); + var extendedConfig = parseConfig(/*json*/ undefined, extendedResult, host, extendedDirname, ts.getBaseFileName(extendedConfigPath), resolutionStack, errors); if (sourceFile) { (_a = sourceFile.extendedSourceFiles).push.apply(_a, extendedResult.extendedSourceFiles); } if (isSuccessfulParsedTsconfig(extendedConfig)) { + // Update the paths to reflect base path var relativeDifference_1 = ts.convertToRelativePath(extendedDirname, basePath, ts.identity); var updatePath_1 = function (path) { return ts.isRootedDiskPath(path) ? path : ts.combinePaths(relativeDifference_1, path); }; var mapPropertiesInRawIfNotUndefined = function (propertyName) { @@ -20761,31 +23964,118 @@ var ts; function trimString(s) { return typeof s.trim === "function" ? s.trim() : s.replace(/^[\s]+|[\s]+$/g, ""); } + /** + * Tests for a path that ends in a recursive directory wildcard. + * Matches **, \**, **\, and \**\, but not a**b. + * + * NOTE: used \ in place of / above to avoid issues with multiline comments. + * + * Breakdown: + * (^|\/) # matches either the beginning of the string or a directory separator. + * \*\* # matches the recursive directory wildcard "**". + * \/?$ # matches an optional trailing directory separator at the end of the string. + */ var invalidTrailingRecursionPattern = /(^|\/)\*\*\/?$/; + /** + * Tests for a path where .. appears after a recursive directory wildcard. + * Matches **\..\*, **\a\..\*, and **\.., but not ..\**\* + * + * NOTE: used \ in place of / above to avoid issues with multiline comments. + * + * Breakdown: + * (^|\/) # matches either the beginning of the string or a directory separator. + * \*\*\/ # matches a recursive directory wildcard "**" followed by a directory separator. + * (.*\/)? # optionally matches any number of characters followed by a directory separator. + * \.\. # matches a parent directory path component ".." + * ($|\/) # matches either the end of the string or a directory separator. + */ var invalidDotDotAfterRecursiveWildcardPattern = /(^|\/)\*\*\/(.*\/)?\.\.($|\/)/; + /** + * Tests for a path containing a wildcard character in a directory component of the path. + * Matches \*\, \?\, and \a*b\, but not \a\ or \a\*. + * + * NOTE: used \ in place of / above to avoid issues with multiline comments. + * + * Breakdown: + * \/ # matches a directory separator. + * [^/]*? # matches any number of characters excluding directory separators (non-greedy). + * [*?] # matches either a wildcard character (* or ?) + * [^/]* # matches any number of characters excluding directory separators (greedy). + * \/ # matches a directory separator. + */ var watchRecursivePattern = /\/[^/]*?[*?][^/]*\//; + /** + * Matches the portion of a wildcard path that does not contain wildcards. + * Matches \a of \a\*, or \a\b\c of \a\b\c\?\d. + * + * NOTE: used \ in place of / above to avoid issues with multiline comments. + * + * Breakdown: + * ^ # matches the beginning of the string + * [^*?]* # matches any number of non-wildcard characters + * (?=\/[^/]*[*?]) # lookahead that matches a directory separator followed by + * # a path component that contains at least one wildcard character (* or ?). + */ var wildcardDirectoryPattern = /^[^*?]*(?=\/[^/]*[*?])/; + /** + * Expands an array of file specifications. + * + * @param filesSpecs The literal file names to include. + * @param includeSpecs The wildcard file specifications to include. + * @param excludeSpecs The wildcard file specifications to exclude. + * @param basePath The base path for any relative file specifications. + * @param options Compiler options. + * @param host The host used to resolve files and directories. + * @param errors An array for diagnostic reporting. + */ function matchFileNames(filesSpecs, includeSpecs, excludeSpecs, basePath, options, host, errors, extraFileExtensions, jsonSourceFile) { basePath = ts.normalizePath(basePath); var validatedIncludeSpecs, validatedExcludeSpecs; + // The exclude spec list is converted into a regular expression, which allows us to quickly + // test whether a file or directory should be excluded before recursively traversing the + // file system. if (includeSpecs) { - validatedIncludeSpecs = validateSpecs(includeSpecs, errors, false, jsonSourceFile, "include"); + validatedIncludeSpecs = validateSpecs(includeSpecs, errors, /*allowTrailingRecursion*/ false, jsonSourceFile, "include"); } if (excludeSpecs) { - validatedExcludeSpecs = validateSpecs(excludeSpecs, errors, true, jsonSourceFile, "exclude"); + validatedExcludeSpecs = validateSpecs(excludeSpecs, errors, /*allowTrailingRecursion*/ true, jsonSourceFile, "exclude"); } + // Wildcard directories (provided as part of a wildcard path) are stored in a + // file map that marks whether it was a regular wildcard match (with a `*` or `?` token), + // or a recursive directory. This information is used by filesystem watchers to monitor for + // new entries in these paths. var wildcardDirectories = getWildcardDirectories(validatedIncludeSpecs, validatedExcludeSpecs, basePath, host.useCaseSensitiveFileNames); var spec = { filesSpecs: filesSpecs, referencesSpecs: undefined, includeSpecs: includeSpecs, excludeSpecs: excludeSpecs, validatedIncludeSpecs: validatedIncludeSpecs, validatedExcludeSpecs: validatedExcludeSpecs, wildcardDirectories: wildcardDirectories }; return getFileNamesFromConfigSpecs(spec, basePath, options, host, extraFileExtensions); } + /** + * Gets the file names from the provided config file specs that contain, files, include, exclude and + * other properties needed to resolve the file names + * @param spec The config file specs extracted with file names to include, wildcards to include/exclude and other details + * @param basePath The base path for any relative file specifications. + * @param options Compiler options. + * @param host The host used to resolve files and directories. + * @param extraFileExtensions optionaly file extra file extension information from host + */ + /* @internal */ function getFileNamesFromConfigSpecs(spec, basePath, options, host, extraFileExtensions) { if (extraFileExtensions === void 0) { extraFileExtensions = []; } basePath = ts.normalizePath(basePath); var keyMapper = host.useCaseSensitiveFileNames ? ts.identity : ts.toLowerCase; + // Literal file names (provided via the "files" array in tsconfig.json) are stored in a + // file map with a possibly case insensitive key. We use this map later when when including + // wildcard paths. var literalFileMap = ts.createMap(); + // Wildcard paths (provided via the "includes" array in tsconfig.json) are stored in a + // file map with a possibly case insensitive key. We use this map to store paths matched + // via wildcard, and to handle extension priority. var wildcardFileMap = ts.createMap(); var filesSpecs = spec.filesSpecs, validatedIncludeSpecs = spec.validatedIncludeSpecs, validatedExcludeSpecs = spec.validatedExcludeSpecs, wildcardDirectories = spec.wildcardDirectories; + // Rather than requery this for each file and filespec, we query the supported extensions + // once and store it on the expansion context. var supportedExtensions = ts.getSupportedExtensions(options, extraFileExtensions); + // Literal files are always included verbatim. An "include" or "exclude" specification cannot + // remove a literal file. if (filesSpecs) { for (var _i = 0, filesSpecs_1 = filesSpecs; _i < filesSpecs_1.length; _i++) { var fileName = filesSpecs_1[_i]; @@ -20794,11 +24084,21 @@ var ts; } } if (validatedIncludeSpecs && validatedIncludeSpecs.length > 0) { - for (var _a = 0, _b = host.readDirectory(basePath, supportedExtensions, validatedExcludeSpecs, validatedIncludeSpecs, undefined); _a < _b.length; _a++) { + for (var _a = 0, _b = host.readDirectory(basePath, supportedExtensions, validatedExcludeSpecs, validatedIncludeSpecs, /*depth*/ undefined); _a < _b.length; _a++) { var file = _b[_a]; + // If we have already included a literal or wildcard path with a + // higher priority extension, we should skip this file. + // + // This handles cases where we may encounter both .ts and + // .d.ts (or .js if "allowJs" is enabled) in the same + // directory when they are compilation outputs. if (hasFileWithHigherPriorityExtension(file, literalFileMap, wildcardFileMap, supportedExtensions, keyMapper)) { continue; } + // We may have included a wildcard path with a lower priority + // extension due to the user-defined order of entries in the + // "include" array. If there is a lower priority extension in the + // same directory, we should remove it. removeWildcardFilesWithLowerPriorityExtension(file, wildcardFileMap, supportedExtensions, keyMapper); var key = keyMapper(file); if (!literalFileMap.has(key) && !wildcardFileMap.has(key)) { @@ -20842,7 +24142,22 @@ var ts; return ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0; } } + /** + * Gets directories in a set of include patterns that should be watched for changes. + */ function getWildcardDirectories(include, exclude, path, useCaseSensitiveFileNames) { + // We watch a directory recursively if it contains a wildcard anywhere in a directory segment + // of the pattern: + // + // /a/b/**/d - Watch /a/b recursively to catch changes to any d in any subfolder recursively + // /a/b/*/d - Watch /a/b recursively to catch any d in any immediate subfolder, even if a new subfolder is added + // /a/b - Watch /a/b recursively to catch changes to anything in any recursive subfoler + // + // We watch a directory without recursion if it contains a wildcard in the file segment of + // the pattern: + // + // /a/b/* - Watch /a/b directly to catch any new file + // /a/b/a?z - Watch /a/b directly to catch any new file matching a?z var rawExcludeRegex = ts.getRegularExpressionForWildcard(exclude, path, "exclude"); var excludeRegex = rawExcludeRegex && new RegExp(rawExcludeRegex, useCaseSensitiveFileNames ? "" : "i"); var wildcardDirectories = {}; @@ -20860,12 +24175,13 @@ var ts; var existingFlags = wildcardDirectories[key]; if (existingFlags === undefined || existingFlags < flags) { wildcardDirectories[key] = flags; - if (flags === 1) { + if (flags === 1 /* Recursive */) { recursiveKeys.push(key); } } } } + // Remove any subpaths under an existing recursively watched directory. for (var key in wildcardDirectories) { if (ts.hasProperty(wildcardDirectories, key)) { for (var _a = 0, recursiveKeys_1 = recursiveKeys; _a < recursiveKeys_1.length; _a++) { @@ -20884,18 +24200,26 @@ var ts; if (match) { return { key: useCaseSensitiveFileNames ? match[0] : match[0].toLowerCase(), - flags: watchRecursivePattern.test(spec) ? 1 : 0 + flags: watchRecursivePattern.test(spec) ? 1 /* Recursive */ : 0 /* None */ }; } if (ts.isImplicitGlob(spec)) { - return { key: spec, flags: 1 }; + return { key: spec, flags: 1 /* Recursive */ }; } return undefined; } + /** + * Determines whether a literal or wildcard file has already been included that has a higher + * extension priority. + * + * @param file The path to the file. + * @param extensionPriority The priority of the extension. + * @param context The expansion context. + */ function hasFileWithHigherPriorityExtension(file, literalFiles, wildcardFiles, extensions, keyMapper) { var extensionPriority = ts.getExtensionPriority(file, extensions); var adjustedExtensionPriority = ts.adjustExtensionPriority(extensionPriority, extensions); - for (var i = 0; i < adjustedExtensionPriority; i++) { + for (var i = 0 /* Highest */; i < adjustedExtensionPriority; i++) { var higherPriorityExtension = extensions[i]; var higherPriorityPath = keyMapper(ts.changeExtension(file, higherPriorityExtension)); if (literalFiles.has(higherPriorityPath) || wildcardFiles.has(higherPriorityPath)) { @@ -20904,6 +24228,14 @@ var ts; } return false; } + /** + * Removes files included via wildcard expansion with a lower extension priority that have + * already been included. + * + * @param file The path to the file. + * @param extensionPriority The priority of the extension. + * @param context The expansion context. + */ function removeWildcardFilesWithLowerPriorityExtension(file, wildcardFiles, extensions, keyMapper) { var extensionPriority = ts.getExtensionPriority(file, extensions); var nextExtensionPriority = ts.getNextLowestExtensionPriority(extensionPriority, extensions); @@ -20913,12 +24245,17 @@ var ts; wildcardFiles.delete(lowerPriorityPath); } } + /** + * Produces a cleaned version of compiler options with personally identifiying info (aka, paths) removed. + * Also converts enum values back to strings. + */ + /* @internal */ function convertCompilerOptionsForTelemetry(opts) { var out = {}; for (var key in opts) { if (opts.hasOwnProperty(key)) { var type = getOptionFromName(key); - if (type !== undefined) { + if (type !== undefined) { // Ignore unknown options out[key] = getOptionValueWithEmptyStrings(opts[key], type); } } @@ -20928,11 +24265,11 @@ var ts; ts.convertCompilerOptionsForTelemetry = convertCompilerOptionsForTelemetry; function getOptionValueWithEmptyStrings(value, option) { switch (option.type) { - case "object": + case "object": // "paths". Can't get any useful information from the value since we blank out strings, so just return "". return ""; - case "string": + case "string": // Could be any arbitrary string -- use empty string instead. return ""; - case "number": + case "number": // Allow numbers, but be sure to check it's actually a number. return typeof value === "number" ? value : ""; case "boolean": return typeof value === "boolean" ? value : ""; @@ -20944,7 +24281,7 @@ var ts; if (optionEnumValue === value) { return optionStringValue; } - }); + }); // TODO: GH#18217 } } })(ts || (ts = {})); @@ -20954,6 +24291,7 @@ var ts; host.trace(ts.formatMessage.apply(undefined, arguments)); } ts.trace = trace; + /* @internal */ function isTraceEnabled(compilerOptions, host) { return !!compilerOptions.traceResolution && host.trace !== undefined; } @@ -20962,15 +24300,20 @@ var ts; return r && { path: r.path, extension: r.ext, packageId: packageId }; } function noPackageId(r) { - return withPackageId(undefined, r); + return withPackageId(/*packageId*/ undefined, r); } + /** + * Kinds of file that we are currently looking for. + * Typically there is one pass with Extensions.TypeScript, then a second pass with Extensions.JavaScript. + */ var Extensions; (function (Extensions) { Extensions[Extensions["TypeScript"] = 0] = "TypeScript"; Extensions[Extensions["JavaScript"] = 1] = "JavaScript"; Extensions[Extensions["Json"] = 2] = "Json"; - Extensions[Extensions["DtsOnly"] = 3] = "DtsOnly"; + Extensions[Extensions["DtsOnly"] = 3] = "DtsOnly"; /** Only '.d.ts' */ })(Extensions || (Extensions = {})); + /** Used with `Extensions.DtsOnly` to extract the path from TypeScript results. */ function resolvedTypeScriptOnly(resolved) { if (!resolved) { return undefined; @@ -20984,6 +24327,7 @@ var ts; failedLookupLocations: failedLookupLocations }; } + /** Reads from "main" or "types"/"typings" depending on `extensions`. */ function tryReadPackageJsonFields(readTypes, jsonContent, baseDirectory, state) { return readTypes ? tryReadFromField("typings") || tryReadFromField("types") : tryReadFromField("main"); function tryReadFromField(fieldName) { @@ -21007,6 +24351,7 @@ var ts; return path; } } + /* @internal */ function readJson(path, host) { try { var jsonText = host.readFile(path); @@ -21019,6 +24364,7 @@ var ts; return result.config; } catch (e) { + // gracefully handle if readFile fails or returns not JSON return {}; } } @@ -21039,9 +24385,14 @@ var ts; } } ts.getEffectiveTypeRoots = getEffectiveTypeRoots; + /** + * Returns the path to every node_modules/@types directory from some ancestor directory. + * Returns undefined if there are none. + */ function getDefaultTypeRoots(currentDirectory, host) { if (!host.directoryExists) { return [ts.combinePaths(currentDirectory, nodeModulesAtTypes)]; + // And if it doesn't exist, tough. } var typeRoots; ts.forEachAncestorDirectory(ts.normalizePath(currentDirectory), function (directory) { @@ -21054,6 +24405,11 @@ var ts; return typeRoots; } var nodeModulesAtTypes = ts.combinePaths("node_modules", "@types"); + /** + * @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. + * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups + * is assumed to be the same as root directory of the project. + */ function resolveTypeReferenceDirective(typeReferenceDirectiveName, containingFile, options, host) { var traceEnabled = isTraceEnabled(options, host); var moduleResolutionState = { compilerOptions: options, host: host, traceEnabled: traceEnabled }; @@ -21095,6 +24451,7 @@ var ts; } return { resolvedTypeReferenceDirective: resolvedTypeReferenceDirective, failedLookupLocations: failedLookupLocations }; function primaryLookup() { + // Check primary library paths if (typeRoots && typeRoots.length) { if (traceEnabled) { trace(host, ts.Diagnostics.Resolving_with_primary_search_path_0, typeRoots.join(", ")); @@ -21118,10 +24475,11 @@ var ts; function secondaryLookup() { var initialLocationForSecondaryLookup = containingFile && ts.getDirectoryPath(containingFile); if (initialLocationForSecondaryLookup !== undefined) { + // check secondary locations if (traceEnabled) { trace(host, ts.Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, initialLocationForSecondaryLookup); } - var result = loadModuleFromNodeModules(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, failedLookupLocations, moduleResolutionState, undefined); + var result = loadModuleFromNodeModules(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, failedLookupLocations, moduleResolutionState, /*cache*/ undefined); var resolvedFile = resolvedTypeScriptOnly(result && result.value); if (!resolvedFile && traceEnabled) { trace(host, ts.Diagnostics.Type_reference_directive_0_was_not_resolved, typeReferenceDirectiveName); @@ -21136,10 +24494,20 @@ var ts; } } ts.resolveTypeReferenceDirective = resolveTypeReferenceDirective; + /** + * Given a set of options, returns the set of type directive names + * that should be included for this program automatically. + * This list could either come from the config file, + * or from enumerating the types root + initial secondary types lookup location. + * More type directives might appear in the program later as a result of loading actual source files; + * this list is only the set of defaults that are implicitly included. + */ function getAutomaticTypeDirectiveNames(options, host) { + // Use explicit type list from tsconfig.json if (options.types) { return options.types; } + // Walk the primary type lookup locations var result = []; if (host.directoryExists && host.getDirectories) { var typeRoots = getEffectiveTypeRoots(options, host); @@ -21151,8 +24519,12 @@ var ts; var typeDirectivePath = _b[_a]; var normalized = ts.normalizePath(typeDirectivePath); var packageJsonPath = pathToPackageJson(ts.combinePaths(root, normalized)); + // `types-publisher` sometimes creates packages with `"typings": null` for packages that don't provide their own types. + // See `createNotNeededPackageJSON` in the types-publisher` repo. + // tslint:disable-next-line:no-null-keyword var isNotNeededPackage = host.fileExists(packageJsonPath) && readJson(packageJsonPath, host).typings === null; if (!isNotNeededPackage) { + // Return just the type directive names result.push(ts.getBaseFileName(normalized)); } } @@ -21167,6 +24539,7 @@ var ts; return createModuleResolutionCacheWithMaps(ts.createMap(), ts.createMap(), currentDirectory, getCanonicalFileName); } ts.createModuleResolutionCache = createModuleResolutionCache; + /*@internal*/ function createModuleResolutionCacheWithMaps(directoryToModuleNameMap, moduleNameToDirectoryMap, currentDirectory, getCanonicalFileName) { return { getOrCreateCacheForDirectory: getOrCreateCacheForDirectory, getOrCreateCacheForModuleName: getOrCreateCacheForModuleName }; function getOrCreateCacheForDirectory(directoryName) { @@ -21180,7 +24553,7 @@ var ts; } function getOrCreateCacheForModuleName(nonRelativeModuleName) { if (ts.isExternalModuleNameRelative(nonRelativeModuleName)) { - return undefined; + return undefined; // TODO: GH#18217 } var perModuleNameCache = moduleNameToDirectoryMap.get(nonRelativeModuleName); if (!perModuleNameCache) { @@ -21195,13 +24568,29 @@ var ts; function get(directory) { return directoryPathMap.get(ts.toPath(directory, currentDirectory, getCanonicalFileName)); } + /** + * At first this function add entry directory -> module resolution result to the table. + * Then it computes the set of parent folders for 'directory' that should have the same module resolution result + * and for every parent folder in set it adds entry: parent -> module resolution. . + * Lets say we first directory name: /a/b/c/d/e and resolution result is: /a/b/bar.ts. + * Set of parent folders that should have the same result will be: + * [ + * /a/b/c/d, /a/b/c, /a/b + * ] + * this means that request for module resolution from file in any of these folder will be immediately found in cache. + */ function set(directory, result) { var path = ts.toPath(directory, currentDirectory, getCanonicalFileName); + // if entry is already in cache do nothing if (directoryPathMap.has(path)) { return; } directoryPathMap.set(path, result); var resolvedFileName = result.resolvedModule && result.resolvedModule.resolvedFileName; + // find common prefix between directory and resolved file name + // this common prefix should be the shorted path that has the same resolution + // directory: /a/b/c/d/e + // resolvedFileName: /a/b/foo.d.ts var commonPrefix = getCommonPrefix(path, resolvedFileName); var current = path; while (true) { @@ -21221,10 +24610,12 @@ var ts; return undefined; } var resolutionDirectory = ts.toPath(ts.getDirectoryPath(resolution), currentDirectory, getCanonicalFileName); + // find first position where directory and resolution differs var i = 0; while (i < Math.min(directory.length, resolutionDirectory.length) && directory.charCodeAt(i) === resolutionDirectory.charCodeAt(i)) { i++; } + // find last directory separator before position i var sep = directory.lastIndexOf(ts.directorySeparator, i); if (sep < 0) { return undefined; @@ -21278,6 +24669,7 @@ var ts; } if (perFolderCache) { perFolderCache.set(moduleName, result); + // put result in per-module name cache var perModuleNameCache = cache.getOrCreateCacheForModuleName(moduleName); if (perModuleNameCache) { perModuleNameCache.set(containingDirectory, result); @@ -21295,6 +24687,66 @@ var ts; return result; } ts.resolveModuleName = resolveModuleName; + /** + * Any module resolution kind can be augmented with optional settings: 'baseUrl', 'paths' and 'rootDirs' - they are used to + * mitigate differences between design time structure of the project and its runtime counterpart so the same import name + * can be resolved successfully by TypeScript compiler and runtime module loader. + * If these settings are set then loading procedure will try to use them to resolve module name and it can of failure it will + * fallback to standard resolution routine. + * + * - baseUrl - this setting controls how non-relative module names are resolved. If this setting is specified then non-relative + * names will be resolved relative to baseUrl: i.e. if baseUrl is '/a/b' then candidate location to resolve module name 'c/d' will + * be '/a/b/c/d' + * - paths - this setting can only be used when baseUrl is specified. allows to tune how non-relative module names + * will be resolved based on the content of the module name. + * Structure of 'paths' compiler options + * 'paths': { + * pattern-1: [...substitutions], + * pattern-2: [...substitutions], + * ... + * pattern-n: [...substitutions] + * } + * Pattern here is a string that can contain zero or one '*' character. During module resolution module name will be matched against + * all patterns in the list. Matching for patterns that don't contain '*' means that module name must be equal to pattern respecting the case. + * If pattern contains '*' then to match pattern "*" module name must start with the and end with . + * denotes part of the module name between and . + * If module name can be matches with multiple patterns then pattern with the longest prefix will be picked. + * After selecting pattern we'll use list of substitutions to get candidate locations of the module and the try to load module + * from the candidate location. + * Substitution is a string that can contain zero or one '*'. To get candidate location from substitution we'll pick every + * substitution in the list and replace '*' with string. If candidate location is not rooted it + * will be converted to absolute using baseUrl. + * For example: + * baseUrl: /a/b/c + * "paths": { + * // match all module names + * "*": [ + * "*", // use matched name as is, + * // will be looked as /a/b/c/ + * + * "folder1/*" // substitution will convert matched name to 'folder1/', + * // since it is not rooted then final candidate location will be /a/b/c/folder1/ + * ], + * // match module names that start with 'components/' + * "components/*": [ "/root/components/*" ] // substitution will convert /components/folder1/ to '/root/components/folder1/', + * // it is rooted so it will be final candidate location + * } + * + * 'rootDirs' allows the project to be spreaded across multiple locations and resolve modules with relative names as if + * they were in the same location. For example lets say there are two files + * '/local/src/content/file1.ts' + * '/shared/components/contracts/src/content/protocols/file2.ts' + * After bundling content of '/shared/components/contracts/src' will be merged with '/local/src' so + * if file1 has the following import 'import {x} from "./protocols/file2"' it will be resolved successfully in runtime. + * 'rootDirs' provides the way to tell compiler that in order to get the whole project it should behave as if content of all + * root dirs were merged together. + * I.e. for the example above 'rootDirs' will have two entries: [ '/local/src', '/shared/components/contracts/src' ]. + * Compiler will first convert './protocols/file2' into absolute path relative to the location of containing file: + * '/local/src/content/protocols/file2' and try to load it - failure. + * Then it will search 'rootDirs' looking for a longest matching prefix of this absolute path and if such prefix is found - absolute path will + * be converted to a path relative to found rootDir entry './content/protocols/file2' (*). As a last step compiler will check all remaining + * entries in 'rootDirs', use them to build absolute path out of (*) and try to resolve module from this location. + */ function tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, loader, failedLookupLocations, state) { if (!ts.isExternalModuleNameRelative(moduleName)) { return tryLoadModuleUsingBaseUrl(extensions, moduleName, loader, failedLookupLocations, state); @@ -21315,6 +24767,9 @@ var ts; var matchedNormalizedPrefix; for (var _i = 0, _a = state.compilerOptions.rootDirs; _i < _a.length; _i++) { var rootDir = _a[_i]; + // rootDirs are expected to be absolute + // in case of tsconfig.json this will happen automatically - compiler will expand relative names + // using location of tsconfig.json as base location var normalizedRoot = ts.normalizePath(rootDir); if (!ts.endsWith(normalizedRoot, ts.directorySeparator)) { normalizedRoot += ts.directorySeparator; @@ -21334,6 +24789,7 @@ var ts; trace(state.host, ts.Diagnostics.Longest_matching_prefix_for_0_is_1, candidate, matchedNormalizedPrefix); } var suffix = candidate.substr(matchedNormalizedPrefix.length); + // first - try to load from a initial location if (state.traceEnabled) { trace(state.host, ts.Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, matchedNormalizedPrefix, candidate); } @@ -21344,9 +24800,11 @@ var ts; if (state.traceEnabled) { trace(state.host, ts.Diagnostics.Trying_other_entries_in_rootDirs); } + // then try to resolve using remaining entries in rootDirs for (var _b = 0, _c = state.compilerOptions.rootDirs; _b < _c.length; _b++) { var rootDir = _c[_b]; if (rootDir === matchedRootDir) { + // skip the initially matched entry continue; } var candidate_1 = ts.combinePaths(ts.normalizePath(rootDir), suffix); @@ -21372,6 +24830,7 @@ var ts; if (state.traceEnabled) { trace(state.host, ts.Diagnostics.baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1, state.compilerOptions.baseUrl, moduleName); } + // string is for exact match var matchedPattern; if (state.compilerOptions.paths) { if (state.traceEnabled) { @@ -21391,9 +24850,10 @@ var ts; if (state.traceEnabled) { trace(state.host, ts.Diagnostics.Trying_substitution_0_candidate_module_location_Colon_1, subst, path); } + // A path mapping may have an extension, in contrast to an import, which should omit it. var extension = ts.tryGetExtensionFromPath(candidate); if (extension !== undefined) { - var path_1 = tryFile(candidate, failedLookupLocations, false, state); + var path_1 = tryFile(candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state); if (path_1 !== undefined) { return noPackageId({ path: path_1, ext: extension }); } @@ -21410,11 +24870,17 @@ var ts; } } function nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host, cache) { - return nodeModuleNameResolverWorker(moduleName, ts.getDirectoryPath(containingFile), compilerOptions, host, cache, false); + return nodeModuleNameResolverWorker(moduleName, ts.getDirectoryPath(containingFile), compilerOptions, host, cache, /*jsOnly*/ false); } ts.nodeModuleNameResolver = nodeModuleNameResolver; + /** + * Expose resolution logic to allow us to use Node module resolution logic from arbitrary locations. + * No way to do this with `require()`: https://github.com/nodejs/node/issues/5963 + * Throws an error if the module can't be resolved. + */ + /* @internal */ function resolveJavaScriptModule(moduleName, initialDir, host) { - var _a = nodeModuleNameResolverWorker(moduleName, initialDir, { moduleResolution: ts.ModuleResolutionKind.NodeJs, allowJs: true }, host, undefined, true), resolvedModule = _a.resolvedModule, failedLookupLocations = _a.failedLookupLocations; + var _a = nodeModuleNameResolverWorker(moduleName, initialDir, { moduleResolution: ts.ModuleResolutionKind.NodeJs, allowJs: true }, host, /*cache*/ undefined, /*jsOnly*/ true), resolvedModule = _a.resolvedModule, failedLookupLocations = _a.failedLookupLocations; if (!resolvedModule) { throw new Error("Could not resolve JS module '" + moduleName + "' starting at '" + initialDir + "'. Looked in: " + failedLookupLocations.join(", ")); } @@ -21436,7 +24902,7 @@ var ts; } return { resolvedModule: undefined, failedLookupLocations: failedLookupLocations }; function tryResolve(extensions) { - var loader = function (extensions, candidate, failedLookupLocations, onlyRecordFailures, state) { return nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, onlyRecordFailures, state, true); }; + var loader = function (extensions, candidate, failedLookupLocations, onlyRecordFailures, state) { return nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, onlyRecordFailures, state, /*considerPackageJson*/ true); }; var resolved = tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, loader, failedLookupLocations, state); if (resolved) { return toSearchResult({ resolved: resolved, isExternalLibraryImport: false }); @@ -21458,11 +24924,13 @@ var ts; } resolvedValue = __assign({}, resolvedValue, { path: path }); } + // For node_modules lookups, get the real path so that multiple accesses to an `npm link`-ed module do not create duplicate files. return { value: resolvedValue && { resolved: resolvedValue, originalPath: originalPath, isExternalLibraryImport: true } }; } else { var _a = ts.normalizePathAndParts(ts.combinePaths(containingDirectory, moduleName)), candidate = _a.path, parts = _a.parts; - var resolved_2 = nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, false, state, true); + var resolved_2 = nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state, /*considerPackageJson*/ true); + // Treat explicit "node_modules" import as an external library import. return resolved_2 && toSearchResult({ resolved: resolved_2, isExternalLibraryImport: ts.contains(parts, "node_modules") }); } } @@ -21475,7 +24943,7 @@ var ts; if (traceEnabled) { trace(host, ts.Diagnostics.Resolving_real_path_for_0_result_1, path, real); } - ts.Debug.assert(host.fileExists(real), path + " linked to nonexistent file " + real); + ts.Debug.assert(host.fileExists(real), path + " linked to nonexistent file " + real); // tslint:disable-line return real; } function nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, onlyRecordFailures, state, considerPackageJson) { @@ -21495,7 +24963,7 @@ var ts; var resolvedFromFile = loadModuleFromFile(extensions, candidate, failedLookupLocations, onlyRecordFailures, state); if (resolvedFromFile) { var nm = considerPackageJson ? parseNodeModuleFromPath(resolvedFromFile) : undefined; - var packageId = nm && getPackageJsonInfo(nm.packageDirectory, nm.subModuleName, failedLookupLocations, false, state).packageId; + var packageId = nm && getPackageJsonInfo(nm.packageDirectory, nm.subModuleName, failedLookupLocations, /*onlyRecordFailures*/ false, state).packageId; return withPackageId(packageId, resolvedFromFile); } } @@ -21511,6 +24979,17 @@ var ts; return loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocations, onlyRecordFailures, state, considerPackageJson); } var nodeModulesPathPart = "/node_modules/"; + /** + * This will be called on the successfully resolved path from `loadModuleFromFile`. + * (Not neeeded for `loadModuleFromNodeModules` as that looks up the `package.json` as part of resolution.) + * + * packageDirectory is the directory of the package itself. + * subModuleName is the path within the package. + * For `blah/node_modules/foo/index.d.ts` this is { packageDirectory: "foo", subModuleName: "index.d.ts" }. (Part before "/node_modules/" is ignored.) + * For `/node_modules/foo/bar.d.ts` this is { packageDirectory: "foo", subModuleName": "bar/index.d.ts" }. + * For `/node_modules/@types/foo/bar/index.d.ts` this is { packageDirectory: "@types/foo", subModuleName: "bar/index.d.ts" }. + * For `/node_modules/foo/bar/index.d.ts` this is { packageDirectory: "foo", subModuleName": "bar/index.d.ts" }. + */ function parseNodeModuleFromPath(resolved) { var path = ts.normalizePath(resolved.path); var idx = path.lastIndexOf(nodeModulesPathPart); @@ -21519,11 +24998,11 @@ var ts; } var indexAfterNodeModules = idx + nodeModulesPathPart.length; var indexAfterPackageName = moveToNextDirectorySeparatorIfAvailable(path, indexAfterNodeModules); - if (path.charCodeAt(indexAfterNodeModules) === 64) { + if (path.charCodeAt(indexAfterNodeModules) === 64 /* at */) { indexAfterPackageName = moveToNextDirectorySeparatorIfAvailable(path, indexAfterPackageName); } var packageDirectory = path.slice(0, indexAfterPackageName); - var subModuleName = ts.removeExtension(path.slice(indexAfterPackageName + 1), resolved.ext) + ".d.ts"; + var subModuleName = ts.removeExtension(path.slice(indexAfterPackageName + 1), resolved.ext) + ".d.ts" /* Dts */; return { packageDirectory: packageDirectory, subModuleName: subModuleName }; } function moveToNextDirectorySeparatorIfAvailable(path, prevSeparatorIndex) { @@ -21542,22 +25021,31 @@ var ts; } return path + "/index.d.ts"; } + /* @internal */ function directoryProbablyExists(directoryName, host) { + // if host does not support 'directoryExists' assume that directory will exist return !host.directoryExists || host.directoryExists(directoryName); } ts.directoryProbablyExists = directoryProbablyExists; function loadModuleFromFileNoPackageId(extensions, candidate, failedLookupLocations, onlyRecordFailures, state) { return noPackageId(loadModuleFromFile(extensions, candidate, failedLookupLocations, onlyRecordFailures, state)); } + /** + * @param {boolean} onlyRecordFailures - if true then function won't try to actually load files but instead record all attempts as failures. This flag is necessary + * in cases when we know upfront that all load attempts will fail (because containing folder does not exists) however we still need to record all failed lookup locations. + */ function loadModuleFromFile(extensions, candidate, failedLookupLocations, onlyRecordFailures, state) { if (extensions === Extensions.Json) { - var extensionLess = ts.tryRemoveExtension(candidate, ".json"); + var extensionLess = ts.tryRemoveExtension(candidate, ".json" /* Json */); return extensionLess === undefined ? undefined : tryAddingExtensions(extensionLess, extensions, failedLookupLocations, onlyRecordFailures, state); } + // First, try adding an extension. An import of "foo" could be matched by a file "foo.ts", or "foo.js" by "foo.js.ts" var resolvedByAddingExtension = tryAddingExtensions(candidate, extensions, failedLookupLocations, onlyRecordFailures, state); if (resolvedByAddingExtension) { return resolvedByAddingExtension; } + // If that didn't work, try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one; + // e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts" if (ts.hasJavaScriptFileExtension(candidate)) { var extensionless = ts.removeFileExtension(candidate); if (state.traceEnabled) { @@ -21567,8 +25055,10 @@ var ts; return tryAddingExtensions(extensionless, extensions, failedLookupLocations, onlyRecordFailures, state); } } + /** Try to return an existing file that adds one of the `extensions` to `candidate`. */ function tryAddingExtensions(candidate, extensions, failedLookupLocations, onlyRecordFailures, state) { if (!onlyRecordFailures) { + // check if containing folder exists - if it doesn't then just record failures for all supported extensions without disk probing var directory = ts.getDirectoryPath(candidate); if (directory) { onlyRecordFailures = !directoryProbablyExists(directory, state.host); @@ -21576,19 +25066,20 @@ var ts; } switch (extensions) { case Extensions.DtsOnly: - return tryExtension(".d.ts"); + return tryExtension(".d.ts" /* Dts */); case Extensions.TypeScript: - return tryExtension(".ts") || tryExtension(".tsx") || tryExtension(".d.ts"); + return tryExtension(".ts" /* Ts */) || tryExtension(".tsx" /* Tsx */) || tryExtension(".d.ts" /* Dts */); case Extensions.JavaScript: - return tryExtension(".js") || tryExtension(".jsx"); + return tryExtension(".js" /* Js */) || tryExtension(".jsx" /* Jsx */); case Extensions.Json: - return tryExtension(".json"); + return tryExtension(".json" /* Json */); } function tryExtension(ext) { var path = tryFile(candidate + ext, failedLookupLocations, onlyRecordFailures, state); return path === undefined ? undefined : { path: path, ext: ext }; } } + /** Return the file if it exists. */ function tryFile(fileName, failedLookupLocations, onlyRecordFailures, state) { if (!onlyRecordFailures) { if (state.host.fileExists(fileName)) { @@ -21627,25 +25118,25 @@ var ts; var packageJsonPath = pathToPackageJson(nodeModuleDirectory); if (directoryExists && host.fileExists(packageJsonPath)) { var packageJsonContent = readJson(packageJsonPath, host); - if (subModuleName === "") { - var path = tryReadPackageJsonFields(true, packageJsonContent, nodeModuleDirectory, state); + if (subModuleName === "") { // looking up the root - need to handle types/typings/main redirects for subModuleName + var path = tryReadPackageJsonFields(/*readTypes*/ true, packageJsonContent, nodeModuleDirectory, state); if (typeof path === "string") { subModuleName = addExtensionAndIndex(path.substring(nodeModuleDirectory.length + 1)); } else { - var jsPath = tryReadPackageJsonFields(false, packageJsonContent, nodeModuleDirectory, state); + var jsPath = tryReadPackageJsonFields(/*readTypes*/ false, packageJsonContent, nodeModuleDirectory, state); if (typeof jsPath === "string" && jsPath.length > nodeModuleDirectory.length) { var potentialSubModule_1 = jsPath.substring(nodeModuleDirectory.length + 1); subModuleName = (ts.forEach(ts.supportedJavascriptExtensions, function (extension) { return ts.tryRemoveExtension(potentialSubModule_1, extension); - }) || potentialSubModule_1) + ".d.ts"; + }) || potentialSubModule_1) + ".d.ts" /* Dts */; } else { subModuleName = "index.d.ts"; } } } - if (!ts.endsWith(subModuleName, ".d.ts")) { + if (!ts.endsWith(subModuleName, ".d.ts" /* Dts */)) { subModuleName = addExtensionAndIndex(subModuleName); } var packageId = typeof packageJsonContent.name === "string" && typeof packageJsonContent.version === "string" @@ -21665,6 +25156,7 @@ var ts; if (directoryExists && traceEnabled) { trace(host, ts.Diagnostics.File_0_does_not_exist, packageJsonPath); } + // record package json as one of failed lookup locations - in the future if this file will appear it will invalidate resolution results failedLookupLocations.push(packageJsonPath); return { found: false, packageJsonContent: undefined, packageId: undefined }; } @@ -21673,7 +25165,8 @@ var ts; var file = tryReadPackageJsonFields(extensions !== Extensions.JavaScript && extensions !== Extensions.Json, jsonContent, candidate, state); if (!file) { if (extensions === Extensions.TypeScript) { - file = tryReadPackageJsonFields(false, jsonContent, candidate, state); + // When resolving typescript modules, try resolving using main field as well + file = tryReadPackageJsonFields(/*readTypes*/ false, jsonContent, candidate, state); if (!file) { return undefined; } @@ -21693,27 +25186,32 @@ var ts; trace(state.host, ts.Diagnostics.File_0_has_an_unsupported_extension_so_skipping_it, fromFile); } } + // Even if extensions is DtsOnly, we can still look up a .ts file as a result of package.json "types" var nextExtensions = extensions === Extensions.DtsOnly ? Extensions.TypeScript : extensions; - var result = nodeLoadModuleByRelativeName(nextExtensions, file, failedLookupLocations, onlyRecordFailures, state, false); + // Don't do package.json lookup recursively, because Node.js' package lookup doesn't. + var result = nodeLoadModuleByRelativeName(nextExtensions, file, failedLookupLocations, onlyRecordFailures, state, /*considerPackageJson*/ false); if (result) { + // It won't have a `packageId` set, because we disabled `considerPackageJson`. ts.Debug.assert(result.packageId === undefined); return { path: result.path, ext: result.extension }; } } + /** Resolve from an arbitrarily specified file. Return `undefined` if it has an unsupported extension. */ function resolvedIfExtensionMatches(extensions, path) { var ext = ts.tryGetExtensionFromPath(path); return ext !== undefined && extensionIsOk(extensions, ext) ? { path: path, ext: ext } : undefined; } + /** True if `extension` is one of the supported `extensions`. */ function extensionIsOk(extensions, extension) { switch (extensions) { case Extensions.JavaScript: - return extension === ".js" || extension === ".jsx"; + return extension === ".js" /* Js */ || extension === ".jsx" /* Jsx */; case Extensions.Json: - return extension === ".json"; + return extension === ".json" /* Json */; case Extensions.TypeScript: - return extension === ".ts" || extension === ".tsx" || extension === ".d.ts"; + return extension === ".ts" /* Ts */ || extension === ".tsx" /* Tsx */ || extension === ".d.ts" /* Dts */; case Extensions.DtsOnly: - return extension === ".d.ts"; + return extension === ".d.ts" /* Dts */; } } function pathToPackageJson(directory) { @@ -21721,16 +25219,18 @@ var ts; } function loadModuleFromNodeModulesFolder(extensions, moduleName, nodeModulesFolder, nodeModulesFolderExists, failedLookupLocations, state) { var candidate = ts.normalizePath(ts.combinePaths(nodeModulesFolder, moduleName)); + // First look for a nested package.json, as in `node_modules/foo/bar/package.json`. var packageJsonContent; var packageId; - var packageInfo = getPackageJsonInfo(candidate, "", failedLookupLocations, !nodeModulesFolderExists, state); + var packageInfo = getPackageJsonInfo(candidate, "", failedLookupLocations, /*onlyRecordFailures*/ !nodeModulesFolderExists, state); if (packageInfo.found) { (packageJsonContent = packageInfo.packageJsonContent, packageId = packageInfo.packageId); } else { var _a = getPackageName(moduleName), packageName = _a.packageName, rest = _a.rest; - if (rest !== "") { + if (rest !== "") { // If "rest" is empty, we just did this search above. var packageRootPath = ts.combinePaths(nodeModulesFolder, packageName); + // Don't use a "types" or "main" from here because we're not loading the root, but a subdirectory -- just here for the packageId. packageId = getPackageJsonInfo(packageRootPath, rest, failedLookupLocations, !nodeModulesFolderExists, state).packageId; } } @@ -21738,6 +25238,7 @@ var ts; loadNodeModuleFromDirectoryWorker(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state, packageJsonContent); return withPackageId(packageId, pathAndExtension); } + /* @internal */ function getPackageName(moduleName) { var idx = moduleName.indexOf(ts.directorySeparator); if (moduleName[0] === "@") { @@ -21747,10 +25248,11 @@ var ts; } ts.getPackageName = getPackageName; function loadModuleFromNodeModules(extensions, moduleName, directory, failedLookupLocations, state, cache) { - return loadModuleFromNodeModulesWorker(extensions, moduleName, directory, failedLookupLocations, state, false, cache); + return loadModuleFromNodeModulesWorker(extensions, moduleName, directory, failedLookupLocations, state, /*typesOnly*/ false, cache); } function loadModuleFromNodeModulesAtTypes(moduleName, directory, failedLookupLocations, state) { - return loadModuleFromNodeModulesWorker(Extensions.DtsOnly, moduleName, directory, failedLookupLocations, state, true, undefined); + // Extensions parameter here doesn't actually matter, because typesOnly ensures we're just doing @types lookup, which is always DtsOnly. + return loadModuleFromNodeModulesWorker(Extensions.DtsOnly, moduleName, directory, failedLookupLocations, state, /*typesOnly*/ true, /*cache*/ undefined); } function loadModuleFromNodeModulesWorker(extensions, moduleName, directory, failedLookupLocations, state, typesOnly, cache) { var perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName); @@ -21764,6 +25266,7 @@ var ts; } }); } + /** Load a module from a single node_modules directory, but not from any ancestors' node_modules directories. */ function loadModuleFromNodeModulesOneLevel(extensions, moduleName, directory, failedLookupLocations, state, typesOnly) { if (typesOnly === void 0) { typesOnly = false; } var nodeModulesFolder = ts.combinePaths(directory, "node_modules"); @@ -21787,7 +25290,9 @@ var ts; return loadModuleFromNodeModulesFolder(Extensions.DtsOnly, mangleScopedPackage(moduleName, state), nodeModulesAtTypes_1, nodeModulesAtTypesExists, failedLookupLocations, state); } } + /** Double underscores are used in DefinitelyTyped to delimit scoped packages. */ var mangledScopedPackageSeparator = "__"; + /** For a scoped package, we must look in `@types/foo__bar` instead of `@types/@foo/bar`. */ function mangleScopedPackage(packageName, state) { var mangled = getMangledNameForScopedPackage(packageName); if (state.traceEnabled && mangled !== packageName) { @@ -21795,20 +25300,23 @@ var ts; } return mangled; } + /* @internal */ function getTypesPackageName(packageName) { return "@types/" + getMangledNameForScopedPackage(packageName); } ts.getTypesPackageName = getTypesPackageName; + /* @internal */ function getMangledNameForScopedPackage(packageName) { if (ts.startsWith(packageName, "@")) { var replaceSlash = packageName.replace(ts.directorySeparator, mangledScopedPackageSeparator); if (replaceSlash !== packageName) { - return replaceSlash.slice(1); + return replaceSlash.slice(1); // Take off the "@" } } return packageName; } ts.getMangledNameForScopedPackage = getMangledNameForScopedPackage; + /* @internal */ function getPackageNameFromAtTypesDirectory(mangledName) { var withoutAtTypePrefix = ts.removePrefix(mangledName, "@types/"); if (withoutAtTypePrefix !== mangledName) { @@ -21817,6 +25325,7 @@ var ts; return mangledName; } ts.getPackageNameFromAtTypesDirectory = getPackageNameFromAtTypesDirectory; + /* @internal */ function getUnmangledNameForScopedPackage(typesPackageName) { return ts.stringContains(typesPackageName, mangledScopedPackageSeparator) ? "@" + typesPackageName.replace(mangledScopedPackageSeparator, ts.directorySeparator) : @@ -21839,7 +25348,8 @@ var ts; var failedLookupLocations = []; var containingDirectory = ts.getDirectoryPath(containingFile); var resolved = tryResolve(Extensions.TypeScript) || tryResolve(Extensions.JavaScript); - return createResolvedModuleWithFailedLookupLocations(resolved && resolved.value, undefined, false, failedLookupLocations); + // No originalPath because classic resolution doesn't resolve realPath + return createResolvedModuleWithFailedLookupLocations(resolved && resolved.value, /*originalPath*/ undefined, /*isExternalLibraryImport*/ false, failedLookupLocations); function tryResolve(extensions) { var resolvedUsingSettings = tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, loadModuleFromFileNoPackageId, failedLookupLocations, state); if (resolvedUsingSettings) { @@ -21847,28 +25357,35 @@ var ts; } var perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName); if (!ts.isExternalModuleNameRelative(moduleName)) { + // Climb up parent directories looking for a module. var resolved_3 = ts.forEachAncestorDirectory(containingDirectory, function (directory) { var resolutionFromCache = tryFindNonRelativeModuleNameInCache(perModuleNameCache, moduleName, directory, traceEnabled, host, failedLookupLocations); if (resolutionFromCache) { return resolutionFromCache; } var searchName = ts.normalizePath(ts.combinePaths(directory, moduleName)); - return toSearchResult(loadModuleFromFileNoPackageId(extensions, searchName, failedLookupLocations, false, state)); + return toSearchResult(loadModuleFromFileNoPackageId(extensions, searchName, failedLookupLocations, /*onlyRecordFailures*/ false, state)); }); if (resolved_3) { return resolved_3; } if (extensions === Extensions.TypeScript) { + // If we didn't find the file normally, look it up in @types. return loadModuleFromNodeModulesAtTypes(moduleName, containingDirectory, failedLookupLocations, state); } } else { var candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); - return toSearchResult(loadModuleFromFileNoPackageId(extensions, candidate, failedLookupLocations, false, state)); + return toSearchResult(loadModuleFromFileNoPackageId(extensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state)); } } } ts.classicNameResolver = classicNameResolver; + /** + * LSHost may load a module from a global cache of typings. + * This is the minumum code needed to expose that functionality; the rest is in LSHost. + */ + /* @internal */ function loadModuleFromGlobalCache(moduleName, projectName, compilerOptions, host, globalCache) { var traceEnabled = isTraceEnabled(compilerOptions, host); if (traceEnabled) { @@ -21877,13 +25394,18 @@ var ts; var state = { compilerOptions: compilerOptions, host: host, traceEnabled: traceEnabled }; var failedLookupLocations = []; var resolved = loadModuleFromNodeModulesOneLevel(Extensions.DtsOnly, moduleName, globalCache, failedLookupLocations, state); - return createResolvedModuleWithFailedLookupLocations(resolved, undefined, true, failedLookupLocations); + return createResolvedModuleWithFailedLookupLocations(resolved, /*originalPath*/ undefined, /*isExternalLibraryImport*/ true, failedLookupLocations); } ts.loadModuleFromGlobalCache = loadModuleFromGlobalCache; + /** + * Wraps value to SearchResult. + * @returns undefined if value is undefined or { value } otherwise + */ function toSearchResult(value) { return value !== undefined ? { value: value } : undefined; } })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var ModuleInstanceState; @@ -21893,37 +25415,45 @@ var ts; ModuleInstanceState[ModuleInstanceState["ConstEnumOnly"] = 2] = "ConstEnumOnly"; })(ModuleInstanceState = ts.ModuleInstanceState || (ts.ModuleInstanceState = {})); function getModuleInstanceState(node) { - return node.body ? getModuleInstanceStateWorker(node.body) : 1; + return node.body ? getModuleInstanceStateWorker(node.body) : 1 /* Instantiated */; } ts.getModuleInstanceState = getModuleInstanceState; function getModuleInstanceStateWorker(node) { + // A module is uninstantiated if it contains only switch (node.kind) { - case 236: - case 237: - return 0; - case 238: + // 1. interface declarations, type alias declarations + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: + return 0 /* NonInstantiated */; + // 2. const enum declarations + case 238 /* EnumDeclaration */: if (ts.isConst(node)) { - return 2; + return 2 /* ConstEnumOnly */; } break; - case 244: - case 243: - if (!(ts.hasModifier(node, 1))) { - return 0; + // 3. non-exported import declarations + case 244 /* ImportDeclaration */: + case 243 /* ImportEqualsDeclaration */: + if (!(ts.hasModifier(node, 1 /* Export */))) { + return 0 /* NonInstantiated */; } break; - case 240: { - var state_1 = 0; + // 4. other uninstantiated module declarations. + case 240 /* ModuleBlock */: { + var state_1 = 0 /* NonInstantiated */; ts.forEachChild(node, function (n) { var childState = getModuleInstanceStateWorker(n); switch (childState) { - case 0: + case 0 /* NonInstantiated */: + // child is non-instantiated - continue searching return; - case 2: - state_1 = 2; + case 2 /* ConstEnumOnly */: + // child is const enum only - record state and continue searching + state_1 = 2 /* ConstEnumOnly */; return; - case 1: - state_1 = 1; + case 1 /* Instantiated */: + // child is instantiated - record state and stop + state_1 = 1 /* Instantiated */; return true; default: ts.Debug.assertNever(childState); @@ -21931,20 +25461,34 @@ var ts; }); return state_1; } - case 239: + case 239 /* ModuleDeclaration */: return getModuleInstanceState(node); - case 71: + case 71 /* Identifier */: + // Only jsdoc typedef definition can exist in jsdoc namespace, and it should + // be considered the same as type alias if (node.isInJSDocNamespace) { - return 0; + return 0 /* NonInstantiated */; } } - return 1; + return 1 /* Instantiated */; } var ContainerFlags; (function (ContainerFlags) { + // The current node is not a container, and no container manipulation should happen before + // recursing into it. ContainerFlags[ContainerFlags["None"] = 0] = "None"; + // The current node is a container. It should be set as the current container (and block- + // container) before recursing into it. The current node does not have locals. Examples: + // + // Classes, ObjectLiterals, TypeLiterals, Interfaces... ContainerFlags[ContainerFlags["IsContainer"] = 1] = "IsContainer"; + // The current node is a block-scoped-container. It should be set as the current block- + // container before recursing into it. Examples: + // + // Blocks (when not parented by functions), Catch clauses, For/For-in/For-of statements... ContainerFlags[ContainerFlags["IsBlockScopedContainer"] = 2] = "IsBlockScopedContainer"; + // The current node is the container of a control flow path. The current control flow should + // be saved and restored, and a new control flow initialized within the container. ContainerFlags[ContainerFlags["IsControlFlowContainer"] = 4] = "IsControlFlowContainer"; ContainerFlags[ContainerFlags["IsFunctionLike"] = 8] = "IsFunctionLike"; ContainerFlags[ContainerFlags["IsFunctionExpression"] = 16] = "IsFunctionExpression"; @@ -21966,11 +25510,12 @@ var ts; var languageVersion; var parent; var container; - var thisParentContainer; + var thisParentContainer; // Container one level up var blockScopeContainer; var lastContainer; var delayedTypeAliases; var seenThisKeyword; + // state used by control flow analysis var currentFlow; var currentBreakTarget; var currentContinueTarget; @@ -21980,15 +25525,26 @@ var ts; var preSwitchCaseFlow; var activeLabels; var hasExplicitReturn; + // state used for emit helpers var emitFlags; + // If this file is an external module, then it is automatically in strict-mode according to + // ES6. If it is not an external module, then we'll determine if it is in strict mode or + // not depending on if we see "use strict" in certain places or if we hit a class/namespace + // or if compiler options contain alwaysStrict. var inStrictMode; var symbolCount = 0; - var Symbol; + var Symbol; // tslint:disable-line variable-name var classifiableNames; - var unreachableFlow = { flags: 1 }; - var reportedUnreachableFlow = { flags: 1 }; - var subtreeTransformFlags = 0; + var unreachableFlow = { flags: 1 /* Unreachable */ }; + var reportedUnreachableFlow = { flags: 1 /* Unreachable */ }; + // state used to aggregate transform flags during bind. + var subtreeTransformFlags = 0 /* None */; var skipTransformFlagAggregation; + /** + * Inside the binder, we may create a diagnostic for an as-yet unbound node (with potentially no parent pointers, implying no accessible source file) + * If so, the node _must_ be in the current file (as that's the only way anything could have traversed to it to yield it as the error node) + * This version of `createDiagnosticForNode` uses the binder's context to account for this, and always yields correct diagnostics even in these situations. + */ function createDiagnosticForNode(node, message, arg0, arg1, arg2) { return ts.createDiagnosticForNodeInSourceFile(ts.getSourceFileOfNode(node) || file, node, message, arg0, arg1, arg2); } @@ -22025,12 +25581,13 @@ var ts; currentFalseTarget = undefined; activeLabels = undefined; hasExplicitReturn = false; - emitFlags = 0; - subtreeTransformFlags = 0; + emitFlags = 0 /* None */; + subtreeTransformFlags = 0 /* None */; } return bindSourceFile; function bindInStrictMode(file, opts) { if (ts.getStrictOptionValue(opts, "alwaysStrict") && !file.isDeclarationFile) { + // bind in strict mode source files with alwaysStrict option return true; } else { @@ -22045,23 +25602,26 @@ var ts; symbol.flags |= symbolFlags; node.symbol = symbol; symbol.declarations = ts.append(symbol.declarations, node); - if (symbolFlags & 1955 && !symbol.exports) { + if (symbolFlags & 1955 /* HasExports */ && !symbol.exports) { symbol.exports = ts.createSymbolTable(); } - if (symbolFlags & 6240 && !symbol.members) { + if (symbolFlags & 6240 /* HasMembers */ && !symbol.members) { symbol.members = ts.createSymbolTable(); } - if (symbolFlags & 67216319) { + if (symbolFlags & 67216319 /* Value */) { var valueDeclaration = symbol.valueDeclaration; if (!valueDeclaration || (valueDeclaration.kind !== node.kind && ts.isEffectiveModuleDeclaration(valueDeclaration))) { + // other kinds of value declarations take precedence over modules symbol.valueDeclaration = node; } } } + // Should not be called on a declaration with a computed property name, + // unless it is a well known Symbol. function getDeclarationName(node) { - if (node.kind === 249) { - return node.isExportEquals ? "export=" : "default"; + if (node.kind === 249 /* ExportAssignment */) { + return node.isExportEquals ? "export=" /* ExportEquals */ : "default" /* Default */; } var name = ts.getNameOfDeclaration(node); if (name) { @@ -22069,8 +25629,9 @@ var ts; var moduleName = ts.getTextOfIdentifierOrLiteral(name); return (ts.isGlobalScopeAugmentation(node) ? "__global" : "\"" + moduleName + "\""); } - if (name.kind === 147) { + if (name.kind === 147 /* ComputedPropertyName */) { var nameExpression = name.expression; + // treat computed property names where expression is string/numeric literal as just string/numeric literal if (ts.isStringOrNumericLiteral(nameExpression)) { return ts.escapeLeadingUnderscores(nameExpression.text); } @@ -22080,81 +25641,130 @@ var ts; return ts.isPropertyNameLiteral(name) ? ts.getEscapedTextOfIdentifierOrLiteral(name) : undefined; } switch (node.kind) { - case 155: - return "__constructor"; - case 163: - case 158: - case 288: - return "__call"; - case 164: - case 159: - return "__new"; - case 160: - return "__index"; - case 250: - return "__export"; - case 274: - return "export="; - case 200: - if (ts.getSpecialPropertyAssignmentKind(node) === 2) { - return "export="; + case 155 /* Constructor */: + return "__constructor" /* Constructor */; + case 163 /* FunctionType */: + case 158 /* CallSignature */: + case 288 /* JSDocSignature */: + return "__call" /* Call */; + case 164 /* ConstructorType */: + case 159 /* ConstructSignature */: + return "__new" /* New */; + case 160 /* IndexSignature */: + return "__index" /* Index */; + case 250 /* ExportDeclaration */: + return "__export" /* ExportStar */; + case 274 /* SourceFile */: + // json file should behave as + // module.exports = ... + return "export=" /* ExportEquals */; + case 200 /* BinaryExpression */: + if (ts.getSpecialPropertyAssignmentKind(node) === 2 /* ModuleExports */) { + // module.exports = ... + return "export=" /* ExportEquals */; } ts.Debug.fail("Unknown binary declaration kind"); break; - case 284: - return (ts.isJSDocConstructSignature(node) ? "__new" : "__call"); - case 149: - ts.Debug.assert(node.parent.kind === 284, "Impossible parameter parent kind", function () { return "parent is: " + (ts.SyntaxKind ? ts.SyntaxKind[node.parent.kind] : node.parent.kind) + ", expected JSDocFunctionType"; }); + case 284 /* JSDocFunctionType */: + return (ts.isJSDocConstructSignature(node) ? "__new" /* New */ : "__call" /* Call */); + case 149 /* Parameter */: + // Parameters with names are handled at the top of this function. Parameters + // without names can only come from JSDocFunctionTypes. + ts.Debug.assert(node.parent.kind === 284 /* JSDocFunctionType */, "Impossible parameter parent kind", function () { return "parent is: " + (ts.SyntaxKind ? ts.SyntaxKind[node.parent.kind] : node.parent.kind) + ", expected JSDocFunctionType"; }); var functionType = node.parent; var index = functionType.parameters.indexOf(node); return "arg" + index; } } function getDisplayName(node) { - return ts.isNamedDeclaration(node) ? ts.declarationNameToString(node.name) : ts.unescapeLeadingUnderscores(getDeclarationName(node)); + return ts.isNamedDeclaration(node) ? ts.declarationNameToString(node.name) : ts.unescapeLeadingUnderscores(getDeclarationName(node)); // TODO: GH#18217 } + /** + * Declares a Symbol for the node and adds it to symbols. Reports errors for conflicting identifier names. + * @param symbolTable - The symbol table which node will be added to. + * @param parent - node's parent declaration. + * @param node - The declaration to be added to the symbol table + * @param includes - The SymbolFlags that node has in addition to its declaration type (eg: export, ambient, etc.) + * @param excludes - The flags which node cannot be declared alongside in a symbol table. Used to report forbidden declarations. + */ function declareSymbol(symbolTable, parent, node, includes, excludes, isReplaceableByMethod) { ts.Debug.assert(!ts.hasDynamicName(node)); - var isDefaultExport = ts.hasModifier(node, 512); - var name = isDefaultExport && parent ? "default" : getDeclarationName(node); + var isDefaultExport = ts.hasModifier(node, 512 /* Default */); + // The exported symbol for an export default function/class node is always named "default" + var name = isDefaultExport && parent ? "default" /* Default */ : getDeclarationName(node); var symbol; if (name === undefined) { - symbol = createSymbol(0, "__missing"); + symbol = createSymbol(0 /* None */, "__missing" /* Missing */); } else { + // Check and see if the symbol table already has a symbol with this name. If not, + // create a new symbol with this name and add it to the table. Note that we don't + // give the new symbol any flags *yet*. This ensures that it will not conflict + // with the 'excludes' flags we pass in. + // + // If we do get an existing symbol, see if it conflicts with the new symbol we're + // creating. For example, a 'var' symbol and a 'class' symbol will conflict within + // the same symbol table. If we have a conflict, report the issue on each + // declaration we have for this symbol, and then create a new symbol for this + // declaration. + // + // Note that when properties declared in Javascript constructors + // (marked by isReplaceableByMethod) conflict with another symbol, the property loses. + // Always. This allows the common Javascript pattern of overwriting a prototype method + // with an bound instance method of the same type: `this.method = this.method.bind(this)` + // + // If we created a new symbol, either because we didn't have a symbol with this name + // in the symbol table, or we conflicted with an existing symbol, then just add this + // node as the sole declaration of the new symbol. + // + // Otherwise, we'll be merging into a compatible existing symbol (for example when + // you have multiple 'vars' with the same name in the same container). In this case + // just add this node into the declarations list of the symbol. symbol = symbolTable.get(name); - if (includes & 2885600) { + if (includes & 2885600 /* Classifiable */) { classifiableNames.set(name, true); } if (!symbol) { - symbolTable.set(name, symbol = createSymbol(0, name)); + symbolTable.set(name, symbol = createSymbol(0 /* None */, name)); if (isReplaceableByMethod) symbol.isReplaceableByMethod = true; } else if (isReplaceableByMethod && !symbol.isReplaceableByMethod) { + // A symbol already exists, so don't add this as a declaration. return symbol; } else if (symbol.flags & excludes) { if (symbol.isReplaceableByMethod) { - symbolTable.set(name, symbol = createSymbol(0, name)); + // Javascript constructor-declared symbols can be discarded in favor of + // prototype symbols like methods. + symbolTable.set(name, symbol = createSymbol(0 /* None */, name)); } else { if (ts.isNamedDeclaration(node)) { node.name.parent = node; } - var message_1 = symbol.flags & 2 + // Report errors every position with duplicate declaration + // Report errors on previous encountered declarations + var message_1 = symbol.flags & 2 /* BlockScopedVariable */ ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 : ts.Diagnostics.Duplicate_identifier_0; - if (symbol.flags & 384 || includes & 384) { + if (symbol.flags & 384 /* Enum */ || includes & 384 /* Enum */) { message_1 = ts.Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations; } if (symbol.declarations && symbol.declarations.length) { + // If the current node is a default export of some sort, then check if + // there are any other default exports that we need to error on. + // We'll know whether we have other default exports depending on if `symbol` already has a declaration list set. if (isDefaultExport) { message_1 = ts.Diagnostics.A_module_cannot_have_multiple_default_exports; } else { + // This is to properly report an error in the case "export default { }" is after export default of class declaration or function declaration. + // Error on multiple export default in the following case: + // 1. multiple export default of class declaration or function declaration by checking NodeFlags.Default + // 2. multiple export default of export assignment. This one doesn't have NodeFlags.Default on (as export default doesn't considered as modifiers) if (symbol.declarations && symbol.declarations.length && - (node.kind === 249 && !node.isExportEquals)) { + (node.kind === 249 /* ExportAssignment */ && !node.isExportEquals)) { message_1 = ts.Diagnostics.A_module_cannot_have_multiple_default_exports; } } @@ -22163,7 +25773,7 @@ var ts; file.bindDiagnostics.push(createDiagnosticForNode(ts.getNameOfDeclaration(declaration) || declaration, message_1, getDisplayName(declaration))); }); file.bindDiagnostics.push(createDiagnosticForNode(ts.getNameOfDeclaration(node) || node, message_1, getDisplayName(node))); - symbol = createSymbol(0, name); + symbol = createSymbol(0 /* None */, name); } } } @@ -22177,85 +25787,127 @@ var ts; return symbol; } function declareModuleMember(node, symbolFlags, symbolExcludes) { - var hasExportModifier = ts.getCombinedModifierFlags(node) & 1; - if (symbolFlags & 2097152) { - if (node.kind === 252 || (node.kind === 243 && hasExportModifier)) { + var hasExportModifier = ts.getCombinedModifierFlags(node) & 1 /* Export */; + if (symbolFlags & 2097152 /* Alias */) { + if (node.kind === 252 /* ExportSpecifier */ || (node.kind === 243 /* ImportEqualsDeclaration */ && hasExportModifier)) { return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); } else { - return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); + return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); } } else { + // Exported module members are given 2 symbols: A local symbol that is classified with an ExportValue flag, + // and an associated export symbol with all the correct flags set on it. There are 2 main reasons: + // + // 1. We treat locals and exports of the same name as mutually exclusive within a container. + // That means the binder will issue a Duplicate Identifier error if you mix locals and exports + // with the same name in the same container. + // TODO: Make this a more specific error and decouple it from the exclusion logic. + // 2. When we checkIdentifier in the checker, we set its resolved symbol to the local symbol, + // but return the export symbol (by calling getExportSymbolOfValueSymbolIfExported). That way + // when the emitter comes back to it, it knows not to qualify the name if it was found in a containing scope. + // NOTE: Nested ambient modules always should go to to 'locals' table to prevent their automatic merge + // during global merging in the checker. Why? The only case when ambient module is permitted inside another module is module augmentation + // and this case is specially handled. Module augmentations should only be merged with original module definition + // and should never be merged directly with other augmentation, and the latter case would be possible if automatic merge is allowed. if (ts.isJSDocTypeAlias(node)) - ts.Debug.assert(ts.isInJavaScriptFile(node)); - if ((!ts.isAmbientModule(node) && (hasExportModifier || container.flags & 32)) || ts.isJSDocTypeAlias(node)) { - if (ts.hasModifier(node, 512) && !getDeclarationName(node)) { - return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); + ts.Debug.assert(ts.isInJavaScriptFile(node)); // We shouldn't add symbols for JSDoc nodes if not in a JS file. + if ((!ts.isAmbientModule(node) && (hasExportModifier || container.flags & 32 /* ExportContext */)) || ts.isJSDocTypeAlias(node)) { + if (ts.hasModifier(node, 512 /* Default */) && !getDeclarationName(node)) { + return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); // No local symbol for an unnamed default! } - var exportKind = symbolFlags & 67216319 ? 1048576 : 0; - var local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes); + var exportKind = symbolFlags & 67216319 /* Value */ ? 1048576 /* ExportValue */ : 0; + var local = declareSymbol(container.locals, /*parent*/ undefined, node, exportKind, symbolExcludes); local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); node.localSymbol = local; return local; } else { - return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); + return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); } } } + // All container nodes are kept on a linked list in declaration order. This list is used by + // the getLocalNameOfContainer function in the type checker to validate that the local name + // used for a container is unique. function bindContainer(node, containerFlags) { + // Before we recurse into a node's children, we first save the existing parent, container + // and block-container. Then after we pop out of processing the children, we restore + // these saved values. var saveContainer = container; var saveThisParentContainer = thisParentContainer; var savedBlockScopeContainer = blockScopeContainer; - if (containerFlags & 1) { - if (node.kind !== 193) { + // Depending on what kind of node this is, we may have to adjust the current container + // and block-container. If the current node is a container, then it is automatically + // considered the current block-container as well. Also, for containers that we know + // may contain locals, we eagerly initialize the .locals field. We do this because + // it's highly likely that the .locals will be needed to place some child in (for example, + // a parameter, or variable declaration). + // + // However, we do not proactively create the .locals for block-containers because it's + // totally normal and common for block-containers to never actually have a block-scoped + // variable in them. We don't want to end up allocating an object for every 'block' we + // run into when most of them won't be necessary. + // + // Finally, if this is a block-container, then we clear out any existing .locals object + // it may contain within it. This happens in incremental scenarios. Because we can be + // reusing a node from a previous compilation, that node may have had 'locals' created + // for it. We must clear this so we don't accidentally move any stale data forward from + // a previous compilation. + if (containerFlags & 1 /* IsContainer */) { + if (node.kind !== 193 /* ArrowFunction */) { thisParentContainer = container; } container = blockScopeContainer = node; - if (containerFlags & 32) { + if (containerFlags & 32 /* HasLocals */) { container.locals = ts.createSymbolTable(); } addToContainerChain(container); } - else if (containerFlags & 2) { + else if (containerFlags & 2 /* IsBlockScopedContainer */) { blockScopeContainer = node; blockScopeContainer.locals = undefined; } - if (containerFlags & 4) { + if (containerFlags & 4 /* IsControlFlowContainer */) { var saveCurrentFlow = currentFlow; var saveBreakTarget = currentBreakTarget; var saveContinueTarget = currentContinueTarget; var saveReturnTarget = currentReturnTarget; var saveActiveLabels = activeLabels; var saveHasExplicitReturn = hasExplicitReturn; - var isIIFE = containerFlags & 16 && !ts.hasModifier(node, 256) && + var isIIFE = containerFlags & 16 /* IsFunctionExpression */ && !ts.hasModifier(node, 256 /* Async */) && !node.asteriskToken && !!ts.getImmediatelyInvokedFunctionExpression(node); + // A non-async, non-generator IIFE is considered part of the containing control flow. Return statements behave + // similarly to break statements that exit to a label just past the statement body. if (!isIIFE) { - currentFlow = { flags: 2 }; - if (containerFlags & (16 | 128)) { + currentFlow = { flags: 2 /* Start */ }; + if (containerFlags & (16 /* IsFunctionExpression */ | 128 /* IsObjectLiteralOrClassExpressionMethod */)) { currentFlow.container = node; } } - currentReturnTarget = isIIFE || node.kind === 155 ? createBranchLabel() : undefined; + // We create a return control flow graph for IIFEs and constructors. For constructors + // we use the return control flow graph in strict property intialization checks. + currentReturnTarget = isIIFE || node.kind === 155 /* Constructor */ ? createBranchLabel() : undefined; currentBreakTarget = undefined; currentContinueTarget = undefined; activeLabels = undefined; hasExplicitReturn = false; bindChildren(node); - node.flags &= ~1408; - if (!(currentFlow.flags & 1) && containerFlags & 8 && ts.nodeIsPresent(node.body)) { - node.flags |= 128; + // Reset all reachability check related flags on node (for incremental scenarios) + node.flags &= ~1408 /* ReachabilityAndEmitFlags */; + if (!(currentFlow.flags & 1 /* Unreachable */) && containerFlags & 8 /* IsFunctionLike */ && ts.nodeIsPresent(node.body)) { + node.flags |= 128 /* HasImplicitReturn */; if (hasExplicitReturn) - node.flags |= 256; + node.flags |= 256 /* HasExplicitReturn */; } - if (node.kind === 274) { + if (node.kind === 274 /* SourceFile */) { node.flags |= emitFlags; } if (currentReturnTarget) { addAntecedent(currentReturnTarget, currentFlow); currentFlow = finishFlowLabel(currentReturnTarget); - if (node.kind === 155) { + if (node.kind === 155 /* Constructor */) { node.returnFlowNode = currentFlow; } } @@ -22268,10 +25920,10 @@ var ts; activeLabels = saveActiveLabels; hasExplicitReturn = saveHasExplicitReturn; } - else if (containerFlags & 64) { + else if (containerFlags & 64 /* IsInterface */) { seenThisKeyword = false; bindChildren(node); - node.flags = seenThisKeyword ? node.flags | 64 : node.flags & ~64; + node.flags = seenThisKeyword ? node.flags | 64 /* ContainsThis */ : node.flags & ~64 /* ContainsThis */; } else { bindChildren(node); @@ -22284,7 +25936,7 @@ var ts; if (skipTransformFlagAggregation) { bindChildrenWorker(node); } - else if (node.transformFlags & 536870912) { + else if (node.transformFlags & 536870912 /* HasComputedFlags */) { skipTransformFlagAggregation = true; bindChildrenWorker(node); skipTransformFlagAggregation = false; @@ -22298,8 +25950,8 @@ var ts; } } function bindEachFunctionsFirst(nodes) { - bindEach(nodes, function (n) { return n.kind === 234 ? bind(n) : undefined; }); - bindEach(nodes, function (n) { return n.kind !== 234 ? bind(n) : undefined; }); + bindEach(nodes, function (n) { return n.kind === 234 /* FunctionDeclaration */ ? bind(n) : undefined; }); + bindEach(nodes, function (n) { return n.kind !== 234 /* FunctionDeclaration */ ? bind(n) : undefined; }); } function bindEach(nodes, bindFunction) { if (bindFunction === void 0) { bindFunction = bind; } @@ -22311,14 +25963,14 @@ var ts; } else { var savedSubtreeTransformFlags = subtreeTransformFlags; - subtreeTransformFlags = 0; - var nodeArrayFlags = 0; + subtreeTransformFlags = 0 /* None */; + var nodeArrayFlags = 0 /* None */; for (var _i = 0, nodes_2 = nodes; _i < nodes_2.length; _i++) { var node = nodes_2[_i]; bindFunction(node); - nodeArrayFlags |= node.transformFlags & ~536870912; + nodeArrayFlags |= node.transformFlags & ~536870912 /* HasComputedFlags */; } - nodes.transformFlags = nodeArrayFlags | 536870912; + nodes.transformFlags = nodeArrayFlags | 536870912 /* HasComputedFlags */; subtreeTransformFlags |= savedSubtreeTransformFlags; } } @@ -22331,76 +25983,77 @@ var ts; return; } switch (node.kind) { - case 219: + case 219 /* WhileStatement */: bindWhileStatement(node); break; - case 218: + case 218 /* DoStatement */: bindDoStatement(node); break; - case 220: + case 220 /* ForStatement */: bindForStatement(node); break; - case 221: - case 222: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: bindForInOrForOfStatement(node); break; - case 217: + case 217 /* IfStatement */: bindIfStatement(node); break; - case 225: - case 229: + case 225 /* ReturnStatement */: + case 229 /* ThrowStatement */: bindReturnOrThrow(node); break; - case 224: - case 223: + case 224 /* BreakStatement */: + case 223 /* ContinueStatement */: bindBreakOrContinueStatement(node); break; - case 230: + case 230 /* TryStatement */: bindTryStatement(node); break; - case 227: + case 227 /* SwitchStatement */: bindSwitchStatement(node); break; - case 241: + case 241 /* CaseBlock */: bindCaseBlock(node); break; - case 266: + case 266 /* CaseClause */: bindCaseClause(node); break; - case 228: + case 228 /* LabeledStatement */: bindLabeledStatement(node); break; - case 198: + case 198 /* PrefixUnaryExpression */: bindPrefixUnaryExpressionFlow(node); break; - case 199: + case 199 /* PostfixUnaryExpression */: bindPostfixUnaryExpressionFlow(node); break; - case 200: + case 200 /* BinaryExpression */: bindBinaryExpressionFlow(node); break; - case 194: + case 194 /* DeleteExpression */: bindDeleteExpressionFlow(node); break; - case 201: + case 201 /* ConditionalExpression */: bindConditionalExpressionFlow(node); break; - case 232: + case 232 /* VariableDeclaration */: bindVariableDeclarationFlow(node); break; - case 187: + case 187 /* CallExpression */: bindCallExpressionFlow(node); break; - case 298: - case 292: + case 298 /* JSDocTypedefTag */: + case 292 /* JSDocCallbackTag */: bindJSDocTypeAlias(node); break; - case 274: + // In source files and blocks, bind functions first to match hoisting that occurs at runtime + case 274 /* SourceFile */: bindEachFunctionsFirst(node.statements); bind(node.endOfFileToken); break; - case 213: - case 240: + case 213 /* Block */: + case 240 /* ModuleBlock */: bindEachFunctionsFirst(node.statements); break; default: @@ -22411,26 +26064,26 @@ var ts; } function isNarrowingExpression(expr) { switch (expr.kind) { - case 71: - case 99: - case 185: + case 71 /* Identifier */: + case 99 /* ThisKeyword */: + case 185 /* PropertyAccessExpression */: return isNarrowableReference(expr); - case 187: + case 187 /* CallExpression */: return hasNarrowableArgument(expr); - case 191: + case 191 /* ParenthesizedExpression */: return isNarrowingExpression(expr.expression); - case 200: + case 200 /* BinaryExpression */: return isNarrowingBinaryExpression(expr); - case 198: - return expr.operator === 51 && isNarrowingExpression(expr.operand); + case 198 /* PrefixUnaryExpression */: + return expr.operator === 51 /* ExclamationToken */ && isNarrowingExpression(expr.operand); } return false; } function isNarrowableReference(expr) { - return expr.kind === 71 || - expr.kind === 99 || - expr.kind === 97 || - expr.kind === 185 && isNarrowableReference(expr.expression); + return expr.kind === 71 /* Identifier */ || + expr.kind === 99 /* ThisKeyword */ || + expr.kind === 97 /* SuperKeyword */ || + expr.kind === 185 /* PropertyAccessExpression */ && isNarrowableReference(expr.expression); } function hasNarrowableArgument(expr) { if (expr.arguments) { @@ -22441,7 +26094,7 @@ var ts; } } } - if (expr.expression.kind === 185 && + if (expr.expression.kind === 185 /* PropertyAccessExpression */ && isNarrowableReference(expr.expression.expression)) { return true; } @@ -22455,32 +26108,32 @@ var ts; } function isNarrowingBinaryExpression(expr) { switch (expr.operatorToken.kind) { - case 58: + case 58 /* EqualsToken */: return isNarrowableReference(expr.left); - case 32: - case 33: - case 34: - case 35: + case 32 /* EqualsEqualsToken */: + case 33 /* ExclamationEqualsToken */: + case 34 /* EqualsEqualsEqualsToken */: + case 35 /* ExclamationEqualsEqualsToken */: return isNarrowableOperand(expr.left) || isNarrowableOperand(expr.right) || isNarrowingTypeofOperands(expr.right, expr.left) || isNarrowingTypeofOperands(expr.left, expr.right); - case 93: + case 93 /* InstanceOfKeyword */: return isNarrowableOperand(expr.left); - case 92: + case 92 /* InKeyword */: return isNarrowableInOperands(expr.left, expr.right); - case 26: + case 26 /* CommaToken */: return isNarrowingExpression(expr.right); } return false; } function isNarrowableOperand(expr) { switch (expr.kind) { - case 191: + case 191 /* ParenthesizedExpression */: return isNarrowableOperand(expr.expression); - case 200: + case 200 /* BinaryExpression */: switch (expr.operatorToken.kind) { - case 58: + case 58 /* EqualsToken */: return isNarrowableOperand(expr.left); - case 26: + case 26 /* CommaToken */: return isNarrowableOperand(expr.right); } } @@ -22488,34 +26141,35 @@ var ts; } function createBranchLabel() { return { - flags: 4, + flags: 4 /* BranchLabel */, antecedents: undefined }; } function createLoopLabel() { return { - flags: 8, + flags: 8 /* LoopLabel */, antecedents: undefined }; } function setFlowNodeReferenced(flow) { - flow.flags |= flow.flags & 512 ? 1024 : 512; + // On first reference we set the Referenced flag, thereafter we set the Shared flag + flow.flags |= flow.flags & 512 /* Referenced */ ? 1024 /* Shared */ : 512 /* Referenced */; } function addAntecedent(label, antecedent) { - if (!(antecedent.flags & 1) && !ts.contains(label.antecedents, antecedent)) { + if (!(antecedent.flags & 1 /* Unreachable */) && !ts.contains(label.antecedents, antecedent)) { (label.antecedents || (label.antecedents = [])).push(antecedent); setFlowNodeReferenced(antecedent); } } function createFlowCondition(flags, antecedent, expression) { - if (antecedent.flags & 1) { + if (antecedent.flags & 1 /* Unreachable */) { return antecedent; } if (!expression) { - return flags & 32 ? antecedent : unreachableFlow; + return flags & 32 /* TrueCondition */ ? antecedent : unreachableFlow; } - if (expression.kind === 101 && flags & 64 || - expression.kind === 86 && flags & 32) { + if (expression.kind === 101 /* TrueKeyword */ && flags & 64 /* FalseCondition */ || + expression.kind === 86 /* FalseKeyword */ && flags & 32 /* TrueCondition */) { return unreachableFlow; } if (!isNarrowingExpression(expression)) { @@ -22529,15 +26183,15 @@ var ts; return antecedent; } setFlowNodeReferenced(antecedent); - return { flags: 128, switchStatement: switchStatement, clauseStart: clauseStart, clauseEnd: clauseEnd, antecedent: antecedent }; + return { flags: 128 /* SwitchClause */, switchStatement: switchStatement, clauseStart: clauseStart, clauseEnd: clauseEnd, antecedent: antecedent }; } function createFlowAssignment(antecedent, node) { setFlowNodeReferenced(antecedent); - return { flags: 16, antecedent: antecedent, node: node }; + return { flags: 16 /* Assignment */, antecedent: antecedent, node: node }; } function createFlowArrayMutation(antecedent, node) { setFlowNodeReferenced(antecedent); - var res = { flags: 256, antecedent: antecedent, node: node }; + var res = { flags: 256 /* ArrayMutation */, antecedent: antecedent, node: node }; return res; } function finishFlowLabel(flow) { @@ -22553,34 +26207,34 @@ var ts; function isStatementCondition(node) { var parent = node.parent; switch (parent.kind) { - case 217: - case 219: - case 218: + case 217 /* IfStatement */: + case 219 /* WhileStatement */: + case 218 /* DoStatement */: return parent.expression === node; - case 220: - case 201: + case 220 /* ForStatement */: + case 201 /* ConditionalExpression */: return parent.condition === node; } return false; } function isLogicalExpression(node) { while (true) { - if (node.kind === 191) { + if (node.kind === 191 /* ParenthesizedExpression */) { node = node.expression; } - else if (node.kind === 198 && node.operator === 51) { + else if (node.kind === 198 /* PrefixUnaryExpression */ && node.operator === 51 /* ExclamationToken */) { node = node.operand; } else { - return node.kind === 200 && (node.operatorToken.kind === 53 || - node.operatorToken.kind === 54); + return node.kind === 200 /* BinaryExpression */ && (node.operatorToken.kind === 53 /* AmpersandAmpersandToken */ || + node.operatorToken.kind === 54 /* BarBarToken */); } } } function isTopLevelLogicalExpression(node) { - while (node.parent.kind === 191 || - node.parent.kind === 198 && - node.parent.operator === 51) { + while (node.parent.kind === 191 /* ParenthesizedExpression */ || + node.parent.kind === 198 /* PrefixUnaryExpression */ && + node.parent.operator === 51 /* ExclamationToken */) { node = node.parent; } return !isStatementCondition(node) && !isLogicalExpression(node.parent); @@ -22594,8 +26248,8 @@ var ts; currentTrueTarget = saveTrueTarget; currentFalseTarget = saveFalseTarget; if (!node || !isLogicalExpression(node)) { - addAntecedent(trueTarget, createFlowCondition(32, currentFlow, node)); - addAntecedent(falseTarget, createFlowCondition(64, currentFlow, node)); + addAntecedent(trueTarget, createFlowCondition(32 /* TrueCondition */, currentFlow, node)); + addAntecedent(falseTarget, createFlowCondition(64 /* FalseCondition */, currentFlow, node)); } } function bindIterativeStatement(node, breakTarget, continueTarget) { @@ -22621,9 +26275,11 @@ var ts; } function bindDoStatement(node) { var preDoLabel = createLoopLabel(); - var enclosingLabeledStatement = node.parent.kind === 228 + var enclosingLabeledStatement = node.parent.kind === 228 /* LabeledStatement */ ? ts.lastOrUndefined(activeLabels) : undefined; + // if do statement is wrapped in labeled statement then target labels for break/continue with or without + // label should be the same var preConditionLabel = enclosingLabeledStatement ? enclosingLabeledStatement.continueTarget : createBranchLabel(); var postDoLabel = enclosingLabeledStatement ? enclosingLabeledStatement.breakTarget : createBranchLabel(); addAntecedent(preDoLabel, currentFlow); @@ -22653,13 +26309,13 @@ var ts; var postLoopLabel = createBranchLabel(); addAntecedent(preLoopLabel, currentFlow); currentFlow = preLoopLabel; - if (node.kind === 222) { + if (node.kind === 222 /* ForOfStatement */) { bind(node.awaitModifier); } bind(node.expression); addAntecedent(postLoopLabel, currentFlow); bind(node.initializer); - if (node.initializer.kind !== 233) { + if (node.initializer.kind !== 233 /* VariableDeclarationList */) { bindAssignmentTargetFlow(node.initializer); } bindIterativeStatement(node.statement, postLoopLabel, preLoopLabel); @@ -22681,7 +26337,7 @@ var ts; } function bindReturnOrThrow(node) { bind(node.expression); - if (node.kind === 225) { + if (node.kind === 225 /* ReturnStatement */) { hasExplicitReturn = true; if (currentReturnTarget) { addAntecedent(currentReturnTarget, currentFlow); @@ -22701,7 +26357,7 @@ var ts; return undefined; } function bindBreakOrContinueFlow(node, breakTarget, continueTarget) { - var flowLabel = node.kind === 224 ? breakTarget : continueTarget; + var flowLabel = node.kind === 224 /* BreakStatement */ ? breakTarget : continueTarget; if (flowLabel) { addAntecedent(flowLabel, currentFlow); currentFlow = unreachableFlow; @@ -22723,6 +26379,7 @@ var ts; function bindTryStatement(node) { var preFinallyLabel = createBranchLabel(); var preTryFlow = currentFlow; + // TODO: Every statement in try block is potentially an exit point! bind(node.tryBlock); addAntecedent(preFinallyLabel, currentFlow); var flowAfterTry = currentFlow; @@ -22734,19 +26391,51 @@ var ts; flowAfterCatch = currentFlow; } if (node.finallyBlock) { - var preFinallyFlow = { flags: 2048, antecedent: preTryFlow, lock: {} }; + // in finally flow is combined from pre-try/flow from try/flow from catch + // pre-flow is necessary to make sure that finally is reachable even if finally flows in both try and finally blocks are unreachable + // also for finally blocks we inject two extra edges into the flow graph. + // first -> edge that connects pre-try flow with the label at the beginning of the finally block, it has lock associated with it + // second -> edge that represents post-finally flow. + // these edges are used in following scenario: + // let a; (1) + // try { a = someOperation(); (2)} + // finally { (3) console.log(a) } (4) + // (5) a + // flow graph for this case looks roughly like this (arrows show ): + // (1-pre-try-flow) <--.. <-- (2-post-try-flow) + // ^ ^ + // |*****(3-pre-finally-label) -----| + // ^ + // |-- ... <-- (4-post-finally-label) <--- (5) + // In case when we walk the flow starting from inside the finally block we want to take edge '*****' into account + // since it ensures that finally is always reachable. However when we start outside the finally block and go through label (5) + // then edge '*****' should be discarded because label 4 is only reachable if post-finally label-4 is reachable + // Simply speaking code inside finally block is treated as reachable as pre-try-flow + // since we conservatively assume that any line in try block can throw or return in which case we'll enter finally. + // However code after finally is reachable only if control flow was not abrupted in try/catch or finally blocks - it should be composed from + // final flows of these blocks without taking pre-try flow into account. + // + // extra edges that we inject allows to control this behavior + // if when walking the flow we step on post-finally edge - we can mark matching pre-finally edge as locked so it will be skipped. + var preFinallyFlow = { flags: 2048 /* PreFinally */, antecedent: preTryFlow, lock: {} }; addAntecedent(preFinallyLabel, preFinallyFlow); currentFlow = finishFlowLabel(preFinallyLabel); bind(node.finallyBlock); - if (!(currentFlow.flags & 1)) { - if ((flowAfterTry.flags & 1) && (flowAfterCatch.flags & 1)) { + // if flow after finally is unreachable - keep it + // otherwise check if flows after try and after catch are unreachable + // if yes - convert current flow to unreachable + // i.e. + // try { return "1" } finally { console.log(1); } + // console.log(2); // this line should be unreachable even if flow falls out of finally block + if (!(currentFlow.flags & 1 /* Unreachable */)) { + if ((flowAfterTry.flags & 1 /* Unreachable */) && (flowAfterCatch.flags & 1 /* Unreachable */)) { currentFlow = flowAfterTry === reportedUnreachableFlow || flowAfterCatch === reportedUnreachableFlow ? reportedUnreachableFlow : unreachableFlow; } } - if (!(currentFlow.flags & 1)) { - var afterFinallyFlow = { flags: 4096, antecedent: currentFlow }; + if (!(currentFlow.flags & 1 /* Unreachable */)) { + var afterFinallyFlow = { flags: 4096 /* AfterFinally */, antecedent: currentFlow }; preFinallyFlow.lock = afterFinallyFlow; currentFlow = afterFinallyFlow; } @@ -22764,7 +26453,9 @@ var ts; preSwitchCaseFlow = currentFlow; bind(node.caseBlock); addAntecedent(postSwitchLabel, currentFlow); - var hasDefault = ts.forEach(node.caseBlock.clauses, function (c) { return c.kind === 267; }); + var hasDefault = ts.forEach(node.caseBlock.clauses, function (c) { return c.kind === 267 /* DefaultClause */; }); + // We mark a switch statement as possibly exhaustive if it has no default clause and if all + // case clauses have unreachable end points (e.g. they all return). node.possiblyExhaustive = !hasDefault && !postSwitchLabel.antecedents; if (!hasDefault) { addAntecedent(postSwitchLabel, createFlowSwitchClause(preSwitchCaseFlow, node, 0, 0)); @@ -22792,11 +26483,11 @@ var ts; var clause = clauses[i]; bind(clause); fallthroughFlow = currentFlow; - if (!(currentFlow.flags & 1) && i !== clauses.length - 1 && options.noFallthroughCasesInSwitch) { + if (!(currentFlow.flags & 1 /* Unreachable */) && i !== clauses.length - 1 && options.noFallthroughCasesInSwitch) { errorOnFirstToken(clause, ts.Diagnostics.Fallthrough_case_in_switch); } } - clauses.transformFlags = subtreeTransformFlags | 536870912; + clauses.transformFlags = subtreeTransformFlags | 536870912 /* HasComputedFlags */; subtreeTransformFlags |= savedSubtreeTransformFlags; } function bindCaseClause(node) { @@ -22830,13 +26521,14 @@ var ts; if (!activeLabel.referenced && !options.allowUnusedLabels) { errorOrSuggestionOnFirstToken(ts.unusedLabelIsError(options), node, ts.Diagnostics.Unused_label); } - if (!node.statement || node.statement.kind !== 218) { + if (!node.statement || node.statement.kind !== 218 /* DoStatement */) { + // do statement sets current flow inside bindDoStatement addAntecedent(postStatementLabel, currentFlow); currentFlow = finishFlowLabel(postStatementLabel); } } function bindDestructuringTargetFlow(node) { - if (node.kind === 200 && node.operatorToken.kind === 58) { + if (node.kind === 200 /* BinaryExpression */ && node.operatorToken.kind === 58 /* EqualsToken */) { bindAssignmentTargetFlow(node.left); } else { @@ -22847,10 +26539,10 @@ var ts; if (isNarrowableReference(node)) { currentFlow = createFlowAssignment(currentFlow, node); } - else if (node.kind === 183) { + else if (node.kind === 183 /* ArrayLiteralExpression */) { for (var _i = 0, _a = node.elements; _i < _a.length; _i++) { var e = _a[_i]; - if (e.kind === 204) { + if (e.kind === 204 /* SpreadElement */) { bindAssignmentTargetFlow(e.expression); } else { @@ -22858,16 +26550,16 @@ var ts; } } } - else if (node.kind === 184) { + else if (node.kind === 184 /* ObjectLiteralExpression */) { for (var _b = 0, _c = node.properties; _b < _c.length; _b++) { var p = _c[_b]; - if (p.kind === 270) { + if (p.kind === 270 /* PropertyAssignment */) { bindDestructuringTargetFlow(p.initializer); } - else if (p.kind === 271) { + else if (p.kind === 271 /* ShorthandPropertyAssignment */) { bindAssignmentTargetFlow(p.name); } - else if (p.kind === 272) { + else if (p.kind === 272 /* SpreadAssignment */) { bindAssignmentTargetFlow(p.expression); } } @@ -22875,7 +26567,7 @@ var ts; } function bindLogicalExpression(node, trueTarget, falseTarget) { var preRightLabel = createBranchLabel(); - if (node.operatorToken.kind === 53) { + if (node.operatorToken.kind === 53 /* AmpersandAmpersandToken */) { bindCondition(node.left, preRightLabel, falseTarget); } else { @@ -22886,7 +26578,7 @@ var ts; bindCondition(node.right, trueTarget, falseTarget); } function bindPrefixUnaryExpressionFlow(node) { - if (node.operator === 51) { + if (node.operator === 51 /* ExclamationToken */) { var saveTrueTarget = currentTrueTarget; currentTrueTarget = currentFalseTarget; currentFalseTarget = saveTrueTarget; @@ -22896,20 +26588,20 @@ var ts; } else { bindEachChild(node); - if (node.operator === 43 || node.operator === 44) { + if (node.operator === 43 /* PlusPlusToken */ || node.operator === 44 /* MinusMinusToken */) { bindAssignmentTargetFlow(node.operand); } } } function bindPostfixUnaryExpressionFlow(node) { bindEachChild(node); - if (node.operator === 43 || node.operator === 44) { + if (node.operator === 43 /* PlusPlusToken */ || node.operator === 44 /* MinusMinusToken */) { bindAssignmentTargetFlow(node.operand); } } function bindBinaryExpressionFlow(node) { var operator = node.operatorToken.kind; - if (operator === 53 || operator === 54) { + if (operator === 53 /* AmpersandAmpersandToken */ || operator === 54 /* BarBarToken */) { if (isTopLevelLogicalExpression(node)) { var postExpressionLabel = createBranchLabel(); bindLogicalExpression(node, postExpressionLabel, postExpressionLabel); @@ -22923,7 +26615,7 @@ var ts; bindEachChild(node); if (ts.isAssignmentOperator(operator) && !ts.isAssignmentTarget(node)) { bindAssignmentTargetFlow(node.left); - if (operator === 58 && node.left.kind === 186) { + if (operator === 58 /* EqualsToken */ && node.left.kind === 186 /* ElementAccessExpression */) { var elementAccess = node.left; if (isNarrowableOperand(elementAccess.expression)) { currentFlow = createFlowArrayMutation(currentFlow, node); @@ -22934,7 +26626,7 @@ var ts; } function bindDeleteExpressionFlow(node) { bindEachChild(node); - if (node.expression.kind === 185) { + if (node.expression.kind === 185 /* PropertyAccessExpression */) { bindAssignmentTargetFlow(node.expression); } } @@ -22977,11 +26669,14 @@ var ts; } } function bindCallExpressionFlow(node) { + // If the target of the call expression is a function expression or arrow function we have + // an immediately invoked function expression (IIFE). Initialize the flowNode property to + // the current control flow (which includes evaluation of the IIFE arguments). var expr = node.expression; - while (expr.kind === 191) { + while (expr.kind === 191 /* ParenthesizedExpression */) { expr = expr.expression; } - if (expr.kind === 192 || expr.kind === 193) { + if (expr.kind === 192 /* FunctionExpression */ || expr.kind === 193 /* ArrowFunction */) { bindEach(node.typeArguments); bindEach(node.arguments); bind(node.expression); @@ -22989,7 +26684,7 @@ var ts; else { bindEachChild(node); } - if (node.expression.kind === 185) { + if (node.expression.kind === 185 /* PropertyAccessExpression */) { var propertyAccess = node.expression; if (isNarrowableOperand(propertyAccess.expression) && ts.isPushOrUnshiftIdentifier(propertyAccess.name)) { currentFlow = createFlowArrayMutation(currentFlow, node); @@ -22998,56 +26693,73 @@ var ts; } function getContainerFlags(node) { switch (node.kind) { - case 205: - case 235: - case 238: - case 184: - case 166: - case 287: - case 263: - return 1; - case 236: - return 1 | 64; - case 239: - case 237: - case 177: - return 1 | 32; - case 274: - return 1 | 4 | 32; - case 154: + case 205 /* ClassExpression */: + case 235 /* ClassDeclaration */: + case 238 /* EnumDeclaration */: + case 184 /* ObjectLiteralExpression */: + case 166 /* TypeLiteral */: + case 287 /* JSDocTypeLiteral */: + case 263 /* JsxAttributes */: + return 1 /* IsContainer */; + case 236 /* InterfaceDeclaration */: + return 1 /* IsContainer */ | 64 /* IsInterface */; + case 239 /* ModuleDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 177 /* MappedType */: + return 1 /* IsContainer */ | 32 /* HasLocals */; + case 274 /* SourceFile */: + return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */; + case 154 /* MethodDeclaration */: if (ts.isObjectLiteralOrClassExpressionMethod(node)) { - return 1 | 4 | 32 | 8 | 128; + return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */ | 8 /* IsFunctionLike */ | 128 /* IsObjectLiteralOrClassExpressionMethod */; } - case 155: - case 234: - case 153: - case 156: - case 157: - case 158: - case 288: - case 284: - case 163: - case 159: - case 160: - case 164: - return 1 | 4 | 32 | 8; - case 192: - case 193: - return 1 | 4 | 32 | 8 | 16; - case 240: - return 4; - case 152: - return node.initializer ? 4 : 0; - case 269: - case 220: - case 221: - case 222: - case 241: - return 2; - case 213: - return ts.isFunctionLike(node.parent) ? 0 : 2; + // falls through + case 155 /* Constructor */: + case 234 /* FunctionDeclaration */: + case 153 /* MethodSignature */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 158 /* CallSignature */: + case 288 /* JSDocSignature */: + case 284 /* JSDocFunctionType */: + case 163 /* FunctionType */: + case 159 /* ConstructSignature */: + case 160 /* IndexSignature */: + case 164 /* ConstructorType */: + return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */ | 8 /* IsFunctionLike */; + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */ | 8 /* IsFunctionLike */ | 16 /* IsFunctionExpression */; + case 240 /* ModuleBlock */: + return 4 /* IsControlFlowContainer */; + case 152 /* PropertyDeclaration */: + return node.initializer ? 4 /* IsControlFlowContainer */ : 0; + case 269 /* CatchClause */: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 241 /* CaseBlock */: + return 2 /* IsBlockScopedContainer */; + case 213 /* Block */: + // do not treat blocks directly inside a function as a block-scoped-container. + // Locals that reside in this block should go to the function locals. Otherwise 'x' + // would not appear to be a redeclaration of a block scoped local in the following + // example: + // + // function foo() { + // var x; + // let x; + // } + // + // If we placed 'var x' into the function locals and 'let x' into the locals of + // the block, then there would be no collision. + // + // By not creating a new block-scoped-container here, we ensure that both 'var x' + // and 'let x' go into the Function-container's locals, and we do get a collision + // conflict. + return ts.isFunctionLike(node.parent) ? 0 /* None */ : 2 /* IsBlockScopedContainer */; } - return 0; + return 0 /* None */; } function addToContainerChain(next) { if (lastContainer) { @@ -23057,59 +26769,74 @@ var ts; } function declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes) { switch (container.kind) { - case 239: + // Modules, source files, and classes need specialized handling for how their + // members are declared (for example, a member of a class will go into a specific + // symbol table depending on if it is static or not). We defer to specialized + // handlers to take care of declaring these child members. + case 239 /* ModuleDeclaration */: return declareModuleMember(node, symbolFlags, symbolExcludes); - case 274: + case 274 /* SourceFile */: return declareSourceFileMember(node, symbolFlags, symbolExcludes); - case 205: - case 235: + case 205 /* ClassExpression */: + case 235 /* ClassDeclaration */: return declareClassMember(node, symbolFlags, symbolExcludes); - case 238: + case 238 /* EnumDeclaration */: return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); - case 166: - case 287: - case 184: - case 236: - case 263: + case 166 /* TypeLiteral */: + case 287 /* JSDocTypeLiteral */: + case 184 /* ObjectLiteralExpression */: + case 236 /* InterfaceDeclaration */: + case 263 /* JsxAttributes */: + // Interface/Object-types always have their children added to the 'members' of + // their container. They are only accessible through an instance of their + // container, and are never in scope otherwise (even inside the body of the + // object / type / interface declaring them). An exception is type parameters, + // which are in scope without qualification (similar to 'locals'). return declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); - case 163: - case 164: - case 158: - case 159: - case 288: - case 160: - case 154: - case 153: - case 155: - case 156: - case 157: - case 234: - case 192: - case 193: - case 284: - case 298: - case 292: - case 237: - case 177: - return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 288 /* JSDocSignature */: + case 160 /* IndexSignature */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 284 /* JSDocFunctionType */: + case 298 /* JSDocTypedefTag */: + case 292 /* JSDocCallbackTag */: + case 237 /* TypeAliasDeclaration */: + case 177 /* MappedType */: + // All the children of these container types are never visible through another + // symbol (i.e. through another symbol's 'exports' or 'members'). Instead, + // they're only accessed 'lexically' (i.e. from code that exists underneath + // their container in the tree). To accomplish this, we simply add their declared + // symbol to the 'locals' of the container. These symbols can then be found as + // the type checker walks up the containers, checking them for matching names. + return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); } } function declareClassMember(node, symbolFlags, symbolExcludes) { - return ts.hasModifier(node, 32) + return ts.hasModifier(node, 32 /* Static */) ? declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes) : declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); } function declareSourceFileMember(node, symbolFlags, symbolExcludes) { return ts.isExternalModule(file) ? declareModuleMember(node, symbolFlags, symbolExcludes) - : declareSymbol(file.locals, undefined, node, symbolFlags, symbolExcludes); + : declareSymbol(file.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); } function hasExportDeclarations(node) { - var body = node.kind === 274 ? node : node.body; - if (body && (body.kind === 274 || body.kind === 240)) { + var body = node.kind === 274 /* SourceFile */ ? node : node.body; + if (body && (body.kind === 274 /* SourceFile */ || body.kind === 240 /* ModuleBlock */)) { for (var _i = 0, _a = body.statements; _i < _a.length; _i++) { var stat = _a[_i]; - if (stat.kind === 250 || stat.kind === 249) { + if (stat.kind === 250 /* ExportDeclaration */ || stat.kind === 249 /* ExportAssignment */) { return true; } } @@ -23117,17 +26844,19 @@ var ts; return false; } function setExportContextFlag(node) { - if (node.flags & 4194304 && !hasExportDeclarations(node)) { - node.flags |= 32; + // A declaration source file or ambient module declaration that contains no export declarations (but possibly regular + // declarations with export modifiers) is an export context in which declarations are implicitly exported. + if (node.flags & 4194304 /* Ambient */ && !hasExportDeclarations(node)) { + node.flags |= 32 /* ExportContext */; } else { - node.flags &= ~32; + node.flags &= ~32 /* ExportContext */; } } function bindModuleDeclaration(node) { setExportContextFlag(node); if (ts.isAmbientModule(node)) { - if (ts.hasModifier(node, 1)) { + if (ts.hasModifier(node, 1 /* Export */)) { errorOnFirstToken(node, ts.Diagnostics.export_modifier_cannot_be_applied_to_ambient_modules_and_module_augmentations_since_they_are_always_visible); } if (ts.isModuleAugmentationExternal(node)) { @@ -23135,7 +26864,7 @@ var ts; } else { var pattern = void 0; - if (node.name.kind === 9) { + if (node.name.kind === 9 /* StringLiteral */) { var text = node.name.text; if (ts.hasZeroOrOneAsteriskCharacter(text)) { pattern = ts.tryParsePattern(text); @@ -23144,31 +26873,40 @@ var ts; errorOnFirstToken(node.name, ts.Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, text); } } - var symbol = declareSymbolAndAddToSymbolTable(node, 512, 67215503); + var symbol = declareSymbolAndAddToSymbolTable(node, 512 /* ValueModule */, 67215503 /* ValueModuleExcludes */); file.patternAmbientModules = ts.append(file.patternAmbientModules, pattern && { pattern: pattern, symbol: symbol }); } } else { var state = declareModuleSymbol(node); - if (state !== 0) { + if (state !== 0 /* NonInstantiated */) { var symbol = node.symbol; - symbol.constEnumOnlyModule = (!(symbol.flags & (16 | 32 | 256))) - && state === 2 + // if module was already merged with some function, class or non-const enum, treat it as non-const-enum-only + symbol.constEnumOnlyModule = (!(symbol.flags & (16 /* Function */ | 32 /* Class */ | 256 /* RegularEnum */))) + // Current must be `const enum` only + && state === 2 /* ConstEnumOnly */ + // Can't have been set to 'false' in a previous merged symbol. ('undefined' OK) && symbol.constEnumOnlyModule !== false; } } } function declareModuleSymbol(node) { var state = getModuleInstanceState(node); - var instantiated = state !== 0; - declareSymbolAndAddToSymbolTable(node, instantiated ? 512 : 1024, instantiated ? 67215503 : 0); + var instantiated = state !== 0 /* NonInstantiated */; + declareSymbolAndAddToSymbolTable(node, instantiated ? 512 /* ValueModule */ : 1024 /* NamespaceModule */, instantiated ? 67215503 /* ValueModuleExcludes */ : 0 /* NamespaceModuleExcludes */); return state; } function bindFunctionOrConstructorType(node) { - var symbol = createSymbol(131072, getDeclarationName(node)); - addDeclarationToSymbol(symbol, node, 131072); - var typeLiteralSymbol = createSymbol(2048, "__type"); - addDeclarationToSymbol(typeLiteralSymbol, node, 2048); + // For a given function symbol "<...>(...) => T" we want to generate a symbol identical + // to the one we would get for: { <...>(...): T } + // + // We do that by making an anonymous type literal symbol, and then setting the function + // symbol as its sole member. To the rest of the system, this symbol will be indistinguishable + // from an actual type literal symbol you would have gotten had you used the long form. + var symbol = createSymbol(131072 /* Signature */, getDeclarationName(node)); // TODO: GH#18217 + addDeclarationToSymbol(symbol, node, 131072 /* Signature */); + var typeLiteralSymbol = createSymbol(2048 /* TypeLiteral */, "__type" /* Type */); + addDeclarationToSymbol(typeLiteralSymbol, node, 2048 /* TypeLiteral */); typeLiteralSymbol.members = ts.createSymbolTable(); typeLiteralSymbol.members.set(symbol.escapedName, symbol); } @@ -23182,35 +26920,43 @@ var ts; var seen = ts.createUnderscoreEscapedMap(); for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { var prop = _a[_i]; - if (prop.kind === 272 || prop.name.kind !== 71) { + if (prop.kind === 272 /* SpreadAssignment */ || prop.name.kind !== 71 /* Identifier */) { continue; } var identifier = prop.name; - var currentKind = prop.kind === 270 || prop.kind === 271 || prop.kind === 154 - ? 1 - : 2; + // ECMA-262 11.1.5 Object Initializer + // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true + // a.This production is contained in strict code and IsDataDescriptor(previous) is true and + // IsDataDescriptor(propId.descriptor) is true. + // b.IsDataDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true. + // c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(propId.descriptor) is true. + // d.IsAccessorDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true + // and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields + var currentKind = prop.kind === 270 /* PropertyAssignment */ || prop.kind === 271 /* ShorthandPropertyAssignment */ || prop.kind === 154 /* MethodDeclaration */ + ? 1 /* Property */ + : 2 /* Accessor */; var existingKind = seen.get(identifier.escapedText); if (!existingKind) { seen.set(identifier.escapedText, currentKind); continue; } - if (currentKind === 1 && existingKind === 1) { + if (currentKind === 1 /* Property */ && existingKind === 1 /* Property */) { var span = ts.getErrorSpanForNode(file, identifier); file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode)); } } } - return bindAnonymousDeclaration(node, 4096, "__object"); + return bindAnonymousDeclaration(node, 4096 /* ObjectLiteral */, "__object" /* Object */); } function bindJsxAttributes(node) { - return bindAnonymousDeclaration(node, 4096, "__jsxAttributes"); + return bindAnonymousDeclaration(node, 4096 /* ObjectLiteral */, "__jsxAttributes" /* JSXAttributes */); } function bindJsxAttribute(node, symbolFlags, symbolExcludes) { return declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); } function bindAnonymousDeclaration(node, symbolFlags, name) { var symbol = createSymbol(symbolFlags, name); - if (symbolFlags & (8 | 106500)) { + if (symbolFlags & (8 /* EnumMember */ | 106500 /* ClassMember */)) { symbol.parent = container.symbol; } addDeclarationToSymbol(symbol, node, symbolFlags); @@ -23218,24 +26964,25 @@ var ts; } function bindBlockScopedDeclaration(node, symbolFlags, symbolExcludes) { switch (blockScopeContainer.kind) { - case 239: + case 239 /* ModuleDeclaration */: declareModuleMember(node, symbolFlags, symbolExcludes); break; - case 274: + case 274 /* SourceFile */: if (ts.isExternalOrCommonJsModule(container)) { declareModuleMember(node, symbolFlags, symbolExcludes); break; } + // falls through default: if (!blockScopeContainer.locals) { blockScopeContainer.locals = ts.createSymbolTable(); addToContainerChain(blockScopeContainer); } - declareSymbol(blockScopeContainer.locals, undefined, node, symbolFlags, symbolExcludes); + declareSymbol(blockScopeContainer.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); } } function bindBlockScopedVariableDeclaration(node) { - bindBlockScopedDeclaration(node, 2, 67216319); + bindBlockScopedDeclaration(node, 2 /* BlockScopedVariable */, 67216319 /* BlockScopedVariableExcludes */); } function delayedBindJSDocTypedefTag() { if (!delayedTypeAliases) { @@ -23249,14 +26996,14 @@ var ts; for (var _i = 0, delayedTypeAliases_1 = delayedTypeAliases; _i < delayedTypeAliases_1.length; _i++) { var typeAlias = delayedTypeAliases_1[_i]; var host = ts.getJSDocHost(typeAlias); - container = ts.findAncestor(host.parent, function (n) { return !!(getContainerFlags(n) & 1); }) || file; + container = ts.findAncestor(host.parent, function (n) { return !!(getContainerFlags(n) & 1 /* IsContainer */); }) || file; blockScopeContainer = ts.getEnclosingBlockScopeContainer(host) || file; - currentFlow = { flags: 2 }; + currentFlow = { flags: 2 /* Start */ }; parent = typeAlias; bind(typeAlias.typeExpression); - if (!typeAlias.fullName || typeAlias.fullName.kind === 71) { + if (!typeAlias.fullName || typeAlias.fullName.kind === 71 /* Identifier */) { parent = typeAlias.parent; - bindBlockScopedDeclaration(typeAlias, 524288, 67901928); + bindBlockScopedDeclaration(typeAlias, 524288 /* TypeAlias */, 67901928 /* TypeAliasExcludes */); } else { bind(typeAlias.fullName); @@ -23268,18 +27015,23 @@ var ts; parent = saveParent; currentFlow = saveCurrentFlow; } + // The binder visits every node in the syntax tree so it is a convenient place to perform a single localized + // check for reserved words used as identifiers in strict mode code. function checkStrictModeIdentifier(node) { if (inStrictMode && - node.originalKeywordKind >= 108 && - node.originalKeywordKind <= 116 && + node.originalKeywordKind >= 108 /* FirstFutureReservedWord */ && + node.originalKeywordKind <= 116 /* LastFutureReservedWord */ && !ts.isIdentifierName(node) && - !(node.flags & 4194304)) { + !(node.flags & 4194304 /* Ambient */)) { + // Report error only if there are no parse errors in file if (!file.parseDiagnostics.length) { file.bindDiagnostics.push(createDiagnosticForNode(node, getStrictModeIdentifierMessage(node), ts.declarationNameToString(node))); } } } function getStrictModeIdentifierMessage(node) { + // Provide specialized messages to help the user understand why we think they're in + // strict mode. if (ts.getContainingClass(node)) { return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode; } @@ -23290,16 +27042,23 @@ var ts; } function checkStrictModeBinaryExpression(node) { if (inStrictMode && ts.isLeftHandSideExpression(node.left) && ts.isAssignmentOperator(node.operatorToken.kind)) { + // ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an + // Assignment operator(11.13) or of a PostfixExpression(11.3) checkStrictModeEvalOrArguments(node, node.left); } } function checkStrictModeCatchClause(node) { + // It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the + // Catch production is eval or arguments if (inStrictMode && node.variableDeclaration) { checkStrictModeEvalOrArguments(node, node.variableDeclaration.name); } } function checkStrictModeDeleteExpression(node) { - if (inStrictMode && node.expression.kind === 71) { + // Grammar checking + if (inStrictMode && node.expression.kind === 71 /* Identifier */) { + // When a delete operator occurs within strict mode code, a SyntaxError is thrown if its + // UnaryExpression is a direct reference to a variable, function argument, or function name var span = ts.getErrorSpanForNode(file, node.expression); file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode)); } @@ -23308,15 +27067,19 @@ var ts; return ts.isIdentifier(node) && (node.escapedText === "eval" || node.escapedText === "arguments"); } function checkStrictModeEvalOrArguments(contextNode, name) { - if (name && name.kind === 71) { + if (name && name.kind === 71 /* Identifier */) { var identifier = name; if (isEvalOrArgumentsIdentifier(identifier)) { + // We check first if the name is inside class declaration or class expression; if so give explicit message + // otherwise report generic error message. var span = ts.getErrorSpanForNode(file, name); file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, getStrictModeEvalOrArgumentsMessage(contextNode), ts.idText(identifier))); } } } function getStrictModeEvalOrArgumentsMessage(node) { + // Provide specialized messages to help the user understand why we think they're in + // strict mode. if (ts.getContainingClass(node)) { return ts.Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode; } @@ -23327,10 +27090,13 @@ var ts; } function checkStrictModeFunctionName(node) { if (inStrictMode) { + // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a strict mode FunctionDeclaration or FunctionExpression (13.1)) checkStrictModeEvalOrArguments(node, node.name); } } function getStrictModeBlockScopeFunctionDeclarationMessage(node) { + // Provide specialized messages to help the user understand why we think they're in + // strict mode. if (ts.getContainingClass(node)) { return ts.Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Class_definitions_are_automatically_in_strict_mode; } @@ -23340,33 +27106,42 @@ var ts; return ts.Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5; } function checkStrictModeFunctionDeclaration(node) { - if (languageVersion < 2) { - if (blockScopeContainer.kind !== 274 && - blockScopeContainer.kind !== 239 && + if (languageVersion < 2 /* ES2015 */) { + // Report error if function is not top level function declaration + if (blockScopeContainer.kind !== 274 /* SourceFile */ && + blockScopeContainer.kind !== 239 /* ModuleDeclaration */ && !ts.isFunctionLike(blockScopeContainer)) { + // We check first if the name is inside class declaration or class expression; if so give explicit message + // otherwise report generic error message. var errorSpan = ts.getErrorSpanForNode(file, node); file.bindDiagnostics.push(ts.createFileDiagnostic(file, errorSpan.start, errorSpan.length, getStrictModeBlockScopeFunctionDeclarationMessage(node))); } } } function checkStrictModeNumericLiteral(node) { - if (inStrictMode && node.numericLiteralFlags & 32) { + if (inStrictMode && node.numericLiteralFlags & 32 /* Octal */) { file.bindDiagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.Octal_literals_are_not_allowed_in_strict_mode)); } } function checkStrictModePostfixUnaryExpression(node) { + // Grammar checking + // The identifier eval or arguments may not appear as the LeftHandSideExpression of an + // Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression + // operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator. if (inStrictMode) { checkStrictModeEvalOrArguments(node, node.operand); } } function checkStrictModePrefixUnaryExpression(node) { + // Grammar checking if (inStrictMode) { - if (node.operator === 43 || node.operator === 44) { + if (node.operator === 43 /* PlusPlusToken */ || node.operator === 44 /* MinusMinusToken */) { checkStrictModeEvalOrArguments(node, node.operand); } } } function checkStrictModeWithStatement(node) { + // Grammar checking for withStatement if (inStrictMode) { errorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_strict_mode); } @@ -23391,12 +27166,36 @@ var ts; } node.parent = parent; var saveInStrictMode = inStrictMode; + // Even though in the AST the jsdoc @typedef node belongs to the current node, + // its symbol might be in the same scope with the current node's symbol. Consider: + // + // /** @typedef {string | number} MyType */ + // function foo(); + // + // Here the current node is "foo", which is a container, but the scope of "MyType" should + // not be inside "foo". Therefore we always bind @typedef before bind the parent node, + // and skip binding this tag later when binding all the other jsdoc tags. + // First we bind declaration nodes to a symbol if possible. We'll both create a symbol + // and then potentially add the symbol to an appropriate symbol table. Possible + // destination symbol tables are: + // + // 1) The 'exports' table of the current container's symbol. + // 2) The 'members' table of the current container's symbol. + // 3) The 'locals' table of the current container. + // + // 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); - if (node.kind > 145) { + // 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 + // a local should go into for example. Since terminal nodes are known not to have + // children, as an optimization we don't process those. + if (node.kind > 145 /* LastToken */) { var saveParent = parent; parent = node; var containerFlags = getContainerFlags(node); - if (containerFlags === 0) { + if (containerFlags === 0 /* None */) { bindChildren(node); } else { @@ -23404,7 +27203,7 @@ var ts; } parent = saveParent; } - else if (!skipTransformFlagAggregation && (node.transformFlags & 536870912) === 0) { + else if (!skipTransformFlagAggregation && (node.transformFlags & 536870912 /* HasComputedFlags */) === 0) { subtreeTransformFlags |= computeTransformFlagsForNode(node, 0); bindJSDoc(node); } @@ -23440,27 +27239,35 @@ var ts; } } } + /// Should be called only on prologue directives (isPrologueDirective(node) should be true) function isUseStrictPrologueDirective(node) { var nodeText = ts.getSourceTextOfNodeFromSourceFile(file, node.expression); + // Note: the node text must be exactly "use strict" or 'use strict'. It is not ok for the + // string to contain unicode escapes (as per ES5). return nodeText === '"use strict"' || nodeText === "'use strict'"; } function bindWorker(node) { switch (node.kind) { - case 71: + /* Strict mode checks */ + case 71 /* Identifier */: + // for typedef type names with namespaces, bind the new jsdoc type symbol here + // because it requires all containing namespaces to be in effect, namely the + // current "blockScopeContainer" needs to be set to its immediate namespace parent. if (node.isInJSDocNamespace) { var parentNode = node.parent; while (parentNode && !ts.isJSDocTypeAlias(parentNode)) { parentNode = parentNode.parent; } - bindBlockScopedDeclaration(parentNode, 524288, 67901928); + bindBlockScopedDeclaration(parentNode, 524288 /* TypeAlias */, 67901928 /* TypeAliasExcludes */); break; } - case 99: - if (currentFlow && (ts.isExpression(node) || parent.kind === 271)) { + // falls through + case 99 /* ThisKeyword */: + if (currentFlow && (ts.isExpression(node) || parent.kind === 271 /* ShorthandPropertyAssignment */)) { node.flowNode = currentFlow; } return checkStrictModeIdentifier(node); - case 185: + case 185 /* PropertyAccessExpression */: if (currentFlow && isNarrowableReference(node)) { node.flowNode = currentFlow; } @@ -23468,162 +27275,173 @@ var ts; bindSpecialPropertyDeclaration(node); } break; - case 200: + case 200 /* BinaryExpression */: var specialKind = ts.getSpecialPropertyAssignmentKind(node); switch (specialKind) { - case 1: + case 1 /* ExportsProperty */: bindExportsPropertyAssignment(node); break; - case 2: + case 2 /* ModuleExports */: bindModuleExportsAssignment(node); break; - case 3: + case 3 /* PrototypeProperty */: bindPrototypePropertyAssignment(node.left, node); break; - case 6: + case 6 /* Prototype */: bindPrototypeAssignment(node); break; - case 4: + case 4 /* ThisProperty */: bindThisPropertyAssignment(node); break; - case 5: + case 5 /* Property */: bindSpecialPropertyAssignment(node); break; - case 0: + case 0 /* None */: + // Nothing to do break; default: ts.Debug.fail("Unknown special property assignment kind"); } return checkStrictModeBinaryExpression(node); - case 269: + case 269 /* CatchClause */: return checkStrictModeCatchClause(node); - case 194: + case 194 /* DeleteExpression */: return checkStrictModeDeleteExpression(node); - case 8: + case 8 /* NumericLiteral */: return checkStrictModeNumericLiteral(node); - case 199: + case 199 /* PostfixUnaryExpression */: return checkStrictModePostfixUnaryExpression(node); - case 198: + case 198 /* PrefixUnaryExpression */: return checkStrictModePrefixUnaryExpression(node); - case 226: + case 226 /* WithStatement */: return checkStrictModeWithStatement(node); - case 174: + case 174 /* ThisType */: seenThisKeyword = true; return; - case 161: - break; - case 148: + case 161 /* TypePredicate */: + break; // Binding the children will handle everything + case 148 /* TypeParameter */: return bindTypeParameter(node); - case 149: + case 149 /* Parameter */: return bindParameter(node); - case 232: + case 232 /* VariableDeclaration */: return bindVariableDeclarationOrBindingElement(node); - case 182: + case 182 /* BindingElement */: node.flowNode = currentFlow; return bindVariableDeclarationOrBindingElement(node); - case 152: - case 151: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: return bindPropertyWorker(node); - case 270: - case 271: - return bindPropertyOrMethodOrAccessor(node, 4, 0); - case 273: - return bindPropertyOrMethodOrAccessor(node, 8, 68008959); - case 158: - case 159: - case 160: - return declareSymbolAndAddToSymbolTable(node, 131072, 0); - case 154: - case 153: - return bindPropertyOrMethodOrAccessor(node, 8192 | (node.questionToken ? 16777216 : 0), ts.isObjectLiteralMethod(node) ? 0 : 67208127); - case 234: + case 270 /* PropertyAssignment */: + case 271 /* ShorthandPropertyAssignment */: + return bindPropertyOrMethodOrAccessor(node, 4 /* Property */, 0 /* PropertyExcludes */); + case 273 /* EnumMember */: + return bindPropertyOrMethodOrAccessor(node, 8 /* EnumMember */, 68008959 /* EnumMemberExcludes */); + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 160 /* IndexSignature */: + return declareSymbolAndAddToSymbolTable(node, 131072 /* Signature */, 0 /* None */); + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + // If this is an ObjectLiteralExpression method, then it sits in the same space + // as other properties in the object literal. So we use SymbolFlags.PropertyExcludes + // so that it will conflict with any other object literal members with the same + // name. + return bindPropertyOrMethodOrAccessor(node, 8192 /* Method */ | (node.questionToken ? 16777216 /* Optional */ : 0 /* None */), ts.isObjectLiteralMethod(node) ? 0 /* PropertyExcludes */ : 67208127 /* MethodExcludes */); + case 234 /* FunctionDeclaration */: return bindFunctionDeclaration(node); - case 155: - return declareSymbolAndAddToSymbolTable(node, 16384, 0); - case 156: - return bindPropertyOrMethodOrAccessor(node, 32768, 67150783); - case 157: - return bindPropertyOrMethodOrAccessor(node, 65536, 67183551); - case 163: - case 284: - case 288: - case 164: + case 155 /* Constructor */: + return declareSymbolAndAddToSymbolTable(node, 16384 /* Constructor */, /*symbolExcludes:*/ 0 /* None */); + case 156 /* GetAccessor */: + return bindPropertyOrMethodOrAccessor(node, 32768 /* GetAccessor */, 67150783 /* GetAccessorExcludes */); + case 157 /* SetAccessor */: + return bindPropertyOrMethodOrAccessor(node, 65536 /* SetAccessor */, 67183551 /* SetAccessorExcludes */); + case 163 /* FunctionType */: + case 284 /* JSDocFunctionType */: + case 288 /* JSDocSignature */: + case 164 /* ConstructorType */: return bindFunctionOrConstructorType(node); - case 166: - case 287: - case 177: + case 166 /* TypeLiteral */: + case 287 /* JSDocTypeLiteral */: + case 177 /* MappedType */: return bindAnonymousTypeWorker(node); - case 184: + case 184 /* ObjectLiteralExpression */: return bindObjectLiteralExpression(node); - case 192: - case 193: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: return bindFunctionExpression(node); - case 187: + case 187 /* CallExpression */: if (ts.isInJavaScriptFile(node)) { bindCallExpression(node); } break; - case 205: - case 235: + // Members of classes, interfaces, and modules + case 205 /* ClassExpression */: + case 235 /* ClassDeclaration */: + // All classes are automatically in strict mode in ES6. inStrictMode = true; return bindClassLikeDeclaration(node); - case 236: - return bindBlockScopedDeclaration(node, 64, 67901832); - case 237: - return bindBlockScopedDeclaration(node, 524288, 67901928); - case 238: + case 236 /* InterfaceDeclaration */: + return bindBlockScopedDeclaration(node, 64 /* Interface */, 67901832 /* InterfaceExcludes */); + case 237 /* TypeAliasDeclaration */: + return bindBlockScopedDeclaration(node, 524288 /* TypeAlias */, 67901928 /* TypeAliasExcludes */); + case 238 /* EnumDeclaration */: return bindEnumDeclaration(node); - case 239: + case 239 /* ModuleDeclaration */: return bindModuleDeclaration(node); - case 263: + // Jsx-attributes + case 263 /* JsxAttributes */: return bindJsxAttributes(node); - case 262: - return bindJsxAttribute(node, 4, 0); - case 243: - case 246: - case 248: - case 252: - return declareSymbolAndAddToSymbolTable(node, 2097152, 2097152); - case 242: + case 262 /* JsxAttribute */: + return bindJsxAttribute(node, 4 /* Property */, 0 /* PropertyExcludes */); + // Imports and exports + case 243 /* ImportEqualsDeclaration */: + case 246 /* NamespaceImport */: + case 248 /* ImportSpecifier */: + case 252 /* ExportSpecifier */: + return declareSymbolAndAddToSymbolTable(node, 2097152 /* Alias */, 2097152 /* AliasExcludes */); + case 242 /* NamespaceExportDeclaration */: return bindNamespaceExportDeclaration(node); - case 245: + case 245 /* ImportClause */: return bindImportClause(node); - case 250: + case 250 /* ExportDeclaration */: return bindExportDeclaration(node); - case 249: + case 249 /* ExportAssignment */: return bindExportAssignment(node); - case 274: + case 274 /* SourceFile */: updateStrictModeStatementList(node.statements); return bindSourceFileIfExternalModule(); - case 213: + case 213 /* Block */: if (!ts.isFunctionLike(node.parent)) { return; } - case 240: + // falls through + case 240 /* ModuleBlock */: return updateStrictModeStatementList(node.statements); - case 293: - if (node.parent.kind === 288) { + case 293 /* JSDocParameterTag */: + if (node.parent.kind === 288 /* JSDocSignature */) { return bindParameter(node); } - if (node.parent.kind !== 287) { + if (node.parent.kind !== 287 /* JSDocTypeLiteral */) { break; } - case 299: + // falls through + case 299 /* JSDocPropertyTag */: var propTag = node; - var flags = propTag.isBracketed || propTag.typeExpression && propTag.typeExpression.type.kind === 283 ? - 4 | 16777216 : - 4; - return declareSymbolAndAddToSymbolTable(propTag, flags, 0); - case 298: - case 292: + var flags = propTag.isBracketed || propTag.typeExpression && propTag.typeExpression.type.kind === 283 /* JSDocOptionalType */ ? + 4 /* Property */ | 16777216 /* Optional */ : + 4 /* Property */; + return declareSymbolAndAddToSymbolTable(propTag, flags, 0 /* PropertyExcludes */); + case 298 /* JSDocTypedefTag */: + case 292 /* JSDocCallbackTag */: return (delayedTypeAliases || (delayedTypeAliases = [])).push(node); } } function bindPropertyWorker(node) { - return bindPropertyOrMethodOrAccessor(node, 4 | (node.questionToken ? 16777216 : 0), 0); + return bindPropertyOrMethodOrAccessor(node, 4 /* Property */ | (node.questionToken ? 16777216 /* Optional */ : 0 /* None */), 0 /* PropertyExcludes */); } function bindAnonymousTypeWorker(node) { - return bindAnonymousDeclaration(node, 2048, "__type"); + return bindAnonymousDeclaration(node, 2048 /* TypeLiteral */, "__type" /* Type */); } function bindSourceFileIfExternalModule() { setExportContextFlag(file); @@ -23632,30 +27450,36 @@ var ts; } else if (ts.isJsonSourceFile(file)) { bindSourceFileAsExternalModule(); + // Create symbol equivalent for the module.exports = {} var originalSymbol = file.symbol; - declareSymbol(file.symbol.exports, file.symbol, file, 4, 67108863); + declareSymbol(file.symbol.exports, file.symbol, file, 4 /* Property */, 67108863 /* All */); file.symbol = originalSymbol; } } function bindSourceFileAsExternalModule() { - bindAnonymousDeclaration(file, 512, "\"" + ts.removeFileExtension(file.fileName) + "\""); + bindAnonymousDeclaration(file, 512 /* ValueModule */, "\"" + ts.removeFileExtension(file.fileName) + "\""); } function bindExportAssignment(node) { if (!container.symbol || !container.symbol.exports) { - bindAnonymousDeclaration(node, 2097152, getDeclarationName(node)); + // Export assignment in some sort of block construct + bindAnonymousDeclaration(node, 2097152 /* Alias */, getDeclarationName(node)); } else { - var flags = node.kind === 249 && ts.exportAssignmentIsAlias(node) - ? 2097152 - : 4; - declareSymbol(container.symbol.exports, container.symbol, node, flags, 67108863); + var flags = node.kind === 249 /* ExportAssignment */ && ts.exportAssignmentIsAlias(node) + // An export default clause with an EntityNameExpression or a class expression exports all meanings of that identifier or expression; + ? 2097152 /* Alias */ + // An export default clause with any other expression exports a value + : 4 /* Property */; + // If there is an `export default x;` alias declaration, can't `export default` anything else. + // (In contrast, you can still have `export default function f() {}` and `export default interface I {}`.) + declareSymbol(container.symbol.exports, container.symbol, node, flags, 67108863 /* All */); } } function bindNamespaceExportDeclaration(node) { if (node.modifiers && node.modifiers.length) { file.bindDiagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.Modifiers_cannot_appear_here)); } - if (node.parent.kind !== 274) { + if (node.parent.kind !== 274 /* SourceFile */) { file.bindDiagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.Global_module_exports_may_only_appear_at_top_level)); return; } @@ -23671,19 +27495,21 @@ var ts; } } file.symbol.globalExports = file.symbol.globalExports || ts.createSymbolTable(); - declareSymbol(file.symbol.globalExports, file.symbol, node, 2097152, 2097152); + declareSymbol(file.symbol.globalExports, file.symbol, node, 2097152 /* Alias */, 2097152 /* AliasExcludes */); } function bindExportDeclaration(node) { if (!container.symbol || !container.symbol.exports) { - bindAnonymousDeclaration(node, 8388608, getDeclarationName(node)); + // Export * in some sort of block construct + bindAnonymousDeclaration(node, 8388608 /* ExportStar */, getDeclarationName(node)); } else if (!node.exportClause) { - declareSymbol(container.symbol.exports, container.symbol, node, 8388608, 0); + // All export * declarations are collected in an __export symbol + declareSymbol(container.symbol.exports, container.symbol, node, 8388608 /* ExportStar */, 0 /* None */); } } function bindImportClause(node) { if (node.name) { - declareSymbolAndAddToSymbolTable(node, 2097152, 2097152); + declareSymbolAndAddToSymbolTable(node, 2097152 /* Alias */, 2097152 /* AliasExcludes */); } } function setCommonJsModuleIndicator(node) { @@ -23697,24 +27523,30 @@ var ts; return true; } function bindExportsPropertyAssignment(node) { + // When we create a property via 'exports.foo = bar', the 'exports.foo' property access + // expression is the declaration if (!setCommonJsModuleIndicator(node)) { return; } var lhs = node.left; - var symbol = forEachIdentifierInEntityName(lhs.expression, undefined, function (id, symbol) { + var symbol = forEachIdentifierInEntityName(lhs.expression, /*parent*/ undefined, function (id, symbol) { if (symbol) { - addDeclarationToSymbol(symbol, id, 1536 | 67108864); + addDeclarationToSymbol(symbol, id, 1536 /* Module */ | 67108864 /* JSContainer */); } return symbol; }); if (symbol) { var flags = ts.isClassExpression(node.right) ? - 4 | 1048576 | 32 : - 4 | 1048576; - declareSymbol(symbol.exports, symbol, lhs, flags, 0); + 4 /* Property */ | 1048576 /* ExportValue */ | 32 /* Class */ : + 4 /* Property */ | 1048576 /* ExportValue */; + declareSymbol(symbol.exports, symbol, lhs, flags, 0 /* None */); } } function bindModuleExportsAssignment(node) { + // A common practice in node modules is to set 'export = module.exports = {}', this ensures that 'exports' + // is still pointing to 'module.exports'. + // We do not want to consider this as 'export=' since a module can have only one of these. + // Similarly we do not want to treat 'module.exports = exports' as an 'export='. if (!setCommonJsModuleIndicator(node)) { return; } @@ -23722,49 +27554,57 @@ var ts; if (ts.isEmptyObjectLiteral(assignedExpression) || container === file && isExportsOrModuleExportsOrAlias(file, assignedExpression)) { return; } + // 'module.exports = expr' assignment var flags = ts.exportAssignmentIsAlias(node) - ? 2097152 - : 4 | 1048576 | 512; - declareSymbol(file.symbol.exports, file.symbol, node, flags, 0); + ? 2097152 /* Alias */ + : 4 /* Property */ | 1048576 /* ExportValue */ | 512 /* ValueModule */; + declareSymbol(file.symbol.exports, file.symbol, node, flags, 0 /* None */); } function bindThisPropertyAssignment(node) { ts.Debug.assert(ts.isInJavaScriptFile(node)); - var thisContainer = ts.getThisContainer(node, false); + var thisContainer = ts.getThisContainer(node, /*includeArrowFunctions*/ false); switch (thisContainer.kind) { - case 234: - case 192: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: var constructorSymbol = thisContainer.symbol; - if (ts.isBinaryExpression(thisContainer.parent) && thisContainer.parent.operatorToken.kind === 58) { + // For `f.prototype.m = function() { this.x = 0; }`, `this.x = 0` should modify `f`'s members, not the function expression. + if (ts.isBinaryExpression(thisContainer.parent) && thisContainer.parent.operatorToken.kind === 58 /* EqualsToken */) { var l = thisContainer.parent.left; if (ts.isPropertyAccessEntityNameExpression(l) && ts.isPrototypeAccess(l.expression)) { constructorSymbol = lookupSymbolForPropertyAccess(l.expression.expression, thisParentContainer); } } if (constructorSymbol) { + // Declare a 'member' if the container is an ES5 class or ES6 constructor constructorSymbol.members = constructorSymbol.members || ts.createSymbolTable(); - declareSymbol(constructorSymbol.members, constructorSymbol, node, 4, 0 & ~4); + // It's acceptable for multiple 'this' assignments of the same identifier to occur + declareSymbol(constructorSymbol.members, constructorSymbol, node, 4 /* Property */, 0 /* PropertyExcludes */ & ~4 /* Property */); } break; - case 155: - case 152: - case 154: - case 156: - case 157: + case 155 /* Constructor */: + case 152 /* PropertyDeclaration */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + // this.foo assignment in a JavaScript class + // Bind this property to the containing class var containingClass = thisContainer.parent; - var symbolTable = ts.hasModifier(thisContainer, 32) ? containingClass.symbol.exports : containingClass.symbol.members; - declareSymbol(symbolTable, containingClass.symbol, node, 4, 0, true); + var symbolTable = ts.hasModifier(thisContainer, 32 /* Static */) ? containingClass.symbol.exports : containingClass.symbol.members; + declareSymbol(symbolTable, containingClass.symbol, node, 4 /* Property */, 0 /* None */, /*isReplaceableByMethod*/ true); break; - case 274: + case 274 /* SourceFile */: + // this.foo assignment in a source file + // Do not bind. It would be nice to support this someday though. break; default: ts.Debug.fail(ts.Debug.showSyntaxKind(thisContainer)); } } function bindSpecialPropertyDeclaration(node) { - if (node.expression.kind === 99) { + if (node.expression.kind === 99 /* ThisKeyword */) { bindThisPropertyAssignment(node); } - else if (ts.isPropertyAccessEntityNameExpression(node) && node.parent.parent.kind === 274) { + else if (ts.isPropertyAccessEntityNameExpression(node) && node.parent.parent.kind === 274 /* SourceFile */) { if (ts.isPrototypeAccess(node.expression)) { bindPrototypePropertyAssignment(node, node.parent); } @@ -23773,44 +27613,61 @@ var ts; } } } + /** For `x.prototype = { p, ... }`, declare members p,... if `x` is function/class/{}, or not declared. */ function bindPrototypeAssignment(node) { node.left.parent = node; node.right.parent = node; var lhs = node.left; - bindPropertyAssignment(lhs, lhs, false); + bindPropertyAssignment(lhs, lhs, /*isPrototypeProperty*/ false); } + /** + * For `x.prototype.y = z`, declare a member `y` on `x` if `x` is a function or class, or not declared. + * Note that jsdoc preceding an ExpressionStatement like `x.prototype.y;` is also treated as a declaration. + */ function bindPrototypePropertyAssignment(lhs, parent) { + // Look up the function in the local scope, since prototype assignments should + // follow the function declaration var classPrototype = lhs.expression; var constructorFunction = classPrototype.expression; + // Fix up parent pointers since we're going to use these nodes before we bind into them lhs.parent = parent; constructorFunction.parent = classPrototype; classPrototype.parent = lhs; - bindPropertyAssignment(constructorFunction, lhs, true); + bindPropertyAssignment(constructorFunction, lhs, /*isPrototypeProperty*/ true); } function bindSpecialPropertyAssignment(node) { var lhs = node.left; + // Fix up parent pointers since we're going to use these nodes before we bind into them node.left.parent = node; node.right.parent = node; if (ts.isIdentifier(lhs.expression) && container === file && isNameOfExportsOrModuleExportsAliasDeclaration(file, lhs.expression)) { + // This can be an alias for the 'exports' or 'module.exports' names, e.g. + // var util = module.exports; + // util.property = function ... bindExportsPropertyAssignment(node); } else { bindStaticPropertyAssignment(lhs); } } + /** + * For nodes like `x.y = z`, declare a member 'y' on 'x' if x is a function (or IIFE) or class or {}, or not declared. + * Also works for expression statements preceded by JSDoc, like / ** @type number * / x.y; + */ function bindStaticPropertyAssignment(node) { node.expression.parent = node; - bindPropertyAssignment(node.expression, node, false); + bindPropertyAssignment(node.expression, node, /*isPrototypeProperty*/ false); } function bindPropertyAssignment(name, propertyAccess, isPrototypeProperty) { var namespaceSymbol = lookupSymbolForPropertyAccess(name); var isToplevelNamespaceableInitializer = ts.isBinaryExpression(propertyAccess.parent) - ? getParentOfBinaryExpression(propertyAccess.parent).parent.kind === 274 && + ? getParentOfBinaryExpression(propertyAccess.parent).parent.kind === 274 /* SourceFile */ && !!ts.getJavascriptInitializer(ts.getInitializerOfBinaryExpression(propertyAccess.parent), ts.isPrototypeAccess(propertyAccess.parent.left)) - : propertyAccess.parent.parent.kind === 274; - if (!isPrototypeProperty && (!namespaceSymbol || !(namespaceSymbol.flags & 1920)) && isToplevelNamespaceableInitializer) { - var flags_1 = 1536 | 67108864; - var excludeFlags_1 = 67215503 & ~67108864; + : propertyAccess.parent.parent.kind === 274 /* SourceFile */; + if (!isPrototypeProperty && (!namespaceSymbol || !(namespaceSymbol.flags & 1920 /* Namespace */)) && isToplevelNamespaceableInitializer) { + // make symbols or add declarations for intermediate containers + var flags_1 = 1536 /* Module */ | 67108864 /* JSContainer */; + var excludeFlags_1 = 67215503 /* ValueModuleExcludes */ & ~67108864 /* JSContainer */; namespaceSymbol = forEachIdentifierInEntityName(propertyAccess.expression, namespaceSymbol, function (id, symbol, parent) { if (symbol) { addDeclarationToSymbol(symbol, id, flags_1); @@ -23824,17 +27681,29 @@ var ts; if (!namespaceSymbol || !isJavascriptContainer(namespaceSymbol)) { return; } + // Set up the members collection if it doesn't exist already var symbolTable = isPrototypeProperty ? (namespaceSymbol.members || (namespaceSymbol.members = ts.createSymbolTable())) : (namespaceSymbol.exports || (namespaceSymbol.exports = ts.createSymbolTable())); - var jsContainerFlag = isToplevelNamespaceableInitializer ? 67108864 : 0; + // Declare the method/property + var jsContainerFlag = isToplevelNamespaceableInitializer ? 67108864 /* JSContainer */ : 0; var isMethod = ts.isFunctionLikeDeclaration(ts.getAssignedJavascriptInitializer(propertyAccess)); - var symbolFlags = (isMethod ? 8192 : 4) | jsContainerFlag; - var symbolExcludes = (isMethod ? 67208127 : 0) & ~jsContainerFlag; + var symbolFlags = (isMethod ? 8192 /* Method */ : 4 /* Property */) | jsContainerFlag; + var symbolExcludes = (isMethod ? 67208127 /* MethodExcludes */ : 0 /* PropertyExcludes */) & ~jsContainerFlag; declareSymbol(symbolTable, namespaceSymbol, propertyAccess, symbolFlags, symbolExcludes); } + /** + * Javascript containers are: + * - Functions + * - classes + * - namespaces + * - variables initialized with function expressions + * - with class expressions + * - with empty object literals + * - with non-empty object literals if assigned to the prototype property + */ function isJavascriptContainer(symbol) { - if (symbol.flags & (16 | 32 | 1024)) { + if (symbol.flags & (16 /* Function */ | 32 /* Class */ | 1024 /* NamespaceModule */)) { return true; } var node = symbol.valueDeclaration; @@ -23846,7 +27715,7 @@ var ts; init = init && ts.getRightMostAssignedExpression(init); if (init) { var isPrototypeAssignment = ts.isPrototypeAccess(ts.isVariableDeclaration(node) ? node.name : ts.isBinaryExpression(node) ? node.left : node); - return !!ts.getJavascriptInitializer(ts.isBinaryExpression(init) && init.operatorToken.kind === 54 ? init.right : init, isPrototypeAssignment); + return !!ts.getJavascriptInitializer(ts.isBinaryExpression(init) && init.operatorToken.kind === 54 /* BarBarToken */ ? init.right : init, isPrototypeAssignment); } return false; } @@ -23881,23 +27750,35 @@ var ts; } } function bindCallExpression(node) { - if (!file.commonJsModuleIndicator && ts.isRequireCall(node, false)) { + // We're only inspecting call expressions to detect CommonJS modules, so we can skip + // this check if we've already seen the module indicator + if (!file.commonJsModuleIndicator && ts.isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ false)) { setCommonJsModuleIndicator(node); } } function bindClassLikeDeclaration(node) { - if (node.kind === 235) { - bindBlockScopedDeclaration(node, 32, 68008383); + if (node.kind === 235 /* ClassDeclaration */) { + bindBlockScopedDeclaration(node, 32 /* Class */, 68008383 /* ClassExcludes */); } else { - var bindingName = node.name ? node.name.escapedText : "__class"; - bindAnonymousDeclaration(node, 32, bindingName); + var bindingName = node.name ? node.name.escapedText : "__class" /* Class */; + bindAnonymousDeclaration(node, 32 /* Class */, bindingName); + // Add name of class expression into the map for semantic classifier if (node.name) { classifiableNames.set(node.name.escapedText, true); } } var symbol = node.symbol; - var prototypeSymbol = createSymbol(4 | 4194304, "prototype"); + // TypeScript 1.0 spec (April 2014): 8.4 + // Every class automatically contains a static property member named 'prototype', the + // type of which is an instantiation of the class type with type Any supplied as a type + // argument for each type parameter. It is an error to explicitly declare a static + // property member with the name 'prototype'. + // + // Note: we check for this here because this class may be merging into a module. The + // module might have an exported variable called 'prototype'. We can't allow that as + // that would clash with the built-in 'prototype' for the class. + var prototypeSymbol = createSymbol(4 /* Property */ | 4194304 /* Prototype */, "prototype"); var symbolExport = symbol.exports.get(prototypeSymbol.escapedName); if (symbolExport) { if (node.name) { @@ -23910,8 +27791,8 @@ var ts; } function bindEnumDeclaration(node) { return ts.isConst(node) - ? bindBlockScopedDeclaration(node, 128, 68008831) - : bindBlockScopedDeclaration(node, 256, 68008191); + ? bindBlockScopedDeclaration(node, 128 /* ConstEnum */, 68008831 /* ConstEnumExcludes */) + : bindBlockScopedDeclaration(node, 256 /* RegularEnum */, 68008191 /* RegularEnumExcludes */); } function bindVariableDeclarationOrBindingElement(node) { if (inStrictMode) { @@ -23922,68 +27803,81 @@ var ts; bindBlockScopedVariableDeclaration(node); } else if (ts.isParameterDeclaration(node)) { - declareSymbolAndAddToSymbolTable(node, 1, 67216319); + // It is safe to walk up parent chain to find whether the node is a destructuring parameter declaration + // because its parent chain has already been set up, since parents are set before descending into children. + // + // If node is a binding element in parameter declaration, we need to use ParameterExcludes. + // Using ParameterExcludes flag allows the compiler to report an error on duplicate identifiers in Parameter Declaration + // For example: + // function foo([a,a]) {} // Duplicate Identifier error + // function bar(a,a) {} // Duplicate Identifier error, parameter declaration in this case is handled in bindParameter + // // which correctly set excluded symbols + declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 67216319 /* ParameterExcludes */); } else { - declareSymbolAndAddToSymbolTable(node, 1, 67216318); + declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 67216318 /* FunctionScopedVariableExcludes */); } } } function bindParameter(node) { - if (node.kind === 293 && container.kind !== 288) { + if (node.kind === 293 /* JSDocParameterTag */ && container.kind !== 288 /* JSDocSignature */) { return; } - if (inStrictMode && !(node.flags & 4194304)) { + if (inStrictMode && !(node.flags & 4194304 /* Ambient */)) { + // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a + // strict mode FunctionLikeDeclaration or FunctionExpression(13.1) checkStrictModeEvalOrArguments(node, node.name); } if (ts.isBindingPattern(node.name)) { - bindAnonymousDeclaration(node, 1, "__" + node.parent.parameters.indexOf(node)); + bindAnonymousDeclaration(node, 1 /* FunctionScopedVariable */, "__" + node.parent.parameters.indexOf(node)); } else { - declareSymbolAndAddToSymbolTable(node, 1, 67216319); + declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 67216319 /* ParameterExcludes */); } + // If this is a property-parameter, then also declare the property symbol into the + // containing class. if (ts.isParameterPropertyDeclaration(node)) { var classDeclaration = node.parent.parent; - declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, 4 | (node.questionToken ? 16777216 : 0), 0); + declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, 4 /* Property */ | (node.questionToken ? 16777216 /* Optional */ : 0 /* None */), 0 /* PropertyExcludes */); } } function bindFunctionDeclaration(node) { - if (!file.isDeclarationFile && !(node.flags & 4194304)) { + if (!file.isDeclarationFile && !(node.flags & 4194304 /* Ambient */)) { if (ts.isAsyncFunction(node)) { - emitFlags |= 1024; + emitFlags |= 1024 /* HasAsyncFunctions */; } } checkStrictModeFunctionName(node); if (inStrictMode) { checkStrictModeFunctionDeclaration(node); - bindBlockScopedDeclaration(node, 16, 67215791); + bindBlockScopedDeclaration(node, 16 /* Function */, 67215791 /* FunctionExcludes */); } else { - declareSymbolAndAddToSymbolTable(node, 16, 67215791); + declareSymbolAndAddToSymbolTable(node, 16 /* Function */, 67215791 /* FunctionExcludes */); } } function bindFunctionExpression(node) { - if (!file.isDeclarationFile && !(node.flags & 4194304)) { + if (!file.isDeclarationFile && !(node.flags & 4194304 /* Ambient */)) { if (ts.isAsyncFunction(node)) { - emitFlags |= 1024; + emitFlags |= 1024 /* HasAsyncFunctions */; } } if (currentFlow) { node.flowNode = currentFlow; } checkStrictModeFunctionName(node); - var bindingName = node.name ? node.name.escapedText : "__function"; - return bindAnonymousDeclaration(node, 16, bindingName); + var bindingName = node.name ? node.name.escapedText : "__function" /* Function */; + return bindAnonymousDeclaration(node, 16 /* Function */, bindingName); } function bindPropertyOrMethodOrAccessor(node, symbolFlags, symbolExcludes) { - if (!file.isDeclarationFile && !(node.flags & 4194304) && ts.isAsyncFunction(node)) { - emitFlags |= 1024; + if (!file.isDeclarationFile && !(node.flags & 4194304 /* Ambient */) && ts.isAsyncFunction(node)) { + emitFlags |= 1024 /* HasAsyncFunctions */; } if (currentFlow && ts.isObjectLiteralOrClassExpressionMethod(node)) { node.flowNode = currentFlow; } return ts.hasDynamicName(node) - ? bindAnonymousDeclaration(node, symbolFlags, "__computed") + ? bindAnonymousDeclaration(node, symbolFlags, "__computed" /* Computed */) : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); } function getInferTypeContainer(node) { @@ -23992,53 +27886,68 @@ var ts; } function bindTypeParameter(node) { if (ts.isJSDocTemplateTag(node.parent)) { - var container_1 = ts.find(node.parent.parent.tags, ts.isJSDocTypeAlias) || ts.getHostSignatureFromJSDoc(node.parent); + var container_1 = ts.find(node.parent.parent.tags, ts.isJSDocTypeAlias) || ts.getHostSignatureFromJSDoc(node.parent); // TODO: GH#18217 if (container_1) { if (!container_1.locals) { container_1.locals = ts.createSymbolTable(); } - declareSymbol(container_1.locals, undefined, node, 262144, 67639784); + declareSymbol(container_1.locals, /*parent*/ undefined, node, 262144 /* TypeParameter */, 67639784 /* TypeParameterExcludes */); } else { - declareSymbolAndAddToSymbolTable(node, 262144, 67639784); + declareSymbolAndAddToSymbolTable(node, 262144 /* TypeParameter */, 67639784 /* TypeParameterExcludes */); } } - else if (node.parent.kind === 172) { + else if (node.parent.kind === 172 /* InferType */) { var container_2 = getInferTypeContainer(node.parent); if (container_2) { if (!container_2.locals) { container_2.locals = ts.createSymbolTable(); } - declareSymbol(container_2.locals, undefined, node, 262144, 67639784); + declareSymbol(container_2.locals, /*parent*/ undefined, node, 262144 /* TypeParameter */, 67639784 /* TypeParameterExcludes */); } else { - bindAnonymousDeclaration(node, 262144, getDeclarationName(node)); + bindAnonymousDeclaration(node, 262144 /* TypeParameter */, getDeclarationName(node)); // TODO: GH#18217 } } else { - declareSymbolAndAddToSymbolTable(node, 262144, 67639784); + declareSymbolAndAddToSymbolTable(node, 262144 /* TypeParameter */, 67639784 /* TypeParameterExcludes */); } } + // reachability checks function shouldReportErrorOnModuleDeclaration(node) { var instanceState = getModuleInstanceState(node); - return instanceState === 1 || (instanceState === 2 && !!options.preserveConstEnums); + return instanceState === 1 /* Instantiated */ || (instanceState === 2 /* ConstEnumOnly */ && !!options.preserveConstEnums); } function checkUnreachable(node) { - if (!(currentFlow.flags & 1)) { + if (!(currentFlow.flags & 1 /* Unreachable */)) { return false; } if (currentFlow === unreachableFlow) { - var reportError = (ts.isStatementButNotDeclaration(node) && node.kind !== 215) || - node.kind === 235 || - (node.kind === 239 && shouldReportErrorOnModuleDeclaration(node)) || - (node.kind === 238 && (!ts.isConstEnumDeclaration(node) || options.preserveConstEnums)); + var reportError = + // report error on all statements except empty ones + (ts.isStatementButNotDeclaration(node) && node.kind !== 215 /* EmptyStatement */) || + // report error on class declarations + node.kind === 235 /* ClassDeclaration */ || + // report error on instantiated modules or const-enums only modules if preserveConstEnums is set + (node.kind === 239 /* ModuleDeclaration */ && shouldReportErrorOnModuleDeclaration(node)) || + // report error on regular enums and const enums if preserveConstEnums is set + (node.kind === 238 /* EnumDeclaration */ && (!ts.isConstEnumDeclaration(node) || options.preserveConstEnums)); if (reportError) { currentFlow = reportedUnreachableFlow; if (!options.allowUnreachableCode) { + // unreachable code is reported if + // - user has explicitly asked about it AND + // - statement is in not ambient context (statements in ambient context is already an error + // so we should not report extras) AND + // - node is not variable statement OR + // - node is block scoped variable statement OR + // - node is not block scoped variable statement and at least one variable declaration has initializer + // Rationale: we don't want to report errors on non-initialized var's since they are hoisted + // On the other side we do want to report errors on non-initialized 'lets' because of TDZ var isError = ts.unreachableCodeIsError(options) && - !(node.flags & 4194304) && + !(node.flags & 4194304 /* Ambient */) && (!ts.isVariableStatement(node) || - !!(ts.getCombinedNodeFlags(node.declarationList) & 3) || + !!(ts.getCombinedNodeFlags(node.declarationList) & 3 /* BlockScoped */) || node.declarationList.declarations.some(function (d) { return !!d.initializer; })); errorOrSuggestionOnFirstToken(isError, node, ts.Diagnostics.Unreachable_code_detected); } @@ -24047,6 +27956,7 @@ var ts; return true; } } + /* @internal */ function isExportsOrModuleExportsOrAlias(sourceFile, node) { return ts.isExportsIdentifier(node) || ts.isModuleExportsPropertyAccessExpression(node) || @@ -24060,7 +27970,7 @@ var ts; } function isExportsOrModuleExportsOrAliasOrAssignment(sourceFile, node) { return isExportsOrModuleExportsOrAlias(sourceFile, node) || - (ts.isAssignmentExpression(node, true) && (isExportsOrModuleExportsOrAliasOrAssignment(sourceFile, node.left) || isExportsOrModuleExportsOrAliasOrAssignment(sourceFile, node.right))); + (ts.isAssignmentExpression(node, /*excludeCompoundAssignment*/ true) && (isExportsOrModuleExportsOrAliasOrAssignment(sourceFile, node.left) || isExportsOrModuleExportsOrAliasOrAssignment(sourceFile, node.right))); } function lookupSymbolForNameWorker(container, name) { var local = container.locals && container.locals.get(name); @@ -24069,61 +27979,67 @@ var ts; } return container.symbol && container.symbol.exports && container.symbol.exports.get(name); } + /** + * 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 + */ function computeTransformFlagsForNode(node, subtreeFlags) { var kind = node.kind; switch (kind) { - case 187: + case 187 /* CallExpression */: return computeCallExpression(node, subtreeFlags); - case 188: + case 188 /* NewExpression */: return computeNewExpression(node, subtreeFlags); - case 239: + case 239 /* ModuleDeclaration */: return computeModuleDeclaration(node, subtreeFlags); - case 191: + case 191 /* ParenthesizedExpression */: return computeParenthesizedExpression(node, subtreeFlags); - case 200: + case 200 /* BinaryExpression */: return computeBinaryExpression(node, subtreeFlags); - case 216: + case 216 /* ExpressionStatement */: return computeExpressionStatement(node, subtreeFlags); - case 149: + case 149 /* Parameter */: return computeParameter(node, subtreeFlags); - case 193: + case 193 /* ArrowFunction */: return computeArrowFunction(node, subtreeFlags); - case 192: + case 192 /* FunctionExpression */: return computeFunctionExpression(node, subtreeFlags); - case 234: + case 234 /* FunctionDeclaration */: return computeFunctionDeclaration(node, subtreeFlags); - case 232: + case 232 /* VariableDeclaration */: return computeVariableDeclaration(node, subtreeFlags); - case 233: + case 233 /* VariableDeclarationList */: return computeVariableDeclarationList(node, subtreeFlags); - case 214: + case 214 /* VariableStatement */: return computeVariableStatement(node, subtreeFlags); - case 228: + case 228 /* LabeledStatement */: return computeLabeledStatement(node, subtreeFlags); - case 235: + case 235 /* ClassDeclaration */: return computeClassDeclaration(node, subtreeFlags); - case 205: + case 205 /* ClassExpression */: return computeClassExpression(node, subtreeFlags); - case 268: + case 268 /* HeritageClause */: return computeHeritageClause(node, subtreeFlags); - case 269: + case 269 /* CatchClause */: return computeCatchClause(node, subtreeFlags); - case 207: + case 207 /* ExpressionWithTypeArguments */: return computeExpressionWithTypeArguments(node, subtreeFlags); - case 155: + case 155 /* Constructor */: return computeConstructor(node, subtreeFlags); - case 152: + case 152 /* PropertyDeclaration */: return computePropertyDeclaration(node, subtreeFlags); - case 154: + case 154 /* MethodDeclaration */: return computeMethod(node, subtreeFlags); - case 156: - case 157: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return computeAccessor(node, subtreeFlags); - case 243: + case 243 /* ImportEqualsDeclaration */: return computeImportEquals(node, subtreeFlags); - case 185: + case 185 /* PropertyAccessExpression */: return computePropertyAccess(node, subtreeFlags); - case 186: + case 186 /* ElementAccessExpression */: return computeElementAccess(node, subtreeFlags); default: return computeOther(node, kind, subtreeFlags); @@ -24134,645 +28050,790 @@ var ts; var transformFlags = subtreeFlags; var expression = node.expression; if (node.typeArguments) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (subtreeFlags & 524288 - || (expression.transformFlags & (134217728 | 268435456))) { - transformFlags |= 192; - if (expression.transformFlags & 268435456) { - transformFlags |= 16384; + if (subtreeFlags & 524288 /* ContainsSpread */ + || (expression.transformFlags & (134217728 /* Super */ | 268435456 /* ContainsSuper */))) { + // If the this node contains a SpreadExpression, or is a super call, then it is an ES6 + // node. + transformFlags |= 192 /* AssertES2015 */; + // super property or element accesses could be inside lambdas, etc, and need a captured `this`, + // while super keyword for super calls (indicated by TransformFlags.Super) does not (since it can only be top-level in a constructor) + if (expression.transformFlags & 268435456 /* ContainsSuper */) { + transformFlags |= 16384 /* ContainsLexicalThis */; } } - if (expression.kind === 91) { - transformFlags |= 67108864; - if (subtreeFlags & 16384) { - transformFlags |= 32768; + if (expression.kind === 91 /* ImportKeyword */) { + transformFlags |= 67108864 /* ContainsDynamicImport */; + // A dynamic 'import()' call that contains a lexical 'this' will + // require a captured 'this' when emitting down-level. + if (subtreeFlags & 16384 /* ContainsLexicalThis */) { + transformFlags |= 32768 /* ContainsCapturedLexicalThis */; } } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~940049729; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~940049729 /* ArrayLiteralOrCallOrNewExcludes */; } function computeNewExpression(node, subtreeFlags) { var transformFlags = subtreeFlags; if (node.typeArguments) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (subtreeFlags & 524288) { - transformFlags |= 192; + if (subtreeFlags & 524288 /* ContainsSpread */) { + // If the this node contains a SpreadElementExpression then it is an ES6 + // node. + transformFlags |= 192 /* AssertES2015 */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~940049729; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~940049729 /* ArrayLiteralOrCallOrNewExcludes */; } function computeBinaryExpression(node, subtreeFlags) { var transformFlags = subtreeFlags; var operatorTokenKind = node.operatorToken.kind; var leftKind = node.left.kind; - if (operatorTokenKind === 58 && leftKind === 184) { - transformFlags |= 8 | 192 | 3072; + if (operatorTokenKind === 58 /* EqualsToken */ && leftKind === 184 /* ObjectLiteralExpression */) { + // Destructuring object assignments with are ES2015 syntax + // and possibly ESNext if they contain rest + transformFlags |= 8 /* AssertESNext */ | 192 /* AssertES2015 */ | 3072 /* AssertDestructuringAssignment */; } - else if (operatorTokenKind === 58 && leftKind === 183) { - transformFlags |= 192 | 3072; + else if (operatorTokenKind === 58 /* EqualsToken */ && leftKind === 183 /* ArrayLiteralExpression */) { + // Destructuring assignments are ES2015 syntax. + transformFlags |= 192 /* AssertES2015 */ | 3072 /* AssertDestructuringAssignment */; } - else if (operatorTokenKind === 40 - || operatorTokenKind === 62) { - transformFlags |= 32; + else if (operatorTokenKind === 40 /* AsteriskAsteriskToken */ + || operatorTokenKind === 62 /* AsteriskAsteriskEqualsToken */) { + // Exponentiation is ES2016 syntax. + transformFlags |= 32 /* AssertES2016 */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~939525441; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~939525441 /* NodeExcludes */; } function computeParameter(node, subtreeFlags) { var transformFlags = subtreeFlags; var name = node.name; var initializer = node.initializer; var dotDotDotToken = node.dotDotDotToken; + // The '?' token, type annotations, decorators, and 'this' parameters are TypeSCript + // syntax. if (node.questionToken || node.type - || subtreeFlags & 4096 + || subtreeFlags & 4096 /* ContainsDecorators */ || ts.isThisIdentifier(name)) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (ts.hasModifier(node, 92)) { - transformFlags |= 3 | 262144; + // If a parameter has an accessibility modifier, then it is TypeScript syntax. + if (ts.hasModifier(node, 92 /* ParameterPropertyModifier */)) { + transformFlags |= 3 /* AssertTypeScript */ | 262144 /* ContainsParameterPropertyAssignments */; } - if (subtreeFlags & 1048576) { - transformFlags |= 8; + // parameters with object rest destructuring are ES Next syntax + if (subtreeFlags & 1048576 /* ContainsObjectRest */) { + transformFlags |= 8 /* AssertESNext */; } - if (subtreeFlags & 8388608 || initializer || dotDotDotToken) { - transformFlags |= 192 | 131072; + // If a parameter has an initializer, a binding pattern or a dotDotDot token, then + // it is ES6 syntax and its container must emit default value assignments or parameter destructuring downlevel. + if (subtreeFlags & 8388608 /* ContainsBindingPattern */ || initializer || dotDotDotToken) { + transformFlags |= 192 /* AssertES2015 */ | 131072 /* ContainsDefaultValueAssignments */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~939525441; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~939525441 /* ParameterExcludes */; } function computeParenthesizedExpression(node, subtreeFlags) { var transformFlags = subtreeFlags; var expression = node.expression; var expressionKind = expression.kind; var expressionTransformFlags = expression.transformFlags; - if (expressionKind === 208 - || expressionKind === 190) { - transformFlags |= 3; + // If the node is synthesized, it means the emitter put the parentheses there, + // not the user. If we didn't want them, the emitter would not have put them + // there. + if (expressionKind === 208 /* AsExpression */ + || expressionKind === 190 /* TypeAssertionExpression */) { + transformFlags |= 3 /* AssertTypeScript */; } - if (expressionTransformFlags & 1024) { - transformFlags |= 1024; + // If the expression of a ParenthesizedExpression is a destructuring assignment, + // then the ParenthesizedExpression is a destructuring assignment. + if (expressionTransformFlags & 1024 /* DestructuringAssignment */) { + transformFlags |= 1024 /* DestructuringAssignment */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~536872257; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536872257 /* OuterExpressionExcludes */; } function computeClassDeclaration(node, subtreeFlags) { var transformFlags; - if (ts.hasModifier(node, 2)) { - transformFlags = 3; + if (ts.hasModifier(node, 2 /* Ambient */)) { + // An ambient declaration is TypeScript syntax. + transformFlags = 3 /* AssertTypeScript */; } else { - transformFlags = subtreeFlags | 192; - if ((subtreeFlags & 274432) + // A ClassDeclaration is ES6 syntax. + transformFlags = subtreeFlags | 192 /* AssertES2015 */; + // A class with a parameter property assignment, property initializer, computed property name, or decorator is + // TypeScript syntax. + // An exported declaration may be TypeScript syntax, but is handled by the visitor + // for a namespace declaration. + if ((subtreeFlags & 274432 /* TypeScriptClassSyntaxMask */) || node.typeParameters) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (subtreeFlags & 65536) { - transformFlags |= 16384; + if (subtreeFlags & 65536 /* ContainsLexicalThisInComputedPropertyName */) { + // A computed property name containing `this` might need to be rewritten, + // so propagate the ContainsLexicalThis flag upward. + transformFlags |= 16384 /* ContainsLexicalThis */; } } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~942011713; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~942011713 /* ClassExcludes */; } function computeClassExpression(node, subtreeFlags) { - var transformFlags = subtreeFlags | 192; - if (subtreeFlags & 274432 + // A ClassExpression is ES6 syntax. + var transformFlags = subtreeFlags | 192 /* AssertES2015 */; + // A class with a parameter property assignment, property initializer, or decorator is + // TypeScript syntax. + if (subtreeFlags & 274432 /* TypeScriptClassSyntaxMask */ || node.typeParameters) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (subtreeFlags & 65536) { - transformFlags |= 16384; + if (subtreeFlags & 65536 /* ContainsLexicalThisInComputedPropertyName */) { + // A computed property name containing `this` might need to be rewritten, + // so propagate the ContainsLexicalThis flag upward. + transformFlags |= 16384 /* ContainsLexicalThis */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~942011713; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~942011713 /* ClassExcludes */; } function computeHeritageClause(node, subtreeFlags) { var transformFlags = subtreeFlags; switch (node.token) { - case 85: - transformFlags |= 192; + case 85 /* ExtendsKeyword */: + // An `extends` HeritageClause is ES6 syntax. + transformFlags |= 192 /* AssertES2015 */; break; - case 108: - transformFlags |= 3; + case 108 /* ImplementsKeyword */: + // An `implements` HeritageClause is TypeScript syntax. + transformFlags |= 3 /* AssertTypeScript */; break; default: ts.Debug.fail("Unexpected token for heritage clause"); break; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~939525441; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~939525441 /* NodeExcludes */; } function computeCatchClause(node, subtreeFlags) { var transformFlags = subtreeFlags; if (!node.variableDeclaration) { - transformFlags |= 8; + transformFlags |= 8 /* AssertESNext */; } else if (ts.isBindingPattern(node.variableDeclaration.name)) { - transformFlags |= 192; + transformFlags |= 192 /* AssertES2015 */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~940574017; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~940574017 /* CatchClauseExcludes */; } function computeExpressionWithTypeArguments(node, subtreeFlags) { - var transformFlags = subtreeFlags | 192; + // An ExpressionWithTypeArguments is ES6 syntax, as it is used in the + // extends clause of a class. + var transformFlags = subtreeFlags | 192 /* AssertES2015 */; + // If an ExpressionWithTypeArguments contains type arguments, then it + // is TypeScript syntax. if (node.typeArguments) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~939525441; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~939525441 /* NodeExcludes */; } function computeConstructor(node, subtreeFlags) { var transformFlags = subtreeFlags; - if (ts.hasModifier(node, 2270) + // TypeScript-specific modifiers and overloads are TypeScript syntax + if (ts.hasModifier(node, 2270 /* TypeScriptModifier */) || !node.body) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (subtreeFlags & 1048576) { - transformFlags |= 8; + // function declarations with object rest destructuring are ES Next syntax + if (subtreeFlags & 1048576 /* ContainsObjectRest */) { + transformFlags |= 8 /* AssertESNext */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~1003668801; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~1003668801 /* ConstructorExcludes */; } function computeMethod(node, subtreeFlags) { - var transformFlags = subtreeFlags | 192; + // A MethodDeclaration is ES6 syntax. + var transformFlags = subtreeFlags | 192 /* AssertES2015 */; + // Decorators, TypeScript-specific modifiers, type parameters, type annotations, and + // overloads are TypeScript syntax. if (node.decorators - || ts.hasModifier(node, 2270) + || ts.hasModifier(node, 2270 /* TypeScriptModifier */) || node.typeParameters || node.type - || (node.name && ts.isComputedPropertyName(node.name)) + || (node.name && ts.isComputedPropertyName(node.name)) // While computed method names aren't typescript, the TS transform must visit them to emit property declarations correctly || !node.body) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (subtreeFlags & 1048576) { - transformFlags |= 8; + // function declarations with object rest destructuring are ES Next syntax + if (subtreeFlags & 1048576 /* ContainsObjectRest */) { + transformFlags |= 8 /* AssertESNext */; } - if (ts.hasModifier(node, 256)) { - transformFlags |= node.asteriskToken ? 8 : 16; + // An async method declaration is ES2017 syntax. + if (ts.hasModifier(node, 256 /* Async */)) { + transformFlags |= node.asteriskToken ? 8 /* AssertESNext */ : 16 /* AssertES2017 */; } if (node.asteriskToken) { - transformFlags |= 768; + transformFlags |= 768 /* AssertGenerator */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~1003668801; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~1003668801 /* MethodOrAccessorExcludes */; } function computeAccessor(node, subtreeFlags) { var transformFlags = subtreeFlags; + // Decorators, TypeScript-specific modifiers, type annotations, and overloads are + // TypeScript syntax. if (node.decorators - || ts.hasModifier(node, 2270) + || ts.hasModifier(node, 2270 /* TypeScriptModifier */) || node.type - || (node.name && ts.isComputedPropertyName(node.name)) + || (node.name && ts.isComputedPropertyName(node.name)) // While computed accessor names aren't typescript, the TS transform must visit them to emit property declarations correctly || !node.body) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (subtreeFlags & 1048576) { - transformFlags |= 8; + // function declarations with object rest destructuring are ES Next syntax + if (subtreeFlags & 1048576 /* ContainsObjectRest */) { + transformFlags |= 8 /* AssertESNext */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~1003668801; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~1003668801 /* MethodOrAccessorExcludes */; } function computePropertyDeclaration(node, subtreeFlags) { - var transformFlags = subtreeFlags | 3; + // A PropertyDeclaration is TypeScript syntax. + var transformFlags = subtreeFlags | 3 /* AssertTypeScript */; + // If the PropertyDeclaration has an initializer or a computed name, we need to inform its ancestor + // so that it handle the transformation. if (node.initializer || ts.isComputedPropertyName(node.name)) { - transformFlags |= 8192; + transformFlags |= 8192 /* ContainsPropertyInitializer */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~939525441; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~939525441 /* NodeExcludes */; } function computeFunctionDeclaration(node, subtreeFlags) { var transformFlags; var modifierFlags = ts.getModifierFlags(node); var body = node.body; - if (!body || (modifierFlags & 2)) { - transformFlags = 3; + if (!body || (modifierFlags & 2 /* Ambient */)) { + // An ambient declaration is TypeScript syntax. + // A FunctionDeclaration without a body is an overload and is TypeScript syntax. + transformFlags = 3 /* AssertTypeScript */; } else { - transformFlags = subtreeFlags | 33554432; - if (modifierFlags & 2270 + transformFlags = subtreeFlags | 33554432 /* ContainsHoistedDeclarationOrCompletion */; + // TypeScript-specific modifiers, type parameters, and type annotations are TypeScript + // syntax. + if (modifierFlags & 2270 /* TypeScriptModifier */ || node.typeParameters || node.type) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (modifierFlags & 256) { - transformFlags |= node.asteriskToken ? 8 : 16; + // An async function declaration is ES2017 syntax. + if (modifierFlags & 256 /* Async */) { + transformFlags |= node.asteriskToken ? 8 /* AssertESNext */ : 16 /* AssertES2017 */; } - if (subtreeFlags & 1048576) { - transformFlags |= 8; + // function declarations with object rest destructuring are ES Next syntax + if (subtreeFlags & 1048576 /* ContainsObjectRest */) { + transformFlags |= 8 /* AssertESNext */; } - if (subtreeFlags & 163840) { - transformFlags |= 192; + // If a FunctionDeclaration's subtree has marked the container as needing to capture the + // lexical this, or the function contains parameters with initializers, then this node is + // ES6 syntax. + if (subtreeFlags & 163840 /* ES2015FunctionSyntaxMask */) { + transformFlags |= 192 /* AssertES2015 */; } + // If a FunctionDeclaration is generator function and is the body of a + // transformed async function, then this node can be transformed to a + // down-level generator. + // Currently we do not support transforming any other generator fucntions + // down level. if (node.asteriskToken) { - transformFlags |= 768; + transformFlags |= 768 /* AssertGenerator */; } } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~1003935041; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~1003935041 /* FunctionExcludes */; } function computeFunctionExpression(node, subtreeFlags) { var transformFlags = subtreeFlags; - if (ts.hasModifier(node, 2270) + // TypeScript-specific modifiers, type parameters, and type annotations are TypeScript + // syntax. + if (ts.hasModifier(node, 2270 /* TypeScriptModifier */) || node.typeParameters || node.type) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (ts.hasModifier(node, 256)) { - transformFlags |= node.asteriskToken ? 8 : 16; + // An async function expression is ES2017 syntax. + if (ts.hasModifier(node, 256 /* Async */)) { + transformFlags |= node.asteriskToken ? 8 /* AssertESNext */ : 16 /* AssertES2017 */; } - if (subtreeFlags & 1048576) { - transformFlags |= 8; + // function expressions with object rest destructuring are ES Next syntax + if (subtreeFlags & 1048576 /* ContainsObjectRest */) { + transformFlags |= 8 /* AssertESNext */; } - if (subtreeFlags & 163840) { - transformFlags |= 192; + // If a FunctionExpression's subtree has marked the container as needing to capture the + // lexical this, or the function contains parameters with initializers, then this node is + // ES6 syntax. + if (subtreeFlags & 163840 /* ES2015FunctionSyntaxMask */) { + transformFlags |= 192 /* AssertES2015 */; } + // If a FunctionExpression is generator function and is the body of a + // transformed async function, then this node can be transformed to a + // down-level generator. if (node.asteriskToken) { - transformFlags |= 768; + transformFlags |= 768 /* AssertGenerator */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~1003935041; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~1003935041 /* FunctionExcludes */; } function computeArrowFunction(node, subtreeFlags) { - var transformFlags = subtreeFlags | 192; - if (ts.hasModifier(node, 2270) + // An ArrowFunction is ES6 syntax, and excludes markers that should not escape the scope of an ArrowFunction. + var transformFlags = subtreeFlags | 192 /* AssertES2015 */; + // TypeScript-specific modifiers, type parameters, and type annotations are TypeScript + // syntax. + if (ts.hasModifier(node, 2270 /* TypeScriptModifier */) || node.typeParameters || node.type) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (ts.hasModifier(node, 256)) { - transformFlags |= 16; + // An async arrow function is ES2017 syntax. + if (ts.hasModifier(node, 256 /* Async */)) { + transformFlags |= 16 /* AssertES2017 */; } - if (subtreeFlags & 1048576) { - transformFlags |= 8; + // arrow functions with object rest destructuring are ES Next syntax + if (subtreeFlags & 1048576 /* ContainsObjectRest */) { + transformFlags |= 8 /* AssertESNext */; } - if (subtreeFlags & 16384) { - transformFlags |= 32768; + // If an ArrowFunction contains a lexical this, its container must capture the lexical this. + if (subtreeFlags & 16384 /* ContainsLexicalThis */) { + transformFlags |= 32768 /* ContainsCapturedLexicalThis */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~1003902273; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~1003902273 /* ArrowFunctionExcludes */; } function computePropertyAccess(node, subtreeFlags) { var transformFlags = subtreeFlags; - if (transformFlags & 134217728) { - transformFlags ^= 134217728; - transformFlags |= 268435456; + // If a PropertyAccessExpression starts with a super keyword, then it is + // ES6 syntax, and requires a lexical `this` binding. + if (transformFlags & 134217728 /* Super */) { + transformFlags ^= 134217728 /* Super */; + transformFlags |= 268435456 /* ContainsSuper */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~671089985; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~671089985 /* PropertyAccessExcludes */; } function computeElementAccess(node, subtreeFlags) { var transformFlags = subtreeFlags; var expression = node.expression; - var expressionFlags = expression.transformFlags; - if (expressionFlags & 134217728) { - transformFlags &= ~134217728; - transformFlags |= 268435456; + var expressionFlags = expression.transformFlags; // We do not want to aggregate flags from the argument expression for super/this capturing + // If an ElementAccessExpression starts with a super keyword, then it is + // ES6 syntax, and requires a lexical `this` binding. + if (expressionFlags & 134217728 /* Super */) { + transformFlags &= ~134217728 /* Super */; + transformFlags |= 268435456 /* ContainsSuper */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~671089985; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~671089985 /* PropertyAccessExcludes */; } function computeVariableDeclaration(node, subtreeFlags) { var transformFlags = subtreeFlags; - transformFlags |= 192 | 8388608; - if (subtreeFlags & 1048576) { - transformFlags |= 8; + transformFlags |= 192 /* AssertES2015 */ | 8388608 /* ContainsBindingPattern */; + // A VariableDeclaration containing ObjectRest is ESNext syntax + if (subtreeFlags & 1048576 /* ContainsObjectRest */) { + transformFlags |= 8 /* AssertESNext */; } + // Type annotations are TypeScript syntax. if (node.type) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~939525441; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~939525441 /* NodeExcludes */; } function computeVariableStatement(node, subtreeFlags) { var transformFlags; var declarationListTransformFlags = node.declarationList.transformFlags; - if (ts.hasModifier(node, 2)) { - transformFlags = 3; + // An ambient declaration is TypeScript syntax. + if (ts.hasModifier(node, 2 /* Ambient */)) { + transformFlags = 3 /* AssertTypeScript */; } else { transformFlags = subtreeFlags; - if (declarationListTransformFlags & 8388608) { - transformFlags |= 192; + if (declarationListTransformFlags & 8388608 /* ContainsBindingPattern */) { + transformFlags |= 192 /* AssertES2015 */; } } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~939525441; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~939525441 /* NodeExcludes */; } function computeLabeledStatement(node, subtreeFlags) { var transformFlags = subtreeFlags; - if (subtreeFlags & 4194304 - && ts.isIterationStatement(node, true)) { - transformFlags |= 192; + // A labeled statement containing a block scoped binding *may* need to be transformed from ES6. + if (subtreeFlags & 4194304 /* ContainsBlockScopedBinding */ + && ts.isIterationStatement(node, /*lookInLabeledStatements*/ true)) { + transformFlags |= 192 /* AssertES2015 */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~939525441; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~939525441 /* NodeExcludes */; } function computeImportEquals(node, subtreeFlags) { var transformFlags = subtreeFlags; + // An ImportEqualsDeclaration with a namespace reference is TypeScript. if (!ts.isExternalModuleImportEqualsDeclaration(node)) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~939525441; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~939525441 /* NodeExcludes */; } function computeExpressionStatement(node, subtreeFlags) { var transformFlags = subtreeFlags; - if (node.expression.transformFlags & 1024) { - transformFlags |= 192; + // If the expression of an expression statement is a destructuring assignment, + // then we treat the statement as ES6 so that we can indicate that we do not + // need to hold on to the right-hand side. + if (node.expression.transformFlags & 1024 /* DestructuringAssignment */) { + transformFlags |= 192 /* AssertES2015 */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~939525441; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~939525441 /* NodeExcludes */; } function computeModuleDeclaration(node, subtreeFlags) { - var transformFlags = 3; + var transformFlags = 3 /* AssertTypeScript */; var modifierFlags = ts.getModifierFlags(node); - if ((modifierFlags & 2) === 0) { + if ((modifierFlags & 2 /* Ambient */) === 0) { transformFlags |= subtreeFlags; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~977327425; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~977327425 /* ModuleExcludes */; } function computeVariableDeclarationList(node, subtreeFlags) { - var transformFlags = subtreeFlags | 33554432; - if (subtreeFlags & 8388608) { - transformFlags |= 192; + var transformFlags = subtreeFlags | 33554432 /* ContainsHoistedDeclarationOrCompletion */; + if (subtreeFlags & 8388608 /* ContainsBindingPattern */) { + transformFlags |= 192 /* AssertES2015 */; } - if (node.flags & 3) { - transformFlags |= 192 | 4194304; + // If a VariableDeclarationList is `let` or `const`, then it is ES6 syntax. + if (node.flags & 3 /* BlockScoped */) { + transformFlags |= 192 /* AssertES2015 */ | 4194304 /* ContainsBlockScopedBinding */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~948962625; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~948962625 /* VariableDeclarationListExcludes */; } function computeOther(node, kind, subtreeFlags) { + // Mark transformations needed for each node var transformFlags = subtreeFlags; - var excludeFlags = 939525441; + var excludeFlags = 939525441 /* NodeExcludes */; switch (kind) { - case 120: - case 197: - transformFlags |= 8 | 16; + case 120 /* AsyncKeyword */: + case 197 /* AwaitExpression */: + // async/await is ES2017 syntax, but may be ESNext syntax (for async generators) + transformFlags |= 8 /* AssertESNext */ | 16 /* AssertES2017 */; break; - case 190: - case 208: - case 302: - transformFlags |= 3; - excludeFlags = 536872257; + case 190 /* TypeAssertionExpression */: + case 208 /* AsExpression */: + case 302 /* PartiallyEmittedExpression */: + // These nodes are TypeScript syntax. + transformFlags |= 3 /* AssertTypeScript */; + excludeFlags = 536872257 /* OuterExpressionExcludes */; break; - case 114: - case 112: - case 113: - case 117: - case 124: - case 76: - case 238: - case 273: - case 209: - case 132: - transformFlags |= 3; + case 114 /* PublicKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: + case 117 /* AbstractKeyword */: + case 124 /* DeclareKeyword */: + case 76 /* ConstKeyword */: + case 238 /* EnumDeclaration */: + case 273 /* EnumMember */: + case 209 /* NonNullExpression */: + case 132 /* ReadonlyKeyword */: + // These nodes are TypeScript syntax. + transformFlags |= 3 /* AssertTypeScript */; break; - case 255: - case 256: - case 257: - case 10: - case 258: - case 259: - case 260: - case 261: - case 262: - case 263: - case 264: - case 265: - transformFlags |= 4; + case 255 /* JsxElement */: + case 256 /* JsxSelfClosingElement */: + case 257 /* JsxOpeningElement */: + case 10 /* JsxText */: + case 258 /* JsxClosingElement */: + case 259 /* JsxFragment */: + case 260 /* JsxOpeningFragment */: + case 261 /* JsxClosingFragment */: + case 262 /* JsxAttribute */: + case 263 /* JsxAttributes */: + case 264 /* JsxSpreadAttribute */: + case 265 /* JsxExpression */: + // These nodes are Jsx syntax. + transformFlags |= 4 /* AssertJsx */; break; - case 13: - case 14: - case 15: - case 16: - case 202: - case 189: - case 271: - case 115: - case 210: - transformFlags |= 192; + case 13 /* NoSubstitutionTemplateLiteral */: + case 14 /* TemplateHead */: + case 15 /* TemplateMiddle */: + case 16 /* TemplateTail */: + case 202 /* TemplateExpression */: + case 189 /* TaggedTemplateExpression */: + case 271 /* ShorthandPropertyAssignment */: + case 115 /* StaticKeyword */: + case 210 /* MetaProperty */: + // These nodes are ES6 syntax. + transformFlags |= 192 /* AssertES2015 */; break; - case 9: + case 9 /* StringLiteral */: if (node.hasExtendedUnicodeEscape) { - transformFlags |= 192; + transformFlags |= 192 /* AssertES2015 */; } break; - case 8: - if (node.numericLiteralFlags & 384) { - transformFlags |= 192; + case 8 /* NumericLiteral */: + if (node.numericLiteralFlags & 384 /* BinaryOrOctalSpecifier */) { + transformFlags |= 192 /* AssertES2015 */; } break; - case 222: + case 222 /* ForOfStatement */: + // This node is either ES2015 syntax or ES2017 syntax (if it is a for-await-of). if (node.awaitModifier) { - transformFlags |= 8; + transformFlags |= 8 /* AssertESNext */; } - transformFlags |= 192; + transformFlags |= 192 /* AssertES2015 */; break; - case 203: - transformFlags |= 8 | 192 | 16777216; + case 203 /* YieldExpression */: + // This node is either ES2015 syntax (in a generator) or ES2017 syntax (in an async + // generator). + transformFlags |= 8 /* AssertESNext */ | 192 /* AssertES2015 */ | 16777216 /* ContainsYield */; break; - case 119: - case 134: - case 131: - case 135: - case 137: - case 122: - case 138: - case 105: - case 148: - case 151: - case 153: - case 158: - case 159: - case 160: - case 161: - case 162: - case 163: - case 164: - case 165: - case 166: - case 167: - case 168: - case 169: - case 170: - case 171: - case 172: - case 173: - case 236: - case 237: - case 174: - case 175: - case 176: - case 177: - case 178: - case 242: - transformFlags = 3; - excludeFlags = -3; + case 119 /* AnyKeyword */: + case 134 /* NumberKeyword */: + case 131 /* NeverKeyword */: + case 135 /* ObjectKeyword */: + case 137 /* StringKeyword */: + case 122 /* BooleanKeyword */: + case 138 /* SymbolKeyword */: + case 105 /* VoidKeyword */: + case 148 /* TypeParameter */: + case 151 /* PropertySignature */: + case 153 /* MethodSignature */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 160 /* IndexSignature */: + case 161 /* TypePredicate */: + case 162 /* TypeReference */: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 165 /* TypeQuery */: + case 166 /* TypeLiteral */: + case 167 /* ArrayType */: + case 168 /* TupleType */: + case 169 /* UnionType */: + case 170 /* IntersectionType */: + case 171 /* ConditionalType */: + case 172 /* InferType */: + case 173 /* ParenthesizedType */: + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 174 /* ThisType */: + case 175 /* TypeOperator */: + case 176 /* IndexedAccessType */: + case 177 /* MappedType */: + case 178 /* LiteralType */: + case 242 /* NamespaceExportDeclaration */: + // Types and signatures are TypeScript syntax, and exclude all other facts. + transformFlags = 3 /* AssertTypeScript */; + excludeFlags = -3 /* TypeExcludes */; break; - case 147: - transformFlags |= 2097152; - if (subtreeFlags & 16384) { - transformFlags |= 65536; + case 147 /* 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 |= 2097152 /* ContainsComputedPropertyName */; + if (subtreeFlags & 16384 /* ContainsLexicalThis */) { + // A computed method name like `[this.getName()](x: string) { ... }` needs to + // distinguish itself from the normal case of a method body containing `this`: + // `this` inside a method doesn't need to be rewritten (the method provides `this`), + // whereas `this` inside a computed name *might* need to be rewritten if the class/object + // is inside an arrow function: + // `_this = this; () => class K { [_this.getName()]() { ... } }` + // To make this distinction, use ContainsLexicalThisInComputedPropertyName + // instead of ContainsLexicalThis for computed property names + transformFlags |= 65536 /* ContainsLexicalThisInComputedPropertyName */; } break; - case 204: - transformFlags |= 192 | 524288; + case 204 /* SpreadElement */: + transformFlags |= 192 /* AssertES2015 */ | 524288 /* ContainsSpread */; break; - case 272: - transformFlags |= 8 | 1048576; + case 272 /* SpreadAssignment */: + transformFlags |= 8 /* AssertESNext */ | 1048576 /* ContainsObjectSpread */; break; - case 97: - transformFlags |= 192 | 134217728; - excludeFlags = 536872257; + case 97 /* SuperKeyword */: + // This node is ES6 syntax. + transformFlags |= 192 /* AssertES2015 */ | 134217728 /* Super */; + excludeFlags = 536872257 /* OuterExpressionExcludes */; // must be set to persist `Super` break; - case 99: - transformFlags |= 16384; + case 99 /* ThisKeyword */: + // Mark this node and its ancestors as containing a lexical `this` keyword. + transformFlags |= 16384 /* ContainsLexicalThis */; break; - case 180: - transformFlags |= 192 | 8388608; - if (subtreeFlags & 524288) { - transformFlags |= 8 | 1048576; + case 180 /* ObjectBindingPattern */: + transformFlags |= 192 /* AssertES2015 */ | 8388608 /* ContainsBindingPattern */; + if (subtreeFlags & 524288 /* ContainsRest */) { + transformFlags |= 8 /* AssertESNext */ | 1048576 /* ContainsObjectRest */; } - excludeFlags = 940049729; + excludeFlags = 940049729 /* BindingPatternExcludes */; break; - case 181: - transformFlags |= 192 | 8388608; - excludeFlags = 940049729; + case 181 /* ArrayBindingPattern */: + transformFlags |= 192 /* AssertES2015 */ | 8388608 /* ContainsBindingPattern */; + excludeFlags = 940049729 /* BindingPatternExcludes */; break; - case 182: - transformFlags |= 192; + case 182 /* BindingElement */: + transformFlags |= 192 /* AssertES2015 */; if (node.dotDotDotToken) { - transformFlags |= 524288; + transformFlags |= 524288 /* ContainsRest */; } break; - case 150: - transformFlags |= 3 | 4096; + case 150 /* Decorator */: + // This node is TypeScript syntax, and marks its container as also being TypeScript syntax. + transformFlags |= 3 /* AssertTypeScript */ | 4096 /* ContainsDecorators */; break; - case 184: - excludeFlags = 942740801; - if (subtreeFlags & 2097152) { - transformFlags |= 192; + case 184 /* ObjectLiteralExpression */: + excludeFlags = 942740801 /* ObjectLiteralExcludes */; + if (subtreeFlags & 2097152 /* ContainsComputedPropertyName */) { + // If an ObjectLiteralExpression contains a ComputedPropertyName, then it + // is an ES6 node. + transformFlags |= 192 /* AssertES2015 */; } - if (subtreeFlags & 65536) { - transformFlags |= 16384; + if (subtreeFlags & 65536 /* ContainsLexicalThisInComputedPropertyName */) { + // A computed property name containing `this` might need to be rewritten, + // so propagate the ContainsLexicalThis flag upward. + transformFlags |= 16384 /* ContainsLexicalThis */; } - if (subtreeFlags & 1048576) { - transformFlags |= 8; + if (subtreeFlags & 1048576 /* ContainsObjectSpread */) { + // If an ObjectLiteralExpression contains a spread element, then it + // is an ES next node. + transformFlags |= 8 /* AssertESNext */; } break; - case 183: - case 188: - excludeFlags = 940049729; - if (subtreeFlags & 524288) { - transformFlags |= 192; + case 183 /* ArrayLiteralExpression */: + case 188 /* NewExpression */: + excludeFlags = 940049729 /* ArrayLiteralOrCallOrNewExcludes */; + if (subtreeFlags & 524288 /* ContainsSpread */) { + // If the this node contains a SpreadExpression, then it is an ES6 + // node. + transformFlags |= 192 /* AssertES2015 */; } break; - case 218: - case 219: - case 220: - case 221: - if (subtreeFlags & 4194304) { - transformFlags |= 192; + case 218 /* DoStatement */: + case 219 /* WhileStatement */: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + // A loop containing a block scoped binding *may* need to be transformed from ES6. + if (subtreeFlags & 4194304 /* ContainsBlockScopedBinding */) { + transformFlags |= 192 /* AssertES2015 */; } break; - case 274: - if (subtreeFlags & 32768) { - transformFlags |= 192; + case 274 /* SourceFile */: + if (subtreeFlags & 32768 /* ContainsCapturedLexicalThis */) { + transformFlags |= 192 /* AssertES2015 */; } break; - case 225: - transformFlags |= 33554432 | 8; + case 225 /* ReturnStatement */: + // Return statements may require an `await` in ESNext. + transformFlags |= 33554432 /* ContainsHoistedDeclarationOrCompletion */ | 8 /* AssertESNext */; break; - case 223: - case 224: - transformFlags |= 33554432; + case 223 /* ContinueStatement */: + case 224 /* BreakStatement */: + transformFlags |= 33554432 /* ContainsHoistedDeclarationOrCompletion */; break; } - node.transformFlags = transformFlags | 536870912; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; return transformFlags & ~excludeFlags; } + /** + * Gets the transform flags to exclude when unioning the transform flags of a subtree. + * + * NOTE: This needs to be kept up-to-date with the exclusions used in `computeTransformFlagsForNode`. + * For performance reasons, `computeTransformFlagsForNode` uses local constant values rather + * than calling this function. + */ + /* @internal */ function getTransformFlagsSubtreeExclusions(kind) { - if (kind >= 161 && kind <= 179) { - return -3; + if (kind >= 161 /* FirstTypeNode */ && kind <= 179 /* LastTypeNode */) { + return -3 /* TypeExcludes */; } switch (kind) { - case 187: - case 188: - case 183: - return 940049729; - case 239: - return 977327425; - case 149: - return 939525441; - case 193: - return 1003902273; - case 192: - case 234: - return 1003935041; - case 233: - return 948962625; - case 235: - case 205: - return 942011713; - case 155: - return 1003668801; - case 154: - case 156: - case 157: - return 1003668801; - case 119: - case 134: - case 131: - case 137: - case 135: - case 122: - case 138: - case 105: - case 148: - case 151: - case 153: - case 158: - case 159: - case 160: - case 236: - case 237: - return -3; - case 184: - return 942740801; - case 269: - return 940574017; - case 180: - case 181: - return 940049729; - case 190: - case 208: - case 302: - case 191: - case 97: - return 536872257; - case 185: - case 186: - return 671089985; + case 187 /* CallExpression */: + case 188 /* NewExpression */: + case 183 /* ArrayLiteralExpression */: + return 940049729 /* ArrayLiteralOrCallOrNewExcludes */; + case 239 /* ModuleDeclaration */: + return 977327425 /* ModuleExcludes */; + case 149 /* Parameter */: + return 939525441 /* ParameterExcludes */; + case 193 /* ArrowFunction */: + return 1003902273 /* ArrowFunctionExcludes */; + case 192 /* FunctionExpression */: + case 234 /* FunctionDeclaration */: + return 1003935041 /* FunctionExcludes */; + case 233 /* VariableDeclarationList */: + return 948962625 /* VariableDeclarationListExcludes */; + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + return 942011713 /* ClassExcludes */; + case 155 /* Constructor */: + return 1003668801 /* ConstructorExcludes */; + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + return 1003668801 /* MethodOrAccessorExcludes */; + case 119 /* AnyKeyword */: + case 134 /* NumberKeyword */: + case 131 /* NeverKeyword */: + case 137 /* StringKeyword */: + case 135 /* ObjectKeyword */: + case 122 /* BooleanKeyword */: + case 138 /* SymbolKeyword */: + case 105 /* VoidKeyword */: + case 148 /* TypeParameter */: + case 151 /* PropertySignature */: + case 153 /* MethodSignature */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 160 /* IndexSignature */: + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: + return -3 /* TypeExcludes */; + case 184 /* ObjectLiteralExpression */: + return 942740801 /* ObjectLiteralExcludes */; + case 269 /* CatchClause */: + return 940574017 /* CatchClauseExcludes */; + case 180 /* ObjectBindingPattern */: + case 181 /* ArrayBindingPattern */: + return 940049729 /* BindingPatternExcludes */; + case 190 /* TypeAssertionExpression */: + case 208 /* AsExpression */: + case 302 /* PartiallyEmittedExpression */: + case 191 /* ParenthesizedExpression */: + case 97 /* SuperKeyword */: + return 536872257 /* OuterExpressionExcludes */; + case 185 /* PropertyAccessExpression */: + case 186 /* ElementAccessExpression */: + return 671089985 /* PropertyAccessExcludes */; default: - return 939525441; + return 939525441 /* NodeExcludes */; } } ts.getTransformFlagsSubtreeExclusions = getTransformFlagsSubtreeExclusions; + /** + * "Binds" JSDoc nodes in TypeScript code. + * Since we will never create symbols for JSDoc, we just set parent pointers instead. + */ function setParentPointers(parent, child) { child.parent = parent; ts.forEachChild(child, function (grandchild) { return setParentPointers(child, grandchild); }); } })(ts || (ts = {})); +/** @internal */ var ts; (function (ts) { function createGetSymbolWalker(getRestTypeOfSignature, getTypePredicateOfSignature, getReturnTypeOfSignature, getBaseTypes, resolveStructuredTypeMembers, getTypeOfSymbol, getResolvedSymbol, getIndexTypeOfStructuredType, getConstraintFromTypeParameter, getFirstIdentifier) { return getSymbolWalker; function getSymbolWalker(accept) { if (accept === void 0) { accept = function () { return true; }; } - var visitedTypes = []; - var visitedSymbols = []; + var visitedTypes = []; // Sparse array from id to type + var visitedSymbols = []; // Sparse array from id to symbol return { walkType: function (type) { try { @@ -24803,35 +28864,38 @@ var ts; return; } visitedTypes[type.id] = type; + // Reuse visitSymbol to visit the type's symbol, + // but be sure to bail on recuring into the type if accept declines the symbol. var shouldBail = visitSymbol(type.symbol); if (shouldBail) return; - if (type.flags & 131072) { + // Visit the type's related types, if any + if (type.flags & 131072 /* Object */) { var objectType = type; var objectFlags = objectType.objectFlags; - if (objectFlags & 4) { + if (objectFlags & 4 /* Reference */) { visitTypeReference(type); } - if (objectFlags & 32) { + if (objectFlags & 32 /* Mapped */) { visitMappedType(type); } - if (objectFlags & (1 | 2)) { + if (objectFlags & (1 /* Class */ | 2 /* Interface */)) { visitInterfaceType(type); } - if (objectFlags & (8 | 16)) { + if (objectFlags & (8 /* Tuple */ | 16 /* Anonymous */)) { visitObjectType(objectType); } } - if (type.flags & 65536) { + if (type.flags & 65536 /* TypeParameter */) { visitTypeParameter(type); } - if (type.flags & 786432) { + if (type.flags & 786432 /* UnionOrIntersection */) { visitUnionOrIntersectionType(type); } - if (type.flags & 1048576) { + if (type.flags & 1048576 /* Index */) { visitIndexType(type); } - if (type.flags & 2097152) { + if (type.flags & 2097152 /* IndexedAccess */) { visitIndexedAccessType(type); } } @@ -24879,10 +28943,11 @@ var ts; visitType(interfaceT.thisType); } function visitObjectType(type) { - var stringIndexType = getIndexTypeOfStructuredType(type, 0); + var stringIndexType = getIndexTypeOfStructuredType(type, 0 /* String */); visitType(stringIndexType); - var numberIndexType = getIndexTypeOfStructuredType(type, 1); + var numberIndexType = getIndexTypeOfStructuredType(type, 1 /* Number */); visitType(numberIndexType); + // The two checks above *should* have already resolved the type (if needed), so this should be cached var resolved = resolveStructuredTypeMembers(type); for (var _i = 0, _a = resolved.callSignatures; _i < _a.length; _i++) { var signature = _a[_i]; @@ -24910,12 +28975,16 @@ var ts; return true; } var t = getTypeOfSymbol(symbol); - visitType(t); - if (symbol.flags & 1955) { + visitType(t); // Should handle members on classes and such + if (symbol.flags & 1955 /* HasExports */) { symbol.exports.forEach(visitSymbol); } ts.forEach(symbol.declarations, function (d) { - if (d.type && d.type.kind === 165) { + // Type queries are too far resolved when we just visit the symbol's type + // (their type resolved directly to the member deeply referenced) + // So to get the intervening symbols, we need to check if there's a type + // query node on any of the symbol's declarations and get symbols there + if (d.type && d.type.kind === 165 /* TypeQuery */) { var query = d.type; var entity = getResolvedSymbol(getFirstIdentifier(query.exprName)); visitSymbol(entity); @@ -24927,6 +28996,7 @@ var ts; } ts.createGetSymbolWalker = createGetSymbolWalker; })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var ambientModuleSymbolRegex = /^".+"$/; @@ -24952,17 +29022,28 @@ var ts; ts.getSymbolId = getSymbolId; function isInstantiatedModule(node, preserveConstEnums) { var moduleState = ts.getModuleInstanceState(node); - return moduleState === 1 || - (preserveConstEnums && moduleState === 2); + return moduleState === 1 /* Instantiated */ || + (preserveConstEnums && moduleState === 2 /* ConstEnumOnly */); } ts.isInstantiatedModule = isInstantiatedModule; function createTypeChecker(host, produceDiagnostics) { + // Cancellation that controls whether or not we can cancel in the middle of type checking. + // In general cancelling is *not* safe for the type checker. We might be in the middle of + // computing something, and we will leave our internals in an inconsistent state. Callers + // who set the cancellation token should catch if a cancellation exception occurs, and + // should throw away and create a new TypeChecker. + // + // Currently we only support setting the cancellation token when getting diagnostics. This + // is because diagnostics can be quite expensive, and we want to allow hosts to bail out if + // they no longer need the information (for example, if the user started editing again). var cancellationToken; var requestedExternalEmitHelpers; var externalHelpersModule; + // tslint:disable variable-name var Symbol = ts.objectAllocator.getSymbolConstructor(); var Type = ts.objectAllocator.getTypeConstructor(); var Signature = ts.objectAllocator.getSignatureConstructor(); + // tslint:enable variable-name var typeCount = 0; var symbolCount = 0; var enumCount = 0; @@ -24981,12 +29062,18 @@ var ts; var keyofStringsOnly = !!compilerOptions.keyofStringsOnly; var emitResolver = createResolver(); var nodeBuilder = createNodeBuilder(); - var undefinedSymbol = createSymbol(4, "undefined"); + var undefinedSymbol = createSymbol(4 /* Property */, "undefined"); undefinedSymbol.declarations = []; - var argumentsSymbol = createSymbol(4, "arguments"); - var requireSymbol = createSymbol(4, "require"); - var moduleSymbol = createSymbol(4, "module"); + var argumentsSymbol = createSymbol(4 /* Property */, "arguments"); + var requireSymbol = createSymbol(4 /* Property */, "require"); + var moduleSymbol = createSymbol(4 /* Property */, "module"); + /** This will be set during calls to `getResolvedSignature` where services determines an apparent number of arguments greater than what is actually provided. */ var apparentArgumentCount; + // for public members that accept a Node or one of its subtypes, we must guard against + // synthetic nodes created during transformations by calling `getParseTreeNode`. + // for most of these, we perform the guard only on `checker` to avoid any possible + // extra cost of calling `getParseTreeNode` when calling these functions from inside the + // checker. var checker = { getNodeCount: function () { return ts.sum(host.getSourceFiles(), "nodeCount"); }, getIdentifierCount: function () { return ts.sum(host.getSourceFiles(), "identifierCount"); }, @@ -25129,13 +29216,13 @@ var ts; return parsed ? isImplementationOfOverload(parsed) : undefined; }, getImmediateAliasedSymbol: function (symbol) { - ts.Debug.assert((symbol.flags & 2097152) !== 0, "Should only get Alias here."); + ts.Debug.assert((symbol.flags & 2097152 /* Alias */) !== 0, "Should only get Alias here."); var links = getSymbolLinks(symbol); if (!links.immediateTarget) { var node = getDeclarationOfAliasSymbol(symbol); if (!node) return ts.Debug.fail(); - links.immediateTarget = getTargetOfAliasDeclaration(node, true); + links.immediateTarget = getTargetOfAliasDeclaration(node, /*dontRecursivelyResolve*/ true); } return links.immediateTarget; }, @@ -25157,7 +29244,9 @@ var ts; tryGetMemberInModuleExports: function (name, symbol) { return tryGetMemberInModuleExports(ts.escapeLeadingUnderscores(name), symbol); }, tryGetMemberInModuleExportsAndProperties: function (name, symbol) { return tryGetMemberInModuleExportsAndProperties(ts.escapeLeadingUnderscores(name), symbol); }, tryFindAmbientModuleWithoutAugmentations: function (moduleName) { - return tryFindAmbientModule(moduleName, false); + // we deliberately exclude augmentations + // since we are only interested in declarations of the module itself + return tryFindAmbientModule(moduleName, /*withAugmentations*/ false); }, getApparentType: getApparentType, getUnionType: getUnionType, @@ -25185,9 +29274,9 @@ var ts; getSuggestionForNonexistentSymbol: function (location, name, meaning) { return getSuggestionForNonexistentSymbol(location, ts.escapeLeadingUnderscores(name), meaning); }, getSuggestionForNonexistentModule: function (node, target) { return getSuggestionForNonexistentModule(node, target); }, getBaseConstraintOfType: getBaseConstraintOfType, - getDefaultFromTypeParameter: function (type) { return type && type.flags & 65536 ? getDefaultFromTypeParameter(type) : undefined; }, + getDefaultFromTypeParameter: function (type) { return type && type.flags & 65536 /* TypeParameter */ ? getDefaultFromTypeParameter(type) : undefined; }, resolveName: function (name, location, meaning, excludeGlobals) { - return resolveName(location, ts.escapeLeadingUnderscores(name), meaning, undefined, undefined, false, excludeGlobals); + return resolveName(location, ts.escapeLeadingUnderscores(name), meaning, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false, excludeGlobals); }, getJsxNamespace: function (n) { return ts.unescapeLeadingUnderscores(getJsxNamespace(n)); }, getAccessibleSymbolChain: getAccessibleSymbolChain, @@ -25204,11 +29293,15 @@ var ts; getSuggestionDiagnostics: function (file, ct) { var diagnostics; try { + // Record the cancellation token so it can be checked later on during checkSourceElement. + // Do this in a finally block so we can ensure that it gets reset back to nothing after + // this call is done. cancellationToken = ct; + // Ensure file is type checked checkSourceFile(file); - ts.Debug.assert(!!(getNodeLinks(file).flags & 1)); + ts.Debug.assert(!!(getNodeLinks(file).flags & 1 /* TypeChecked */)); diagnostics = ts.addRange(diagnostics, suggestionDiagnostics.get(file.fileName)); - if (!file.isDeclarationFile && (!unusedIsError(0) || !unusedIsError(1))) { + if (!file.isDeclarationFile && (!unusedIsError(0 /* Local */) || !unusedIsError(1 /* Parameter */))) { addUnusedDiagnostics(); } return diagnostics || ts.emptyArray; @@ -25241,56 +29334,63 @@ var ts; var indexedAccessTypes = ts.createMap(); var evolvingArrayTypes = []; var undefinedProperties = ts.createMap(); - var unknownSymbol = createSymbol(4, "unknown"); - var resolvingSymbol = createSymbol(0, "__resolving__"); - var anyType = createIntrinsicType(1, "any"); - var autoType = createIntrinsicType(1, "any"); - var wildcardType = createIntrinsicType(1, "any"); - var errorType = createIntrinsicType(1, "error"); - var unknownType = createIntrinsicType(2, "unknown"); - var undefinedType = createIntrinsicType(8192, "undefined"); - var undefinedWideningType = strictNullChecks ? undefinedType : createIntrinsicType(8192 | 134217728, "undefined"); - var nullType = createIntrinsicType(16384, "null"); - var nullWideningType = strictNullChecks ? nullType : createIntrinsicType(16384 | 134217728, "null"); - var stringType = createIntrinsicType(4, "string"); - var numberType = createIntrinsicType(8, "number"); - var falseType = createIntrinsicType(256, "false"); - var trueType = createIntrinsicType(256, "true"); + var unknownSymbol = createSymbol(4 /* Property */, "unknown"); + var resolvingSymbol = createSymbol(0, "__resolving__" /* Resolving */); + var anyType = createIntrinsicType(1 /* Any */, "any"); + var autoType = createIntrinsicType(1 /* Any */, "any"); + var wildcardType = createIntrinsicType(1 /* Any */, "any"); + var errorType = createIntrinsicType(1 /* Any */, "error"); + var unknownType = createIntrinsicType(2 /* Unknown */, "unknown"); + var undefinedType = createIntrinsicType(8192 /* Undefined */, "undefined"); + var undefinedWideningType = strictNullChecks ? undefinedType : createIntrinsicType(8192 /* Undefined */ | 134217728 /* ContainsWideningType */, "undefined"); + var nullType = createIntrinsicType(16384 /* Null */, "null"); + var nullWideningType = strictNullChecks ? nullType : createIntrinsicType(16384 /* Null */ | 134217728 /* ContainsWideningType */, "null"); + var stringType = createIntrinsicType(4 /* String */, "string"); + var numberType = createIntrinsicType(8 /* Number */, "number"); + var falseType = createIntrinsicType(256 /* BooleanLiteral */, "false"); + var trueType = createIntrinsicType(256 /* BooleanLiteral */, "true"); var booleanType = createBooleanType([falseType, trueType]); - var esSymbolType = createIntrinsicType(1024, "symbol"); - var voidType = createIntrinsicType(4096, "void"); - var neverType = createIntrinsicType(32768, "never"); - var silentNeverType = createIntrinsicType(32768, "never"); - var implicitNeverType = createIntrinsicType(32768, "never"); - var nonPrimitiveType = createIntrinsicType(16777216, "object"); + var esSymbolType = createIntrinsicType(1024 /* ESSymbol */, "symbol"); + var voidType = createIntrinsicType(4096 /* Void */, "void"); + var neverType = createIntrinsicType(32768 /* Never */, "never"); + var silentNeverType = createIntrinsicType(32768 /* Never */, "never"); + var implicitNeverType = createIntrinsicType(32768 /* Never */, "never"); + var nonPrimitiveType = createIntrinsicType(16777216 /* NonPrimitive */, "object"); var stringNumberSymbolType = getUnionType([stringType, numberType, esSymbolType]); var keyofConstraintType = keyofStringsOnly ? stringType : stringNumberSymbolType; var emptyObjectType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, undefined, undefined); - var emptyTypeLiteralSymbol = createSymbol(2048, "__type"); + var emptyTypeLiteralSymbol = createSymbol(2048 /* TypeLiteral */, "__type" /* Type */); emptyTypeLiteralSymbol.members = ts.createSymbolTable(); var emptyTypeLiteralType = createAnonymousType(emptyTypeLiteralSymbol, emptySymbols, ts.emptyArray, ts.emptyArray, undefined, undefined); var emptyGenericType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, undefined, undefined); emptyGenericType.instantiations = ts.createMap(); var anyFunctionType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, undefined, undefined); - anyFunctionType.flags |= 536870912; + // The anyFunctionType contains the anyFunctionType by definition. The flag is further propagated + // in getPropagatingFlagsOfTypes, and it is checked in inferFromTypes. + anyFunctionType.flags |= 536870912 /* ContainsAnyFunctionType */; var noConstraintType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, undefined, undefined); var circularConstraintType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, undefined, undefined); var resolvingDefaultType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, undefined, undefined); - var markerSuperType = createType(65536); - var markerSubType = createType(65536); + var markerSuperType = createType(65536 /* TypeParameter */); + var markerSubType = createType(65536 /* TypeParameter */); markerSubType.constraint = markerSuperType; - var markerOtherType = createType(65536); + var markerOtherType = createType(65536 /* TypeParameter */); var noTypePredicate = createIdentifierTypePredicate("<>", 0, anyType); - var anySignature = createSignature(undefined, undefined, undefined, ts.emptyArray, anyType, undefined, 0, false, false); - var unknownSignature = createSignature(undefined, undefined, undefined, ts.emptyArray, errorType, undefined, 0, false, false); - var resolvingSignature = createSignature(undefined, undefined, undefined, ts.emptyArray, anyType, undefined, 0, false, false); - var silentNeverSignature = createSignature(undefined, undefined, undefined, ts.emptyArray, silentNeverType, undefined, 0, false, false); + var anySignature = createSignature(undefined, undefined, undefined, ts.emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); + var unknownSignature = createSignature(undefined, undefined, undefined, ts.emptyArray, errorType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); + var resolvingSignature = createSignature(undefined, undefined, undefined, ts.emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); + var silentNeverSignature = createSignature(undefined, undefined, undefined, ts.emptyArray, silentNeverType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); var resolvingSignaturesArray = [resolvingSignature]; - var enumNumberIndexInfo = createIndexInfo(stringType, true); - var jsObjectLiteralIndexInfo = createIndexInfo(anyType, false); + var enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true); + var jsObjectLiteralIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false); var globals = ts.createSymbolTable(); var reverseMappedCache = ts.createMap(); var ambientModulesCache; + /** + * List of every ambient module with a "*" wildcard. + * Unlike other ambient modules, these can't be stored in `globals` because symbol tables only deal with exact matches. + * This is only used if there is no exact match. + */ var patternAmbientModules; var globalObjectType; var globalFunctionType; @@ -25305,6 +29405,9 @@ var ts; var autoArrayType; var anyReadonlyArrayType; var deferredGlobalNonNullableTypeAlias; + // The library files are only loaded when the feature is used. + // This allows users to just specify library files they want to used through --lib + // and they will not get an error from not having unrelated library files var deferredGlobalESSymbolConstructorSymbol; var deferredGlobalESSymbolType; var deferredGlobalTypedPropertyDescriptorType; @@ -25321,7 +29424,7 @@ var ts; var deferredGlobalImportMetaType; var deferredGlobalExtractSymbol; var deferredNodes; - var allPotentiallyUnusedIdentifiers = ts.createMap(); + var allPotentiallyUnusedIdentifiers = ts.createMap(); // key is file name var flowLoopStart = 0; var flowLoopCount = 0; var sharedFlowCount = 0; @@ -25346,6 +29449,7 @@ var ts; var potentialNewTargetCollisions = []; var awaitedTypeStack = []; var diagnostics = ts.createDiagnosticCollection(); + // Suggestion diagnostics must have a file. Keyed by source file name. var suggestionDiagnostics = ts.createMultiMap(); var TypeFacts; (function (TypeFacts) { @@ -25373,6 +29477,9 @@ var ts; TypeFacts[TypeFacts["Truthy"] = 1048576] = "Truthy"; TypeFacts[TypeFacts["Falsy"] = 2097152] = "Falsy"; TypeFacts[TypeFacts["All"] = 4194303] = "All"; + // The following members encode facts about particular kinds of types for use in the getTypeFacts function. + // The presence of a particular fact means that the given test is true for some (and possibly all) values + // of that kind of type. TypeFacts[TypeFacts["BaseStringStrictFacts"] = 933633] = "BaseStringStrictFacts"; TypeFacts[TypeFacts["BaseStringFacts"] = 3145473] = "BaseStringFacts"; TypeFacts[TypeFacts["StringStrictFacts"] = 4079361] = "StringStrictFacts"; @@ -25407,22 +29514,22 @@ var ts; TypeFacts[TypeFacts["NullFacts"] = 2340752] = "NullFacts"; })(TypeFacts || (TypeFacts = {})); var typeofEQFacts = ts.createMapFromTemplate({ - string: 1, - number: 2, - boolean: 4, - symbol: 8, - undefined: 16384, - object: 16, - function: 32 + string: 1 /* TypeofEQString */, + number: 2 /* TypeofEQNumber */, + boolean: 4 /* TypeofEQBoolean */, + symbol: 8 /* TypeofEQSymbol */, + undefined: 16384 /* EQUndefined */, + object: 16 /* TypeofEQObject */, + function: 32 /* TypeofEQFunction */ }); var typeofNEFacts = ts.createMapFromTemplate({ - string: 128, - number: 256, - boolean: 512, - symbol: 1024, - undefined: 131072, - object: 2048, - function: 4096 + string: 128 /* TypeofNEString */, + number: 256 /* TypeofNENumber */, + boolean: 512 /* TypeofNEBoolean */, + symbol: 1024 /* TypeofNESymbol */, + undefined: 131072 /* NEUndefined */, + object: 2048 /* TypeofNEObject */, + function: 4096 /* TypeofNEFunction */ }); var typeofTypesByName = ts.createMapFromTemplate({ string: stringType, @@ -25490,52 +29597,55 @@ var ts; var isNotOverloadAndNotAccessor = ts.and(isNotOverload, isNotAccessor); initializeTypeChecker(); return checker; + /** + * @deprecated + */ function getSymbolDisplayBuilder() { return { buildTypeDisplay: function (type, writer, enclosingDeclaration, flags) { typeToString(type, enclosingDeclaration, flags, emitTextWriterWrapper(writer)); }, buildSymbolDisplay: function (symbol, writer, enclosingDeclaration, meaning, flags) { - if (flags === void 0) { flags = 0; } - symbolToString(symbol, enclosingDeclaration, meaning, flags | 4, emitTextWriterWrapper(writer)); + if (flags === void 0) { flags = 0 /* None */; } + symbolToString(symbol, enclosingDeclaration, meaning, flags | 4 /* AllowAnyNodeKind */, emitTextWriterWrapper(writer)); }, buildSignatureDisplay: function (signature, writer, enclosing, flags, kind) { signatureToString(signature, enclosing, flags, kind, emitTextWriterWrapper(writer)); }, buildIndexSignatureDisplay: function (info, writer, kind, enclosing, flags) { - var sig = nodeBuilder.indexInfoToIndexSignatureDeclaration(info, kind, enclosing, toNodeBuilderFlags(flags) | 3112960, writer); + var sig = nodeBuilder.indexInfoToIndexSignatureDeclaration(info, kind, enclosing, toNodeBuilderFlags(flags) | 3112960 /* IgnoreErrors */, writer); var printer = ts.createPrinter({ removeComments: true }); - printer.writeNode(4, sig, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + printer.writeNode(4 /* Unspecified */, sig, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); }, buildParameterDisplay: function (symbol, writer, enclosing, flags) { - var node = nodeBuilder.symbolToParameterDeclaration(symbol, enclosing, toNodeBuilderFlags(flags) | 3112960, writer); + var node = nodeBuilder.symbolToParameterDeclaration(symbol, enclosing, toNodeBuilderFlags(flags) | 3112960 /* IgnoreErrors */, writer); var printer = ts.createPrinter({ removeComments: true }); - printer.writeNode(4, node, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + printer.writeNode(4 /* Unspecified */, node, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); // TODO: GH#18217 }, buildTypeParameterDisplay: function (tp, writer, enclosing, flags) { - var node = nodeBuilder.typeParameterToDeclaration(tp, enclosing, toNodeBuilderFlags(flags) | 3112960 | 8192, writer); + var node = nodeBuilder.typeParameterToDeclaration(tp, enclosing, toNodeBuilderFlags(flags) | 3112960 /* IgnoreErrors */ | 8192 /* OmitParameterModifiers */, writer); var printer = ts.createPrinter({ removeComments: true }); - printer.writeNode(4, node, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + printer.writeNode(4 /* Unspecified */, node, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); // TODO: GH#18217 }, buildTypePredicateDisplay: function (predicate, writer, enclosing, flags) { typePredicateToString(predicate, enclosing, flags, emitTextWriterWrapper(writer)); }, buildTypeParameterDisplayFromSymbol: function (symbol, writer, enclosing, flags) { - var nodes = nodeBuilder.symbolToTypeParameterDeclarations(symbol, enclosing, toNodeBuilderFlags(flags) | 3112960, writer); + var nodes = nodeBuilder.symbolToTypeParameterDeclarations(symbol, enclosing, toNodeBuilderFlags(flags) | 3112960 /* IgnoreErrors */, writer); var printer = ts.createPrinter({ removeComments: true }); - printer.writeList(26896, nodes, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + printer.writeList(26896 /* TypeParameters */, nodes, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); }, buildDisplayForParametersAndDelimiters: function (thisParameter, parameters, writer, enclosing, originalFlags) { var printer = ts.createPrinter({ removeComments: true }); - var flags = 8192 | 3112960 | toNodeBuilderFlags(originalFlags); - var thisParameterArray = thisParameter ? [nodeBuilder.symbolToParameterDeclaration(thisParameter, enclosing, flags)] : []; - var params = ts.createNodeArray(thisParameterArray.concat(ts.map(parameters, function (param) { return nodeBuilder.symbolToParameterDeclaration(param, enclosing, flags); }))); - printer.writeList(1296, params, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + var flags = 8192 /* OmitParameterModifiers */ | 3112960 /* IgnoreErrors */ | toNodeBuilderFlags(originalFlags); + var thisParameterArray = thisParameter ? [nodeBuilder.symbolToParameterDeclaration(thisParameter, enclosing, flags)] : []; // TODO: GH#18217 + var params = ts.createNodeArray(thisParameterArray.concat(ts.map(parameters, function (param) { return nodeBuilder.symbolToParameterDeclaration(param, enclosing, flags); }))); // TODO: GH#18217 + printer.writeList(1296 /* CallExpressionArguments */, params, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); }, buildDisplayForTypeParametersAndDelimiters: function (typeParameters, writer, enclosing, flags) { var printer = ts.createPrinter({ removeComments: true }); - var args = ts.createNodeArray(ts.map(typeParameters, function (p) { return nodeBuilder.typeParameterToDeclaration(p, enclosing, toNodeBuilderFlags(flags)); })); - printer.writeList(26896, args, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + var args = ts.createNodeArray(ts.map(typeParameters, function (p) { return nodeBuilder.typeParameterToDeclaration(p, enclosing, toNodeBuilderFlags(flags)); })); // TODO: GH#18217 + printer.writeList(26896 /* TypeParameters */, args, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); }, buildReturnTypeDisplay: function (signature, writer, enclosing, flags) { writer.writePunctuation(":"); @@ -25544,9 +29654,9 @@ var ts; if (predicate) { return typePredicateToString(predicate, enclosing, flags, emitTextWriterWrapper(writer)); } - var node = nodeBuilder.typeToTypeNode(getReturnTypeOfSignature(signature), enclosing, toNodeBuilderFlags(flags) | 3112960, writer); + var node = nodeBuilder.typeToTypeNode(getReturnTypeOfSignature(signature), enclosing, toNodeBuilderFlags(flags) | 3112960 /* IgnoreErrors */, writer); var printer = ts.createPrinter({ removeComments: true }); - printer.writeNode(4, node, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + printer.writeNode(4 /* Unspecified */, node, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); // TODO: GH#18217 } }; function emitTextWriterWrapper(underlying) { @@ -25633,7 +29743,7 @@ var ts; } var jsxPragma = file.pragmas.get("jsx"); if (jsxPragma) { - var chosenpragma = ts.isArray(jsxPragma) ? jsxPragma[0] : jsxPragma; + var chosenpragma = ts.isArray(jsxPragma) ? jsxPragma[0] : jsxPragma; // TODO: GH#18217 file.localJsxFactory = ts.parseIsolatedEntityName(chosenpragma.arguments.factory, languageVersion); if (file.localJsxFactory) { return file.localJsxNamespace = getFirstIdentifier(file.localJsxFactory).escapedText; @@ -25656,6 +29766,8 @@ var ts; return _jsxNamespace; } function getEmitResolver(sourceFile, cancellationToken) { + // Ensure we have all the type information in place for this file so that all the + // emitter questions of this resolver will return the right information. getDiagnostics(sourceFile, cancellationToken); return emitResolver; } @@ -25679,47 +29791,47 @@ var ts; } function createSymbol(flags, name, checkFlags) { symbolCount++; - var symbol = (new Symbol(flags | 33554432, name)); + var symbol = (new Symbol(flags | 33554432 /* Transient */, name)); symbol.checkFlags = checkFlags || 0; return symbol; } function isTransientSymbol(symbol) { - return (symbol.flags & 33554432) !== 0; + return (symbol.flags & 33554432 /* Transient */) !== 0; } function getExcludedSymbolFlags(flags) { var result = 0; - if (flags & 2) - result |= 67216319; - if (flags & 1) - result |= 67216318; - if (flags & 4) - result |= 0; - if (flags & 8) - result |= 68008959; - if (flags & 16) - result |= 67215791; - if (flags & 32) - result |= 68008383; - if (flags & 64) - result |= 67901832; - if (flags & 256) - result |= 68008191; - if (flags & 128) - result |= 68008831; - if (flags & 512) - result |= 67215503; - if (flags & 8192) - result |= 67208127; - if (flags & 32768) - result |= 67150783; - if (flags & 65536) - result |= 67183551; - if (flags & 262144) - result |= 67639784; - if (flags & 524288) - result |= 67901928; - if (flags & 2097152) - result |= 2097152; + if (flags & 2 /* BlockScopedVariable */) + result |= 67216319 /* BlockScopedVariableExcludes */; + if (flags & 1 /* FunctionScopedVariable */) + result |= 67216318 /* FunctionScopedVariableExcludes */; + if (flags & 4 /* Property */) + result |= 0 /* PropertyExcludes */; + if (flags & 8 /* EnumMember */) + result |= 68008959 /* EnumMemberExcludes */; + if (flags & 16 /* Function */) + result |= 67215791 /* FunctionExcludes */; + if (flags & 32 /* Class */) + result |= 68008383 /* ClassExcludes */; + if (flags & 64 /* Interface */) + result |= 67901832 /* InterfaceExcludes */; + if (flags & 256 /* RegularEnum */) + result |= 68008191 /* RegularEnumExcludes */; + if (flags & 128 /* ConstEnum */) + result |= 68008831 /* ConstEnumExcludes */; + if (flags & 512 /* ValueModule */) + result |= 67215503 /* ValueModuleExcludes */; + if (flags & 8192 /* Method */) + result |= 67208127 /* MethodExcludes */; + if (flags & 32768 /* GetAccessor */) + result |= 67150783 /* GetAccessorExcludes */; + if (flags & 65536 /* SetAccessor */) + result |= 67183551 /* SetAccessorExcludes */; + if (flags & 262144 /* TypeParameter */) + result |= 67639784 /* TypeParameterExcludes */; + if (flags & 524288 /* TypeAlias */) + result |= 67901928 /* TypeAliasExcludes */; + if (flags & 2097152 /* Alias */) + result |= 2097152 /* AliasExcludes */; return result; } function recordMergedSymbol(target, source) { @@ -25744,20 +29856,27 @@ var ts; recordMergedSymbol(result, symbol); return result; } + /** + * Note: if target is transient, then it is mutable, and mergeSymbol with both mutate and return it. + * If target is not transient, mergeSymbol will produce a transient clone, mutate that and return it. + */ function mergeSymbol(target, source) { if (!(target.flags & getExcludedSymbolFlags(source.flags)) || - (source.flags | target.flags) & 67108864) { + (source.flags | target.flags) & 67108864 /* JSContainer */) { ts.Debug.assert(source !== target); - if (!(target.flags & 33554432)) { + if (!(target.flags & 33554432 /* Transient */)) { target = cloneSymbol(target); } - if (source.flags & 512 && target.flags & 512 && target.constEnumOnlyModule && !source.constEnumOnlyModule) { + // Javascript static-property-assignment declarations always merge, even though they are also values + if (source.flags & 512 /* ValueModule */ && target.flags & 512 /* ValueModule */ && target.constEnumOnlyModule && !source.constEnumOnlyModule) { + // reset flag when merging instantiated module into value module that has only const enums target.constEnumOnlyModule = false; } target.flags |= source.flags; if (source.valueDeclaration && (!target.valueDeclaration || ts.isEffectiveModuleDeclaration(target.valueDeclaration) && !ts.isEffectiveModuleDeclaration(source.valueDeclaration))) { + // other kinds of value declarations take precedence over modules target.valueDeclaration = source.valueDeclaration; } ts.addRange(target.declarations, source.declarations); @@ -25773,21 +29892,21 @@ var ts; } recordMergedSymbol(target, source); } - else if (target.flags & 1024) { + else if (target.flags & 1024 /* NamespaceModule */) { error(ts.getNameOfDeclaration(source.declarations[0]), ts.Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity, symbolToString(target)); } else { - var message_2 = target.flags & 384 || source.flags & 384 + var message_2 = target.flags & 384 /* Enum */ || source.flags & 384 /* Enum */ ? ts.Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations - : target.flags & 2 || source.flags & 2 + : target.flags & 2 /* BlockScopedVariable */ || source.flags & 2 /* BlockScopedVariable */ ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 : ts.Diagnostics.Duplicate_identifier_0; ts.forEach(source.declarations, function (node) { - var errorNode = (ts.getJavascriptInitializer(node, false) ? ts.getOuterNameOfJsInitializer(node) : ts.getNameOfDeclaration(node)) || node; + var errorNode = (ts.getJavascriptInitializer(node, /*isPrototypeAssignment*/ false) ? ts.getOuterNameOfJsInitializer(node) : ts.getNameOfDeclaration(node)) || node; error(errorNode, message_2, symbolToString(source)); }); ts.forEach(target.declarations, function (node) { - var errorNode = (ts.getJavascriptInitializer(node, false) ? ts.getOuterNameOfJsInitializer(node) : ts.getNameOfDeclaration(node)) || node; + var errorNode = (ts.getJavascriptInitializer(node, /*isPrototypeAssignment*/ false) ? ts.getOuterNameOfJsInitializer(node) : ts.getNameOfDeclaration(node)) || node; error(errorNode, message_2, symbolToString(source)); }); } @@ -25811,6 +29930,9 @@ var ts; function mergeModuleAugmentation(moduleName) { var moduleAugmentation = moduleName.parent; if (moduleAugmentation.symbol.declarations[0] !== moduleAugmentation) { + // this is a combined symbol for multiple augmentations within the same file. + // its symbol already has accumulated information for all declarations + // so we need to add it just once - do the work only for first declaration ts.Debug.assert(moduleAugmentation.symbol.declarations.length > 1); return; } @@ -25818,18 +29940,22 @@ var ts; mergeSymbolTable(globals, moduleAugmentation.symbol.exports); } else { - var moduleNotFoundError = !(moduleName.parent.parent.flags & 4194304) + // find a module that about to be augmented + // do not validate names of augmentations that are defined in ambient context + var moduleNotFoundError = !(moduleName.parent.parent.flags & 4194304 /* Ambient */) ? ts.Diagnostics.Invalid_module_name_in_augmentation_module_0_cannot_be_found : undefined; - var mainModule = resolveExternalModuleNameWorker(moduleName, moduleName, moduleNotFoundError, true); + var mainModule = resolveExternalModuleNameWorker(moduleName, moduleName, moduleNotFoundError, /*isForAugmentation*/ true); if (!mainModule) { return; } + // obtain item referenced by 'export=' mainModule = resolveExternalModuleSymbol(mainModule); - if (mainModule.flags & 1920) { + if (mainModule.flags & 1920 /* Namespace */) { mainModule = mergeSymbol(mainModule, moduleAugmentation.symbol); } else { + // moduleName will be a StringLiteral since this is not `declare global`. error(moduleName, ts.Diagnostics.Cannot_augment_module_0_because_it_resolves_to_a_non_module_entity, moduleName.text); } } @@ -25838,6 +29964,7 @@ var ts; source.forEach(function (sourceSymbol, id) { var targetSymbol = target.get(id); if (targetSymbol) { + // Error on redeclarations ts.forEach(targetSymbol.declarations, addDeclarationDiagnostic(ts.unescapeLeadingUnderscores(id), message)); } else { @@ -25849,7 +29976,7 @@ var ts; } } function getSymbolLinks(symbol) { - if (symbol.flags & 33554432) + if (symbol.flags & 33554432 /* Transient */) return symbol; var id = getSymbolId(symbol); return symbolLinks[id] || (symbolLinks[id] = {}); @@ -25859,30 +29986,38 @@ var ts; return nodeLinks[nodeId] || (nodeLinks[nodeId] = { flags: 0 }); } function isGlobalSourceFile(node) { - return node.kind === 274 && !ts.isExternalOrCommonJsModule(node); + return node.kind === 274 /* SourceFile */ && !ts.isExternalOrCommonJsModule(node); } function getSymbol(symbols, name, meaning) { if (meaning) { var symbol = symbols.get(name); if (symbol) { - ts.Debug.assert((ts.getCheckFlags(symbol) & 1) === 0, "Should never get an instantiated symbol here."); + ts.Debug.assert((ts.getCheckFlags(symbol) & 1 /* Instantiated */) === 0, "Should never get an instantiated symbol here."); if (symbol.flags & meaning) { return symbol; } - if (symbol.flags & 2097152) { + if (symbol.flags & 2097152 /* Alias */) { var target = resolveAlias(symbol); + // Unknown symbol means an error occurred in alias resolution, treat it as positive answer to avoid cascading errors if (target === unknownSymbol || target.flags & meaning) { return symbol; } } } } + // return undefined if we can't find a symbol. } + /** + * Get symbols that represent parameter-property-declaration as parameter and as property declaration + * @param parameter a parameterDeclaration node + * @param parameterName a name of the parameter to get the symbols for. + * @return a tuple of two symbols + */ function getSymbolsOfParameterPropertyDeclaration(parameter, parameterName) { var constructorDeclaration = parameter.parent; var classDeclaration = parameter.parent.parent; - var parameterSymbol = getSymbol(constructorDeclaration.locals, parameterName, 67216319); - var propertySymbol = getSymbol(getMembersOfSymbol(classDeclaration.symbol), parameterName, 67216319); + var parameterSymbol = getSymbol(constructorDeclaration.locals, parameterName, 67216319 /* Value */); + var propertySymbol = getSymbol(getMembersOfSymbol(classDeclaration.symbol), parameterName, 67216319 /* Value */); if (parameterSymbol && propertySymbol) { return [parameterSymbol, propertySymbol]; } @@ -25895,9 +30030,12 @@ var ts; if ((moduleKind && (declarationFile.externalModuleIndicator || useFile.externalModuleIndicator)) || (!compilerOptions.outFile && !compilerOptions.out) || isInTypeQuery(usage) || - declaration.flags & 4194304) { + declaration.flags & 4194304 /* Ambient */) { + // nodes are in different files and order cannot be determined return true; } + // declaration is after usage + // can be legal if usage is deferred (i.e. inside function or in initializer of instance property) if (isUsedInFunctionOrInstanceProperty(usage, declaration)) { return true; } @@ -25905,26 +30043,41 @@ var ts; return sourceFiles.indexOf(declarationFile) <= sourceFiles.indexOf(useFile); } if (declaration.pos <= usage.pos) { - if (declaration.kind === 182) { - var errorBindingElement = ts.getAncestor(usage, 182); + // declaration is before usage + if (declaration.kind === 182 /* BindingElement */) { + // still might be illegal if declaration and usage are both binding elements (eg var [a = b, b = b] = [1, 2]) + var errorBindingElement = ts.getAncestor(usage, 182 /* BindingElement */); if (errorBindingElement) { return ts.findAncestor(errorBindingElement, ts.isBindingElement) !== ts.findAncestor(declaration, ts.isBindingElement) || declaration.pos < errorBindingElement.pos; } - return isBlockScopedNameDeclaredBeforeUse(ts.getAncestor(declaration, 232), usage); + // or it might be illegal if usage happens before parent variable is declared (eg var [a] = a) + return isBlockScopedNameDeclaredBeforeUse(ts.getAncestor(declaration, 232 /* VariableDeclaration */), usage); } - else if (declaration.kind === 232) { + else if (declaration.kind === 232 /* VariableDeclaration */) { + // still might be illegal if usage is in the initializer of the variable declaration (eg var a = a) return !isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration, usage); } else if (ts.isClassDeclaration(declaration)) { + // still might be illegal if the usage is within a computed property name in the class (eg class A { static p = "a"; [A.p]() {} }) return !ts.findAncestor(usage, function (n) { return ts.isComputedPropertyName(n) && n.parent.parent === declaration; }); } return true; } - if (usage.parent.kind === 252 || (usage.parent.kind === 249 && usage.parent.isExportEquals)) { + // declaration is after usage, but it can still be legal if usage is deferred: + // 1. inside an export specifier + // 2. inside a function + // 3. inside an instance property initializer, a reference to a non-instance property + // 4. inside a static property initializer, a reference to a static method in the same class + // 5. inside a TS export= declaration (since we will move the export statement during emit to avoid TDZ) + // or if usage is in a type context: + // 1. inside a type query (typeof in type position) + if (usage.parent.kind === 252 /* ExportSpecifier */ || (usage.parent.kind === 249 /* ExportAssignment */ && usage.parent.isExportEquals)) { + // export specifiers do not use the variable, they only make it available for use return true; } - if (usage.kind === 249 && usage.isExportEquals) { + // When resolving symbols for exports, the `usage` location passed in can be the export site directly + if (usage.kind === 249 /* ExportAssignment */ && usage.isExportEquals) { return true; } var container = ts.getEnclosingBlockScopeContainer(declaration); @@ -25932,14 +30085,17 @@ var ts; function isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration, usage) { var container = ts.getEnclosingBlockScopeContainer(declaration); switch (declaration.parent.parent.kind) { - case 214: - case 220: - case 222: + case 214 /* VariableStatement */: + case 220 /* ForStatement */: + case 222 /* ForOfStatement */: + // variable statement/for/for-of statement case, + // use site should not be inside variable declaration (initializer of declaration or binding element) if (isSameScopeDescendentOf(usage, declaration, container)) { return true; } break; } + // ForIn/ForOf case - use site should not be used in expression part var grandparent = declaration.parent.parent; return ts.isForInOrOfStatement(grandparent) && isSameScopeDescendentOf(usage, grandparent.expression, container); } @@ -25952,16 +30108,16 @@ var ts; return true; } var initializerOfProperty = current.parent && - current.parent.kind === 152 && + current.parent.kind === 152 /* PropertyDeclaration */ && current.parent.initializer === current; if (initializerOfProperty) { - if (ts.hasModifier(current.parent, 32)) { - if (declaration.kind === 154) { + if (ts.hasModifier(current.parent, 32 /* Static */)) { + if (declaration.kind === 154 /* MethodDeclaration */) { return true; } } else { - var isDeclarationInstanceProperty = declaration.kind === 152 && !ts.hasModifier(declaration, 32); + var isDeclarationInstanceProperty = declaration.kind === 152 /* PropertyDeclaration */ && !ts.hasModifier(declaration, 32 /* Static */); if (!isDeclarationInstanceProperty || ts.getContainingClass(usage) !== ts.getContainingClass(declaration)) { return true; } @@ -25971,12 +30127,19 @@ var ts; }); } } + /** + * Resolve a given name for a given meaning at a given location. An error is reported if the name was not found and + * the nameNotFoundMessage argument is not undefined. Returns the resolved symbol, or undefined if no symbol with + * the given name can be found. + * + * @param isUse If true, this will count towards --noUnusedLocals / --noUnusedParameters. + */ function resolveName(location, name, meaning, nameNotFoundMessage, nameArg, isUse, excludeGlobals, suggestedNameNotFoundMessage) { if (excludeGlobals === void 0) { excludeGlobals = false; } return resolveNameHelper(location, name, meaning, nameNotFoundMessage, nameArg, isUse, excludeGlobals, getSymbol, suggestedNameNotFoundMessage); } function resolveNameHelper(location, name, meaning, nameNotFoundMessage, nameArg, isUse, excludeGlobals, lookup, suggestedNameNotFoundMessage) { - var originalLocation = location; + var originalLocation = location; // needed for did-you-mean error reporting, which gathers candidates starting from the original location var result; var lastLocation; var lastSelfReferenceLocation; @@ -25985,25 +30148,40 @@ var ts; var grandparent; var isInExternalModule = false; loop: while (location) { + // Locals of a source file are not in scope (because they get merged into the global symbol table) if (location.locals && !isGlobalSourceFile(location)) { if (result = lookup(location.locals, name, meaning)) { var useResult = true; if (ts.isFunctionLike(location) && lastLocation && lastLocation !== location.body) { - if (meaning & result.flags & 67901928 && lastLocation.kind !== 286) { - useResult = result.flags & 262144 + // symbol lookup restrictions for function-like declarations + // - Type parameters of a function are in scope in the entire function declaration, including the parameter + // list and return type. However, local types are only in scope in the function body. + // - parameters are only in the scope of function body + // This restriction does not apply to JSDoc comment types because they are parented + // at a higher level than type parameters would normally be + if (meaning & result.flags & 67901928 /* Type */ && lastLocation.kind !== 286 /* JSDocComment */) { + useResult = result.flags & 262144 /* TypeParameter */ + // type parameters are visible in parameter list, return type and type parameter list ? lastLocation === location.type || - lastLocation.kind === 149 || - lastLocation.kind === 148 + lastLocation.kind === 149 /* Parameter */ || + lastLocation.kind === 148 /* TypeParameter */ + // local types not visible outside the function body : false; } - if (meaning & 67216319 && result.flags & 1) { + if (meaning & 67216319 /* Value */ && result.flags & 1 /* FunctionScopedVariable */) { + // parameters are visible only inside function body, parameter list and return type + // technically for parameter list case here we might mix parameters and variables declared in function, + // however it is detected separately when checking initializers of parameters + // to make sure that they reference no variables declared after them. useResult = - lastLocation.kind === 149 || + lastLocation.kind === 149 /* Parameter */ || (lastLocation === location.type && !!ts.findAncestor(result.valueDeclaration, ts.isParameter)); } } - else if (location.kind === 171) { + else if (location.kind === 171 /* ConditionalType */) { + // A type parameter declared using 'infer T' in a conditional type is visible only in + // the true branch of the conditional type. useResult = lastLocation === location.trueType; } if (useResult) { @@ -26015,28 +30193,43 @@ var ts; } } switch (location.kind) { - case 274: + case 274 /* SourceFile */: if (!ts.isExternalOrCommonJsModule(location)) break; isInExternalModule = true; - case 239: + // falls through + case 239 /* ModuleDeclaration */: var moduleExports = getSymbolOfNode(location).exports; - if (location.kind === 274 || ts.isAmbientModule(location)) { - if (result = moduleExports.get("default")) { + if (location.kind === 274 /* SourceFile */ || ts.isAmbientModule(location)) { + // It's an external module. First see if the module has an export default and if the local + // name of that export default matches. + if (result = moduleExports.get("default" /* Default */)) { var localSymbol = ts.getLocalSymbolForExportDefault(result); if (localSymbol && (result.flags & meaning) && localSymbol.escapedName === name) { break loop; } result = undefined; } + // Because of module/namespace merging, a module's exports are in scope, + // yet we never want to treat an export specifier as putting a member in scope. + // Therefore, if the name we find is purely an export specifier, it is not actually considered in scope. + // Two things to note about this: + // 1. We have to check this without calling getSymbol. The problem with calling getSymbol + // on an export specifier is that it might find the export specifier itself, and try to + // resolve it as an alias. This will cause the checker to consider the export specifier + // a circular alias reference when it might not be. + // 2. We check === SymbolFlags.Alias in order to check that the symbol is *purely* + // an alias. If we used &, we'd be throwing out symbols that have non alias aspects, + // which is not the desired behavior. var moduleExport = moduleExports.get(name); if (moduleExport && - moduleExport.flags === 2097152 && - ts.getDeclarationOfKind(moduleExport, 252)) { + moduleExport.flags === 2097152 /* Alias */ && + ts.getDeclarationOfKind(moduleExport, 252 /* ExportSpecifier */)) { break; } } - if (name !== "default" && (result = lookup(moduleExports, name, meaning & 2623475))) { + // ES6 exports are also visible locally (except for 'default'), but commonjs exports are not (except typedefs) + if (name !== "default" /* Default */ && (result = lookup(moduleExports, name, meaning & 2623475 /* ModuleMember */))) { if (ts.isSourceFile(location) && location.commonJsModuleIndicator && !result.declarations.some(ts.isJSDocTypeAlias)) { result = undefined; } @@ -26045,37 +30238,48 @@ var ts; } } break; - case 238: - if (result = lookup(getSymbolOfNode(location).exports, name, meaning & 8)) { + case 238 /* EnumDeclaration */: + if (result = lookup(getSymbolOfNode(location).exports, name, meaning & 8 /* EnumMember */)) { break loop; } break; - case 152: - case 151: - if (ts.isClassLike(location.parent) && !ts.hasModifier(location, 32)) { + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + // TypeScript 1.0 spec (April 2014): 8.4.1 + // Initializer expressions for instance member variables are evaluated in the scope + // of the class constructor body but are not permitted to reference parameters or + // local variables of the constructor. This effectively means that entities from outer scopes + // by the same name as a constructor parameter or local variable are inaccessible + // in initializer expressions for instance member variables. + if (ts.isClassLike(location.parent) && !ts.hasModifier(location, 32 /* Static */)) { var ctor = findConstructorDeclaration(location.parent); if (ctor && ctor.locals) { - if (lookup(ctor.locals, name, meaning & 67216319)) { + if (lookup(ctor.locals, name, meaning & 67216319 /* Value */)) { + // Remember the property node, it will be used later to report appropriate error propertyWithInvalidInitializer = location; } } } break; - case 235: - case 205: - case 236: - if (result = lookup(getMembersOfSymbol(getSymbolOfNode(location)), name, meaning & 67901928)) { + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 236 /* InterfaceDeclaration */: + if (result = lookup(getMembersOfSymbol(getSymbolOfNode(location)), name, meaning & 67901928 /* Type */)) { if (!isTypeParameterSymbolDeclaredInContainer(result, location)) { + // ignore type parameters not declared in this container result = undefined; break; } - if (lastLocation && ts.hasModifier(lastLocation, 32)) { + if (lastLocation && ts.hasModifier(lastLocation, 32 /* Static */)) { + // TypeScript 1.0 spec (April 2014): 3.4.1 + // The scope of a type parameter extends over the entire declaration with which the type + // parameter list is associated, with the exception of static member declarations in classes. error(errorLocation, ts.Diagnostics.Static_members_cannot_reference_class_type_parameters); return undefined; } break loop; } - if (location.kind === 205 && meaning & 32) { + if (location.kind === 205 /* ClassExpression */ && meaning & 32 /* Class */) { var className = location.name; if (className && name === className.escapedText) { result = location.symbol; @@ -26083,10 +30287,11 @@ var ts; } } break; - case 207: - if (lastLocation === location.expression && location.parent.token === 85) { + case 207 /* ExpressionWithTypeArguments */: + // The type parameters of a class are not in scope in the base class expression. + if (lastLocation === location.expression && location.parent.token === 85 /* ExtendsKeyword */) { var container = location.parent.parent; - if (ts.isClassLike(container) && (result = lookup(getSymbolOfNode(container).members, name, meaning & 67901928))) { + if (ts.isClassLike(container) && (result = lookup(getSymbolOfNode(container).members, name, meaning & 67901928 /* Type */))) { if (nameNotFoundMessage) { error(errorLocation, ts.Diagnostics.Base_class_expressions_cannot_reference_class_type_parameters); } @@ -26094,33 +30299,42 @@ var ts; } } break; - case 147: + // It is not legal to reference a class's own type parameters from a computed property name that + // belongs to the class. For example: + // + // function foo() { return '' } + // class C { // <-- Class's own type parameter T + // [foo()]() { } // <-- Reference to T from class's own computed property + // } + // + case 147 /* ComputedPropertyName */: grandparent = location.parent.parent; - if (ts.isClassLike(grandparent) || grandparent.kind === 236) { - if (result = lookup(getSymbolOfNode(grandparent).members, name, meaning & 67901928)) { + if (ts.isClassLike(grandparent) || grandparent.kind === 236 /* InterfaceDeclaration */) { + // A reference to this grandparent's type parameters would be an error + if (result = lookup(getSymbolOfNode(grandparent).members, name, meaning & 67901928 /* Type */)) { error(errorLocation, ts.Diagnostics.A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type); return undefined; } } break; - case 154: - case 153: - case 155: - case 156: - case 157: - case 234: - case 193: - if (meaning & 3 && name === "arguments") { + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 234 /* FunctionDeclaration */: + case 193 /* ArrowFunction */: + if (meaning & 3 /* Variable */ && name === "arguments") { result = argumentsSymbol; break loop; } break; - case 192: - if (meaning & 3 && name === "arguments") { + case 192 /* FunctionExpression */: + if (meaning & 3 /* Variable */ && name === "arguments") { result = argumentsSymbol; break loop; } - if (meaning & 16) { + if (meaning & 16 /* Function */) { var functionName = location.name; if (functionName && name === functionName.escapedText) { result = location.symbol; @@ -26128,16 +30342,31 @@ var ts; } } break; - case 150: - if (location.parent && location.parent.kind === 149) { + case 150 /* Decorator */: + // Decorators are resolved at the class declaration. Resolving at the parameter + // or member would result in looking up locals in the method. + // + // function y() {} + // class C { + // method(@y x, y) {} // <-- decorator y should be resolved at the class declaration, not the parameter. + // } + // + if (location.parent && location.parent.kind === 149 /* Parameter */) { location = location.parent; } + // + // function y() {} + // class C { + // @y method(x, y) {} // <-- decorator y should be resolved at the class declaration, not the method. + // } + // if (location.parent && ts.isClassElement(location.parent)) { location = location.parent; } break; - case 298: - case 292: + case 298 /* JSDocTypedefTag */: + case 292 /* JSDocCallbackTag */: + // js type aliases do not resolve names from their host, so skip past it location = ts.getJSDocHost(location); break; } @@ -26147,12 +30376,15 @@ var ts; lastLocation = location; location = location.parent; } + // We just climbed up parents looking for the name, meaning that we started in a descendant node of `lastLocation`. + // If `result === lastSelfReferenceLocation.symbol`, that means that we are somewhere inside `lastSelfReferenceLocation` looking up a name, and resolving to `lastLocation` itself. + // That means that this is a self-reference of `lastLocation`, and shouldn't count this when considering whether `lastLocation` is used. if (isUse && result && (!lastSelfReferenceLocation || result !== lastSelfReferenceLocation.symbol)) { result.isReferenced |= meaning; } if (!result) { if (lastLocation) { - ts.Debug.assert(lastLocation.kind === 274); + ts.Debug.assert(lastLocation.kind === 274 /* SourceFile */); if (lastLocation.commonJsModuleIndicator && name === "exports") { return lastLocation.symbol; } @@ -26163,7 +30395,7 @@ var ts; } if (!result) { if (originalLocation && ts.isInJavaScriptFile(originalLocation) && originalLocation.parent) { - if (ts.isRequireCall(originalLocation.parent, false)) { + if (ts.isRequireCall(originalLocation.parent, /*checkArgumentIsStringLiteralLike*/ false)) { return requireSymbol; } if (ts.isIdentifier(originalLocation) && ts.isPropertyAccessExpression(originalLocation.parent) && @@ -26175,7 +30407,7 @@ var ts; if (!result) { if (nameNotFoundMessage) { if (!errorLocation || - !checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg) && + !checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg) && // TODO: GH#18217 !checkAndReportErrorForExtendingInterface(errorLocation) && !checkAndReportErrorForUsingTypeAsNamespace(errorLocation, name, meaning) && !checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) && @@ -26195,24 +30427,39 @@ var ts; } return undefined; } + // Perform extra checks only if error reporting was requested if (nameNotFoundMessage) { if (propertyWithInvalidInitializer) { + // We have a match, but the reference occurred within a property initializer and the identifier also binds + // to a local variable in the constructor where the code will be emitted. var propertyName = propertyWithInvalidInitializer.name; error(errorLocation, ts.Diagnostics.Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor, ts.declarationNameToString(propertyName), diagnosticName(nameArg)); return undefined; } + // Only check for block-scoped variable if we have an error location and are looking for the + // name with variable meaning + // For example, + // declare module foo { + // interface bar {} + // } + // const foo/*1*/: foo/*2*/.bar; + // The foo at /*1*/ and /*2*/ will share same symbol with two meanings: + // block-scoped variable and namespace module. However, only when we + // try to resolve name in /*1*/ which is used in variable position, + // we want to check for block-scoped if (errorLocation && - (meaning & 2 || - ((meaning & 32 || meaning & 384) && (meaning & 67216319) === 67216319))) { + (meaning & 2 /* BlockScopedVariable */ || + ((meaning & 32 /* Class */ || meaning & 384 /* Enum */) && (meaning & 67216319 /* Value */) === 67216319 /* Value */))) { var exportOrLocalSymbol = getExportSymbolOfValueSymbolIfExported(result); - if (exportOrLocalSymbol.flags & 2 || exportOrLocalSymbol.flags & 32 || exportOrLocalSymbol.flags & 384) { + if (exportOrLocalSymbol.flags & 2 /* BlockScopedVariable */ || exportOrLocalSymbol.flags & 32 /* Class */ || exportOrLocalSymbol.flags & 384 /* Enum */) { checkResolvedBlockScopedVariable(exportOrLocalSymbol, errorLocation); } } - if (result && isInExternalModule && (meaning & 67216319) === 67216319 && !(originalLocation.flags & 2097152)) { + // If we're in an external module, we can't reference value symbols created from UMD export declarations + if (result && isInExternalModule && (meaning & 67216319 /* Value */) === 67216319 /* Value */ && !(originalLocation.flags & 2097152 /* JSDoc */)) { var decls = result.declarations; - if (decls && decls.length === 1 && decls[0].kind === 242) { - error(errorLocation, ts.Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead, ts.unescapeLeadingUnderscores(name)); + if (decls && decls.length === 1 && decls[0].kind === 242 /* NamespaceExportDeclaration */) { + error(errorLocation, ts.Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead, ts.unescapeLeadingUnderscores(name)); // TODO: GH#18217 } } } @@ -26220,12 +30467,12 @@ var ts; } function isSelfReferenceLocation(node) { switch (node.kind) { - case 234: - case 235: - case 236: - case 238: - case 237: - case 239: + case 234 /* FunctionDeclaration */: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + case 238 /* EnumDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 239 /* ModuleDeclaration */: // For `namespace N { N; }` return true; default: return false; @@ -26237,10 +30484,10 @@ var ts; function isTypeParameterSymbolDeclaredInContainer(symbol, container) { for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var decl = _a[_i]; - if (decl.kind === 148) { + if (decl.kind === 148 /* TypeParameter */) { var parent = ts.isJSDocTemplateTag(decl.parent) ? ts.getJSDocHost(decl.parent) : decl.parent; if (parent === container) { - return !(ts.isJSDocTemplateTag(decl.parent) && ts.find(decl.parent.parent.tags, ts.isJSDocTypeAlias)); + return !(ts.isJSDocTemplateTag(decl.parent) && ts.find(decl.parent.parent.tags, ts.isJSDocTypeAlias)); // TODO: GH#18217 } } } @@ -26250,7 +30497,7 @@ var ts; if (!ts.isIdentifier(errorLocation) || errorLocation.escapedText !== name || isTypeReferenceIdentifier(errorLocation) || isInTypeQuery(errorLocation)) { return false; } - var container = ts.getThisContainer(errorLocation, false); + var container = ts.getThisContainer(errorLocation, /*includeArrowFunctions*/ false); var location = container; while (location) { if (ts.isClassLike(location.parent)) { @@ -26258,13 +30505,16 @@ var ts; if (!classSymbol) { break; } + // Check to see if a static member exists. var constructorType = getTypeOfSymbol(classSymbol); if (getPropertyOfType(constructorType, name)) { error(errorLocation, ts.Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0, diagnosticName(nameArg), symbolToString(classSymbol)); return true; } - if (location === container && !ts.hasModifier(location, 32)) { - var instanceType = getDeclaredTypeOfSymbol(classSymbol).thisType; + // No static member is present. + // Check if we're in an instance method and look for a relevant instance member. + if (location === container && !ts.hasModifier(location, 32 /* Static */)) { + var instanceType = getDeclaredTypeOfSymbol(classSymbol).thisType; // TODO: GH#18217 if (getPropertyOfType(instanceType, name)) { error(errorLocation, ts.Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, diagnosticName(nameArg)); return true; @@ -26277,29 +30527,34 @@ var ts; } function checkAndReportErrorForExtendingInterface(errorLocation) { var expression = getEntityNameForExtendingInterface(errorLocation); - if (expression && resolveEntityName(expression, 64, true)) { + if (expression && resolveEntityName(expression, 64 /* Interface */, /*ignoreErrors*/ true)) { error(errorLocation, ts.Diagnostics.Cannot_extend_an_interface_0_Did_you_mean_implements, ts.getTextOfNode(expression)); return true; } return false; } + /** + * Climbs up parents to an ExpressionWithTypeArguments, and returns its expression, + * but returns undefined if that expression is not an EntityNameExpression. + */ function getEntityNameForExtendingInterface(node) { switch (node.kind) { - case 71: - case 185: + case 71 /* Identifier */: + case 185 /* PropertyAccessExpression */: return node.parent ? getEntityNameForExtendingInterface(node.parent) : undefined; - case 207: + case 207 /* ExpressionWithTypeArguments */: if (ts.isEntityNameExpression(node.expression)) { return node.expression; } + // falls through default: return undefined; } } function checkAndReportErrorForUsingTypeAsNamespace(errorLocation, name, meaning) { - var namespaceMeaning = 1920 | (ts.isInJavaScriptFile(errorLocation) ? 67216319 : 0); + var namespaceMeaning = 1920 /* Namespace */ | (ts.isInJavaScriptFile(errorLocation) ? 67216319 /* Value */ : 0); if (meaning === namespaceMeaning) { - var symbol = resolveSymbol(resolveName(errorLocation, name, 67901928 & ~namespaceMeaning, undefined, undefined, false)); + var symbol = resolveSymbol(resolveName(errorLocation, name, 67901928 /* Type */ & ~namespaceMeaning, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)); var parent = errorLocation.parent; if (symbol) { if (ts.isQualifiedName(parent)) { @@ -26318,13 +30573,13 @@ var ts; return false; } function checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) { - if (meaning & (67216319 & ~1024)) { + if (meaning & (67216319 /* Value */ & ~1024 /* NamespaceModule */)) { if (name === "any" || name === "string" || name === "number" || name === "boolean" || name === "never") { error(errorLocation, ts.Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, ts.unescapeLeadingUnderscores(name)); return true; } - var symbol = resolveSymbol(resolveName(errorLocation, name, 67901928 & ~67216319, undefined, undefined, false)); - if (symbol && !(symbol.flags & 1024)) { + var symbol = resolveSymbol(resolveName(errorLocation, name, 67901928 /* Type */ & ~67216319 /* Value */, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)); + if (symbol && !(symbol.flags & 1024 /* NamespaceModule */)) { error(errorLocation, ts.Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, ts.unescapeLeadingUnderscores(name)); return true; } @@ -26332,15 +30587,15 @@ var ts; return false; } function checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation, name, meaning) { - if (meaning & (67216319 & ~1024 & ~67901928)) { - var symbol = resolveSymbol(resolveName(errorLocation, name, 1024 & ~67216319, undefined, undefined, false)); + if (meaning & (67216319 /* Value */ & ~1024 /* NamespaceModule */ & ~67901928 /* Type */)) { + var symbol = resolveSymbol(resolveName(errorLocation, name, 1024 /* NamespaceModule */ & ~67216319 /* Value */, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)); if (symbol) { error(errorLocation, ts.Diagnostics.Cannot_use_namespace_0_as_a_value, ts.unescapeLeadingUnderscores(name)); return true; } } - else if (meaning & (67901928 & ~1024 & ~67216319)) { - var symbol = resolveSymbol(resolveName(errorLocation, name, (512 | 1024) & ~67901928, undefined, undefined, false)); + else if (meaning & (67901928 /* Type */ & ~1024 /* NamespaceModule */ & ~67216319 /* Value */)) { + var symbol = resolveSymbol(resolveName(errorLocation, name, (512 /* ValueModule */ | 1024 /* NamespaceModule */) & ~67901928 /* Type */, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)); if (symbol) { error(errorLocation, ts.Diagnostics.Cannot_use_namespace_0_as_a_type, ts.unescapeLeadingUnderscores(name)); return true; @@ -26349,34 +30604,39 @@ var ts; return false; } function checkResolvedBlockScopedVariable(result, errorLocation) { - ts.Debug.assert(!!(result.flags & 2 || result.flags & 32 || result.flags & 384)); - var declaration = ts.forEach(result.declarations, function (d) { return ts.isBlockOrCatchScoped(d) || ts.isClassLike(d) || (d.kind === 238) ? d : undefined; }); + ts.Debug.assert(!!(result.flags & 2 /* BlockScopedVariable */ || result.flags & 32 /* Class */ || result.flags & 384 /* Enum */)); + // Block-scoped variables cannot be used before their definition + var declaration = ts.forEach(result.declarations, function (d) { return ts.isBlockOrCatchScoped(d) || ts.isClassLike(d) || (d.kind === 238 /* EnumDeclaration */) ? d : undefined; }); if (declaration === undefined) return ts.Debug.fail("Declaration to checkResolvedBlockScopedVariable is undefined"); - if (!(declaration.flags & 4194304) && !isBlockScopedNameDeclaredBeforeUse(declaration, errorLocation)) { - if (result.flags & 2) { + if (!(declaration.flags & 4194304 /* Ambient */) && !isBlockScopedNameDeclaredBeforeUse(declaration, errorLocation)) { + if (result.flags & 2 /* BlockScopedVariable */) { error(errorLocation, ts.Diagnostics.Block_scoped_variable_0_used_before_its_declaration, ts.declarationNameToString(ts.getNameOfDeclaration(declaration))); } - else if (result.flags & 32) { + else if (result.flags & 32 /* Class */) { error(errorLocation, ts.Diagnostics.Class_0_used_before_its_declaration, ts.declarationNameToString(ts.getNameOfDeclaration(declaration))); } - else if (result.flags & 256) { + else if (result.flags & 256 /* RegularEnum */) { error(errorLocation, ts.Diagnostics.Enum_0_used_before_its_declaration, ts.declarationNameToString(ts.getNameOfDeclaration(declaration))); } } } + /* Starting from 'initial' node walk up the parent chain until 'stopAt' node is reached. + * If at any point current node is equal to 'parent' node - return true. + * Return false if 'stopAt' node is reached or isFunctionLike(current) === true. + */ function isSameScopeDescendentOf(initial, parent, stopAt) { return !!parent && !!ts.findAncestor(initial, function (n) { return n === stopAt || ts.isFunctionLike(n) ? "quit" : n === parent; }); } function getAnyImportSyntax(node) { switch (node.kind) { - case 243: + case 243 /* ImportEqualsDeclaration */: return node; - case 245: + case 245 /* ImportClause */: return node.parent; - case 246: + case 246 /* NamespaceImport */: return node.parent.parent; - case 248: + case 248 /* ImportSpecifier */: return node.parent.parent.parent; default: return undefined; @@ -26386,37 +30646,48 @@ var ts; return ts.find(symbol.declarations, ts.isAliasSymbolDeclaration); } function getTargetOfImportEqualsDeclaration(node, dontResolveAlias) { - if (node.moduleReference.kind === 254) { + if (node.moduleReference.kind === 254 /* ExternalModuleReference */) { return resolveExternalModuleSymbol(resolveExternalModuleName(node, ts.getExternalModuleImportEqualsDeclarationExpression(node))); } return getSymbolOfPartOfRightHandSideOfImportEquals(node.moduleReference, dontResolveAlias); } function resolveExportByName(moduleSymbol, name, dontResolveAlias) { - var exportValue = moduleSymbol.exports.get("export="); + var exportValue = moduleSymbol.exports.get("export=" /* ExportEquals */); return exportValue ? getPropertyOfType(getTypeOfSymbol(exportValue), name) : resolveSymbol(moduleSymbol.exports.get(name), dontResolveAlias); } function isSyntacticDefault(node) { - return ((ts.isExportAssignment(node) && !node.isExportEquals) || ts.hasModifier(node, 512) || ts.isExportSpecifier(node)); + return ((ts.isExportAssignment(node) && !node.isExportEquals) || ts.hasModifier(node, 512 /* Default */) || ts.isExportSpecifier(node)); } function canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias) { if (!allowSyntheticDefaultImports) { return false; } + // Declaration files (and ambient modules) if (!file || file.isDeclarationFile) { - var defaultExportSymbol = resolveExportByName(moduleSymbol, "default", true); + // Definitely cannot have a synthetic default if they have a syntactic default member specified + var defaultExportSymbol = resolveExportByName(moduleSymbol, "default" /* Default */, /*dontResolveAlias*/ true); // Dont resolve alias because we want the immediately exported symbol's declaration if (defaultExportSymbol && ts.some(defaultExportSymbol.declarations, isSyntacticDefault)) { return false; } + // It _might_ still be incorrect to assume there is no __esModule marker on the import at runtime, even if there is no `default` member + // So we check a bit more, if (resolveExportByName(moduleSymbol, ts.escapeLeadingUnderscores("__esModule"), dontResolveAlias)) { + // If there is an `__esModule` specified in the declaration (meaning someone explicitly added it or wrote it in their code), + // it definitely is a module and does not have a synthetic default return false; } + // There are _many_ declaration files not written with esmodules in mind that still get compiled into a format with __esModule set + // Meaning there may be no default at runtime - however to be on the permissive side, we allow access to a synthetic default member + // as there is no marker to indicate if the accompanying JS has `__esModule` or not, or is even native esm return true; } + // TypeScript files never have a synthetic default (as they are always emitted with an __esModule marker) _unless_ they contain an export= statement if (!ts.isSourceFileJavaScript(file)) { return hasExportAssignmentSymbol(moduleSymbol); } + // JS files have a synthetic default if they do not contain ES2015+ module syntax (export = is not valid in js) _and_ do not have an __esModule marker return !file.externalModuleIndicator && !resolveExportByName(moduleSymbol, ts.escapeLeadingUnderscores("__esModule"), dontResolveAlias); } function getTargetOfImportClause(node, dontResolveAlias) { @@ -26427,7 +30698,7 @@ var ts; exportDefaultSymbol = moduleSymbol; } else { - exportDefaultSymbol = resolveExportByName(moduleSymbol, "default", dontResolveAlias); + exportDefaultSymbol = resolveExportByName(moduleSymbol, "default" /* Default */, dontResolveAlias); } var file = ts.find(moduleSymbol.declarations, ts.isSourceFile); var hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias); @@ -26435,6 +30706,7 @@ var ts; error(node.name, ts.Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol)); } else if (hasSyntheticDefault) { + // per emit behavior, a synthetic default overrides a "real" .default member if `__esModule` is not present return resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias); } return exportDefaultSymbol; @@ -26444,11 +30716,29 @@ var ts; var moduleSpecifier = node.parent.parent.moduleSpecifier; return resolveESModuleSymbol(resolveExternalModuleName(node, moduleSpecifier), moduleSpecifier, dontResolveAlias); } + // This function creates a synthetic symbol that combines the value side of one symbol with the + // type/namespace side of another symbol. Consider this example: + // + // declare module graphics { + // interface Point { + // x: number; + // y: number; + // } + // } + // declare var graphics: { + // Point: new (x: number, y: number) => graphics.Point; + // } + // declare module "graphics" { + // export = graphics; + // } + // + // An 'import { Point } from "graphics"' needs to create a symbol that combines the value side 'Point' + // property with the type/namespace side interface 'Point'. function combineValueAndTypeSymbols(valueSymbol, typeSymbol) { if (valueSymbol === unknownSymbol && typeSymbol === unknownSymbol) { return unknownSymbol; } - if (valueSymbol.flags & (67901928 | 1920)) { + if (valueSymbol.flags & (67901928 /* Type */ | 1920 /* Namespace */)) { return valueSymbol; } var result = createSymbol(valueSymbol.flags | typeSymbol.flags, valueSymbol.escapedName); @@ -26463,21 +30753,21 @@ var ts; return result; } function getExportOfModule(symbol, name, dontResolveAlias) { - if (symbol.flags & 1536) { + if (symbol.flags & 1536 /* Module */) { return resolveSymbol(getExportsOfSymbol(symbol).get(name), dontResolveAlias); } } function getPropertyOfVariable(symbol, name) { - if (symbol.flags & 3) { + if (symbol.flags & 3 /* Variable */) { var typeAnnotation = symbol.valueDeclaration.type; if (typeAnnotation) { - return resolveSymbol(getPropertyOfType(getTypeFromTypeNode(typeAnnotation), name)); + return resolveSymbol(getPropertyOfType(getTypeFromTypeNode(typeAnnotation), name)); // TODO: GH#18217 } } } function getExternalModuleMember(node, specifier, dontResolveAlias) { if (dontResolveAlias === void 0) { dontResolveAlias = false; } - var moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier); + var moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier); // TODO: GH#18217 var targetSymbol = resolveESModuleSymbol(moduleSymbol, node.moduleSpecifier, dontResolveAlias); if (targetSymbol) { var name = specifier.propertyName || specifier.name; @@ -26486,15 +30776,18 @@ var ts; return moduleSymbol; } var symbolFromVariable = void 0; - if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get("export=")) { + // First check if module was specified with "export=". If so, get the member from the resolved type + if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get("export=" /* ExportEquals */)) { symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name.escapedText); } else { symbolFromVariable = getPropertyOfVariable(targetSymbol, name.escapedText); } + // if symbolFromVariable is export - get its final target symbolFromVariable = resolveSymbol(symbolFromVariable, dontResolveAlias); var symbolFromModule = getExportOfModule(targetSymbol, name.escapedText, dontResolveAlias); - if (!symbolFromModule && allowSyntheticDefaultImports && name.escapedText === "default") { + // If the export member we're looking for is default, and there is no real default but allowSyntheticDefaultImports is on, return the entire module as the default + if (!symbolFromModule && allowSyntheticDefaultImports && name.escapedText === "default" /* Default */) { symbolFromModule = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias); } var symbol = symbolFromModule && symbolFromVariable && symbolFromModule !== symbolFromVariable ? @@ -26524,14 +30817,14 @@ var ts; function getTargetOfExportSpecifier(node, meaning, dontResolveAlias) { return node.parent.parent.moduleSpecifier ? getExternalModuleMember(node.parent.parent, node, dontResolveAlias) : - resolveEntityName(node.propertyName || node.name, meaning, false, dontResolveAlias); + resolveEntityName(node.propertyName || node.name, meaning, /*ignoreErrors*/ false, dontResolveAlias); } function getTargetOfExportAssignment(node, dontResolveAlias) { var expression = (ts.isExportAssignment(node) ? node.expression : node.right); if (ts.isClassExpression(expression)) { return checkExpression(expression).symbol; } - var aliasLike = resolveEntityName(expression, 67216319 | 67901928 | 1920, true, dontResolveAlias); + var aliasLike = resolveEntityName(expression, 67216319 /* Value */ | 67901928 /* Type */ | 1920 /* Namespace */, /*ignoreErrors*/ true, dontResolveAlias); if (aliasLike) { return aliasLike; } @@ -26541,36 +30834,40 @@ var ts; function getTargetOfAliasDeclaration(node, dontRecursivelyResolve) { if (dontRecursivelyResolve === void 0) { dontRecursivelyResolve = false; } switch (node.kind) { - case 243: + case 243 /* ImportEqualsDeclaration */: return getTargetOfImportEqualsDeclaration(node, dontRecursivelyResolve); - case 245: + case 245 /* ImportClause */: return getTargetOfImportClause(node, dontRecursivelyResolve); - case 246: + case 246 /* NamespaceImport */: return getTargetOfNamespaceImport(node, dontRecursivelyResolve); - case 248: + case 248 /* ImportSpecifier */: return getTargetOfImportSpecifier(node, dontRecursivelyResolve); - case 252: - return getTargetOfExportSpecifier(node, 67216319 | 67901928 | 1920, dontRecursivelyResolve); - case 249: - case 200: + case 252 /* ExportSpecifier */: + return getTargetOfExportSpecifier(node, 67216319 /* Value */ | 67901928 /* Type */ | 1920 /* Namespace */, dontRecursivelyResolve); + case 249 /* ExportAssignment */: + case 200 /* BinaryExpression */: return getTargetOfExportAssignment(node, dontRecursivelyResolve); - case 242: + case 242 /* NamespaceExportDeclaration */: return getTargetOfNamespaceExportDeclaration(node, dontRecursivelyResolve); default: return ts.Debug.fail(); } } + /** + * Indicates that a symbol is an alias that does not merge with a local declaration. + * OR Is a JSContainer which may merge an alias with a local declaration + */ function isNonLocalAlias(symbol, excludes) { - if (excludes === void 0) { excludes = 67216319 | 67901928 | 1920; } + if (excludes === void 0) { excludes = 67216319 /* Value */ | 67901928 /* Type */ | 1920 /* Namespace */; } if (!symbol) return false; - return (symbol.flags & (2097152 | excludes)) === 2097152 || !!(symbol.flags & 2097152 && symbol.flags & 67108864); + return (symbol.flags & (2097152 /* Alias */ | excludes)) === 2097152 /* Alias */ || !!(symbol.flags & 2097152 /* Alias */ && symbol.flags & 67108864 /* JSContainer */); } function resolveSymbol(symbol, dontResolveAlias) { return !dontResolveAlias && isNonLocalAlias(symbol) ? resolveAlias(symbol) : symbol; } function resolveAlias(symbol) { - ts.Debug.assert((symbol.flags & 2097152) !== 0, "Should only get Alias here."); + ts.Debug.assert((symbol.flags & 2097152 /* Alias */) !== 0, "Should only get Alias here."); var links = getSymbolLinks(symbol); if (!links.target) { links.target = resolvingSymbol; @@ -26595,12 +30892,15 @@ var ts; var target = resolveAlias(symbol); if (target) { var markAlias = target === unknownSymbol || - ((target.flags & 67216319) && !isConstEnumOrConstEnumOnlyModule(target)); + ((target.flags & 67216319 /* Value */) && !isConstEnumOrConstEnumOnlyModule(target)); if (markAlias) { markAliasSymbolAsReferenced(symbol); } } } + // When an alias symbol is referenced, we need to mark the entity it references as referenced and in turn repeat that until + // we reach a non-alias or an exported entity (which is always considered referenced). We do this by checking the target of + // the alias as an expression (which recursively takes us back here if the target references another alias). function markAliasSymbolAsReferenced(symbol) { var links = getSymbolLinks(symbol); if (!links.referenced) { @@ -26608,50 +30908,66 @@ var ts; var node = getDeclarationOfAliasSymbol(symbol); if (!node) return ts.Debug.fail(); - if (node.kind === 249) { + if (node.kind === 249 /* ExportAssignment */) { + // export default checkExpressionCached(node.expression); } - else if (node.kind === 252) { + else if (node.kind === 252 /* ExportSpecifier */) { + // export { } or export { as foo } checkExpressionCached(node.propertyName || node.name); } else if (ts.isInternalModuleImportEqualsDeclaration(node)) { + // import foo = checkExpressionCached(node.moduleReference); } } } + // This function is only for imports with entity names function getSymbolOfPartOfRightHandSideOfImportEquals(entityName, dontResolveAlias) { - if (entityName.kind === 71 && ts.isRightSideOfQualifiedNameOrPropertyAccess(entityName)) { + // There are three things we might try to look for. In the following examples, + // the search term is enclosed in |...|: + // + // import a = |b|; // Namespace + // import a = |b.c|; // Value, type, namespace + // import a = |b.c|.d; // Namespace + if (entityName.kind === 71 /* Identifier */ && ts.isRightSideOfQualifiedNameOrPropertyAccess(entityName)) { entityName = entityName.parent; } - if (entityName.kind === 71 || entityName.parent.kind === 146) { - return resolveEntityName(entityName, 1920, false, dontResolveAlias); + // Check for case 1 and 3 in the above example + if (entityName.kind === 71 /* Identifier */ || entityName.parent.kind === 146 /* QualifiedName */) { + return resolveEntityName(entityName, 1920 /* Namespace */, /*ignoreErrors*/ false, dontResolveAlias); } else { - ts.Debug.assert(entityName.parent.kind === 243); - return resolveEntityName(entityName, 67216319 | 67901928 | 1920, false, dontResolveAlias); + // Case 2 in above example + // entityName.kind could be a QualifiedName or a Missing identifier + ts.Debug.assert(entityName.parent.kind === 243 /* ImportEqualsDeclaration */); + return resolveEntityName(entityName, 67216319 /* Value */ | 67901928 /* Type */ | 1920 /* Namespace */, /*ignoreErrors*/ false, dontResolveAlias); } } function getFullyQualifiedName(symbol) { return symbol.parent ? getFullyQualifiedName(symbol.parent) + "." + symbolToString(symbol) : symbolToString(symbol); } + /** + * Resolves a qualified name and any involved aliases. + */ function resolveEntityName(name, meaning, ignoreErrors, dontResolveAlias, location) { if (ts.nodeIsMissing(name)) { return undefined; } - var namespaceMeaning = 1920 | (ts.isInJavaScriptFile(name) ? meaning & 67216319 : 0); + var namespaceMeaning = 1920 /* Namespace */ | (ts.isInJavaScriptFile(name) ? meaning & 67216319 /* Value */ : 0); var symbol; - if (name.kind === 71) { + if (name.kind === 71 /* Identifier */) { var message = meaning === namespaceMeaning ? ts.Diagnostics.Cannot_find_namespace_0 : ts.Diagnostics.Cannot_find_name_0; var symbolFromJSPrototype = ts.isInJavaScriptFile(name) ? resolveEntityNameFromJSSpecialAssignment(name, meaning) : undefined; - symbol = resolveName(location || name, name.escapedText, meaning, ignoreErrors || symbolFromJSPrototype ? undefined : message, name, true); + symbol = resolveName(location || name, name.escapedText, meaning, ignoreErrors || symbolFromJSPrototype ? undefined : message, name, /*isUse*/ true); if (!symbol) { return symbolFromJSPrototype; } } - else if (name.kind === 146 || name.kind === 185) { - var left = name.kind === 146 ? name.left : name.expression; - var right = name.kind === 146 ? name.right : name.name; - var namespace = resolveEntityName(left, namespaceMeaning, ignoreErrors, false, location); + else if (name.kind === 146 /* QualifiedName */ || name.kind === 185 /* PropertyAccessExpression */) { + var left = name.kind === 146 /* QualifiedName */ ? name.left : name.expression; + var right = name.kind === 146 /* QualifiedName */ ? name.right : name.name; + var namespace = resolveEntityName(left, namespaceMeaning, ignoreErrors, /*dontResolveAlias*/ false, location); if (!namespace || ts.nodeIsMissing(right)) { return undefined; } @@ -26684,26 +31000,32 @@ var ts; else { throw ts.Debug.assertNever(name, "Unknown entity name kind."); } - ts.Debug.assert((ts.getCheckFlags(symbol) & 1) === 0, "Should never get an instantiated symbol here."); + ts.Debug.assert((ts.getCheckFlags(symbol) & 1 /* Instantiated */) === 0, "Should never get an instantiated symbol here."); return (symbol.flags & meaning) || dontResolveAlias ? symbol : resolveAlias(symbol); } + /** + * 1. For prototype-property methods like `A.prototype.m = function () ...`, try to resolve names in the scope of `A` too. + * Note that prototype-property assignment to locations outside the current file (eg globals) doesn't work, so + * name resolution won't work either. + * 2. For property assignments like `{ x: function f () { } }`, try to resolve names in the scope of `f` too. + */ function resolveEntityNameFromJSSpecialAssignment(name, meaning) { if (isJSDocTypeReference(name.parent)) { var secondaryLocation = getJSSpecialAssignmentLocation(name.parent); if (secondaryLocation) { - return resolveName(secondaryLocation, name.escapedText, meaning, undefined, name, true); + return resolveName(secondaryLocation, name.escapedText, meaning, /*nameNotFoundMessage*/ undefined, name, /*isUse*/ true); } } } function getJSSpecialAssignmentLocation(node) { - var typeAlias = ts.findAncestor(node, function (node) { return !(ts.isJSDocNode(node) || node.flags & 2097152) ? "quit" : ts.isJSDocTypeAlias(node); }); + var typeAlias = ts.findAncestor(node, function (node) { return !(ts.isJSDocNode(node) || node.flags & 2097152 /* JSDoc */) ? "quit" : ts.isJSDocTypeAlias(node); }); if (typeAlias) { return; } var host = ts.getJSDocHost(node); if (ts.isExpressionStatement(host) && ts.isBinaryExpression(host.expression) && - ts.getSpecialPropertyAssignmentKind(host.expression) === 3) { + ts.getSpecialPropertyAssignmentKind(host.expression) === 3 /* PrototypeProperty */) { var symbol = getSymbolOfNode(host.expression.left); return symbol && symbol.parent.valueDeclaration; } @@ -26732,22 +31054,24 @@ var ts; var withoutAtTypePrefix = ts.removePrefix(moduleReference, "@types/"); error(errorNode, diag, withoutAtTypePrefix, moduleReference); } - var ambientModule = tryFindAmbientModule(moduleReference, true); + var ambientModule = tryFindAmbientModule(moduleReference, /*withAugmentations*/ true); if (ambientModule) { return ambientModule; } var currentSourceFile = ts.getSourceFileOfNode(location); - var resolvedModule = ts.getResolvedModule(currentSourceFile, moduleReference); + var resolvedModule = ts.getResolvedModule(currentSourceFile, moduleReference); // TODO: GH#18217 var resolutionDiagnostic = resolvedModule && ts.getResolutionDiagnostic(compilerOptions, resolvedModule); var sourceFile = resolvedModule && !resolutionDiagnostic && host.getSourceFile(resolvedModule.resolvedFileName); if (sourceFile) { if (sourceFile.symbol) { if (resolvedModule.isExternalLibraryImport && !ts.extensionIsTypeScript(resolvedModule.extension)) { - errorOnImplicitAnyModule(false, errorNode, resolvedModule, moduleReference); + errorOnImplicitAnyModule(/*isError*/ false, errorNode, resolvedModule, moduleReference); } + // merged symbol is module declaration symbol combined with all augmentations return getMergedSymbol(sourceFile.symbol); } if (moduleNotFoundError) { + // report errors only if it was requested error(errorNode, ts.Diagnostics.File_0_is_not_a_module, sourceFile.fileName); } return undefined; @@ -26758,23 +31082,26 @@ var ts; return getMergedSymbol(pattern.symbol); } } + // May be an untyped module. If so, ignore resolutionDiagnostic. if (resolvedModule && !ts.resolutionExtensionIsTypeScriptOrJson(resolvedModule.extension) && resolutionDiagnostic === undefined || resolutionDiagnostic === ts.Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type) { if (isForAugmentation) { var diag = ts.Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented; error(errorNode, diag, moduleReference, resolvedModule.resolvedFileName); } else { - errorOnImplicitAnyModule(noImplicitAny && !!moduleNotFoundError, errorNode, resolvedModule, moduleReference); + errorOnImplicitAnyModule(/*isError*/ noImplicitAny && !!moduleNotFoundError, errorNode, resolvedModule, moduleReference); } + // Failed imports and untyped modules are both treated in an untyped manner; only difference is whether we give a diagnostic first. return undefined; } if (moduleNotFoundError) { + // For relative paths, see if this was possibly a projectReference redirect if (ts.pathIsRelative(moduleReference)) { var sourceFile_1 = ts.getSourceFileOfNode(location); var redirects = sourceFile_1.redirectedReferences; if (redirects) { var normalizedTargetPath = ts.getNormalizedAbsolutePath(moduleReference, ts.getDirectoryPath(sourceFile_1.fileName)); - for (var _i = 0, _a = [".ts", ".tsx"]; _i < _a.length; _i++) { + for (var _i = 0, _a = [".ts" /* Ts */, ".tsx" /* Tsx */]; _i < _a.length; _i++) { var ext = _a[_i]; var probePath = normalizedTargetPath + ext; if (redirects.indexOf(probePath) >= 0) { @@ -26802,11 +31129,12 @@ var ts; } function errorOnImplicitAnyModule(isError, errorNode, _a, moduleReference) { var packageId = _a.packageId, resolvedFileName = _a.resolvedFileName; - var errorInfo = packageId && ts.chainDiagnosticMessages(undefined, ts.Diagnostics.Try_npm_install_types_Slash_0_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_module_0, ts.getMangledNameForScopedPackage(packageId.name)); + var errorInfo = packageId && ts.chainDiagnosticMessages( + /*details*/ undefined, ts.Diagnostics.Try_npm_install_types_Slash_0_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_module_0, ts.getMangledNameForScopedPackage(packageId.name)); errorOrSuggestion(isError, errorNode, ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type, moduleReference, resolvedFileName)); } function resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) { - return moduleSymbol && getMergedSymbol(getCommonJsExportEquals(resolveSymbol(moduleSymbol.exports.get("export="), dontResolveAlias), moduleSymbol)) || moduleSymbol; + return moduleSymbol && getMergedSymbol(getCommonJsExportEquals(resolveSymbol(moduleSymbol.exports.get("export=" /* ExportEquals */), dontResolveAlias), moduleSymbol)) || moduleSymbol; } function getCommonJsExportEquals(exported, moduleSymbol) { if (!exported || moduleSymbol.exports.size === 1) { @@ -26814,20 +31142,23 @@ var ts; } var merged = cloneSymbol(exported); if (merged.exports === undefined) { - merged.flags = merged.flags | 512; + merged.flags = merged.flags | 512 /* ValueModule */; merged.exports = ts.createSymbolTable(); } moduleSymbol.exports.forEach(function (s, name) { - if (name === "export=") + if (name === "export=" /* ExportEquals */) return; merged.exports.set(name, merged.exports.has(name) ? mergeSymbol(merged.exports.get(name), s) : s); }); return merged; } + // An external module with an 'export =' declaration may be referenced as an ES6 module provided the 'export =' + // references a symbol that is at least declared as a module or a variable. The target of the 'export =' may + // combine other declarations with the module or variable (e.g. a class/module, function/module, interface/variable). function resolveESModuleSymbol(moduleSymbol, referencingLocation, dontResolveAlias) { var symbol = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias); if (!dontResolveAlias && symbol) { - if (!(symbol.flags & (1536 | 3))) { + if (!(symbol.flags & (1536 /* Module */ | 3 /* Variable */))) { error(referencingLocation, ts.Diagnostics.Module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct, symbolToString(moduleSymbol)); return symbol; } @@ -26836,12 +31167,13 @@ var ts; if ((ts.isImportDeclaration(referenceParent) && ts.getNamespaceDeclarationNode(referenceParent)) || ts.isImportCall(referenceParent)) { var type = getTypeOfSymbol(symbol); - var sigs = getSignaturesOfStructuredType(type, 0); + var sigs = getSignaturesOfStructuredType(type, 0 /* Call */); if (!sigs || !sigs.length) { - sigs = getSignaturesOfStructuredType(type, 1); + sigs = getSignaturesOfStructuredType(type, 1 /* Construct */); } if (sigs && sigs.length) { var moduleType = getTypeWithSyntheticDefaultImportType(type, symbol, moduleSymbol); + // Create a new symbol which has the module's type less the call and construct signatures var result = createSymbol(symbol.flags, symbol.escapedName); result.declarations = symbol.declarations ? symbol.declarations.slice() : []; result.parent = symbol.parent; @@ -26855,7 +31187,7 @@ var ts; result.members = ts.cloneMap(symbol.members); if (symbol.exports) result.exports = ts.cloneMap(symbol.exports); - var resolvedModuleType = resolveStructuredTypeMembers(moduleType); + var resolvedModuleType = resolveStructuredTypeMembers(moduleType); // Should already be resolved from the signature checks above result.type = createAnonymousType(result, resolvedModuleType.members, ts.emptyArray, ts.emptyArray, resolvedModuleType.stringIndexInfo, resolvedModuleType.numberIndexInfo); return result; } @@ -26865,7 +31197,7 @@ var ts; return symbol; } function hasExportAssignmentSymbol(moduleSymbol) { - return moduleSymbol.exports.get("export=") !== undefined; + return moduleSymbol.exports.get("export=" /* ExportEquals */) !== undefined; } function getExportsOfModuleAsArray(moduleSymbol) { return symbolsToArray(getExportsOfModule(moduleSymbol)); @@ -26894,22 +31226,26 @@ var ts; return undefined; } var type = getTypeOfSymbol(exportEquals); - return type.flags & 32764 ? undefined : getPropertyOfType(type, memberName); + return type.flags & 32764 /* Primitive */ ? undefined : getPropertyOfType(type, memberName); } function getExportsOfSymbol(symbol) { - return symbol.flags & 32 ? getResolvedMembersOrExportsOfSymbol(symbol, "resolvedExports") : - symbol.flags & 1536 ? getExportsOfModule(symbol) : + return symbol.flags & 32 /* Class */ ? getResolvedMembersOrExportsOfSymbol(symbol, "resolvedExports" /* resolvedExports */) : + symbol.flags & 1536 /* Module */ ? getExportsOfModule(symbol) : symbol.exports || emptySymbols; } function getExportsOfModule(moduleSymbol) { var links = getSymbolLinks(moduleSymbol); return links.resolvedExports || (links.resolvedExports = getExportsOfModuleWorker(moduleSymbol)); } + /** + * Extends one symbol table with another while collecting information on name collisions for error message generation into the `lookupTable` argument + * Not passing `lookupTable` and `exportNode` disables this collection, and just extends the tables + */ function extendExportSymbols(target, source, lookupTable, exportNode) { if (!source) return; source.forEach(function (sourceSymbol, id) { - if (id === "default") + if (id === "default" /* Default */) return; var targetSymbol = target.get(id); if (!targetSymbol) { @@ -26933,14 +31269,18 @@ var ts; } function getExportsOfModuleWorker(moduleSymbol) { var visitedSymbols = []; + // A module defined by an 'export=' consists on one export that needs to be resolved moduleSymbol = resolveExternalModuleSymbol(moduleSymbol); return visit(moduleSymbol) || emptySymbols; + // The ES6 spec permits export * declarations in a module to circularly reference the module itself. For example, + // module 'a' can 'export * from "b"' and 'b' can 'export * from "a"' without error. function visit(symbol) { - if (!(symbol && symbol.flags & 1955 && ts.pushIfUnique(visitedSymbols, symbol))) { + if (!(symbol && symbol.flags & 1955 /* HasExports */ && ts.pushIfUnique(visitedSymbols, symbol))) { return; } var symbols = ts.cloneMap(symbol.exports); - var exportStars = symbol.exports.get("__export"); + // All export * declarations are collected in an __export symbol by the binder + var exportStars = symbol.exports.get("__export" /* ExportStar */); if (exportStars) { var nestedSymbols = ts.createSymbolTable(); var lookupTable_1 = ts.createMap(); @@ -26952,6 +31292,7 @@ var ts; } lookupTable_1.forEach(function (_a, id) { var exportsWithDuplicate = _a.exportsWithDuplicate; + // It's not an error if the file with multiple `export *`s with duplicate names exports a member with that name itself if (id === "export=" || !(exportsWithDuplicate && exportsWithDuplicate.length) || symbols.has(id)) { return; } @@ -26975,6 +31316,10 @@ var ts; function getParentOfSymbol(symbol) { return getMergedSymbol(symbol.parent && getLateBoundSymbol(symbol.parent)); } + /** + * Attempts to find the symbol corresponding to the container a symbol is in - usually this + * is just its' `.parent`, but for locals, this value is `undefined` + */ function getContainerOfSymbol(symbol) { var container = getParentOfSymbol(symbol); if (container) { @@ -26989,6 +31334,7 @@ var ts; } function getAliasForSymbolInContainer(container, symbol) { if (container === getParentOfSymbol(symbol)) { + // fast path, `symbol` is either already the alias or isn't aliased return symbol; } var exports = getExportsOfSymbol(container); @@ -27008,18 +31354,18 @@ var ts; } } function getExportSymbolOfValueSymbolIfExported(symbol) { - return symbol && (symbol.flags & 1048576) !== 0 + return symbol && (symbol.flags & 1048576 /* ExportValue */) !== 0 ? getMergedSymbol(symbol.exportSymbol) : symbol; } function symbolIsValue(symbol) { - return !!(symbol.flags & 67216319 || symbol.flags & 2097152 && resolveAlias(symbol).flags & 67216319); + return !!(symbol.flags & 67216319 /* Value */ || symbol.flags & 2097152 /* Alias */ && resolveAlias(symbol).flags & 67216319 /* Value */); } function findConstructorDeclaration(node) { var members = node.members; for (var _i = 0, members_2 = members; _i < members_2.length; _i++) { var member = members_2[_i]; - if (member.kind === 155 && ts.nodeIsPresent(member.body)) { + if (member.kind === 155 /* Constructor */ && ts.nodeIsPresent(member.body)) { return member; } } @@ -27037,12 +31383,12 @@ var ts; } function createBooleanType(trueFalseTypes) { var type = getUnionType(trueFalseTypes); - type.flags |= 16; + type.flags |= 16 /* Boolean */; type.intrinsicName = "boolean"; return type; } function createObjectType(objectFlags, symbol) { - var type = createType(131072); + var type = createType(131072 /* Object */); type.objectFlags = objectFlags; type.symbol = symbol; return type; @@ -27050,11 +31396,15 @@ var ts; function createTypeofType() { return getUnionType(ts.arrayFrom(typeofEQFacts.keys(), getLiteralType)); } + // A reserved member name starts with two underscores, but the third character cannot be an underscore + // or the @ symbol. A third underscore indicates an escaped form of an identifer that started + // with at least two underscores. The @ character indicates that the name is denoted by a well known ES + // Symbol instance. function isReservedMemberName(name) { - return name.charCodeAt(0) === 95 && - name.charCodeAt(1) === 95 && - name.charCodeAt(2) !== 95 && - name.charCodeAt(2) !== 64; + return name.charCodeAt(0) === 95 /* _ */ && + name.charCodeAt(1) === 95 /* _ */ && + name.charCodeAt(2) !== 95 /* _ */ && + name.charCodeAt(2) !== 64 /* at */; } function getNamedMembers(members) { var result; @@ -27081,22 +31431,24 @@ var ts; return type; } function createAnonymousType(symbol, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo) { - return setStructuredTypeMembers(createObjectType(16, symbol), members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); + return setStructuredTypeMembers(createObjectType(16 /* Anonymous */, symbol), members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); } function forEachSymbolTableInScope(enclosingDeclaration, callback) { var result; for (var location = enclosingDeclaration; location; location = location.parent) { + // Locals of a source file are not in scope (because they get merged into the global symbol table) if (location.locals && !isGlobalSourceFile(location)) { if (result = callback(location.locals)) { return result; } } switch (location.kind) { - case 274: + case 274 /* SourceFile */: if (!ts.isExternalOrCommonJsModule(location)) { break; } - case 239: + // falls through + case 239 /* ModuleDeclaration */: if (result = callback(getSymbolOfNode(location).exports)) { return result; } @@ -27106,7 +31458,8 @@ var ts; return callback(globals); } function getQualifiedLeftMeaning(rightMeaning) { - return rightMeaning === 67216319 ? 67216319 : 1920; + // If we are looking in value space, the parent meaning is value, other wise it is namespace + return rightMeaning === 67216319 /* Value */ ? 67216319 /* Value */ : 1920 /* Namespace */; } function getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, useOnlyExternalAliasing, visitedSymbolTablesMap) { if (visitedSymbolTablesMap === void 0) { visitedSymbolTablesMap = ts.createMap(); } @@ -27119,6 +31472,9 @@ var ts; visitedSymbolTablesMap.set(id, visitedSymbolTables = []); } return forEachSymbolTableInScope(enclosingDeclaration, getAccessibleSymbolChainFromSymbolTable); + /** + * @param {ignoreQualification} boolean Set when a symbol is being looked for through the exports of another symbol (meaning we have a route to qualify it already) + */ function getAccessibleSymbolChainFromSymbolTable(symbols, ignoreQualification) { if (!ts.pushIfUnique(visitedSymbolTables, symbols)) { return undefined; @@ -27128,36 +31484,46 @@ var ts; return result; } function canQualifySymbol(symbolFromSymbolTable, meaning) { + // If the symbol is equivalent and doesn't need further qualification, this symbol is accessible return !needsQualification(symbolFromSymbolTable, enclosingDeclaration, meaning) || + // If symbol needs qualification, make sure that parent is accessible, if it is then this symbol is accessible too !!getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing, visitedSymbolTablesMap); } function isAccessible(symbolFromSymbolTable, resolvedAliasSymbol, ignoreQualification) { return symbol === (resolvedAliasSymbol || symbolFromSymbolTable) && + // if the symbolFromSymbolTable is not external module (it could be if it was determined as ambient external module and would be in globals table) + // and if symbolFromSymbolTable or alias resolution matches the symbol, + // check the symbol can be qualified, it is only then this symbol is accessible !ts.some(symbolFromSymbolTable.declarations, hasNonGlobalAugmentationExternalModuleSymbol) && (ignoreQualification || canQualifySymbol(symbolFromSymbolTable, meaning)); } function trySymbolTable(symbols, ignoreQualification) { - if (isAccessible(symbols.get(symbol.escapedName), undefined, ignoreQualification)) { + // If symbol is directly available by its name in the symbol table + if (isAccessible(symbols.get(symbol.escapedName), /*resolvedAliasSymbol*/ undefined, ignoreQualification)) { return [symbol]; } + // Check if symbol is any of the alias return ts.forEachEntry(symbols, function (symbolFromSymbolTable) { - if (symbolFromSymbolTable.flags & 2097152 - && symbolFromSymbolTable.escapedName !== "export=" - && symbolFromSymbolTable.escapedName !== "default" + if (symbolFromSymbolTable.flags & 2097152 /* Alias */ + && symbolFromSymbolTable.escapedName !== "export=" /* ExportEquals */ + && symbolFromSymbolTable.escapedName !== "default" /* Default */ && !(ts.isUMDExportSymbol(symbolFromSymbolTable) && enclosingDeclaration && ts.isExternalModule(ts.getSourceFileOfNode(enclosingDeclaration))) + // If `!useOnlyExternalAliasing`, we can use any type of alias to get the name && (!useOnlyExternalAliasing || ts.some(symbolFromSymbolTable.declarations, ts.isExternalModuleImportEqualsDeclaration))) { var resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable); if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol, ignoreQualification)) { return [symbolFromSymbolTable]; } + // Look in the exported members, if we can find accessibleSymbolChain, symbol is accessible using this chain + // but only if the symbolFromSymbolTable can be qualified var candidateTable = getExportsOfSymbol(resolvedImportedSymbol); - var accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable, true); + var accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable, /*ignoreQualification*/ true); if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) { return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports); } } if (symbolFromSymbolTable.escapedName === symbol.escapedName && symbolFromSymbolTable.exportSymbol) { - if (isAccessible(getMergedSymbol(symbolFromSymbolTable.exportSymbol), undefined, ignoreQualification)) { + if (isAccessible(getMergedSymbol(symbolFromSymbolTable.exportSymbol), /*aliasSymbol*/ undefined, ignoreQualification)) { return [symbol]; } } @@ -27167,18 +31533,24 @@ var ts; function needsQualification(symbol, enclosingDeclaration, meaning) { var qualify = false; forEachSymbolTableInScope(enclosingDeclaration, function (symbolTable) { + // If symbol of this name is not available in the symbol table we are ok var symbolFromSymbolTable = getMergedSymbol(symbolTable.get(symbol.escapedName)); if (!symbolFromSymbolTable) { + // Continue to the next symbol table return false; } + // If the symbol with this name is present it should refer to the symbol if (symbolFromSymbolTable === symbol) { + // No need to qualify return true; } - symbolFromSymbolTable = (symbolFromSymbolTable.flags & 2097152 && !ts.getDeclarationOfKind(symbolFromSymbolTable, 252)) ? resolveAlias(symbolFromSymbolTable) : symbolFromSymbolTable; + // Qualify if the symbol from symbol table has same meaning as expected + symbolFromSymbolTable = (symbolFromSymbolTable.flags & 2097152 /* Alias */ && !ts.getDeclarationOfKind(symbolFromSymbolTable, 252 /* ExportSpecifier */)) ? resolveAlias(symbolFromSymbolTable) : symbolFromSymbolTable; if (symbolFromSymbolTable.flags & meaning) { qualify = true; return true; } + // Continue to the next symbol table return false; }); return qualify; @@ -27188,10 +31560,10 @@ var ts; for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var declaration = _a[_i]; switch (declaration.kind) { - case 152: - case 154: - case 156: - case 157: + case 152 /* PropertyDeclaration */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: continue; default: return false; @@ -27202,97 +31574,129 @@ var ts; return false; } function isTypeSymbolAccessible(typeSymbol, enclosingDeclaration) { - var access = isSymbolAccessible(typeSymbol, enclosingDeclaration, 67901928, false); - return access.accessibility === 0; + var access = isSymbolAccessible(typeSymbol, enclosingDeclaration, 67901928 /* Type */, /*shouldComputeAliasesToMakeVisible*/ false); + return access.accessibility === 0 /* Accessible */; } function isValueSymbolAccessible(typeSymbol, enclosingDeclaration) { - var access = isSymbolAccessible(typeSymbol, enclosingDeclaration, 67216319, false); - return access.accessibility === 0; + var access = isSymbolAccessible(typeSymbol, enclosingDeclaration, 67216319 /* Value */, /*shouldComputeAliasesToMakeVisible*/ false); + return access.accessibility === 0 /* Accessible */; } + /** + * Check if the given symbol in given enclosing declaration is accessible and mark all associated alias to be visible if requested + * + * @param symbol a Symbol to check if accessible + * @param enclosingDeclaration a Node containing reference to the symbol + * @param meaning a SymbolFlags to check if such meaning of the symbol is accessible + * @param shouldComputeAliasToMakeVisible a boolean value to indicate whether to return aliases to be mark visible in case the symbol is accessible + */ function isSymbolAccessible(symbol, enclosingDeclaration, meaning, shouldComputeAliasesToMakeVisible) { if (symbol && enclosingDeclaration) { var initialSymbol = symbol; var meaningToLook = meaning; while (symbol) { - var accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaningToLook, false); + // Symbol is accessible if it by itself is accessible + var accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaningToLook, /*useOnlyExternalAliasing*/ false); if (accessibleSymbolChain) { var hasAccessibleDeclarations = hasVisibleDeclarations(accessibleSymbolChain[0], shouldComputeAliasesToMakeVisible); if (!hasAccessibleDeclarations) { return { - accessibility: 1, + accessibility: 1 /* NotAccessible */, errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning), - errorModuleName: symbol !== initialSymbol ? symbolToString(symbol, enclosingDeclaration, 1920) : undefined, + errorModuleName: symbol !== initialSymbol ? symbolToString(symbol, enclosingDeclaration, 1920 /* Namespace */) : undefined, }; } return hasAccessibleDeclarations; } else { if (ts.some(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol)) { + // Any meaning of a module symbol is always accessible via an `import` type return { - accessibility: 0 + accessibility: 0 /* Accessible */ }; } } + // If we haven't got the accessible symbol, it doesn't mean the symbol is actually inaccessible. + // It could be a qualified symbol and hence verify the path + // e.g.: + // module m { + // export class c { + // } + // } + // const x: typeof m.c + // In the above example when we start with checking if typeof m.c symbol is accessible, + // we are going to see if c can be accessed in scope directly. + // But it can't, hence the accessible is going to be undefined, but that doesn't mean m.c is inaccessible + // It is accessible if the parent m is accessible because then m.c can be accessed through qualification meaningToLook = getQualifiedLeftMeaning(meaning); symbol = getContainerOfSymbol(symbol); } + // This could be a symbol that is not exported in the external module + // or it could be a symbol from different external module that is not aliased and hence cannot be named var symbolExternalModule = ts.forEach(initialSymbol.declarations, getExternalModuleContainer); if (symbolExternalModule) { var enclosingExternalModule = getExternalModuleContainer(enclosingDeclaration); if (symbolExternalModule !== enclosingExternalModule) { + // name from different external module that is not visible return { - accessibility: 2, + accessibility: 2 /* CannotBeNamed */, errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning), errorModuleName: symbolToString(symbolExternalModule) }; } } + // Just a local name that is not accessible return { - accessibility: 1, + accessibility: 1 /* NotAccessible */, errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning), }; } - return { accessibility: 0 }; + return { accessibility: 0 /* Accessible */ }; function getExternalModuleContainer(declaration) { var node = ts.findAncestor(declaration, hasExternalModuleSymbol); return node && getSymbolOfNode(node); } } function hasExternalModuleSymbol(declaration) { - return ts.isAmbientModule(declaration) || (declaration.kind === 274 && ts.isExternalOrCommonJsModule(declaration)); + return ts.isAmbientModule(declaration) || (declaration.kind === 274 /* SourceFile */ && ts.isExternalOrCommonJsModule(declaration)); } function hasNonGlobalAugmentationExternalModuleSymbol(declaration) { - return ts.isModuleWithStringLiteralName(declaration) || (declaration.kind === 274 && ts.isExternalOrCommonJsModule(declaration)); + return ts.isModuleWithStringLiteralName(declaration) || (declaration.kind === 274 /* SourceFile */ && ts.isExternalOrCommonJsModule(declaration)); } function hasVisibleDeclarations(symbol, shouldComputeAliasToMakeVisible) { var aliasesToMakeVisible; if (!ts.every(symbol.declarations, getIsDeclarationVisible)) { return undefined; } - return { accessibility: 0, aliasesToMakeVisible: aliasesToMakeVisible }; + return { accessibility: 0 /* Accessible */, aliasesToMakeVisible: aliasesToMakeVisible }; function getIsDeclarationVisible(declaration) { if (!isDeclarationVisible(declaration)) { + // Mark the unexported alias as visible if its parent is visible + // because these kind of aliases can be used to name types in declaration file var anyImportSyntax = getAnyImportSyntax(declaration); if (anyImportSyntax && - !ts.hasModifier(anyImportSyntax, 1) && + !ts.hasModifier(anyImportSyntax, 1 /* Export */) && // import clause without export isDeclarationVisible(anyImportSyntax.parent)) { return addVisibleAlias(declaration, anyImportSyntax); } else if (ts.isVariableDeclaration(declaration) && ts.isVariableStatement(declaration.parent.parent) && - !ts.hasModifier(declaration.parent.parent, 1) && + !ts.hasModifier(declaration.parent.parent, 1 /* Export */) && // unexported variable statement isDeclarationVisible(declaration.parent.parent.parent)) { return addVisibleAlias(declaration, declaration.parent.parent); } - else if (ts.isLateVisibilityPaintedStatement(declaration) - && !ts.hasModifier(declaration, 1) + else if (ts.isLateVisibilityPaintedStatement(declaration) // unexported top-level statement + && !ts.hasModifier(declaration, 1 /* Export */) && isDeclarationVisible(declaration.parent)) { return addVisibleAlias(declaration, declaration); } + // Declaration is not visible return false; } return true; } function addVisibleAlias(declaration, aliasingStatement) { + // In function "buildTypeDisplay" where we decide whether to write type-alias or serialize types, + // we want to just check if type- alias is accessible or not but we don't care about emitting those alias at that time + // since we will do the emitting later in trackSymbol. if (shouldComputeAliasToMakeVisible) { getNodeLinks(declaration).isVisible = true; aliasesToMakeVisible = ts.appendIfUnique(aliasesToMakeVisible, aliasingStatement); @@ -27301,141 +31705,147 @@ var ts; } } function isEntityNameVisible(entityName, enclosingDeclaration) { + // get symbol of the first identifier of the entityName var meaning; - if (entityName.parent.kind === 165 || + if (entityName.parent.kind === 165 /* TypeQuery */ || ts.isExpressionWithTypeArgumentsInClassExtendsClause(entityName.parent) || - entityName.parent.kind === 147) { - meaning = 67216319 | 1048576; + entityName.parent.kind === 147 /* ComputedPropertyName */) { + // Typeof value + meaning = 67216319 /* Value */ | 1048576 /* ExportValue */; } - else if (entityName.kind === 146 || entityName.kind === 185 || - entityName.parent.kind === 243) { - meaning = 1920; + else if (entityName.kind === 146 /* QualifiedName */ || entityName.kind === 185 /* PropertyAccessExpression */ || + entityName.parent.kind === 243 /* ImportEqualsDeclaration */) { + // Left identifier from type reference or TypeAlias + // Entity name of the import declaration + meaning = 1920 /* Namespace */; } else { - meaning = 67901928; + // Type Reference or TypeAlias entity = Identifier + meaning = 67901928 /* Type */; } var firstIdentifier = getFirstIdentifier(entityName); - var symbol = resolveName(enclosingDeclaration, firstIdentifier.escapedText, meaning, undefined, undefined, false); - return (symbol && hasVisibleDeclarations(symbol, true)) || { - accessibility: 1, + var symbol = resolveName(enclosingDeclaration, firstIdentifier.escapedText, meaning, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); + // Verify if the symbol is accessible + return (symbol && hasVisibleDeclarations(symbol, /*shouldComputeAliasToMakeVisible*/ true)) || { + accessibility: 1 /* NotAccessible */, errorSymbolName: ts.getTextOfNode(firstIdentifier), errorNode: firstIdentifier }; } function symbolToString(symbol, enclosingDeclaration, meaning, flags, writer) { - if (flags === void 0) { flags = 4; } - var nodeFlags = 3112960; - if (flags & 2) { - nodeFlags |= 128; + if (flags === void 0) { flags = 4 /* AllowAnyNodeKind */; } + var nodeFlags = 3112960 /* IgnoreErrors */; + if (flags & 2 /* UseOnlyExternalAliasing */) { + nodeFlags |= 128 /* UseOnlyExternalAliasing */; } - if (flags & 1) { - nodeFlags |= 512; + if (flags & 1 /* WriteTypeParametersOrArguments */) { + nodeFlags |= 512 /* WriteTypeParametersInQualifiedName */; } - if (flags & 8) { - nodeFlags |= 16384; + if (flags & 8 /* UseAliasDefinedOutsideCurrentScope */) { + nodeFlags |= 16384 /* UseAliasDefinedOutsideCurrentScope */; } - var builder = flags & 4 ? nodeBuilder.symbolToExpression : nodeBuilder.symbolToEntityName; + var builder = flags & 4 /* AllowAnyNodeKind */ ? nodeBuilder.symbolToExpression : nodeBuilder.symbolToEntityName; return writer ? symbolToStringWorker(writer).getText() : ts.usingSingleLineStringWriter(symbolToStringWorker); function symbolToStringWorker(writer) { - var entity = builder(symbol, meaning, enclosingDeclaration, nodeFlags); + var entity = builder(symbol, meaning, enclosingDeclaration, nodeFlags); // TODO: GH#18217 var printer = ts.createPrinter({ removeComments: true }); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); - printer.writeNode(4, entity, sourceFile, writer); + printer.writeNode(4 /* Unspecified */, entity, /*sourceFile*/ sourceFile, writer); return writer; } } function signatureToString(signature, enclosingDeclaration, flags, kind, writer) { - if (flags === void 0) { flags = 0; } + if (flags === void 0) { flags = 0 /* None */; } return writer ? signatureToStringWorker(writer).getText() : ts.usingSingleLineStringWriter(signatureToStringWorker); function signatureToStringWorker(writer) { var sigOutput; - if (flags & 262144) { - sigOutput = kind === 1 ? 164 : 163; + if (flags & 262144 /* WriteArrowStyleSignature */) { + sigOutput = kind === 1 /* Construct */ ? 164 /* ConstructorType */ : 163 /* FunctionType */; } else { - sigOutput = kind === 1 ? 159 : 158; + sigOutput = kind === 1 /* Construct */ ? 159 /* ConstructSignature */ : 158 /* CallSignature */; } - var sig = nodeBuilder.signatureToSignatureDeclaration(signature, sigOutput, enclosingDeclaration, toNodeBuilderFlags(flags) | 3112960 | 512); + var sig = nodeBuilder.signatureToSignatureDeclaration(signature, sigOutput, enclosingDeclaration, toNodeBuilderFlags(flags) | 3112960 /* IgnoreErrors */ | 512 /* WriteTypeParametersInQualifiedName */); var printer = ts.createPrinter({ removeComments: true, omitTrailingSemicolon: true }); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); - printer.writeNode(4, sig, sourceFile, writer); + printer.writeNode(4 /* Unspecified */, sig, /*sourceFile*/ sourceFile, writer); // TODO: GH#18217 return writer; } } function typeToString(type, enclosingDeclaration, flags, writer) { - if (flags === void 0) { flags = 1048576 | 16384; } + if (flags === void 0) { flags = 1048576 /* AllowUniqueESSymbolType */ | 16384 /* UseAliasDefinedOutsideCurrentScope */; } if (writer === void 0) { writer = ts.createTextWriter(""); } - var typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | 3112960, writer); + var typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | 3112960 /* IgnoreErrors */, writer); if (typeNode === undefined) return ts.Debug.fail("should always get typenode"); var options = { removeComments: true }; var printer = ts.createPrinter(options); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); - printer.writeNode(4, typeNode, sourceFile, writer); + printer.writeNode(4 /* Unspecified */, typeNode, /*sourceFile*/ sourceFile, writer); var result = writer.getText(); - var maxLength = compilerOptions.noErrorTruncation || flags & 1 ? undefined : 100; + var maxLength = compilerOptions.noErrorTruncation || flags & 1 /* NoTruncation */ ? undefined : 100; if (maxLength && result && result.length >= maxLength) { return result.substr(0, maxLength - "...".length) + "..."; } return result; } function toNodeBuilderFlags(flags) { - if (flags === void 0) { flags = 0; } - return flags & 9469291; + if (flags === void 0) { flags = 0 /* None */; } + return flags & 9469291 /* NodeBuilderFlagsMask */; } function createNodeBuilder() { return { typeToTypeNode: function (type, enclosingDeclaration, flags, tracker) { - ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8) === 0); + ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8 /* Synthesized */) === 0); var context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); var resultingNode = typeToTypeNodeHelper(type, context); var result = context.encounteredError ? undefined : resultingNode; return result; }, indexInfoToIndexSignatureDeclaration: function (indexInfo, kind, enclosingDeclaration, flags, tracker) { - ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8) === 0); + ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8 /* Synthesized */) === 0); var context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); var resultingNode = indexInfoToIndexSignatureDeclarationHelper(indexInfo, kind, context); var result = context.encounteredError ? undefined : resultingNode; - return result; + return result; // TODO: GH#18217 }, signatureToSignatureDeclaration: function (signature, kind, enclosingDeclaration, flags, tracker) { - ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8) === 0); + ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8 /* Synthesized */) === 0); var context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); var resultingNode = signatureToSignatureDeclarationHelper(signature, kind, context); var result = context.encounteredError ? undefined : resultingNode; return result; }, symbolToEntityName: function (symbol, meaning, enclosingDeclaration, flags, tracker) { - ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8) === 0); + ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8 /* Synthesized */) === 0); var context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); - var resultingNode = symbolToName(symbol, context, meaning, false); + var resultingNode = symbolToName(symbol, context, meaning, /*expectsIdentifier*/ false); var result = context.encounteredError ? undefined : resultingNode; return result; }, symbolToExpression: function (symbol, meaning, enclosingDeclaration, flags, tracker) { - ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8) === 0); + ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8 /* Synthesized */) === 0); var context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); var resultingNode = symbolToExpression(symbol, context, meaning); var result = context.encounteredError ? undefined : resultingNode; return result; }, symbolToTypeParameterDeclarations: function (symbol, enclosingDeclaration, flags, tracker) { - ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8) === 0); + ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8 /* Synthesized */) === 0); var context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); var resultingNode = typeParametersToTypeParameterDeclarations(symbol, context); var result = context.encounteredError ? undefined : resultingNode; return result; }, symbolToParameterDeclaration: function (symbol, enclosingDeclaration, flags, tracker) { - ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8) === 0); + ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8 /* Synthesized */) === 0); var context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); var resultingNode = symbolToParameterDeclaration(symbol, context); var result = context.encounteredError ? undefined : resultingNode; return result; }, typeParameterToDeclaration: function (parameter, enclosingDeclaration, flags, tracker) { - ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8) === 0); + ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8 /* Synthesized */) === 0); var context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); var resultingNode = typeParameterToDeclaration(parameter, context); var result = context.encounteredError ? undefined : resultingNode; @@ -27445,7 +31855,7 @@ var ts; function createNodeBuilderContext(enclosingDeclaration, flags, tracker) { return { enclosingDeclaration: enclosingDeclaration, - flags: flags || 0, + flags: flags || 0 /* None */, tracker: tracker && tracker.trackSymbol ? tracker : { trackSymbol: ts.noop }, encounteredError: false, visitedSymbols: undefined, @@ -27456,78 +31866,78 @@ var ts; if (cancellationToken && cancellationToken.throwIfCancellationRequested) { cancellationToken.throwIfCancellationRequested(); } - var inTypeAlias = context.flags & 8388608; - context.flags &= ~8388608; + var inTypeAlias = context.flags & 8388608 /* InTypeAlias */; + context.flags &= ~8388608 /* InTypeAlias */; if (!type) { context.encounteredError = true; - return undefined; + return undefined; // TODO: GH#18217 } - if (type.flags & 1) { - return ts.createKeywordTypeNode(119); + if (type.flags & 1 /* Any */) { + return ts.createKeywordTypeNode(119 /* AnyKeyword */); } - if (type.flags & 2) { - return ts.createKeywordTypeNode(142); + if (type.flags & 2 /* Unknown */) { + return ts.createKeywordTypeNode(142 /* UnknownKeyword */); } - if (type.flags & 4) { - return ts.createKeywordTypeNode(137); + if (type.flags & 4 /* String */) { + return ts.createKeywordTypeNode(137 /* StringKeyword */); } - if (type.flags & 8) { - return ts.createKeywordTypeNode(134); + if (type.flags & 8 /* Number */) { + return ts.createKeywordTypeNode(134 /* NumberKeyword */); } - if (type.flags & 16) { - return ts.createKeywordTypeNode(122); + if (type.flags & 16 /* Boolean */) { + return ts.createKeywordTypeNode(122 /* BooleanKeyword */); } - if (type.flags & 512 && !(type.flags & 262144)) { + if (type.flags & 512 /* EnumLiteral */ && !(type.flags & 262144 /* Union */)) { var parentSymbol = getParentOfSymbol(type.symbol); - var parentName = symbolToName(parentSymbol, context, 67901928, false); + var parentName = symbolToName(parentSymbol, context, 67901928 /* Type */, /*expectsIdentifier*/ false); var enumLiteralName = getDeclaredTypeOfSymbol(parentSymbol) === type ? parentName : ts.createQualifiedName(parentName, ts.symbolName(type.symbol)); - return ts.createTypeReferenceNode(enumLiteralName, undefined); + return ts.createTypeReferenceNode(enumLiteralName, /*typeArguments*/ undefined); } - if (type.flags & 544) { - var name = symbolToName(type.symbol, context, 67901928, false); - return ts.createTypeReferenceNode(name, undefined); + if (type.flags & 544 /* EnumLike */) { + var name = symbolToName(type.symbol, context, 67901928 /* Type */, /*expectsIdentifier*/ false); + return ts.createTypeReferenceNode(name, /*typeArguments*/ undefined); } - if (type.flags & (64)) { - return ts.createLiteralTypeNode(ts.setEmitFlags(ts.createLiteral(type.value), 16777216)); + if (type.flags & (64 /* StringLiteral */)) { + return ts.createLiteralTypeNode(ts.setEmitFlags(ts.createLiteral(type.value), 16777216 /* NoAsciiEscaping */)); } - if (type.flags & (128)) { + if (type.flags & (128 /* NumberLiteral */)) { return ts.createLiteralTypeNode((ts.createLiteral(type.value))); } - if (type.flags & 256) { + if (type.flags & 256 /* BooleanLiteral */) { return type.intrinsicName === "true" ? ts.createTrue() : ts.createFalse(); } - if (type.flags & 2048) { - if (!(context.flags & 1048576)) { + if (type.flags & 2048 /* UniqueESSymbol */) { + if (!(context.flags & 1048576 /* AllowUniqueESSymbolType */)) { if (isValueSymbolAccessible(type.symbol, context.enclosingDeclaration)) { - return symbolToTypeNode(type.symbol, context, 67216319); + return symbolToTypeNode(type.symbol, context, 67216319 /* Value */); } if (context.tracker.reportInaccessibleUniqueSymbolError) { context.tracker.reportInaccessibleUniqueSymbolError(); } } - return ts.createTypeOperatorNode(141, ts.createKeywordTypeNode(138)); + return ts.createTypeOperatorNode(141 /* UniqueKeyword */, ts.createKeywordTypeNode(138 /* SymbolKeyword */)); } - if (type.flags & 4096) { - return ts.createKeywordTypeNode(105); + if (type.flags & 4096 /* Void */) { + return ts.createKeywordTypeNode(105 /* VoidKeyword */); } - if (type.flags & 8192) { - return ts.createKeywordTypeNode(140); + if (type.flags & 8192 /* Undefined */) { + return ts.createKeywordTypeNode(140 /* UndefinedKeyword */); } - if (type.flags & 16384) { - return ts.createKeywordTypeNode(95); + if (type.flags & 16384 /* Null */) { + return ts.createKeywordTypeNode(95 /* NullKeyword */); } - if (type.flags & 32768) { - return ts.createKeywordTypeNode(131); + if (type.flags & 32768 /* Never */) { + return ts.createKeywordTypeNode(131 /* NeverKeyword */); } - if (type.flags & 1024) { - return ts.createKeywordTypeNode(138); + if (type.flags & 1024 /* ESSymbol */) { + return ts.createKeywordTypeNode(138 /* SymbolKeyword */); } - if (type.flags & 16777216) { - return ts.createKeywordTypeNode(135); + if (type.flags & 16777216 /* NonPrimitive */) { + return ts.createKeywordTypeNode(135 /* ObjectKeyword */); } - if (type.flags & 65536 && type.isThisType) { - if (context.flags & 4194304) { - if (!context.encounteredError && !(context.flags & 32768)) { + if (type.flags & 65536 /* TypeParameter */ && type.isThisType) { + if (context.flags & 4194304 /* InObjectTypeLiteral */) { + if (!context.encounteredError && !(context.flags & 32768 /* AllowThisInObjectLiteral */)) { context.encounteredError = true; } if (context.tracker.reportInaccessibleThisError) { @@ -27537,61 +31947,63 @@ var ts; return ts.createThis(); } var objectFlags = ts.getObjectFlags(type); - if (objectFlags & 4) { - ts.Debug.assert(!!(type.flags & 131072)); + if (objectFlags & 4 /* Reference */) { + ts.Debug.assert(!!(type.flags & 131072 /* Object */)); return typeReferenceToTypeNode(type); } - if (type.flags & 65536 || objectFlags & 3) { - if (type.flags & 65536 && ts.contains(context.inferTypeParameters, type)) { - return ts.createInferTypeNode(typeParameterToDeclarationWithConstraint(type, context, undefined)); + if (type.flags & 65536 /* TypeParameter */ || objectFlags & 3 /* ClassOrInterface */) { + if (type.flags & 65536 /* TypeParameter */ && ts.contains(context.inferTypeParameters, type)) { + return ts.createInferTypeNode(typeParameterToDeclarationWithConstraint(type, context, /*constraintNode*/ undefined)); } - if (context.flags & 4 && - type.flags & 65536 && + if (context.flags & 4 /* GenerateNamesForShadowedTypeParams */ && + type.flags & 65536 /* TypeParameter */ && ts.length(type.symbol.declarations) && ts.isTypeParameterDeclaration(type.symbol.declarations[0]) && typeParameterShadowsNameInScope(type, context) && !isTypeSymbolAccessible(type.symbol, context.enclosingDeclaration)) { - return ts.createTypeReferenceNode(ts.getGeneratedNameForNode(type.symbol.declarations[0].name, 16 | 8), undefined); + return ts.createTypeReferenceNode(ts.getGeneratedNameForNode(type.symbol.declarations[0].name, 16 /* Optimistic */ | 8 /* ReservedInNestedScopes */), /*typeArguments*/ undefined); } + // Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter. return type.symbol - ? symbolToTypeNode(type.symbol, context, 67901928) - : ts.createTypeReferenceNode(ts.createIdentifier("?"), undefined); + ? symbolToTypeNode(type.symbol, context, 67901928 /* Type */) + : ts.createTypeReferenceNode(ts.createIdentifier("?"), /*typeArguments*/ undefined); } - if (!inTypeAlias && type.aliasSymbol && (context.flags & 16384 || isTypeSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration))) { + if (!inTypeAlias && type.aliasSymbol && (context.flags & 16384 /* UseAliasDefinedOutsideCurrentScope */ || isTypeSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration))) { var typeArgumentNodes = mapToTypeNodes(type.aliasTypeArguments, context); - if (isReservedMemberName(type.aliasSymbol.escapedName) && !(type.aliasSymbol.flags & 32)) + if (isReservedMemberName(type.aliasSymbol.escapedName) && !(type.aliasSymbol.flags & 32 /* Class */)) return ts.createTypeReferenceNode(ts.createIdentifier(""), typeArgumentNodes); - return symbolToTypeNode(type.aliasSymbol, context, 67901928, typeArgumentNodes); + return symbolToTypeNode(type.aliasSymbol, context, 67901928 /* Type */, typeArgumentNodes); } - if (type.flags & (262144 | 524288)) { - var types = type.flags & 262144 ? formatUnionTypes(type.types) : type.types; + if (type.flags & (262144 /* Union */ | 524288 /* Intersection */)) { + var types = type.flags & 262144 /* Union */ ? formatUnionTypes(type.types) : type.types; var typeNodes = mapToTypeNodes(types, context); if (typeNodes && typeNodes.length > 0) { - var unionOrIntersectionTypeNode = ts.createUnionOrIntersectionTypeNode(type.flags & 262144 ? 169 : 170, typeNodes); + var unionOrIntersectionTypeNode = ts.createUnionOrIntersectionTypeNode(type.flags & 262144 /* Union */ ? 169 /* UnionType */ : 170 /* IntersectionType */, typeNodes); return unionOrIntersectionTypeNode; } else { - if (!context.encounteredError && !(context.flags & 262144)) { + if (!context.encounteredError && !(context.flags & 262144 /* AllowEmptyUnionOrIntersection */)) { context.encounteredError = true; } - return undefined; + return undefined; // TODO: GH#18217 } } - if (objectFlags & (16 | 32)) { - ts.Debug.assert(!!(type.flags & 131072)); + if (objectFlags & (16 /* Anonymous */ | 32 /* Mapped */)) { + ts.Debug.assert(!!(type.flags & 131072 /* Object */)); + // The type is an object literal type. return createAnonymousTypeNode(type); } - if (type.flags & 1048576) { + if (type.flags & 1048576 /* Index */) { var indexedType = type.type; var indexTypeNode = typeToTypeNodeHelper(indexedType, context); return ts.createTypeOperatorNode(indexTypeNode); } - if (type.flags & 2097152) { + if (type.flags & 2097152 /* IndexedAccess */) { var objectTypeNode = typeToTypeNodeHelper(type.objectType, context); var indexTypeNode = typeToTypeNodeHelper(type.indexType, context); return ts.createIndexedAccessTypeNode(objectTypeNode, indexTypeNode); } - if (type.flags & 4194304) { + if (type.flags & 4194304 /* Conditional */) { var checkTypeNode = typeToTypeNodeHelper(type.checkType, context); var saveInferTypeParameters = context.inferTypeParameters; context.inferTypeParameters = type.root.inferTypeParameters; @@ -27601,16 +32013,18 @@ var ts; var falseTypeNode = typeToTypeNodeHelper(getFalseTypeFromConditionalType(type), context); return ts.createConditionalTypeNode(checkTypeNode, extendsTypeNode, trueTypeNode, falseTypeNode); } - if (type.flags & 8388608) { + if (type.flags & 8388608 /* Substitution */) { return typeToTypeNodeHelper(type.typeVariable, context); } return ts.Debug.fail("Should be unreachable."); function createMappedTypeNodeFromType(type) { - ts.Debug.assert(!!(type.flags & 131072)); + ts.Debug.assert(!!(type.flags & 131072 /* Object */)); var readonlyToken = type.declaration.readonlyToken ? ts.createToken(type.declaration.readonlyToken.kind) : undefined; var questionToken = type.declaration.questionToken ? ts.createToken(type.declaration.questionToken.kind) : undefined; var appropriateConstraintTypeNode; if (isMappedTypeWithKeyofConstraintDeclaration(type)) { + // We have a { [P in keyof T]: X } + // We do this to ensure we retain the toplevel keyof-ness of the type which may be lost due to keyof distribution during `getConstraintTypeFromMappedType` appropriateConstraintTypeNode = ts.createTypeOperatorNode(typeToTypeNodeHelper(getModifiersTypeFromMappedType(type), context)); } else { @@ -27619,33 +32033,39 @@ var ts; var typeParameterNode = typeParameterToDeclarationWithConstraint(getTypeParameterFromMappedType(type), context, appropriateConstraintTypeNode); var templateTypeNode = typeToTypeNodeHelper(getTemplateTypeFromMappedType(type), context); var mappedTypeNode = ts.createMappedTypeNode(readonlyToken, typeParameterNode, questionToken, templateTypeNode); - return ts.setEmitFlags(mappedTypeNode, 1); + return ts.setEmitFlags(mappedTypeNode, 1 /* SingleLine */); } function createAnonymousTypeNode(type) { var symbol = type.symbol; var id; if (symbol) { - var isConstructorObject = ts.getObjectFlags(type) & 16 && type.symbol && type.symbol.flags & 32; + var isConstructorObject = ts.getObjectFlags(type) & 16 /* Anonymous */ && type.symbol && type.symbol.flags & 32 /* Class */; id = (isConstructorObject ? "+" : "") + getSymbolId(symbol); if (isJavaScriptConstructor(symbol.valueDeclaration)) { - var isInstanceType = type === getInferredClassType(symbol) ? 67901928 : 67216319; + // Instance and static types share the same symbol; only add 'typeof' for the static side. + var isInstanceType = type === getInferredClassType(symbol) ? 67901928 /* Type */ : 67216319 /* Value */; return symbolToTypeNode(symbol, context, isInstanceType); } - else if (symbol.flags & 32 && !getBaseTypeVariableOfClass(symbol) && !(symbol.valueDeclaration.kind === 205 && context.flags & 2048) || - symbol.flags & (384 | 512) || + // Always use 'typeof T' for type of class, enum, and module objects + else if (symbol.flags & 32 /* Class */ && !getBaseTypeVariableOfClass(symbol) && !(symbol.valueDeclaration.kind === 205 /* ClassExpression */ && context.flags & 2048 /* WriteClassExpressionAsTypeLiteral */) || + symbol.flags & (384 /* Enum */ | 512 /* ValueModule */) || shouldWriteTypeOfFunctionSymbol()) { - return symbolToTypeNode(symbol, context, 67216319); + return symbolToTypeNode(symbol, context, 67216319 /* Value */); } else if (context.visitedSymbols && context.visitedSymbols.has(id)) { + // If type is an anonymous type literal in a type alias declaration, use type alias name var typeAlias = getTypeAliasForTypeLiteral(type); if (typeAlias) { - return symbolToTypeNode(typeAlias, context, 67901928); + // The specified symbol flags need to be reinterpreted as type flags + return symbolToTypeNode(typeAlias, context, 67901928 /* Type */); } else { - return ts.createKeywordTypeNode(119); + return ts.createKeywordTypeNode(119 /* AnyKeyword */); } } else { + // Since instantiations of the same anonymous type have the same symbol, tracking symbols instead + // of types allows us to catch circular references to instantiations of the same anonymous type if (!context.visitedSymbols) { context.visitedSymbols = ts.createMap(); } @@ -27656,19 +32076,21 @@ var ts; } } else { + // Anonymous types without a symbol are never circular. return createTypeNodeFromObjectType(type); } function shouldWriteTypeOfFunctionSymbol() { - var isStaticMethodSymbol = !!(symbol.flags & 8192) && - ts.some(symbol.declarations, function (declaration) { return ts.hasModifier(declaration, 32); }); - var isNonLocalFunctionSymbol = !!(symbol.flags & 16) && - (symbol.parent || + var isStaticMethodSymbol = !!(symbol.flags & 8192 /* Method */) && // typeof static method + ts.some(symbol.declarations, function (declaration) { return ts.hasModifier(declaration, 32 /* Static */); }); + var isNonLocalFunctionSymbol = !!(symbol.flags & 16 /* Function */) && + (symbol.parent || // is exported function symbol ts.forEach(symbol.declarations, function (declaration) { - return declaration.parent.kind === 274 || declaration.parent.kind === 240; + return declaration.parent.kind === 274 /* SourceFile */ || declaration.parent.kind === 240 /* ModuleBlock */; })); if (isStaticMethodSymbol || isNonLocalFunctionSymbol) { - return (!!(context.flags & 4096) || (context.visitedSymbols && context.visitedSymbols.has(id))) && - (!(context.flags & 8) || isValueSymbolAccessible(symbol, context.enclosingDeclaration)); + // typeof is allowed only for static/non local functions + return (!!(context.flags & 4096 /* UseTypeOfFunction */) || (context.visitedSymbols && context.visitedSymbols.has(id))) && // it is type of the symbol uses itself recursively + (!(context.flags & 8 /* UseStructuralFallback */) || isValueSymbolAccessible(symbol, context.enclosingDeclaration)); // TODO: GH#18217 // And the build is going to succeed without visibility error or there is no structural fallback allowed } } } @@ -27679,50 +32101,50 @@ var ts; var resolved = resolveStructuredTypeMembers(type); if (!resolved.properties.length && !resolved.stringIndexInfo && !resolved.numberIndexInfo) { if (!resolved.callSignatures.length && !resolved.constructSignatures.length) { - return ts.setEmitFlags(ts.createTypeLiteralNode(undefined), 1); + return ts.setEmitFlags(ts.createTypeLiteralNode(/*members*/ undefined), 1 /* SingleLine */); } if (resolved.callSignatures.length === 1 && !resolved.constructSignatures.length) { var signature = resolved.callSignatures[0]; - var signatureNode = signatureToSignatureDeclarationHelper(signature, 163, context); + var signatureNode = signatureToSignatureDeclarationHelper(signature, 163 /* FunctionType */, context); return signatureNode; } if (resolved.constructSignatures.length === 1 && !resolved.callSignatures.length) { var signature = resolved.constructSignatures[0]; - var signatureNode = signatureToSignatureDeclarationHelper(signature, 164, context); + var signatureNode = signatureToSignatureDeclarationHelper(signature, 164 /* ConstructorType */, context); return signatureNode; } } var savedFlags = context.flags; - context.flags |= 4194304; + context.flags |= 4194304 /* InObjectTypeLiteral */; var members = createTypeNodesFromResolvedType(resolved); context.flags = savedFlags; var typeLiteralNode = ts.createTypeLiteralNode(members); - return ts.setEmitFlags(typeLiteralNode, (context.flags & 1024) ? 0 : 1); + return ts.setEmitFlags(typeLiteralNode, (context.flags & 1024 /* MultilineObjectLiterals */) ? 0 : 1 /* SingleLine */); } function typeReferenceToTypeNode(type) { var typeArguments = type.typeArguments || ts.emptyArray; if (type.target === globalArrayType) { - if (context.flags & 2) { + if (context.flags & 2 /* WriteArrayAsGenericType */) { var typeArgumentNode = typeToTypeNodeHelper(typeArguments[0], context); return ts.createTypeReferenceNode("Array", [typeArgumentNode]); } var elementType = typeToTypeNodeHelper(typeArguments[0], context); return ts.createArrayTypeNode(elementType); } - else if (type.target.objectFlags & 8) { + else if (type.target.objectFlags & 8 /* Tuple */) { if (typeArguments.length > 0) { var tupleConstituentNodes = mapToTypeNodes(typeArguments.slice(0, getTypeReferenceArity(type)), context); if (tupleConstituentNodes && tupleConstituentNodes.length > 0) { return ts.createTupleTypeNode(tupleConstituentNodes); } } - if (context.encounteredError || (context.flags & 524288)) { + if (context.encounteredError || (context.flags & 524288 /* AllowEmptyTuple */)) { return ts.createTupleTypeNode([]); } context.encounteredError = true; - return undefined; + return undefined; // TODO: GH#18217 } - else if (context.flags & 2048 && + else if (context.flags & 2048 /* WriteClassExpressionAsTypeLiteral */ && type.symbol.valueDeclaration && ts.isClassLike(type.symbol.valueDeclaration) && !isValueSymbolAccessible(type.symbol, context.enclosingDeclaration)) { @@ -27735,16 +32157,19 @@ var ts; if (outerTypeParameters) { var length_1 = outerTypeParameters.length; while (i < length_1) { + // Find group of type arguments for type parameters with the same declaring container. var start = i; var parent = getParentSymbolOfTypeParameter(outerTypeParameters[i]); do { i++; } while (i < length_1 && getParentSymbolOfTypeParameter(outerTypeParameters[i]) === parent); + // When type parameters are their own type arguments for the whole group (i.e. we have + // the default outer type arguments), we don't show the group. if (!ts.rangeEquals(outerTypeParameters, typeArguments, start, i)) { var typeArgumentSlice = mapToTypeNodes(typeArguments.slice(start, i), context); var flags_2 = context.flags; - context.flags |= 16; - var ref = symbolToTypeNode(parent, context, 67901928, typeArgumentSlice); + context.flags |= 16 /* ForbidIndexedAccessSymbolReferences */; + var ref = symbolToTypeNode(parent, context, 67901928 /* Type */, typeArgumentSlice); context.flags = flags_2; resultType = !resultType ? ref : appendReferenceToType(resultType, ref); } @@ -27756,19 +32181,21 @@ var ts; typeArgumentNodes = mapToTypeNodes(typeArguments.slice(i, typeParameterCount), context); } var flags = context.flags; - context.flags |= 16; - var finalRef = symbolToTypeNode(type.symbol, context, 67901928, typeArgumentNodes); + context.flags |= 16 /* ForbidIndexedAccessSymbolReferences */; + var finalRef = symbolToTypeNode(type.symbol, context, 67901928 /* Type */, typeArgumentNodes); context.flags = flags; return !resultType ? finalRef : appendReferenceToType(resultType, finalRef); } } function appendReferenceToType(root, ref) { if (ts.isImportTypeNode(root)) { + // first shift type arguments var innerParams = root.typeArguments; if (root.qualifier) { (ts.isIdentifier(root.qualifier) ? root.qualifier : root.qualifier.right).typeArguments = innerParams; } root.typeArguments = ref.typeArguments; + // then move qualifiers var ids = getAccessStack(ref); for (var _i = 0, ids_1 = ids; _i < ids_1.length; _i++) { var id = ids_1[_i]; @@ -27777,9 +32204,11 @@ var ts; return root; } else { + // first shift type arguments var innerParams = root.typeArguments; (ts.isIdentifier(root.typeName) ? root.typeName : root.typeName.right).typeArguments = innerParams; root.typeArguments = ref.typeArguments; + // then move qualifiers var ids = getAccessStack(ref); for (var _a = 0, ids_2 = ids; _a < ids_2.length; _a++) { var id = ids_2[_a]; @@ -27802,20 +32231,20 @@ var ts; var typeElements = []; for (var _i = 0, _a = resolvedType.callSignatures; _i < _a.length; _i++) { var signature = _a[_i]; - typeElements.push(signatureToSignatureDeclarationHelper(signature, 158, context)); + typeElements.push(signatureToSignatureDeclarationHelper(signature, 158 /* CallSignature */, context)); } for (var _b = 0, _c = resolvedType.constructSignatures; _b < _c.length; _b++) { var signature = _c[_b]; - typeElements.push(signatureToSignatureDeclarationHelper(signature, 159, context)); + typeElements.push(signatureToSignatureDeclarationHelper(signature, 159 /* ConstructSignature */, context)); } if (resolvedType.stringIndexInfo) { - var indexInfo = resolvedType.objectFlags & 2048 ? + var indexInfo = resolvedType.objectFlags & 2048 /* ReverseMapped */ ? createIndexInfo(anyType, resolvedType.stringIndexInfo.isReadonly, resolvedType.stringIndexInfo.declaration) : resolvedType.stringIndexInfo; - typeElements.push(indexInfoToIndexSignatureDeclarationHelper(indexInfo, 0, context)); + typeElements.push(indexInfoToIndexSignatureDeclarationHelper(indexInfo, 0 /* String */, context)); } if (resolvedType.numberIndexInfo) { - typeElements.push(indexInfoToIndexSignatureDeclarationHelper(resolvedType.numberIndexInfo, 1, context)); + typeElements.push(indexInfoToIndexSignatureDeclarationHelper(resolvedType.numberIndexInfo, 1 /* Number */, context)); } var properties = resolvedType.properties; if (!properties) { @@ -27823,39 +32252,41 @@ var ts; } for (var _d = 0, properties_1 = properties; _d < properties_1.length; _d++) { var propertySymbol = properties_1[_d]; - if (context.flags & 2048) { - if (propertySymbol.flags & 4194304) { + if (context.flags & 2048 /* WriteClassExpressionAsTypeLiteral */) { + if (propertySymbol.flags & 4194304 /* Prototype */) { continue; } - if (ts.getDeclarationModifierFlagsFromSymbol(propertySymbol) & (8 | 16) && context.tracker.reportPrivateInBaseOfClassExpression) { + if (ts.getDeclarationModifierFlagsFromSymbol(propertySymbol) & (8 /* Private */ | 16 /* Protected */) && context.tracker.reportPrivateInBaseOfClassExpression) { context.tracker.reportPrivateInBaseOfClassExpression(ts.unescapeLeadingUnderscores(propertySymbol.escapedName)); } } - var propertyType = ts.getCheckFlags(propertySymbol) & 2048 && context.flags & 33554432 ? + var propertyType = ts.getCheckFlags(propertySymbol) & 2048 /* ReverseMapped */ && context.flags & 33554432 /* InReverseMappedType */ ? anyType : getTypeOfSymbol(propertySymbol); var saveEnclosingDeclaration = context.enclosingDeclaration; context.enclosingDeclaration = undefined; - if (ts.getCheckFlags(propertySymbol) & 1024) { + if (ts.getCheckFlags(propertySymbol) & 1024 /* Late */) { var decl = ts.first(propertySymbol.declarations); if (context.tracker.trackSymbol && hasLateBindableName(decl)) { + // get symbol of the first identifier of the entityName var firstIdentifier = getFirstIdentifier(decl.name.expression); - var name = resolveName(firstIdentifier, firstIdentifier.escapedText, 67216319 | 1048576, undefined, undefined, true); + var name = resolveName(firstIdentifier, firstIdentifier.escapedText, 67216319 /* Value */ | 1048576 /* ExportValue */, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); if (name) { - context.tracker.trackSymbol(name, saveEnclosingDeclaration, 67216319); + context.tracker.trackSymbol(name, saveEnclosingDeclaration, 67216319 /* Value */); } } } - var propertyName = symbolToName(propertySymbol, context, 67216319, true); + var propertyName = symbolToName(propertySymbol, context, 67216319 /* Value */, /*expectsIdentifier*/ true); context.enclosingDeclaration = saveEnclosingDeclaration; - var optionalToken = propertySymbol.flags & 16777216 ? ts.createToken(55) : undefined; - if (propertySymbol.flags & (16 | 8192) && !getPropertiesOfObjectType(propertyType).length) { - var signatures = getSignaturesOfType(propertyType, 0); + var optionalToken = propertySymbol.flags & 16777216 /* Optional */ ? ts.createToken(55 /* QuestionToken */) : undefined; + if (propertySymbol.flags & (16 /* Function */ | 8192 /* Method */) && !getPropertiesOfObjectType(propertyType).length) { + var signatures = getSignaturesOfType(propertyType, 0 /* Call */); for (var _e = 0, signatures_1 = signatures; _e < signatures_1.length; _e++) { var signature = signatures_1[_e]; - var methodDeclaration = signatureToSignatureDeclarationHelper(signature, 153, context); + var methodDeclaration = signatureToSignatureDeclarationHelper(signature, 153 /* MethodSignature */, context); methodDeclaration.name = propertyName; methodDeclaration.questionToken = optionalToken; if (propertySymbol.valueDeclaration) { + // Copy comments to node for declaration emit ts.setCommentRange(methodDeclaration, propertySymbol.valueDeclaration); } typeElements.push(methodDeclaration); @@ -27863,12 +32294,14 @@ var ts; } else { var savedFlags = context.flags; - context.flags |= !!(ts.getCheckFlags(propertySymbol) & 2048) ? 33554432 : 0; - var propertyTypeNode = propertyType ? typeToTypeNodeHelper(propertyType, context) : ts.createKeywordTypeNode(119); + context.flags |= !!(ts.getCheckFlags(propertySymbol) & 2048 /* ReverseMapped */) ? 33554432 /* InReverseMappedType */ : 0; + var propertyTypeNode = propertyType ? typeToTypeNodeHelper(propertyType, context) : ts.createKeywordTypeNode(119 /* AnyKeyword */); context.flags = savedFlags; - var modifiers = isReadonlySymbol(propertySymbol) ? [ts.createToken(132)] : undefined; - var propertySignature = ts.createPropertySignature(modifiers, propertyName, optionalToken, propertyTypeNode, undefined); + var modifiers = isReadonlySymbol(propertySymbol) ? [ts.createToken(132 /* ReadonlyKeyword */)] : undefined; + var propertySignature = ts.createPropertySignature(modifiers, propertyName, optionalToken, propertyTypeNode, + /*initializer*/ undefined); if (propertySymbol.valueDeclaration) { + // Copy comments to node for declaration emit ts.setCommentRange(propertySignature, propertySymbol.valueDeclaration); } typeElements.push(propertySignature); @@ -27892,24 +32325,30 @@ var ts; } function indexInfoToIndexSignatureDeclarationHelper(indexInfo, kind, context) { var name = ts.getNameFromIndexInfo(indexInfo) || "x"; - var indexerTypeNode = ts.createKeywordTypeNode(kind === 0 ? 137 : 134); - var indexingParameter = ts.createParameter(undefined, undefined, undefined, name, undefined, indexerTypeNode, undefined); + var indexerTypeNode = ts.createKeywordTypeNode(kind === 0 /* String */ ? 137 /* StringKeyword */ : 134 /* NumberKeyword */); + var indexingParameter = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, name, + /*questionToken*/ undefined, indexerTypeNode, + /*initializer*/ undefined); var typeNode = typeToTypeNodeHelper(indexInfo.type || anyType, context); - if (!indexInfo.type && !(context.flags & 2097152)) { + if (!indexInfo.type && !(context.flags & 2097152 /* AllowEmptyIndexInfoType */)) { context.encounteredError = true; } - return ts.createIndexSignature(undefined, indexInfo.isReadonly ? [ts.createToken(132)] : undefined, [indexingParameter], typeNode); + return ts.createIndexSignature( + /*decorators*/ undefined, indexInfo.isReadonly ? [ts.createToken(132 /* ReadonlyKeyword */)] : undefined, [indexingParameter], typeNode); } function signatureToSignatureDeclarationHelper(signature, kind, context) { var typeParameters; var typeArguments; - if (context.flags & 32 && signature.target && signature.mapper && signature.target.typeParameters) { + if (context.flags & 32 /* WriteTypeArgumentsOfSignature */ && signature.target && signature.mapper && signature.target.typeParameters) { typeArguments = signature.target.typeParameters.map(function (parameter) { return typeToTypeNodeHelper(instantiateType(parameter, signature.mapper), context); }); } else { typeParameters = signature.typeParameters && signature.typeParameters.map(function (parameter) { return typeParameterToDeclaration(parameter, context); }); } - var parameters = signature.parameters.map(function (parameter) { return symbolToParameterDeclaration(parameter, context, kind === 155); }); + var parameters = signature.parameters.map(function (parameter) { return symbolToParameterDeclaration(parameter, context, kind === 155 /* Constructor */); }); if (signature.thisParameter) { var thisParameter = symbolToParameterDeclaration(signature.thisParameter, context); parameters.unshift(thisParameter); @@ -27917,8 +32356,8 @@ var ts; var returnTypeNode; var typePredicate = getTypePredicateOfSignature(signature); if (typePredicate) { - var parameterName = typePredicate.kind === 1 ? - ts.setEmitFlags(ts.createIdentifier(typePredicate.parameterName), 16777216) : + var parameterName = typePredicate.kind === 1 /* Identifier */ ? + ts.setEmitFlags(ts.createIdentifier(typePredicate.parameterName), 16777216 /* NoAsciiEscaping */) : ts.createThisTypeNode(); var typeNode = typeToTypeNodeHelper(typePredicate.type, context); returnTypeNode = ts.createTypePredicateNode(parameterName, typeNode); @@ -27927,29 +32366,29 @@ var ts; var returnType = getReturnTypeOfSignature(signature); returnTypeNode = returnType && typeToTypeNodeHelper(returnType, context); } - if (context.flags & 256) { - if (returnTypeNode && returnTypeNode.kind === 119) { + if (context.flags & 256 /* SuppressAnyReturnType */) { + if (returnTypeNode && returnTypeNode.kind === 119 /* AnyKeyword */) { returnTypeNode = undefined; } } else if (!returnTypeNode) { - returnTypeNode = ts.createKeywordTypeNode(119); + returnTypeNode = ts.createKeywordTypeNode(119 /* AnyKeyword */); } return ts.createSignatureDeclaration(kind, typeParameters, parameters, returnTypeNode, typeArguments); } function typeParameterShadowsNameInScope(type, context) { - return !!resolveName(context.enclosingDeclaration, type.symbol.escapedName, 67901928, undefined, type.symbol.escapedName, false); + return !!resolveName(context.enclosingDeclaration, type.symbol.escapedName, 67901928 /* Type */, /*nameNotFoundArg*/ undefined, type.symbol.escapedName, /*isUse*/ false); } function typeParameterToDeclarationWithConstraint(type, context, constraintNode) { var savedContextFlags = context.flags; - context.flags &= ~512; - var shouldUseGeneratedName = context.flags & 4 && + context.flags &= ~512 /* WriteTypeParametersInQualifiedName */; // Avoids potential infinite loop when building for a claimspace with a generic + var shouldUseGeneratedName = context.flags & 4 /* GenerateNamesForShadowedTypeParams */ && type.symbol.declarations[0] && ts.isTypeParameterDeclaration(type.symbol.declarations[0]) && typeParameterShadowsNameInScope(type, context); var name = shouldUseGeneratedName - ? ts.getGeneratedNameForNode(type.symbol.declarations[0].name, 16 | 8) - : symbolToName(type.symbol, context, 67901928, true); + ? ts.getGeneratedNameForNode(type.symbol.declarations[0].name, 16 /* Optimistic */ | 8 /* ReservedInNestedScopes */) + : symbolToName(type.symbol, context, 67901928 /* Type */, /*expectsIdentifier*/ true); var defaultParameter = getDefaultFromTypeParameter(type); var defaultParameterNode = defaultParameter && typeToTypeNodeHelper(defaultParameter, context); context.flags = savedContextFlags; @@ -27961,60 +32400,65 @@ var ts; return typeParameterToDeclarationWithConstraint(type, context, constraintNode); } function symbolToParameterDeclaration(parameterSymbol, context, preserveModifierFlags) { - var parameterDeclaration = ts.getDeclarationOfKind(parameterSymbol, 149); + var parameterDeclaration = ts.getDeclarationOfKind(parameterSymbol, 149 /* Parameter */); if (!parameterDeclaration && !isTransientSymbol(parameterSymbol)) { - parameterDeclaration = ts.getDeclarationOfKind(parameterSymbol, 293); + parameterDeclaration = ts.getDeclarationOfKind(parameterSymbol, 293 /* JSDocParameterTag */); } var parameterType = getTypeOfSymbol(parameterSymbol); if (parameterDeclaration && isRequiredInitializedParameter(parameterDeclaration)) { parameterType = getOptionalType(parameterType); } var parameterTypeNode = typeToTypeNodeHelper(parameterType, context); - var modifiers = !(context.flags & 8192) && preserveModifierFlags && parameterDeclaration && parameterDeclaration.modifiers ? parameterDeclaration.modifiers.map(ts.getSynthesizedClone) : undefined; + var modifiers = !(context.flags & 8192 /* OmitParameterModifiers */) && preserveModifierFlags && parameterDeclaration && parameterDeclaration.modifiers ? parameterDeclaration.modifiers.map(ts.getSynthesizedClone) : undefined; var isRest = parameterDeclaration ? ts.isRestParameter(parameterDeclaration) : parameterSymbol.isRestParameter; - var dotDotDotToken = isRest ? ts.createToken(24) : undefined; + var dotDotDotToken = isRest ? ts.createToken(24 /* DotDotDotToken */) : undefined; var name = parameterDeclaration ? parameterDeclaration.name ? - parameterDeclaration.name.kind === 71 ? ts.setEmitFlags(ts.getSynthesizedClone(parameterDeclaration.name), 16777216) : - parameterDeclaration.name.kind === 146 ? ts.setEmitFlags(ts.getSynthesizedClone(parameterDeclaration.name.right), 16777216) : + parameterDeclaration.name.kind === 71 /* Identifier */ ? ts.setEmitFlags(ts.getSynthesizedClone(parameterDeclaration.name), 16777216 /* NoAsciiEscaping */) : + parameterDeclaration.name.kind === 146 /* QualifiedName */ ? ts.setEmitFlags(ts.getSynthesizedClone(parameterDeclaration.name.right), 16777216 /* NoAsciiEscaping */) : cloneBindingName(parameterDeclaration.name) : ts.symbolName(parameterSymbol) : ts.symbolName(parameterSymbol); - var questionToken = parameterDeclaration && isOptionalParameter(parameterDeclaration) ? ts.createToken(55) : undefined; - var parameterNode = ts.createParameter(undefined, modifiers, dotDotDotToken, name, questionToken, parameterTypeNode, undefined); + var questionToken = parameterDeclaration && isOptionalParameter(parameterDeclaration) ? ts.createToken(55 /* QuestionToken */) : undefined; + var parameterNode = ts.createParameter( + /*decorators*/ undefined, modifiers, dotDotDotToken, name, questionToken, parameterTypeNode, + /*initializer*/ undefined); return parameterNode; function cloneBindingName(node) { return elideInitializerAndSetEmitFlags(node); function elideInitializerAndSetEmitFlags(node) { - var visited = ts.visitEachChild(node, elideInitializerAndSetEmitFlags, ts.nullTransformationContext, undefined, elideInitializerAndSetEmitFlags); + var visited = ts.visitEachChild(node, elideInitializerAndSetEmitFlags, ts.nullTransformationContext, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags); var clone = ts.nodeIsSynthesized(visited) ? visited : ts.getSynthesizedClone(visited); - if (clone.kind === 182) { + if (clone.kind === 182 /* BindingElement */) { clone.initializer = undefined; } - return ts.setEmitFlags(clone, 1 | 16777216); + return ts.setEmitFlags(clone, 1 /* SingleLine */ | 16777216 /* NoAsciiEscaping */); } } } function lookupSymbolChain(symbol, context, meaning, yieldModuleSymbol) { - context.tracker.trackSymbol(symbol, context.enclosingDeclaration, meaning); + context.tracker.trackSymbol(symbol, context.enclosingDeclaration, meaning); // TODO: GH#18217 + // Try to get qualified name if the symbol is not a type parameter and there is an enclosing declaration. var chain; - var isTypeParameter = symbol.flags & 262144; - if (!isTypeParameter && (context.enclosingDeclaration || context.flags & 64)) { - chain = ts.Debug.assertDefined(getSymbolChain(symbol, meaning, true)); + var isTypeParameter = symbol.flags & 262144 /* TypeParameter */; + if (!isTypeParameter && (context.enclosingDeclaration || context.flags & 64 /* UseFullyQualifiedType */)) { + chain = ts.Debug.assertDefined(getSymbolChain(symbol, meaning, /*endOfChain*/ true)); ts.Debug.assert(chain && chain.length > 0); } else { chain = [symbol]; } return chain; + /** @param endOfChain Set to false for recursive calls; non-recursive calls should always output something. */ function getSymbolChain(symbol, meaning, endOfChain) { - var accessibleSymbolChain = getAccessibleSymbolChain(symbol, context.enclosingDeclaration, meaning, !!(context.flags & 128)); + var accessibleSymbolChain = getAccessibleSymbolChain(symbol, context.enclosingDeclaration, meaning, !!(context.flags & 128 /* UseOnlyExternalAliasing */)); var parentSymbol; if (!accessibleSymbolChain || needsQualification(accessibleSymbolChain[0], context.enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) { + // Go up and add our parent. var parent = getContainerOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol); if (parent) { - var parentChain = getSymbolChain(parent, getQualifiedLeftMeaning(meaning), false); + var parentChain = getSymbolChain(parent, getQualifiedLeftMeaning(meaning), /*endOfChain*/ false); if (parentChain) { parentSymbol = parent; accessibleSymbolChain = parentChain.concat(accessibleSymbolChain || [getAliasForSymbolInContainer(parent, symbol) || symbol]); @@ -28024,9 +32468,13 @@ var ts; if (accessibleSymbolChain) { return accessibleSymbolChain; } - if (endOfChain || + if ( + // If this is the last part of outputting the symbol, always output. The cases apply only to parent symbols. + endOfChain || + // If a parent symbol is an external module, don't write it. (We prefer just `x` vs `"foo/bar".x`.) (yieldModuleSymbol || !(!parentSymbol && ts.forEach(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol))) && - !(symbol.flags & (2048 | 4096))) { + // If a parent symbol is an anonymous type, don't write it. + !(symbol.flags & (2048 /* TypeLiteral */ | 4096 /* ObjectLiteral */))) { return [symbol]; } } @@ -28034,7 +32482,7 @@ var ts; function typeParametersToTypeParameterDeclarations(symbol, context) { var typeParameterNodes; var targetSymbol = getTargetSymbol(symbol); - if (targetSymbol.flags & (32 | 64 | 524288)) { + if (targetSymbol.flags & (32 /* Class */ | 64 /* Interface */ | 524288 /* TypeAlias */)) { typeParameterNodes = ts.createNodeArray(ts.map(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol), function (tp) { return typeParameterToDeclaration(tp, context); })); } return typeParameterNodes; @@ -28043,11 +32491,11 @@ var ts; ts.Debug.assert(chain && 0 <= index && index < chain.length); var symbol = chain[index]; var typeParameterNodes; - if (context.flags & 512 && index < (chain.length - 1)) { + if (context.flags & 512 /* WriteTypeParametersInQualifiedName */ && index < (chain.length - 1)) { var parentSymbol = symbol; var nextSymbol = chain[index + 1]; - if (ts.getCheckFlags(nextSymbol) & 1) { - var params = getTypeParametersOfClassOrInterface(parentSymbol.flags & 2097152 ? resolveAlias(parentSymbol) : parentSymbol); + if (ts.getCheckFlags(nextSymbol) & 1 /* Instantiated */) { + var params = getTypeParametersOfClassOrInterface(parentSymbol.flags & 2097152 /* Alias */ ? resolveAlias(parentSymbol) : parentSymbol); typeParameterNodes = mapToTypeNodes(ts.map(params, nextSymbol.mapper), context); } else { @@ -28056,6 +32504,9 @@ var ts; } return typeParameterNodes; } + /** + * Given A[B][C][D], finds A[B] + */ function getTopmostIndexedAccessType(top) { if (ts.isIndexedAccessTypeNode(top.objectType)) { return getTopmostIndexedAccessType(top.objectType); @@ -28063,12 +32514,13 @@ var ts; return top; } function symbolToTypeNode(symbol, context, meaning, overrideTypeArguments) { - var chain = lookupSymbolChain(symbol, context, meaning, !(context.flags & 16384)); - context.flags |= 16777216; + var chain = lookupSymbolChain(symbol, context, meaning, !(context.flags & 16384 /* UseAliasDefinedOutsideCurrentScope */)); // If we're using aliases outside the current scope, dont bother with the module + context.flags |= 16777216 /* InInitialEntityName */; var rootName = getNameOfSymbolAsWritten(chain[0], context); - context.flags ^= 16777216; - var isTypeOf = meaning === 67216319; + context.flags ^= 16777216 /* InInitialEntityName */; + var isTypeOf = meaning === 67216319 /* Value */; if (ambientModuleSymbolRegex.test(rootName)) { + // module is root, must use `ImportTypeNode` var nonRootParts = chain.length > 1 ? createAccessFromSymbolChain(chain, chain.length - 1, 1) : undefined; var typeParameterNodes = overrideTypeArguments || lookupTypeParameterNodes(chain, 0, context); var lit = ts.createLiteralTypeNode(ts.createLiteral(rootName.substring(1, rootName.length - 1))); @@ -28087,7 +32539,7 @@ var ts; } var entityName = createAccessFromSymbolChain(chain, chain.length - 1, 0); if (ts.isIndexedAccessTypeNode(entityName)) { - return entityName; + return entityName; // Indexed accesses can never be `typeof` } if (isTypeOf) { return ts.createTypeQueryNode(entityName); @@ -28102,14 +32554,15 @@ var ts; var typeParameterNodes = index === (chain.length - 1) ? overrideTypeArguments : lookupTypeParameterNodes(chain, index, context); var symbol = chain[index]; if (index === 0) { - context.flags |= 16777216; + context.flags |= 16777216 /* InInitialEntityName */; } var symbolName = getNameOfSymbolAsWritten(symbol, context); if (index === 0) { - context.flags ^= 16777216; + context.flags ^= 16777216 /* InInitialEntityName */; } var parent = chain[index - 1]; - if (!(context.flags & 16) && parent && getMembersOfSymbol(parent) && getMembersOfSymbol(parent).get(symbol.escapedName) === symbol) { + if (!(context.flags & 16 /* ForbidIndexedAccessSymbolReferences */) && parent && getMembersOfSymbol(parent) && getMembersOfSymbol(parent).get(symbol.escapedName) === symbol) { + // Should use an indexed access var LHS = createAccessFromSymbolChain(chain, index - 1, stopper); if (ts.isIndexedAccessTypeNode(LHS)) { return ts.createIndexedAccessTypeNode(LHS, ts.createLiteralTypeNode(ts.createLiteral(symbolName))); @@ -28118,7 +32571,7 @@ var ts; return ts.createIndexedAccessTypeNode(ts.createTypeReferenceNode(LHS, typeParameterNodes), ts.createLiteralTypeNode(ts.createLiteral(symbolName))); } } - var identifier = ts.setEmitFlags(ts.createIdentifier(symbolName, typeParameterNodes), 16777216); + var identifier = ts.setEmitFlags(ts.createIdentifier(symbolName, typeParameterNodes), 16777216 /* NoAsciiEscaping */); identifier.symbol = symbol; if (index > stopper) { var LHS = createAccessFromSymbolChain(chain, index - 1, stopper); @@ -28134,7 +32587,7 @@ var ts; var chain = lookupSymbolChain(symbol, context, meaning); if (expectsIdentifier && chain.length !== 1 && !context.encounteredError - && !(context.flags & 65536)) { + && !(context.flags & 65536 /* AllowQualifedNameInPlaceOfIdentifier */)) { context.encounteredError = true; } return createEntityNameFromSymbolChain(chain, chain.length - 1); @@ -28142,13 +32595,13 @@ var ts; var typeParameterNodes = lookupTypeParameterNodes(chain, index, context); var symbol = chain[index]; if (index === 0) { - context.flags |= 16777216; + context.flags |= 16777216 /* InInitialEntityName */; } var symbolName = getNameOfSymbolAsWritten(symbol, context); if (index === 0) { - context.flags ^= 16777216; + context.flags ^= 16777216 /* InInitialEntityName */; } - var identifier = ts.setEmitFlags(ts.createIdentifier(symbolName, typeParameterNodes), 16777216); + var identifier = ts.setEmitFlags(ts.createIdentifier(symbolName, typeParameterNodes), 16777216 /* NoAsciiEscaping */); identifier.symbol = symbol; return index > 0 ? ts.createQualifiedName(createEntityNameFromSymbolChain(chain, index - 1), identifier) : identifier; } @@ -28160,34 +32613,34 @@ var ts; var typeParameterNodes = lookupTypeParameterNodes(chain, index, context); var symbol = chain[index]; if (index === 0) { - context.flags |= 16777216; + context.flags |= 16777216 /* InInitialEntityName */; } var symbolName = getNameOfSymbolAsWritten(symbol, context); if (index === 0) { - context.flags ^= 16777216; + context.flags ^= 16777216 /* InInitialEntityName */; } var firstChar = symbolName.charCodeAt(0); var canUsePropertyAccess = ts.isIdentifierStart(firstChar, languageVersion); if (index === 0 || canUsePropertyAccess) { - var identifier = ts.setEmitFlags(ts.createIdentifier(symbolName, typeParameterNodes), 16777216); + var identifier = ts.setEmitFlags(ts.createIdentifier(symbolName, typeParameterNodes), 16777216 /* NoAsciiEscaping */); identifier.symbol = symbol; return index > 0 ? ts.createPropertyAccess(createExpressionFromSymbolChain(chain, index - 1), identifier) : identifier; } else { - if (firstChar === 91) { + if (firstChar === 91 /* openBracket */) { symbolName = symbolName.substring(1, symbolName.length - 1); firstChar = symbolName.charCodeAt(0); } var expression = void 0; if (ts.isSingleOrDoubleQuote(firstChar)) { expression = ts.createLiteral(symbolName.substring(1, symbolName.length - 1).replace(/\\./g, function (s) { return s.substring(1); })); - expression.singleQuote = firstChar === 39; + expression.singleQuote = firstChar === 39 /* singleQuote */; } else if (("" + +symbolName) === symbolName) { expression = ts.createLiteral(+symbolName); } if (!expression) { - expression = ts.setEmitFlags(ts.createIdentifier(symbolName, typeParameterNodes), 16777216); + expression = ts.setEmitFlags(ts.createIdentifier(symbolName, typeParameterNodes), 16777216 /* NoAsciiEscaping */); expression.symbol = symbol; } return ts.createElementAccess(createExpressionFromSymbolChain(chain, index - 1), expression); @@ -28196,13 +32649,13 @@ var ts; } } function typePredicateToString(typePredicate, enclosingDeclaration, flags, writer) { - if (flags === void 0) { flags = 16384; } + if (flags === void 0) { flags = 16384 /* UseAliasDefinedOutsideCurrentScope */; } return writer ? typePredicateToStringWorker(writer).getText() : ts.usingSingleLineStringWriter(typePredicateToStringWorker); function typePredicateToStringWorker(writer) { - var predicate = ts.createTypePredicateNode(typePredicate.kind === 1 ? ts.createIdentifier(typePredicate.parameterName) : ts.createThisTypeNode(), nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | 3112960 | 512)); + var predicate = ts.createTypePredicateNode(typePredicate.kind === 1 /* Identifier */ ? ts.createIdentifier(typePredicate.parameterName) : ts.createThisTypeNode(), nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | 3112960 /* IgnoreErrors */ | 512 /* WriteTypeParametersInQualifiedName */)); var printer = ts.createPrinter({ removeComments: true }); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); - printer.writeNode(4, predicate, sourceFile, writer); + printer.writeNode(4 /* Unspecified */, predicate, /*sourceFile*/ sourceFile, writer); return writer; } } @@ -28212,10 +32665,10 @@ var ts; for (var i = 0; i < types.length; i++) { var t = types[i]; flags |= t.flags; - if (!(t.flags & 24576)) { - if (t.flags & (256 | 512)) { - var baseType = t.flags & 256 ? booleanType : getBaseTypeOfEnumLiteralType(t); - if (baseType.flags & 262144) { + if (!(t.flags & 24576 /* Nullable */)) { + if (t.flags & (256 /* BooleanLiteral */ | 512 /* EnumLiteral */)) { + var baseType = t.flags & 256 /* BooleanLiteral */ ? booleanType : getBaseTypeOfEnumLiteralType(t); + if (baseType.flags & 262144 /* Union */) { var count = baseType.types.length; if (i + count <= types.length && types[i + count - 1] === baseType.types[count - 1]) { result.push(baseType); @@ -28227,25 +32680,25 @@ var ts; result.push(t); } } - if (flags & 16384) + if (flags & 16384 /* Null */) result.push(nullType); - if (flags & 8192) + if (flags & 8192 /* Undefined */) result.push(undefinedType); return result || types; } function visibilityToString(flags) { - if (flags === 8) { + if (flags === 8 /* Private */) { return "private"; } - if (flags === 16) { + if (flags === 16 /* Protected */) { return "protected"; } return "public"; } function getTypeAliasForTypeLiteral(type) { - if (type.symbol && type.symbol.flags & 2048) { - var node = ts.findAncestor(type.symbol.declarations[0].parent, function (n) { return n.kind !== 173; }); - if (node.kind === 237) { + if (type.symbol && type.symbol.flags & 2048 /* TypeLiteral */) { + var node = ts.findAncestor(type.symbol.declarations[0].parent, function (n) { return n.kind !== 173 /* ParenthesizedType */; }); + if (node.kind === 237 /* TypeAliasDeclaration */) { return getSymbolOfNode(node); } } @@ -28253,32 +32706,43 @@ var ts; } function isTopLevelInExternalModuleAugmentation(node) { return node && node.parent && - node.parent.kind === 240 && + node.parent.kind === 240 /* ModuleBlock */ && ts.isExternalModuleAugmentation(node.parent.parent); } function isDefaultBindingContext(location) { - return location.kind === 274 || ts.isAmbientModule(location); + return location.kind === 274 /* SourceFile */ || ts.isAmbientModule(location); } + /** + * Gets a human-readable name for a symbol. + * Should *not* be used for the right-hand side of a `.` -- use `symbolName(symbol)` for that instead. + * + * Unlike `symbolName(symbol)`, this will include quotes if the name is from a string literal. + * It will also use a representation of a number as written instead of a decimal form, e.g. `0o11` instead of `9`. + */ function getNameOfSymbolAsWritten(symbol, context) { - if (context && symbol.escapedName === "default" && !(context.flags & 16384) && - (!(context.flags & 16777216) || + if (context && symbol.escapedName === "default" /* Default */ && !(context.flags & 16384 /* UseAliasDefinedOutsideCurrentScope */) && + // If it's not the first part of an entity name, it must print as `default` + (!(context.flags & 16777216 /* InInitialEntityName */) || + // if the symbol is synthesized, it will only be referenced externally it must print as `default` !symbol.declarations || + // if not in the same binding context (source file, module declaration), it must print as `default` (context.enclosingDeclaration && ts.findAncestor(symbol.declarations[0], isDefaultBindingContext) !== ts.findAncestor(context.enclosingDeclaration, isDefaultBindingContext)))) { return "default"; } if (symbol.declarations && symbol.declarations.length) { - if (ts.some(symbol.declarations, hasExternalModuleSymbol) && context.enclosingDeclaration) { - var file = ts.getDeclarationOfKind(symbol, 274); + if (ts.some(symbol.declarations, hasExternalModuleSymbol) && context.enclosingDeclaration) { // TODO: GH#18217 + var file = ts.getDeclarationOfKind(symbol, 274 /* SourceFile */); if (!file || !context.tracker.moduleResolverHost) { if (context.tracker.trackReferencedAmbientModule) { var ambientDecls = ts.filter(symbol.declarations, ts.isAmbientModule); if (ts.length(ambientDecls)) { for (var _i = 0, ambientDecls_1 = ambientDecls; _i < ambientDecls_1.length; _i++) { var decl = ambientDecls_1[_i]; - context.tracker.trackReferencedAmbientModule(decl); + context.tracker.trackReferencedAmbientModule(decl); // TODO: GH#18217 } } } + // ambient module, just use declaration/symbol name (fallthrough) } else { var contextFile = ts.getSourceFileOfNode(ts.getOriginalNode(context.enclosingDeclaration)); @@ -28290,26 +32754,26 @@ var ts; if (name) { return ts.declarationNameToString(name); } - if (declaration.parent && declaration.parent.kind === 232) { + if (declaration.parent && declaration.parent.kind === 232 /* VariableDeclaration */) { return ts.declarationNameToString(declaration.parent.name); } - if (context && !context.encounteredError && !(context.flags & 131072)) { + if (context && !context.encounteredError && !(context.flags & 131072 /* AllowAnonymousIdentifier */)) { context.encounteredError = true; } switch (declaration.kind) { - case 205: + case 205 /* ClassExpression */: return "(Anonymous class)"; - case 192: - case 193: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: return "(Anonymous function)"; } } var nameType = symbol.nameType; if (nameType) { - if (nameType.flags & 64 && !ts.isIdentifierText(nameType.value, compilerOptions.target)) { - return "\"" + ts.escapeString(nameType.value, 34) + "\""; + if (nameType.flags & 64 /* StringLiteral */ && !ts.isIdentifierText(nameType.value, compilerOptions.target)) { + return "\"" + ts.escapeString(nameType.value, 34 /* doubleQuote */) + "\""; } - if (nameType && nameType.flags & 2048) { + if (nameType && nameType.flags & 2048 /* UniqueESSymbol */) { return "[" + getNameOfSymbolAsWritten(nameType.symbol, context) + "]"; } } @@ -28326,66 +32790,81 @@ var ts; return false; function determineIfDeclarationIsVisible() { switch (node.kind) { - case 292: - case 298: + case 292 /* JSDocCallbackTag */: + case 298 /* JSDocTypedefTag */: + // Top-level jsdoc type aliases are considered exported + // First parent is comment node, second is hosting declaration or token; we only care about those tokens or declarations whose parent is a source file return !!(node.parent && node.parent.parent && node.parent.parent.parent && ts.isSourceFile(node.parent.parent.parent)); - case 182: + case 182 /* BindingElement */: return isDeclarationVisible(node.parent.parent); - case 232: + case 232 /* VariableDeclaration */: if (ts.isBindingPattern(node.name) && !node.name.elements.length) { + // If the binding pattern is empty, this variable declaration is not visible return false; } - case 239: - case 235: - case 236: - case 237: - case 234: - case 238: - case 243: + // falls through + case 239 /* ModuleDeclaration */: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 234 /* FunctionDeclaration */: + case 238 /* EnumDeclaration */: + case 243 /* ImportEqualsDeclaration */: + // external module augmentation is always visible if (ts.isExternalModuleAugmentation(node)) { return true; } var parent = getDeclarationContainer(node); - if (!(ts.getCombinedModifierFlags(node) & 1) && - !(node.kind !== 243 && parent.kind !== 274 && parent.flags & 4194304)) { + // If the node is not exported or it is not ambient module element (except import declaration) + if (!(ts.getCombinedModifierFlags(node) & 1 /* Export */) && + !(node.kind !== 243 /* ImportEqualsDeclaration */ && parent.kind !== 274 /* SourceFile */ && parent.flags & 4194304 /* Ambient */)) { return isGlobalSourceFile(parent); } + // Exported members/ambient module elements (exception import declaration) are visible if parent is visible return isDeclarationVisible(parent); - case 152: - case 151: - case 156: - case 157: - case 154: - case 153: - if (ts.hasModifier(node, 8 | 16)) { + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + if (ts.hasModifier(node, 8 /* Private */ | 16 /* Protected */)) { + // Private/protected properties/methods are not visible return false; } - case 155: - case 159: - case 158: - case 160: - case 149: - case 240: - case 163: - case 164: - case 166: - case 162: - case 167: - case 168: - case 169: - case 170: - case 173: + // Public properties/methods are visible if its parents are visible, so: + // falls through + case 155 /* Constructor */: + case 159 /* ConstructSignature */: + case 158 /* CallSignature */: + case 160 /* IndexSignature */: + case 149 /* Parameter */: + case 240 /* ModuleBlock */: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 166 /* TypeLiteral */: + case 162 /* TypeReference */: + case 167 /* ArrayType */: + case 168 /* TupleType */: + case 169 /* UnionType */: + case 170 /* IntersectionType */: + case 173 /* ParenthesizedType */: return isDeclarationVisible(node.parent); - case 245: - case 246: - case 248: + // Default binding, import specifier and namespace import is visible + // only on demand so by default it is not visible + case 245 /* ImportClause */: + case 246 /* NamespaceImport */: + case 248 /* ImportSpecifier */: return false; - case 148: - case 274: - case 242: + // Type parameters are always visible + case 148 /* TypeParameter */: + // Source file and namespace export are always visible + case 274 /* SourceFile */: + case 242 /* NamespaceExportDeclaration */: return true; - case 249: + // Export assignments do not create name bindings outside the module + case 249 /* ExportAssignment */: return false; default: return false; @@ -28394,11 +32873,11 @@ var ts; } function collectLinkedAliases(node, setVisibility) { var exportSymbol; - if (node.parent && node.parent.kind === 249) { - exportSymbol = resolveName(node, node.escapedText, 67216319 | 67901928 | 1920 | 2097152, undefined, node, false); + if (node.parent && node.parent.kind === 249 /* ExportAssignment */) { + exportSymbol = resolveName(node, node.escapedText, 67216319 /* Value */ | 67901928 /* Type */ | 1920 /* Namespace */ | 2097152 /* Alias */, /*nameNotFoundMessage*/ undefined, node, /*isUse*/ false); } - else if (node.parent.kind === 252) { - exportSymbol = getTargetOfExportSpecifier(node.parent, 67216319 | 67901928 | 1920 | 2097152); + else if (node.parent.kind === 252 /* ExportSpecifier */) { + exportSymbol = getTargetOfExportSpecifier(node.parent, 67216319 /* Value */ | 67901928 /* Type */ | 1920 /* Namespace */ | 2097152 /* Alias */); } var result; if (exportSymbol) { @@ -28416,9 +32895,10 @@ var ts; ts.pushIfUnique(result, resultNode); } if (ts.isInternalModuleImportEqualsDeclaration(declaration)) { + // Add the referenced top container visible var internalModuleReference = declaration.moduleReference; var firstIdentifier = getFirstIdentifier(internalModuleReference); - var importSymbol = resolveName(declaration, firstIdentifier.escapedText, 67216319 | 67901928 | 1920, undefined, undefined, false); + var importSymbol = resolveName(declaration, firstIdentifier.escapedText, 67216319 /* Value */ | 67901928 /* Type */ | 1920 /* Namespace */, undefined, undefined, /*isUse*/ false); if (importSymbol) { buildVisibleNodeList(importSymbol.declarations); } @@ -28426,9 +32906,21 @@ var 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. + * 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 + * must match the one passed in. + * + * @param target The symbol, type, or signature whose type is being queried + * @param propertyName The property name that should be used to query the target for its type + */ function pushTypeResolution(target, propertyName) { var resolutionCycleStartIndex = findResolutionCycleStartIndex(target, propertyName); if (resolutionCycleStartIndex >= 0) { + // A cycle was found var length_2 = resolutionTargets.length; for (var i = resolutionCycleStartIndex; i < length_2; i++) { resolutionResults[i] = false; @@ -28436,7 +32928,7 @@ var ts; return false; } resolutionTargets.push(target); - resolutionResults.push(true); + resolutionResults.push(/*items*/ true); resolutionPropertyNames.push(propertyName); return true; } @@ -28452,24 +32944,26 @@ var ts; return -1; } function hasType(target, propertyName) { - if (propertyName === 0) { + if (propertyName === 0 /* Type */) { return !!getSymbolLinks(target).type; } - if (propertyName === 2) { + if (propertyName === 2 /* DeclaredType */) { return !!getSymbolLinks(target).declaredType; } - if (propertyName === 1) { + if (propertyName === 1 /* ResolvedBaseConstructorType */) { return !!target.resolvedBaseConstructorType; } - if (propertyName === 3) { + if (propertyName === 3 /* ResolvedReturnType */) { return !!target.resolvedReturnType; } - if (propertyName === 4) { + if (propertyName === 4 /* ResolvedBaseConstraint */) { var bc = target.resolvedBaseConstraint; return !!bc && bc !== circularConstraintType; } return ts.Debug.fail("Unhandled TypeSystemPropertyName " + propertyName); } + // Pop an entry from the type resolution stack and return its associated result value. The result value will + // be true if no circularities were detected, or false if a circularity was found. function popTypeResolution() { resolutionTargets.pop(); resolutionPropertyNames.pop(); @@ -28478,12 +32972,12 @@ var ts; function getDeclarationContainer(node) { return ts.findAncestor(ts.getRootDeclaration(node), function (node) { switch (node.kind) { - case 232: - case 233: - case 248: - case 247: - case 246: - case 245: + case 232 /* VariableDeclaration */: + case 233 /* VariableDeclarationList */: + case 248 /* ImportSpecifier */: + case 247 /* NamedImports */: + case 246 /* NamespaceImport */: + case 245 /* ImportClause */: return false; default: return true; @@ -28491,29 +32985,36 @@ var ts; }).parent; } function getTypeOfPrototypeProperty(prototype) { + // TypeScript 1.0 spec (April 2014): 8.4 + // Every class automatically contains a static property member named 'prototype', + // the type of which is an instantiation of the class type with type Any supplied as a type argument for each type parameter. + // It is an error to explicitly declare a static property member with the name 'prototype'. var classType = getDeclaredTypeOfSymbol(getParentOfSymbol(prototype)); return classType.typeParameters ? createTypeReference(classType, ts.map(classType.typeParameters, function (_) { return anyType; })) : classType; } + // Return the type of the given property in the given type, or undefined if no such property exists function getTypeOfPropertyOfType(type, name) { var prop = getPropertyOfType(type, name); return prop ? getTypeOfSymbol(prop) : undefined; } function isTypeAny(type) { - return type && (type.flags & 1) !== 0; + return type && (type.flags & 1 /* Any */) !== 0; } + // Return the type of a binding element parent. We check SymbolLinks first to see if a type has been + // assigned by contextual typing. function getTypeForBindingElementParent(node) { var symbol = getSymbolOfNode(node); - return symbol && getSymbolLinks(symbol).type || getTypeForVariableLikeDeclaration(node, false); + return symbol && getSymbolLinks(symbol).type || getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false); } function isComputedNonLiteralName(name) { - return name.kind === 147 && !ts.isStringOrNumericLiteral(name.expression); + return name.kind === 147 /* ComputedPropertyName */ && !ts.isStringOrNumericLiteral(name.expression); } function getRestType(source, properties, symbol) { - source = filterType(source, function (t) { return !(t.flags & 24576); }); - if (source.flags & 32768) { + source = filterType(source, function (t) { return !(t.flags & 24576 /* Nullable */); }); + if (source.flags & 32768 /* Never */) { return emptyObjectType; } - if (source.flags & 262144) { + if (source.flags & 262144 /* Union */) { return mapType(source, function (t) { return getRestType(t, properties, symbol); }); } var members = ts.createSymbolTable(); @@ -28525,22 +33026,27 @@ var ts; for (var _a = 0, _b = getPropertiesOfType(source); _a < _b.length; _a++) { var prop = _b[_a]; var inNamesToRemove = names.has(prop.escapedName); - var isPrivate = ts.getDeclarationModifierFlagsFromSymbol(prop) & (8 | 16); - var isSetOnlyAccessor = prop.flags & 65536 && !(prop.flags & 32768); + var isPrivate = ts.getDeclarationModifierFlagsFromSymbol(prop) & (8 /* Private */ | 16 /* Protected */); + var isSetOnlyAccessor = prop.flags & 65536 /* SetAccessor */ && !(prop.flags & 32768 /* GetAccessor */); if (!inNamesToRemove && !isPrivate && !isClassMethod(prop) && !isSetOnlyAccessor) { members.set(prop.escapedName, getNonReadonlySymbol(prop)); } } - var stringIndexInfo = getIndexInfoOfType(source, 0); - var numberIndexInfo = getIndexInfoOfType(source, 1); + var stringIndexInfo = getIndexInfoOfType(source, 0 /* String */); + var numberIndexInfo = getIndexInfoOfType(source, 1 /* Number */); return createAnonymousType(symbol, members, ts.emptyArray, ts.emptyArray, stringIndexInfo, numberIndexInfo); } + /** Return the inferred type for a binding element */ function getTypeForBindingElement(declaration) { var pattern = declaration.parent; var parentType = getTypeForBindingElementParent(pattern.parent); + // If parent has the unknown (error) type, then so does this binding element if (parentType === errorType) { return errorType; } + // If no type was specified or inferred for parent, + // infer from the initializer of the binding element if one is present. + // Otherwise, go with the undefined type of the parent. if (!parentType) { return declaration.initializer ? checkDeclarationInitializer(declaration) : parentType; } @@ -28548,9 +33054,9 @@ var ts; return parentType; } var type; - if (pattern.kind === 180) { + if (pattern.kind === 180 /* ObjectBindingPattern */) { if (declaration.dotDotDotToken) { - if (parentType.flags & 2 || !isValidSpreadType(parentType)) { + if (parentType.flags & 2 /* Unknown */ || !isValidSpreadType(parentType)) { error(declaration, ts.Diagnostics.Rest_types_may_only_be_created_from_object_types); return errorType; } @@ -28564,20 +33070,21 @@ var ts; type = getRestType(parentType, literalMembers, declaration.symbol); } else { + // Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form) var name = declaration.propertyName || declaration.name; var isLate = isLateBindableName(name); var isWellKnown = ts.isComputedPropertyName(name) && ts.isWellKnownSymbolSyntactically(name.expression); if (!isLate && !isWellKnown && isComputedNonLiteralName(name)) { var exprType = checkExpression(name.expression); - if (isTypeAssignableToKind(exprType, 3072)) { + if (isTypeAssignableToKind(exprType, 3072 /* ESSymbolLike */)) { if (noImplicitAny) { error(declaration, ts.Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(exprType), typeToString(parentType)); } return anyType; } - var indexerType = isTypeAssignableToKind(exprType, 168) && getIndexTypeOfType(parentType, 1) || getIndexTypeOfType(parentType, 0); + var indexerType = isTypeAssignableToKind(exprType, 168 /* NumberLike */) && getIndexTypeOfType(parentType, 1 /* Number */) || getIndexTypeOfType(parentType, 0 /* String */); if (!indexerType && noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors) { - if (getIndexTypeOfType(parentType, 1)) { + if (getIndexTypeOfType(parentType, 1 /* Number */)) { error(declaration, ts.Diagnostics.Element_implicitly_has_an_any_type_because_index_expression_is_not_of_type_number); } else { @@ -28586,14 +33093,17 @@ var ts; } return indexerType || anyType; } + // Use type of the specified property, or otherwise, for a numeric name, the type of the numeric index signature, + // or otherwise the type of the string index signature. var nameType = isLate ? checkComputedPropertyName(name) : undefined; var text = isLate ? getLateBoundNameFromType(nameType) : isWellKnown ? ts.getPropertyNameForKnownSymbolName(ts.idText(name.expression.name)) : ts.getTextOfPropertyName(name); - if (strictNullChecks && declaration.flags & 4194304 && ts.isParameterDeclaration(declaration)) { + // Relax null check on ambient destructuring parameters, since the parameters have no implementation and are just documentation + if (strictNullChecks && declaration.flags & 4194304 /* Ambient */ && ts.isParameterDeclaration(declaration)) { parentType = getNonNullableType(parentType); } - if (isLate && nameType && !getPropertyOfType(parentType, text) && isTypeAssignableToKind(nameType, 3072)) { + if (isLate && nameType && !getPropertyOfType(parentType, text) && isTypeAssignableToKind(nameType, 3072 /* ESSymbolLike */)) { if (noImplicitAny) { error(declaration, ts.Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(nameType), typeToString(parentType)); } @@ -28601,8 +33111,8 @@ var ts; } var declaredType = getConstraintForLocation(getTypeOfPropertyOfType(parentType, text), declaration.name); type = declaredType && getFlowTypeOfReference(declaration, declaredType) || - isNumericLiteralName(text) && getIndexTypeOfType(parentType, 1) || - getIndexTypeOfType(parentType, 0); + isNumericLiteralName(text) && getIndexTypeOfType(parentType, 1 /* Number */) || + getIndexTypeOfType(parentType, 0 /* String */); if (!type) { error(name, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), ts.declarationNameToString(name)); return errorType; @@ -28610,11 +33120,16 @@ var ts; } } else { - var elementType = checkIteratedTypeOrElementType(parentType, pattern, false, false); + // This elementType will be used if the specific property corresponding to this index is not + // present (aka the tuple element property). This call also checks that the parentType is in + // fact an iterable or array (depending on target language). + var elementType = checkIteratedTypeOrElementType(parentType, pattern, /*allowStringInput*/ false, /*allowAsyncIterables*/ false); if (declaration.dotDotDotToken) { + // Rest element has an array type with the same element type as the parent type type = createArrayType(elementType); } else { + // Use specific property type when parent is a tuple or numeric index type when parent is an array var propName = "" + pattern.elements.indexOf(declaration); type = isTupleLikeType(parentType) ? getTypeOfPropertyOfType(parentType, propName) @@ -28630,11 +33145,13 @@ var ts; } } } - if (strictNullChecks && declaration.initializer && !(getFalsyFlags(checkExpressionCached(declaration.initializer)) & 8192)) { - type = getTypeWithFacts(type, 131072); + // In strict null checking mode, if a default value of a non-undefined type is specified, remove + // undefined from the final type. + if (strictNullChecks && declaration.initializer && !(getFalsyFlags(checkExpressionCached(declaration.initializer)) & 8192 /* Undefined */)) { + type = getTypeWithFacts(type, 131072 /* NEUndefined */); } return declaration.initializer ? - getUnionType([type, checkExpressionCached(declaration.initializer)], 2) : + getUnionType([type, checkExpressionCached(declaration.initializer)], 2 /* Subtype */) : type; } function getTypeForDeclarationFromJSDocComment(declaration) { @@ -28646,22 +33163,29 @@ var ts; } function isNullOrUndefined(node) { var expr = ts.skipParentheses(node); - return expr.kind === 95 || expr.kind === 71 && getResolvedSymbol(expr) === undefinedSymbol; + return expr.kind === 95 /* NullKeyword */ || expr.kind === 71 /* Identifier */ && getResolvedSymbol(expr) === undefinedSymbol; } function isEmptyArrayLiteral(node) { var expr = ts.skipParentheses(node); - return expr.kind === 183 && expr.elements.length === 0; + return expr.kind === 183 /* ArrayLiteralExpression */ && expr.elements.length === 0; } function addOptionality(type, optional) { if (optional === void 0) { optional = true; } return strictNullChecks && optional ? getOptionalType(type) : type; } + // Return the inferred type for a variable, parameter, or property declaration function getTypeForVariableLikeDeclaration(declaration, includeOptionality) { - if (ts.isVariableDeclaration(declaration) && declaration.parent.parent.kind === 221) { + // A variable declared in a for..in statement is of type string, or of type keyof T when the + // right hand expression is of a type parameter type. + if (ts.isVariableDeclaration(declaration) && declaration.parent.parent.kind === 221 /* ForInStatement */) { var indexType = getIndexType(checkNonNullExpression(declaration.parent.parent.expression)); - return indexType.flags & (65536 | 1048576) ? getExtractStringType(indexType) : stringType; + return indexType.flags & (65536 /* TypeParameter */ | 1048576 /* Index */) ? getExtractStringType(indexType) : stringType; } - if (ts.isVariableDeclaration(declaration) && declaration.parent.parent.kind === 222) { + if (ts.isVariableDeclaration(declaration) && declaration.parent.parent.kind === 222 /* ForOfStatement */) { + // checkRightHandSideOfForOf will return undefined if the for-of expression type was + // missing properties/signatures required to get its iteratedType (like + // [Symbol.iterator] or next). This may be because we accessed properties from anyType, + // or it may have led to an error inside getElementTypeOfIterable. var forOfStatement = declaration.parent.parent; return checkRightHandSideOfForOf(forOfStatement.expression, forOfStatement.awaitModifier) || anyType; } @@ -28670,34 +33194,43 @@ var ts; } var isOptional = includeOptionality && (ts.isParameter(declaration) && isJSDocOptionalParameter(declaration) || !ts.isBindingElement(declaration) && !ts.isVariableDeclaration(declaration) && !!declaration.questionToken); + // Use type from type annotation if one is present var declaredType = tryGetTypeFromEffectiveTypeNode(declaration); if (declaredType) { return addOptionality(declaredType, isOptional); } if ((noImplicitAny || ts.isInJavaScriptFile(declaration)) && - declaration.kind === 232 && !ts.isBindingPattern(declaration.name) && - !(ts.getCombinedModifierFlags(declaration) & 1) && !(declaration.flags & 4194304)) { - if (!(ts.getCombinedNodeFlags(declaration) & 2) && (!declaration.initializer || isNullOrUndefined(declaration.initializer))) { + declaration.kind === 232 /* VariableDeclaration */ && !ts.isBindingPattern(declaration.name) && + !(ts.getCombinedModifierFlags(declaration) & 1 /* Export */) && !(declaration.flags & 4194304 /* Ambient */)) { + // If --noImplicitAny is on or the declaration is in a Javascript file, + // use control flow tracked 'any' type for non-ambient, non-exported var or let variables with no + // initializer or a 'null' or 'undefined' initializer. + if (!(ts.getCombinedNodeFlags(declaration) & 2 /* Const */) && (!declaration.initializer || isNullOrUndefined(declaration.initializer))) { return autoType; } + // Use control flow tracked 'any[]' type for non-ambient, non-exported variables with an empty array + // literal initializer. if (declaration.initializer && isEmptyArrayLiteral(declaration.initializer)) { return autoArrayType; } } - if (declaration.kind === 149) { + if (declaration.kind === 149 /* Parameter */) { var func = declaration.parent; - if (func.kind === 157 && !hasNonBindableDynamicName(func)) { - var getter = ts.getDeclarationOfKind(getSymbolOfNode(declaration.parent), 156); + // For a parameter of a set accessor, use the type of the get accessor if one is present + if (func.kind === 157 /* SetAccessor */ && !hasNonBindableDynamicName(func)) { + var getter = ts.getDeclarationOfKind(getSymbolOfNode(declaration.parent), 156 /* GetAccessor */); if (getter) { var getterSignature = getSignatureFromDeclaration(getter); var thisParameter = getAccessorThisParameter(func); if (thisParameter && declaration === thisParameter) { + // Use the type from the *getter* ts.Debug.assert(!thisParameter.type); return getTypeOfSymbol(getterSignature.thisParameter); } return getReturnTypeOfSignature(getterSignature); } } + // Use contextual parameter type if one is available var type = void 0; if (declaration.symbol.escapedName === "this") { type = getContextualThisParameterType(func); @@ -28709,19 +33242,25 @@ var ts; return addOptionality(type, isOptional); } } + // Use the type of the initializer expression if one is present if (declaration.initializer) { var type = checkDeclarationInitializer(declaration); return addOptionality(type, isOptional); } if (ts.isJsxAttribute(declaration)) { + // if JSX attribute doesn't have initializer, by default the attribute will have boolean value of true. + // I.e is sugar for return trueType; } + // If the declaration specifies a binding pattern, use the type implied by the binding pattern if (ts.isBindingPattern(declaration.name)) { - return getTypeFromBindingPattern(declaration.name, false, true); + return getTypeFromBindingPattern(declaration.name, /*includePatternInType*/ false, /*reportErrors*/ true); } + // No type specified and nothing can be inferred return undefined; } function getWidenedTypeFromJSSpecialPropertyDeclarations(symbol) { + // function/class/{} assignments are fresh declarations, not property assignments, so only add prototype assignments var specialDeclaration = ts.getAssignedJavascriptInitializer(symbol.valueDeclaration); if (specialDeclaration) { return getWidenedLiteralType(checkExpressionCached(specialDeclaration)); @@ -28733,18 +33272,20 @@ var ts; var jsDocType; var _loop_4 = function (declaration) { var declarationInConstructor = false; - var expression = declaration.kind === 200 ? declaration : - declaration.kind === 185 ? ts.cast(declaration.parent, ts.isBinaryExpression) : + var expression = declaration.kind === 200 /* BinaryExpression */ ? declaration : + declaration.kind === 185 /* PropertyAccessExpression */ ? ts.cast(declaration.parent, ts.isBinaryExpression) : undefined; if (!expression) { return { value: errorType }; } var special = ts.getSpecialPropertyAssignmentKind(expression); - if (special === 4) { - var thisContainer = ts.getThisContainer(expression, false); - declarationInConstructor = thisContainer.kind === 155 || - thisContainer.kind === 234 || - (thisContainer.kind === 192 && !ts.isPrototypePropertyAssignment(thisContainer.parent)); + if (special === 4 /* ThisProperty */) { + var thisContainer = ts.getThisContainer(expression, /*includeArrowFunctions*/ false); + // Properties defined in a constructor (or base constructor, or javascript constructor function) don't get undefined added. + // Function expressions that are assigned to the prototype count as methods. + declarationInConstructor = thisContainer.kind === 155 /* Constructor */ || + thisContainer.kind === 234 /* FunctionDeclaration */ || + (thisContainer.kind === 192 /* FunctionExpression */ && !ts.isPrototypePropertyAssignment(thisContainer.parent)); if (declarationInConstructor) { definedInConstructor = true; } @@ -28752,6 +33293,7 @@ var ts; definedInMethod = true; } } + // If there is a JSDoc type, use it var type_1 = getTypeForDeclarationFromJSDocComment(expression.parent); if (type_1) { var declarationType = getWidenedType(type_1); @@ -28760,15 +33302,16 @@ var ts; } else if (jsDocType !== errorType && declarationType !== errorType && !isTypeIdenticalTo(jsDocType, declarationType) && - !(symbol.flags & 67108864)) { + !(symbol.flags & 67108864 /* JSContainer */)) { errorNextVariableOrPropertyDeclarationMustHaveSameType(jsDocType, declaration, declarationType); } } else if (!jsDocType) { + // If we don't have an explicit JSDoc type, get the type from the expression. var type_2 = getWidenedLiteralType(checkExpressionCached(expression.right)); - if (ts.getObjectFlags(type_2) & 16 && - special === 2 && - symbol.escapedName === "export=") { + if (ts.getObjectFlags(type_2) & 16 /* Anonymous */ && + special === 2 /* ModuleExports */ && + symbol.escapedName === "export=" /* ExportEquals */) { var exportedType_1 = resolveStructuredTypeMembers(type_2); var members_3 = ts.createSymbolTable(); ts.copyEntries(exportedType_1.members, members_3); @@ -28806,6 +33349,7 @@ var ts; } var type = jsDocType; if (!type) { + // use only the constructor types unless they were only assigned null | undefined (including widening variants) if (definedInMethod) { var propType = getTypeOfSpecialPropertyOfBaseType(symbol); if (propType) { @@ -28813,11 +33357,11 @@ var ts; definedInConstructor = true; } } - var sourceTypes = ts.some(constructorTypes, function (t) { return !!(t.flags & ~(24576 | 134217728)); }) ? constructorTypes : types; - type = getUnionType(sourceTypes, 2); + var sourceTypes = ts.some(constructorTypes, function (t) { return !!(t.flags & ~(24576 /* Nullable */ | 134217728 /* ContainsWideningType */)); }) ? constructorTypes : types; // TODO: GH#18217 + type = getUnionType(sourceTypes, 2 /* Subtype */); } var widened = getWidenedType(addOptionality(type, definedInMethod && !definedInConstructor)); - if (filterType(widened, function (t) { return !!(t.flags & ~24576); }) === neverType) { + if (filterType(widened, function (t) { return !!(t.flags & ~24576 /* Nullable */); }) === neverType) { if (noImplicitAny) { reportImplicitAnyError(symbol.valueDeclaration, anyType); } @@ -28825,9 +33369,10 @@ var ts; } return widened; } + /** check for definition in base class if any declaration is in a class */ function getTypeOfSpecialPropertyOfBaseType(specialProperty) { var parentDeclaration = ts.forEach(specialProperty.declarations, function (d) { - var parent = ts.getThisContainer(d, false).parent; + var parent = ts.getThisContainer(d, /*includeArrowFunctions*/ false).parent; return ts.isClassLike(parent) && parent; }); if (parentDeclaration) { @@ -28838,6 +33383,9 @@ var ts; } } } + // Return the type implied by a binding pattern element. This is the type of the initializer of the element if + // one is present. Otherwise, if the element is itself a binding pattern, it is the type implied by the binding + // pattern. Otherwise, it is the type any. function getTypeFromBindingElement(element, includePatternInType, reportErrors) { if (element.initializer) { return checkDeclarationInitializer(element); @@ -28850,41 +33398,45 @@ var ts; } return anyType; } + // Return the type implied by an object binding pattern function getTypeFromObjectBindingPattern(pattern, includePatternInType, reportErrors) { var members = ts.createSymbolTable(); var stringIndexInfo; - var objectFlags = 128; + var objectFlags = 128 /* ObjectLiteral */; ts.forEach(pattern.elements, function (e) { var name = e.propertyName || e.name; if (isComputedNonLiteralName(name)) { - objectFlags |= 512; + // do not include computed properties in the implied type + objectFlags |= 512 /* ObjectLiteralPatternWithComputedProperties */; return; } if (e.dotDotDotToken) { - stringIndexInfo = createIndexInfo(anyType, false); + stringIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false); return; } var text = ts.getTextOfPropertyName(name); - var flags = 4 | (e.initializer ? 16777216 : 0); + var flags = 4 /* Property */ | (e.initializer ? 16777216 /* Optional */ : 0); var symbol = createSymbol(flags, text); symbol.type = getTypeFromBindingElement(e, includePatternInType, reportErrors); symbol.bindingElement = e; members.set(symbol.escapedName, symbol); }); var result = createAnonymousType(undefined, members, ts.emptyArray, ts.emptyArray, stringIndexInfo, undefined); - result.flags |= 268435456; + result.flags |= 268435456 /* ContainsObjectLiteral */; result.objectFlags |= objectFlags; if (includePatternInType) { result.pattern = pattern; } return result; } + // Return the type implied by an array binding pattern function getTypeFromArrayBindingPattern(pattern, includePatternInType, reportErrors) { var elements = pattern.elements; var lastElement = ts.lastOrUndefined(elements); if (!lastElement || (!ts.isOmittedExpression(lastElement) && lastElement.dotDotDotToken)) { - return languageVersion >= 2 ? createIterableType(anyType) : anyArrayType; + return languageVersion >= 2 /* ES2015 */ ? createIterableType(anyType) : anyArrayType; } + // If the pattern has at least one element, and no rest element, then it should imply a tuple type. var elementTypes = ts.map(elements, function (e) { return ts.isOmittedExpression(e) ? anyType : getTypeFromBindingElement(e, includePatternInType, reportErrors); }); var result = createTupleType(elementTypes); if (includePatternInType) { @@ -28893,27 +33445,46 @@ var ts; } return result; } + // Return the type implied by a binding pattern. This is the type implied purely by the binding pattern itself + // and without regard to its context (i.e. without regard any type annotation or initializer associated with the + // declaration in which the binding pattern is contained). For example, the implied type of [x, y] is [any, any] + // and the implied type of { x, y: z = 1 } is { x: any; y: number; }. The type implied by a binding pattern is + // used as the contextual type of an initializer associated with the binding pattern. Also, for a destructuring + // parameter with no type annotation or initializer, the type implied by the binding pattern becomes the type of + // the parameter. function getTypeFromBindingPattern(pattern, includePatternInType, reportErrors) { if (includePatternInType === void 0) { includePatternInType = false; } if (reportErrors === void 0) { reportErrors = false; } - return pattern.kind === 180 + return pattern.kind === 180 /* ObjectBindingPattern */ ? getTypeFromObjectBindingPattern(pattern, includePatternInType, reportErrors) : getTypeFromArrayBindingPattern(pattern, includePatternInType, reportErrors); } + // Return the type associated with a variable, parameter, or property declaration. In the simple case this is the type + // specified in a type annotation or inferred from an initializer. However, in the case of a destructuring declaration it + // is a bit more involved. For example: + // + // var [x, s = ""] = [1, "one"]; + // + // Here, the array literal [1, "one"] is contextually typed by the type [any, string], which is the implied type of the + // binding pattern [x, s = ""]. Because the contextual type is a tuple type, the resulting type of [1, "one"] is the + // tuple type [number, string]. Thus, the type inferred for 'x' is number and the type inferred for 's' is string. function getWidenedTypeForVariableLikeDeclaration(declaration, reportErrors) { - return widenTypeForVariableLikeDeclaration(getTypeForVariableLikeDeclaration(declaration, true), declaration, reportErrors); + return widenTypeForVariableLikeDeclaration(getTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ true), declaration, reportErrors); } function widenTypeForVariableLikeDeclaration(type, declaration, reportErrors) { if (type) { if (reportErrors) { reportErrorsFromWidening(declaration, type); } - if (type.flags & 2048 && (ts.isBindingElement(declaration) || !declaration.type) && type.symbol !== getSymbolOfNode(declaration)) { + // always widen a 'unique symbol' type if the type was created for a different declaration. + if (type.flags & 2048 /* UniqueESSymbol */ && (ts.isBindingElement(declaration) || !declaration.type) && type.symbol !== getSymbolOfNode(declaration)) { type = esSymbolType; } return getWidenedType(type); } + // Rest parameters default to type any[], other parameters default to type any type = ts.isParameter(declaration) && declaration.dotDotDotToken ? anyArrayType : anyType; + // Report implicit any errors unless this is a private property within an ambient declaration if (reportErrors && noImplicitAny) { if (!declarationBelongsToPrivateAmbientMember(declaration)) { reportImplicitAnyError(declaration, type); @@ -28923,7 +33494,7 @@ var ts; } function declarationBelongsToPrivateAmbientMember(declaration) { var root = ts.getRootDeclaration(declaration); - var memberDeclaration = root.kind === 149 ? root.parent : root; + var memberDeclaration = root.kind === 149 /* Parameter */ ? root.parent : root; return isPrivateWithinAmbient(memberDeclaration); } function tryGetTypeFromEffectiveTypeNode(declaration) { @@ -28935,24 +33506,29 @@ var ts; function getTypeOfVariableOrParameterOrProperty(symbol) { var links = getSymbolLinks(symbol); if (!links.type) { - if (symbol.flags & 4194304) { + // Handle prototype property + if (symbol.flags & 4194304 /* Prototype */) { return links.type = getTypeOfPrototypeProperty(symbol); } + // CommonsJS require and module both have type any. if (symbol === requireSymbol || symbol === moduleSymbol) { return links.type = anyType; } + // Handle catch clause variables var declaration = symbol.valueDeclaration; if (ts.isCatchClauseVariableDeclarationOrBindingElement(declaration)) { return links.type = anyType; } + // Handle export default expressions if (ts.isSourceFile(declaration)) { var jsonSourceFile = ts.cast(declaration, ts.isJsonSourceFile); return links.type = jsonSourceFile.statements.length ? checkExpression(jsonSourceFile.statements[0].expression) : emptyObjectType; } - if (declaration.kind === 249) { + if (declaration.kind === 249 /* ExportAssignment */) { return links.type = checkExpression(declaration.expression); } - if (!pushTypeResolution(symbol, 0)) { + // Handle variable, parameter or property + if (!pushTypeResolution(symbol, 0 /* Type */)) { return errorType; } var type = getJSSpecialType(symbol, declaration); @@ -28964,7 +33540,8 @@ var ts; || ts.isFunctionDeclaration(declaration) || (ts.isMethodDeclaration(declaration) && !ts.isObjectLiteralMethod(declaration)) || ts.isMethodSignature(declaration)) { - if (symbol.flags & (16 | 8192 | 32 | 384 | 512)) { + // Symbol is property of some kind that is merged with something - should use `getTypeOfFuncClassEnumModule` and not `getTypeOfVariableOrParameterOrProperty` + if (symbol.flags & (16 /* Function */ | 8192 /* Method */ | 32 /* Class */ | 384 /* Enum */ | 512 /* ValueModule */)) { return getTypeOfFuncClassEnumModule(symbol); } type = tryGetTypeFromEffectiveTypeNode(declaration) || anyType; @@ -28976,17 +33553,17 @@ var ts; type = tryGetTypeFromEffectiveTypeNode(declaration) || checkJsxAttribute(declaration); } else if (ts.isShorthandPropertyAssignment(declaration)) { - type = tryGetTypeFromEffectiveTypeNode(declaration) || checkExpressionForMutableLocation(declaration.name, 0); + type = tryGetTypeFromEffectiveTypeNode(declaration) || checkExpressionForMutableLocation(declaration.name, 0 /* Normal */); } else if (ts.isObjectLiteralMethod(declaration)) { - type = tryGetTypeFromEffectiveTypeNode(declaration) || checkObjectLiteralMethod(declaration, 0); + type = tryGetTypeFromEffectiveTypeNode(declaration) || checkObjectLiteralMethod(declaration, 0 /* Normal */); } else if (ts.isParameter(declaration) || ts.isPropertyDeclaration(declaration) || ts.isPropertySignature(declaration) || ts.isVariableDeclaration(declaration) || ts.isBindingElement(declaration)) { - type = getWidenedTypeForVariableLikeDeclaration(declaration, true); + type = getWidenedTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ true); } else { return ts.Debug.fail("Unhandled declaration kind! " + ts.Debug.showSyntaxKind(declaration) + " for " + ts.Debug.showSymbol(symbol)); @@ -29006,6 +33583,11 @@ var ts; else if (ts.isJSDocPropertyLikeTag(decl) && decl.typeExpression) { return getTypeFromTypeNode(decl.typeExpression.type); } + // Handle certain special assignment kinds, which happen to union across multiple declarations: + // * module.exports = expr + // * exports.p = expr + // * this.p = expr + // * className.prototype.method = expr else if (ts.isBinaryExpression(decl) || ts.isPropertyAccessExpression(decl) && ts.isBinaryExpression(decl.parent)) { return getJSInitializerType(decl, symbol, ts.getAssignedJavascriptInitializer(ts.isBinaryExpression(decl) ? decl.left : decl)) || @@ -29016,12 +33598,13 @@ var ts; || ts.isPropertySignature(decl) || ts.isVariableDeclaration(decl) || ts.isBindingElement(decl)) { + // Use type from type annotation if one is present var isOptional = ts.isParameter(decl) && isJSDocOptionalParameter(decl) || !ts.isBindingElement(decl) && !ts.isVariableDeclaration(decl) && !!decl.questionToken; var declaredType = tryGetTypeFromEffectiveTypeNode(decl); return declaredType && addOptionality(declaredType, isOptional) || getJSInitializerType(decl, symbol, ts.getDeclaredJavascriptInitializer(decl)) || - getWidenedTypeForVariableLikeDeclaration(decl, true); + getWidenedTypeForVariableLikeDeclaration(decl, /*includeOptionality*/ true); } } function getJSInitializerType(decl, symbol, init) { @@ -29043,7 +33626,7 @@ var ts; } function getAnnotatedAccessorType(accessor) { if (accessor) { - if (accessor.kind === 156) { + if (accessor.kind === 156 /* GetAccessor */) { var getterTypeAnnotation = ts.getEffectiveReturnTypeNode(accessor); return getterTypeAnnotation && getTypeFromTypeNode(getterTypeAnnotation); } @@ -29064,31 +33647,35 @@ var ts; function getTypeOfAccessors(symbol) { var links = getSymbolLinks(symbol); if (!links.type) { - var getter = ts.getDeclarationOfKind(symbol, 156); - var setter = ts.getDeclarationOfKind(symbol, 157); + var getter = ts.getDeclarationOfKind(symbol, 156 /* GetAccessor */); + var setter = ts.getDeclarationOfKind(symbol, 157 /* SetAccessor */); if (getter && ts.isInJavaScriptFile(getter)) { var jsDocType = getTypeForDeclarationFromJSDocComment(getter); if (jsDocType) { return links.type = jsDocType; } } - if (!pushTypeResolution(symbol, 0)) { + if (!pushTypeResolution(symbol, 0 /* Type */)) { return errorType; } var type = void 0; + // First try to see if the user specified a return type on the get-accessor. var getterReturnType = getAnnotatedAccessorType(getter); if (getterReturnType) { type = getterReturnType; } else { + // If the user didn't specify a return type, try to use the set-accessor's parameter type. var setterParameterType = getAnnotatedAccessorType(setter); if (setterParameterType) { type = setterParameterType; } else { + // If there are no specified types, try to infer it from the body of the get accessor if it exists. if (getter && getter.body) { type = getReturnTypeFromBody(getter); } + // Otherwise, fall back to 'any'. else { if (noImplicitAny) { if (setter) { @@ -29106,7 +33693,7 @@ var ts; if (!popTypeResolution()) { type = anyType; if (noImplicitAny) { - var getter_1 = ts.getDeclarationOfKind(symbol, 156); + var getter_1 = ts.getDeclarationOfKind(symbol, 156 /* GetAccessor */); error(getter_1, ts.Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol)); } } @@ -29116,7 +33703,7 @@ var ts; } function getBaseTypeVariableOfClass(symbol) { var baseConstructorType = getBaseConstructorTypeOfClass(getDeclaredTypeOfClassOrInterface(symbol)); - return baseConstructorType.flags & 2162688 ? baseConstructorType : undefined; + return baseConstructorType.flags & 2162688 /* TypeVariable */ ? baseConstructorType : undefined; } function getTypeOfFuncClassEnumModule(symbol) { var links = getSymbolLinks(symbol); @@ -29126,6 +33713,7 @@ var ts; var jsSymbol = getSymbolOfNode(jsDeclaration); if (jsSymbol && (ts.hasEntries(jsSymbol.exports) || ts.hasEntries(jsSymbol.members))) { symbol = cloneSymbol(symbol); + // note:we overwrite links because we just cloned the symbol links = symbol; if (ts.hasEntries(jsSymbol.exports)) { symbol.exports = symbol.exports || ts.createSymbolTable(); @@ -29137,21 +33725,21 @@ var ts; } } } - if (symbol.flags & 1536 && ts.isShorthandAmbientModuleSymbol(symbol)) { + if (symbol.flags & 1536 /* Module */ && ts.isShorthandAmbientModuleSymbol(symbol)) { links.type = anyType; } - else if (symbol.valueDeclaration.kind === 200 || - symbol.valueDeclaration.kind === 185 && symbol.valueDeclaration.parent.kind === 200) { + else if (symbol.valueDeclaration.kind === 200 /* BinaryExpression */ || + symbol.valueDeclaration.kind === 185 /* PropertyAccessExpression */ && symbol.valueDeclaration.parent.kind === 200 /* BinaryExpression */) { links.type = getWidenedTypeFromJSSpecialPropertyDeclarations(symbol); } else { - var type = createObjectType(16, symbol); - if (symbol.flags & 32) { + var type = createObjectType(16 /* Anonymous */, symbol); + if (symbol.flags & 32 /* Class */) { var baseTypeVariable = getBaseTypeVariableOfClass(symbol); links.type = baseTypeVariable ? getIntersectionType([type, baseTypeVariable]) : type; } else { - links.type = strictNullChecks && symbol.flags & 16777216 ? getOptionalType(type) : type; + links.type = strictNullChecks && symbol.flags & 16777216 /* Optional */ ? getOptionalType(type) : type; } } } @@ -29168,7 +33756,12 @@ var ts; var links = getSymbolLinks(symbol); if (!links.type) { var targetSymbol = resolveAlias(symbol); - links.type = targetSymbol.flags & 67216319 + // It only makes sense to get the type of a value symbol. If the result of resolving + // the alias is not a value, then it has no type. To get the type associated with a + // type symbol, call getDeclaredTypeOfSymbol. + // This check is important because without it, a call to getTypeOfSymbol could end + // up recursively calling getTypeOfAlias, causing a stack overflow. + links.type = targetSymbol.flags & 67216319 /* Value */ ? getTypeOfSymbol(targetSymbol) : errorType; } @@ -29182,7 +33775,7 @@ var ts; links.type = errorType; } else { - if (!pushTypeResolution(symbol, 0)) { + if (!pushTypeResolution(symbol, 0 /* Type */)) { return errorType; } symbolInstantiationDepth++; @@ -29197,35 +33790,37 @@ var ts; return links.type; } function reportCircularityError(symbol) { + // Check if variable has type annotation that circularly references the variable itself if (ts.getEffectiveTypeAnnotationNode(symbol.valueDeclaration)) { error(symbol.valueDeclaration, ts.Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol)); return errorType; } + // Otherwise variable has initializer that circularly references the variable itself if (noImplicitAny) { error(symbol.valueDeclaration, ts.Diagnostics._0_implicitly_has_type_any_because_it_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer, symbolToString(symbol)); } return anyType; } function getTypeOfSymbol(symbol) { - if (ts.getCheckFlags(symbol) & 1) { + if (ts.getCheckFlags(symbol) & 1 /* Instantiated */) { return getTypeOfInstantiatedSymbol(symbol); } - if (ts.getCheckFlags(symbol) & 2048) { + if (ts.getCheckFlags(symbol) & 2048 /* ReverseMapped */) { return getTypeOfReverseMappedSymbol(symbol); } - if (symbol.flags & (3 | 4)) { + if (symbol.flags & (3 /* Variable */ | 4 /* Property */)) { return getTypeOfVariableOrParameterOrProperty(symbol); } - if (symbol.flags & (16 | 8192 | 32 | 384 | 512)) { + if (symbol.flags & (16 /* Function */ | 8192 /* Method */ | 32 /* Class */ | 384 /* Enum */ | 512 /* ValueModule */)) { return getTypeOfFuncClassEnumModule(symbol); } - if (symbol.flags & 8) { + if (symbol.flags & 8 /* EnumMember */) { return getTypeOfEnumMember(symbol); } - if (symbol.flags & 98304) { + if (symbol.flags & 98304 /* Accessor */) { return getTypeOfAccessors(symbol); } - if (symbol.flags & 2097152) { + if (symbol.flags & 2097152 /* Alias */) { return getTypeOfAlias(symbol); } return errorType; @@ -29233,25 +33828,29 @@ var ts; function isReferenceToType(type, target) { return type !== undefined && target !== undefined - && (ts.getObjectFlags(type) & 4) !== 0 + && (ts.getObjectFlags(type) & 4 /* Reference */) !== 0 && type.target === target; } function getTargetType(type) { - return ts.getObjectFlags(type) & 4 ? type.target : type; + return ts.getObjectFlags(type) & 4 /* Reference */ ? type.target : type; } + // TODO: GH#18217 If `checkBase` is undefined, we should not call this because this will always return false. function hasBaseType(type, checkBase) { return check(type); function check(type) { - if (ts.getObjectFlags(type) & (3 | 4)) { + if (ts.getObjectFlags(type) & (3 /* ClassOrInterface */ | 4 /* Reference */)) { var target = getTargetType(type); return target === checkBase || ts.some(getBaseTypes(target), check); } - else if (type.flags & 524288) { + else if (type.flags & 524288 /* Intersection */) { return ts.some(type.types, check); } return false; } } + // Appends the type parameters given by a list of declarations to a set of type parameters and returns the resulting set. + // The function allocates a new array if the input type parameter set is undefined, but otherwise it modifies the set + // in-place and returns the same array. function appendTypeParameters(typeParameters, declarations) { for (var _i = 0, declarations_2 = declarations; _i < declarations_2.length; _i++) { var declaration = declarations_2[_i]; @@ -29259,58 +33858,62 @@ var ts; } return typeParameters; } + // Return the outer type parameters of a node or undefined if the node has no outer type parameters. function getOuterTypeParameters(node, includeThisTypes) { while (true) { - node = node.parent; + node = node.parent; // TODO: GH#18217 Use SourceFile kind check instead if (!node) { return undefined; } switch (node.kind) { - case 235: - case 205: - case 236: - case 158: - case 159: - case 153: - case 163: - case 164: - case 284: - case 234: - case 154: - case 192: - case 193: - case 237: - case 297: - case 298: - case 292: - case 177: - case 171: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 236 /* InterfaceDeclaration */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 153 /* MethodSignature */: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 284 /* JSDocFunctionType */: + case 234 /* FunctionDeclaration */: + case 154 /* MethodDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 237 /* TypeAliasDeclaration */: + case 297 /* JSDocTemplateTag */: + case 298 /* JSDocTypedefTag */: + case 292 /* JSDocCallbackTag */: + case 177 /* MappedType */: + case 171 /* ConditionalType */: var outerTypeParameters = getOuterTypeParameters(node, includeThisTypes); - if (node.kind === 177) { + if (node.kind === 177 /* MappedType */) { return ts.append(outerTypeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode(node.typeParameter))); } - else if (node.kind === 171) { + else if (node.kind === 171 /* ConditionalType */) { return ts.concatenate(outerTypeParameters, getInferTypeParameters(node)); } var outerAndOwnTypeParameters = appendTypeParameters(outerTypeParameters, ts.getEffectiveTypeParameterDeclarations(node)); var thisType = includeThisTypes && - (node.kind === 235 || node.kind === 205 || node.kind === 236) && + (node.kind === 235 /* ClassDeclaration */ || node.kind === 205 /* ClassExpression */ || node.kind === 236 /* InterfaceDeclaration */) && getDeclaredTypeOfClassOrInterface(getSymbolOfNode(node)).thisType; return thisType ? ts.append(outerAndOwnTypeParameters, thisType) : outerAndOwnTypeParameters; } } } + // The outer type parameters are those defined by enclosing generic classes, methods, or functions. function getOuterTypeParametersOfClassOrInterface(symbol) { - var declaration = symbol.flags & 32 ? symbol.valueDeclaration : ts.getDeclarationOfKind(symbol, 236); + var declaration = symbol.flags & 32 /* Class */ ? symbol.valueDeclaration : ts.getDeclarationOfKind(symbol, 236 /* InterfaceDeclaration */); return getOuterTypeParameters(declaration); } + // The local type parameters are the combined set of type parameters from all declarations of the class, + // interface, or type alias. function getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) { var result; for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var node = _a[_i]; - if (node.kind === 236 || - node.kind === 235 || - node.kind === 205 || + if (node.kind === 236 /* InterfaceDeclaration */ || + node.kind === 235 /* ClassDeclaration */ || + node.kind === 205 /* ClassExpression */ || ts.isTypeAlias(node)) { var declaration = node; result = appendTypeParameters(result, ts.getEffectiveTypeParameterDeclarations(declaration)); @@ -29318,11 +33921,15 @@ var ts; } return result; } + // The full set of type parameters for a generic class or interface type consists of its outer type parameters plus + // its locally declared type parameters. function getTypeParametersOfClassOrInterface(symbol) { return ts.concatenate(getOuterTypeParametersOfClassOrInterface(symbol), getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol)); } + // A type is a mixin constructor if it has a single construct signature taking no type parameters and a single + // rest parameter of type any[]. function isMixinConstructorType(type) { - var signatures = getSignaturesOfType(type, 1); + var signatures = getSignaturesOfType(type, 1 /* Construct */); if (signatures.length === 1) { var s = signatures[0]; return !s.typeParameters && s.parameters.length === 1 && s.hasRestParameter && getTypeOfParameter(s.parameters[0]) === anyArrayType; @@ -29330,10 +33937,10 @@ var ts; return false; } function isConstructorType(type) { - if (isValidBaseType(type) && getSignaturesOfType(type, 1).length > 0) { + if (isValidBaseType(type) && getSignaturesOfType(type, 1 /* Construct */).length > 0) { return true; } - if (type.flags & 2162688) { + if (type.flags & 2162688 /* TypeVariable */) { var constraint = getBaseConstraintOfType(type); return !!constraint && isValidBaseType(constraint) && isMixinConstructorType(constraint); } @@ -29342,6 +33949,7 @@ var ts; function getBaseTypeNodeOfClass(type) { var decl = type.symbol.valueDeclaration; if (ts.isInJavaScriptFile(decl)) { + // Prefer an @augments tag because it may have type parameters. var tag = ts.getJSDocAugmentsTag(decl); if (tag) { return tag.class; @@ -29352,13 +33960,21 @@ var ts; function getConstructorsForTypeArguments(type, typeArgumentNodes, location) { var typeArgCount = ts.length(typeArgumentNodes); var isJavaScript = ts.isInJavaScriptFile(location); - return ts.filter(getSignaturesOfType(type, 1), function (sig) { return (isJavaScript || typeArgCount >= getMinTypeArgumentCount(sig.typeParameters)) && typeArgCount <= ts.length(sig.typeParameters); }); + return ts.filter(getSignaturesOfType(type, 1 /* Construct */), function (sig) { return (isJavaScript || typeArgCount >= getMinTypeArgumentCount(sig.typeParameters)) && typeArgCount <= ts.length(sig.typeParameters); }); } function getInstantiatedConstructorsForTypeArguments(type, typeArgumentNodes, location) { var signatures = getConstructorsForTypeArguments(type, typeArgumentNodes, location); var typeArguments = ts.map(typeArgumentNodes, getTypeFromTypeNode); return ts.sameMap(signatures, function (sig) { return ts.some(sig.typeParameters) ? getSignatureInstantiation(sig, typeArguments, ts.isInJavaScriptFile(location)) : sig; }); } + /** + * The base constructor of a class can resolve to + * * undefinedType if the class has no extends clause, + * * unknownType if an error occurred during resolution of the extends expression, + * * nullType if the extends expression is the null value, + * * anyType if the extends expression has type any, or + * * an object type with at least one construct signature. + */ function getBaseConstructorTypeOfClass(type) { if (!type.resolvedBaseConstructorType) { var decl = type.symbol.valueDeclaration; @@ -29367,22 +33983,24 @@ var ts; if (!baseTypeNode) { return type.resolvedBaseConstructorType = undefinedType; } - if (!pushTypeResolution(type, 1)) { + if (!pushTypeResolution(type, 1 /* ResolvedBaseConstructorType */)) { return errorType; } var baseConstructorType = checkExpression(baseTypeNode.expression); if (extended && baseTypeNode !== extended) { - ts.Debug.assert(!extended.typeArguments); + ts.Debug.assert(!extended.typeArguments); // Because this is in a JS file, and baseTypeNode is in an @extends tag checkExpression(extended.expression); } - if (baseConstructorType.flags & (131072 | 524288)) { + if (baseConstructorType.flags & (131072 /* Object */ | 524288 /* Intersection */)) { + // Resolving the members of a class requires us to resolve the base class of that class. + // We force resolution here such that we catch circularities now. resolveStructuredTypeMembers(baseConstructorType); } if (!popTypeResolution()) { error(type.symbol.valueDeclaration, ts.Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol)); return type.resolvedBaseConstructorType = errorType; } - if (!(baseConstructorType.flags & 1) && baseConstructorType !== nullWideningType && !isConstructorType(baseConstructorType)) { + if (!(baseConstructorType.flags & 1 /* Any */) && baseConstructorType !== nullWideningType && !isConstructorType(baseConstructorType)) { error(baseTypeNode.expression, ts.Diagnostics.Type_0_is_not_a_constructor_function_type, typeToString(baseConstructorType)); return type.resolvedBaseConstructorType = errorType; } @@ -29392,14 +34010,14 @@ var ts; } function getBaseTypes(type) { if (!type.resolvedBaseTypes) { - if (type.objectFlags & 8) { + if (type.objectFlags & 8 /* Tuple */) { type.resolvedBaseTypes = [createArrayType(getUnionType(type.typeParameters))]; } - else if (type.symbol.flags & (32 | 64)) { - if (type.symbol.flags & 32) { + else if (type.symbol.flags & (32 /* Class */ | 64 /* Interface */)) { + if (type.symbol.flags & 32 /* Class */) { resolveBaseTypesOfClass(type); } - if (type.symbol.flags & 64) { + if (type.symbol.flags & 64 /* Interface */) { resolveBaseTypesOfInterface(type); } } @@ -29412,21 +34030,27 @@ var ts; function resolveBaseTypesOfClass(type) { type.resolvedBaseTypes = ts.resolvingEmptyArray; var baseConstructorType = getApparentType(getBaseConstructorTypeOfClass(type)); - if (!(baseConstructorType.flags & (131072 | 524288 | 1))) { + if (!(baseConstructorType.flags & (131072 /* Object */ | 524288 /* Intersection */ | 1 /* Any */))) { return type.resolvedBaseTypes = ts.emptyArray; } var baseTypeNode = getBaseTypeNodeOfClass(type); var typeArgs = typeArgumentsFromTypeReferenceNode(baseTypeNode); var baseType; var originalBaseType = baseConstructorType && baseConstructorType.symbol ? getDeclaredTypeOfSymbol(baseConstructorType.symbol) : undefined; - if (baseConstructorType.symbol && baseConstructorType.symbol.flags & 32 && + if (baseConstructorType.symbol && baseConstructorType.symbol.flags & 32 /* Class */ && areAllOuterTypeParametersApplied(originalBaseType)) { + // When base constructor type is a class with no captured type arguments we know that the constructors all have the same type parameters as the + // class and all return the instance type of the class. There is no need for further checks and we can apply the + // type arguments in the same manner as a type reference to get the same error reporting experience. baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseConstructorType.symbol, typeArgs); } - else if (baseConstructorType.flags & 1) { + else if (baseConstructorType.flags & 1 /* Any */) { baseType = baseConstructorType; } else { + // The class derives from a "class-like" constructor function, check that we have at least one construct signature + // with a matching number of type parameters and use the return type of the first instantiated signature. Elsewhere + // we check that all instantiated signatures return the same type. var constructors = getInstantiatedConstructorsForTypeArguments(baseConstructorType, baseTypeNode.typeArguments, baseTypeNode); if (!constructors.length) { error(baseTypeNode.expression, ts.Diagnostics.No_base_constructor_has_the_specified_number_of_type_arguments); @@ -29442,15 +34066,21 @@ var ts; return type.resolvedBaseTypes = ts.emptyArray; } if (type === baseType || hasBaseType(baseType, type)) { - error(type.symbol.valueDeclaration, ts.Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, undefined, 2)); + error(type.symbol.valueDeclaration, ts.Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, 2 /* WriteArrayAsGenericType */)); return type.resolvedBaseTypes = ts.emptyArray; } if (type.resolvedBaseTypes === ts.resolvingEmptyArray) { - type.members = undefined; + // Circular reference, likely through instantiation of default parameters + // (otherwise there'd be an error from hasBaseType) - this is fine, but `.members` should be reset + // as `getIndexedAccessType` via `instantiateType` via `getTypeFromClassOrInterfaceReference` forces a + // partial instantiation of the members without the base types fully resolved + type.members = undefined; // TODO: GH#18217 } return type.resolvedBaseTypes = [baseType]; } function areAllOuterTypeParametersApplied(type) { + // An unapplied type parameter has its symbol still the same as the matching argument symbol. + // Since parameters are applied outer-to-inner, only the last outer parameter needs to be checked. var outerTypeParameters = type.outerTypeParameters; if (outerTypeParameters) { var last_1 = outerTypeParameters.length - 1; @@ -29459,15 +34089,17 @@ var ts; } return true; } + // A valid base type is `any`, any non-generic object type or intersection of non-generic + // object types. function isValidBaseType(type) { - return !!(type.flags & (131072 | 16777216 | 1)) && !isGenericMappedType(type) || - !!(type.flags & 524288) && ts.every(type.types, isValidBaseType); + return !!(type.flags & (131072 /* Object */ | 16777216 /* NonPrimitive */ | 1 /* Any */)) && !isGenericMappedType(type) || + !!(type.flags & 524288 /* Intersection */) && ts.every(type.types, isValidBaseType); } function resolveBaseTypesOfInterface(type) { type.resolvedBaseTypes = type.resolvedBaseTypes || ts.emptyArray; for (var _i = 0, _a = type.symbol.declarations; _i < _a.length; _i++) { var declaration = _a[_i]; - if (declaration.kind === 236 && ts.getInterfaceBaseTypeNodes(declaration)) { + if (declaration.kind === 236 /* InterfaceDeclaration */ && ts.getInterfaceBaseTypeNodes(declaration)) { for (var _b = 0, _c = ts.getInterfaceBaseTypeNodes(declaration); _b < _c.length; _b++) { var node = _c[_b]; var baseType = getTypeFromTypeNode(node); @@ -29482,7 +34114,7 @@ var ts; } } else { - error(declaration, ts.Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, undefined, 2)); + error(declaration, ts.Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, 2 /* WriteArrayAsGenericType */)); } } else { @@ -29493,11 +34125,18 @@ var ts; } } } + /** + * Returns true if the interface given by the symbol is free of "this" references. + * + * Specifically, the result is true if the interface itself contains no references + * to "this" in its body, if all base types are interfaces, + * and if none of the base interfaces have a "this" type. + */ function isThislessInterface(symbol) { for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var declaration = _a[_i]; - if (declaration.kind === 236) { - if (declaration.flags & 64) { + if (declaration.kind === 236 /* InterfaceDeclaration */) { + if (declaration.flags & 64 /* ContainsThis */) { return false; } var baseTypeNodes = ts.getInterfaceBaseTypeNodes(declaration); @@ -29505,8 +34144,8 @@ var ts; for (var _b = 0, baseTypeNodes_1 = baseTypeNodes; _b < baseTypeNodes_1.length; _b++) { var node = baseTypeNodes_1[_b]; if (ts.isEntityNameExpression(node.expression)) { - var baseSymbol = resolveEntityName(node.expression, 67901928, true); - if (!baseSymbol || !(baseSymbol.flags & 64) || getDeclaredTypeOfClassOrInterface(baseSymbol).thisType) { + var baseSymbol = resolveEntityName(node.expression, 67901928 /* Type */, /*ignoreErrors*/ true); + if (!baseSymbol || !(baseSymbol.flags & 64 /* Interface */) || getDeclaredTypeOfClassOrInterface(baseSymbol).thisType) { return false; } } @@ -29519,12 +34158,17 @@ var ts; function getDeclaredTypeOfClassOrInterface(symbol) { var links = getSymbolLinks(symbol); if (!links.declaredType) { - var kind = symbol.flags & 32 ? 1 : 2; + var kind = symbol.flags & 32 /* Class */ ? 1 /* Class */ : 2 /* Interface */; var type = links.declaredType = createObjectType(kind, symbol); var outerTypeParameters = getOuterTypeParametersOfClassOrInterface(symbol); var localTypeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol); - if (outerTypeParameters || localTypeParameters || kind === 1 || !isThislessInterface(symbol)) { - type.objectFlags |= 4; + // A class or interface is generic if it has type parameters or a "this" type. We always give classes a "this" type + // because it is not feasible to analyze all members to determine if the "this" type escapes the class (in particular, + // property types inferred from initializers and method return types inferred from return statements are very hard + // to exhaustively analyze). We give interfaces a "this" type if we can't definitely determine that they are free of + // "this" references. + if (outerTypeParameters || localTypeParameters || kind === 1 /* Class */ || !isThislessInterface(symbol)) { + type.objectFlags |= 4 /* Reference */; type.typeParameters = ts.concatenate(outerTypeParameters, localTypeParameters); type.outerTypeParameters = outerTypeParameters; type.localTypeParameters = localTypeParameters; @@ -29532,7 +34176,7 @@ var ts; type.instantiations.set(getTypeListId(type.typeParameters), type); type.target = type; type.typeArguments = type.typeParameters; - type.thisType = createType(65536); + type.thisType = createType(65536 /* TypeParameter */); type.thisType.isThisType = true; type.thisType.symbol = symbol; type.thisType.constraint = type; @@ -29543,17 +34187,22 @@ var ts; function getDeclaredTypeOfTypeAlias(symbol) { var links = getSymbolLinks(symbol); if (!links.declaredType) { - if (!pushTypeResolution(symbol, 2)) { + // Note that we use the links object as the target here because the symbol object is used as the unique + // identity for resolution of the 'type' property in SymbolLinks. + if (!pushTypeResolution(symbol, 2 /* DeclaredType */)) { return errorType; } var declaration = ts.find(symbol.declarations, function (d) { - return ts.isJSDocTypeAlias(d) || d.kind === 237; + return ts.isJSDocTypeAlias(d) || d.kind === 237 /* TypeAliasDeclaration */; }); var typeNode = ts.isJSDocTypeAlias(declaration) ? declaration.typeExpression : declaration.type; + // If typeNode is missing, we will error in checkJSDocTypedefTag. var type = typeNode ? getTypeFromTypeNode(typeNode) : errorType; if (popTypeResolution()) { var typeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol); if (typeParameters) { + // Initialize the instantiation cache for generic type aliases. The declared type corresponds to + // an instantiation of the type alias with the type parameters supplied as type arguments. links.typeParameters = typeParameters; links.instantiations = ts.createMap(); links.instantiations.set(getTypeListId(typeParameters), type); @@ -29568,10 +34217,10 @@ var ts; return links.declaredType; } function isStringConcatExpression(expr) { - if (expr.kind === 9) { + if (expr.kind === 9 /* StringLiteral */) { return true; } - else if (expr.kind === 200) { + else if (expr.kind === 200 /* BinaryExpression */) { return isStringConcatExpression(expr.left) && isStringConcatExpression(expr.right); } return false; @@ -29579,18 +34228,18 @@ var ts; function isLiteralEnumMember(member) { var expr = member.initializer; if (!expr) { - return !(member.flags & 4194304); + return !(member.flags & 4194304 /* Ambient */); } switch (expr.kind) { - case 9: - case 8: + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: return true; - case 198: - return expr.operator === 38 && - expr.operand.kind === 8; - case 71: + case 198 /* PrefixUnaryExpression */: + return expr.operator === 38 /* MinusToken */ && + expr.operand.kind === 8 /* NumericLiteral */; + case 71 /* Identifier */: return ts.nodeIsMissing(expr) || !!getSymbolOfNode(member.parent).exports.get(expr.escapedText); - case 200: + case 200 /* BinaryExpression */: return isStringConcatExpression(expr); default: return false; @@ -29604,11 +34253,11 @@ var ts; var hasNonLiteralMember = false; for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var declaration = _a[_i]; - if (declaration.kind === 238) { + if (declaration.kind === 238 /* EnumDeclaration */) { for (var _b = 0, _c = declaration.members; _b < _c.length; _b++) { var member = _c[_b]; - if (member.initializer && member.initializer.kind === 9) { - return links.enumKind = 1; + if (member.initializer && member.initializer.kind === 9 /* StringLiteral */) { + return links.enumKind = 1 /* Literal */; } if (!isLiteralEnumMember(member)) { hasNonLiteralMember = true; @@ -29616,40 +34265,40 @@ var ts; } } } - return links.enumKind = hasNonLiteralMember ? 0 : 1; + return links.enumKind = hasNonLiteralMember ? 0 /* Numeric */ : 1 /* Literal */; } function getBaseTypeOfEnumLiteralType(type) { - return type.flags & 512 && !(type.flags & 262144) ? getDeclaredTypeOfSymbol(getParentOfSymbol(type.symbol)) : type; + return type.flags & 512 /* EnumLiteral */ && !(type.flags & 262144 /* Union */) ? getDeclaredTypeOfSymbol(getParentOfSymbol(type.symbol)) : type; } function getDeclaredTypeOfEnum(symbol) { var links = getSymbolLinks(symbol); if (links.declaredType) { return links.declaredType; } - if (getEnumKind(symbol) === 1) { + if (getEnumKind(symbol) === 1 /* Literal */) { enumCount++; var memberTypeList = []; for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var declaration = _a[_i]; - if (declaration.kind === 238) { + if (declaration.kind === 238 /* EnumDeclaration */) { for (var _b = 0, _c = declaration.members; _b < _c.length; _b++) { var member = _c[_b]; - var memberType = getLiteralType(getEnumMemberValue(member), enumCount, getSymbolOfNode(member)); + var memberType = getLiteralType(getEnumMemberValue(member), enumCount, getSymbolOfNode(member)); // TODO: GH#18217 getSymbolLinks(getSymbolOfNode(member)).declaredType = memberType; memberTypeList.push(memberType); } } } if (memberTypeList.length) { - var enumType_1 = getUnionType(memberTypeList, 1, symbol, undefined); - if (enumType_1.flags & 262144) { - enumType_1.flags |= 512; + var enumType_1 = getUnionType(memberTypeList, 1 /* Literal */, symbol, /*aliasTypeArguments*/ undefined); + if (enumType_1.flags & 262144 /* Union */) { + enumType_1.flags |= 512 /* EnumLiteral */; enumType_1.symbol = symbol; } return links.declaredType = enumType_1; } } - var enumType = createType(32); + var enumType = createType(32 /* Enum */); enumType.symbol = symbol; return links.declaredType = enumType; } @@ -29666,7 +34315,7 @@ var ts; function getDeclaredTypeOfTypeParameter(symbol) { var links = getSymbolLinks(symbol); if (!links.declaredType) { - var type = createType(65536); + var type = createType(65536 /* TypeParameter */); type.symbol = symbol; links.declaredType = type; } @@ -29683,79 +34332,103 @@ var ts; return tryGetDeclaredTypeOfSymbol(symbol) || errorType; } function tryGetDeclaredTypeOfSymbol(symbol) { - if (symbol.flags & (32 | 64)) { + if (symbol.flags & (32 /* Class */ | 64 /* Interface */)) { return getDeclaredTypeOfClassOrInterface(symbol); } - if (symbol.flags & 524288) { + if (symbol.flags & 524288 /* TypeAlias */) { return getDeclaredTypeOfTypeAlias(symbol); } - if (symbol.flags & 262144) { + if (symbol.flags & 262144 /* TypeParameter */) { return getDeclaredTypeOfTypeParameter(symbol); } - if (symbol.flags & 384) { + if (symbol.flags & 384 /* Enum */) { return getDeclaredTypeOfEnum(symbol); } - if (symbol.flags & 8) { + if (symbol.flags & 8 /* EnumMember */) { return getDeclaredTypeOfEnumMember(symbol); } - if (symbol.flags & 2097152) { + if (symbol.flags & 2097152 /* Alias */) { return getDeclaredTypeOfAlias(symbol); } return undefined; } + /** + * A type is free of this references if it's the any, string, number, boolean, symbol, or void keyword, a string + * literal type, an array with an element type that is free of this references, or a type reference that is + * free of this references. + */ function isThislessType(node) { switch (node.kind) { - case 119: - case 142: - case 137: - case 134: - case 122: - case 138: - case 135: - case 105: - case 140: - case 95: - case 131: - case 178: + case 119 /* AnyKeyword */: + case 142 /* UnknownKeyword */: + case 137 /* StringKeyword */: + case 134 /* NumberKeyword */: + case 122 /* BooleanKeyword */: + case 138 /* SymbolKeyword */: + case 135 /* ObjectKeyword */: + case 105 /* VoidKeyword */: + case 140 /* UndefinedKeyword */: + case 95 /* NullKeyword */: + case 131 /* NeverKeyword */: + case 178 /* LiteralType */: return true; - case 167: + case 167 /* ArrayType */: return isThislessType(node.elementType); - case 162: + case 162 /* TypeReference */: return !node.typeArguments || node.typeArguments.every(isThislessType); } return false; } + /** A type parameter is thisless if its contraint is thisless, or if it has no constraint. */ function isThislessTypeParameter(node) { return !node.constraint || isThislessType(node.constraint); } + /** + * A variable-like declaration is free of this references if it has a type annotation + * that is thisless, or if it has no type annotation and no initializer (and is thus of type any). + */ function isThislessVariableLikeDeclaration(node) { var typeNode = ts.getEffectiveTypeAnnotationNode(node); return typeNode ? isThislessType(typeNode) : !ts.hasInitializer(node); } + /** + * A function-like declaration is considered free of `this` references if it has a return type + * annotation that is free of this references and if each parameter is thisless and if + * each type parameter (if present) is thisless. + */ function isThislessFunctionLikeDeclaration(node) { var returnType = ts.getEffectiveReturnTypeNode(node); var typeParameters = ts.getEffectiveTypeParameterDeclarations(node); - return (node.kind === 155 || (!!returnType && isThislessType(returnType))) && + return (node.kind === 155 /* Constructor */ || (!!returnType && isThislessType(returnType))) && node.parameters.every(isThislessVariableLikeDeclaration) && typeParameters.every(isThislessTypeParameter); } + /** + * Returns true if the class or interface member given by the symbol is free of "this" references. The + * function may return false for symbols that are actually free of "this" references because it is not + * feasible to perform a complete analysis in all cases. In particular, property members with types + * inferred from their initializers and function members with inferred return types are conservatively + * assumed not to be free of "this" references. + */ function isThisless(symbol) { if (symbol.declarations && symbol.declarations.length === 1) { var declaration = symbol.declarations[0]; if (declaration) { switch (declaration.kind) { - case 152: - case 151: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: return isThislessVariableLikeDeclaration(declaration); - case 154: - case 153: - case 155: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: return isThislessFunctionLikeDeclaration(declaration); } } } return false; } + // The mappingThisOnly flag indicates that the only type parameter being mapped is "this". When the flag is true, + // we check symbols to see if we can quickly conclude they are free of "this" references, thus needing no instantiation. function createInstantiatedSymbolTable(symbols, mapper, mappingThisOnly) { var result = ts.createSymbolTable(); for (var _i = 0, symbols_2 = symbols; _i < symbols_2.length; _i++) { @@ -29777,44 +34450,73 @@ var ts; var symbol = type.symbol; var members = getMembersOfSymbol(symbol); type.declaredProperties = getNamedMembers(members); + // Start with signatures at empty array in case of recursive types type.declaredCallSignatures = ts.emptyArray; type.declaredConstructSignatures = ts.emptyArray; - type.declaredCallSignatures = getSignaturesOfSymbol(members.get("__call")); - type.declaredConstructSignatures = getSignaturesOfSymbol(members.get("__new")); - type.declaredStringIndexInfo = getIndexInfoOfSymbol(symbol, 0); - type.declaredNumberIndexInfo = getIndexInfoOfSymbol(symbol, 1); + type.declaredCallSignatures = getSignaturesOfSymbol(members.get("__call" /* Call */)); + type.declaredConstructSignatures = getSignaturesOfSymbol(members.get("__new" /* New */)); + type.declaredStringIndexInfo = getIndexInfoOfSymbol(symbol, 0 /* String */); + type.declaredNumberIndexInfo = getIndexInfoOfSymbol(symbol, 1 /* Number */); } return type; } + /** + * Indicates whether a type can be used as a late-bound name. + */ function isTypeUsableAsLateBoundName(type) { - return !!(type.flags & 2240); + return !!(type.flags & 2240 /* StringOrNumberLiteralOrUnique */); } + /** + * Indicates whether a declaration name is definitely late-bindable. + * A declaration name is only late-bindable if: + * - It is a `ComputedPropertyName`. + * - Its expression is an `Identifier` or either a `PropertyAccessExpression` an + * `ElementAccessExpression` consisting only of these same three types of nodes. + * - The type of its expression is a string or numeric literal type, or is a `unique symbol` type. + */ function isLateBindableName(node) { return ts.isComputedPropertyName(node) && ts.isEntityNameExpression(node.expression) && isTypeUsableAsLateBoundName(checkComputedPropertyName(node)); } + /** + * Indicates whether a declaration has a late-bindable dynamic name. + */ function hasLateBindableName(node) { var name = ts.getNameOfDeclaration(node); return !!name && isLateBindableName(name); } + /** + * Indicates whether a declaration has a dynamic name that cannot be late-bound. + */ function hasNonBindableDynamicName(node) { return ts.hasDynamicName(node) && !hasLateBindableName(node); } + /** + * Indicates whether a declaration name is a dynamic name that cannot be late-bound. + */ function isNonBindableDynamicName(node) { return ts.isDynamicName(node) && !isLateBindableName(node); } + /** + * Gets the symbolic name for a late-bound member from its type. + */ function getLateBoundNameFromType(type) { - if (type.flags & 2048) { + if (type.flags & 2048 /* UniqueESSymbol */) { return "__@" + type.symbol.escapedName + "@" + getSymbolId(type.symbol); } - if (type.flags & 192) { + if (type.flags & 192 /* StringOrNumberLiteral */) { return ts.escapeLeadingUnderscores("" + type.value); } return ts.Debug.fail(); } + /** + * Adds a declaration to a late-bound dynamic member. This performs the same function for + * late-bound members that `addDeclarationToSymbol` in binder.ts performs for early-bound + * members. + */ function addDeclarationToLateBoundSymbol(symbol, member, symbolFlags) { - ts.Debug.assert(!!(ts.getCheckFlags(symbol) & 1024), "Expected a late-bound symbol."); + ts.Debug.assert(!!(ts.getCheckFlags(symbol) & 1024 /* Late */), "Expected a late-bound symbol."); symbol.flags |= symbolFlags; getSymbolLinks(member.symbol).lateSymbol = symbol; if (!symbol.declarations) { @@ -29823,31 +34525,67 @@ var ts; else { symbol.declarations.push(member); } - if (symbolFlags & 67216319) { + if (symbolFlags & 67216319 /* Value */) { if (!symbol.valueDeclaration || symbol.valueDeclaration.kind !== member.kind) { symbol.valueDeclaration = member; } } } + /** + * Performs late-binding of a dynamic member. This performs the same function for + * late-bound members that `declareSymbol` in binder.ts performs for early-bound + * members. + * + * If a symbol is a dynamic name from a computed property, we perform an additional "late" + * binding phase to attempt to resolve the name for the symbol from the type of the computed + * property's expression. If the type of the expression is a string-literal, numeric-literal, + * or unique symbol type, we can use that type as the name of the symbol. + * + * For example, given: + * + * const x = Symbol(); + * + * interface I { + * [x]: number; + * } + * + * The binder gives the property `[x]: number` a special symbol with the name "__computed". + * In the late-binding phase we can type-check the expression `x` and see that it has a + * unique symbol type which we can then use as the name of the member. This allows users + * to define custom symbols that can be used in the members of an object type. + * + * @param parent The containing symbol for the member. + * @param earlySymbols The early-bound symbols of the parent. + * @param lateSymbols The late-bound symbols of the parent. + * @param decl The member to bind. + */ function lateBindMember(parent, earlySymbols, lateSymbols, decl) { ts.Debug.assert(!!decl.symbol, "The member is expected to have a symbol."); var links = getNodeLinks(decl); if (!links.resolvedSymbol) { + // In the event we attempt to resolve the late-bound name of this member recursively, + // fall back to the early-bound name of this member. links.resolvedSymbol = decl.symbol; var type = checkComputedPropertyName(decl.name); if (isTypeUsableAsLateBoundName(type)) { var memberName = getLateBoundNameFromType(type); var symbolFlags = decl.symbol.flags; + // Get or add a late-bound symbol for the member. This allows us to merge late-bound accessor declarations. var lateSymbol = lateSymbols.get(memberName); if (!lateSymbol) - lateSymbols.set(memberName, lateSymbol = createSymbol(0, memberName, 1024)); + lateSymbols.set(memberName, lateSymbol = createSymbol(0 /* None */, memberName, 1024 /* Late */)); + // Report an error if a late-bound member has the same name as an early-bound member, + // or if we have another early-bound symbol declaration with the same name and + // conflicting flags. var earlySymbol = earlySymbols && earlySymbols.get(memberName); if (lateSymbol.flags & getExcludedSymbolFlags(symbolFlags) || earlySymbol) { + // If we have an existing early-bound member, combine its declarations so that we can + // report an error at each declaration. var declarations = earlySymbol ? ts.concatenate(earlySymbol.declarations, lateSymbol.declarations) : lateSymbol.declarations; var name_2 = ts.declarationNameToString(decl.name); ts.forEach(declarations, function (declaration) { return error(ts.getNameOfDeclaration(declaration) || declaration, ts.Diagnostics.Duplicate_declaration_0, name_2); }); error(decl.name || decl, ts.Diagnostics.Duplicate_declaration_0, name_2); - lateSymbol = createSymbol(0, memberName, 1024); + lateSymbol = createSymbol(0 /* None */, memberName, 1024 /* Late */); } lateSymbol.nameType = type; addDeclarationToLateBoundSymbol(lateSymbol, decl, symbolFlags); @@ -29865,11 +34603,15 @@ var ts; function getResolvedMembersOrExportsOfSymbol(symbol, resolutionKind) { var links = getSymbolLinks(symbol); if (!links[resolutionKind]) { - var isStatic = resolutionKind === "resolvedExports"; + var isStatic = resolutionKind === "resolvedExports" /* resolvedExports */; var earlySymbols = !isStatic ? symbol.members : - symbol.flags & 1536 ? getExportsOfModuleWorker(symbol) : + symbol.flags & 1536 /* Module */ ? getExportsOfModuleWorker(symbol) : symbol.exports; + // In the event we recursively resolve the members/exports of the symbol, we + // set the initial value of resolvedMembers/resolvedExports to the early-bound + // members/exports of the symbol. links[resolutionKind] = earlySymbols || emptySymbols; + // fill in any as-yet-unresolved late-bound members. var lateSymbols = ts.createSymbolTable(); for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var decl = _a[_i]; @@ -29887,15 +34629,27 @@ var ts; } return links[resolutionKind]; } + /** + * Gets a SymbolTable containing both the early- and late-bound members of a symbol. + * + * For a description of late-binding, see `lateBindMember`. + */ function getMembersOfSymbol(symbol) { - return symbol.flags & 6240 - ? getResolvedMembersOrExportsOfSymbol(symbol, "resolvedMembers") + return symbol.flags & 6240 /* LateBindingContainer */ + ? getResolvedMembersOrExportsOfSymbol(symbol, "resolvedMembers" /* resolvedMembers */) : symbol.members || emptySymbols; } + /** + * If a symbol is the dynamic name of the member of an object type, get the late-bound + * symbol of the member. + * + * For a description of late-binding, see `lateBindMember`. + */ function getLateBoundSymbol(symbol) { - if (symbol.flags & 106500 && symbol.escapedName === "__computed") { + if (symbol.flags & 106500 /* ClassMember */ && symbol.escapedName === "__computed" /* Computed */) { var links = getSymbolLinks(symbol); if (!links.lateSymbol && ts.some(symbol.declarations, hasLateBindableName)) { + // force late binding of members/exports. This will set the late-bound symbol if (ts.some(symbol.declarations, ts.hasStaticModifier)) { getExportsOfSymbol(symbol.parent); } @@ -29908,7 +34662,7 @@ var ts; return symbol; } function getTypeWithThisArgument(type, thisArgument, needApparentType) { - if (ts.getObjectFlags(type) & 4) { + if (ts.getObjectFlags(type) & 4 /* Reference */) { var target = type.target; var typeArguments = type.typeArguments; if (ts.length(target.typeParameters) === ts.length(typeArguments)) { @@ -29916,7 +34670,7 @@ var ts; return needApparentType ? getApparentType(ref) : ref; } } - else if (type.flags & 524288) { + else if (type.flags & 524288 /* Intersection */) { return getIntersectionType(ts.map(type.types, function (t) { return getTypeWithThisArgument(t, thisArgument, needApparentType); })); } return needApparentType ? getApparentType(type) : type; @@ -29938,7 +34692,7 @@ var ts; } else { mapper = createTypeMapper(typeParameters, typeArguments); - members = createInstantiatedSymbolTable(source.declaredProperties, mapper, typeParameters.length === 1); + members = createInstantiatedSymbolTable(source.declaredProperties, mapper, /*mappingThisOnly*/ typeParameters.length === 1); callSignatures = instantiateSignatures(source.declaredCallSignatures, mapper); constructSignatures = instantiateSignatures(source.declaredConstructSignatures, mapper); stringIndexInfo = instantiateIndexInfo(source.declaredStringIndexInfo, mapper); @@ -29955,14 +34709,14 @@ var ts; var baseType = baseTypes_1[_i]; var instantiatedBaseType = thisArgument ? getTypeWithThisArgument(instantiateType(baseType, mapper), thisArgument) : baseType; addInheritedMembers(members, getPropertiesOfType(instantiatedBaseType)); - callSignatures = ts.concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, 0)); - constructSignatures = ts.concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, 1)); + callSignatures = ts.concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, 0 /* Call */)); + constructSignatures = ts.concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, 1 /* Construct */)); if (!stringIndexInfo) { stringIndexInfo = instantiatedBaseType === anyType ? - createIndexInfo(anyType, false) : - getIndexInfoOfType(instantiatedBaseType, 0); + createIndexInfo(anyType, /*isReadonly*/ false) : + getIndexInfoOfType(instantiatedBaseType, 0 /* String */); } - numberIndexInfo = numberIndexInfo || getIndexInfoOfType(instantiatedBaseType, 1); + numberIndexInfo = numberIndexInfo || getIndexInfoOfType(instantiatedBaseType, 1 /* Number */); } } setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); @@ -29993,13 +34747,14 @@ var ts; return sig; } function cloneSignature(sig) { - return createSignature(sig.declaration, sig.typeParameters, sig.thisParameter, sig.parameters, undefined, undefined, sig.minArgumentCount, sig.hasRestParameter, sig.hasLiteralTypes); + return createSignature(sig.declaration, sig.typeParameters, sig.thisParameter, sig.parameters, /*resolvedReturnType*/ undefined, + /*resolvedTypePredicate*/ undefined, sig.minArgumentCount, sig.hasRestParameter, sig.hasLiteralTypes); } function getDefaultConstructSignatures(classType) { var baseConstructorType = getBaseConstructorTypeOfClass(classType); - var baseSignatures = getSignaturesOfType(baseConstructorType, 1); + var baseSignatures = getSignaturesOfType(baseConstructorType, 1 /* Construct */); if (baseSignatures.length === 0) { - return [createSignature(undefined, classType.localTypeParameters, undefined, ts.emptyArray, classType, undefined, 0, false, false)]; + return [createSignature(undefined, classType.localTypeParameters, undefined, ts.emptyArray, classType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false)]; // TODO: GH#18217 } var baseTypeNode = getBaseTypeNodeOfClass(classType); var isJavaScript = ts.isInJavaScriptFile(baseTypeNode); @@ -30029,11 +34784,13 @@ var ts; } function findMatchingSignatures(signatureLists, signature, listIndex) { if (signature.typeParameters) { + // We require an exact match for generic signatures, so we only return signatures from the first + // signature list and only if they have exact matches in the other signature lists. if (listIndex > 0) { return undefined; } for (var i = 1; i < signatureLists.length; i++) { - if (!findMatchingSignature(signatureLists[i], signature, false, false, false)) { + if (!findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ false)) { return undefined; } } @@ -30041,7 +34798,8 @@ var ts; } var result; for (var i = 0; i < signatureLists.length; i++) { - var match = i === listIndex ? signature : findMatchingSignature(signatureLists[i], signature, true, true, true); + // Allow matching non-generic signatures to have excess parameters and different return types + var match = i === listIndex ? signature : findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ true, /*ignoreThisTypes*/ true, /*ignoreReturnTypes*/ true); if (!match) { return undefined; } @@ -30049,20 +34807,27 @@ var ts; } return result; } + // The signatures of a union type are those signatures that are present in each of the constituent types. + // Generic signatures must match exactly, but non-generic signatures are allowed to have extra optional + // parameters and may differ in return types. When signatures differ in return types, the resulting return + // type is the union of the constituent return types. function getUnionSignatures(types, kind) { var signatureLists = ts.map(types, function (t) { return getSignaturesOfType(t, kind); }); var result; for (var i = 0; i < signatureLists.length; i++) { for (var _i = 0, _a = signatureLists[i]; _i < _a.length; _i++) { var signature = _a[_i]; - if (!result || !findMatchingSignature(result, signature, false, true, true)) { + // Only process signatures with parameter lists that aren't already in the result list + if (!result || !findMatchingSignature(result, signature, /*partialMatch*/ false, /*ignoreThisTypes*/ true, /*ignoreReturnTypes*/ true)) { var unionSignatures = findMatchingSignatures(signatureLists, signature, i); if (unionSignatures) { var s = signature; + // Union the result types when more than one signature matches if (unionSignatures.length > 1) { var thisParameter = signature.thisParameter; if (ts.forEach(unionSignatures, function (sig) { return sig.thisParameter; })) { - var thisType = getUnionType(ts.map(unionSignatures, function (sig) { return sig.thisParameter ? getTypeOfSymbol(sig.thisParameter) : anyType; }), 2); + // TODO: GH#18217 We tested that *some* has thisParameter and now act as if *all* do + var thisType = getUnionType(ts.map(unionSignatures, function (sig) { return sig.thisParameter ? getTypeOfSymbol(sig.thisParameter) : anyType; }), 2 /* Subtype */); thisParameter = createSymbolWithType(signature.thisParameter, thisType); } s = cloneSignature(signature); @@ -30088,13 +34853,15 @@ var ts; indexTypes.push(indexInfo.type); isAnyReadonly = isAnyReadonly || indexInfo.isReadonly; } - return createIndexInfo(getUnionType(indexTypes, 2), isAnyReadonly); + return createIndexInfo(getUnionType(indexTypes, 2 /* Subtype */), isAnyReadonly); } function resolveUnionTypeMembers(type) { - var callSignatures = getUnionSignatures(type.types, 0); - var constructSignatures = getUnionSignatures(type.types, 1); - var stringIndexInfo = getUnionIndexInfo(type.types, 0); - var numberIndexInfo = getUnionIndexInfo(type.types, 1); + // The members and properties collections are empty for union types. To get all properties of a union + // type use getPropertiesOfType (only the language service uses this). + var callSignatures = getUnionSignatures(type.types, 0 /* Call */); + var constructSignatures = getUnionSignatures(type.types, 1 /* Construct */); + var stringIndexInfo = getUnionIndexInfo(type.types, 0 /* String */); + var numberIndexInfo = getUnionIndexInfo(type.types, 1 /* Number */); setStructuredTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); } function intersectTypes(type1, type2) { @@ -30113,12 +34880,14 @@ var ts; mixedTypes.push(type); } else if (isMixinConstructorType(types[i])) { - mixedTypes.push(getReturnTypeOfSignature(getSignaturesOfType(types[i], 1)[0])); + mixedTypes.push(getReturnTypeOfSignature(getSignaturesOfType(types[i], 1 /* Construct */)[0])); } } return getIntersectionType(mixedTypes); } function resolveIntersectionTypeMembers(type) { + // The members and properties collections are empty for intersection types. To get all properties of an + // intersection type use getPropertiesOfType (only the language service uses this). var callSignatures = ts.emptyArray; var constructSignatures = ts.emptyArray; var stringIndexInfo; @@ -30127,8 +34896,13 @@ var ts; var mixinCount = ts.countWhere(types, isMixinConstructorType); var _loop_5 = function (i) { var t = type.types[i]; + // When an intersection type contains mixin constructor types, the construct signatures from + // those types are discarded and their return types are mixed into the return types of all + // other construct signatures in the intersection type. For example, the intersection type + // '{ new(...args: any[]) => A } & { new(s: string) => B }' has a single construct signature + // 'new(s: string) => A & B'. if (mixinCount === 0 || mixinCount === types.length && i === 0 || !isMixinConstructorType(t)) { - var signatures = getSignaturesOfType(t, 1); + var signatures = getSignaturesOfType(t, 1 /* Construct */); if (signatures.length && mixinCount > 0) { signatures = ts.map(signatures, function (s) { var clone = cloneSignature(s); @@ -30138,59 +34912,68 @@ var ts; } constructSignatures = ts.concatenate(constructSignatures, signatures); } - callSignatures = ts.concatenate(callSignatures, getSignaturesOfType(t, 0)); - stringIndexInfo = intersectIndexInfos(stringIndexInfo, getIndexInfoOfType(t, 0)); - numberIndexInfo = intersectIndexInfos(numberIndexInfo, getIndexInfoOfType(t, 1)); + callSignatures = ts.concatenate(callSignatures, getSignaturesOfType(t, 0 /* Call */)); + stringIndexInfo = intersectIndexInfos(stringIndexInfo, getIndexInfoOfType(t, 0 /* String */)); + numberIndexInfo = intersectIndexInfos(numberIndexInfo, getIndexInfoOfType(t, 1 /* Number */)); }; for (var i = 0; i < types.length; i++) { _loop_5(i); } setStructuredTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); } + /** + * Converts an AnonymousType to a ResolvedType. + */ function resolveAnonymousTypeMembers(type) { var symbol = type.symbol; if (type.target) { - var members = createInstantiatedSymbolTable(getPropertiesOfObjectType(type.target), type.mapper, false); - var callSignatures = instantiateSignatures(getSignaturesOfType(type.target, 0), type.mapper); - var constructSignatures = instantiateSignatures(getSignaturesOfType(type.target, 1), type.mapper); - var stringIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, 0), type.mapper); - var numberIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, 1), type.mapper); + var members = createInstantiatedSymbolTable(getPropertiesOfObjectType(type.target), type.mapper, /*mappingThisOnly*/ false); + var callSignatures = instantiateSignatures(getSignaturesOfType(type.target, 0 /* Call */), type.mapper); + var constructSignatures = instantiateSignatures(getSignaturesOfType(type.target, 1 /* Construct */), type.mapper); + var stringIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, 0 /* String */), type.mapper); + var numberIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, 1 /* Number */), type.mapper); setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); } - else if (symbol.flags & 2048) { + else if (symbol.flags & 2048 /* TypeLiteral */) { var members = getMembersOfSymbol(symbol); - var callSignatures = getSignaturesOfSymbol(members.get("__call")); - var constructSignatures = getSignaturesOfSymbol(members.get("__new")); - var stringIndexInfo = getIndexInfoOfSymbol(symbol, 0); - var numberIndexInfo = getIndexInfoOfSymbol(symbol, 1); + var callSignatures = getSignaturesOfSymbol(members.get("__call" /* Call */)); + var constructSignatures = getSignaturesOfSymbol(members.get("__new" /* New */)); + var stringIndexInfo = getIndexInfoOfSymbol(symbol, 0 /* String */); + var numberIndexInfo = getIndexInfoOfSymbol(symbol, 1 /* Number */); setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); } else { + // Combinations of function, class, enum and module var members = emptySymbols; var stringIndexInfo = void 0; if (symbol.exports) { members = getExportsOfSymbol(symbol); } setStructuredTypeMembers(type, members, ts.emptyArray, ts.emptyArray, undefined, undefined); - if (symbol.flags & 32) { + if (symbol.flags & 32 /* Class */) { var classType = getDeclaredTypeOfClassOrInterface(symbol); var baseConstructorType = getBaseConstructorTypeOfClass(classType); - if (baseConstructorType.flags & (131072 | 524288 | 2162688)) { + if (baseConstructorType.flags & (131072 /* Object */ | 524288 /* Intersection */ | 2162688 /* TypeVariable */)) { members = ts.createSymbolTable(getNamedMembers(members)); addInheritedMembers(members, getPropertiesOfType(baseConstructorType)); } else if (baseConstructorType === anyType) { - stringIndexInfo = createIndexInfo(anyType, false); + stringIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false); } } - var numberIndexInfo = symbol.flags & 384 ? enumNumberIndexInfo : undefined; + var numberIndexInfo = symbol.flags & 384 /* Enum */ ? enumNumberIndexInfo : undefined; setStructuredTypeMembers(type, members, ts.emptyArray, ts.emptyArray, stringIndexInfo, numberIndexInfo); - if (symbol.flags & (16 | 8192)) { + // We resolve the members before computing the signatures because a signature may use + // typeof with a qualified name expression that circularly references the type we are + // in the process of resolving (see issue #6072). The temporarily empty signature list + // will never be observed because a qualified name can't reference signatures. + if (symbol.flags & (16 /* Function */ | 8192 /* Method */)) { type.callSignatures = getSignaturesOfSymbol(symbol); } - if (symbol.flags & 32) { + // And likewise for construct signatures for classes + if (symbol.flags & 32 /* Class */) { var classType = getDeclaredTypeOfClassOrInterface(symbol); - var constructSignatures = getSignaturesOfSymbol(symbol.members.get("__constructor")); + var constructSignatures = getSignaturesOfSymbol(symbol.members.get("__constructor" /* Constructor */)); if (!constructSignatures.length) { constructSignatures = getDefaultConstructSignatures(classType); } @@ -30199,16 +34982,16 @@ var ts; } } function resolveReverseMappedTypeMembers(type) { - var indexInfo = getIndexInfoOfType(type.source, 0); + var indexInfo = getIndexInfoOfType(type.source, 0 /* String */); var modifiers = getMappedTypeModifiers(type.mappedType); - var readonlyMask = modifiers & 1 ? false : true; - var optionalMask = modifiers & 4 ? 0 : 16777216; + var readonlyMask = modifiers & 1 /* IncludeReadonly */ ? false : true; + var optionalMask = modifiers & 4 /* IncludeOptional */ ? 0 : 16777216 /* Optional */; var stringIndexInfo = indexInfo && createIndexInfo(inferReverseMappedType(indexInfo.type, type.mappedType), readonlyMask && indexInfo.isReadonly); var members = ts.createSymbolTable(); for (var _i = 0, _a = getPropertiesOfType(type.source); _i < _a.length; _i++) { var prop = _a[_i]; - var checkFlags = 2048 | (readonlyMask && isReadonlySymbol(prop) ? 8 : 0); - var inferredProp = createSymbol(4 | prop.flags & optionalMask, prop.escapedName, checkFlags); + var checkFlags = 2048 /* ReverseMapped */ | (readonlyMask && isReadonlySymbol(prop) ? 8 /* Readonly */ : 0); + var inferredProp = createSymbol(4 /* Property */ | prop.flags & optionalMask, prop.escapedName, checkFlags); inferredProp.declarations = prop.declarations; inferredProp.nameType = prop.nameType; inferredProp.propertyType = getTypeOfSymbol(prop); @@ -30217,48 +35000,64 @@ var ts; } setStructuredTypeMembers(type, members, ts.emptyArray, ts.emptyArray, stringIndexInfo, undefined); } + /** Resolve the members of a mapped type { [P in K]: T } */ function resolveMappedTypeMembers(type) { var members = ts.createSymbolTable(); var stringIndexInfo; var numberIndexInfo; + // Resolve upfront such that recursive references see an empty object type. setStructuredTypeMembers(type, emptySymbols, ts.emptyArray, ts.emptyArray, undefined, undefined); + // In { [P in K]: T }, we refer to P as the type parameter type, K as the constraint type, + // and T as the template type. var typeParameter = getTypeParameterFromMappedType(type); var constraintType = getConstraintTypeFromMappedType(type); var templateType = getTemplateTypeFromMappedType(type.target || type); - var modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); + var modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T' var templateModifiers = getMappedTypeModifiers(type); - var include = keyofStringsOnly ? 64 : 2240; + var include = keyofStringsOnly ? 64 /* StringLiteral */ : 2240 /* StringOrNumberLiteralOrUnique */; if (isMappedTypeWithKeyofConstraintDeclaration(type)) { + // We have a { [P in keyof T]: X } for (var _i = 0, _a = getPropertiesOfType(modifiersType); _i < _a.length; _i++) { var prop = _a[_i]; - addMemberForKeyType(getLiteralTypeFromPropertyName(prop, include), undefined, prop); + addMemberForKeyType(getLiteralTypeFromPropertyName(prop, include), /*_index*/ undefined, prop); } - if (modifiersType.flags & 1 || getIndexInfoOfType(modifiersType, 0)) { + if (modifiersType.flags & 1 /* Any */ || getIndexInfoOfType(modifiersType, 0 /* String */)) { addMemberForKeyType(stringType); } - if (!keyofStringsOnly && getIndexInfoOfType(modifiersType, 1)) { + if (!keyofStringsOnly && getIndexInfoOfType(modifiersType, 1 /* Number */)) { addMemberForKeyType(numberType); } } else { - var keyType = constraintType.flags & 14745600 ? getApparentType(constraintType) : constraintType; - var iterationType = keyType.flags & 1048576 ? getIndexType(getApparentType(keyType.type)) : keyType; + // First, if the constraint type is a type parameter, obtain the base constraint. Then, + // if the key type is a 'keyof X', obtain 'keyof C' where C is the base constraint of X. + // Finally, iterate over the constituents of the resulting iteration type. + var keyType = constraintType.flags & 14745600 /* InstantiableNonPrimitive */ ? getApparentType(constraintType) : constraintType; + var iterationType = keyType.flags & 1048576 /* Index */ ? getIndexType(getApparentType(keyType.type)) : keyType; forEachType(iterationType, addMemberForKeyType); } setStructuredTypeMembers(type, members, ts.emptyArray, ts.emptyArray, stringIndexInfo, numberIndexInfo); function addMemberForKeyType(t, _index, origin) { + // Create a mapper from T to the current iteration type constituent. Then, if the + // mapped type is itself an instantiated type, combine the iteration mapper with the + // instantiation mapper. var templateMapper = combineTypeMappers(type.mapper, createTypeMapper([typeParameter], [t])); var propType = instantiateType(templateType, templateMapper); - if (t.flags & 2240) { + // If the current iteration type constituent is a string literal type, create a property. + // Otherwise, for type string create a string index signature. + if (t.flags & 2240 /* StringOrNumberLiteralOrUnique */) { var propName = getLateBoundNameFromType(t); var modifiersProp = getPropertyOfType(modifiersType, propName); - var isOptional = !!(templateModifiers & 4 || - !(templateModifiers & 8) && modifiersProp && modifiersProp.flags & 16777216); - var isReadonly = !!(templateModifiers & 1 || - !(templateModifiers & 2) && modifiersProp && isReadonlySymbol(modifiersProp)); - var prop = createSymbol(4 | (isOptional ? 16777216 : 0), propName, isReadonly ? 8 : 0); + var isOptional = !!(templateModifiers & 4 /* IncludeOptional */ || + !(templateModifiers & 8 /* ExcludeOptional */) && modifiersProp && modifiersProp.flags & 16777216 /* Optional */); + var isReadonly = !!(templateModifiers & 1 /* IncludeReadonly */ || + !(templateModifiers & 2 /* ExcludeReadonly */) && modifiersProp && isReadonlySymbol(modifiersProp)); + var prop = createSymbol(4 /* Property */ | (isOptional ? 16777216 /* Optional */ : 0), propName, isReadonly ? 8 /* Readonly */ : 0); + // When creating an optional property in strictNullChecks mode, if 'undefined' isn't assignable to the + // type, we include 'undefined' in the type. Similarly, when creating a non-optional property in strictNullChecks + // mode, if the underlying property is optional we remove 'undefined' from the type. prop.type = strictNullChecks && isOptional && !isTypeAssignableTo(undefinedType, propType) ? getOptionalType(propType) : - strictNullChecks && !isOptional && modifiersProp && modifiersProp.flags & 16777216 ? getTypeWithFacts(propType, 131072) : + strictNullChecks && !isOptional && modifiersProp && modifiersProp.flags & 16777216 /* Optional */ ? getTypeWithFacts(propType, 131072 /* NEUndefined */) : propType; if (origin) { prop.syntheticOrigin = origin; @@ -30267,11 +35066,11 @@ var ts; prop.nameType = t; members.set(propName, prop); } - else if (t.flags & (1 | 4)) { - stringIndexInfo = createIndexInfo(propType, !!(templateModifiers & 1)); + else if (t.flags & (1 /* Any */ | 4 /* String */)) { + stringIndexInfo = createIndexInfo(propType, !!(templateModifiers & 1 /* IncludeReadonly */)); } - else if (t.flags & 8) { - numberIndexInfo = createIndexInfo(propType, !!(templateModifiers & 1)); + else if (t.flags & 8 /* Number */) { + numberIndexInfo = createIndexInfo(propType, !!(templateModifiers & 1 /* IncludeReadonly */)); } } } @@ -30286,39 +35085,45 @@ var ts; function getTemplateTypeFromMappedType(type) { return type.templateType || (type.templateType = type.declaration.type ? - instantiateType(addOptionality(getTypeFromTypeNode(type.declaration.type), !!(getMappedTypeModifiers(type) & 4)), type.mapper || identityMapper) : + instantiateType(addOptionality(getTypeFromTypeNode(type.declaration.type), !!(getMappedTypeModifiers(type) & 4 /* IncludeOptional */)), type.mapper || identityMapper) : errorType); } function getConstraintDeclarationForMappedType(type) { return type.declaration.typeParameter.constraint; } function isMappedTypeWithKeyofConstraintDeclaration(type) { - var constraintDeclaration = getConstraintDeclarationForMappedType(type); - return constraintDeclaration.kind === 175 && - constraintDeclaration.operator === 128; + var constraintDeclaration = getConstraintDeclarationForMappedType(type); // TODO: GH#18217 + return constraintDeclaration.kind === 175 /* TypeOperator */ && + constraintDeclaration.operator === 128 /* KeyOfKeyword */; } function getModifiersTypeFromMappedType(type) { if (!type.modifiersType) { if (isMappedTypeWithKeyofConstraintDeclaration(type)) { + // If the constraint declaration is a 'keyof T' node, the modifiers type is T. We check + // AST nodes here because, when T is a non-generic type, the logic below eagerly resolves + // 'keyof T' to a literal union type and we can't recover T from that type. type.modifiersType = instantiateType(getTypeFromTypeNode(getConstraintDeclarationForMappedType(type).type), type.mapper || identityMapper); } else { + // Otherwise, get the declared constraint type, and if the constraint type is a type parameter, + // get the constraint of that type parameter. If the resulting type is an indexed type 'keyof T', + // the modifiers type is T. Otherwise, the modifiers type is {}. var declaredType = getTypeFromMappedTypeNode(type.declaration); var constraint = getConstraintTypeFromMappedType(declaredType); - var extendedConstraint = constraint && constraint.flags & 65536 ? getConstraintOfTypeParameter(constraint) : constraint; - type.modifiersType = extendedConstraint && extendedConstraint.flags & 1048576 ? instantiateType(extendedConstraint.type, type.mapper || identityMapper) : emptyObjectType; + var extendedConstraint = constraint && constraint.flags & 65536 /* TypeParameter */ ? getConstraintOfTypeParameter(constraint) : constraint; + type.modifiersType = extendedConstraint && extendedConstraint.flags & 1048576 /* Index */ ? instantiateType(extendedConstraint.type, type.mapper || identityMapper) : emptyObjectType; } } return type.modifiersType; } function getMappedTypeModifiers(type) { var declaration = type.declaration; - return (declaration.readonlyToken ? declaration.readonlyToken.kind === 38 ? 2 : 1 : 0) | - (declaration.questionToken ? declaration.questionToken.kind === 38 ? 8 : 4 : 0); + return (declaration.readonlyToken ? declaration.readonlyToken.kind === 38 /* MinusToken */ ? 2 /* ExcludeReadonly */ : 1 /* IncludeReadonly */ : 0) | + (declaration.questionToken ? declaration.questionToken.kind === 38 /* MinusToken */ ? 8 /* ExcludeOptional */ : 4 /* IncludeOptional */ : 0); } function getMappedTypeOptionality(type) { var modifiers = getMappedTypeModifiers(type); - return modifiers & 8 ? -1 : modifiers & 4 ? 1 : 0; + return modifiers & 8 /* ExcludeOptional */ ? -1 : modifiers & 4 /* IncludeOptional */ ? 1 : 0; } function getCombinedMappedTypeOptionality(type) { var optionality = getMappedTypeOptionality(type); @@ -30326,47 +35131,51 @@ var ts; return optionality || (isGenericMappedType(modifiersType) ? getMappedTypeOptionality(modifiersType) : 0); } function isPartialMappedType(type) { - return !!(ts.getObjectFlags(type) & 32 && getMappedTypeModifiers(type) & 4); + return !!(ts.getObjectFlags(type) & 32 /* Mapped */ && getMappedTypeModifiers(type) & 4 /* IncludeOptional */); } function isGenericMappedType(type) { - return !!(ts.getObjectFlags(type) & 32) && isGenericIndexType(getConstraintTypeFromMappedType(type)); + return !!(ts.getObjectFlags(type) & 32 /* Mapped */) && isGenericIndexType(getConstraintTypeFromMappedType(type)); } function resolveStructuredTypeMembers(type) { if (!type.members) { - if (type.flags & 131072) { - if (type.objectFlags & 4) { + if (type.flags & 131072 /* Object */) { + if (type.objectFlags & 4 /* Reference */) { resolveTypeReferenceMembers(type); } - else if (type.objectFlags & 3) { + else if (type.objectFlags & 3 /* ClassOrInterface */) { resolveClassOrInterfaceMembers(type); } - else if (type.objectFlags & 2048) { + else if (type.objectFlags & 2048 /* ReverseMapped */) { resolveReverseMappedTypeMembers(type); } - else if (type.objectFlags & 16) { + else if (type.objectFlags & 16 /* Anonymous */) { resolveAnonymousTypeMembers(type); } - else if (type.objectFlags & 32) { + else if (type.objectFlags & 32 /* Mapped */) { resolveMappedTypeMembers(type); } } - else if (type.flags & 262144) { + else if (type.flags & 262144 /* Union */) { resolveUnionTypeMembers(type); } - else if (type.flags & 524288) { + else if (type.flags & 524288 /* Intersection */) { resolveIntersectionTypeMembers(type); } } return type; } + /** Return properties of an object type or an empty array for other types */ function getPropertiesOfObjectType(type) { - if (type.flags & 131072) { + if (type.flags & 131072 /* Object */) { return resolveStructuredTypeMembers(type).properties; } return ts.emptyArray; } + /** If the given type is an object type and that type has a property by the given name, + * return the symbol for that property. Otherwise return undefined. + */ function getPropertyOfObjectType(type, name) { - if (type.flags & 131072) { + if (type.flags & 131072 /* Object */) { var resolved = resolveStructuredTypeMembers(type); var symbol = resolved.members.get(name); if (symbol && symbolIsValue(symbol)) { @@ -30388,7 +35197,9 @@ var ts; } } } - if (type.flags & 262144) { + // The properties of a union type are those that are present in all constituent types, so + // we only need to check the properties of the first type + if (type.flags & 262144 /* Union */) { break; } } @@ -30398,13 +35209,13 @@ var ts; } function getPropertiesOfType(type) { type = getApparentType(type); - return type.flags & 786432 ? + return type.flags & 786432 /* UnionOrIntersection */ ? getPropertiesOfUnionOrIntersectionType(type) : getPropertiesOfObjectType(type); } function getAllPossiblePropertiesOfTypes(types) { var unionType = getUnionType(types); - if (!(unionType.flags & 262144)) { + if (!(unionType.flags & 262144 /* Union */)) { return getAugmentedPropertiesOfType(unionType); } var props = ts.createSymbolTable(); @@ -30414,6 +35225,7 @@ var ts; var escapedName = _b[_a].escapedName; if (!props.has(escapedName)) { var prop = createUnionOrIntersectionProperty(unionType, escapedName); + // May be undefined if the property is private if (prop) props.set(escapedName, prop); } @@ -30422,9 +35234,9 @@ var ts; return ts.arrayFrom(props.values()); } function getConstraintOfType(type) { - return type.flags & 65536 ? getConstraintOfTypeParameter(type) : - type.flags & 2097152 ? getConstraintOfIndexedAccess(type) : - type.flags & 4194304 ? getConstraintOfConditionalType(type) : + return type.flags & 65536 /* TypeParameter */ ? getConstraintOfTypeParameter(type) : + type.flags & 2097152 /* IndexedAccess */ ? getConstraintOfIndexedAccess(type) : + type.flags & 4194304 /* Conditional */ ? getConstraintOfConditionalType(type) : getBaseConstraintOfType(type); } function getConstraintOfTypeParameter(typeParameter) { @@ -30439,18 +35251,23 @@ var ts; function getDefaultConstraintOfConditionalType(type) { if (!type.resolvedDefaultConstraint) { var rootTrueType = type.root.trueType; - var rootTrueConstraint = rootTrueType.flags & 8388608 ? rootTrueType.substitute : rootTrueType; + var rootTrueConstraint = rootTrueType.flags & 8388608 /* Substitution */ ? rootTrueType.substitute : rootTrueType; type.resolvedDefaultConstraint = getUnionType([instantiateType(rootTrueConstraint, type.combinedMapper || type.mapper), getFalseTypeFromConditionalType(type)]); } return type.resolvedDefaultConstraint; } function getConstraintOfDistributiveConditionalType(type) { + // Check if we have a conditional type of the form 'T extends U ? X : Y', where T is a constrained + // type parameter. If so, create an instantiation of the conditional type where T is replaced + // with its constraint. We do this because if the constraint is a union type it will be distributed + // over the conditional type and possibly reduced. For example, 'T extends undefined ? never : T' + // removes 'undefined' from T. if (type.root.isDistributive) { var constraint = getConstraintOfType(getSimplifiedType(type.checkType)); if (constraint) { var mapper = makeUnaryTypeMapper(type.root.checkType, constraint); var instantiated = getConditionalTypeInstantiation(type, combineTypeMappers(mapper, type.mapper)); - if (!(instantiated.flags & 32768)) { + if (!(instantiated.flags & 32768 /* Never */)) { return instantiated; } } @@ -30465,27 +35282,35 @@ var ts; var hasDisjointDomainType = false; for (var _i = 0, _a = type.types; _i < _a.length; _i++) { var t = _a[_i]; - if (t.flags & 15794176) { + if (t.flags & 15794176 /* Instantiable */) { + // We keep following constraints as long as we have an instantiable type that is known + // not to be circular or infinite (hence we stop on index access types). var constraint = getConstraintOfType(t); - while (constraint && constraint.flags & (65536 | 1048576 | 4194304)) { + while (constraint && constraint.flags & (65536 /* TypeParameter */ | 1048576 /* Index */ | 4194304 /* Conditional */)) { constraint = getConstraintOfType(constraint); } if (constraint) { - if (!(constraint.flags & 262144)) { + // A constraint that isn't a union type implies that the final type would be a non-union + // type as well. Since non-union constraints are of no interest, we can exit here. + if (!(constraint.flags & 262144 /* Union */)) { return undefined; } constraints = ts.append(constraints, constraint); } } - else if (t.flags & 16809468) { + else if (t.flags & 16809468 /* DisjointDomains */) { hasDisjointDomainType = true; } } + // If the target is a union type or if we are intersecting with types belonging to one of the + // disjoint domans, we may end up producing a constraint that hasn't been examined before. if (constraints && (targetIsUnion || hasDisjointDomainType)) { if (hasDisjointDomainType) { + // We add any types belong to one of the disjoint domans because they might cause the final + // intersection operation to reduce the union constraints. for (var _b = 0, _c = type.types; _b < _c.length; _b++) { var t = _c[_b]; - if (t.flags & 16809468) { + if (t.flags & 16809468 /* DisjointDomains */) { constraints = ts.append(constraints, t); } } @@ -30495,7 +35320,7 @@ var ts; return undefined; } function getBaseConstraintOfInstantiableNonPrimitiveUnionOrIntersection(type) { - if (type.flags & (14745600 | 786432)) { + if (type.flags & (14745600 /* InstantiableNonPrimitive */ | 786432 /* UnionOrIntersection */)) { var constraint = getResolvedBaseConstraint(type); if (constraint !== noConstraintType && constraint !== circularConstraintType) { return constraint; @@ -30504,17 +35329,26 @@ var ts; } function getBaseConstraintOfType(type) { var constraint = getBaseConstraintOfInstantiableNonPrimitiveUnionOrIntersection(type); - if (!constraint && type.flags & 1048576) { + if (!constraint && type.flags & 1048576 /* Index */) { return keyofConstraintType; } return constraint; } + /** + * This is similar to `getBaseConstraintOfType` except it returns the input type if there's no base constraint, instead of `undefined` + * It also doesn't map indexes to `string`, as where this is used this would be unneeded (and likely undesirable) + */ function getBaseConstraintOrType(type) { return getBaseConstraintOfType(type) || type; } function hasNonCircularBaseConstraint(type) { return getResolvedBaseConstraint(type) !== circularConstraintType; } + /** + * Return the resolved base constraint of a type variable. The noConstraintType singleton is returned if the + * type variable has no constraint, and the circularConstraintType singleton is returned if the constraint + * circularly references the type variable. + */ function getResolvedBaseConstraint(type) { var circular; if (!type.resolvedBaseConstraint) { @@ -30523,7 +35357,7 @@ var ts; } return type.resolvedBaseConstraint; function getBaseConstraint(t) { - if (!pushTypeResolution(t, 4)) { + if (!pushTypeResolution(t, 4 /* ResolvedBaseConstraint */)) { circular = true; return undefined; } @@ -30535,13 +35369,13 @@ var ts; return result; } function computeBaseConstraint(t) { - if (t.flags & 65536) { + if (t.flags & 65536 /* TypeParameter */) { var constraint = getConstraintFromTypeParameter(t); return t.isThisType || !constraint ? constraint : getBaseConstraint(constraint); } - if (t.flags & 786432) { + if (t.flags & 786432 /* UnionOrIntersection */) { var types = t.types; var baseTypes = []; for (var _i = 0, types_4 = types; _i < types_4.length; _i++) { @@ -30551,24 +35385,24 @@ var ts; baseTypes.push(baseType); } } - return t.flags & 262144 && baseTypes.length === types.length ? getUnionType(baseTypes) : - t.flags & 524288 && baseTypes.length ? getIntersectionType(baseTypes) : + return t.flags & 262144 /* Union */ && baseTypes.length === types.length ? getUnionType(baseTypes) : + t.flags & 524288 /* Intersection */ && baseTypes.length ? getIntersectionType(baseTypes) : undefined; } - if (t.flags & 1048576) { + if (t.flags & 1048576 /* Index */) { return keyofConstraintType; } - if (t.flags & 2097152) { + if (t.flags & 2097152 /* IndexedAccess */) { var baseObjectType = getBaseConstraint(t.objectType); var baseIndexType = getBaseConstraint(t.indexType); var baseIndexedAccess = baseObjectType && baseIndexType ? getIndexedAccessType(baseObjectType, baseIndexType) : undefined; return baseIndexedAccess && baseIndexedAccess !== errorType ? getBaseConstraint(baseIndexedAccess) : undefined; } - if (t.flags & 4194304) { + if (t.flags & 4194304 /* Conditional */) { var constraint = getConstraintOfConditionalType(t); return constraint && getBaseConstraint(constraint); } - if (t.flags & 8388608) { + if (t.flags & 8388608 /* Substitution */) { return getBaseConstraint(t.substitute); } if (isGenericMappedType(t)) { @@ -30578,7 +35412,7 @@ var ts; } } function getApparentTypeOfIntersectionType(type) { - return type.resolvedApparentType || (type.resolvedApparentType = getTypeWithThisArgument(type, type, true)); + return type.resolvedApparentType || (type.resolvedApparentType = getTypeWithThisArgument(type, type, /*apparentType*/ true)); } function getResolvedTypeParameterDefault(typeParameter) { if (!typeParameter.default) { @@ -30587,19 +35421,29 @@ var ts; typeParameter.default = targetDefault ? instantiateType(targetDefault, typeParameter.mapper) : noConstraintType; } else { + // To block recursion, set the initial value to the resolvingDefaultType. typeParameter.default = resolvingDefaultType; var defaultDeclaration = typeParameter.symbol && ts.forEach(typeParameter.symbol.declarations, function (decl) { return ts.isTypeParameterDeclaration(decl) && decl.default; }); var defaultType = defaultDeclaration ? getTypeFromTypeNode(defaultDeclaration) : noConstraintType; if (typeParameter.default === resolvingDefaultType) { + // If we have not been called recursively, set the correct default type. typeParameter.default = defaultType; } } } else if (typeParameter.default === resolvingDefaultType) { + // If we are called recursively for this type parameter, mark the default as circular. typeParameter.default = circularConstraintType; } return typeParameter.default; } + /** + * Gets the default type for a type parameter. + * + * If the type parameter is the result of an instantiation, this gets the instantiated + * default type of its target. If the type parameter has no default type or the default is + * circular, `undefined` is returned. + */ function getDefaultFromTypeParameter(typeParameter) { var defaultType = getResolvedTypeParameterDefault(typeParameter); return defaultType !== noConstraintType && defaultType !== circularConstraintType ? defaultType : undefined; @@ -30607,26 +35451,35 @@ var ts; function hasNonCircularTypeParameterDefault(typeParameter) { return getResolvedTypeParameterDefault(typeParameter) !== circularConstraintType; } + /** + * Indicates whether the declaration of a typeParameter has a default type. + */ function hasTypeParameterDefault(typeParameter) { return !!(typeParameter.symbol && ts.forEach(typeParameter.symbol.declarations, function (decl) { return ts.isTypeParameterDeclaration(decl) && decl.default; })); } + /** + * For a type parameter, return the base constraint of the type parameter. For the string, number, + * boolean, and symbol primitive types, return the corresponding object types. Otherwise return the + * type itself. Note that the apparent type of a union type is the union type itself. + */ function getApparentType(type) { - var t = type.flags & 15794176 ? getBaseConstraintOfType(type) || emptyObjectType : type; - return t.flags & 524288 ? getApparentTypeOfIntersectionType(t) : - t.flags & 68 ? globalStringType : - t.flags & 168 ? globalNumberType : - t.flags & 272 ? globalBooleanType : - t.flags & 3072 ? getGlobalESSymbolType(languageVersion >= 2) : - t.flags & 16777216 ? emptyObjectType : - t.flags & 1048576 ? keyofConstraintType : + var t = type.flags & 15794176 /* Instantiable */ ? getBaseConstraintOfType(type) || emptyObjectType : type; + return t.flags & 524288 /* Intersection */ ? getApparentTypeOfIntersectionType(t) : + t.flags & 68 /* StringLike */ ? globalStringType : + t.flags & 168 /* NumberLike */ ? globalNumberType : + t.flags & 272 /* BooleanLike */ ? globalBooleanType : + t.flags & 3072 /* ESSymbolLike */ ? getGlobalESSymbolType(/*reportErrors*/ languageVersion >= 2 /* ES2015 */) : + t.flags & 16777216 /* NonPrimitive */ ? emptyObjectType : + t.flags & 1048576 /* Index */ ? keyofConstraintType : t; } function createUnionOrIntersectionProperty(containingType, name) { var props; - var isUnion = containingType.flags & 262144; - var excludeModifiers = isUnion ? 24 : 0; - var commonFlags = isUnion ? 0 : 16777216; - var syntheticFlag = 4; + var isUnion = containingType.flags & 262144 /* Union */; + var excludeModifiers = isUnion ? 24 /* NonPublicAccessibilityModifier */ : 0; + // Flags we want to propagate to the result if they exist in all source symbols + var commonFlags = isUnion ? 0 /* None */ : 16777216 /* Optional */; + var syntheticFlag = 4 /* SyntheticMethod */; var checkFlags = 0; for (var _i = 0, _a = containingType.types; _i < _a.length; _i++) { var current = _a[_i]; @@ -30637,24 +35490,24 @@ var ts; if (prop && !(modifiers & excludeModifiers)) { commonFlags &= prop.flags; props = ts.appendIfUnique(props, prop); - checkFlags |= (isReadonlySymbol(prop) ? 8 : 0) | - (!(modifiers & 24) ? 64 : 0) | - (modifiers & 16 ? 128 : 0) | - (modifiers & 8 ? 256 : 0) | - (modifiers & 32 ? 512 : 0); + checkFlags |= (isReadonlySymbol(prop) ? 8 /* Readonly */ : 0) | + (!(modifiers & 24 /* NonPublicAccessibilityModifier */) ? 64 /* ContainsPublic */ : 0) | + (modifiers & 16 /* Protected */ ? 128 /* ContainsProtected */ : 0) | + (modifiers & 8 /* Private */ ? 256 /* ContainsPrivate */ : 0) | + (modifiers & 32 /* Static */ ? 512 /* ContainsStatic */ : 0); if (!isPrototypeProperty(prop)) { - syntheticFlag = 2; + syntheticFlag = 2 /* SyntheticProperty */; } } else if (isUnion) { - checkFlags |= 16; + checkFlags |= 16 /* Partial */; } } } if (!props) { return undefined; } - if (props.length === 1 && !(checkFlags & 16)) { + if (props.length === 1 && !(checkFlags & 16 /* Partial */)) { return props[0]; } var declarations; @@ -30681,12 +35534,12 @@ var ts; } else { if (type !== commonType) { - checkFlags |= 32; + checkFlags |= 32 /* HasNonUniformType */; } } propTypes.push(type); } - var result = createSymbol(4 | commonFlags, name, syntheticFlag | checkFlags); + var result = createSymbol(4 /* Property */ | commonFlags, name, syntheticFlag | checkFlags); result.containingType = containingType; if (!hasNonUniformValueDeclaration && commonValueDeclaration) { result.valueDeclaration = commonValueDeclaration; @@ -30696,6 +35549,11 @@ var ts; result.type = isUnion ? getUnionType(propTypes) : getIntersectionType(propTypes); return result; } + // Return the symbol for a given property in a union or intersection type, or undefined if the property + // does not exist in any constituent type. Note that the returned property may only be present in some + // constituents, in which case the isPartial flag is set when the containing type is union type. We need + // these partial properties when identifying discriminant properties, but otherwise they are filtered out + // and do not appear to be present in the union type. function getUnionOrIntersectionProperty(type, name) { var properties = type.propertyCache || (type.propertyCache = ts.createSymbolTable()); var property = properties.get(name); @@ -30709,11 +35567,20 @@ var ts; } function getPropertyOfUnionOrIntersectionType(type, name) { var property = getUnionOrIntersectionProperty(type, name); - return property && !(ts.getCheckFlags(property) & 16) ? property : undefined; + // We need to filter out partial properties in union types + return property && !(ts.getCheckFlags(property) & 16 /* Partial */) ? property : undefined; } + /** + * Return the symbol for the property with the given name in the given type. Creates synthetic union properties when + * necessary, maps primitive types and type parameters are to their apparent types, and augments with properties from + * Object and Function as appropriate. + * + * @param type a type to look up property from + * @param name a name of property to look up in a given type + */ function getPropertyOfType(type, name) { type = getApparentType(type); - if (type.flags & 131072) { + if (type.flags & 131072 /* Object */) { var resolved = resolveStructuredTypeMembers(type); var symbol = resolved.members.get(name); if (symbol && symbolIsValue(symbol)) { @@ -30727,34 +35594,42 @@ var ts; } return getPropertyOfObjectType(globalObjectType, name); } - if (type.flags & 786432) { + if (type.flags & 786432 /* UnionOrIntersection */) { return getPropertyOfUnionOrIntersectionType(type, name); } return undefined; } function getSignaturesOfStructuredType(type, kind) { - if (type.flags & 917504) { + if (type.flags & 917504 /* StructuredType */) { var resolved = resolveStructuredTypeMembers(type); - return kind === 0 ? resolved.callSignatures : resolved.constructSignatures; + return kind === 0 /* Call */ ? resolved.callSignatures : resolved.constructSignatures; } return ts.emptyArray; } + /** + * Return the signatures of the given kind in the given type. Creates synthetic union signatures when necessary and + * maps primitive types and type parameters are to their apparent types. + */ function getSignaturesOfType(type, kind) { return getSignaturesOfStructuredType(getApparentType(type), kind); } function getIndexInfoOfStructuredType(type, kind) { - if (type.flags & 917504) { + if (type.flags & 917504 /* StructuredType */) { var resolved = resolveStructuredTypeMembers(type); - return kind === 0 ? resolved.stringIndexInfo : resolved.numberIndexInfo; + return kind === 0 /* String */ ? resolved.stringIndexInfo : resolved.numberIndexInfo; } } function getIndexTypeOfStructuredType(type, kind) { var info = getIndexInfoOfStructuredType(type, kind); return info && info.type; } + // Return the indexing info of the given kind in the given type. Creates synthetic union index types when necessary and + // maps primitive types and type parameters are to their apparent types. function getIndexInfoOfType(type, kind) { return getIndexInfoOfStructuredType(getApparentType(type), kind); } + // Return the index type of the given kind in the given type. Creates synthetic union index types when necessary and + // maps primitive types and type parameters are to their apparent types. function getIndexTypeOfType(type, kind) { return getIndexTypeOfStructuredType(getApparentType(type), kind); } @@ -30763,16 +35638,18 @@ var ts; var propTypes = []; for (var _i = 0, _a = getPropertiesOfType(type); _i < _a.length; _i++) { var prop = _a[_i]; - if (kind === 0 || isNumericLiteralName(prop.escapedName)) { + if (kind === 0 /* String */ || isNumericLiteralName(prop.escapedName)) { propTypes.push(getTypeOfSymbol(prop)); } } if (propTypes.length) { - return getUnionType(propTypes, 2); + return getUnionType(propTypes, 2 /* Subtype */); } } return undefined; } + // Return list of type parameters with duplicates removed (duplicate identifier errors are generated in the actual + // type checking functions). function getTypeParametersFromDeclaration(declaration) { var result; for (var _i = 0, _a = ts.getEffectiveTypeParameterDeclarations(declaration); _i < _a.length; _i++) { @@ -30791,17 +35668,20 @@ var ts; return result; } function isJSDocOptionalParameter(node) { - return ts.isInJavaScriptFile(node) && (node.type && node.type.kind === 283 + return ts.isInJavaScriptFile(node) && ( + // node.type should only be a JSDocOptionalType when node is a parameter of a JSDocFunctionType + node.type && node.type.kind === 283 /* JSDocOptionalType */ || ts.getJSDocParameterTags(node).some(function (_a) { var isBracketed = _a.isBracketed, typeExpression = _a.typeExpression; - return isBracketed || !!typeExpression && typeExpression.type.kind === 283; + return isBracketed || !!typeExpression && typeExpression.type.kind === 283 /* JSDocOptionalType */; })); } function tryFindAmbientModule(moduleName, withAugmentations) { if (ts.isExternalModuleNameRelative(moduleName)) { return undefined; } - var symbol = getSymbol(globals, '"' + moduleName + '"', 512); + var symbol = getSymbol(globals, '"' + moduleName + '"', 512 /* ValueModule */); + // merged symbol is module declaration symbol combined with all augmentations return symbol && withAugmentations ? getMergedSymbol(symbol) : symbol; } function isOptionalParameter(node) { @@ -30827,24 +35707,29 @@ var ts; return false; } var isBracketed = node.isBracketed, typeExpression = node.typeExpression; - return isBracketed || !!typeExpression && typeExpression.type.kind === 283; + return isBracketed || !!typeExpression && typeExpression.type.kind === 283 /* JSDocOptionalType */; } function createTypePredicateFromTypePredicateNode(node) { var parameterName = node.parameterName; var type = getTypeFromTypeNode(node.type); - if (parameterName.kind === 71) { - return createIdentifierTypePredicate(parameterName && parameterName.escapedText, parameterName && getTypePredicateParameterIndex(node.parent.parameters, parameterName), type); + if (parameterName.kind === 71 /* Identifier */) { + return createIdentifierTypePredicate(parameterName && parameterName.escapedText, // TODO: GH#18217 + parameterName && getTypePredicateParameterIndex(node.parent.parameters, parameterName), type); } else { return createThisTypePredicate(type); } } function createIdentifierTypePredicate(parameterName, parameterIndex, type) { - return { kind: 1, parameterName: parameterName, parameterIndex: parameterIndex, type: type }; + return { kind: 1 /* Identifier */, parameterName: parameterName, parameterIndex: parameterIndex, type: type }; } function createThisTypePredicate(type) { - return { kind: 0, type: type }; + return { kind: 0 /* This */, type: type }; } + /** + * Gets the minimum number of type arguments needed to satisfy all non-optional type + * parameters. + */ function getMinTypeArgumentCount(typeParameters) { var minTypeArgumentCount = 0; if (typeParameters) { @@ -30864,6 +35749,9 @@ var ts; if (!typeArguments) { typeArguments = []; } + // Map an unsatisfied type parameter with a default type. + // If a type parameter does not have a default type, or if the default type + // is a forward reference, the empty object type is used. for (var i = numTypeArguments; i < numTypeParameters; i++) { typeArguments[i] = getDefaultTypeArgumentType(isJavaScriptImplicitAny); } @@ -30895,12 +35783,16 @@ var ts; ts.isValueSignatureDeclaration(declaration) && !ts.hasJSDocParameterTags(declaration) && !ts.getJSDocType(declaration); + // If this is a JSDoc construct signature, then skip the first parameter in the + // parameter list. The first parameter represents the return type of the construct + // signature. for (var i = isJSConstructSignature ? 1 : 0; i < declaration.parameters.length; i++) { var param = declaration.parameters[i]; var paramSymbol = param.symbol; var type = ts.isJSDocParameterTag(param) ? (param.typeExpression && param.typeExpression.type) : param.type; - if (paramSymbol && !!(paramSymbol.flags & 4) && !ts.isBindingPattern(param.name)) { - var resolvedSymbol = resolveName(param, paramSymbol.escapedName, 67216319, undefined, undefined, false); + // Include parameter symbol instead of property symbol in the signature + if (paramSymbol && !!(paramSymbol.flags & 4 /* Property */) && !ts.isBindingPattern(param.name)) { + var resolvedSymbol = resolveName(param, paramSymbol.escapedName, 67216319 /* Value */, undefined, undefined, /*isUse*/ false); paramSymbol = resolvedSymbol; } if (i === 0 && paramSymbol.escapedName === "this") { @@ -30910,9 +35802,10 @@ var ts; else { parameters.push(paramSymbol); } - if (type && type.kind === 178) { + if (type && type.kind === 178 /* LiteralType */) { hasLiteralTypes = true; } + // Record a new minimum argument count if this is not an optional parameter var isOptionalParameter_1 = isOptionalJSDocParameterTag(param) || param.initializer || param.questionToken || param.dotDotDotToken || iife && parameters.length > iife.arguments.length && !type || @@ -30922,25 +35815,32 @@ var ts; minArgumentCount = parameters.length; } } - if ((declaration.kind === 156 || declaration.kind === 157) && + // If only one accessor includes a this-type annotation, the other behaves as if it had the same type annotation + if ((declaration.kind === 156 /* GetAccessor */ || declaration.kind === 157 /* SetAccessor */) && !hasNonBindableDynamicName(declaration) && (!hasThisParameter || !thisParameter)) { - var otherKind = declaration.kind === 156 ? 157 : 156; + var otherKind = declaration.kind === 156 /* GetAccessor */ ? 157 /* SetAccessor */ : 156 /* GetAccessor */; var other = ts.getDeclarationOfKind(getSymbolOfNode(declaration), otherKind); if (other) { thisParameter = getAnnotatedAccessorThisParameter(other); } } - var classType = declaration.kind === 155 ? + var classType = declaration.kind === 155 /* Constructor */ ? getDeclaredTypeOfClassOrInterface(getMergedSymbol(declaration.parent.symbol)) : undefined; var typeParameters = classType ? classType.localTypeParameters : getTypeParametersFromDeclaration(declaration); var returnType = getSignatureReturnTypeFromDeclaration(declaration, isJSConstructSignature, classType); var hasRestLikeParameter = ts.hasRestParameter(declaration) || ts.isInJavaScriptFile(declaration) && maybeAddJsSyntheticRestParameter(declaration, parameters); - links.resolvedSignature = createSignature(declaration, typeParameters, thisParameter, parameters, returnType, undefined, minArgumentCount, hasRestLikeParameter, hasLiteralTypes); + links.resolvedSignature = createSignature(declaration, typeParameters, thisParameter, parameters, returnType, /*resolvedTypePredicate*/ undefined, minArgumentCount, hasRestLikeParameter, hasLiteralTypes); } return links.resolvedSignature; } + /** + * A JS function gets a synthetic rest parameter if it references `arguments` AND: + * 1. It has no parameters but at least one `@param` with a type that starts with `...` + * OR + * 2. It has at least one parameter, and the last parameter has a matching `@param` with a type that starts with `...` + */ function maybeAddJsSyntheticRestParameter(declaration, parameters) { if (ts.isJSDocSignature(declaration) || !containsArgumentsReference(declaration)) { return false; @@ -30950,10 +35850,11 @@ var ts; var lastParamVariadicType = ts.firstDefined(lastParamTags, function (p) { return p.typeExpression && ts.isJSDocVariadicType(p.typeExpression.type) ? p.typeExpression.type : undefined; }); - var syntheticArgsSymbol = createSymbol(3, "args"); + var syntheticArgsSymbol = createSymbol(3 /* Variable */, "args"); syntheticArgsSymbol.type = lastParamVariadicType ? createArrayType(getTypeFromTypeNode(lastParamVariadicType.type)) : anyArrayType; syntheticArgsSymbol.isRestParameter = true; if (lastParamVariadicType) { + // Replace the last parameter with a rest parameter. parameters.pop(); } parameters.push(syntheticArgsSymbol); @@ -30961,7 +35862,7 @@ var ts; } function getSignatureReturnTypeFromDeclaration(declaration, isJSConstructSignature, classType) { if (isJSConstructSignature) { - return getTypeFromTypeNode(declaration.parameters[0].type); + return getTypeFromTypeNode(declaration.parameters[0].type); // TODO: GH#18217 } else if (classType) { return classType; @@ -30970,8 +35871,10 @@ var ts; if (typeNode) { return getTypeFromTypeNode(typeNode); } - if (declaration.kind === 156 && !hasNonBindableDynamicName(declaration)) { - var setter = ts.getDeclarationOfKind(getSymbolOfNode(declaration), 157); + // TypeScript 1.0 spec (April 2014): + // If only one accessor includes a type annotation, the other behaves as if it had the same type annotation. + if (declaration.kind === 156 /* GetAccessor */ && !hasNonBindableDynamicName(declaration)) { + var setter = ts.getDeclarationOfKind(getSymbolOfNode(declaration), 157 /* SetAccessor */); return getAnnotatedAccessorType(setter); } if (ts.nodeIsMissing(declaration.body)) { @@ -30981,7 +35884,7 @@ var ts; function containsArgumentsReference(declaration) { var links = getNodeLinks(declaration); if (links.containsArgumentsReference === undefined) { - if (links.flags & 8192) { + if (links.flags & 8192 /* CaptureArguments */) { links.containsArgumentsReference = true; } else { @@ -30993,13 +35896,13 @@ var ts; if (!node) return false; switch (node.kind) { - case 71: + case 71 /* Identifier */: return node.escapedText === "arguments" && ts.isExpressionNode(node); - case 152: - case 154: - case 156: - case 157: - return node.name.kind === 147 + case 152 /* PropertyDeclaration */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + return node.name.kind === 147 /* ComputedPropertyName */ && traverse(node.name); default: return !ts.nodeStartsNewLexicalEnvironment(node) && !ts.isPartOfTypeNode(node) && !!ts.forEachChild(node, traverse); @@ -31014,6 +35917,9 @@ var ts; var decl = symbol.declarations[i]; if (!ts.isFunctionLike(decl)) continue; + // Don't include signature if node is the implementation of an overloaded function. A node is considered + // an implementation node if it has a body and the previous node is of the same kind and immediately + // precedes the implementation node (i.e. has the same parent and ends where the implementation starts). if (i > 0 && decl.body) { var previous = symbol.declarations[i - 1]; if (decl.parent === previous.parent && decl.kind === previous.kind && decl.pos === previous.end) { @@ -31053,7 +35959,7 @@ var ts; } else { var declaration = signature.declaration; - signature.resolvedTypePredicate = declaration && declaration.type && declaration.type.kind === 161 ? + signature.resolvedTypePredicate = declaration && declaration.type && declaration.type.kind === 161 /* TypePredicate */ ? createTypePredicateFromTypePredicateNode(declaration.type) : noTypePredicate; } @@ -31063,7 +35969,7 @@ var ts; } function getReturnTypeOfSignature(signature) { if (!signature.resolvedReturnType) { - if (!pushTypeResolution(signature, 3)) { + if (!pushTypeResolution(signature, 3 /* ResolvedReturnType */)) { return errorType; } var type = void 0; @@ -31071,7 +35977,7 @@ var ts; type = instantiateType(getReturnTypeOfSignature(signature.target), signature.mapper); } else if (signature.unionSignatures) { - type = getUnionType(ts.map(signature.unionSignatures, getReturnTypeOfSignature), 2); + type = getUnionType(ts.map(signature.unionSignatures, getReturnTypeOfSignature), 2 /* Subtype */); } else { type = getReturnTypeFromBody(signature.declaration); @@ -31094,12 +36000,12 @@ var ts; return signature.resolvedReturnType; } function isResolvingReturnTypeOfSignature(signature) { - return !signature.resolvedReturnType && findResolutionCycleStartIndex(signature, 3) >= 0; + return !signature.resolvedReturnType && findResolutionCycleStartIndex(signature, 3 /* ResolvedReturnType */) >= 0; } function getRestTypeOfSignature(signature) { if (signature.hasRestParameter) { var type = getTypeOfSymbol(ts.last(signature.parameters)); - if (ts.getObjectFlags(type) & 4 && type.target === globalArrayType) { + if (ts.getObjectFlags(type) & 4 /* Reference */ && type.target === globalArrayType) { return type.typeArguments[0]; } } @@ -31116,7 +36022,7 @@ var ts; return instantiation; } function createSignatureInstantiation(signature, typeArguments) { - return instantiateSignature(signature, createSignatureTypeMapper(signature, typeArguments), true); + return instantiateSignature(signature, createSignatureTypeMapper(signature, typeArguments), /*eraseTypeParameters*/ true); } function createSignatureTypeMapper(signature, typeArguments) { return createTypeMapper(signature.typeParameters, typeArguments); @@ -31127,7 +36033,8 @@ var ts; signature; } function createErasedSignature(signature) { - return instantiateSignature(signature, createTypeEraser(signature.typeParameters), true); + // Create an instantiation of the signature where all type arguments are the any type. + return instantiateSignature(signature, createTypeEraser(signature.typeParameters), /*eraseTypeParameters*/ true); } function getCanonicalSignature(signature) { return signature.typeParameters ? @@ -31135,6 +36042,12 @@ var ts; signature; } function createCanonicalSignature(signature) { + // Create an instantiation of the signature where each unconstrained type parameter is replaced with + // its original. When a generic class or interface is instantiated, each generic method in the class or + // interface is instantiated with a fresh set of cloned type parameters (which we need to handle scenarios + // where different generations of the same type parameter are in scope). This leads to a lot of new type + // identities, and potentially a lot of work comparing those identities, so here we create an instantiation + // that uses the original type identities for all unconstrained type parameters. return getSignatureInstantiation(signature, ts.map(signature.typeParameters, function (tp) { return tp.target && !getConstraintOfTypeParameter(tp.target) ? tp.target : tp; }), ts.isInJavaScriptFile(signature.declaration)); } function getBaseSignature(signature) { @@ -31142,14 +36055,18 @@ var ts; if (typeParameters) { var typeEraser_1 = createTypeEraser(typeParameters); var baseConstraints = ts.map(typeParameters, function (tp) { return instantiateType(getBaseConstraintOfType(tp), typeEraser_1) || emptyObjectType; }); - return instantiateSignature(signature, createTypeMapper(typeParameters, baseConstraints), true); + return instantiateSignature(signature, createTypeMapper(typeParameters, baseConstraints), /*eraseTypeParameters*/ true); } return signature; } function getOrCreateTypeFromSignature(signature) { + // There are two ways to declare a construct signature, one is by declaring a class constructor + // using the constructor keyword, and the other is declaring a bare construct signature in an + // object type literal or interface (using the new keyword). Each way of declaring a constructor + // will result in a different declaration kind. if (!signature.isolatedSignatureType) { - var isConstructor = signature.declaration.kind === 155 || signature.declaration.kind === 159; - var type = createObjectType(16); + var isConstructor = signature.declaration.kind === 155 /* Constructor */ || signature.declaration.kind === 159 /* ConstructSignature */; // TODO: GH#18217 + var type = createObjectType(16 /* Anonymous */); type.members = emptySymbols; type.properties = ts.emptyArray; type.callSignatures = !isConstructor ? [signature] : ts.emptyArray; @@ -31159,10 +36076,10 @@ var ts; return signature.isolatedSignatureType; } function getIndexSymbol(symbol) { - return symbol.members.get("__index"); + return symbol.members.get("__index" /* Index */); } function getIndexDeclarationOfSymbol(symbol, kind) { - var syntaxKind = kind === 1 ? 134 : 137; + var syntaxKind = kind === 1 /* Number */ ? 134 /* NumberKeyword */ : 137 /* StringKeyword */; var indexSymbol = getIndexSymbol(symbol); if (indexSymbol) { for (var _i = 0, _a = indexSymbol.declarations; _i < _a.length; _i++) { @@ -31184,12 +36101,12 @@ var ts; function getIndexInfoOfSymbol(symbol, kind) { var declaration = getIndexDeclarationOfSymbol(symbol, kind); if (declaration) { - return createIndexInfo(declaration.type ? getTypeFromTypeNode(declaration.type) : anyType, ts.hasModifier(declaration, 64), declaration); + return createIndexInfo(declaration.type ? getTypeFromTypeNode(declaration.type) : anyType, ts.hasModifier(declaration, 64 /* Readonly */), declaration); } return undefined; } function getConstraintDeclaration(type) { - var decl = type.symbol && ts.getDeclarationOfKind(type.symbol, 148); + var decl = type.symbol && ts.getDeclarationOfKind(type.symbol, 148 /* TypeParameter */); return decl && decl.constraint; } function getInferredTypeParameterConstraint(typeParameter) { @@ -31197,7 +36114,11 @@ var ts; if (typeParameter.symbol) { for (var _i = 0, _a = typeParameter.symbol.declarations; _i < _a.length; _i++) { var declaration = _a[_i]; - if (declaration.parent.kind === 172 && declaration.parent.parent.kind === 162) { + // When an 'infer T' declaration is immediately contained in a type reference node + // (such as 'Foo'), T's constraint is inferred from the constraint of the + // corresponding type parameter in 'Foo'. When multiple 'infer T' declarations are + // present, we form an intersection of the inferred constraint types. + if (declaration.parent.kind === 172 /* InferType */ && declaration.parent.parent.kind === 162 /* TypeReference */) { var typeReference = declaration.parent.parent; var typeParameters = getTypeParametersForTypeReference(typeReference); if (typeParameters) { @@ -31205,6 +36126,12 @@ var ts; if (index < typeParameters.length) { var declaredConstraint = getConstraintOfTypeParameter(typeParameters[index]); if (declaredConstraint) { + // Type parameter constraints can reference other type parameters so + // constraints need to be instantiated. If instantiation produces the + // type parameter itself, we discard that inference. For example, in + // type Foo = [T, U]; + // type Bar = T extends Foo ? Foo : T; + // the instantiated constraint for U is X, so we discard that inference. var mapper = createTypeMapper(typeParameters, getEffectiveTypeArguments(typeReference, typeParameters)); var constraint = instantiateType(declaredConstraint, mapper); if (constraint !== typeParameter) { @@ -31233,7 +36160,7 @@ var ts; return typeParameter.constraint === noConstraintType ? undefined : typeParameter.constraint; } function getParentSymbolOfTypeParameter(typeParameter) { - return getSymbolOfNode(ts.getDeclarationOfKind(typeParameter.symbol, 148).parent); + return getSymbolOfNode(ts.getDeclarationOfKind(typeParameter.symbol, 148 /* TypeParameter */).parent); } function getTypeListId(types) { var result = ""; @@ -31258,6 +36185,10 @@ var ts; } return result; } + // This function is used to propagate certain flags when creating new object type references and union types. + // It is only necessary to do so if a constituent type might be the undefined type, the null type, the type + // of an object literal or the anyFunctionType. This is because there are operations in the type checker + // that care about the presence of such types at arbitrary depth in a containing type. function getPropagatingFlagsOfTypes(types, excludeKinds) { var result = 0; for (var _i = 0, types_5 = types; _i < types_5.length; _i++) { @@ -31266,15 +36197,15 @@ var ts; result |= type.flags; } } - return result & 939524096; + return result & 939524096 /* PropagatingFlags */; } function createTypeReference(target, typeArguments) { var id = getTypeListId(typeArguments); var type = target.instantiations.get(id); if (!type) { - type = createObjectType(4, target.symbol); + type = createObjectType(4 /* Reference */, target.symbol); target.instantiations.set(id, type); - type.flags |= typeArguments ? getPropagatingFlagsOfTypes(typeArguments, 0) : 0; + type.flags |= typeArguments ? getPropagatingFlagsOfTypes(typeArguments, /*excludeKinds*/ 0) : 0; type.target = target; type.typeArguments = typeArguments; } @@ -31291,6 +36222,9 @@ var ts; function getTypeReferenceArity(type) { return ts.length(type.target.typeParameters); } + /** + * Get type from type-reference that reference to class or interface + */ function getTypeFromClassOrInterfaceReference(node, symbol, typeArgs) { var type = getDeclaredTypeOfSymbol(getMergedSymbol(symbol)); var typeParameters = type.localTypeParameters; @@ -31300,7 +36234,7 @@ var ts; var isJs = ts.isInJavaScriptFile(node); var isJsImplicitAny = !noImplicitAny && isJs; if (!isJsImplicitAny && (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length)) { - var missingAugmentsTag = isJs && node.parent.kind !== 290; + var missingAugmentsTag = isJs && node.parent.kind !== 290 /* JSDocAugmentsTag */; var diag = minTypeArgumentCount === typeParameters.length ? missingAugmentsTag ? ts.Diagnostics.Expected_0_type_arguments_provide_these_with_an_extends_tag @@ -31308,12 +36242,16 @@ var ts; : missingAugmentsTag ? ts.Diagnostics.Expected_0_1_type_arguments_provide_these_with_an_extends_tag : ts.Diagnostics.Generic_type_0_requires_between_1_and_2_type_arguments; - var typeStr = typeToString(type, undefined, 2); + var typeStr = typeToString(type, /*enclosingDeclaration*/ undefined, 2 /* WriteArrayAsGenericType */); error(node, diag, typeStr, minTypeArgumentCount, typeParameters.length); if (!isJs) { + // TODO: Adopt same permissive behavior in TS as in JS to reduce follow-on editing experience failures (requires editing fillMissingTypeArguments) return errorType; } } + // In a type reference, the outer type parameters of the referenced class or interface are automatically + // supplied as type arguments and the type reference only specifies arguments for the local type parameters + // of the class or interface. var typeArguments = ts.concatenate(type.outerTypeParameters, fillMissingTypeArguments(typeArgs, typeParameters, minTypeArgumentCount, isJs)); return createTypeReference(type, typeArguments); } @@ -31330,6 +36268,11 @@ var ts; } return instantiation; } + /** + * Get type from reference to type alias. When a type alias is generic, the declared type of the type alias may include + * references to the type parameters of the alias. We replace those with the actual type arguments by instantiating the + * declared type. Instantiations are cached using the type identities of the type arguments as the key. + */ function getTypeFromTypeAliasReference(node, symbol, typeArguments) { var type = getDeclaredTypeOfSymbol(symbol); var typeParameters = getSymbolLinks(symbol).typeParameters; @@ -31348,13 +36291,16 @@ var ts; } function getTypeReferenceName(node) { switch (node.kind) { - case 162: + case 162 /* TypeReference */: return node.typeName; - case 207: + case 207 /* ExpressionWithTypeArguments */: + // We only support expressions that are simple qualified names. For other + // expressions this produces undefined. var expr = node.expression; if (ts.isEntityNameExpression(expr)) { return expr; } + // fall through; } return undefined; } @@ -31365,7 +36311,7 @@ var ts; return resolveEntityName(typeReferenceName, meaning) || unknownSymbol; } function getTypeReferenceType(node, symbol) { - var typeArguments = typeArgumentsFromTypeReferenceNode(node); + var typeArguments = typeArgumentsFromTypeReferenceNode(node); // Do unconditionally so we mark type arguments as referenced. if (symbol === unknownSymbol) { return errorType; } @@ -31373,32 +36319,40 @@ var ts; if (type) { return type; } + // Get type from reference to named type that cannot be generic (enum or type parameter) var res = tryGetDeclaredTypeOfSymbol(symbol); if (res) { return checkNoTypeArguments(node, symbol) ? - res.flags & 65536 ? getConstrainedTypeVariable(res, node) : res : + res.flags & 65536 /* TypeParameter */ ? getConstrainedTypeVariable(res, node) : res : errorType; } - if (!(symbol.flags & 67216319 && isJSDocTypeReference(node))) { + if (!(symbol.flags & 67216319 /* Value */ && isJSDocTypeReference(node))) { return errorType; } var jsdocType = getJSDocTypeReference(node, symbol, typeArguments); if (jsdocType) { return jsdocType; } - resolveTypeReferenceName(getTypeReferenceName(node), 67901928); + // Resolve the type reference as a Type for the purpose of reporting errors. + resolveTypeReferenceName(getTypeReferenceName(node), 67901928 /* Type */); return getTypeOfSymbol(symbol); } + /** + * A jsdoc TypeReference may have resolved to a value (as opposed to a type). If + * the symbol is a constructor function, return the inferred class type; otherwise, + * the type of this reference is just the type of the value we resolved to. + */ function getJSDocTypeReference(node, symbol, typeArguments) { var assignedType = getAssignedClassType(symbol); var valueType = getTypeOfSymbol(symbol); var referenceType = valueType.symbol && valueType.symbol !== symbol && !isInferredClassType(valueType) && getTypeReferenceTypeWorker(node, valueType.symbol, typeArguments); if (referenceType || assignedType) { + // TODO: GH#18217 (should the `|| assignedType` be at a lower precedence?) return (referenceType && assignedType ? getIntersectionType([assignedType, referenceType]) : referenceType || assignedType); } } function getTypeReferenceTypeWorker(node, symbol, typeArguments) { - if (symbol.flags & (32 | 64)) { + if (symbol.flags & (32 /* Class */ | 64 /* Interface */)) { if (symbol.valueDeclaration && ts.isBinaryExpression(symbol.valueDeclaration.parent)) { var jsdocType = getJSDocTypeReference(node, symbol, typeArguments); if (jsdocType) { @@ -31407,23 +36361,23 @@ var ts; } return getTypeFromClassOrInterfaceReference(node, symbol, typeArguments); } - if (symbol.flags & 524288) { + if (symbol.flags & 524288 /* TypeAlias */) { return getTypeFromTypeAliasReference(node, symbol, typeArguments); } - if (symbol.flags & 16 && + if (symbol.flags & 16 /* Function */ && isJSDocTypeReference(node) && (symbol.members || ts.getJSDocClassTag(symbol.valueDeclaration))) { return getInferredClassType(symbol); } } function getSubstitutionType(typeVariable, substitute) { - var result = createType(8388608); + var result = createType(8388608 /* Substitution */); result.typeVariable = typeVariable; result.substitute = substitute; return result; } function isUnaryTupleTypeNode(node) { - return node.kind === 168 && node.elementTypes.length === 1; + return node.kind === 168 /* TupleType */ && node.elementTypes.length === 1; } function getImpliedConstraint(typeVariable, checkNode, extendsNode) { return isUnaryTupleTypeNode(checkNode) && isUnaryTupleTypeNode(extendsNode) ? getImpliedConstraint(typeVariable, checkNode.elementTypes[0], extendsNode.elementTypes[0]) : @@ -31432,9 +36386,9 @@ var ts; } function getConstrainedTypeVariable(typeVariable, node) { var constraints; - while (node && !ts.isStatement(node) && node.kind !== 286) { + while (node && !ts.isStatement(node) && node.kind !== 286 /* JSDocComment */) { var parent = node.parent; - if (parent.kind === 171 && node === parent.trueType) { + if (parent.kind === 171 /* ConditionalType */ && node === parent.trueType) { var constraint = getImpliedConstraint(typeVariable, parent.checkType, parent.extendsType); if (constraint) { constraints = ts.append(constraints, constraint); @@ -31445,7 +36399,7 @@ var ts; return constraints ? getSubstitutionType(typeVariable, getIntersectionType(ts.append(constraints, typeVariable))) : typeVariable; } function isJSDocTypeReference(node) { - return !!(node.flags & 2097152) && node.kind === 162; + return !!(node.flags & 2097152 /* JSDoc */) && node.kind === 162 /* TypeReference */; } function checkNoTypeArguments(node, symbol) { if (node.typeArguments) { @@ -31491,7 +36445,7 @@ var ts; if (ts.isJSDocIndexSignature(node)) { var indexed = getTypeFromTypeNode(typeArgs[0]); var target = getTypeFromTypeNode(typeArgs[1]); - var index = createIndexInfo(target, false); + var index = createIndexInfo(target, /*isReadonly*/ false); return createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, indexed === stringType ? index : undefined, indexed === numberType ? index : undefined); } return anyType; @@ -31503,22 +36457,24 @@ var ts; } function getTypeFromJSDocNullableTypeNode(node) { var type = getTypeFromTypeNode(node.type); - return strictNullChecks ? getNullableType(type, 16384) : type; + return strictNullChecks ? getNullableType(type, 16384 /* Null */) : type; } function getTypeFromTypeReference(node) { var links = getNodeLinks(node); if (!links.resolvedType) { var symbol = void 0; var type = void 0; - var meaning = 67901928; + var meaning = 67901928 /* Type */; if (isJSDocTypeReference(node)) { type = getIntendedTypeFromJSDocTypeReference(node); - meaning |= 67216319; + meaning |= 67216319 /* Value */; } if (!type) { symbol = resolveTypeReferenceName(getTypeReferenceName(node), meaning); type = getTypeReferenceType(node, symbol); } + // Cache both the resolved symbol and the resolved type. The resolved symbol is needed in when we check the + // type reference in checkTypeReferenceNode. links.resolvedSymbol = symbol; links.resolvedType = type; } @@ -31530,6 +36486,10 @@ var ts; function getTypeFromTypeQueryNode(node) { var links = getNodeLinks(node); if (!links.resolvedType) { + // TypeScript 1.0 spec (April 2014): 3.6.3 + // The expression is processed as an identifier expression (section 4.3) + // or property access expression(section 4.10), + // the widened type(section 3.9) of which becomes the result. links.resolvedType = getWidenedType(checkExpression(node.exprName)); } return links.resolvedType; @@ -31540,9 +36500,9 @@ var ts; for (var _i = 0, declarations_3 = declarations; _i < declarations_3.length; _i++) { var declaration = declarations_3[_i]; switch (declaration.kind) { - case 235: - case 236: - case 238: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + case 238 /* EnumDeclaration */: return declaration; } } @@ -31551,7 +36511,7 @@ var ts; return arity ? emptyGenericType : emptyObjectType; } var type = getDeclaredTypeOfSymbol(symbol); - if (!(type.flags & 131072)) { + if (!(type.flags & 131072 /* Object */)) { error(getTypeDeclaration(symbol), ts.Diagnostics.Global_type_0_must_be_a_class_or_interface_type, ts.symbolName(symbol)); return arity ? emptyGenericType : emptyObjectType; } @@ -31562,68 +36522,72 @@ var ts; return type; } function getGlobalValueSymbol(name, reportErrors) { - return getGlobalSymbol(name, 67216319, reportErrors ? ts.Diagnostics.Cannot_find_global_value_0 : undefined); + return getGlobalSymbol(name, 67216319 /* Value */, reportErrors ? ts.Diagnostics.Cannot_find_global_value_0 : undefined); } function getGlobalTypeSymbol(name, reportErrors) { - return getGlobalSymbol(name, 67901928, reportErrors ? ts.Diagnostics.Cannot_find_global_type_0 : undefined); + return getGlobalSymbol(name, 67901928 /* Type */, reportErrors ? ts.Diagnostics.Cannot_find_global_type_0 : undefined); } function getGlobalSymbol(name, meaning, diagnostic) { - return resolveName(undefined, name, meaning, diagnostic, name, false); + // Don't track references for global symbols anyway, so value if `isReference` is arbitrary + return resolveName(undefined, name, meaning, diagnostic, name, /*isUse*/ false); } function getGlobalType(name, arity, reportErrors) { var symbol = getGlobalTypeSymbol(name, reportErrors); return symbol || reportErrors ? getTypeOfGlobalSymbol(symbol, arity) : undefined; } function getGlobalTypedPropertyDescriptorType() { - return deferredGlobalTypedPropertyDescriptorType || (deferredGlobalTypedPropertyDescriptorType = getGlobalType("TypedPropertyDescriptor", 1, true)) || emptyGenericType; + return deferredGlobalTypedPropertyDescriptorType || (deferredGlobalTypedPropertyDescriptorType = getGlobalType("TypedPropertyDescriptor", /*arity*/ 1, /*reportErrors*/ true)) || emptyGenericType; } function getGlobalTemplateStringsArrayType() { - return deferredGlobalTemplateStringsArrayType || (deferredGlobalTemplateStringsArrayType = getGlobalType("TemplateStringsArray", 0, true)) || emptyObjectType; + return deferredGlobalTemplateStringsArrayType || (deferredGlobalTemplateStringsArrayType = getGlobalType("TemplateStringsArray", /*arity*/ 0, /*reportErrors*/ true)) || emptyObjectType; } function getGlobalImportMetaType() { - return deferredGlobalImportMetaType || (deferredGlobalImportMetaType = getGlobalType("ImportMeta", 0, true)) || emptyObjectType; + return deferredGlobalImportMetaType || (deferredGlobalImportMetaType = getGlobalType("ImportMeta", /*arity*/ 0, /*reportErrors*/ true)) || emptyObjectType; } function getGlobalESSymbolConstructorSymbol(reportErrors) { return deferredGlobalESSymbolConstructorSymbol || (deferredGlobalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol", reportErrors)); } function getGlobalESSymbolType(reportErrors) { - return deferredGlobalESSymbolType || (deferredGlobalESSymbolType = getGlobalType("Symbol", 0, reportErrors)) || emptyObjectType; + return deferredGlobalESSymbolType || (deferredGlobalESSymbolType = getGlobalType("Symbol", /*arity*/ 0, reportErrors)) || emptyObjectType; } function getGlobalPromiseType(reportErrors) { - return deferredGlobalPromiseType || (deferredGlobalPromiseType = getGlobalType("Promise", 1, reportErrors)) || emptyGenericType; + return deferredGlobalPromiseType || (deferredGlobalPromiseType = getGlobalType("Promise", /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalPromiseConstructorSymbol(reportErrors) { return deferredGlobalPromiseConstructorSymbol || (deferredGlobalPromiseConstructorSymbol = getGlobalValueSymbol("Promise", reportErrors)); } function getGlobalPromiseConstructorLikeType(reportErrors) { - return deferredGlobalPromiseConstructorLikeType || (deferredGlobalPromiseConstructorLikeType = getGlobalType("PromiseConstructorLike", 0, reportErrors)) || emptyObjectType; + return deferredGlobalPromiseConstructorLikeType || (deferredGlobalPromiseConstructorLikeType = getGlobalType("PromiseConstructorLike", /*arity*/ 0, reportErrors)) || emptyObjectType; } function getGlobalAsyncIterableType(reportErrors) { - return deferredGlobalAsyncIterableType || (deferredGlobalAsyncIterableType = getGlobalType("AsyncIterable", 1, reportErrors)) || emptyGenericType; + return deferredGlobalAsyncIterableType || (deferredGlobalAsyncIterableType = getGlobalType("AsyncIterable", /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalAsyncIteratorType(reportErrors) { - return deferredGlobalAsyncIteratorType || (deferredGlobalAsyncIteratorType = getGlobalType("AsyncIterator", 1, reportErrors)) || emptyGenericType; + return deferredGlobalAsyncIteratorType || (deferredGlobalAsyncIteratorType = getGlobalType("AsyncIterator", /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalAsyncIterableIteratorType(reportErrors) { - return deferredGlobalAsyncIterableIteratorType || (deferredGlobalAsyncIterableIteratorType = getGlobalType("AsyncIterableIterator", 1, reportErrors)) || emptyGenericType; + return deferredGlobalAsyncIterableIteratorType || (deferredGlobalAsyncIterableIteratorType = getGlobalType("AsyncIterableIterator", /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalIterableType(reportErrors) { - return deferredGlobalIterableType || (deferredGlobalIterableType = getGlobalType("Iterable", 1, reportErrors)) || emptyGenericType; + return deferredGlobalIterableType || (deferredGlobalIterableType = getGlobalType("Iterable", /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalIteratorType(reportErrors) { - return deferredGlobalIteratorType || (deferredGlobalIteratorType = getGlobalType("Iterator", 1, reportErrors)) || emptyGenericType; + return deferredGlobalIteratorType || (deferredGlobalIteratorType = getGlobalType("Iterator", /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalIterableIteratorType(reportErrors) { - return deferredGlobalIterableIteratorType || (deferredGlobalIterableIteratorType = getGlobalType("IterableIterator", 1, reportErrors)) || emptyGenericType; + return deferredGlobalIterableIteratorType || (deferredGlobalIterableIteratorType = getGlobalType("IterableIterator", /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalTypeOrUndefined(name, arity) { if (arity === void 0) { arity = 0; } - var symbol = getGlobalSymbol(name, 67901928, undefined); + var symbol = getGlobalSymbol(name, 67901928 /* Type */, /*diagnostic*/ undefined); return symbol && getTypeOfGlobalSymbol(symbol, arity); } function getGlobalExtractSymbol() { - return deferredGlobalExtractSymbol || (deferredGlobalExtractSymbol = getGlobalSymbol("Extract", 524288, ts.Diagnostics.Cannot_find_global_type_0)); + return deferredGlobalExtractSymbol || (deferredGlobalExtractSymbol = getGlobalSymbol("Extract", 524288 /* TypeAlias */, ts.Diagnostics.Cannot_find_global_type_0)); // TODO: GH#18217 } + /** + * Instantiates a global type that is generic with some element type, and returns that instantiation. + */ function createTypeFromGenericGlobalType(genericGlobalType, typeArguments) { return genericGlobalType !== emptyGenericType ? createTypeReference(genericGlobalType, typeArguments) : emptyObjectType; } @@ -31631,16 +36595,16 @@ var ts; return createTypeFromGenericGlobalType(getGlobalTypedPropertyDescriptorType(), [propertyType]); } function createAsyncIterableType(iteratedType) { - return createTypeFromGenericGlobalType(getGlobalAsyncIterableType(true), [iteratedType]); + return createTypeFromGenericGlobalType(getGlobalAsyncIterableType(/*reportErrors*/ true), [iteratedType]); } function createAsyncIterableIteratorType(iteratedType) { - return createTypeFromGenericGlobalType(getGlobalAsyncIterableIteratorType(true), [iteratedType]); + return createTypeFromGenericGlobalType(getGlobalAsyncIterableIteratorType(/*reportErrors*/ true), [iteratedType]); } function createIterableType(iteratedType) { - return createTypeFromGenericGlobalType(getGlobalIterableType(true), [iteratedType]); + return createTypeFromGenericGlobalType(getGlobalIterableType(/*reportErrors*/ true), [iteratedType]); } function createIterableIteratorType(iteratedType) { - return createTypeFromGenericGlobalType(getGlobalIterableIteratorType(true), [iteratedType]); + return createTypeFromGenericGlobalType(getGlobalIterableIteratorType(/*reportErrors*/ true), [iteratedType]); } function createArrayType(elementType) { return createTypeFromGenericGlobalType(globalArrayType, [elementType]); @@ -31652,20 +36616,27 @@ var ts; } return links.resolvedType; } + // We represent tuple types as type references to synthesized generic interface types created by + // this function. The types are of the form: + // + // interface Tuple extends Array { 0: T0, 1: T1, 2: T2, ... } + // + // Note that the generic type created by this function has no symbol associated with it. The same + // is true for each of the synthesized type parameters. function createTupleTypeOfArity(arity) { var typeParameters = []; var properties = []; for (var i = 0; i < arity; i++) { - var typeParameter = createType(65536); + var typeParameter = createType(65536 /* TypeParameter */); typeParameters.push(typeParameter); - var property = createSymbol(4, "" + i); + var property = createSymbol(4 /* Property */, "" + i); property.type = typeParameter; properties.push(property); } - var lengthSymbol = createSymbol(4, "length"); + var lengthSymbol = createSymbol(4 /* Property */, "length"); lengthSymbol.type = getLiteralType(arity); properties.push(lengthSymbol); - var type = createObjectType(8 | 4); + var type = createObjectType(8 /* Tuple */ | 4 /* Reference */); type.typeParameters = typeParameters; type.outerTypeParameters = undefined; type.localTypeParameters = typeParameters; @@ -31673,7 +36644,7 @@ var ts; type.instantiations.set(getTypeListId(type.typeParameters), type); type.target = type; type.typeArguments = type.typeParameters; - type.thisType = createType(65536); + type.thisType = createType(65536 /* TypeParameter */); type.thisType.isThisType = true; type.thisType.constraint = type; type.declaredProperties = properties; @@ -31702,20 +36673,28 @@ var ts; function containsType(types, type) { return ts.binarySearch(types, type, getTypeId, ts.compareValues) >= 0; } + // Return true if the given intersection type contains + // more than one unit type or, + // an object type and a nullable type (null or undefined), or + // a string-like type and a type known to be non-string-like, or + // a number-like type and a type known to be non-number-like, or + // a symbol-like type and a type known to be non-symbol-like, or + // a void-like type and a type known to be non-void-like, or + // a non-primitive type and a type known to be primitive. function isEmptyIntersectionType(type) { var combined = 0; for (var _i = 0, _a = type.types; _i < _a.length; _i++) { var t = _a[_i]; - if (t.flags & 27072 && combined & 27072) { + if (t.flags & 27072 /* Unit */ && combined & 27072 /* Unit */) { return true; } combined |= t.flags; - if (combined & 24576 && combined & (131072 | 16777216) || - combined & 16777216 && combined & (16809468 & ~16777216) || - combined & 68 && combined & (16809468 & ~68) || - combined & 168 && combined & (16809468 & ~168) || - combined & 3072 && combined & (16809468 & ~3072) || - combined & 12288 && combined & (16809468 & ~12288)) { + if (combined & 24576 /* Nullable */ && combined & (131072 /* Object */ | 16777216 /* NonPrimitive */) || + combined & 16777216 /* NonPrimitive */ && combined & (16809468 /* DisjointDomains */ & ~16777216 /* NonPrimitive */) || + combined & 68 /* StringLike */ && combined & (16809468 /* DisjointDomains */ & ~68 /* StringLike */) || + combined & 168 /* NumberLike */ && combined & (16809468 /* DisjointDomains */ & ~168 /* NumberLike */) || + combined & 3072 /* ESSymbolLike */ && combined & (16809468 /* DisjointDomains */ & ~3072 /* ESSymbolLike */) || + combined & 12288 /* VoidLike */ && combined & (16809468 /* DisjointDomains */ & ~12288 /* VoidLike */)) { return true; } } @@ -31723,25 +36702,29 @@ var ts; } function addTypeToUnion(typeSet, includes, type) { var flags = type.flags; - if (flags & 262144) { + if (flags & 262144 /* Union */) { return addTypesToUnion(typeSet, includes, type.types); } - if (!(flags & 32768 || flags & 524288 && isEmptyIntersectionType(type))) { - includes |= flags & ~939524096; - if (flags & 3) { + // We ignore 'never' types in unions. Likewise, we ignore intersections of unit types as they are + // another form of 'never' (in that they have an empty value domain). We could in theory turn + // intersections of unit types into 'never' upon construction, but deferring the reduction makes it + // easier to reason about their origin. + if (!(flags & 32768 /* Never */ || flags & 524288 /* Intersection */ && isEmptyIntersectionType(type))) { + includes |= flags & ~939524096 /* ConstructionFlags */; + if (flags & 3 /* AnyOrUnknown */) { if (type === wildcardType) - includes |= 268435456; + includes |= 268435456 /* Wildcard */; } - else if (!strictNullChecks && flags & 24576) { - if (!(flags & 134217728)) - includes |= 134217728; + else if (!strictNullChecks && flags & 24576 /* Nullable */) { + if (!(flags & 134217728 /* ContainsWideningType */)) + includes |= 134217728 /* NonWideningType */; } else { var len = typeSet.length; var index = len && type.id > typeSet[len - 1].id ? ~len : ts.binarySearch(typeSet, type, getTypeId, ts.compareValues); if (index < 0) { - if (!(flags & 131072 && type.objectFlags & 16 && - type.symbol && type.symbol.flags & (16 | 8192) && containsIdenticalType(typeSet, type))) { + if (!(flags & 131072 /* Object */ && type.objectFlags & 16 /* Anonymous */ && + type.symbol && type.symbol.flags & (16 /* Function */ | 8192 /* Method */) && containsIdenticalType(typeSet, type))) { typeSet.splice(~index, 0, type); } } @@ -31749,6 +36732,8 @@ var ts; } return includes; } + // Add the given types to the given type set. Order is preserved, duplicates are removed, + // and nested types of the given kind are flattened into the set. function addTypesToUnion(typeSet, includes, types) { for (var _i = 0, types_6 = types; _i < types_6.length; _i++) { var type = types_6[_i]; @@ -31768,8 +36753,8 @@ var ts; function isSubtypeOfAny(source, targets) { for (var _i = 0, targets_1 = targets; _i < targets_1.length; _i++) { var target = targets_1[_i]; - if (source !== target && isTypeSubtypeOf(source, target) && (!(ts.getObjectFlags(getTargetType(source)) & 1) || - !(ts.getObjectFlags(getTargetType(target)) & 1) || + if (source !== target && isTypeSubtypeOf(source, target) && (!(ts.getObjectFlags(getTargetType(source)) & 1 /* Class */) || + !(ts.getObjectFlags(getTargetType(target)) & 1 /* Class */) || isTypeDerivedFrom(source, target))) { return true; } @@ -31778,11 +36763,11 @@ var ts; } function isSetOfLiteralsFromSameEnum(types) { var first = types[0]; - if (first.flags & 512) { + if (first.flags & 512 /* EnumLiteral */) { var firstEnum = getParentOfSymbol(first.symbol); for (var i = 1; i < types.length; i++) { var other = types[i]; - if (!(other.flags & 512) || (firstEnum !== getParentOfSymbol(other.symbol))) { + if (!(other.flags & 512 /* EnumLiteral */) || (firstEnum !== getParentOfSymbol(other.symbol))) { return false; } } @@ -31807,17 +36792,24 @@ var ts; while (i > 0) { i--; var t = types[i]; - var remove = t.flags & 64 && includes & 4 || - t.flags & 128 && includes & 8 || - t.flags & 2048 && includes & 1024 || - t.flags & 192 && t.flags & 33554432 && containsType(types, t.regularType); + var remove = t.flags & 64 /* StringLiteral */ && includes & 4 /* String */ || + t.flags & 128 /* NumberLiteral */ && includes & 8 /* Number */ || + t.flags & 2048 /* UniqueESSymbol */ && includes & 1024 /* ESSymbol */ || + t.flags & 192 /* StringOrNumberLiteral */ && t.flags & 33554432 /* FreshLiteral */ && containsType(types, t.regularType); if (remove) { ts.orderedRemoveItemAt(types, i); } } } + // We sort and deduplicate the constituent types based on object identity. If the subtypeReduction + // flag is specified we also reduce the constituent type set to only include types that aren't subtypes + // of other types. Subtype reduction is expensive for large union types and is possible only when union + // types are known not to circularly reference themselves (as is the case with union types created by + // expression constructs such as array literals and the || and ?: operators). Named types can + // circularly reference themselves and therefore cannot be subtype reduced during their declaration. + // For example, "type Item = string | (() => Item" is a named type that circularly references itself. function getUnionType(types, unionReduction, aliasSymbol, aliasTypeArguments) { - if (unionReduction === void 0) { unionReduction = 1; } + if (unionReduction === void 0) { unionReduction = 1 /* Literal */; } if (types.length === 0) { return neverType; } @@ -31826,25 +36818,25 @@ var ts; } var typeSet = []; var includes = addTypesToUnion(typeSet, 0, types); - if (includes & 3) { - return includes & 1 ? includes & 268435456 ? wildcardType : anyType : unknownType; + if (includes & 3 /* AnyOrUnknown */) { + return includes & 1 /* Any */ ? includes & 268435456 /* Wildcard */ ? wildcardType : anyType : unknownType; } switch (unionReduction) { - case 1: - if (includes & 2240) { + case 1 /* Literal */: + if (includes & 2240 /* StringOrNumberLiteralOrUnique */) { removeRedundantLiteralTypes(typeSet, includes); } break; - case 2: + case 2 /* Subtype */: removeSubtypes(typeSet); break; } if (typeSet.length === 0) { - return includes & 16384 ? includes & 134217728 ? nullType : nullWideningType : - includes & 8192 ? includes & 134217728 ? undefinedType : undefinedWideningType : + return includes & 16384 /* Null */ ? includes & 134217728 /* NonWideningType */ ? nullType : nullWideningType : + includes & 8192 /* Undefined */ ? includes & 134217728 /* NonWideningType */ ? undefinedType : undefinedWideningType : neverType; } - return getUnionTypeFromSortedList(typeSet, includes & 16749629 ? 0 : 67108864, aliasSymbol, aliasTypeArguments); + return getUnionTypeFromSortedList(typeSet, includes & 16749629 /* NotUnit */ ? 0 : 67108864 /* UnionOfUnitTypes */, aliasSymbol, aliasTypeArguments); } function getUnionTypePredicate(signatures) { var first; @@ -31857,6 +36849,7 @@ var ts; } if (first) { if (!typePredicateKindsMatch(first, pred)) { + // No common type predicate. return undefined; } } @@ -31866,6 +36859,7 @@ var ts; types.push(pred.type); } if (!first) { + // No union signatures had a type predicate. return undefined; } var unionType = getUnionType(types); @@ -31878,6 +36872,7 @@ var ts; ? ts.isIdentifierTypePredicate(b) && a.parameterIndex === b.parameterIndex : !ts.isIdentifierTypePredicate(b); } + // This function assumes the constituent type list is sorted and deduplicated. function getUnionTypeFromSortedList(types, unionOfUnitTypes, aliasSymbol, aliasTypeArguments) { if (types.length === 0) { return neverType; @@ -31888,10 +36883,16 @@ var ts; var id = getTypeListId(types); var type = unionTypes.get(id); if (!type) { - var propagatedFlags = getPropagatingFlagsOfTypes(types, 24576); - type = createType(262144 | propagatedFlags | unionOfUnitTypes); + var propagatedFlags = getPropagatingFlagsOfTypes(types, /*excludeKinds*/ 24576 /* Nullable */); + type = createType(262144 /* Union */ | propagatedFlags | unionOfUnitTypes); unionTypes.set(id, type); type.types = types; + /* + Note: This is the alias symbol (or lack thereof) that we see when we first encounter this union type. + For aliases of identical unions, eg `type T = A | B; type U = A | B`, the symbol of the first alias encountered is the aliasSymbol. + (In the language service, the order may depend on the order in which a user takes actions, such as hovering over symbols.) + It's important that we create equivalent union types only once, so that's an unfortunate side effect. + */ type.aliasSymbol = aliasSymbol; type.aliasTypeArguments = aliasTypeArguments; } @@ -31901,33 +36902,35 @@ var ts; var links = getNodeLinks(node); if (!links.resolvedType) { var aliasSymbol = getAliasSymbolForTypeNode(node); - links.resolvedType = getUnionType(ts.map(node.types, getTypeFromTypeNode), 1, aliasSymbol, getTypeArgumentsForAliasSymbol(aliasSymbol)); + links.resolvedType = getUnionType(ts.map(node.types, getTypeFromTypeNode), 1 /* Literal */, aliasSymbol, getTypeArgumentsForAliasSymbol(aliasSymbol)); } return links.resolvedType; } function addTypeToIntersection(typeSet, includes, type) { var flags = type.flags; - if (flags & 524288) { + if (flags & 524288 /* Intersection */) { return addTypesToIntersection(typeSet, includes, type.types); } - if (ts.getObjectFlags(type) & 16 && isEmptyObjectType(type)) { - includes |= 536870912; + if (ts.getObjectFlags(type) & 16 /* Anonymous */ && isEmptyObjectType(type)) { + includes |= 536870912 /* EmptyObject */; } else { - includes |= flags & ~939524096; - if (flags & 3) { + includes |= flags & ~939524096 /* ConstructionFlags */; + if (flags & 3 /* AnyOrUnknown */) { if (type === wildcardType) - includes |= 268435456; + includes |= 268435456 /* Wildcard */; } - else if ((strictNullChecks || !(flags & 24576)) && !ts.contains(typeSet, type) && - !(flags & 131072 && type.objectFlags & 16 && - type.symbol && type.symbol.flags & (16 | 8192) && + else if ((strictNullChecks || !(flags & 24576 /* Nullable */)) && !ts.contains(typeSet, type) && + !(flags & 131072 /* Object */ && type.objectFlags & 16 /* Anonymous */ && + type.symbol && type.symbol.flags & (16 /* Function */ | 8192 /* Method */) && containsIdenticalType(typeSet, type))) { typeSet.push(type); } } return includes; } + // Add the given types to the given type set. Order is preserved, freshness is removed from literal + // types, duplicates are removed, and nested types of the given kind are flattened into the set. function addTypesToIntersection(typeSet, includes, types) { for (var _i = 0, types_8 = types; _i < types_8.length; _i++) { var type = types_8[_i]; @@ -31940,22 +36943,25 @@ var ts; while (i > 0) { i--; var t = types[i]; - var remove = t.flags & 4 && includes & 64 || - t.flags & 8 && includes & 128 || - t.flags & 1024 && includes & 2048; + var remove = t.flags & 4 /* String */ && includes & 64 /* StringLiteral */ || + t.flags & 8 /* Number */ && includes & 128 /* NumberLiteral */ || + t.flags & 1024 /* ESSymbol */ && includes & 2048 /* UniqueESSymbol */; if (remove) { ts.orderedRemoveItemAt(types, i); } } } + // When intersecting unions of unit types we can simply intersect based on type identity. + // Here we remove all unions of unit types from the given list and replace them with a + // a single union containing an intersection of the unit types. function intersectUnionsOfUnitTypes(types) { - var unionIndex = ts.findIndex(types, function (t) { return (t.flags & 67108864) !== 0; }); + var unionIndex = ts.findIndex(types, function (t) { return (t.flags & 67108864 /* UnionOfUnitTypes */) !== 0; }); var unionType = types[unionIndex]; var intersection = unionType.types; var i = types.length - 1; var _loop_6 = function () { var t = types[i]; - if (t.flags & 67108864) { + if (t.flags & 67108864 /* UnionOfUnitTypes */) { intersection = ts.filter(intersection, function (u) { return containsType(t.types, u); }); ts.orderedRemoveItemAt(types, i); } @@ -31967,27 +36973,37 @@ var ts; if (intersection === unionType.types) { return false; } - types[unionIndex] = getUnionTypeFromSortedList(intersection, unionType.flags & 67108864); + types[unionIndex] = getUnionTypeFromSortedList(intersection, unionType.flags & 67108864 /* UnionOfUnitTypes */); return true; } + // We normalize combinations of intersection and union types based on the distributive property of the '&' + // operator. Specifically, because X & (A | B) is equivalent to X & A | X & B, we can transform intersection + // types with union type constituents into equivalent union types with intersection type constituents and + // effectively ensure that union types are always at the top level in type representations. + // + // We do not perform structural deduplication on intersection types. Intersection types are created only by the & + // type operator and we can't reduce those because we want to support recursive intersection types. For example, + // a type alias of the form "type List = T & { next: List }" cannot be reduced during its declaration. + // Also, unlike union types, the order of the constituent types is preserved in order that overload resolution + // for intersections of types with signatures can be deterministic. function getIntersectionType(types, aliasSymbol, aliasTypeArguments) { var typeSet = []; var includes = addTypesToIntersection(typeSet, 0, types); - if (includes & 32768) { + if (includes & 32768 /* Never */) { return neverType; } - if (includes & 1) { - return includes & 268435456 ? wildcardType : anyType; + if (includes & 1 /* Any */) { + return includes & 268435456 /* Wildcard */ ? wildcardType : anyType; } - if (!strictNullChecks && includes & 24576) { - return includes & 8192 ? undefinedType : nullType; + if (!strictNullChecks && includes & 24576 /* Nullable */) { + return includes & 8192 /* Undefined */ ? undefinedType : nullType; } - if (includes & 4 && includes & 64 || - includes & 8 && includes & 128 || - includes & 1024 && includes & 2048) { + if (includes & 4 /* String */ && includes & 64 /* StringLiteral */ || + includes & 8 /* Number */ && includes & 128 /* NumberLiteral */ || + includes & 1024 /* ESSymbol */ && includes & 2048 /* UniqueESSymbol */) { removeRedundantPrimitiveTypes(typeSet, includes); } - if (includes & 536870912 && !(includes & 131072)) { + if (includes & 536870912 /* EmptyObject */ && !(includes & 131072 /* Object */)) { typeSet.push(emptyObjectType); } if (typeSet.length === 0) { @@ -31996,22 +37012,27 @@ var ts; if (typeSet.length === 1) { return typeSet[0]; } - if (includes & 262144) { - if (includes & 67108864 && intersectUnionsOfUnitTypes(typeSet)) { + if (includes & 262144 /* Union */) { + if (includes & 67108864 /* UnionOfUnitTypes */ && intersectUnionsOfUnitTypes(typeSet)) { + // When the intersection creates a reduced set (which might mean that *all* union types have + // disappeared), we restart the operation to get a new set of combined flags. Once we have + // reduced we'll never reduce again, so this occurs at most once. return getIntersectionType(typeSet, aliasSymbol, aliasTypeArguments); } - var unionIndex_1 = ts.findIndex(typeSet, function (t) { return (t.flags & 262144) !== 0; }); + // We are attempting to construct a type of the form X & (A | B) & Y. Transform this into a type of + // the form X & A & Y | X & B & Y and recursively reduce until no union type constituents remain. + var unionIndex_1 = ts.findIndex(typeSet, function (t) { return (t.flags & 262144 /* Union */) !== 0; }); var unionType = typeSet[unionIndex_1]; - return getUnionType(ts.map(unionType.types, function (t) { return getIntersectionType(ts.replaceElement(typeSet, unionIndex_1, t)); }), 1, aliasSymbol, aliasTypeArguments); + return getUnionType(ts.map(unionType.types, function (t) { return getIntersectionType(ts.replaceElement(typeSet, unionIndex_1, t)); }), 1 /* Literal */, aliasSymbol, aliasTypeArguments); } var id = getTypeListId(typeSet); var type = intersectionTypes.get(id); if (!type) { - var propagatedFlags = getPropagatingFlagsOfTypes(typeSet, 24576); - type = createType(524288 | propagatedFlags); + var propagatedFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ 24576 /* Nullable */); + type = createType(524288 /* Intersection */ | propagatedFlags); intersectionTypes.set(id, type); type.types = typeSet; - type.aliasSymbol = aliasSymbol; + type.aliasSymbol = aliasSymbol; // See comment in `getUnionTypeFromSortedList`. type.aliasTypeArguments = aliasTypeArguments; } return type; @@ -32025,23 +37046,23 @@ var ts; return links.resolvedType; } function createIndexType(type, stringsOnly) { - var result = createType(1048576); + var result = createType(1048576 /* Index */); result.type = type; result.stringsOnly = stringsOnly; return result; } function getIndexTypeForGenericType(type, stringsOnly) { return stringsOnly ? - type.resolvedStringIndexType || (type.resolvedStringIndexType = createIndexType(type, true)) : - type.resolvedIndexType || (type.resolvedIndexType = createIndexType(type, false)); + type.resolvedStringIndexType || (type.resolvedStringIndexType = createIndexType(type, /*stringsOnly*/ true)) : + type.resolvedIndexType || (type.resolvedIndexType = createIndexType(type, /*stringsOnly*/ false)); } function getLiteralTypeFromPropertyName(prop, include) { - if (!(ts.getDeclarationModifierFlagsFromSymbol(prop) & 24)) { + if (!(ts.getDeclarationModifierFlagsFromSymbol(prop) & 24 /* NonPublicAccessibilityModifier */)) { var type = getLateBoundSymbol(prop).nameType; if (!type && !ts.isKnownSymbol(prop)) { var name = ts.getNameOfDeclaration(prop.valueDeclaration); type = name && ts.isNumericLiteral(name) ? getLiteralType(+name.text) : - name && name.kind === 147 && ts.isNumericLiteral(name.expression) ? getLiteralType(+name.expression.text) : + name && name.kind === 147 /* ComputedPropertyName */ && ts.isNumericLiteral(name.expression) ? getLiteralType(+name.expression.text) : getLiteralType(ts.symbolName(prop)); } if (type && type.flags & include) { @@ -32054,21 +37075,21 @@ var ts; return getUnionType(ts.map(getPropertiesOfType(type), function (t) { return getLiteralTypeFromPropertyName(t, include); })); } function getNonEnumNumberIndexInfo(type) { - var numberIndexInfo = getIndexInfoOfType(type, 1); + var numberIndexInfo = getIndexInfoOfType(type, 1 /* Number */); return numberIndexInfo !== enumNumberIndexInfo ? numberIndexInfo : undefined; } function getIndexType(type, stringsOnly) { if (stringsOnly === void 0) { stringsOnly = keyofStringsOnly; } - return type.flags & 262144 ? getIntersectionType(ts.map(type.types, function (t) { return getIndexType(t, stringsOnly); })) : - type.flags & 524288 ? getUnionType(ts.map(type.types, function (t) { return getIndexType(t, stringsOnly); })) : - maybeTypeOfKind(type, 14745600) ? getIndexTypeForGenericType(type, stringsOnly) : - ts.getObjectFlags(type) & 32 ? getConstraintTypeFromMappedType(type) : + return type.flags & 262144 /* Union */ ? getIntersectionType(ts.map(type.types, function (t) { return getIndexType(t, stringsOnly); })) : + type.flags & 524288 /* Intersection */ ? getUnionType(ts.map(type.types, function (t) { return getIndexType(t, stringsOnly); })) : + maybeTypeOfKind(type, 14745600 /* InstantiableNonPrimitive */) ? getIndexTypeForGenericType(type, stringsOnly) : + ts.getObjectFlags(type) & 32 /* Mapped */ ? getConstraintTypeFromMappedType(type) : type === wildcardType ? wildcardType : - type.flags & 1 ? keyofConstraintType : - stringsOnly ? getIndexInfoOfType(type, 0) ? stringType : getLiteralTypeFromPropertyNames(type, 64) : - getIndexInfoOfType(type, 0) ? getUnionType([stringType, numberType, getLiteralTypeFromPropertyNames(type, 2048)]) : - getNonEnumNumberIndexInfo(type) ? getUnionType([numberType, getLiteralTypeFromPropertyNames(type, 64 | 2048)]) : - getLiteralTypeFromPropertyNames(type, 2240); + type.flags & 1 /* Any */ ? keyofConstraintType : + stringsOnly ? getIndexInfoOfType(type, 0 /* String */) ? stringType : getLiteralTypeFromPropertyNames(type, 64 /* StringLiteral */) : + getIndexInfoOfType(type, 0 /* String */) ? getUnionType([stringType, numberType, getLiteralTypeFromPropertyNames(type, 2048 /* UniqueESSymbol */)]) : + getNonEnumNumberIndexInfo(type) ? getUnionType([numberType, getLiteralTypeFromPropertyNames(type, 64 /* StringLiteral */ | 2048 /* UniqueESSymbol */)]) : + getLiteralTypeFromPropertyNames(type, 2240 /* StringOrNumberLiteralOrUnique */); } function getExtractStringType(type) { if (keyofStringsOnly) { @@ -32079,41 +37100,41 @@ var ts; } function getIndexTypeOrString(type) { var indexType = getExtractStringType(getIndexType(type)); - return indexType.flags & 32768 ? stringType : indexType; + return indexType.flags & 32768 /* Never */ ? stringType : indexType; } function getTypeFromTypeOperatorNode(node) { var links = getNodeLinks(node); if (!links.resolvedType) { switch (node.operator) { - case 128: + case 128 /* KeyOfKeyword */: links.resolvedType = getIndexType(getTypeFromTypeNode(node.type)); break; - case 141: - links.resolvedType = node.type.kind === 138 + case 141 /* UniqueKeyword */: + links.resolvedType = node.type.kind === 138 /* SymbolKeyword */ ? getESSymbolLikeTypeForNode(ts.walkUpParenthesizedTypes(node.parent)) : errorType; break; } } - return links.resolvedType; + return links.resolvedType; // TODO: GH#18217 } function createIndexedAccessType(objectType, indexType) { - var type = createType(2097152); + var type = createType(2097152 /* IndexedAccess */); type.objectType = objectType; type.indexType = indexType; return type; } function getPropertyTypeForIndexType(objectType, indexType, accessNode, cacheSymbol) { - var accessExpression = accessNode && accessNode.kind === 186 ? accessNode : undefined; + var accessExpression = accessNode && accessNode.kind === 186 /* ElementAccessExpression */ ? accessNode : undefined; var propName = isTypeUsableAsLateBoundName(indexType) ? getLateBoundNameFromType(indexType) : - accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression, indexType, false) ? + accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression, indexType, /*reportError*/ false) ? ts.getPropertyNameForKnownSymbolName(ts.idText(accessExpression.argumentExpression.name)) : undefined; if (propName !== undefined) { var prop = getPropertyOfType(objectType, propName); if (prop) { if (accessExpression) { - markPropertyAsReferenced(prop, accessExpression, accessExpression.expression.kind === 99); + markPropertyAsReferenced(prop, accessExpression, /*isThisAccess*/ accessExpression.expression.kind === 99 /* ThisKeyword */); if (ts.isAssignmentTarget(accessExpression) && (isReferenceToReadonlyEntity(accessExpression, prop) || isReferenceThroughNamespaceImport(accessExpression))) { error(accessExpression.argumentExpression, ts.Diagnostics.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, symbolToString(prop)); return errorType; @@ -32125,16 +37146,16 @@ var ts; return getTypeOfSymbol(prop); } } - if (!(indexType.flags & 24576) && isTypeAssignableToKind(indexType, 68 | 168 | 3072)) { + if (!(indexType.flags & 24576 /* Nullable */) && isTypeAssignableToKind(indexType, 68 /* StringLike */ | 168 /* NumberLike */ | 3072 /* ESSymbolLike */)) { if (isTypeAny(objectType)) { return objectType; } - var indexInfo = isTypeAssignableToKind(indexType, 168) && getIndexInfoOfType(objectType, 1) || - getIndexInfoOfType(objectType, 0) || + var indexInfo = isTypeAssignableToKind(indexType, 168 /* NumberLike */) && getIndexInfoOfType(objectType, 1 /* Number */) || + getIndexInfoOfType(objectType, 0 /* String */) || undefined; if (indexInfo) { - if (accessNode && !isTypeAssignableToKind(indexType, 4 | 8)) { - var indexNode = accessNode.kind === 186 ? accessNode.argumentExpression : accessNode.indexType; + if (accessNode && !isTypeAssignableToKind(indexType, 4 /* String */ | 8 /* Number */)) { + var indexNode = accessNode.kind === 186 /* ElementAccessExpression */ ? accessNode.argumentExpression : accessNode.indexType; error(indexNode, ts.Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeToString(indexType)); } else if (accessExpression && indexInfo.isReadonly && (ts.isAssignmentTarget(accessExpression) || ts.isDeleteTarget(accessExpression))) { @@ -32142,12 +37163,12 @@ var ts; } return indexInfo.type; } - if (indexType.flags & 32768) { + if (indexType.flags & 32768 /* Never */) { return neverType; } if (accessExpression && !isConstEnumObjectType(objectType)) { if (noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors) { - if (getIndexTypeOfType(objectType, 1)) { + if (getIndexTypeOfType(objectType, 1 /* Number */)) { error(accessExpression.argumentExpression, ts.Diagnostics.Element_implicitly_has_an_any_type_because_index_expression_is_not_of_type_number); } else { @@ -32158,11 +37179,11 @@ var ts; } } if (accessNode) { - var indexNode = accessNode.kind === 186 ? accessNode.argumentExpression : accessNode.indexType; - if (indexType.flags & (64 | 128)) { + var indexNode = accessNode.kind === 186 /* ElementAccessExpression */ ? accessNode.argumentExpression : accessNode.indexType; + if (indexType.flags & (64 /* StringLiteral */ | 128 /* NumberLiteral */)) { error(indexNode, ts.Diagnostics.Property_0_does_not_exist_on_type_1, "" + indexType.value, typeToString(objectType)); } - else if (indexType.flags & (4 | 8)) { + else if (indexType.flags & (4 /* String */ | 8 /* Number */)) { error(indexNode, ts.Diagnostics.Type_0_has_no_matching_index_signature_for_type_1, typeToString(objectType), typeToString(indexType)); } else { @@ -32172,13 +37193,15 @@ var ts; return errorType; } function isGenericObjectType(type) { - return maybeTypeOfKind(type, 14745600 | 134217728); + return maybeTypeOfKind(type, 14745600 /* InstantiableNonPrimitive */ | 134217728 /* GenericMappedType */); } function isGenericIndexType(type) { - return maybeTypeOfKind(type, 14745600 | 1048576); + return maybeTypeOfKind(type, 14745600 /* InstantiableNonPrimitive */ | 1048576 /* Index */); } + // Return true if the given type is a non-generic object type with a string index signature and no + // other members. function isStringIndexOnlyType(type) { - if (type.flags & 131072 && !isGenericMappedType(type)) { + if (type.flags & 131072 /* Object */ && !isGenericMappedType(type)) { var t = resolveStructuredTypeMembers(type); return t.properties.length === 0 && t.callSignatures.length === 0 && t.constructSignatures.length === 0 && @@ -32187,25 +37210,33 @@ var ts; return false; } function isMappedTypeToNever(type) { - return !!(ts.getObjectFlags(type) & 32) && getTemplateTypeFromMappedType(type) === neverType; + return !!(ts.getObjectFlags(type) & 32 /* Mapped */) && getTemplateTypeFromMappedType(type) === neverType; } function getSimplifiedType(type) { - return type.flags & 2097152 ? getSimplifiedIndexedAccessType(type) : type; + return type.flags & 2097152 /* IndexedAccess */ ? getSimplifiedIndexedAccessType(type) : type; } + // Transform an indexed access to a simpler form, if possible. Return the simpler form, or return + // the type itself if no transformation is possible. function getSimplifiedIndexedAccessType(type) { if (type.simplified) { return type.simplified === circularConstraintType ? type : type.simplified; } type.simplified = circularConstraintType; + // We recursively simplify the object type as it may in turn be an indexed access type. For example, with + // '{ [P in T]: { [Q in U]: number } }[T][U]' we want to first simplify the inner indexed access type. var objectType = getSimplifiedType(type.objectType); - if (objectType.flags & 524288 && isGenericObjectType(objectType)) { + if (objectType.flags & 524288 /* Intersection */ && isGenericObjectType(objectType)) { + // Given an indexed access type T[K], if T is an intersection containing one or more generic types and one or + // more object types with only a string index signature, e.g. '(U & V & { [x: string]: D })[K]', return a + // transformed type of the form '(U & V)[K] | D'. This allows us to properly reason about higher order indexed + // access types with default property values as expressed by D. if (ts.some(objectType.types, isStringIndexOnlyType)) { var regularTypes = []; var stringIndexTypes = []; for (var _i = 0, _a = objectType.types; _i < _a.length; _i++) { var t = _a[_i]; if (isStringIndexOnlyType(t)) { - stringIndexTypes.push(getIndexTypeOfType(t, 0)); + stringIndexTypes.push(getIndexTypeOfType(t, 0 /* String */)); } else { regularTypes.push(t); @@ -32216,15 +37247,23 @@ var ts; getIntersectionType(stringIndexTypes) ]); } + // Given an indexed access type T[K], if T is an intersection containing one or more generic types and one or + // more mapped types with a template type `never`, '(U & V & { [P in T]: never })[K]', return a + // transformed type that removes the never-mapped type: '(U & V)[K]'. This mirrors what would happen + // eventually anyway, but it easier to reason about. if (ts.some(objectType.types, isMappedTypeToNever)) { var nonNeverTypes = ts.filter(objectType.types, function (t) { return !isMappedTypeToNever(t); }); return type.simplified = getSimplifiedType(getIndexedAccessType(getIntersectionType(nonNeverTypes), type.indexType)); } } + // If the object type is a mapped type { [P in K]: E }, where K is generic, instantiate E using a mapper + // that substitutes the index type for P. For example, for an index access { [P in K]: Box }[X], we + // construct the type Box. We do not further simplify the result because mapped types can be recursive + // and we might never terminate. if (isGenericMappedType(objectType)) { return type.simplified = substituteIndexedMappedType(objectType, type); } - if (objectType.flags & 65536) { + if (objectType.flags & 65536 /* TypeParameter */) { var constraint = getConstraintFromTypeParameter(objectType); if (constraint && isGenericMappedType(constraint)) { return type.simplified = substituteIndexedMappedType(constraint, type); @@ -32241,10 +37280,16 @@ var ts; if (objectType === wildcardType || indexType === wildcardType) { return wildcardType; } - if (isGenericIndexType(indexType) || !(accessNode && accessNode.kind === 186) && isGenericObjectType(objectType)) { - if (objectType.flags & 3) { + // If the index type is generic, or if the object type is generic and doesn't originate in an expression, + // we are performing a higher-order index access where we cannot meaningfully access the properties of the + // object type. Note that for a generic T and a non-generic K, we eagerly resolve T[K] if it originates in + // an expression. This is to preserve backwards compatibility. For example, an element access 'this["foo"]' + // has always been resolved eagerly using the constraint type of 'this' at the given location. + if (isGenericIndexType(indexType) || !(accessNode && accessNode.kind === 186 /* ElementAccessExpression */) && isGenericObjectType(objectType)) { + if (objectType.flags & 3 /* AnyOrUnknown */) { return objectType; } + // Defer the operation by creating an indexed access type. var id = objectType.id + "," + indexType.id; var type = indexedAccessTypes.get(id); if (!type) { @@ -32252,12 +37297,15 @@ var ts; } return type; } + // In the following we resolve T[K] to the type of the property in T selected by K. + // We treat boolean as different from other unions to improve errors; + // skipping straight to getPropertyTypeForIndexType gives errors with 'boolean' instead of 'true'. var apparentObjectType = getApparentType(objectType); - if (indexType.flags & 262144 && !(indexType.flags & 16)) { + if (indexType.flags & 262144 /* Union */ && !(indexType.flags & 16 /* Boolean */)) { var propTypes = []; for (var _i = 0, _a = indexType.types; _i < _a.length; _i++) { var t = _a[_i]; - var propType = getPropertyTypeForIndexType(apparentObjectType, t, accessNode, false); + var propType = getPropertyTypeForIndexType(apparentObjectType, t, accessNode, /*cacheSymbol*/ false); if (propType === errorType) { return errorType; } @@ -32265,7 +37313,7 @@ var ts; } return getUnionType(propTypes); } - return getPropertyTypeForIndexType(apparentObjectType, indexType, accessNode, true); + return getPropertyTypeForIndexType(apparentObjectType, indexType, accessNode, /*cacheSymbol*/ true); } function getTypeFromIndexedAccessTypeNode(node) { var links = getNodeLinks(node); @@ -32273,7 +37321,7 @@ var ts; var objectType = getTypeFromTypeNode(node.objectType); var indexType = getTypeFromTypeNode(node.indexType); var resolved = getIndexedAccessType(objectType, indexType, node); - links.resolvedType = resolved.flags & 2097152 && + links.resolvedType = resolved.flags & 2097152 /* IndexedAccess */ && resolved.objectType === objectType && resolved.indexType === indexType ? getConstrainedTypeVariable(resolved, node) : resolved; @@ -32283,17 +37331,19 @@ var ts; function getTypeFromMappedTypeNode(node) { var links = getNodeLinks(node); if (!links.resolvedType) { - var type = createObjectType(32, node.symbol); + var type = createObjectType(32 /* Mapped */, node.symbol); type.declaration = node; type.aliasSymbol = getAliasSymbolForTypeNode(node); type.aliasTypeArguments = getTypeArgumentsForAliasSymbol(type.aliasSymbol); links.resolvedType = type; + // Eagerly resolve the constraint type which forces an error if the constraint type circularly + // references itself through one or more type aliases. getConstraintTypeFromMappedType(type); } return links.resolvedType; } function getActualTypeVariable(type) { - return type.flags & 8388608 ? type.typeVariable : type; + return type.flags & 8388608 /* Substitution */ ? type.typeVariable : type; } function getConditionalType(root, mapper) { var checkType = instantiateType(root.checkType, mapper); @@ -32301,39 +37351,56 @@ var ts; if (checkType === wildcardType || extendsType === wildcardType) { return wildcardType; } - var isDeferred = root.isDistributive && maybeTypeOfKind(checkType, 15794176); + // If this is a distributive conditional type and the check type is generic we need to defer + // resolution of the conditional type such that a later instantiation will properly distribute + // over union types. + var isDeferred = root.isDistributive && maybeTypeOfKind(checkType, 15794176 /* Instantiable */); var combinedMapper; if (root.inferTypeParameters) { - var context = createInferenceContext(root.inferTypeParameters, undefined, 0); + var context = createInferenceContext(root.inferTypeParameters, /*signature*/ undefined, 0 /* None */); if (!isDeferred) { - inferTypes(context.inferences, checkType, extendsType, 32 | 64); + // We don't want inferences from constraints as they may cause us to eagerly resolve the + // conditional type instead of deferring resolution. Also, we always want strict function + // types rules (i.e. proper contravariance) for inferences. + inferTypes(context.inferences, checkType, extendsType, 32 /* NoConstraints */ | 64 /* AlwaysStrict */); } combinedMapper = combineTypeMappers(mapper, context); } if (!isDeferred) { - if (extendsType.flags & 3) { + if (extendsType.flags & 3 /* AnyOrUnknown */) { return instantiateType(root.trueType, mapper); } - if (checkType.flags & 1) { + // Return union of trueType and falseType for 'any' since it matches anything + if (checkType.flags & 1 /* Any */) { return getUnionType([instantiateType(root.trueType, combinedMapper || mapper), instantiateType(root.falseType, mapper)]); } + // Instantiate the extends type including inferences for 'infer T' type parameters var inferredExtendsType = combinedMapper ? instantiateType(root.extendsType, combinedMapper) : extendsType; + // Return falseType for a definitely false extends check. We check an instantations of the two + // types with type parameters mapped to the wildcard type, the most permissive instantiations + // possible (the wildcard type is assignable to and from all types). If those are not related, + // then no instatiations will be and we can just return the false branch type. if (!isTypeAssignableTo(getWildcardInstantiation(checkType), getWildcardInstantiation(inferredExtendsType))) { return instantiateType(root.falseType, mapper); } - if (checkTypeRelatedTo(checkType, inferredExtendsType, definitelyAssignableRelation, undefined)) { + // Return trueType for a definitely true extends check. The definitely assignable relation excludes + // type variable constraints from consideration. Without the definitely assignable relation, the type + // type Foo = T extends { x: string } ? string : number + // would immediately resolve to 'string' instead of being deferred. + if (checkTypeRelatedTo(checkType, inferredExtendsType, definitelyAssignableRelation, /*errorNode*/ undefined)) { return instantiateType(root.trueType, combinedMapper || mapper); } } + // Return a deferred type for a check that is neither definitely true nor definitely false var erasedCheckType = getActualTypeVariable(checkType); - var result = createType(4194304); + var result = createType(4194304 /* Conditional */); result.root = root; result.checkType = erasedCheckType; result.extendsType = extendsType; result.mapper = mapper; result.combinedMapper = combinedMapper; result.aliasSymbol = root.aliasSymbol; - result.aliasTypeArguments = instantiateTypes(root.aliasTypeArguments, mapper); + result.aliasTypeArguments = instantiateTypes(root.aliasTypeArguments, mapper); // TODO: GH#18217 return result; } function getTrueTypeFromConditionalType(type) { @@ -32346,7 +37413,7 @@ var ts; var result; if (node.locals) { node.locals.forEach(function (symbol) { - if (symbol.flags & 262144) { + if (symbol.flags & 262144 /* TypeParameter */) { result = ts.append(result, getDeclaredTypeOfSymbol(symbol)); } }); @@ -32358,7 +37425,7 @@ var ts; return true; } while (node) { - if (node.kind === 171) { + if (node.kind === 171 /* ConditionalType */) { if (isTypeParameterPossiblyReferenced(tp, node.extendsType)) { return true; } @@ -32373,7 +37440,7 @@ var ts; var checkType = getTypeFromTypeNode(node.checkType); var aliasSymbol = getAliasSymbolForTypeNode(node); var aliasTypeArguments = getTypeArgumentsForAliasSymbol(aliasSymbol); - var allOuterTypeParameters = getOuterTypeParameters(node, true); + var allOuterTypeParameters = getOuterTypeParameters(node, /*includeThisTypes*/ true); var outerTypeParameters = aliasTypeArguments ? allOuterTypeParameters : ts.filter(allOuterTypeParameters, function (tp) { return isPossiblyReferencedInConditionalType(tp, node); }); var root = { node: node, @@ -32381,14 +37448,14 @@ var ts; extendsType: getTypeFromTypeNode(node.extendsType), trueType: getTypeFromTypeNode(node.trueType), falseType: getTypeFromTypeNode(node.falseType), - isDistributive: !!(checkType.flags & 65536), + isDistributive: !!(checkType.flags & 65536 /* TypeParameter */), inferTypeParameters: getInferTypeParameters(node), outerTypeParameters: outerTypeParameters, instantiations: undefined, aliasSymbol: aliasSymbol, aliasTypeArguments: aliasTypeArguments }; - links.resolvedType = getConditionalType(root, undefined); + links.resolvedType = getConditionalType(root, /*mapper*/ undefined); if (outerTypeParameters) { root.instantiations = ts.createMap(); root.instantiations.set(getTypeListId(outerTypeParameters), links.resolvedType); @@ -32414,7 +37481,7 @@ var ts; function getTypeFromImportTypeNode(node) { var links = getNodeLinks(node); if (!links.resolvedType) { - if (node.isTypeOf && node.typeArguments) { + if (node.isTypeOf && node.typeArguments) { // Only the non-typeof form can make use of type arguments error(node, ts.Diagnostics.Type_arguments_cannot_be_used_here); links.resolvedSymbol = unknownSymbol; return links.resolvedType = errorType; @@ -32425,20 +37492,21 @@ var ts; return links.resolvedType = errorType; } var argumentType = getTypeFromTypeNode(node.argument); - var targetMeaning = node.isTypeOf ? 67216319 : 67901928; + var targetMeaning = node.isTypeOf ? 67216319 /* Value */ : 67901928 /* Type */; + // TODO: Future work: support unions/generics/whatever via a deferred import-type var moduleName = argumentType.value; - var innerModuleSymbol = resolveExternalModule(node, moduleName, ts.Diagnostics.Cannot_find_module_0, node, false); + var innerModuleSymbol = resolveExternalModule(node, moduleName, ts.Diagnostics.Cannot_find_module_0, node, /*isForAugmentation*/ false); if (!innerModuleSymbol) { links.resolvedSymbol = unknownSymbol; return links.resolvedType = errorType; } - var moduleSymbol_1 = resolveExternalModuleSymbol(innerModuleSymbol, false); + var moduleSymbol_1 = resolveExternalModuleSymbol(innerModuleSymbol, /*dontResolveAlias*/ false); if (!ts.nodeIsMissing(node.qualifier)) { var nameStack = getIdentifierChain(node.qualifier); var currentNamespace = moduleSymbol_1; var current = void 0; while (current = nameStack.shift()) { - var meaning = nameStack.length ? 1920 : targetMeaning; + var meaning = nameStack.length ? 1920 /* Namespace */ : targetMeaning; var next = getSymbol(getExportsOfSymbol(getMergedSymbol(resolveSymbol(currentNamespace))), current.escapedText, meaning); if (!next) { error(current, ts.Diagnostics.Namespace_0_has_no_exported_member_1, getFullyQualifiedName(currentNamespace), ts.declarationNameToString(current)); @@ -32455,33 +37523,34 @@ var ts; resolveImportSymbolType(node, links, moduleSymbol_1, targetMeaning); } else { - error(node, targetMeaning === 67216319 ? ts.Diagnostics.Module_0_does_not_refer_to_a_value_but_is_used_as_a_value_here : ts.Diagnostics.Module_0_does_not_refer_to_a_type_but_is_used_as_a_type_here, moduleName); + error(node, targetMeaning === 67216319 /* Value */ ? ts.Diagnostics.Module_0_does_not_refer_to_a_value_but_is_used_as_a_value_here : ts.Diagnostics.Module_0_does_not_refer_to_a_type_but_is_used_as_a_type_here, moduleName); links.resolvedSymbol = unknownSymbol; links.resolvedType = errorType; } } } - return links.resolvedType; + return links.resolvedType; // TODO: GH#18217 } function resolveImportSymbolType(node, links, symbol, meaning) { var resolvedSymbol = resolveSymbol(symbol); links.resolvedSymbol = resolvedSymbol; - if (meaning === 67216319) { - return links.resolvedType = getTypeOfSymbol(symbol); + if (meaning === 67216319 /* Value */) { + return links.resolvedType = getTypeOfSymbol(symbol); // intentionally doesn't use resolved symbol so type is cached as expected on the alias } else { - return links.resolvedType = getTypeReferenceType(node, resolvedSymbol); + return links.resolvedType = getTypeReferenceType(node, resolvedSymbol); // getTypeReferenceType doesn't handle aliases - it must get the resolved symbol } } function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node) { var links = getNodeLinks(node); if (!links.resolvedType) { + // Deferred resolution of members is handled by resolveObjectTypeMembers var aliasSymbol = getAliasSymbolForTypeNode(node); if (getMembersOfSymbol(node.symbol).size === 0 && !aliasSymbol) { links.resolvedType = emptyTypeLiteralType; } else { - var type = createObjectType(16, node.symbol); + var type = createObjectType(16 /* Anonymous */, node.symbol); type.aliasSymbol = aliasSymbol; type.aliasTypeArguments = getTypeArgumentsForAliasSymbol(aliasSymbol); if (ts.isJSDocTypeLiteral(node) && node.isArrayType) { @@ -32498,26 +37567,31 @@ var ts; function getTypeArgumentsForAliasSymbol(symbol) { return symbol ? getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) : undefined; } + /** + * Since the source of spread types are object literals, which are not binary, + * this function should be called in a left folding style, with left = previous result of getSpreadType + * and right = the new element to be spread. + */ function getSpreadType(left, right, symbol, typeFlags, objectFlags) { - if (left.flags & 1 || right.flags & 1) { + if (left.flags & 1 /* Any */ || right.flags & 1 /* Any */) { return anyType; } - if (left.flags & 2 || right.flags & 2) { + if (left.flags & 2 /* Unknown */ || right.flags & 2 /* Unknown */) { return unknownType; } - if (left.flags & 32768) { + if (left.flags & 32768 /* Never */) { return right; } - if (right.flags & 32768) { + if (right.flags & 32768 /* Never */) { return left; } - if (left.flags & 262144) { + if (left.flags & 262144 /* Union */) { return mapType(left, function (t) { return getSpreadType(t, right, symbol, typeFlags, objectFlags); }); } - if (right.flags & 262144) { + if (right.flags & 262144 /* Union */) { return mapType(right, function (t) { return getSpreadType(left, t, symbol, typeFlags, objectFlags); }); } - if (right.flags & (272 | 168 | 68 | 544 | 16777216 | 1048576)) { + if (right.flags & (272 /* BooleanLike */ | 168 /* NumberLike */ | 68 /* StringLike */ | 544 /* EnumLike */ | 16777216 /* NonPrimitive */ | 1048576 /* Index */)) { return left; } var members = ts.createSymbolTable(); @@ -32525,17 +37599,19 @@ var ts; var stringIndexInfo; var numberIndexInfo; if (left === emptyObjectType) { - stringIndexInfo = getIndexInfoOfType(right, 0); - numberIndexInfo = getIndexInfoOfType(right, 1); + // for the first spread element, left === emptyObjectType, so take the right's string indexer + stringIndexInfo = getIndexInfoOfType(right, 0 /* String */); + numberIndexInfo = getIndexInfoOfType(right, 1 /* Number */); } else { - stringIndexInfo = unionSpreadIndexInfos(getIndexInfoOfType(left, 0), getIndexInfoOfType(right, 0)); - numberIndexInfo = unionSpreadIndexInfos(getIndexInfoOfType(left, 1), getIndexInfoOfType(right, 1)); + stringIndexInfo = unionSpreadIndexInfos(getIndexInfoOfType(left, 0 /* String */), getIndexInfoOfType(right, 0 /* String */)); + numberIndexInfo = unionSpreadIndexInfos(getIndexInfoOfType(left, 1 /* Number */), getIndexInfoOfType(right, 1 /* Number */)); } for (var _i = 0, _a = getPropertiesOfType(right); _i < _a.length; _i++) { var rightProp = _a[_i]; - var isSetterWithoutGetter = rightProp.flags & 65536 && !(rightProp.flags & 32768); - if (ts.getDeclarationModifierFlagsFromSymbol(rightProp) & (8 | 16)) { + // we approximate own properties as non-methods plus methods that are inside the object literal + var isSetterWithoutGetter = rightProp.flags & 65536 /* SetAccessor */ && !(rightProp.flags & 32768 /* GetAccessor */); + if (ts.getDeclarationModifierFlagsFromSymbol(rightProp) & (8 /* Private */ | 16 /* Protected */)) { skippedPrivateMembers.set(rightProp.escapedName, true); } else if (!isClassMethod(rightProp) && !isSetterWithoutGetter) { @@ -32544,7 +37620,7 @@ var ts; } for (var _b = 0, _c = getPropertiesOfType(left); _b < _c.length; _b++) { var leftProp = _c[_b]; - if (leftProp.flags & 65536 && !(leftProp.flags & 32768) + if (leftProp.flags & 65536 /* SetAccessor */ && !(leftProp.flags & 32768 /* GetAccessor */) || skippedPrivateMembers.has(leftProp.escapedName) || isClassMethod(leftProp)) { continue; @@ -32552,11 +37628,11 @@ var ts; if (members.has(leftProp.escapedName)) { var rightProp = members.get(leftProp.escapedName); var rightType = getTypeOfSymbol(rightProp); - if (rightProp.flags & 16777216) { + if (rightProp.flags & 16777216 /* Optional */) { var declarations = ts.concatenate(leftProp.declarations, rightProp.declarations); - var flags = 4 | (leftProp.flags & 16777216); + var flags = 4 /* Property */ | (leftProp.flags & 16777216 /* Optional */); var result = createSymbol(flags, leftProp.escapedName); - result.type = getUnionType([getTypeOfSymbol(leftProp), getTypeWithFacts(rightType, 131072)]); + result.type = getUnionType([getTypeOfSymbol(leftProp), getTypeWithFacts(rightType, 131072 /* NEUndefined */)]); result.leftSpread = leftProp; result.rightSpread = rightProp; result.declarations = declarations; @@ -32569,15 +37645,15 @@ var ts; } } var spread = createAnonymousType(symbol, members, ts.emptyArray, ts.emptyArray, getNonReadonlyIndexSignature(stringIndexInfo), getNonReadonlyIndexSignature(numberIndexInfo)); - spread.flags |= typeFlags | 268435456; - spread.objectFlags |= objectFlags | (128 | 1024); + spread.flags |= typeFlags | 268435456 /* ContainsObjectLiteral */; + spread.objectFlags |= objectFlags | (128 /* ObjectLiteral */ | 1024 /* ContainsSpread */); return spread; } function getNonReadonlySymbol(prop) { if (!isReadonlySymbol(prop)) { return prop; } - var flags = 4 | (prop.flags & 16777216); + var flags = 4 /* Property */ | (prop.flags & 16777216 /* Optional */); var result = createSymbol(flags, prop.escapedName); result.type = getTypeOfSymbol(prop); result.declarations = prop.declarations; @@ -32587,12 +37663,12 @@ var ts; } function getNonReadonlyIndexSignature(index) { if (index && index.isReadonly) { - return createIndexInfo(index.type, false, index.declaration); + return createIndexInfo(index.type, /*isReadonly*/ false, index.declaration); } return index; } function isClassMethod(prop) { - return prop.flags & 8192 && ts.find(prop.declarations, function (decl) { return ts.isClassLike(decl.parent); }); + return prop.flags & 8192 /* Method */ && ts.find(prop.declarations, function (decl) { return ts.isClassLike(decl.parent); }); } function createLiteralType(flags, value, symbol) { var type = createType(flags); @@ -32601,9 +37677,9 @@ var ts; return type; } function getFreshTypeOfLiteralType(type) { - if (type.flags & 192 && !(type.flags & 33554432)) { + if (type.flags & 192 /* StringOrNumberLiteral */ && !(type.flags & 33554432 /* FreshLiteral */)) { if (!type.freshType) { - var freshType = createLiteralType(type.flags | 33554432, type.value, type.symbol); + var freshType = createLiteralType(type.flags | 33554432 /* FreshLiteral */, type.value, type.symbol); freshType.regularType = type; type.freshType = freshType; } @@ -32612,16 +37688,20 @@ var ts; return type; } function getRegularTypeOfLiteralType(type) { - return type.flags & 192 && type.flags & 33554432 ? type.regularType : - type.flags & 262144 ? getUnionType(ts.sameMap(type.types, getRegularTypeOfLiteralType)) : + return type.flags & 192 /* StringOrNumberLiteral */ && type.flags & 33554432 /* FreshLiteral */ ? type.regularType : + type.flags & 262144 /* Union */ ? getUnionType(ts.sameMap(type.types, getRegularTypeOfLiteralType)) : type; } function getLiteralType(value, enumId, symbol) { + // We store all literal types in a single map with keys of the form '#NNN' and '@SSS', + // where NNN is the text representation of a numeric literal and SSS are the characters + // of a string literal. For literal enum members we use 'EEE#NNN' and 'EEE@SSS', where + // EEE is a unique id for the containing enum type. var qualifier = typeof value === "number" ? "#" : "@"; var key = enumId ? enumId + qualifier + value : qualifier + value; var type = literalTypes.get(key); if (!type) { - var flags = (typeof value === "number" ? 128 : 64) | (enumId ? 512 : 0); + var flags = (typeof value === "number" ? 128 /* NumberLiteral */ : 64 /* StringLiteral */) | (enumId ? 512 /* EnumLiteral */ : 0); literalTypes.set(key, type = createLiteralType(flags, value, symbol)); } return type; @@ -32634,7 +37714,7 @@ var ts; return links.resolvedType; } function createUniqueESSymbolType(symbol) { - var type = createType(2048); + var type = createType(2048 /* UniqueESSymbol */); type.symbol = symbol; return type; } @@ -32647,11 +37727,11 @@ var ts; return esSymbolType; } function getThisType(node) { - var container = ts.getThisContainer(node, false); + var container = ts.getThisContainer(node, /*includeArrowFunctions*/ false); var parent = container && container.parent; - if (parent && (ts.isClassLike(parent) || parent.kind === 236)) { - if (!ts.hasModifier(container, 32) && - (container.kind !== 155 || ts.isNodeDescendantOf(node, container.body))) { + if (parent && (ts.isClassLike(parent) || parent.kind === 236 /* InterfaceDeclaration */)) { + if (!ts.hasModifier(container, 32 /* Static */) && + (container.kind !== 155 /* Constructor */ || ts.isNodeDescendantOf(node, container.body))) { return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(parent)).thisType; } } @@ -32667,84 +37747,86 @@ var ts; } function getTypeFromTypeNode(node) { switch (node.kind) { - case 119: - case 279: - case 280: + case 119 /* AnyKeyword */: + case 279 /* JSDocAllType */: + case 280 /* JSDocUnknownType */: return anyType; - case 142: + case 142 /* UnknownKeyword */: return unknownType; - case 137: + case 137 /* StringKeyword */: return stringType; - case 134: + case 134 /* NumberKeyword */: return numberType; - case 122: + case 122 /* BooleanKeyword */: return booleanType; - case 138: + case 138 /* SymbolKeyword */: return esSymbolType; - case 105: + case 105 /* VoidKeyword */: return voidType; - case 140: + case 140 /* UndefinedKeyword */: return undefinedType; - case 95: + case 95 /* NullKeyword */: return nullType; - case 131: + case 131 /* NeverKeyword */: return neverType; - case 135: - return node.flags & 65536 ? anyType : nonPrimitiveType; - case 174: - case 99: + case 135 /* ObjectKeyword */: + return node.flags & 65536 /* JavaScriptFile */ ? anyType : nonPrimitiveType; + case 174 /* ThisType */: + case 99 /* ThisKeyword */: return getTypeFromThisTypeNode(node); - case 178: + case 178 /* LiteralType */: return getTypeFromLiteralTypeNode(node); - case 162: + case 162 /* TypeReference */: return getTypeFromTypeReference(node); - case 161: + case 161 /* TypePredicate */: return booleanType; - case 207: + case 207 /* ExpressionWithTypeArguments */: return getTypeFromTypeReference(node); - case 165: + case 165 /* TypeQuery */: return getTypeFromTypeQueryNode(node); - case 167: + case 167 /* ArrayType */: return getTypeFromArrayTypeNode(node); - case 168: + case 168 /* TupleType */: return getTypeFromTupleTypeNode(node); - case 169: + case 169 /* UnionType */: return getTypeFromUnionTypeNode(node); - case 170: + case 170 /* IntersectionType */: return getTypeFromIntersectionTypeNode(node); - case 281: + case 281 /* JSDocNullableType */: return getTypeFromJSDocNullableTypeNode(node); - case 283: + case 283 /* JSDocOptionalType */: return addOptionality(getTypeFromTypeNode(node.type)); - case 173: - case 282: - case 278: + case 173 /* ParenthesizedType */: + case 282 /* JSDocNonNullableType */: + case 278 /* JSDocTypeExpression */: return getTypeFromTypeNode(node.type); - case 285: + case 285 /* JSDocVariadicType */: return getTypeFromJSDocVariadicType(node); - case 163: - case 164: - case 166: - case 287: - case 284: - case 288: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 166 /* TypeLiteral */: + case 287 /* JSDocTypeLiteral */: + case 284 /* JSDocFunctionType */: + case 288 /* JSDocSignature */: return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node); - case 175: + case 175 /* TypeOperator */: return getTypeFromTypeOperatorNode(node); - case 176: + case 176 /* IndexedAccessType */: return getTypeFromIndexedAccessTypeNode(node); - case 177: + case 177 /* MappedType */: return getTypeFromMappedTypeNode(node); - case 171: + case 171 /* ConditionalType */: return getTypeFromConditionalTypeNode(node); - case 172: + case 172 /* InferType */: return getTypeFromInferTypeNode(node); - case 179: + case 179 /* ImportType */: return getTypeFromImportTypeNode(node); - case 71: - case 146: + // This function assumes that an identifier or qualified name is a type expression + // Callers should first ensure this by calling isTypeNode + case 71 /* Identifier */: + case 146 /* QualifiedName */: var symbol = getSymbolAtLocation(node); - return (symbol && getDeclaredTypeOfSymbol(symbol)); + return (symbol && getDeclaredTypeOfSymbol(symbol)); // TODO: GH#18217 default: return errorType; } @@ -32795,8 +37877,12 @@ var ts; makeArrayTypeMapper(sources, targets); } function createTypeEraser(sources) { - return createTypeMapper(sources, undefined); + return createTypeMapper(sources, /*targets*/ undefined); } + /** + * Maps forward-references to later types parameters to the empty object type. + * This is used during inference when instantiating type parameter defaults. + */ function createBackreferenceMapper(typeParameters, index) { return function (t) { return typeParameters.indexOf(t) >= index ? emptyObjectType : t; }; } @@ -32805,7 +37891,7 @@ var ts; } function cloneTypeMapper(mapper) { return mapper && isInferenceContext(mapper) ? - createInferenceContext(mapper.typeParameters, mapper.signature, mapper.flags | 2, mapper.compareTypes, mapper.inferences) : + createInferenceContext(mapper.typeParameters, mapper.signature, mapper.flags | 2 /* NoDefault */, mapper.compareTypes, mapper.inferences) : mapper; } function combineTypeMappers(mapper1, mapper2) { @@ -32819,10 +37905,10 @@ var ts; return function (t) { return t === source ? target : baseMapper(t); }; } function wildcardMapper(type) { - return type.flags & 65536 ? wildcardType : type; + return type.flags & 65536 /* TypeParameter */ ? wildcardType : type; } function cloneTypeParameter(typeParameter) { - var result = createType(65536); + var result = createType(65536 /* TypeParameter */); result.symbol = typeParameter.symbol; result.target = typeParameter; return result; @@ -32830,7 +37916,7 @@ var ts; function instantiateTypePredicate(predicate, mapper) { if (ts.isIdentifierTypePredicate(predicate)) { return { - kind: 1, + kind: 1 /* Identifier */, parameterName: predicate.parameterName, parameterIndex: predicate.parameterIndex, type: instantiateType(predicate.type, mapper) @@ -32838,7 +37924,7 @@ var ts; } else { return { - kind: 0, + kind: 0 /* This */, type: instantiateType(predicate.type, mapper) }; } @@ -32846,6 +37932,9 @@ var ts; function instantiateSignature(signature, mapper, eraseTypeParameters) { var freshTypeParameters; if (signature.typeParameters && !eraseTypeParameters) { + // First create a fresh set of type parameters, then include a mapping from the old to the + // new type parameters in the mapper function. Finally store this mapper in the new type + // parameters such that we can use it when instantiating constraints. freshTypeParameters = ts.map(signature.typeParameters, cloneTypeParameter); mapper = combineTypeMappers(createTypeMapper(signature.typeParameters, freshTypeParameters), mapper); for (var _i = 0, freshTypeParameters_1 = freshTypeParameters; _i < freshTypeParameters_1.length; _i++) { @@ -32853,21 +37942,33 @@ var ts; tp.mapper = mapper; } } - var result = createSignature(signature.declaration, freshTypeParameters, signature.thisParameter && instantiateSymbol(signature.thisParameter, mapper), instantiateList(signature.parameters, mapper, instantiateSymbol), undefined, undefined, signature.minArgumentCount, signature.hasRestParameter, signature.hasLiteralTypes); + // Don't compute resolvedReturnType and resolvedTypePredicate now, + // because using `mapper` now could trigger inferences to become fixed. (See `createInferenceContext`.) + // See GH#17600. + var result = createSignature(signature.declaration, freshTypeParameters, signature.thisParameter && instantiateSymbol(signature.thisParameter, mapper), instantiateList(signature.parameters, mapper, instantiateSymbol), + /*resolvedReturnType*/ undefined, + /*resolvedTypePredicate*/ undefined, signature.minArgumentCount, signature.hasRestParameter, signature.hasLiteralTypes); result.target = signature; result.mapper = mapper; return result; } function instantiateSymbol(symbol, mapper) { var links = getSymbolLinks(symbol); - if (links.type && !maybeTypeOfKind(links.type, 131072 | 15794176)) { + if (links.type && !maybeTypeOfKind(links.type, 131072 /* Object */ | 15794176 /* Instantiable */)) { + // If the type of the symbol is already resolved, and if that type could not possibly + // be affected by instantiation, simply return the symbol itself. return symbol; } - if (ts.getCheckFlags(symbol) & 1) { + if (ts.getCheckFlags(symbol) & 1 /* Instantiated */) { + // If symbol being instantiated is itself a instantiation, fetch the original target and combine the + // type mappers. This ensures that original type identities are properly preserved and that aliases + // always reference a non-aliases. symbol = links.target; mapper = combineTypeMappers(links.mapper, mapper); } - var result = createSymbol(symbol.flags, symbol.escapedName, 1 | (ts.getCheckFlags(symbol) & 1024)); + // Keep the flags from the symbol we're instantiating. Mark that is instantiated, and + // also transient so that we can just store data on it directly. + var result = createSymbol(symbol.flags, symbol.escapedName, 1 /* Instantiated */ | (ts.getCheckFlags(symbol) & 1024 /* Late */)); result.declarations = symbol.declarations; result.parent = symbol.parent; result.target = symbol; @@ -32886,11 +37987,15 @@ var ts; return result; } function getAnonymousTypeInstantiation(type, mapper) { - var target = type.objectFlags & 64 ? type.target : type; + var target = type.objectFlags & 64 /* Instantiated */ ? type.target : type; var symbol = target.symbol; var links = getSymbolLinks(symbol); var typeParameters = links.outerTypeParameters; if (!typeParameters) { + // The first time an anonymous type is instantiated we compute and store a list of the type + // parameters that are in scope (and therefore potentially referenced). For type literals that + // aren't the right hand side of a generic type alias declaration we optimize by reducing the + // set of type parameters to those that are possibly referenced in the literal. var declaration_1 = symbol.declarations[0]; if (ts.isInJavaScriptFile(declaration_1)) { var paramTag = ts.findAncestor(declaration_1, ts.isJSDocParameterTag); @@ -32901,13 +38006,13 @@ var ts; } } } - var outerTypeParameters = getOuterTypeParameters(declaration_1, true); + var outerTypeParameters = getOuterTypeParameters(declaration_1, /*includeThisTypes*/ true); if (isJavaScriptConstructor(declaration_1)) { var templateTagParameters = getTypeParametersFromDeclaration(declaration_1); outerTypeParameters = ts.addRange(outerTypeParameters, templateTagParameters); } typeParameters = outerTypeParameters || ts.emptyArray; - typeParameters = symbol.flags & 2048 && !target.aliasTypeArguments ? + typeParameters = symbol.flags & 2048 /* TypeLiteral */ && !target.aliasTypeArguments ? ts.filter(typeParameters, function (tp) { return isTypeParameterPossiblyReferenced(tp, declaration_1); }) : typeParameters; links.outerTypeParameters = typeParameters; @@ -32917,13 +38022,16 @@ var ts; } } if (typeParameters.length) { - var combinedMapper = type.objectFlags & 64 ? combineTypeMappers(type.mapper, mapper) : mapper; + // We are instantiating an anonymous type that has one or more type parameters in scope. Apply the + // mapper to the type parameters to produce the effective list of type arguments, and compute the + // instantiation cache key from the type IDs of the type arguments. + var combinedMapper = type.objectFlags & 64 /* Instantiated */ ? combineTypeMappers(type.mapper, mapper) : mapper; var typeArguments = ts.map(typeParameters, combinedMapper); var id = getTypeListId(typeArguments); var result = links.instantiations.get(id); if (!result) { var newMapper = createTypeMapper(typeParameters, typeArguments); - result = target.objectFlags & 32 ? instantiateMappedType(target, newMapper) : instantiateAnonymousType(target, newMapper); + result = target.objectFlags & 32 /* Mapped */ ? instantiateMappedType(target, newMapper) : instantiateAnonymousType(target, newMapper); links.instantiations.set(id, result); } return result; @@ -32931,35 +38039,43 @@ var ts; return type; } function maybeTypeParameterReference(node) { - return !(node.kind === 146 || - node.parent.kind === 162 && node.parent.typeArguments && node === node.parent.typeName); + return !(node.kind === 146 /* QualifiedName */ || + node.parent.kind === 162 /* TypeReference */ && node.parent.typeArguments && node === node.parent.typeName); } function isTypeParameterPossiblyReferenced(tp, node) { + // If the type parameter doesn't have exactly one declaration, if there are invening statement blocks + // between the node and the type parameter declaration, if the node contains actual references to the + // type parameter, or if the node contains type queries, we consider the type parameter possibly referenced. if (tp.symbol && tp.symbol.declarations && tp.symbol.declarations.length === 1) { var container_3 = tp.symbol.declarations[0].parent; - if (ts.findAncestor(node, function (n) { return n.kind === 213 ? "quit" : n === container_3; })) { + if (ts.findAncestor(node, function (n) { return n.kind === 213 /* Block */ ? "quit" : n === container_3; })) { return !!ts.forEachChild(node, containsReference); } } return true; function containsReference(node) { switch (node.kind) { - case 174: + case 174 /* ThisType */: return !!tp.isThisType; - case 71: + case 71 /* Identifier */: return !tp.isThisType && ts.isPartOfTypeNode(node) && maybeTypeParameterReference(node) && getTypeFromTypeNode(node) === tp; - case 165: + case 165 /* TypeQuery */: return true; } return !!ts.forEachChild(node, containsReference); } } function instantiateMappedType(type, mapper) { + // Check if we have a homomorphic mapped type, i.e. a type of the form { [P in keyof T]: X } for some + // type variable T. If so, the mapped type is distributive over a union type and when T is instantiated + // to a union type A | B, we produce { [P in keyof A]: X } | { [P in keyof B]: X }. Furthermore, for + // homomorphic mapped types we leave primitive types alone. For example, when T is instantiated to a + // union type A | undefined, we produce { [P in keyof A]: X } | undefined. var constraintType = getConstraintTypeFromMappedType(type); - if (constraintType.flags & 1048576) { + if (constraintType.flags & 1048576 /* Index */) { var typeVariable_1 = constraintType.type; - if (typeVariable_1.flags & 65536) { + if (typeVariable_1.flags & 65536 /* TypeParameter */) { var mappedTypeVariable = instantiateType(typeVariable_1, mapper); if (typeVariable_1 !== mappedTypeVariable) { return mapType(mappedTypeVariable, function (t) { @@ -32974,11 +38090,11 @@ var ts; return instantiateAnonymousType(type, mapper); } function isMappableType(type) { - return type.flags & (3 | 14745600 | 131072 | 524288); + return type.flags & (3 /* AnyOrUnknown */ | 14745600 /* InstantiableNonPrimitive */ | 131072 /* Object */ | 524288 /* Intersection */); } function instantiateAnonymousType(type, mapper) { - var result = createObjectType(type.objectFlags | 64, type.symbol); - if (type.objectFlags & 32) { + var result = createObjectType(type.objectFlags | 64 /* Instantiated */, type.symbol); + if (type.objectFlags & 32 /* Mapped */) { result.declaration = type.declaration; } result.target = type; @@ -32990,6 +38106,9 @@ var ts; function getConditionalTypeInstantiation(type, mapper) { var root = type.root; if (root.outerTypeParameters) { + // We are instantiating a conditional type that has one or more type parameters in scope. Apply the + // mapper to the type parameters to produce the effective list of type arguments, and compute the + // instantiation cache key from the type IDs of the type arguments. var typeArguments = ts.map(root.outerTypeParameters, mapper); var id = getTypeListId(typeArguments); var result = root.instantiations.get(id); @@ -33003,10 +38122,13 @@ var ts; return type; } function instantiateConditionalType(root, mapper) { + // Check if we have a conditional type where the check type is a naked type parameter. If so, + // the conditional type is distributive over union types and when T is instantiated to a union + // type A | B, we produce (A extends U ? X : Y) | (B extends U ? X : Y). if (root.isDistributive) { var checkType_1 = root.checkType; var instantiatedType = mapper(checkType_1); - if (checkType_1 !== instantiatedType && instantiatedType.flags & (262144 | 32768)) { + if (checkType_1 !== instantiatedType && instantiatedType.flags & (262144 /* Union */ | 32768 /* Never */)) { return mapType(instantiatedType, function (t) { return getConditionalType(root, createReplacementMapper(checkType_1, t, mapper)); }); } } @@ -33014,83 +38136,90 @@ var ts; } function instantiateType(type, mapper) { if (type && mapper && mapper !== identityMapper) { - if (type.flags & 65536) { + if (type.flags & 65536 /* TypeParameter */) { return mapper(type); } - if (type.flags & 131072) { - if (type.objectFlags & 16) { - return type.symbol && type.symbol.flags & (16 | 8192 | 32 | 2048 | 4096) && type.symbol.declarations ? + if (type.flags & 131072 /* Object */) { + if (type.objectFlags & 16 /* Anonymous */) { + // If the anonymous type originates in a declaration of a function, method, class, or + // interface, in an object type literal, or in an object literal expression, we may need + // to instantiate the type because it might reference a type parameter. + return type.symbol && type.symbol.flags & (16 /* Function */ | 8192 /* Method */ | 32 /* Class */ | 2048 /* TypeLiteral */ | 4096 /* ObjectLiteral */) && type.symbol.declarations ? getAnonymousTypeInstantiation(type, mapper) : type; } - if (type.objectFlags & 32) { + if (type.objectFlags & 32 /* Mapped */) { return getAnonymousTypeInstantiation(type, mapper); } - if (type.objectFlags & 4) { + if (type.objectFlags & 4 /* Reference */) { var typeArguments = type.typeArguments; var newTypeArguments = instantiateTypes(typeArguments, mapper); return newTypeArguments !== typeArguments ? createTypeReference(type.target, newTypeArguments) : type; } } - if (type.flags & 262144 && !(type.flags & 32764)) { + if (type.flags & 262144 /* Union */ && !(type.flags & 32764 /* Primitive */)) { var types = type.types; var newTypes = instantiateTypes(types, mapper); - return newTypes !== types ? getUnionType(newTypes, 1, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)) : type; + return newTypes !== types ? getUnionType(newTypes, 1 /* Literal */, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)) : type; } - if (type.flags & 524288) { + if (type.flags & 524288 /* Intersection */) { var types = type.types; var newTypes = instantiateTypes(types, mapper); return newTypes !== types ? getIntersectionType(newTypes, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)) : type; } - if (type.flags & 1048576) { + if (type.flags & 1048576 /* Index */) { return getIndexType(instantiateType(type.type, mapper)); } - if (type.flags & 2097152) { + if (type.flags & 2097152 /* IndexedAccess */) { return getIndexedAccessType(instantiateType(type.objectType, mapper), instantiateType(type.indexType, mapper)); } - if (type.flags & 4194304) { + if (type.flags & 4194304 /* Conditional */) { return getConditionalTypeInstantiation(type, combineTypeMappers(type.mapper, mapper)); } - if (type.flags & 8388608) { + if (type.flags & 8388608 /* Substitution */) { return instantiateType(type.typeVariable, mapper); } } return type; } function getWildcardInstantiation(type) { - return type.flags & (32764 | 3 | 32768) ? type : + return type.flags & (32764 /* Primitive */ | 3 /* AnyOrUnknown */ | 32768 /* Never */) ? type : type.wildcardInstantiation || (type.wildcardInstantiation = instantiateType(type, wildcardMapper)); } function instantiateIndexInfo(info, mapper) { return info && createIndexInfo(instantiateType(info.type, mapper), info.isReadonly, info.declaration); } + // Returns true if the given expression contains (at any level of nesting) a function or arrow expression + // that is subject to contextual typing. function isContextSensitive(node) { - ts.Debug.assert(node.kind !== 154 || ts.isObjectLiteralMethod(node)); + ts.Debug.assert(node.kind !== 154 /* MethodDeclaration */ || ts.isObjectLiteralMethod(node)); switch (node.kind) { - case 192: - case 193: - case 154: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 154 /* MethodDeclaration */: return isContextSensitiveFunctionLikeDeclaration(node); - case 184: + case 184 /* ObjectLiteralExpression */: return ts.some(node.properties, isContextSensitive); - case 183: + case 183 /* ArrayLiteralExpression */: return ts.some(node.elements, isContextSensitive); - case 201: + case 201 /* ConditionalExpression */: return isContextSensitive(node.whenTrue) || isContextSensitive(node.whenFalse); - case 200: - return node.operatorToken.kind === 54 && + case 200 /* BinaryExpression */: + return node.operatorToken.kind === 54 /* BarBarToken */ && (isContextSensitive(node.left) || isContextSensitive(node.right)); - case 270: + case 270 /* PropertyAssignment */: return isContextSensitive(node.initializer); - case 191: + case 191 /* ParenthesizedExpression */: return isContextSensitive(node.expression); - case 263: + case 263 /* JsxAttributes */: return ts.some(node.properties, isContextSensitive); - case 262: { + case 262 /* JsxAttribute */: { + // If there is no initializer, JSX attribute has a boolean value of true which is not context sensitive. var initializer = node.initializer; return !!initializer && isContextSensitive(initializer); } - case 265: { + case 265 /* JsxExpression */: { + // It is possible to that node.expression is undefined (e.g
) var expression = node.expression; return !!expression && isContextSensitive(expression); } @@ -33098,30 +38227,35 @@ var ts; return false; } function isContextSensitiveFunctionLikeDeclaration(node) { + // Functions with type parameters are not context sensitive. if (node.typeParameters) { return false; } + // Functions with any parameters that lack type annotations are context sensitive. if (ts.some(node.parameters, function (p) { return !ts.getEffectiveTypeAnnotationNode(p); })) { return true; } - if (node.kind !== 193) { + if (node.kind !== 193 /* ArrowFunction */) { + // If the first parameter is not an explicit 'this' parameter, then the function has + // an implicit 'this' parameter which is subject to contextual typing. var parameter = ts.firstOrUndefined(node.parameters); if (!(parameter && ts.parameterIsThisKeyword(parameter))) { return true; } } + // TODO(anhans): A block should be context-sensitive if it has a context-sensitive return value. var body = node.body; - return body.kind === 213 ? false : isContextSensitive(body); + return body.kind === 213 /* Block */ ? false : isContextSensitive(body); } function isContextSensitiveFunctionOrObjectLiteralMethod(func) { return (ts.isInJavaScriptFile(func) && ts.isFunctionDeclaration(func) || isFunctionExpressionOrArrowFunction(func) || ts.isObjectLiteralMethod(func)) && isContextSensitiveFunctionLikeDeclaration(func); } function getTypeWithoutSignatures(type) { - if (type.flags & 131072) { + if (type.flags & 131072 /* Object */) { var resolved = resolveStructuredTypeMembers(type); if (resolved.constructSignatures.length) { - var result = createObjectType(16, type.symbol); + var result = createObjectType(16 /* Anonymous */, type.symbol); result.members = resolved.members; result.properties = resolved.properties; result.callSignatures = ts.emptyArray; @@ -33129,19 +38263,20 @@ var ts; return result; } } - else if (type.flags & 524288) { + else if (type.flags & 524288 /* Intersection */) { return getIntersectionType(ts.map(type.types, getTypeWithoutSignatures)); } return type; } + // TYPE CHECKING function isTypeIdenticalTo(source, target) { return isTypeRelatedTo(source, target, identityRelation); } function compareTypesIdentical(source, target) { - return isTypeRelatedTo(source, target, identityRelation) ? -1 : 0; + return isTypeRelatedTo(source, target, identityRelation) ? -1 /* True */ : 0 /* False */; } function compareTypesAssignable(source, target) { - return isTypeRelatedTo(source, target, assignableRelation) ? -1 : 0; + return isTypeRelatedTo(source, target, assignableRelation) ? -1 /* True */ : 0 /* False */; } function isTypeSubtypeOf(source, target) { return isTypeRelatedTo(source, target, subtypeRelation); @@ -33149,13 +38284,31 @@ var ts; function isTypeAssignableTo(source, target) { return isTypeRelatedTo(source, target, assignableRelation); } + // An object type S is considered to be derived from an object type T if + // S is a union type and every constituent of S is derived from T, + // T is a union type and S is derived from at least one constituent of T, or + // S is a type variable with a base constraint that is derived from T, + // T is one of the global types Object and Function and S is a subtype of T, or + // T occurs directly or indirectly in an 'extends' clause of S. + // Note that this check ignores type parameters and only considers the + // inheritance hierarchy. function isTypeDerivedFrom(source, target) { - return source.flags & 262144 ? ts.every(source.types, function (t) { return isTypeDerivedFrom(t, target); }) : - target.flags & 262144 ? ts.some(target.types, function (t) { return isTypeDerivedFrom(source, t); }) : - source.flags & 14745600 ? isTypeDerivedFrom(getBaseConstraintOfType(source) || emptyObjectType, target) : + return source.flags & 262144 /* Union */ ? ts.every(source.types, function (t) { return isTypeDerivedFrom(t, target); }) : + target.flags & 262144 /* Union */ ? ts.some(target.types, function (t) { return isTypeDerivedFrom(source, t); }) : + source.flags & 14745600 /* InstantiableNonPrimitive */ ? isTypeDerivedFrom(getBaseConstraintOfType(source) || emptyObjectType, target) : target === globalObjectType || target === globalFunctionType ? isTypeSubtypeOf(source, target) : hasBaseType(source, getTargetType(target)); } + /** + * This is *not* a bi-directional relationship. + * If one needs to check both directions for comparability, use a second call to this function or 'checkTypeComparableTo'. + * + * A type S is comparable to a type T if some (but not necessarily all) of the possible values of S are also possible values of T. + * It is used to check following cases: + * - the types of the left and right sides of equality/inequality operators (`===`, `!==`, `==`, `!=`). + * - the types of `case` clause expressions and their respective `switch` expressions. + * - the type of an expression in a type assertion with the type being asserted. + */ function isTypeComparableTo(source, target) { return isTypeRelatedTo(source, target, comparableRelation); } @@ -33165,38 +38318,48 @@ var ts; function checkTypeAssignableTo(source, target, errorNode, headMessage, containingMessageChain) { return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage, containingMessageChain); } + /** + * This is *not* a bi-directional relationship. + * If one needs to check both directions for comparability, use a second call to this function or 'isTypeComparableTo'. + */ function checkTypeComparableTo(source, target, errorNode, headMessage, containingMessageChain) { return checkTypeRelatedTo(source, target, comparableRelation, errorNode, headMessage, containingMessageChain); } function isSignatureAssignableTo(source, target, ignoreReturnTypes) { - return compareSignaturesRelated(source, target, 0, ignoreReturnTypes, false, undefined, compareTypesAssignable) !== 0; + return compareSignaturesRelated(source, target, 0 /* None */, ignoreReturnTypes, /*reportErrors*/ false, + /*errorReporter*/ undefined, compareTypesAssignable) !== 0 /* False */; } + /** + * See signatureRelatedTo, compareSignaturesIdentical + */ function compareSignaturesRelated(source, target, callbackCheck, ignoreReturnTypes, reportErrors, errorReporter, compareTypes) { + // TODO (drosen): De-duplicate code between related functions. if (source === target) { - return -1; + return -1 /* True */; } if (!target.hasRestParameter && source.minArgumentCount > target.parameters.length) { - return 0; + return 0 /* False */; } if (source.typeParameters && source.typeParameters !== target.typeParameters) { target = getCanonicalSignature(target); - source = instantiateSignatureInContextOf(source, target, undefined, compareTypes); + source = instantiateSignatureInContextOf(source, target, /*contextualMapper*/ undefined, compareTypes); } - var kind = target.declaration ? target.declaration.kind : 0; - var strictVariance = !callbackCheck && strictFunctionTypes && kind !== 154 && - kind !== 153 && kind !== 155; - var result = -1; + var kind = target.declaration ? target.declaration.kind : 0 /* Unknown */; + var strictVariance = !callbackCheck && strictFunctionTypes && kind !== 154 /* MethodDeclaration */ && + kind !== 153 /* MethodSignature */ && kind !== 155 /* Constructor */; + var result = -1 /* True */; var sourceThisType = getThisTypeOfSignature(source); if (sourceThisType && sourceThisType !== voidType) { var targetThisType = getThisTypeOfSignature(target); if (targetThisType) { - var related = !strictVariance && compareTypes(sourceThisType, targetThisType, false) + // void sources are assignable to anything. + var related = !strictVariance && compareTypes(sourceThisType, targetThisType, /*reportErrors*/ false) || compareTypes(targetThisType, sourceThisType, reportErrors); if (!related) { if (reportErrors) { errorReporter(ts.Diagnostics.The_this_types_of_each_signature_are_incompatible); } - return 0; + return 0 /* False */; } result &= related; } @@ -33209,18 +38372,27 @@ var ts; for (var i = 0; i < checkCount; i++) { var sourceType = i < sourceMax ? getTypeOfParameter(sourceParams[i]) : getRestTypeOfSignature(source); var targetType = i < targetMax ? getTypeOfParameter(targetParams[i]) : getRestTypeOfSignature(target); + // In order to ensure that any generic type Foo is at least co-variant with respect to T no matter + // how Foo uses T, we need to relate parameters bi-variantly (given that parameters are input positions, + // they naturally relate only contra-variantly). However, if the source and target parameters both have + // function types with a single call signature, we know we are relating two callback parameters. In + // that case it is sufficient to only relate the parameters of the signatures co-variantly because, + // similar to return values, callback parameters are output positions. This means that a Promise, + // where T is used only in callback parameter positions, will be co-variant (as opposed to bi-variant) + // with respect to T. var sourceSig = callbackCheck ? undefined : getSingleCallSignature(getNonNullableType(sourceType)); var targetSig = callbackCheck ? undefined : getSingleCallSignature(getNonNullableType(targetType)); var callbacks = sourceSig && targetSig && !signatureHasTypePredicate(sourceSig) && !signatureHasTypePredicate(targetSig) && - (getFalsyFlags(sourceType) & 24576) === (getFalsyFlags(targetType) & 24576); + (getFalsyFlags(sourceType) & 24576 /* Nullable */) === (getFalsyFlags(targetType) & 24576 /* Nullable */); var related = callbacks ? - compareSignaturesRelated(targetSig, sourceSig, strictVariance ? 2 : 1, false, reportErrors, errorReporter, compareTypes) : - !callbackCheck && !strictVariance && compareTypes(sourceType, targetType, false) || compareTypes(targetType, sourceType, reportErrors); + // TODO: GH#18217 It will work if they're both `undefined`, but not if only one is + compareSignaturesRelated(targetSig, sourceSig, strictVariance ? 2 /* Strict */ : 1 /* Bivariant */, /*ignoreReturnTypes*/ false, reportErrors, errorReporter, compareTypes) : + !callbackCheck && !strictVariance && compareTypes(sourceType, targetType, /*reportErrors*/ false) || compareTypes(targetType, sourceType, reportErrors); if (!related) { if (reportErrors) { errorReporter(ts.Diagnostics.Types_of_parameters_0_and_1_are_incompatible, ts.symbolName(sourceParams[i < sourceMax ? i : sourceMax]), ts.symbolName(targetParams[i < targetMax ? i : targetMax])); } - return 0; + return 0 /* False */; } result &= related; } @@ -33230,21 +38402,25 @@ var ts; return result; } var sourceReturnType = getReturnTypeOfSignature(source); + // The following block preserves behavior forbidding boolean returning functions from being assignable to type guard returning functions var targetTypePredicate = getTypePredicateOfSignature(target); if (targetTypePredicate) { var sourceTypePredicate = getTypePredicateOfSignature(source); if (sourceTypePredicate) { - result &= compareTypePredicateRelatedTo(sourceTypePredicate, targetTypePredicate, source.declaration, target.declaration, reportErrors, errorReporter, compareTypes); + result &= compareTypePredicateRelatedTo(sourceTypePredicate, targetTypePredicate, source.declaration, target.declaration, reportErrors, errorReporter, compareTypes); // TODO: GH#18217 } else if (ts.isIdentifierTypePredicate(targetTypePredicate)) { if (reportErrors) { errorReporter(ts.Diagnostics.Signature_0_must_be_a_type_predicate, signatureToString(source)); } - return 0; + return 0 /* False */; } } else { - result &= callbackCheck === 1 && compareTypes(targetReturnType, sourceReturnType, false) || + // When relating callback signatures, we still need to relate return types bi-variantly as otherwise + // the containing type wouldn't be co-variant. For example, interface Foo { add(cb: () => T): void } + // wouldn't be co-variant for T without this rule. + result &= callbackCheck === 1 /* Bivariant */ && compareTypes(targetReturnType, sourceReturnType, /*reportErrors*/ false) || compareTypes(sourceReturnType, targetReturnType, reportErrors); } } @@ -33256,9 +38432,9 @@ var ts; errorReporter(ts.Diagnostics.A_this_based_type_guard_is_not_compatible_with_a_parameter_based_type_guard); errorReporter(ts.Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); } - return 0; + return 0 /* False */; } - if (source.kind === 1) { + if (source.kind === 1 /* Identifier */) { var targetPredicate = target; var sourceIndex = source.parameterIndex - (ts.getThisParameter(sourceDeclaration) ? 1 : 0); var targetIndex = targetPredicate.parameterIndex - (ts.getThisParameter(targetDeclaration) ? 1 : 0); @@ -33267,11 +38443,11 @@ var ts; errorReporter(ts.Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, source.parameterName, targetPredicate.parameterName); errorReporter(ts.Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); } - return 0; + return 0 /* False */; } } var related = compareTypes(source.type, target.type, reportErrors); - if (related === 0 && reportErrors) { + if (related === 0 /* False */ && reportErrors) { errorReporter(ts.Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); } return related; @@ -33279,12 +38455,13 @@ var ts; function isImplementationCompatibleWithOverload(implementation, overload) { var erasedSource = getErasedSignature(implementation); var erasedTarget = getErasedSignature(overload); + // First see if the return types are compatible in either direction. var sourceReturnType = getReturnTypeOfSignature(erasedSource); var targetReturnType = getReturnTypeOfSignature(erasedTarget); if (targetReturnType === voidType || isTypeRelatedTo(targetReturnType, sourceReturnType, assignableRelation) || isTypeRelatedTo(sourceReturnType, targetReturnType, assignableRelation)) { - return isSignatureAssignableTo(erasedSource, erasedTarget, true); + return isSignatureAssignableTo(erasedSource, erasedTarget, /*ignoreReturnTypes*/ true); } return false; } @@ -33297,6 +38474,8 @@ var ts; function getNumParametersToCheckForSignatureRelatability(source, sourceNonRestParamCount, target, targetNonRestParamCount) { if (source.hasRestParameter === target.hasRestParameter) { if (source.hasRestParameter) { + // If both have rest parameters, get the max and add 1 to + // compensate for the rest parameter. return Math.max(sourceNonRestParamCount, targetNonRestParamCount) + 1; } else { @@ -33304,6 +38483,7 @@ var ts; } } else { + // Return the count for whichever signature doesn't have rest parameters. return source.hasRestParameter ? targetNonRestParamCount : sourceNonRestParamCount; @@ -33317,10 +38497,10 @@ var ts; !t.numberIndexInfo; } function isEmptyObjectType(type) { - return type.flags & 131072 ? isEmptyResolvedType(resolveStructuredTypeMembers(type)) : - type.flags & 16777216 ? true : - type.flags & 262144 ? ts.some(type.types, isEmptyObjectType) : - type.flags & 524288 ? ts.every(type.types, isEmptyObjectType) : + return type.flags & 131072 /* Object */ ? isEmptyResolvedType(resolveStructuredTypeMembers(type)) : + type.flags & 16777216 /* NonPrimitive */ ? true : + type.flags & 262144 /* Union */ ? ts.some(type.types, isEmptyObjectType) : + type.flags & 524288 /* Intersection */ ? ts.every(type.types, isEmptyObjectType) : false; } function isEnumTypeRelatedTo(sourceSymbol, targetSymbol, errorReporter) { @@ -33332,18 +38512,18 @@ var ts; if (relation !== undefined) { return relation; } - if (sourceSymbol.escapedName !== targetSymbol.escapedName || !(sourceSymbol.flags & 256) || !(targetSymbol.flags & 256)) { + if (sourceSymbol.escapedName !== targetSymbol.escapedName || !(sourceSymbol.flags & 256 /* RegularEnum */) || !(targetSymbol.flags & 256 /* RegularEnum */)) { enumRelation.set(id, false); return false; } var targetEnumType = getTypeOfSymbol(targetSymbol); for (var _i = 0, _a = getPropertiesOfType(getTypeOfSymbol(sourceSymbol)); _i < _a.length; _i++) { var property = _a[_i]; - if (property.flags & 8) { + if (property.flags & 8 /* EnumMember */) { var targetProperty = getPropertyOfType(targetEnumType, property.escapedName); - if (!targetProperty || !(targetProperty.flags & 8)) { + if (!targetProperty || !(targetProperty.flags & 8 /* EnumMember */)) { if (errorReporter) { - errorReporter(ts.Diagnostics.Property_0_is_missing_in_type_1, ts.symbolName(property), typeToString(getDeclaredTypeOfSymbol(targetSymbol), undefined, 64)); + errorReporter(ts.Diagnostics.Property_0_is_missing_in_type_1, ts.symbolName(property), typeToString(getDeclaredTypeOfSymbol(targetSymbol), /*enclosingDeclaration*/ undefined, 64 /* UseFullyQualifiedType */)); } enumRelation.set(id, false); return false; @@ -33356,78 +38536,91 @@ var ts; function isSimpleTypeRelatedTo(source, target, relation, errorReporter) { var s = source.flags; var t = target.flags; - if (t & 3 || s & 32768 || source === wildcardType) + if (t & 3 /* AnyOrUnknown */ || s & 32768 /* Never */ || source === wildcardType) return true; - if (t & 32768) + if (t & 32768 /* Never */) return false; - if (s & 68 && t & 4) + if (s & 68 /* StringLike */ && t & 4 /* String */) return true; - if (s & 64 && s & 512 && - t & 64 && !(t & 512) && + if (s & 64 /* StringLiteral */ && s & 512 /* EnumLiteral */ && + t & 64 /* StringLiteral */ && !(t & 512 /* EnumLiteral */) && source.value === target.value) return true; - if (s & 168 && t & 8) + if (s & 168 /* NumberLike */ && t & 8 /* Number */) return true; - if (s & 128 && s & 512 && - t & 128 && !(t & 512) && + if (s & 128 /* NumberLiteral */ && s & 512 /* EnumLiteral */ && + t & 128 /* NumberLiteral */ && !(t & 512 /* EnumLiteral */) && source.value === target.value) return true; - if (s & 272 && t & 16) + if (s & 272 /* BooleanLike */ && t & 16 /* Boolean */) return true; - if (s & 3072 && t & 1024) + if (s & 3072 /* ESSymbolLike */ && t & 1024 /* ESSymbol */) return true; - if (s & 32 && t & 32 && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) + if (s & 32 /* Enum */ && t & 32 /* Enum */ && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true; - if (s & 512 && t & 512) { - if (s & 262144 && t & 262144 && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) + if (s & 512 /* EnumLiteral */ && t & 512 /* EnumLiteral */) { + if (s & 262144 /* Union */ && t & 262144 /* Union */ && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true; - if (s & 448 && t & 448 && + if (s & 448 /* Literal */ && t & 448 /* Literal */ && source.value === target.value && isEnumTypeRelatedTo(getParentOfSymbol(source.symbol), getParentOfSymbol(target.symbol), errorReporter)) return true; } - if (s & 8192 && (!strictNullChecks || t & (8192 | 4096))) + if (s & 8192 /* Undefined */ && (!strictNullChecks || t & (8192 /* Undefined */ | 4096 /* Void */))) return true; - if (s & 16384 && (!strictNullChecks || t & 16384)) + if (s & 16384 /* Null */ && (!strictNullChecks || t & 16384 /* Null */)) return true; - if (s & 131072 && t & 16777216) + if (s & 131072 /* Object */ && t & 16777216 /* NonPrimitive */) return true; - if (s & 2048 || t & 2048) + if (s & 2048 /* UniqueESSymbol */ || t & 2048 /* UniqueESSymbol */) return false; if (relation === assignableRelation || relation === definitelyAssignableRelation || relation === comparableRelation) { - if (s & 1) + if (s & 1 /* Any */) return true; - if (s & (8 | 128) && !(s & 512) && (t & 32 || t & 128 && t & 512)) + // Type number or any numeric literal type is assignable to any numeric enum type or any + // numeric enum literal type. This rule exists for backwards compatibility reasons because + // bit-flag enum types sometimes look like literal enum types with numeric literal values. + if (s & (8 /* Number */ | 128 /* NumberLiteral */) && !(s & 512 /* EnumLiteral */) && (t & 32 /* Enum */ || t & 128 /* NumberLiteral */ && t & 512 /* EnumLiteral */)) return true; } return false; } function isTypeRelatedTo(source, target, relation) { - if (source.flags & 192 && source.flags & 33554432) { + if (source.flags & 192 /* StringOrNumberLiteral */ && source.flags & 33554432 /* FreshLiteral */) { source = source.regularType; } - if (target.flags & 192 && target.flags & 33554432) { + if (target.flags & 192 /* StringOrNumberLiteral */ && target.flags & 33554432 /* FreshLiteral */) { target = target.regularType; } if (source === target || - relation === comparableRelation && !(target.flags & 32768) && isSimpleTypeRelatedTo(target, source, relation) || + relation === comparableRelation && !(target.flags & 32768 /* Never */) && isSimpleTypeRelatedTo(target, source, relation) || relation !== identityRelation && isSimpleTypeRelatedTo(source, target, relation)) { return true; } - if (source.flags & 131072 && target.flags & 131072) { + if (source.flags & 131072 /* Object */ && target.flags & 131072 /* Object */) { var related = relation.get(getRelationKey(source, target, relation)); if (related !== undefined) { - return related === 1; + return related === 1 /* Succeeded */; } } - if (source.flags & 16711680 || target.flags & 16711680) { - return checkTypeRelatedTo(source, target, relation, undefined); + if (source.flags & 16711680 /* StructuredOrInstantiable */ || target.flags & 16711680 /* StructuredOrInstantiable */) { + return checkTypeRelatedTo(source, target, relation, /*errorNode*/ undefined); } return false; } function isIgnoredJsxProperty(source, sourceProp, targetMemberType) { - return ts.getObjectFlags(source) & 4096 && !(isUnhyphenatedJsxName(sourceProp.escapedName) || targetMemberType); + return ts.getObjectFlags(source) & 4096 /* JsxAttributes */ && !(isUnhyphenatedJsxName(sourceProp.escapedName) || targetMemberType); } + /** + * Checks if 'source' is related to 'target' (e.g.: is a assignable to). + * @param source The left-hand-side of the relation. + * @param target The right-hand-side of the relation. + * @param relation The relation considered. One of 'identityRelation', 'subtypeRelation', 'assignableRelation', or 'comparableRelation'. + * Used as both to determine which checks are performed and as a cache of previously computed results. + * @param errorNode The suggested node upon which all errors will be reported, if defined. This may or may not be the actual node used. + * @param headMessage If the error chain should be prepended by a head message, then headMessage will be used. + * @param containingMessageChain A chain of errors to prepend any new errors found. + */ function checkTypeRelatedTo(source, target, relation, errorNode, headMessage, containingMessageChain) { var errorInfo; var maybeKeys; @@ -33435,11 +38628,11 @@ var ts; var targetStack; var maybeCount = 0; var depth = 0; - var expandingFlags = 0; + var expandingFlags = 0 /* None */; var overflow = false; var isIntersectionConstituent = false; ts.Debug.assert(relation !== identityRelation || !errorNode, "no error reporting in identity checking"); - var result = isRelatedTo(source, target, !!errorNode, headMessage); + var result = isRelatedTo(source, target, /*reportErrors*/ !!errorNode, headMessage); if (overflow) { error(errorNode, ts.Diagnostics.Excessive_stack_depth_comparing_types_0_and_1, typeToString(source), typeToString(target)); } @@ -33451,19 +38644,21 @@ var ts; } } var relatedInformation = void 0; + // Check if we should issue an extra diagnostic to produce a quickfix for a slightly incorrect import statement if (headMessage && errorNode && !result && source.symbol) { var links = getSymbolLinks(source.symbol); if (links.originatingImport && !ts.isImportCall(links.originatingImport)) { - var helpfulRetry = checkTypeRelatedTo(getTypeOfSymbol(links.target), target, relation, undefined); + var helpfulRetry = checkTypeRelatedTo(getTypeOfSymbol(links.target), target, relation, /*errorNode*/ undefined); if (helpfulRetry) { + // Likely an incorrect import. Issue a helpful diagnostic to produce a quickfix to change the import var diag = ts.createDiagnosticForNode(links.originatingImport, ts.Diagnostics.Type_originates_at_this_import_A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_Consider_using_a_default_import_or_import_require_here_instead); - relatedInformation = ts.append(relatedInformation, diag); + relatedInformation = ts.append(relatedInformation, diag); // Cause the error to appear with the error that triggered it } } } - diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(errorNode, errorInfo, relatedInformation)); + diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(errorNode, errorInfo, relatedInformation)); // TODO: GH#18217 } - return result !== 0; + return result !== 0 /* False */; function reportError(message, arg0, arg1, arg2) { ts.Debug.assert(!!errorNode); errorInfo = ts.chainDiagnosticMessages(errorInfo, message, arg0, arg1, arg2); @@ -33472,8 +38667,8 @@ var ts; var sourceType = typeToString(source); var targetType = typeToString(target); if (sourceType === targetType) { - sourceType = typeToString(source, undefined, 64); - targetType = typeToString(target, undefined, 64); + sourceType = typeToString(source, /*enclosingDeclaration*/ undefined, 64 /* UseFullyQualifiedType */); + targetType = typeToString(target, /*enclosingDeclaration*/ undefined, 64 /* UseFullyQualifiedType */); } if (!message) { if (relation === comparableRelation) { @@ -33494,18 +38689,20 @@ var ts; if ((globalStringType === source && stringType === target) || (globalNumberType === source && numberType === target) || (globalBooleanType === source && booleanType === target) || - (getGlobalESSymbolType(false) === source && esSymbolType === target)) { + (getGlobalESSymbolType(/*reportErrors*/ false) === source && esSymbolType === target)) { reportError(ts.Diagnostics._0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible, targetType, sourceType); } } function isUnionOrIntersectionTypeWithoutNullableConstituents(type) { - if (!(type.flags & 786432)) { + if (!(type.flags & 786432 /* UnionOrIntersection */)) { return false; } + // at this point we know that this is union or intersection type possibly with nullable constituents. + // check if we still will have compound type if we ignore nullable components. var seenNonNullable = false; for (var _i = 0, _a = type.types; _i < _a.length; _i++) { var t = _a[_i]; - if (t.flags & 24576) { + if (t.flags & 24576 /* Nullable */) { continue; } if (seenNonNullable) { @@ -33515,95 +38712,131 @@ var ts; } return false; } + /** + * Compare two types and return + * * Ternary.True if they are related with no assumptions, + * * Ternary.Maybe if they are related with assumptions of other relationships, or + * * Ternary.False if they are not related. + */ function isRelatedTo(source, target, reportErrors, headMessage) { if (reportErrors === void 0) { reportErrors = false; } - if (source.flags & 192 && source.flags & 33554432) { + if (source.flags & 192 /* StringOrNumberLiteral */ && source.flags & 33554432 /* FreshLiteral */) { source = source.regularType; } - if (target.flags & 192 && target.flags & 33554432) { + if (target.flags & 192 /* StringOrNumberLiteral */ && target.flags & 33554432 /* FreshLiteral */) { target = target.regularType; } - if (source.flags & 8388608) { + if (source.flags & 8388608 /* Substitution */) { source = relation === definitelyAssignableRelation ? source.typeVariable : source.substitute; } - if (target.flags & 8388608) { + if (target.flags & 8388608 /* Substitution */) { target = target.typeVariable; } - if (source.flags & 2097152) { + if (source.flags & 2097152 /* IndexedAccess */) { source = getSimplifiedType(source); } - if (target.flags & 2097152) { + if (target.flags & 2097152 /* IndexedAccess */) { target = getSimplifiedType(target); } + // both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases if (source === target) - return -1; + return -1 /* True */; if (relation === identityRelation) { return isIdenticalTo(source, target); } - if (relation === comparableRelation && !(target.flags & 32768) && isSimpleTypeRelatedTo(target, source, relation) || + if (relation === comparableRelation && !(target.flags & 32768 /* Never */) && isSimpleTypeRelatedTo(target, source, relation) || isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) - return -1; - if (isObjectLiteralType(source) && source.flags & 33554432) { - var discriminantType = target.flags & 262144 ? findMatchingDiscriminantType(source, target) : undefined; + return -1 /* True */; + if (isObjectLiteralType(source) && source.flags & 33554432 /* FreshLiteral */) { + var discriminantType = target.flags & 262144 /* Union */ ? findMatchingDiscriminantType(source, target) : undefined; if (hasExcessProperties(source, target, discriminantType, reportErrors)) { if (reportErrors) { reportRelationError(headMessage, source, target); } - return 0; + return 0 /* False */; } + // Above we check for excess properties with respect to the entire target type. When union + // and intersection types are further deconstructed on the target side, we don't want to + // make the check again (as it might fail for a partial target type). Therefore we obtain + // the regular source type and proceed with that. if (isUnionOrIntersectionTypeWithoutNullableConstituents(target) && !discriminantType) { source = getRegularTypeOfObjectLiteral(source); } } if (relation !== comparableRelation && - !(source.flags & 786432) && - !(target.flags & 262144) && + !(source.flags & 786432 /* UnionOrIntersection */) && + !(target.flags & 262144 /* Union */) && !isIntersectionConstituent && source !== globalObjectType && (getPropertiesOfType(source).length > 0 || typeHasCallOrConstructSignatures(source)) && isWeakType(target) && !hasCommonProperties(source, target)) { if (reportErrors) { - var calls = getSignaturesOfType(source, 0); - var constructs = getSignaturesOfType(source, 1); - if (calls.length > 0 && isRelatedTo(getReturnTypeOfSignature(calls[0]), target, false) || - constructs.length > 0 && isRelatedTo(getReturnTypeOfSignature(constructs[0]), target, false)) { + var calls = getSignaturesOfType(source, 0 /* Call */); + var constructs = getSignaturesOfType(source, 1 /* Construct */); + if (calls.length > 0 && isRelatedTo(getReturnTypeOfSignature(calls[0]), target, /*reportErrors*/ false) || + constructs.length > 0 && isRelatedTo(getReturnTypeOfSignature(constructs[0]), target, /*reportErrors*/ false)) { reportError(ts.Diagnostics.Value_of_type_0_has_no_properties_in_common_with_type_1_Did_you_mean_to_call_it, typeToString(source), typeToString(target)); } else { reportError(ts.Diagnostics.Type_0_has_no_properties_in_common_with_type_1, typeToString(source), typeToString(target)); } } - return 0; + return 0 /* False */; } - var result = 0; + var result = 0 /* False */; var saveErrorInfo = errorInfo; var saveIsIntersectionConstituent = isIntersectionConstituent; isIntersectionConstituent = false; - if (source.flags & 262144) { + // Note that these checks are specifically ordered to produce correct results. In particular, + // we need to deconstruct unions before intersections (because unions are always at the top), + // and we need to handle "each" relations before "some" relations for the same kind of type. + if (source.flags & 262144 /* Union */) { result = relation === comparableRelation ? - someTypeRelatedToType(source, target, reportErrors && !(source.flags & 32764)) : - eachTypeRelatedToType(source, target, reportErrors && !(source.flags & 32764)); + someTypeRelatedToType(source, target, reportErrors && !(source.flags & 32764 /* Primitive */)) : + eachTypeRelatedToType(source, target, reportErrors && !(source.flags & 32764 /* Primitive */)); } else { - if (target.flags & 262144) { - result = typeRelatedToSomeType(source, target, reportErrors && !(source.flags & 32764) && !(target.flags & 32764)); + if (target.flags & 262144 /* Union */) { + result = typeRelatedToSomeType(source, target, reportErrors && !(source.flags & 32764 /* Primitive */) && !(target.flags & 32764 /* Primitive */)); } - else if (target.flags & 524288) { + else if (target.flags & 524288 /* Intersection */) { isIntersectionConstituent = true; result = typeRelatedToEachType(source, target, reportErrors); } - else if (source.flags & 524288) { - result = someTypeRelatedToType(source, target, false); + else if (source.flags & 524288 /* Intersection */) { + // Check to see if any constituents of the intersection are immediately related to the target. + // + // Don't report errors though. Checking whether a constituent is related to the source is not actually + // useful and leads to some confusing error messages. Instead it is better to let the below checks + // take care of this, or to not elaborate at all. For instance, + // + // - For an object type (such as 'C = A & B'), users are usually more interested in structural errors. + // + // - For a union type (such as '(A | B) = (C & D)'), it's better to hold onto the whole intersection + // than to report that 'D' is not assignable to 'A' or 'B'. + // + // - For a primitive type or type parameter (such as 'number = A & B') there is no point in + // breaking the intersection apart. + result = someTypeRelatedToType(source, target, /*reportErrors*/ false); } - if (!result && (source.flags & 16711680 || target.flags & 16711680)) { + if (!result && (source.flags & 16711680 /* StructuredOrInstantiable */ || target.flags & 16711680 /* StructuredOrInstantiable */)) { if (result = recursiveTypeRelatedTo(source, target, reportErrors)) { errorInfo = saveErrorInfo; } } } - if (!result && source.flags & 524288) { - var constraint = getUnionConstraintOfIntersection(source, !!(target.flags & 262144)); + if (!result && source.flags & 524288 /* Intersection */) { + // The combined constraint of an intersection type is the intersection of the constraints of + // the constituents. When an intersection type contains instantiable types with union type + // constraints, there are situations where we need to examine the combined constraint. One is + // when the target is a union type. Another is when the intersection contains types belonging + // to one of the disjoint domains. For example, given type variables T and U, each with the + // constraint 'string | number', the combined constraint of 'T & U' is 'string | number' and + // we need to check this constraint against a union on the target side. Also, given a type + // variable V constrained to 'string | number', 'V & number' has a combined constraint of + // 'string & number | number & number' which reduces to just 'number'. + var constraint = getUnionConstraintOfIntersection(source, !!(target.flags & 262144 /* Union */)); if (constraint) { if (result = isRelatedTo(constraint, target, reportErrors)) { errorInfo = saveErrorInfo; @@ -33612,18 +38845,19 @@ var ts; } isIntersectionConstituent = saveIsIntersectionConstituent; if (!result && reportErrors) { - if (source.flags & 131072 && target.flags & 32764) { + if (source.flags & 131072 /* Object */ && target.flags & 32764 /* Primitive */) { tryElaborateErrorsForPrimitivesAndObjects(source, target); } - else if (source.symbol && source.flags & 131072 && globalObjectType === source) { + else if (source.symbol && source.flags & 131072 /* Object */ && globalObjectType === source) { reportError(ts.Diagnostics.The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead); } - else if (ts.getObjectFlags(source) & 4096 && target.flags & 524288) { + else if (ts.getObjectFlags(source) & 4096 /* JsxAttributes */ && target.flags & 524288 /* Intersection */) { var targetTypes = target.types; var intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes, errorNode); var intrinsicClassAttributes = getJsxType(JsxNames.IntrinsicClassAttributes, errorNode); if (intrinsicAttributes !== errorType && intrinsicClassAttributes !== errorType && (ts.contains(targetTypes, intrinsicAttributes) || ts.contains(targetTypes, intrinsicClassAttributes))) { + // do not report top error return result; } } @@ -33634,32 +38868,32 @@ var ts; function isIdenticalTo(source, target) { var result; var flags = source.flags & target.flags; - if (flags & 131072) { - return recursiveTypeRelatedTo(source, target, false); + if (flags & 131072 /* Object */) { + return recursiveTypeRelatedTo(source, target, /*reportErrors*/ false); } - if (flags & (262144 | 524288)) { + if (flags & (262144 /* Union */ | 524288 /* Intersection */)) { if (result = eachTypeRelatedToSomeType(source, target)) { if (result &= eachTypeRelatedToSomeType(target, source)) { return result; } } } - if (flags & 1048576) { - return isRelatedTo(source.type, target.type, false); + if (flags & 1048576 /* Index */) { + return isRelatedTo(source.type, target.type, /*reportErrors*/ false); } - if (flags & 2097152) { - if (result = isRelatedTo(source.objectType, target.objectType, false)) { - if (result &= isRelatedTo(source.indexType, target.indexType, false)) { + if (flags & 2097152 /* IndexedAccess */) { + if (result = isRelatedTo(source.objectType, target.objectType, /*reportErrors*/ false)) { + if (result &= isRelatedTo(source.indexType, target.indexType, /*reportErrors*/ false)) { return result; } } } - if (flags & 4194304) { + if (flags & 4194304 /* Conditional */) { if (source.root.isDistributive === target.root.isDistributive) { - if (result = isRelatedTo(source.checkType, target.checkType, false)) { - if (result &= isRelatedTo(source.extendsType, target.extendsType, false)) { - if (result &= isRelatedTo(getTrueTypeFromConditionalType(source), getTrueTypeFromConditionalType(target), false)) { - if (result &= isRelatedTo(getFalseTypeFromConditionalType(source), getFalseTypeFromConditionalType(target), false)) { + if (result = isRelatedTo(source.checkType, target.checkType, /*reportErrors*/ false)) { + if (result &= isRelatedTo(source.extendsType, target.extendsType, /*reportErrors*/ false)) { + if (result &= isRelatedTo(getTrueTypeFromConditionalType(source), getTrueTypeFromConditionalType(target), /*reportErrors*/ false)) { + if (result &= isRelatedTo(getFalseTypeFromConditionalType(source), getFalseTypeFromConditionalType(target), /*reportErrors*/ false)) { return result; } } @@ -33667,30 +38901,37 @@ var ts; } } } - if (flags & 8388608) { - return isRelatedTo(source.substitute, target.substitute, false); + if (flags & 8388608 /* Substitution */) { + return isRelatedTo(source.substitute, target.substitute, /*reportErrors*/ false); } - return 0; + return 0 /* False */; } function hasExcessProperties(source, target, discriminant, reportErrors) { - if (maybeTypeOfKind(target, 131072) && !(ts.getObjectFlags(target) & 512)) { - var isComparingJsxAttributes = !!(ts.getObjectFlags(source) & 4096); + if (maybeTypeOfKind(target, 131072 /* Object */) && !(ts.getObjectFlags(target) & 512 /* ObjectLiteralPatternWithComputedProperties */)) { + var isComparingJsxAttributes = !!(ts.getObjectFlags(source) & 4096 /* JsxAttributes */); if ((relation === assignableRelation || relation === definitelyAssignableRelation || relation === comparableRelation) && (isTypeSubsetOf(globalObjectType, target) || (!isComparingJsxAttributes && isEmptyObjectType(target)))) { return false; } if (discriminant) { - return hasExcessProperties(source, discriminant, undefined, reportErrors); + // check excess properties against discriminant type only, not the entire union + return hasExcessProperties(source, discriminant, /*discriminant*/ undefined, reportErrors); } var _loop_7 = function (prop) { if (!isKnownProperty(target, prop.escapedName, isComparingJsxAttributes)) { if (reportErrors) { + // We know *exactly* where things went wrong when comparing the types. + // Use this property as the error node as this will be more helpful in + // reasoning about what went wrong. if (!errorNode) return { value: ts.Debug.fail() }; if (ts.isJsxAttributes(errorNode) || ts.isJsxOpeningLikeElement(errorNode)) { + // JsxAttributes has an object-literal flag and undergo same type-assignablity check as normal object-literal. + // However, using an object-literal error message will be very confusing to the users so we give different a message. reportError(ts.Diagnostics.Property_0_does_not_exist_on_type_1, symbolToString(prop), typeToString(target)); } else { + // use the property's value declaration if the property is assigned inside the literal itself var objectLiteralDeclaration_1 = source.symbol && ts.firstOrUndefined(source.symbol.declarations); var suggestion = void 0; if (prop.valueDeclaration && ts.findAncestor(prop.valueDeclaration, function (d) { return d === objectLiteralDeclaration_1; })) { @@ -33723,13 +38964,13 @@ var ts; return false; } function eachTypeRelatedToSomeType(source, target) { - var result = -1; + var result = -1 /* True */; var sourceTypes = source.types; for (var _i = 0, sourceTypes_1 = sourceTypes; _i < sourceTypes_1.length; _i++) { var sourceType = sourceTypes_1[_i]; - var related = typeRelatedToSomeType(sourceType, target, false); + var related = typeRelatedToSomeType(sourceType, target, /*reportErrors*/ false); if (!related) { - return 0; + return 0 /* False */; } result &= related; } @@ -33737,22 +38978,23 @@ var ts; } function typeRelatedToSomeType(source, target, reportErrors) { var targetTypes = target.types; - if (target.flags & 262144 && containsType(targetTypes, source)) { - return -1; + if (target.flags & 262144 /* Union */ && containsType(targetTypes, source)) { + return -1 /* True */; } for (var _i = 0, targetTypes_1 = targetTypes; _i < targetTypes_1.length; _i++) { var type = targetTypes_1[_i]; - var related = isRelatedTo(source, type, false); + var related = isRelatedTo(source, type, /*reportErrors*/ false); if (related) { return related; } } if (reportErrors) { var discriminantType = findMatchingDiscriminantType(source, target); - isRelatedTo(source, discriminantType || targetTypes[targetTypes.length - 1], true); + isRelatedTo(source, discriminantType || targetTypes[targetTypes.length - 1], /*reportErrors*/ true); } - return 0; + return 0 /* False */; } + // Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly function findMatchingDiscriminantType(source, target) { var match; var sourceProperties = getPropertiesOfObjectType(source); @@ -33767,7 +39009,7 @@ var ts; var targetType = getTypeOfPropertyOfType(type, sourceProperty.escapedName); if (targetType && isRelatedTo(sourceType, targetType)) { if (type === match) - continue; + continue; // Finding multiple fields which discriminate to the same type is fine if (match) { return undefined; } @@ -33780,13 +39022,13 @@ var ts; return match; } function typeRelatedToEachType(source, target, reportErrors) { - var result = -1; + var result = -1 /* True */; var targetTypes = target.types; for (var _i = 0, targetTypes_2 = targetTypes; _i < targetTypes_2.length; _i++) { var targetType = targetTypes_2[_i]; var related = isRelatedTo(source, targetType, reportErrors); if (!related) { - return 0; + return 0 /* False */; } result &= related; } @@ -33794,8 +39036,8 @@ var ts; } function someTypeRelatedToType(source, target, reportErrors) { var sourceTypes = source.types; - if (source.flags & 262144 && containsType(sourceTypes, target)) { - return -1; + if (source.flags & 262144 /* Union */ && containsType(sourceTypes, target)) { + return -1 /* True */; } var len = sourceTypes.length; for (var i = 0; i < len; i++) { @@ -33804,16 +39046,16 @@ var ts; return related; } } - return 0; + return 0 /* False */; } function eachTypeRelatedToType(source, target, reportErrors) { - var result = -1; + var result = -1 /* True */; var sourceTypes = source.types; for (var _i = 0, sourceTypes_2 = sourceTypes; _i < sourceTypes_2.length; _i++) { var sourceType = sourceTypes_2[_i]; var related = isRelatedTo(sourceType, target, reportErrors); if (!related) { - return 0; + return 0 /* False */; } result &= related; } @@ -33823,54 +39065,72 @@ var ts; var sources = source.typeArguments || ts.emptyArray; var targets = target.typeArguments || ts.emptyArray; if (sources.length !== targets.length && relation === identityRelation) { - return 0; + return 0 /* False */; } var length = sources.length <= targets.length ? sources.length : targets.length; - var result = -1; + var result = -1 /* True */; for (var i = 0; i < length; i++) { - var variance = i < variances.length ? variances[i] : 1; - if (variance !== 4) { + // When variance information isn't available we default to covariance. This happens + // in the process of computing variance information for recursive types and when + // comparing 'this' type arguments. + var variance = i < variances.length ? variances[i] : 1 /* Covariant */; + // We ignore arguments for independent type parameters (because they're never witnessed). + if (variance !== 4 /* Independent */) { var s = sources[i]; var t = targets[i]; - var related = -1; - if (variance === 1) { + var related = -1 /* True */; + if (variance === 1 /* Covariant */) { related = isRelatedTo(s, t, reportErrors); } - else if (variance === 2) { + else if (variance === 2 /* Contravariant */) { related = isRelatedTo(t, s, reportErrors); } - else if (variance === 3) { - related = isRelatedTo(t, s, false); + else if (variance === 3 /* Bivariant */) { + // In the bivariant case we first compare contravariantly without reporting + // errors. Then, if that doesn't succeed, we compare covariantly with error + // reporting. Thus, error elaboration will be based on the the covariant check, + // which is generally easier to reason about. + related = isRelatedTo(t, s, /*reportErrors*/ false); if (!related) { related = isRelatedTo(s, t, reportErrors); } } else { + // In the invariant case we first compare covariantly, and only when that + // succeeds do we proceed to compare contravariantly. Thus, error elaboration + // will typically be based on the covariant check. related = isRelatedTo(s, t, reportErrors); if (related) { related &= isRelatedTo(t, s, reportErrors); } } if (!related) { - return 0; + return 0 /* False */; } result &= related; } } return result; } + // Determine if possibly recursive types are related. First, check if the result is already available in the global cache. + // Second, check if we have already started a comparison of the given two types in which case we assume the result to be true. + // Third, check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are + // equal and infinitely expanding. Fourth, if we have reached a depth of 100 nested comparisons, assume we have runaway recursion + // and issue an error. Otherwise, actually compare the structure of the two types. function recursiveTypeRelatedTo(source, target, reportErrors) { if (overflow) { - return 0; + return 0 /* False */; } var id = getRelationKey(source, target, relation); var related = relation.get(id); if (related !== undefined) { - if (reportErrors && related === 2) { - relation.set(id, 3); + if (reportErrors && related === 2 /* Failed */) { + // We are elaborating errors and the cached result is an unreported failure. Record the result as a reported + // failure and continue computing the relation such that errors get reported. + relation.set(id, 3 /* FailedAndReported */); } else { - return related === 1 ? -1 : 0; + return related === 1 /* Succeeded */ ? -1 /* True */ : 0 /* False */; } } if (!maybeKeys) { @@ -33880,13 +39140,14 @@ var ts; } else { for (var i = 0; i < maybeCount; i++) { + // If source and target are already being compared, consider them related with assumptions if (id === maybeKeys[i]) { - return 1; + return 1 /* Maybe */; } } if (depth === 100) { overflow = true; - return 0; + return 0 /* False */; } } var maybeStart = maybeCount; @@ -33896,23 +39157,26 @@ var ts; targetStack[depth] = target; depth++; var saveExpandingFlags = expandingFlags; - if (!(expandingFlags & 1) && isDeeplyNestedType(source, sourceStack, depth)) - expandingFlags |= 1; - if (!(expandingFlags & 2) && isDeeplyNestedType(target, targetStack, depth)) - expandingFlags |= 2; - var result = expandingFlags !== 3 ? structuredTypeRelatedTo(source, target, reportErrors) : 1; + if (!(expandingFlags & 1 /* Source */) && isDeeplyNestedType(source, sourceStack, depth)) + expandingFlags |= 1 /* Source */; + if (!(expandingFlags & 2 /* Target */) && isDeeplyNestedType(target, targetStack, depth)) + expandingFlags |= 2 /* Target */; + var result = expandingFlags !== 3 /* Both */ ? structuredTypeRelatedTo(source, target, reportErrors) : 1 /* Maybe */; expandingFlags = saveExpandingFlags; depth--; if (result) { - if (result === -1 || depth === 0) { + if (result === -1 /* True */ || depth === 0) { + // If result is definitely true, record all maybe keys as having succeeded for (var i = maybeStart; i < maybeCount; i++) { - relation.set(maybeKeys[i], 1); + relation.set(maybeKeys[i], 1 /* Succeeded */); } maybeCount = maybeStart; } } else { - relation.set(id, reportErrors ? 3 : 2); + // A false result goes straight into global cache (when something is false under + // assumptions it will also be false without assumptions) + relation.set(id, reportErrors ? 3 /* FailedAndReported */ : 2 /* Failed */); maybeCount = maybeStart; } return result; @@ -33924,9 +39188,10 @@ var ts; var result; var originalErrorInfo; var saveErrorInfo = errorInfo; - if (target.flags & 65536) { - if (ts.getObjectFlags(source) & 32 && getConstraintTypeFromMappedType(source) === getIndexType(target)) { - if (!(getMappedTypeModifiers(source) & 4)) { + if (target.flags & 65536 /* TypeParameter */) { + // A source type { [P in keyof T]: X } is related to a target type T if X is related to T[P]. + if (ts.getObjectFlags(source) & 32 /* Mapped */ && getConstraintTypeFromMappedType(source) === getIndexType(target)) { + if (!(getMappedTypeModifiers(source) & 4 /* IncludeOptional */)) { var templateType = getTemplateTypeFromMappedType(source); var indexedAccessType = getIndexedAccessType(target, getTypeParameterFromMappedType(source)); if (result = isRelatedTo(templateType, indexedAccessType, reportErrors)) { @@ -33935,12 +39200,15 @@ var ts; } } } - else if (target.flags & 1048576) { - if (source.flags & 1048576) { - if (result = isRelatedTo(target.type, source.type, false)) { + else if (target.flags & 1048576 /* Index */) { + // A keyof S is related to a keyof T if T is related to S. + if (source.flags & 1048576 /* Index */) { + if (result = isRelatedTo(target.type, source.type, /*reportErrors*/ false)) { return result; } } + // A type S is assignable to keyof T if S is assignable to keyof C, where C is the + // simplified form of T or, if T doesn't simplify, the constraint of T. if (relation !== definitelyAssignableRelation) { var simplified = getSimplifiedType(target.type); var constraint = simplified !== target.type ? simplified : getConstraintOfType(target.type); @@ -33951,7 +39219,9 @@ var ts; } } } - else if (target.flags & 2097152) { + else if (target.flags & 2097152 /* IndexedAccess */) { + // A type S is related to a type T[K] if S is related to C, where C is the + // constraint of T[K] var constraint = getConstraintForRelation(target); if (constraint) { if (result = isRelatedTo(source, constraint, reportErrors)) { @@ -33961,13 +39231,15 @@ var ts; } } else if (isGenericMappedType(target)) { + // A source type T is related to a target type { [P in X]: T[P] } var template = getTemplateTypeFromMappedType(target); var modifiers = getMappedTypeModifiers(target); - if (!(modifiers & 8)) { - if (template.flags & 2097152 && template.objectType === source && + if (!(modifiers & 8 /* ExcludeOptional */)) { + if (template.flags & 2097152 /* IndexedAccess */ && template.objectType === source && template.indexType === getTypeParameterFromMappedType(target)) { - return -1; + return -1 /* True */; } + // A source type T is related to a target type { [P in keyof T]: X } if T[P] is related to X. if (!isGenericMappedType(source) && getConstraintTypeFromMappedType(target) === getIndexType(source)) { var indexedAccessType = getIndexedAccessType(source, getTypeParameterFromMappedType(target)); var templateType = getTemplateTypeFromMappedType(target); @@ -33978,8 +39250,9 @@ var ts; } } } - if (source.flags & 2162688) { - if (source.flags & 2097152 && target.flags & 2097152) { + if (source.flags & 2162688 /* TypeVariable */) { + if (source.flags & 2097152 /* IndexedAccess */ && target.flags & 2097152 /* IndexedAccess */) { + // A type S[K] is related to a type T[J] if S is related to T and K is related to J. if (result = isRelatedTo(source.objectType, target.objectType, reportErrors)) { result &= isRelatedTo(source.indexType, target.indexType, reportErrors); } @@ -33989,8 +39262,9 @@ var ts; } } var constraint = getConstraintForRelation(source); - if (!constraint || (source.flags & 65536 && constraint.flags & 3)) { - if (result = isRelatedTo(emptyObjectType, extractTypesOfKind(target, ~16777216))) { + if (!constraint || (source.flags & 65536 /* TypeParameter */ && constraint.flags & 3 /* AnyOrUnknown */)) { + // A type variable with no constraint is not related to the non-primitive object type. + if (result = isRelatedTo(emptyObjectType, extractTypesOfKind(target, ~16777216 /* NonPrimitive */))) { errorInfo = saveErrorInfo; return result; } @@ -34003,14 +39277,17 @@ var ts; } } } - else if (source.flags & 1048576) { + else if (source.flags & 1048576 /* Index */) { if (result = isRelatedTo(keyofConstraintType, target, reportErrors)) { errorInfo = saveErrorInfo; return result; } } - else if (source.flags & 4194304) { - if (target.flags & 4194304) { + else if (source.flags & 4194304 /* Conditional */) { + if (target.flags & 4194304 /* Conditional */) { + // Two conditional types 'T1 extends U1 ? X1 : Y1' and 'T2 extends U2 ? X2 : Y2' are related if + // one of T1 and T2 is related to the other, U1 and U2 are identical types, X1 is related to X2, + // and Y1 is related to Y2. if (isTypeIdenticalTo(source.extendsType, target.extendsType) && (isRelatedTo(source.checkType, target.checkType) || isRelatedTo(target.checkType, source.checkType))) { if (result = isRelatedTo(getTrueTypeFromConditionalType(source), getTrueTypeFromConditionalType(target), reportErrors)) { @@ -34040,42 +39317,68 @@ var ts; } } else { - if (ts.getObjectFlags(source) & 4 && ts.getObjectFlags(target) & 4 && source.target === target.target && - !(ts.getObjectFlags(source) & 8192 || ts.getObjectFlags(target) & 8192)) { + if (ts.getObjectFlags(source) & 4 /* Reference */ && ts.getObjectFlags(target) & 4 /* Reference */ && source.target === target.target && + !(ts.getObjectFlags(source) & 8192 /* MarkerType */ || ts.getObjectFlags(target) & 8192 /* MarkerType */)) { + // We have type references to the same generic type, and the type references are not marker + // type references (which are intended by be compared structurally). Obtain the variance + // information for the type parameters and relate the type arguments accordingly. var variances = getVariances(source.target); if (result = typeArgumentsRelatedTo(source, target, variances, reportErrors)) { return result; } + // The type arguments did not relate appropriately, but it may be because we have no variance + // information (in which case typeArgumentsRelatedTo defaulted to covariance for all type + // arguments). It might also be the case that the target type has a 'void' type argument for + // a covariant type parameter that is only used in return positions within the generic type + // (in which case any type argument is permitted on the source side). In those cases we proceed + // with a structural comparison. Otherwise, we know for certain the instantiations aren't + // related and we can return here. if (variances !== ts.emptyArray && !hasCovariantVoidArgument(target, variances)) { - if (!(reportErrors && ts.some(variances, function (v) { return v === 0; }))) { - return 0; + // In some cases generic types that are covariant in regular type checking mode become + // invariant in --strictFunctionTypes mode because one or more type parameters are used in + // both co- and contravariant positions. In order to make it easier to diagnose *why* such + // types are invariant, if any of the type parameters are invariant we reset the reported + // errors and instead force a structural comparison (which will include elaborations that + // reveal the reason). + if (!(reportErrors && ts.some(variances, function (v) { return v === 0 /* Invariant */; }))) { + return 0 /* False */; } + // We remember the original error information so we can restore it in case the structural + // comparison unexpectedly succeeds. This can happen when the structural comparison result + // is a Ternary.Maybe for example caused by the recursion depth limiter. originalErrorInfo = errorInfo; errorInfo = saveErrorInfo; } } - var sourceIsPrimitive = !!(source.flags & 32764); + // Even if relationship doesn't hold for unions, intersections, or generic type references, + // it may hold in a structural comparison. + var sourceIsPrimitive = !!(source.flags & 32764 /* Primitive */); if (relation !== identityRelation) { source = getApparentType(source); } - if (source.flags & (131072 | 524288) && target.flags & 131072) { + // In a check of the form X = A & B, we will have previously checked if A relates to X or B relates + // to X. Failing both of those we want to check if the aggregation of A and B's members structurally + // relates to X. Thus, we include intersection types on the source side here. + if (source.flags & (131072 /* Object */ | 524288 /* Intersection */) && target.flags & 131072 /* Object */) { + // Report structural errors only if we haven't reported any errors yet var reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo && !sourceIsPrimitive; + // An empty object type is related to any mapped type that includes a '?' modifier. if (isPartialMappedType(target) && !isGenericMappedType(source) && isEmptyObjectType(source)) { - result = -1; + result = -1 /* True */; } else if (isGenericMappedType(target)) { - result = isGenericMappedType(source) ? mappedTypeRelatedTo(source, target, reportStructuralErrors) : 0; + result = isGenericMappedType(source) ? mappedTypeRelatedTo(source, target, reportStructuralErrors) : 0 /* False */; } else { result = propertiesRelatedTo(source, target, reportStructuralErrors); if (result) { - result &= signaturesRelatedTo(source, target, 0, reportStructuralErrors); + result &= signaturesRelatedTo(source, target, 0 /* Call */, reportStructuralErrors); if (result) { - result &= signaturesRelatedTo(source, target, 1, reportStructuralErrors); + result &= signaturesRelatedTo(source, target, 1 /* Construct */, reportStructuralErrors); if (result) { - result &= indexTypesRelatedTo(source, target, 0, sourceIsPrimitive, reportStructuralErrors); + result &= indexTypesRelatedTo(source, target, 0 /* String */, sourceIsPrimitive, reportStructuralErrors); if (result) { - result &= indexTypesRelatedTo(source, target, 1, sourceIsPrimitive, reportStructuralErrors); + result &= indexTypesRelatedTo(source, target, 1 /* Number */, sourceIsPrimitive, reportStructuralErrors); } } } @@ -34090,8 +39393,11 @@ var ts; } } } - return 0; + return 0 /* False */; } + // A type [P in S]: X is related to a type [Q in T]: Y if T is related to S and X' is + // related to Y, where X' is an instantiation of X in which P is replaced with Q. Notice + // that S and T are contra-variant whereas X and Y are co-variant. function mappedTypeRelatedTo(source, target, reportErrors) { var modifiersRelated = relation === comparableRelation || (relation === identityRelation ? getMappedTypeModifiers(source) === getMappedTypeModifiers(target) : getCombinedMappedTypeOptionality(source) <= getCombinedMappedTypeOptionality(target)); @@ -34102,7 +39408,7 @@ var ts; return result_2 & isRelatedTo(instantiateType(getTemplateTypeFromMappedType(source), mapper), getTemplateTypeFromMappedType(target), reportErrors); } } - return 0; + return 0 /* False */; } function propertiesRelatedTo(source, target, reportErrors) { if (relation === identityRelation) { @@ -34114,7 +39420,7 @@ var ts; if (reportErrors) { reportError(ts.Diagnostics.Property_0_is_missing_in_type_1, symbolToString(unmatchedProperty), typeToString(source)); } - return 0; + return 0 /* False */; } if (isObjectLiteralType(target)) { for (var _i = 0, _a = getPropertiesOfType(source); _i < _a.length; _i++) { @@ -34125,16 +39431,16 @@ var ts; if (reportErrors) { reportError(ts.Diagnostics.Property_0_does_not_exist_on_type_1, symbolToString(sourceProp), typeToString(target)); } - return 0; + return 0 /* False */; } } } } - var result = -1; + var result = -1 /* True */; var properties = getPropertiesOfObjectType(target); for (var _b = 0, properties_3 = properties; _b < properties_3.length; _b++) { var targetProp = properties_3[_b]; - if (!(targetProp.flags & 4194304)) { + if (!(targetProp.flags & 4194304 /* Prototype */)) { var sourceProp = getPropertyOfType(source, targetProp.escapedName); if (sourceProp && sourceProp !== targetProp) { if (isIgnoredJsxProperty(source, sourceProp, getTypeOfSymbol(targetProp))) { @@ -34142,74 +39448,86 @@ var ts; } var sourcePropFlags = ts.getDeclarationModifierFlagsFromSymbol(sourceProp); var targetPropFlags = ts.getDeclarationModifierFlagsFromSymbol(targetProp); - if (sourcePropFlags & 8 || targetPropFlags & 8) { + if (sourcePropFlags & 8 /* Private */ || targetPropFlags & 8 /* Private */) { var hasDifferingDeclarations = sourceProp.valueDeclaration !== targetProp.valueDeclaration; - if (ts.getCheckFlags(sourceProp) & 256 && hasDifferingDeclarations) { + if (ts.getCheckFlags(sourceProp) & 256 /* ContainsPrivate */ && hasDifferingDeclarations) { if (reportErrors) { reportError(ts.Diagnostics.Property_0_has_conflicting_declarations_and_is_inaccessible_in_type_1, symbolToString(sourceProp), typeToString(source)); } - return 0; + return 0 /* False */; } if (hasDifferingDeclarations) { if (reportErrors) { - if (sourcePropFlags & 8 && targetPropFlags & 8) { + if (sourcePropFlags & 8 /* Private */ && targetPropFlags & 8 /* Private */) { reportError(ts.Diagnostics.Types_have_separate_declarations_of_a_private_property_0, symbolToString(targetProp)); } else { - reportError(ts.Diagnostics.Property_0_is_private_in_type_1_but_not_in_type_2, symbolToString(targetProp), typeToString(sourcePropFlags & 8 ? source : target), typeToString(sourcePropFlags & 8 ? target : source)); + reportError(ts.Diagnostics.Property_0_is_private_in_type_1_but_not_in_type_2, symbolToString(targetProp), typeToString(sourcePropFlags & 8 /* Private */ ? source : target), typeToString(sourcePropFlags & 8 /* Private */ ? target : source)); } } - return 0; + return 0 /* False */; } } - else if (targetPropFlags & 16) { + else if (targetPropFlags & 16 /* Protected */) { if (!isValidOverrideOf(sourceProp, targetProp)) { if (reportErrors) { reportError(ts.Diagnostics.Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2, symbolToString(targetProp), typeToString(getDeclaringClass(sourceProp) || source), typeToString(getDeclaringClass(targetProp) || target)); } - return 0; + return 0 /* False */; } } - else if (sourcePropFlags & 16) { + else if (sourcePropFlags & 16 /* Protected */) { if (reportErrors) { reportError(ts.Diagnostics.Property_0_is_protected_in_type_1_but_public_in_type_2, symbolToString(targetProp), typeToString(source), typeToString(target)); } - return 0; + return 0 /* False */; } var related = isRelatedTo(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp), reportErrors); if (!related) { if (reportErrors) { reportError(ts.Diagnostics.Types_of_property_0_are_incompatible, symbolToString(targetProp)); } - return 0; + return 0 /* False */; } result &= related; - if (relation !== comparableRelation && sourceProp.flags & 16777216 && !(targetProp.flags & 16777216)) { + // When checking for comparability, be more lenient with optional properties. + if (relation !== comparableRelation && sourceProp.flags & 16777216 /* Optional */ && !(targetProp.flags & 16777216 /* Optional */)) { + // TypeScript 1.0 spec (April 2014): 3.8.3 + // S is a subtype of a type T, and T is a supertype of S if ... + // S' and T are object types and, for each member M in T.. + // M is a property and S' contains a property N where + // if M is a required property, N is also a required property + // (M - property in T) + // (N - property in S) if (reportErrors) { reportError(ts.Diagnostics.Property_0_is_optional_in_type_1_but_required_in_type_2, symbolToString(targetProp), typeToString(source), typeToString(target)); } - return 0; + return 0 /* False */; } } } } return result; } + /** + * A type is 'weak' if it is an object type with at least one optional property + * and no required properties, call/construct signatures or index signatures + */ function isWeakType(type) { - if (type.flags & 131072) { + if (type.flags & 131072 /* Object */) { var resolved = resolveStructuredTypeMembers(type); return resolved.callSignatures.length === 0 && resolved.constructSignatures.length === 0 && !resolved.stringIndexInfo && !resolved.numberIndexInfo && resolved.properties.length > 0 && - ts.every(resolved.properties, function (p) { return !!(p.flags & 16777216); }); + ts.every(resolved.properties, function (p) { return !!(p.flags & 16777216 /* Optional */); }); } - if (type.flags & 524288) { + if (type.flags & 524288 /* Intersection */) { return ts.every(type.types, isWeakType); } return false; } function hasCommonProperties(source, target) { - var isComparingJsxAttributes = !!(ts.getObjectFlags(source) & 4096); + var isComparingJsxAttributes = !!(ts.getObjectFlags(source) & 4096 /* JsxAttributes */); for (var _i = 0, _a = getPropertiesOfType(source); _i < _a.length; _i++) { var prop = _a[_i]; if (isKnownProperty(target, prop.escapedName, isComparingJsxAttributes)) { @@ -34219,24 +39537,24 @@ var ts; return false; } function propertiesIdenticalTo(source, target) { - if (!(source.flags & 131072 && target.flags & 131072)) { - return 0; + if (!(source.flags & 131072 /* Object */ && target.flags & 131072 /* Object */)) { + return 0 /* False */; } var sourceProperties = getPropertiesOfObjectType(source); var targetProperties = getPropertiesOfObjectType(target); if (sourceProperties.length !== targetProperties.length) { - return 0; + return 0 /* False */; } - var result = -1; + var result = -1 /* True */; for (var _i = 0, sourceProperties_1 = sourceProperties; _i < sourceProperties_1.length; _i++) { var sourceProp = sourceProperties_1[_i]; var targetProp = getPropertyOfObjectType(target, sourceProp.escapedName); if (!targetProp) { - return 0; + return 0 /* False */; } var related = compareProperties(sourceProp, targetProp, isRelatedTo); if (!related) { - return 0; + return 0 /* False */; } result &= related; } @@ -34247,43 +39565,57 @@ var ts; return signaturesIdenticalTo(source, target, kind); } if (target === anyFunctionType || source === anyFunctionType) { - return -1; + return -1 /* True */; } var sourceSignatures = getSignaturesOfType(source, kind); var targetSignatures = getSignaturesOfType(target, kind); - if (kind === 1 && sourceSignatures.length && targetSignatures.length) { + if (kind === 1 /* Construct */ && sourceSignatures.length && targetSignatures.length) { if (ts.isAbstractConstructorType(source) && !ts.isAbstractConstructorType(target)) { + // An abstract constructor type is not assignable to a non-abstract constructor type + // as it would otherwise be possible to new an abstract class. Note that the assignability + // check we perform for an extends clause excludes construct signatures from the target, + // so this check never proceeds. if (reportErrors) { reportError(ts.Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type); } - return 0; + return 0 /* False */; } if (!constructorVisibilitiesAreCompatible(sourceSignatures[0], targetSignatures[0], reportErrors)) { - return 0; + return 0 /* False */; } } - var result = -1; + var result = -1 /* True */; var saveErrorInfo = errorInfo; - if (ts.getObjectFlags(source) & 64 && ts.getObjectFlags(target) & 64 && source.symbol === target.symbol) { + if (ts.getObjectFlags(source) & 64 /* Instantiated */ && ts.getObjectFlags(target) & 64 /* Instantiated */ && source.symbol === target.symbol) { + // We have instantiations of the same anonymous type (which typically will be the type of a + // method). Simply do a pairwise comparison of the signatures in the two signature lists instead + // of the much more expensive N * M comparison matrix we explore below. We erase type parameters + // as they are known to always be the same. for (var i = 0; i < targetSignatures.length; i++) { - var related = signatureRelatedTo(sourceSignatures[i], targetSignatures[i], true, reportErrors); + var related = signatureRelatedTo(sourceSignatures[i], targetSignatures[i], /*erase*/ true, reportErrors); if (!related) { - return 0; + return 0 /* False */; } result &= related; } } else if (sourceSignatures.length === 1 && targetSignatures.length === 1) { + // For simple functions (functions with a single signature) we only erase type parameters for + // the comparable relation. Otherwise, if the source signature is generic, we instantiate it + // in the context of the target signature before checking the relationship. Ideally we'd do + // this regardless of the number of signatures, but the potential costs are prohibitive due + // to the quadratic nature of the logic below. var eraseGenerics = relation === comparableRelation || !!compilerOptions.noStrictGenericChecks; result = signatureRelatedTo(sourceSignatures[0], targetSignatures[0], eraseGenerics, reportErrors); } else { outer: for (var _i = 0, targetSignatures_1 = targetSignatures; _i < targetSignatures_1.length; _i++) { var t = targetSignatures_1[_i]; + // Only elaborate errors from the first failure var shouldElaborateErrors = reportErrors; for (var _a = 0, sourceSignatures_1 = sourceSignatures; _a < sourceSignatures_1.length; _a++) { var s = sourceSignatures_1[_a]; - var related = signatureRelatedTo(s, t, true, shouldElaborateErrors); + var related = signatureRelatedTo(s, t, /*erase*/ true, shouldElaborateErrors); if (related) { result &= related; errorInfo = saveErrorInfo; @@ -34292,49 +39624,53 @@ var ts; shouldElaborateErrors = false; } if (shouldElaborateErrors) { - reportError(ts.Diagnostics.Type_0_provides_no_match_for_the_signature_1, typeToString(source), signatureToString(t, undefined, undefined, kind)); + reportError(ts.Diagnostics.Type_0_provides_no_match_for_the_signature_1, typeToString(source), signatureToString(t, /*enclosingDeclaration*/ undefined, /*flags*/ undefined, kind)); } - return 0; + return 0 /* False */; } } return result; } + /** + * See signatureAssignableTo, compareSignaturesIdentical + */ function signatureRelatedTo(source, target, erase, reportErrors) { - return compareSignaturesRelated(erase ? getErasedSignature(source) : source, erase ? getErasedSignature(target) : target, 0, false, reportErrors, reportError, isRelatedTo); + return compareSignaturesRelated(erase ? getErasedSignature(source) : source, erase ? getErasedSignature(target) : target, 0 /* None */, /*ignoreReturnTypes*/ false, reportErrors, reportError, isRelatedTo); } function signaturesIdenticalTo(source, target, kind) { var sourceSignatures = getSignaturesOfType(source, kind); var targetSignatures = getSignaturesOfType(target, kind); if (sourceSignatures.length !== targetSignatures.length) { - return 0; + return 0 /* False */; } - var result = -1; + var result = -1 /* True */; for (var i = 0; i < sourceSignatures.length; i++) { - var related = compareSignaturesIdentical(sourceSignatures[i], targetSignatures[i], false, false, false, isRelatedTo); + var related = compareSignaturesIdentical(sourceSignatures[i], targetSignatures[i], /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ false, isRelatedTo); if (!related) { - return 0; + return 0 /* False */; } result &= related; } return result; } function eachPropertyRelatedTo(source, target, kind, reportErrors) { - var result = -1; + var result = -1 /* True */; for (var _i = 0, _a = getPropertiesOfObjectType(source); _i < _a.length; _i++) { var prop = _a[_i]; - if (isIgnoredJsxProperty(source, prop, undefined)) { + if (isIgnoredJsxProperty(source, prop, /*targetMemberType*/ undefined)) { continue; } - if (prop.nameType && prop.nameType.flags & 2048) { + // Skip over symbol-named members + if (prop.nameType && prop.nameType.flags & 2048 /* UniqueESSymbol */) { continue; } - if (kind === 0 || isNumericLiteralName(prop.escapedName)) { + if (kind === 0 /* String */ || isNumericLiteralName(prop.escapedName)) { var related = isRelatedTo(getTypeOfSymbol(prop), target, reportErrors); if (!related) { if (reportErrors) { reportError(ts.Diagnostics.Property_0_is_incompatible_with_index_signature, symbolToString(prop)); } - return 0; + return 0 /* False */; } result &= related; } @@ -34353,21 +39689,24 @@ var ts; return indexTypesIdenticalTo(source, target, kind); } var targetInfo = getIndexInfoOfType(target, kind); - if (!targetInfo || targetInfo.type.flags & 3 && !sourceIsPrimitive) { - return -1; + if (!targetInfo || targetInfo.type.flags & 3 /* AnyOrUnknown */ && !sourceIsPrimitive) { + // Index signature of type any permits assignment from everything but primitives + return -1 /* True */; } var sourceInfo = getIndexInfoOfType(source, kind) || - kind === 1 && getIndexInfoOfType(source, 0); + kind === 1 /* Number */ && getIndexInfoOfType(source, 0 /* String */); if (sourceInfo) { return indexInfoRelatedTo(sourceInfo, targetInfo, reportErrors); } if (isGenericMappedType(source)) { - return (kind === 0 && isRelatedTo(getTemplateTypeFromMappedType(source), targetInfo.type, reportErrors)); + // A generic mapped type { [P in K]: T } is related to an index signature { [x: string]: U } + // if T is related to U. + return (kind === 0 /* String */ && isRelatedTo(getTemplateTypeFromMappedType(source), targetInfo.type, reportErrors)); // TODO: GH#18217 } if (isObjectTypeWithInferableIndex(source)) { - var related = -1; - if (kind === 0) { - var sourceNumberInfo = getIndexInfoOfType(source, 1); + var related = -1 /* True */; + if (kind === 0 /* String */) { + var sourceNumberInfo = getIndexInfoOfType(source, 1 /* Number */); if (sourceNumberInfo) { related = indexInfoRelatedTo(sourceNumberInfo, targetInfo, reportErrors); } @@ -34380,32 +39719,35 @@ var ts; if (reportErrors) { reportError(ts.Diagnostics.Index_signature_is_missing_in_type_0, typeToString(source)); } - return 0; + return 0 /* False */; } function indexTypesIdenticalTo(source, target, indexKind) { var targetInfo = getIndexInfoOfType(target, indexKind); var sourceInfo = getIndexInfoOfType(source, indexKind); if (!sourceInfo && !targetInfo) { - return -1; + return -1 /* True */; } if (sourceInfo && targetInfo && sourceInfo.isReadonly === targetInfo.isReadonly) { return isRelatedTo(sourceInfo.type, targetInfo.type); } - return 0; + return 0 /* False */; } function constructorVisibilitiesAreCompatible(sourceSignature, targetSignature, reportErrors) { if (!sourceSignature.declaration || !targetSignature.declaration) { return true; } - var sourceAccessibility = ts.getSelectedModifierFlags(sourceSignature.declaration, 24); - var targetAccessibility = ts.getSelectedModifierFlags(targetSignature.declaration, 24); - if (targetAccessibility === 8) { + var sourceAccessibility = ts.getSelectedModifierFlags(sourceSignature.declaration, 24 /* NonPublicAccessibilityModifier */); + var targetAccessibility = ts.getSelectedModifierFlags(targetSignature.declaration, 24 /* NonPublicAccessibilityModifier */); + // A public, protected and private signature is assignable to a private signature. + if (targetAccessibility === 8 /* Private */) { return true; } - if (targetAccessibility === 16 && sourceAccessibility !== 8) { + // A public and protected signature is assignable to a protected signature. + if (targetAccessibility === 16 /* Protected */ && sourceAccessibility !== 8 /* Private */) { return true; } - if (targetAccessibility !== 16 && !sourceAccessibility) { + // Only a public signature is assignable to public signature. + if (targetAccessibility !== 16 /* Protected */ && !sourceAccessibility) { return true; } if (reportErrors) { @@ -34414,11 +39756,19 @@ var ts; return false; } } + // Return a type reference where the source type parameter is replaced with the target marker + // type, and flag the result as a marker type reference. function getMarkerTypeReference(type, source, target) { var result = createTypeReference(type, ts.map(type.typeParameters, function (t) { return t === source ? target : t; })); - result.objectFlags |= 8192; + result.objectFlags |= 8192 /* MarkerType */; return result; } + // Return an array containing the variance of each type parameter. The variance is effectively + // a digest of the type comparisons that occur for each type argument when instantiations of the + // generic type are structurally compared. We infer the variance information by comparing + // instantiations of the generic type for type arguments with known relations. The function + // returns the emptyArray singleton if we're not in strictFunctionTypes mode or if the function + // has been invoked recursively for the given generic type. function getVariances(type) { if (!strictFunctionTypes) { return ts.emptyArray; @@ -34427,19 +39777,28 @@ var ts; var variances = type.variances; if (!variances) { if (type === globalArrayType || type === globalReadonlyArrayType) { - variances = [1]; + // Arrays are known to be covariant, no need to spend time computing this + variances = [1 /* Covariant */]; } else { + // The emptyArray singleton is used to signal a recursive invocation. type.variances = ts.emptyArray; variances = []; for (var _i = 0, typeParameters_1 = typeParameters; _i < typeParameters_1.length; _i++) { var tp = typeParameters_1[_i]; + // We first compare instantiations where the type parameter is replaced with + // marker types that have a known subtype relationship. From this we can infer + // invariance, covariance, contravariance or bivariance. var typeWithSuper = getMarkerTypeReference(type, tp, markerSuperType); var typeWithSub = getMarkerTypeReference(type, tp, markerSubType); - var variance = (isTypeAssignableTo(typeWithSub, typeWithSuper) ? 1 : 0) | - (isTypeAssignableTo(typeWithSuper, typeWithSub) ? 2 : 0); - if (variance === 3 && isTypeAssignableTo(getMarkerTypeReference(type, tp, markerOtherType), typeWithSuper)) { - variance = 4; + var variance = (isTypeAssignableTo(typeWithSub, typeWithSuper) ? 1 /* Covariant */ : 0) | + (isTypeAssignableTo(typeWithSuper, typeWithSub) ? 2 /* Contravariant */ : 0); + // If the instantiations appear to be related bivariantly it may be because the + // type parameter is independent (i.e. it isn't witnessed anywhere in the generic + // type). To determine this we compare instantiations where the type parameter is + // replaced with marker types that are known to be unrelated. + if (variance === 3 /* Bivariant */ && isTypeAssignableTo(getMarkerTypeReference(type, tp, markerOtherType), typeWithSuper)) { + variance = 4 /* Independent */; } variances.push(variance); } @@ -34448,20 +39807,26 @@ var ts; } return variances; } + // Return true if the given type reference has a 'void' type argument for a covariant type parameter. + // See comment at call in recursiveTypeRelatedTo for when this case matters. function hasCovariantVoidArgument(type, variances) { for (var i = 0; i < variances.length; i++) { - if (variances[i] === 1 && type.typeArguments[i].flags & 4096) { + if (variances[i] === 1 /* Covariant */ && type.typeArguments[i].flags & 4096 /* Void */) { return true; } } return false; } function isUnconstrainedTypeParameter(type) { - return type.flags & 65536 && !getConstraintFromTypeParameter(type); + return type.flags & 65536 /* TypeParameter */ && !getConstraintFromTypeParameter(type); } function isTypeReferenceWithGenericArguments(type) { - return !!(ts.getObjectFlags(type) & 4) && ts.some(type.typeArguments, function (t) { return isUnconstrainedTypeParameter(t) || isTypeReferenceWithGenericArguments(t); }); + return !!(ts.getObjectFlags(type) & 4 /* Reference */) && ts.some(type.typeArguments, function (t) { return isUnconstrainedTypeParameter(t) || isTypeReferenceWithGenericArguments(t); }); } + /** + * getTypeReferenceId(A) returns "111=0-12=1" + * where A.id=111 and number.id=12 + */ function getTypeReferenceId(type, typeParameters, depth) { if (depth === void 0) { depth = 0; } var result = "" + type.target.id; @@ -34484,6 +39849,10 @@ var ts; } return result; } + /** + * To improve caching, the relation key for two generic types uses the target's id plus ids of the type parameters. + * For other cases, the types ids are used. + */ function getRelationKey(source, target, relation) { if (relation === identityRelation && source.id > target.id) { var temp = source; @@ -34496,8 +39865,10 @@ var ts; } return source.id + "," + target.id; } + // Invoke the callback for each underlying property symbol of the given symbol and return the first + // value that isn't undefined. function forEachProperty(prop, callback) { - if (ts.getCheckFlags(prop) & 6) { + if (ts.getCheckFlags(prop) & 6 /* Synthetic */) { for (var _i = 0, _a = prop.containingType.types; _i < _a.length; _i++) { var t = _a[_i]; var p = getPropertyOfType(t, prop.escapedName); @@ -34510,31 +39881,43 @@ var ts; } return callback(prop); } + // Return the declaring class type of a property or undefined if property not declared in class function getDeclaringClass(prop) { - return prop.parent && prop.parent.flags & 32 ? getDeclaredTypeOfSymbol(getParentOfSymbol(prop)) : undefined; + return prop.parent && prop.parent.flags & 32 /* Class */ ? getDeclaredTypeOfSymbol(getParentOfSymbol(prop)) : undefined; } + // Return true if some underlying source property is declared in a class that derives + // from the given base class. function isPropertyInClassDerivedFrom(prop, baseClass) { return forEachProperty(prop, function (sp) { var sourceClass = getDeclaringClass(sp); return sourceClass ? hasBaseType(sourceClass, baseClass) : false; }); } + // Return true if source property is a valid override of protected parts of target property. function isValidOverrideOf(sourceProp, targetProp) { - return !forEachProperty(targetProp, function (tp) { return ts.getDeclarationModifierFlagsFromSymbol(tp) & 16 ? + return !forEachProperty(targetProp, function (tp) { return ts.getDeclarationModifierFlagsFromSymbol(tp) & 16 /* Protected */ ? !isPropertyInClassDerivedFrom(sourceProp, getDeclaringClass(tp)) : false; }); } + // Return true if the given class derives from each of the declaring classes of the protected + // constituents of the given property. function isClassDerivedFromDeclaringClasses(checkClass, prop) { - return forEachProperty(prop, function (p) { return ts.getDeclarationModifierFlagsFromSymbol(p) & 16 ? + return forEachProperty(prop, function (p) { return ts.getDeclarationModifierFlagsFromSymbol(p) & 16 /* Protected */ ? !hasBaseType(checkClass, getDeclaringClass(p)) : false; }) ? undefined : checkClass; } + // Return true if the given type is deeply nested. We consider this to be the case when structural type comparisons + // for 5 or more occurrences or instantiations of the type have been recorded on the given stack. It is possible, + // though highly unlikely, for this test to be true in a situation where a chain of instantiations is not infinitely + // expanding. Effectively, we will generate a false positive when two types are structurally equal to at least 5 + // levels, but unequal at some level beyond that. function isDeeplyNestedType(type, stack, depth) { - if (depth >= 5 && type.flags & 131072) { + // We track all object types that have an associated symbol (representing the origin of the type) + if (depth >= 5 && type.flags & 131072 /* Object */) { var symbol = type.symbol; if (symbol) { var count = 0; for (var i = 0; i < depth; i++) { var t = stack[i]; - if (t.flags & 131072 && t.symbol === symbol) { + if (t.flags & 131072 /* Object */ && t.symbol === symbol) { count++; if (count >= 5) return true; @@ -34545,38 +39928,46 @@ var ts; return false; } function isPropertyIdenticalTo(sourceProp, targetProp) { - return compareProperties(sourceProp, targetProp, compareTypesIdentical) !== 0; + return compareProperties(sourceProp, targetProp, compareTypesIdentical) !== 0 /* False */; } function compareProperties(sourceProp, targetProp, compareTypes) { + // Two members are considered identical when + // - they are public properties with identical names, optionality, and types, + // - they are private or protected properties originating in the same declaration and having identical types if (sourceProp === targetProp) { - return -1; + return -1 /* True */; } - var sourcePropAccessibility = ts.getDeclarationModifierFlagsFromSymbol(sourceProp) & 24; - var targetPropAccessibility = ts.getDeclarationModifierFlagsFromSymbol(targetProp) & 24; + var sourcePropAccessibility = ts.getDeclarationModifierFlagsFromSymbol(sourceProp) & 24 /* NonPublicAccessibilityModifier */; + var targetPropAccessibility = ts.getDeclarationModifierFlagsFromSymbol(targetProp) & 24 /* NonPublicAccessibilityModifier */; if (sourcePropAccessibility !== targetPropAccessibility) { - return 0; + return 0 /* False */; } if (sourcePropAccessibility) { if (getTargetSymbol(sourceProp) !== getTargetSymbol(targetProp)) { - return 0; + return 0 /* False */; } } else { - if ((sourceProp.flags & 16777216) !== (targetProp.flags & 16777216)) { - return 0; + if ((sourceProp.flags & 16777216 /* Optional */) !== (targetProp.flags & 16777216 /* Optional */)) { + return 0 /* False */; } } if (isReadonlySymbol(sourceProp) !== isReadonlySymbol(targetProp)) { - return 0; + return 0 /* False */; } return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp)); } function isMatchingSignature(source, target, partialMatch) { + // A source signature matches a target signature if the two signatures have the same number of required, + // optional, and rest parameters. if (source.parameters.length === target.parameters.length && source.minArgumentCount === target.minArgumentCount && source.hasRestParameter === target.hasRestParameter) { return true; } + // A source signature partially matches a target signature if the target signature has no fewer required + // parameters and no more overall parameters than the source signature (where a signature with a rest + // parameter is always considered to have more overall parameters than one without). var sourceRestCount = source.hasRestParameter ? 1 : 0; var targetRestCount = target.hasRestParameter ? 1 : 0; if (partialMatch && source.minArgumentCount <= target.minArgumentCount && (sourceRestCount > targetRestCount || @@ -34585,19 +39976,30 @@ var ts; } return false; } + /** + * See signatureRelatedTo, compareSignaturesIdentical + */ function compareSignaturesIdentical(source, target, partialMatch, ignoreThisTypes, ignoreReturnTypes, compareTypes) { + // TODO (drosen): De-duplicate code between related functions. if (source === target) { - return -1; + return -1 /* True */; } if (!(isMatchingSignature(source, target, partialMatch))) { - return 0; + return 0 /* False */; } + // Check that the two signatures have the same number of type parameters. We might consider + // also checking that any type parameter constraints match, but that would require instantiating + // the constraints with a common set of type arguments to get relatable entities in places where + // type parameters occur in the constraints. The complexity of doing that doesn't seem worthwhile, + // particularly as we're comparing erased versions of the signatures below. if (ts.length(source.typeParameters) !== ts.length(target.typeParameters)) { - return 0; + return 0 /* False */; } + // Spec 1.0 Section 3.8.3 & 3.8.4: + // M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N source = getErasedSignature(source); target = getErasedSignature(target); - var result = -1; + var result = -1 /* True */; if (!ignoreThisTypes) { var sourceThisType = getThisTypeOfSignature(source); if (sourceThisType) { @@ -34605,7 +40007,7 @@ var ts; if (targetThisType) { var related = compareTypes(sourceThisType, targetThisType); if (!related) { - return 0; + return 0 /* False */; } result &= related; } @@ -34617,7 +40019,7 @@ var ts; var t = isRestParameterIndex(target, i) ? getRestTypeOfSignature(target) : getTypeOfParameter(target.parameters[i]); var related = compareTypes(s, t); if (!related) { - return 0; + return 0 /* False */; } result &= related; } @@ -34626,12 +40028,13 @@ var ts; var targetTypePredicate = getTypePredicateOfSignature(target); result &= sourceTypePredicate !== undefined || targetTypePredicate !== undefined ? compareTypePredicatesIdentical(sourceTypePredicate, targetTypePredicate, compareTypes) + // If they're both type predicates their return types will both be `boolean`, so no need to compare those. : compareTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target)); } return result; } function compareTypePredicatesIdentical(source, target, compareTypes) { - return source === undefined || target === undefined || !typePredicateKindsMatch(source, target) ? 0 : compareTypes(source.type, target.type); + return source === undefined || target === undefined || !typePredicateKindsMatch(source, target) ? 0 /* False */ : compareTypes(source.type, target.type); } function isRestParameterIndex(signature, parameterIndex) { return signature.hasRestParameter && parameterIndex >= signature.parameters.length - 1; @@ -34650,6 +40053,9 @@ var ts; } return true; } + // When the candidate types are all literal types with the same base type, return a union + // of those literal types. Otherwise, return the leftmost type for which no type to the + // right is a supertype. function getSupertypeOrUnion(types) { return literalTypesWithSameBaseType(types) ? getUnionType(types) : @@ -34659,20 +40065,23 @@ var ts; if (!strictNullChecks) { return getSupertypeOrUnion(types); } - var primaryTypes = ts.filter(types, function (t) { return !(t.flags & 24576); }); + var primaryTypes = ts.filter(types, function (t) { return !(t.flags & 24576 /* Nullable */); }); return primaryTypes.length ? - getNullableType(getSupertypeOrUnion(primaryTypes), getFalsyFlagsOfTypes(types) & 24576) : - getUnionType(types, 2); + getNullableType(getSupertypeOrUnion(primaryTypes), getFalsyFlagsOfTypes(types) & 24576 /* Nullable */) : + getUnionType(types, 2 /* Subtype */); } + // Return the leftmost type for which no type to the right is a subtype. function getCommonSubtype(types) { return ts.reduceLeft(types, function (s, t) { return isTypeSubtypeOf(t, s) ? t : s; }); } function isArrayType(type) { - return !!(ts.getObjectFlags(type) & 4) && type.target === globalArrayType; + return !!(ts.getObjectFlags(type) & 4 /* Reference */) && type.target === globalArrayType; } function isArrayLikeType(type) { - return ts.getObjectFlags(type) & 4 && (type.target === globalArrayType || type.target === globalReadonlyArrayType) || - !(type.flags & 24576) && isTypeAssignableTo(type, anyReadonlyArrayType); + // A type is array-like if it is a reference to the global Array or global ReadonlyArray type, + // or if it is not the undefined or null type and if it is assignable to ReadonlyArray + return ts.getObjectFlags(type) & 4 /* Reference */ && (type.target === globalArrayType || type.target === globalReadonlyArrayType) || + !(type.flags & 24576 /* Nullable */) && isTypeAssignableTo(type, anyReadonlyArrayType); } function isEmptyArrayLiteralType(type) { var elementType = isArrayType(type) ? type.typeArguments[0] : undefined; @@ -34682,35 +40091,35 @@ var ts; return !!getPropertyOfType(type, "0"); } function isNeitherUnitTypeNorNever(type) { - return !(type.flags & (27072 | 32768)); + return !(type.flags & (27072 /* Unit */ | 32768 /* Never */)); } function isUnitType(type) { - return !!(type.flags & 27072); + return !!(type.flags & 27072 /* Unit */); } function isLiteralType(type) { - return type.flags & 16 ? true : - type.flags & 262144 ? type.flags & 512 ? true : ts.every(type.types, isUnitType) : + return type.flags & 16 /* Boolean */ ? true : + type.flags & 262144 /* Union */ ? type.flags & 512 /* EnumLiteral */ ? true : ts.every(type.types, isUnitType) : isUnitType(type); } function getBaseTypeOfLiteralType(type) { - return type.flags & 512 ? getBaseTypeOfEnumLiteralType(type) : - type.flags & 64 ? stringType : - type.flags & 128 ? numberType : - type.flags & 256 ? booleanType : - type.flags & 262144 ? getUnionType(ts.sameMap(type.types, getBaseTypeOfLiteralType)) : + return type.flags & 512 /* EnumLiteral */ ? getBaseTypeOfEnumLiteralType(type) : + type.flags & 64 /* StringLiteral */ ? stringType : + type.flags & 128 /* NumberLiteral */ ? numberType : + type.flags & 256 /* BooleanLiteral */ ? booleanType : + type.flags & 262144 /* Union */ ? getUnionType(ts.sameMap(type.types, getBaseTypeOfLiteralType)) : type; } function getWidenedLiteralType(type) { - return type.flags & 512 ? getBaseTypeOfEnumLiteralType(type) : - type.flags & 64 && type.flags & 33554432 ? stringType : - type.flags & 128 && type.flags & 33554432 ? numberType : - type.flags & 256 ? booleanType : - type.flags & 262144 ? getUnionType(ts.sameMap(type.types, getWidenedLiteralType)) : + return type.flags & 512 /* EnumLiteral */ ? getBaseTypeOfEnumLiteralType(type) : + type.flags & 64 /* StringLiteral */ && type.flags & 33554432 /* FreshLiteral */ ? stringType : + type.flags & 128 /* NumberLiteral */ && type.flags & 33554432 /* FreshLiteral */ ? numberType : + type.flags & 256 /* BooleanLiteral */ ? booleanType : + type.flags & 262144 /* Union */ ? getUnionType(ts.sameMap(type.types, getWidenedLiteralType)) : type; } function getWidenedUniqueESSymbolType(type) { - return type.flags & 2048 ? esSymbolType : - type.flags & 262144 ? getUnionType(ts.sameMap(type.types, getWidenedUniqueESSymbolType)) : + return type.flags & 2048 /* UniqueESSymbol */ ? esSymbolType : + type.flags & 262144 /* Union */ ? getUnionType(ts.sameMap(type.types, getWidenedUniqueESSymbolType)) : type; } function getWidenedLiteralLikeTypeForContextualType(type, contextualType) { @@ -34719,8 +40128,12 @@ var ts; } return type; } + /** + * Check if a Type was written as a tuple type literal. + * Prefer using isTupleLikeType() unless the use of `elementTypes` is required. + */ function isTupleType(type) { - return !!(ts.getObjectFlags(type) & 4 && type.target.objectFlags & 8); + return !!(ts.getObjectFlags(type) & 4 /* Reference */ && type.target.objectFlags & 8 /* Tuple */); } function getFalsyFlagsOfTypes(types) { var result = 0; @@ -34730,55 +40143,68 @@ var ts; } return result; } + // Returns the String, Number, Boolean, StringLiteral, NumberLiteral, BooleanLiteral, Void, Undefined, or Null + // flags for the string, number, boolean, "", 0, false, void, undefined, or null types respectively. Returns + // no flags for all other types (including non-falsy literal types). function getFalsyFlags(type) { - return type.flags & 262144 ? getFalsyFlagsOfTypes(type.types) : - type.flags & 64 ? type.value === "" ? 64 : 0 : - type.flags & 128 ? type.value === 0 ? 128 : 0 : - type.flags & 256 ? type === falseType ? 256 : 0 : - type.flags & 29148; + return type.flags & 262144 /* Union */ ? getFalsyFlagsOfTypes(type.types) : + type.flags & 64 /* StringLiteral */ ? type.value === "" ? 64 /* StringLiteral */ : 0 : + type.flags & 128 /* NumberLiteral */ ? type.value === 0 ? 128 /* NumberLiteral */ : 0 : + type.flags & 256 /* BooleanLiteral */ ? type === falseType ? 256 /* BooleanLiteral */ : 0 : + type.flags & 29148 /* PossiblyFalsy */; } function removeDefinitelyFalsyTypes(type) { - return getFalsyFlags(type) & 29120 ? - filterType(type, function (t) { return !(getFalsyFlags(t) & 29120); }) : + return getFalsyFlags(type) & 29120 /* DefinitelyFalsy */ ? + filterType(type, function (t) { return !(getFalsyFlags(t) & 29120 /* DefinitelyFalsy */); }) : type; } function extractDefinitelyFalsyTypes(type) { return mapType(type, getDefinitelyFalsyPartOfType); } function getDefinitelyFalsyPartOfType(type) { - return type.flags & 4 ? emptyStringType : - type.flags & 8 ? zeroType : - type.flags & 16 || type === falseType ? falseType : - type.flags & (4096 | 8192 | 16384) || - type.flags & 64 && type.value === "" || - type.flags & 128 && type.value === 0 ? type : + return type.flags & 4 /* String */ ? emptyStringType : + type.flags & 8 /* Number */ ? zeroType : + type.flags & 16 /* Boolean */ || type === falseType ? falseType : + type.flags & (4096 /* Void */ | 8192 /* Undefined */ | 16384 /* Null */) || + type.flags & 64 /* StringLiteral */ && type.value === "" || + type.flags & 128 /* NumberLiteral */ && type.value === 0 ? type : neverType; } + /** + * Add undefined or null or both to a type if they are missing. + * @param type - type to add undefined and/or null to if not present + * @param flags - Either TypeFlags.Undefined or TypeFlags.Null, or both + */ function getNullableType(type, flags) { - var missing = (flags & ~type.flags) & (8192 | 16384); + var missing = (flags & ~type.flags) & (8192 /* Undefined */ | 16384 /* Null */); return missing === 0 ? type : - missing === 8192 ? getUnionType([type, undefinedType]) : - missing === 16384 ? getUnionType([type, nullType]) : + missing === 8192 /* Undefined */ ? getUnionType([type, undefinedType]) : + missing === 16384 /* Null */ ? getUnionType([type, nullType]) : getUnionType([type, undefinedType, nullType]); } function getOptionalType(type) { ts.Debug.assert(strictNullChecks); - return type.flags & 8192 ? type : getUnionType([type, undefinedType]); + return type.flags & 8192 /* Undefined */ ? type : getUnionType([type, undefinedType]); } function getGlobalNonNullableTypeInstantiation(type) { if (!deferredGlobalNonNullableTypeAlias) { - deferredGlobalNonNullableTypeAlias = getGlobalSymbol("NonNullable", 524288, undefined) || unknownSymbol; + deferredGlobalNonNullableTypeAlias = getGlobalSymbol("NonNullable", 524288 /* TypeAlias */, /*diagnostic*/ undefined) || unknownSymbol; } + // Use NonNullable global type alias if available to improve quick info/declaration emit if (deferredGlobalNonNullableTypeAlias !== unknownSymbol) { return getTypeAliasInstantiation(deferredGlobalNonNullableTypeAlias, [type]); } - return getTypeWithFacts(type, 524288); + return getTypeWithFacts(type, 524288 /* NEUndefinedOrNull */); // Type alias unavailable, fall back to non-higherorder behavior } function getNonNullableType(type) { return strictNullChecks ? getGlobalNonNullableTypeInstantiation(type) : type; } + /** + * Return true if type was inferred from an object literal, written as an object type literal, or is the shape of a module + * with no call or construct signatures. + */ function isObjectTypeWithInferableIndex(type) { - return type.symbol && (type.symbol.flags & (4096 | 2048 | 512)) !== 0 && + return type.symbol && (type.symbol.flags & (4096 /* ObjectLiteral */ | 2048 /* TypeLiteral */ | 512 /* ValueModule */)) !== 0 && !typeHasCallOrConstructSignatures(type); } function createSymbolWithType(source, type) { @@ -34805,8 +40231,13 @@ var ts; } return members; } + /** + * If the the provided object literal is subject to the excess properties check, + * create a new that is exempt. Recursively mark object literal members as exempt. + * Leave signatures alone since they are not subject to the check. + */ function getRegularTypeOfObjectLiteral(type) { - if (!(isObjectLiteralType(type) && type.flags & 33554432)) { + if (!(isObjectLiteralType(type) && type.flags & 33554432 /* FreshLiteral */)) { return type; } var regularType = type.regularType; @@ -34816,8 +40247,8 @@ var ts; var resolved = type; var members = transformTypeOfMembers(type, getRegularTypeOfObjectLiteral); var regularNew = createAnonymousType(resolved.symbol, members, resolved.callSignatures, resolved.constructSignatures, resolved.stringIndexInfo, resolved.numberIndexInfo); - regularNew.flags = resolved.flags & ~33554432; - regularNew.objectFlags |= 128; + regularNew.flags = resolved.flags & ~33554432 /* FreshLiteral */; + regularNew.objectFlags |= 128 /* ObjectLiteral */; type.regularType = regularNew; return regularNew; } @@ -34847,7 +40278,7 @@ var ts; var names = ts.createMap(); for (var _i = 0, _a = getSiblingsOfContext(context); _i < _a.length; _i++) { var t = _a[_i]; - if (isObjectLiteralType(t) && !(ts.getObjectFlags(t) & 1024)) { + if (isObjectLiteralType(t) && !(ts.getObjectFlags(t) & 1024 /* ContainsSpread */)) { for (var _b = 0, _c = getPropertiesOfType(t); _b < _c.length; _b++) { var prop = _c[_b]; names.set(prop.escapedName, prop); @@ -34859,11 +40290,13 @@ var ts; return context.resolvedProperties; } function getWidenedProperty(prop, context) { - if (!(prop.flags & 4)) { + if (!(prop.flags & 4 /* Property */)) { + // Since get accessors already widen their return value there is no need to + // widen accessor based properties here. return prop; } var original = getTypeOfSymbol(prop); - var propContext = context && createWideningContext(context, prop.escapedName, undefined); + var propContext = context && createWideningContext(context, prop.escapedName, /*siblings*/ undefined); var widened = getWidenedTypeWithContext(original, propContext); return widened === original ? prop : createSymbolWithType(prop, widened); } @@ -34873,7 +40306,7 @@ var ts; return cached; } var result = createSymbolWithType(prop, undefinedType); - result.flags |= 16777216; + result.flags |= 16777216 /* Optional */; undefinedProperties.set(prop.escapedName, result); return result; } @@ -34891,25 +40324,28 @@ var ts; } } } - var stringIndexInfo = getIndexInfoOfType(type, 0); - var numberIndexInfo = getIndexInfoOfType(type, 1); + var stringIndexInfo = getIndexInfoOfType(type, 0 /* String */); + var numberIndexInfo = getIndexInfoOfType(type, 1 /* Number */); return createAnonymousType(type.symbol, members, ts.emptyArray, ts.emptyArray, stringIndexInfo && createIndexInfo(getWidenedType(stringIndexInfo.type), stringIndexInfo.isReadonly), numberIndexInfo && createIndexInfo(getWidenedType(numberIndexInfo.type), numberIndexInfo.isReadonly)); } function getWidenedType(type) { - return getWidenedTypeWithContext(type, undefined); + return getWidenedTypeWithContext(type, /*context*/ undefined); } function getWidenedTypeWithContext(type, context) { - if (type.flags & 402653184) { - if (type.flags & 24576) { + if (type.flags & 402653184 /* RequiresWidening */) { + if (type.flags & 24576 /* Nullable */) { return anyType; } if (isObjectLiteralType(type)) { return getWidenedTypeOfObjectLiteral(type, context); } - if (type.flags & 262144) { - var unionContext_1 = context || createWideningContext(undefined, undefined, type.types); - var widenedTypes = ts.sameMap(type.types, function (t) { return t.flags & 24576 ? t : getWidenedTypeWithContext(t, unionContext_1); }); - return getUnionType(widenedTypes, ts.some(widenedTypes, isEmptyObjectType) ? 2 : 1); + if (type.flags & 262144 /* Union */) { + var unionContext_1 = context || createWideningContext(/*parent*/ undefined, /*propertyName*/ undefined, type.types); + var widenedTypes = ts.sameMap(type.types, function (t) { return t.flags & 24576 /* Nullable */ ? t : getWidenedTypeWithContext(t, unionContext_1); }); + // Widening an empty object literal transitions from a highly restrictive type to + // a highly inclusive one. For that reason we perform subtype reduction here if the + // union includes empty object types (e.g. reducing {} | string to just {}). + return getUnionType(widenedTypes, ts.some(widenedTypes, isEmptyObjectType) ? 2 /* Subtype */ : 1 /* Literal */); } if (isArrayType(type) || isTupleType(type)) { return createTypeReference(type.target, ts.sameMap(type.typeArguments, getWidenedType)); @@ -34917,10 +40353,21 @@ var ts; } return type; } + /** + * Reports implicit any errors that occur as a result of widening 'null' and 'undefined' + * to 'any'. A call to reportWideningErrorsInType is normally accompanied by a call to + * getWidenedType. But in some cases getWidenedType is called without reporting errors + * (type argument inference is an example). + * + * The return value indicates whether an error was in fact reported. The particular circumstances + * are on a best effort basis. Currently, if the null or undefined that causes widening is inside + * an object literal property (arbitrarily deeply), this function reports an error. If no error is + * reported, reportImplicitAnyError is a suitable fallback to report a general error. + */ function reportWideningErrorsInType(type) { var errorReported = false; - if (type.flags & 134217728) { - if (type.flags & 262144) { + if (type.flags & 134217728 /* ContainsWideningType */) { + if (type.flags & 262144 /* Union */) { if (ts.some(type.types, isEmptyObjectType)) { errorReported = true; } @@ -34945,7 +40392,7 @@ var ts; for (var _d = 0, _e = getPropertiesOfObjectType(type); _d < _e.length; _d++) { var p = _e[_d]; var t = getTypeOfSymbol(p); - if (t.flags & 134217728) { + if (t.flags & 134217728 /* ContainsWideningType */) { if (!reportWideningErrorsInType(t)) { error(p.valueDeclaration, ts.Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, symbolToString(p), typeToString(getWidenedType(t))); } @@ -34960,33 +40407,33 @@ var ts; var typeAsString = typeToString(getWidenedType(type)); var diagnostic; switch (declaration.kind) { - case 200: - case 152: - case 151: + case 200 /* BinaryExpression */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: diagnostic = ts.Diagnostics.Member_0_implicitly_has_an_1_type; break; - case 149: + case 149 /* Parameter */: diagnostic = declaration.dotDotDotToken ? ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type : ts.Diagnostics.Parameter_0_implicitly_has_an_1_type; break; - case 182: + case 182 /* BindingElement */: diagnostic = ts.Diagnostics.Binding_element_0_implicitly_has_an_1_type; break; - case 234: - case 154: - case 153: - case 156: - case 157: - case 192: - case 193: + case 234 /* FunctionDeclaration */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: if (!declaration.name) { error(declaration, ts.Diagnostics.Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeAsString); return; } diagnostic = ts.Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type; break; - case 177: + case 177 /* MappedType */: error(declaration, ts.Diagnostics.Mapped_object_type_implicitly_has_an_any_template_type); return; default: @@ -34995,7 +40442,8 @@ var ts; error(declaration, diagnostic, ts.declarationNameToString(ts.getNameOfDeclaration(declaration)), typeAsString); } function reportErrorsFromWidening(declaration, type) { - if (produceDiagnostics && noImplicitAny && type.flags & 134217728) { + if (produceDiagnostics && noImplicitAny && type.flags & 134217728 /* ContainsWideningType */) { + // Report implicit any error within type if possible, otherwise report error on declaration if (!reportWideningErrorsInType(type)) { reportImplicitAnyError(declaration, type); } @@ -35062,13 +40510,16 @@ var ts; isFixed: inference.isFixed }; } + // Return true if the given type could possibly reference a type parameter for which + // we perform type inference (i.e. a type parameter of a generic function). We cache + // results for union and intersection types for performance reasons. function couldContainTypeVariables(type) { var objectFlags = ts.getObjectFlags(type); - return !!(type.flags & 15794176 || - objectFlags & 4 && ts.forEach(type.typeArguments, couldContainTypeVariables) || - objectFlags & 16 && type.symbol && type.symbol.flags & (16 | 8192 | 2048 | 32) || - objectFlags & 32 || - type.flags & 786432 && couldUnionOrIntersectionContainTypeVariables(type)); + return !!(type.flags & 15794176 /* Instantiable */ || + objectFlags & 4 /* Reference */ && ts.forEach(type.typeArguments, couldContainTypeVariables) || + objectFlags & 16 /* Anonymous */ && type.symbol && type.symbol.flags & (16 /* Function */ | 8192 /* Method */ | 2048 /* TypeLiteral */ | 32 /* Class */) || + objectFlags & 32 /* Mapped */ || + type.flags & 786432 /* UnionOrIntersection */ && couldUnionOrIntersectionContainTypeVariables(type)); } function couldUnionOrIntersectionContainTypeVariables(type) { if (type.couldContainTypeVariables === undefined) { @@ -35077,16 +40528,17 @@ var ts; return type.couldContainTypeVariables; } function isTypeParameterAtTopLevel(type, typeParameter) { - return type === typeParameter || !!(type.flags & 786432) && ts.some(type.types, function (t) { return isTypeParameterAtTopLevel(t, typeParameter); }); + return type === typeParameter || !!(type.flags & 786432 /* UnionOrIntersection */) && ts.some(type.types, function (t) { return isTypeParameterAtTopLevel(t, typeParameter); }); } + /** Create an object with properties named in the string literal type. Every property has type `any` */ function createEmptyObjectTypeFromStringLiteral(type) { var members = ts.createSymbolTable(); forEachType(type, function (t) { - if (!(t.flags & 64)) { + if (!(t.flags & 64 /* StringLiteral */)) { return; } var name = ts.escapeLeadingUnderscores(t.value); - var literalProp = createSymbol(4, name); + var literalProp = createSymbol(4 /* Property */, name); literalProp.type = anyType; if (t.symbol) { literalProp.declarations = t.symbol.declarations; @@ -35094,9 +40546,15 @@ var ts; } members.set(name, literalProp); }); - var indexInfo = type.flags & 4 ? createIndexInfo(emptyObjectType, false) : undefined; + var indexInfo = type.flags & 4 /* String */ ? createIndexInfo(emptyObjectType, /*isReadonly*/ false) : undefined; return createAnonymousType(undefined, members, ts.emptyArray, ts.emptyArray, indexInfo, undefined); } + /** + * Infer a suitable input type for a homomorphic mapped type { [P in keyof T]: X }. We construct + * an object type with the same set of properties as the source type, where the type of each + * property is computed by inferring from the source property type to X for the type + * variable T[P] (i.e. we treat the type T[P] as the type variable we're inferring for). + */ function inferTypeForHomomorphicMappedType(source, target) { var key = source.id + "," + target.id; if (reverseMappedCache.has(key)) { @@ -35109,16 +40567,18 @@ var ts; } function createReverseMappedType(source, target) { var properties = getPropertiesOfType(source); - if (properties.length === 0 && !getIndexInfoOfType(source, 0)) { + if (properties.length === 0 && !getIndexInfoOfType(source, 0 /* String */)) { return undefined; } + // If any property contains context sensitive functions that have been skipped, the source type + // is incomplete and we can't infer a meaningful input type. for (var _i = 0, properties_4 = properties; _i < properties_4.length; _i++) { var prop = properties_4[_i]; - if (getTypeOfSymbol(prop).flags & 536870912) { + if (getTypeOfSymbol(prop).flags & 536870912 /* ContainsAnyFunctionType */) { return undefined; } } - var reversed = createObjectType(2048 | 16, undefined); + var reversed = createObjectType(2048 /* ReverseMapped */ | 16 /* Anonymous */, /*symbol*/ undefined); reversed.source = source; reversed.mappedType = target; return reversed; @@ -35134,10 +40594,10 @@ var ts; return getTypeFromInference(inference); } function getUnmatchedProperty(source, target, requireOptionalProperties) { - var properties = target.flags & 524288 ? getPropertiesOfUnionOrIntersectionType(target) : getPropertiesOfObjectType(target); + var properties = target.flags & 524288 /* Intersection */ ? getPropertiesOfUnionOrIntersectionType(target) : getPropertiesOfObjectType(target); for (var _i = 0, properties_5 = properties; _i < properties_5.length; _i++) { var targetProp = properties_5[_i]; - if (requireOptionalProperties || !(targetProp.flags & 16777216)) { + if (requireOptionalProperties || !(targetProp.flags & 16777216 /* Optional */)) { var sourceProp = getPropertyOfType(source, targetProp.escapedName); if (!sourceProp) { return targetProp; @@ -35147,11 +40607,13 @@ var ts; return undefined; } function typesDefinitelyUnrelated(source, target) { + // Two tuple types with different arity are definitely unrelated. + // Two object types that each have a property that is unmatched in the other are definitely unrelated. return isTupleType(source) && isTupleType(target) && getTypeReferenceArity(source) !== getTypeReferenceArity(target) || - !!getUnmatchedProperty(source, target, false) && !!getUnmatchedProperty(target, source, false); + !!getUnmatchedProperty(source, target, /*requireOptionalProperties*/ false) && !!getUnmatchedProperty(target, source, /*requireOptionalProperties*/ false); } function getTypeFromInference(inference) { - return inference.candidates ? getUnionType(inference.candidates, 2) : + return inference.candidates ? getUnionType(inference.candidates, 2 /* Subtype */) : inference.contraCandidates ? getIntersectionType(inference.contraCandidates) : emptyObjectType; } @@ -35167,6 +40629,9 @@ var ts; return; } if (source === wildcardType) { + // We are inferring from an 'any' type. We want to infer this type for every type parameter + // referenced in the target type, so we record it as the propagation type and infer from the + // target to itself. Then, as we find candidates we substitute the propagation type. var savePropagationType = propagationType; propagationType = source; inferFromTypes(target, target); @@ -35174,6 +40639,8 @@ var ts; return; } if (source.aliasSymbol && source.aliasTypeArguments && source.aliasSymbol === target.aliasSymbol) { + // Source and target are types originating in the same generic type alias declaration. + // Simply infer from source type arguments to target type arguments. var sourceTypes = source.aliasTypeArguments; var targetTypes = target.aliasTypeArguments; for (var i = 0; i < sourceTypes.length; i++) { @@ -35181,8 +40648,10 @@ var ts; } return; } - if (source.flags & 262144 && target.flags & 262144 && !(source.flags & 512 && target.flags & 512) || - source.flags & 524288 && target.flags & 524288) { + if (source.flags & 262144 /* Union */ && target.flags & 262144 /* Union */ && !(source.flags & 512 /* EnumLiteral */ && target.flags & 512 /* EnumLiteral */) || + source.flags & 524288 /* Intersection */ && target.flags & 524288 /* Intersection */) { + // Source and target are both unions or both intersections. If source and target + // are the same type, just relate each constituent type to itself. if (source === target) { for (var _i = 0, _a = source.types; _i < _a.length; _i++) { var t = _a[_i]; @@ -35190,6 +40659,12 @@ var ts; } return; } + // Find each source constituent type that has an identically matching target constituent + // type, and for each such type infer from the type to itself. When inferring from a + // type to itself we effectively find all type parameter occurrences within that type + // and infer themselves as their type arguments. We have special handling for numeric + // and string literals because the number and string types are not represented as unions + // of all their possible values. var matchingTypes = void 0; for (var _b = 0, _c = source.types; _b < _c.length; _b++) { var t = _c[_b]; @@ -35197,20 +40672,30 @@ var ts; (matchingTypes || (matchingTypes = [])).push(t); inferFromTypes(t, t); } - else if (t.flags & (128 | 64)) { + else if (t.flags & (128 /* NumberLiteral */ | 64 /* StringLiteral */)) { var b = getBaseTypeOfLiteralType(t); if (typeIdenticalToSomeType(b, target.types)) { (matchingTypes || (matchingTypes = [])).push(t, b); } } } + // Next, to improve the quality of inferences, reduce the source and target types by + // removing the identically matched constituents. For example, when inferring from + // 'string | string[]' to 'string | T' we reduce the types to 'string[]' and 'T'. if (matchingTypes) { source = removeTypesFromUnionOrIntersection(source, matchingTypes); target = removeTypesFromUnionOrIntersection(target, matchingTypes); } } - if (target.flags & 2162688) { - if (source.flags & 536870912 || source === silentNeverType) { + if (target.flags & 2162688 /* TypeVariable */) { + // If target is a type parameter, make an inference, unless the source type contains + // the anyFunctionType (the wildcard type that's used to avoid contextually typing functions). + // Because the anyFunctionType is internal, it should not be exposed to the user by adding + // it as an inference candidate. Hopefully, a better candidate will come along that does + // not contain anyFunctionType when we come back to this argument for its second round + // of inference. Also, we exclude inferences for silentNeverType (which is used as a wildcard + // when constructing types from type parameters that had no inference candidates). + if (source.flags & 536870912 /* ContainsAnyFunctionType */ || source === silentNeverType) { return; } var inference = getInferenceInfoForType(target); @@ -35230,20 +40715,21 @@ var ts; inference.candidates = ts.append(inference.candidates, candidate); } } - if (!(priority & 8) && target.flags & 65536 && !isTypeParameterAtTopLevel(originalTarget, target)) { + if (!(priority & 8 /* ReturnType */) && target.flags & 65536 /* TypeParameter */ && !isTypeParameterAtTopLevel(originalTarget, target)) { inference.topLevel = false; } } return; } } - if (ts.getObjectFlags(source) & 4 && ts.getObjectFlags(target) & 4 && source.target === target.target) { + if (ts.getObjectFlags(source) & 4 /* Reference */ && ts.getObjectFlags(target) & 4 /* Reference */ && source.target === target.target) { + // If source and target are references to the same generic type, infer from type arguments var sourceTypes = source.typeArguments || ts.emptyArray; var targetTypes = target.typeArguments || ts.emptyArray; var count = sourceTypes.length < targetTypes.length ? sourceTypes.length : targetTypes.length; var variances = getVariances(source.target); for (var i = 0; i < count; i++) { - if (i < variances.length && variances[i] === 2) { + if (i < variances.length && variances[i] === 2 /* Contravariant */) { inferFromContravariantTypes(sourceTypes[i], targetTypes[i]); } else { @@ -35251,34 +40737,35 @@ var ts; } } } - else if (source.flags & 1048576 && target.flags & 1048576) { + else if (source.flags & 1048576 /* Index */ && target.flags & 1048576 /* Index */) { contravariant = !contravariant; inferFromTypes(source.type, target.type); contravariant = !contravariant; } - else if ((isLiteralType(source) || source.flags & 4) && target.flags & 1048576) { + else if ((isLiteralType(source) || source.flags & 4 /* String */) && target.flags & 1048576 /* Index */) { var empty = createEmptyObjectTypeFromStringLiteral(source); contravariant = !contravariant; var savePriority = priority; - priority |= 16; + priority |= 16 /* LiteralKeyof */; inferFromTypes(empty, target.type); priority = savePriority; contravariant = !contravariant; } - else if (source.flags & 2097152 && target.flags & 2097152) { + else if (source.flags & 2097152 /* IndexedAccess */ && target.flags & 2097152 /* IndexedAccess */) { inferFromTypes(source.objectType, target.objectType); inferFromTypes(source.indexType, target.indexType); } - else if (source.flags & 4194304 && target.flags & 4194304) { + else if (source.flags & 4194304 /* Conditional */ && target.flags & 4194304 /* Conditional */) { inferFromTypes(source.checkType, target.checkType); inferFromTypes(source.extendsType, target.extendsType); inferFromTypes(getTrueTypeFromConditionalType(source), getTrueTypeFromConditionalType(target)); inferFromTypes(getFalseTypeFromConditionalType(source), getFalseTypeFromConditionalType(target)); } - else if (target.flags & 786432) { + else if (target.flags & 786432 /* UnionOrIntersection */) { var targetTypes = target.types; var typeVariableCount = 0; var typeVariable = void 0; + // First infer to each type in union or intersection that isn't a type variable for (var _d = 0, targetTypes_3 = targetTypes; _d < targetTypes_3.length; _d++) { var t = targetTypes_3[_d]; if (getInferenceInfoForType(t)) { @@ -35289,14 +40776,18 @@ var ts; inferFromTypes(source, t); } } + // Next, if target containings a single naked type variable, make a secondary inference to that type + // variable. This gives meaningful results for union types in co-variant positions and intersection + // types in contra-variant positions (such as callback parameters). if (typeVariableCount === 1) { var savePriority = priority; - priority |= 1; + priority |= 1 /* NakedTypeVariable */; inferFromTypes(source, typeVariable); priority = savePriority; } } - else if (source.flags & 262144) { + else if (source.flags & 262144 /* Union */) { + // Source is a union or intersection type, infer from each constituent type var sourceTypes = source.types; for (var _e = 0, sourceTypes_3 = sourceTypes; _e < sourceTypes_3.length; _e++) { var sourceType = sourceTypes_3[_e]; @@ -35304,17 +40795,21 @@ var ts; } } else { - if (!(priority & 32 && source.flags & (524288 | 15794176))) { + if (!(priority & 32 /* NoConstraints */ && source.flags & (524288 /* Intersection */ | 15794176 /* Instantiable */))) { source = getApparentType(source); } - if (source.flags & (131072 | 524288)) { + if (source.flags & (131072 /* Object */ | 524288 /* Intersection */)) { var key = source.id + "," + target.id; if (visited && visited.get(key)) { return; } (visited || (visited = ts.createMap())).set(key, true); - var isNonConstructorObject = target.flags & 131072 && - !(ts.getObjectFlags(target) & 16 && target.symbol && target.symbol.flags & 32); + // If we are already processing another target type with the same associated symbol (such as + // an instantiation of the same generic type), we do not explore this target as it would yield + // no further inferences. We exclude the static side of classes from this check since it shares + // its symbol with the instance side which would lead to false positives. + var isNonConstructorObject = target.flags & 131072 /* Object */ && + !(ts.getObjectFlags(target) & 16 /* Anonymous */ && target.symbol && target.symbol.flags & 32 /* Class */); var symbol = isNonConstructorObject ? target.symbol : undefined; if (symbol) { if (ts.contains(symbolStack, symbol)) { @@ -35331,7 +40826,7 @@ var ts; } } function inferFromContravariantTypes(source, target) { - if (strictFunctionTypes || priority & 64) { + if (strictFunctionTypes || priority & 64 /* AlwaysStrict */) { contravariant = !contravariant; inferFromTypes(source, target); contravariant = !contravariant; @@ -35341,7 +40836,7 @@ var ts; } } function getInferenceInfoForType(type) { - if (type.flags & 2162688) { + if (type.flags & 2162688 /* TypeVariable */) { for (var _i = 0, inferences_1 = inferences; _i < inferences_1.length; _i++) { var inference = inferences_1[_i]; if (type === inference.typeParameter) { @@ -35353,37 +40848,46 @@ var ts; } function inferFromObjectTypes(source, target) { if (isGenericMappedType(source) && isGenericMappedType(target)) { + // The source and target types are generic types { [P in S]: X } and { [P in T]: Y }, so we infer + // from S to T and from X to Y. inferFromTypes(getConstraintTypeFromMappedType(source), getConstraintTypeFromMappedType(target)); inferFromTypes(getTemplateTypeFromMappedType(source), getTemplateTypeFromMappedType(target)); } - if (ts.getObjectFlags(target) & 32) { + if (ts.getObjectFlags(target) & 32 /* Mapped */) { var constraintType = getConstraintTypeFromMappedType(target); - if (constraintType.flags & 1048576) { + if (constraintType.flags & 1048576 /* Index */) { + // We're inferring from some source type S to a homomorphic mapped type { [P in keyof T]: X }, + // where T is a type variable. Use inferTypeForHomomorphicMappedType to infer a suitable source + // type and then make a secondary inference from that type to T. We make a secondary inference + // such that direct inferences to T get priority over inferences to Partial, for example. var inference = getInferenceInfoForType(constraintType.type); if (inference && !inference.isFixed) { var inferredType = inferTypeForHomomorphicMappedType(source, target); if (inferredType) { var savePriority = priority; - priority |= 2; + priority |= 2 /* HomomorphicMappedType */; inferFromTypes(inferredType, inference.typeParameter); priority = savePriority; } } return; } - if (constraintType.flags & 65536) { + if (constraintType.flags & 65536 /* TypeParameter */) { + // We're inferring from some source type S to a mapped type { [P in T]: X }, where T is a type + // parameter. Infer from 'keyof S' to T and infer from a union of each property type in S to X. var savePriority = priority; - priority |= 4; + priority |= 4 /* MappedTypeConstraint */; inferFromTypes(getIndexType(source), constraintType); priority = savePriority; inferFromTypes(getUnionType(ts.map(getPropertiesOfType(source), getTypeOfSymbol)), getTemplateTypeFromMappedType(target)); return; } } + // Infer from the members of source and target only if the two types are possibly related if (!typesDefinitelyUnrelated(source, target)) { inferFromProperties(source, target); - inferFromSignatures(source, target, 0); - inferFromSignatures(source, target, 1); + inferFromSignatures(source, target, 0 /* Call */); + inferFromSignatures(source, target, 1 /* Construct */); inferFromIndexTypes(source, target); } } @@ -35419,19 +40923,19 @@ var ts; } } function inferFromIndexTypes(source, target) { - var targetStringIndexType = getIndexTypeOfType(target, 0); + var targetStringIndexType = getIndexTypeOfType(target, 0 /* String */); if (targetStringIndexType) { - var sourceIndexType = getIndexTypeOfType(source, 0) || - getImplicitIndexTypeOfType(source, 0); + var sourceIndexType = getIndexTypeOfType(source, 0 /* String */) || + getImplicitIndexTypeOfType(source, 0 /* String */); if (sourceIndexType) { inferFromTypes(sourceIndexType, targetStringIndexType); } } - var targetNumberIndexType = getIndexTypeOfType(target, 1); + var targetNumberIndexType = getIndexTypeOfType(target, 1 /* Number */); if (targetNumberIndexType) { - var sourceIndexType = getIndexTypeOfType(source, 1) || - getIndexTypeOfType(source, 0) || - getImplicitIndexTypeOfType(source, 1); + var sourceIndexType = getIndexTypeOfType(source, 1 /* Number */) || + getIndexTypeOfType(source, 0 /* String */) || + getImplicitIndexTypeOfType(source, 1 /* Number */); if (sourceIndexType) { inferFromTypes(sourceIndexType, targetNumberIndexType); } @@ -35447,6 +40951,10 @@ var ts; } return false; } + /** + * Return a new union or intersection type computed by removing a given set of types + * from a given union or intersection type. + */ function removeTypesFromUnionOrIntersection(type, typesToRemove) { var reducedTypes = []; for (var _i = 0, _a = type.types; _i < _a.length; _i++) { @@ -35455,38 +40963,46 @@ var ts; reducedTypes.push(t); } } - return type.flags & 262144 ? getUnionType(reducedTypes) : getIntersectionType(reducedTypes); + return type.flags & 262144 /* Union */ ? getUnionType(reducedTypes) : getIntersectionType(reducedTypes); } function hasPrimitiveConstraint(type) { var constraint = getConstraintOfTypeParameter(type); - return !!constraint && maybeTypeOfKind(constraint, 32764 | 1048576); + return !!constraint && maybeTypeOfKind(constraint, 32764 /* Primitive */ | 1048576 /* Index */); } function isObjectLiteralType(type) { - return !!(ts.getObjectFlags(type) & 128); + return !!(ts.getObjectFlags(type) & 128 /* ObjectLiteral */); } function widenObjectLiteralCandidates(candidates) { if (candidates.length > 1) { var objectLiterals = ts.filter(candidates, isObjectLiteralType); if (objectLiterals.length) { - var objectLiteralsType = getWidenedType(getUnionType(objectLiterals, 2)); + var objectLiteralsType = getWidenedType(getUnionType(objectLiterals, 2 /* Subtype */)); return ts.concatenate(ts.filter(candidates, function (t) { return !isObjectLiteralType(t); }), [objectLiteralsType]); } } return candidates; } function getContravariantInference(inference) { - return inference.priority & 28 ? getIntersectionType(inference.contraCandidates) : getCommonSubtype(inference.contraCandidates); + return inference.priority & 28 /* PriorityImpliesCombination */ ? getIntersectionType(inference.contraCandidates) : getCommonSubtype(inference.contraCandidates); } function getCovariantInference(inference, context, signature) { + // Extract all object literal types and replace them with a single widened and normalized type. var candidates = widenObjectLiteralCandidates(inference.candidates); + // We widen inferred literal types if + // all inferences were made to top-level occurrences of the type parameter, and + // the type parameter has no constraint or its constraint includes no primitive or literal types, and + // the type parameter was fixed during inference or does not occur at top-level in the return type. var primitiveConstraint = hasPrimitiveConstraint(inference.typeParameter); var widenLiteralTypes = !primitiveConstraint && inference.topLevel && (inference.isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), inference.typeParameter)); var baseCandidates = primitiveConstraint ? ts.sameMap(candidates, getRegularTypeOfLiteralType) : widenLiteralTypes ? ts.sameMap(candidates, getWidenedLiteralType) : candidates; - var unwidenedType = context.flags & 1 || inference.priority & 28 ? - getUnionType(baseCandidates, 2) : + // If all inferences were made from contravariant positions, infer a common subtype. Otherwise, if + // union types were requested or if all inferences were made from the return type position, infer a + // union type. Otherwise, infer a common supertype. + var unwidenedType = context.flags & 1 /* InferUnionTypes */ || inference.priority & 28 /* PriorityImpliesCombination */ ? + getUnionType(baseCandidates, 2 /* Subtype */) : getCommonSupertype(baseCandidates); return getWidenedType(unwidenedType); } @@ -35498,23 +41014,34 @@ var ts; if (signature) { if (inference.candidates) { inferredType = getCovariantInference(inference, context, signature); - if (inferredType.flags & 32768 && inference.contraCandidates) { + // If we have inferred 'never' but have contravariant candidates. To get a more specific type we + // infer from the contravariant candidates instead. + if (inferredType.flags & 32768 /* Never */ && inference.contraCandidates) { inferredType = getContravariantInference(inference); } } else if (inference.contraCandidates) { + // We only have contravariant inferences, infer the best common subtype of those inferredType = getContravariantInference(inference); } - else if (context.flags & 2) { + else if (context.flags & 2 /* NoDefault */) { + // We use silentNeverType as the wildcard that signals no inferences. inferredType = silentNeverType; } else { + // Infer either the default or the empty object type when no inferences were + // made. It is important to remember that in this case, inference still + // succeeds, meaning there is no error for not having inference candidates. An + // inference error only occurs when there are *conflicting* candidates, i.e. + // candidates with no common supertype. var defaultType = getDefaultFromTypeParameter(inference.typeParameter); if (defaultType) { + // Instantiate the default type. Any forward reference to a type + // parameter should be instantiated to the empty object type. inferredType = instantiateType(defaultType, combineTypeMappers(createBackreferenceMapper(context.signature.typeParameters, index), context)); } else { - inferredType = getDefaultTypeArgumentType(!!(context.flags & 4)); + inferredType = getDefaultTypeArgumentType(!!(context.flags & 4 /* AnyDefault */)); } } } @@ -35542,32 +41069,43 @@ var ts; } return result; } + // EXPRESSION TYPE CHECKING function getResolvedSymbol(node) { var links = getNodeLinks(node); if (!links.resolvedSymbol) { links.resolvedSymbol = !ts.nodeIsMissing(node) && - resolveName(node, node.escapedText, 67216319 | 1048576, ts.Diagnostics.Cannot_find_name_0, node, !ts.isWriteOnlyAccess(node), false, ts.Diagnostics.Cannot_find_name_0_Did_you_mean_1) || unknownSymbol; + resolveName(node, node.escapedText, 67216319 /* Value */ | 1048576 /* ExportValue */, ts.Diagnostics.Cannot_find_name_0, node, !ts.isWriteOnlyAccess(node), + /*excludeGlobals*/ false, ts.Diagnostics.Cannot_find_name_0_Did_you_mean_1) || unknownSymbol; } return links.resolvedSymbol; } function isInTypeQuery(node) { - return !!ts.findAncestor(node, function (n) { return n.kind === 165 ? true : n.kind === 71 || n.kind === 146 ? false : "quit"; }); + // TypeScript 1.0 spec (April 2014): 3.6.3 + // A type query consists of the keyword typeof followed by an expression. + // The expression is restricted to a single identifier or a sequence of identifiers separated by periods + return !!ts.findAncestor(node, function (n) { return n.kind === 165 /* TypeQuery */ ? true : n.kind === 71 /* Identifier */ || n.kind === 146 /* QualifiedName */ ? false : "quit"; }); } + // Return the flow cache key for a "dotted name" (i.e. a sequence of identifiers + // separated by dots). The key consists of the id of the symbol referenced by the + // leftmost identifier followed by zero or more property names separated by dots. + // The result is undefined if the reference isn't a dotted name. We prefix nodes + // occurring in an apparent type position with '@' because the control flow type + // of such nodes may be based on the apparent type instead of the declared type. function getFlowCacheKey(node) { - if (node.kind === 71) { + if (node.kind === 71 /* Identifier */) { var symbol = getResolvedSymbol(node); return symbol !== unknownSymbol ? (isConstraintPosition(node) ? "@" : "") + getSymbolId(symbol) : undefined; } - if (node.kind === 99) { + if (node.kind === 99 /* ThisKeyword */) { return "0"; } - if (node.kind === 185) { + if (node.kind === 185 /* PropertyAccessExpression */) { var key = getFlowCacheKey(node.expression); return key && key + "." + ts.idText(node.name); } - if (node.kind === 182) { + if (node.kind === 182 /* BindingElement */) { var container = node.parent.parent; - var key = container.kind === 182 ? getFlowCacheKey(container) : (container.initializer && getFlowCacheKey(container.initializer)); + var key = container.kind === 182 /* BindingElement */ ? getFlowCacheKey(container) : (container.initializer && getFlowCacheKey(container.initializer)); var text = getBindingElementNameText(node); var result = key && text && (key + "." + text); return result; @@ -35576,17 +41114,18 @@ var ts; } function getBindingElementNameText(element) { var parent = element.parent; - if (parent.kind === 180) { + if (parent.kind === 180 /* ObjectBindingPattern */) { var name = element.propertyName || element.name; switch (name.kind) { - case 71: + case 71 /* Identifier */: return ts.idText(name); - case 147: + case 147 /* ComputedPropertyName */: return ts.isStringOrNumericLiteral(name.expression) ? name.expression.text : undefined; - case 9: - case 8: + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: return name.text; default: + // Per types, array and object binding patterns remain, however they should never be present if propertyName is not defined ts.Debug.fail("Unexpected name kind for binding element name"); } } @@ -35596,28 +41135,28 @@ var ts; } function isMatchingReference(source, target) { switch (source.kind) { - case 71: - return target.kind === 71 && getResolvedSymbol(source) === getResolvedSymbol(target) || - (target.kind === 232 || target.kind === 182) && + case 71 /* Identifier */: + return target.kind === 71 /* Identifier */ && getResolvedSymbol(source) === getResolvedSymbol(target) || + (target.kind === 232 /* VariableDeclaration */ || target.kind === 182 /* BindingElement */) && getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(source)) === getSymbolOfNode(target); - case 99: - return target.kind === 99; - case 97: - return target.kind === 97; - case 185: - return target.kind === 185 && + case 99 /* ThisKeyword */: + return target.kind === 99 /* ThisKeyword */; + case 97 /* SuperKeyword */: + return target.kind === 97 /* SuperKeyword */; + case 185 /* PropertyAccessExpression */: + return target.kind === 185 /* PropertyAccessExpression */ && source.name.escapedText === target.name.escapedText && isMatchingReference(source.expression, target.expression); - case 182: - if (target.kind !== 185) + case 182 /* BindingElement */: + if (target.kind !== 185 /* PropertyAccessExpression */) return false; var t = target; if (t.name.escapedText !== getBindingElementNameText(source)) return false; - if (source.parent.parent.kind === 182 && isMatchingReference(source.parent.parent, t.expression)) { + if (source.parent.parent.kind === 182 /* BindingElement */ && isMatchingReference(source.parent.parent, t.expression)) { return true; } - if (source.parent.parent.kind === 232) { + if (source.parent.parent.kind === 232 /* VariableDeclaration */) { var maybeId = source.parent.parent.initializer; return !!maybeId && isMatchingReference(maybeId, t.expression); } @@ -35625,7 +41164,7 @@ var ts; return false; } function containsMatchingReference(source, target) { - while (source.kind === 185) { + while (source.kind === 185 /* PropertyAccessExpression */) { source = source.expression; if (isMatchingReference(source, target)) { return true; @@ -35633,27 +41172,31 @@ var ts; } return false; } + // Return true if target is a property access xxx.yyy, source is a property access xxx.zzz, the declared + // type of xxx is a union type, and yyy is a property that is possibly a discriminant. We consider a property + // a possible discriminant if its type differs in the constituents of containing union type, and if every + // choice is a unit type or a union of unit types. function containsMatchingReferenceDiscriminant(source, target) { - return target.kind === 185 && + return target.kind === 185 /* PropertyAccessExpression */ && containsMatchingReference(source, target.expression) && isDiscriminantProperty(getDeclaredTypeOfReference(target.expression), target.name.escapedText); } function getDeclaredTypeOfReference(expr) { - if (expr.kind === 71) { + if (expr.kind === 71 /* Identifier */) { return getTypeOfSymbol(getResolvedSymbol(expr)); } - if (expr.kind === 185) { + if (expr.kind === 185 /* PropertyAccessExpression */) { var type = getDeclaredTypeOfReference(expr.expression); return type && getTypeOfPropertyOfType(type, expr.name.escapedText); } return undefined; } function isDiscriminantProperty(type, name) { - if (type && type.flags & 262144) { + if (type && type.flags & 262144 /* Union */) { var prop = getUnionOrIntersectionProperty(type, name); - if (prop && ts.getCheckFlags(prop) & 2) { + if (prop && ts.getCheckFlags(prop) & 2 /* SyntheticProperty */) { if (prop.isDiscriminantProperty === undefined) { - prop.isDiscriminantProperty = !!(prop.checkFlags & 32) && isLiteralType(getTypeOfSymbol(prop)); + prop.isDiscriminantProperty = !!(prop.checkFlags & 32 /* HasNonUniformType */) && isLiteralType(getTypeOfSymbol(prop)); } return prop.isDiscriminantProperty; } @@ -35686,7 +41229,7 @@ var ts; } } } - if (callExpression.expression.kind === 185 && + if (callExpression.expression.kind === 185 /* PropertyAccessExpression */ && isOrContainsMatchingReference(reference, callExpression.expression.expression)) { return true; } @@ -35700,7 +41243,7 @@ var ts; return flow.id; } function typeMaybeAssignableTo(source, target) { - if (!(source.flags & 262144)) { + if (!(source.flags & 262144 /* Union */)) { return isTypeAssignableTo(source, target); } for (var _i = 0, _a = source.types; _i < _a.length; _i++) { @@ -35711,20 +41254,23 @@ var ts; } return false; } + // Remove those constituent types of declaredType to which no constituent type of assignedType is assignable. + // For example, when a variable of type number | string | boolean is assigned a value of type number | boolean, + // we remove type string. function getAssignmentReducedType(declaredType, assignedType) { if (declaredType !== assignedType) { - if (assignedType.flags & 32768) { + if (assignedType.flags & 32768 /* Never */) { return assignedType; } var reducedType = filterType(declaredType, function (t) { return typeMaybeAssignableTo(assignedType, t); }); - if (!(reducedType.flags & 32768)) { + if (!(reducedType.flags & 32768 /* Never */)) { return reducedType; } } return declaredType; } function getTypeFactsOfTypes(types) { - var result = 0; + var result = 0 /* None */; for (var _i = 0, types_12 = types; _i < types_12.length; _i++) { var t = types_12[_i]; result |= getTypeFacts(t); @@ -35732,62 +41278,64 @@ var ts; return result; } function isFunctionObjectType(type) { + // We do a quick check for a "bind" property before performing the more expensive subtype + // check. This gives us a quicker out in the common case where an object type is not a function. var resolved = resolveStructuredTypeMembers(type); return !!(resolved.callSignatures.length || resolved.constructSignatures.length || resolved.members.get("bind") && isTypeSubtypeOf(type, globalFunctionType)); } function getTypeFacts(type) { var flags = type.flags; - if (flags & 4) { - return strictNullChecks ? 4079361 : 4194049; + if (flags & 4 /* String */) { + return strictNullChecks ? 4079361 /* StringStrictFacts */ : 4194049 /* StringFacts */; } - if (flags & 64) { + if (flags & 64 /* StringLiteral */) { var isEmpty = type.value === ""; return strictNullChecks ? - isEmpty ? 3030785 : 1982209 : - isEmpty ? 3145473 : 4194049; + isEmpty ? 3030785 /* EmptyStringStrictFacts */ : 1982209 /* NonEmptyStringStrictFacts */ : + isEmpty ? 3145473 /* EmptyStringFacts */ : 4194049 /* NonEmptyStringFacts */; } - if (flags & (8 | 32)) { - return strictNullChecks ? 4079234 : 4193922; + if (flags & (8 /* Number */ | 32 /* Enum */)) { + return strictNullChecks ? 4079234 /* NumberStrictFacts */ : 4193922 /* NumberFacts */; } - if (flags & 128) { + if (flags & 128 /* NumberLiteral */) { var isZero = type.value === 0; return strictNullChecks ? - isZero ? 3030658 : 1982082 : - isZero ? 3145346 : 4193922; + isZero ? 3030658 /* ZeroStrictFacts */ : 1982082 /* NonZeroStrictFacts */ : + isZero ? 3145346 /* ZeroFacts */ : 4193922 /* NonZeroFacts */; } - if (flags & 16) { - return strictNullChecks ? 4078980 : 4193668; + if (flags & 16 /* Boolean */) { + return strictNullChecks ? 4078980 /* BooleanStrictFacts */ : 4193668 /* BooleanFacts */; } - if (flags & 272) { + if (flags & 272 /* BooleanLike */) { return strictNullChecks ? - type === falseType ? 3030404 : 1981828 : - type === falseType ? 3145092 : 4193668; + type === falseType ? 3030404 /* FalseStrictFacts */ : 1981828 /* TrueStrictFacts */ : + type === falseType ? 3145092 /* FalseFacts */ : 4193668 /* TrueFacts */; } - if (flags & 131072) { + if (flags & 131072 /* Object */) { return isFunctionObjectType(type) ? - strictNullChecks ? 1970144 : 4181984 : - strictNullChecks ? 1972176 : 4184016; + strictNullChecks ? 1970144 /* FunctionStrictFacts */ : 4181984 /* FunctionFacts */ : + strictNullChecks ? 1972176 /* ObjectStrictFacts */ : 4184016 /* ObjectFacts */; } - if (flags & (4096 | 8192)) { - return 2457472; + if (flags & (4096 /* Void */ | 8192 /* Undefined */)) { + return 2457472 /* UndefinedFacts */; } - if (flags & 16384) { - return 2340752; + if (flags & 16384 /* Null */) { + return 2340752 /* NullFacts */; } - if (flags & 3072) { - return strictNullChecks ? 1981320 : 4193160; + if (flags & 3072 /* ESSymbolLike */) { + return strictNullChecks ? 1981320 /* SymbolStrictFacts */ : 4193160 /* SymbolFacts */; } - if (flags & 16777216) { - return strictNullChecks ? 1972176 : 4184016; + if (flags & 16777216 /* NonPrimitive */) { + return strictNullChecks ? 1972176 /* ObjectStrictFacts */ : 4184016 /* ObjectFacts */; } - if (flags & 15794176) { + if (flags & 15794176 /* Instantiable */) { return getTypeFacts(getBaseConstraintOfType(type) || emptyObjectType); } - if (flags & 786432) { + if (flags & 786432 /* UnionOrIntersection */) { return getTypeFactsOfTypes(type.types); } - return 4194303; + return 4194303 /* All */; } function getTypeWithFacts(type, include) { return filterType(type, function (t) { return (getTypeFacts(t) & include) !== 0; }); @@ -35795,35 +41343,35 @@ var ts; function getTypeWithDefault(type, defaultExpression) { if (defaultExpression) { var defaultType = getTypeOfExpression(defaultExpression); - return getUnionType([getTypeWithFacts(type, 131072), defaultType]); + return getUnionType([getTypeWithFacts(type, 131072 /* NEUndefined */), defaultType]); } return type; } function getTypeOfDestructuredProperty(type, name) { var text = ts.getTextOfPropertyName(name); return getConstraintForLocation(getTypeOfPropertyOfType(type, text), name) || - isNumericLiteralName(text) && getIndexTypeOfType(type, 1) || - getIndexTypeOfType(type, 0) || + isNumericLiteralName(text) && getIndexTypeOfType(type, 1 /* Number */) || + getIndexTypeOfType(type, 0 /* String */) || errorType; } function getTypeOfDestructuredArrayElement(type, index) { return isTupleLikeType(type) && getTypeOfPropertyOfType(type, "" + index) || - checkIteratedTypeOrElementType(type, undefined, false, false) || + checkIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false) || errorType; } function getTypeOfDestructuredSpreadExpression(type) { - return createArrayType(checkIteratedTypeOrElementType(type, undefined, false, false) || errorType); + return createArrayType(checkIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false) || errorType); } function getAssignedTypeOfBinaryExpression(node) { - var isDestructuringDefaultAssignment = node.parent.kind === 183 && isDestructuringAssignmentTarget(node.parent) || - node.parent.kind === 270 && isDestructuringAssignmentTarget(node.parent.parent); + var isDestructuringDefaultAssignment = node.parent.kind === 183 /* ArrayLiteralExpression */ && isDestructuringAssignmentTarget(node.parent) || + node.parent.kind === 270 /* PropertyAssignment */ && isDestructuringAssignmentTarget(node.parent.parent); return isDestructuringDefaultAssignment ? getTypeWithDefault(getAssignedType(node), node.right) : getTypeOfExpression(node.right); } function isDestructuringAssignmentTarget(parent) { - return parent.parent.kind === 200 && parent.parent.left === parent || - parent.parent.kind === 222 && parent.parent.initializer === parent; + return parent.parent.kind === 200 /* BinaryExpression */ && parent.parent.left === parent || + parent.parent.kind === 222 /* ForOfStatement */ && parent.parent.initializer === parent; } function getAssignedTypeOfArrayLiteralElement(node, element) { return getTypeOfDestructuredArrayElement(getAssignedType(node), node.elements.indexOf(element)); @@ -35840,21 +41388,21 @@ var ts; function getAssignedType(node) { var parent = node.parent; switch (parent.kind) { - case 221: + case 221 /* ForInStatement */: return stringType; - case 222: + case 222 /* ForOfStatement */: return checkRightHandSideOfForOf(parent.expression, parent.awaitModifier) || errorType; - case 200: + case 200 /* BinaryExpression */: return getAssignedTypeOfBinaryExpression(parent); - case 194: + case 194 /* DeleteExpression */: return undefinedType; - case 183: + case 183 /* ArrayLiteralExpression */: return getAssignedTypeOfArrayLiteralElement(parent, node); - case 204: + case 204 /* SpreadElement */: return getAssignedTypeOfSpreadExpression(parent); - case 270: + case 270 /* PropertyAssignment */: return getAssignedTypeOfPropertyAssignment(parent); - case 271: + case 271 /* ShorthandPropertyAssignment */: return getAssignedTypeOfShorthandPropertyAssignment(parent); } return errorType; @@ -35862,7 +41410,7 @@ var ts; function getInitialTypeOfBindingElement(node) { var pattern = node.parent; var parentType = getInitialType(pattern.parent); - var type = pattern.kind === 180 ? + var type = pattern.kind === 180 /* ObjectBindingPattern */ ? getTypeOfDestructuredProperty(parentType, node.propertyName || node.name) : !node.dotDotDotToken ? getTypeOfDestructuredArrayElement(parentType, pattern.elements.indexOf(node)) : @@ -35870,6 +41418,9 @@ var ts; return getTypeWithDefault(type, node.initializer); } function getTypeOfInitializer(node) { + // Return the cached type if one is available. If the type of the variable was inferred + // from its initializer, we'll already have cached the type. Otherwise we compute it now + // without caching such that transient types are reflected. var links = getNodeLinks(node); return links.resolvedType || getTypeOfExpression(node); } @@ -35877,39 +41428,39 @@ var ts; if (node.initializer) { return getTypeOfInitializer(node.initializer); } - if (node.parent.parent.kind === 221) { + if (node.parent.parent.kind === 221 /* ForInStatement */) { return stringType; } - if (node.parent.parent.kind === 222) { + if (node.parent.parent.kind === 222 /* ForOfStatement */) { return checkRightHandSideOfForOf(node.parent.parent.expression, node.parent.parent.awaitModifier) || errorType; } return errorType; } function getInitialType(node) { - return node.kind === 232 ? + return node.kind === 232 /* VariableDeclaration */ ? getInitialTypeOfVariableDeclaration(node) : getInitialTypeOfBindingElement(node); } function getInitialOrAssignedType(node) { - return node.kind === 232 || node.kind === 182 ? + return node.kind === 232 /* VariableDeclaration */ || node.kind === 182 /* BindingElement */ ? getInitialType(node) : getAssignedType(node); } function isEmptyArrayAssignment(node) { - return node.kind === 232 && node.initializer && + return node.kind === 232 /* VariableDeclaration */ && node.initializer && isEmptyArrayLiteral(node.initializer) || - node.kind !== 182 && node.parent.kind === 200 && + node.kind !== 182 /* BindingElement */ && node.parent.kind === 200 /* BinaryExpression */ && isEmptyArrayLiteral(node.parent.right); } function getReferenceCandidate(node) { switch (node.kind) { - case 191: + case 191 /* ParenthesizedExpression */: return getReferenceCandidate(node.expression); - case 200: + case 200 /* BinaryExpression */: switch (node.operatorToken.kind) { - case 58: + case 58 /* EqualsToken */: return getReferenceCandidate(node.left); - case 26: + case 26 /* CommaToken */: return getReferenceCandidate(node.right); } } @@ -35917,13 +41468,13 @@ var ts; } function getReferenceRoot(node) { var parent = node.parent; - return parent.kind === 191 || - parent.kind === 200 && parent.operatorToken.kind === 58 && parent.left === node || - parent.kind === 200 && parent.operatorToken.kind === 26 && parent.right === node ? + return parent.kind === 191 /* ParenthesizedExpression */ || + parent.kind === 200 /* BinaryExpression */ && parent.operatorToken.kind === 58 /* EqualsToken */ && parent.left === node || + parent.kind === 200 /* BinaryExpression */ && parent.operatorToken.kind === 26 /* CommaToken */ && parent.right === node ? getReferenceRoot(parent) : node; } function getTypeOfSwitchClause(clause) { - if (clause.kind === 266) { + if (clause.kind === 266 /* CaseClause */) { return getRegularTypeOfLiteralType(getTypeOfExpression(clause.expression)); } return neverType; @@ -35940,13 +41491,13 @@ var ts; return links.switchTypes; } function eachTypeContainedIn(source, types) { - return source.flags & 262144 ? !ts.forEach(source.types, function (t) { return !ts.contains(types, t); }) : ts.contains(types, source); + return source.flags & 262144 /* Union */ ? !ts.forEach(source.types, function (t) { return !ts.contains(types, t); }) : ts.contains(types, source); } function isTypeSubsetOf(source, target) { - return source === target || target.flags & 262144 && isTypeSubsetOfUnion(source, target); + return source === target || target.flags & 262144 /* Union */ && isTypeSubsetOfUnion(source, target); } function isTypeSubsetOfUnion(source, target) { - if (source.flags & 262144) { + if (source.flags & 262144 /* Union */) { for (var _i = 0, _a = source.types; _i < _a.length; _i++) { var t = _a[_i]; if (!containsType(target.types, t)) { @@ -35955,27 +41506,27 @@ var ts; } return true; } - if (source.flags & 512 && getBaseTypeOfEnumLiteralType(source) === target) { + if (source.flags & 512 /* EnumLiteral */ && getBaseTypeOfEnumLiteralType(source) === target) { return true; } return containsType(target.types, source); } function forEachType(type, f) { - return type.flags & 262144 ? ts.forEach(type.types, f) : f(type); + return type.flags & 262144 /* Union */ ? ts.forEach(type.types, f) : f(type); } function filterType(type, f) { - if (type.flags & 262144) { + if (type.flags & 262144 /* Union */) { var types = type.types; var filtered = ts.filter(types, f); - return filtered === types ? type : getUnionTypeFromSortedList(filtered, type.flags & 67108864); + return filtered === types ? type : getUnionTypeFromSortedList(filtered, type.flags & 67108864 /* UnionOfUnitTypes */); } return f(type) ? type : neverType; } function mapType(type, mapper, noReductions) { - if (type.flags & 32768) { + if (type.flags & 32768 /* Never */) { return type; } - if (!(type.flags & 262144)) { + if (!(type.flags & 262144 /* Union */)) { return mapper(type); } var types = type.types; @@ -35996,17 +41547,20 @@ var ts; } } } - return mappedTypes ? getUnionType(mappedTypes, noReductions ? 0 : 1) : mappedType; + return mappedTypes ? getUnionType(mappedTypes, noReductions ? 0 /* None */ : 1 /* Literal */) : mappedType; } function extractTypesOfKind(type, kind) { return filterType(type, function (t) { return (t.flags & kind) !== 0; }); } + // Return a new type in which occurrences of the string and number primitive types in + // typeWithPrimitives have been replaced with occurrences of string literals and numeric + // literals in typeWithLiterals, respectively. function replacePrimitivesWithLiterals(typeWithPrimitives, typeWithLiterals) { - if (isTypeSubsetOf(stringType, typeWithPrimitives) && maybeTypeOfKind(typeWithLiterals, 64) || - isTypeSubsetOf(numberType, typeWithPrimitives) && maybeTypeOfKind(typeWithLiterals, 128)) { + if (isTypeSubsetOf(stringType, typeWithPrimitives) && maybeTypeOfKind(typeWithLiterals, 64 /* StringLiteral */) || + isTypeSubsetOf(numberType, typeWithPrimitives) && maybeTypeOfKind(typeWithLiterals, 128 /* NumberLiteral */)) { return mapType(typeWithPrimitives, function (t) { - return t.flags & 4 ? extractTypesOfKind(typeWithLiterals, 4 | 64) : - t.flags & 8 ? extractTypesOfKind(typeWithLiterals, 8 | 128) : + return t.flags & 4 /* String */ ? extractTypesOfKind(typeWithLiterals, 4 /* String */ | 64 /* StringLiteral */) : + t.flags & 8 /* Number */ ? extractTypesOfKind(typeWithLiterals, 8 /* Number */ | 128 /* NumberLiteral */) : t; }); } @@ -36021,40 +41575,48 @@ var ts; function createFlowType(type, incomplete) { return incomplete ? { flags: 0, type: type } : type; } + // An evolving array type tracks the element types that have so far been seen in an + // 'x.push(value)' or 'x[n] = value' operation along the control flow graph. Evolving + // array types are ultimately converted into manifest array types (using getFinalArrayType) + // and never escape the getFlowTypeOfReference function. function createEvolvingArrayType(elementType) { - var result = createObjectType(256); + var result = createObjectType(256 /* EvolvingArray */); result.elementType = elementType; return result; } function getEvolvingArrayType(elementType) { return evolvingArrayTypes[elementType.id] || (evolvingArrayTypes[elementType.id] = createEvolvingArrayType(elementType)); } + // When adding evolving array element types we do not perform subtype reduction. Instead, + // we defer subtype reduction until the evolving array type is finalized into a manifest + // array type. function addEvolvingArrayElementType(evolvingArrayType, node) { var elementType = getBaseTypeOfLiteralType(getContextFreeTypeOfExpression(node)); return isTypeSubsetOf(elementType, evolvingArrayType.elementType) ? evolvingArrayType : getEvolvingArrayType(getUnionType([evolvingArrayType.elementType, elementType])); } function createFinalArrayType(elementType) { - return elementType.flags & 32768 ? + return elementType.flags & 32768 /* Never */ ? autoArrayType : - createArrayType(elementType.flags & 262144 ? - getUnionType(elementType.types, 2) : + createArrayType(elementType.flags & 262144 /* Union */ ? + getUnionType(elementType.types, 2 /* Subtype */) : elementType); } + // We perform subtype reduction upon obtaining the final array type from an evolving array type. function getFinalArrayType(evolvingArrayType) { return evolvingArrayType.finalArrayType || (evolvingArrayType.finalArrayType = createFinalArrayType(evolvingArrayType.elementType)); } function finalizeEvolvingArrayType(type) { - return ts.getObjectFlags(type) & 256 ? getFinalArrayType(type) : type; + return ts.getObjectFlags(type) & 256 /* EvolvingArray */ ? getFinalArrayType(type) : type; } function getElementTypeOfEvolvingArrayType(type) { - return ts.getObjectFlags(type) & 256 ? type.elementType : neverType; + return ts.getObjectFlags(type) & 256 /* EvolvingArray */ ? type.elementType : neverType; } function isEvolvingArrayTypeList(types) { var hasEvolvingArrayType = false; for (var _i = 0, types_14 = types; _i < types_14.length; _i++) { var t = types_14[_i]; - if (!(t.flags & 32768)) { - if (!(ts.getObjectFlags(t) & 256)) { + if (!(t.flags & 32768 /* Never */)) { + if (!(ts.getObjectFlags(t) & 256 /* EvolvingArray */)) { return false; } hasEvolvingArrayType = true; @@ -36062,23 +41624,28 @@ var ts; } return hasEvolvingArrayType; } + // At flow control branch or loop junctions, if the type along every antecedent code path + // is an evolving array type, we construct a combined evolving array type. Otherwise we + // finalize all evolving array types. function getUnionOrEvolvingArrayType(types, subtypeReduction) { return isEvolvingArrayTypeList(types) ? getEvolvingArrayType(getUnionType(ts.map(types, getElementTypeOfEvolvingArrayType))) : getUnionType(ts.sameMap(types, finalizeEvolvingArrayType), subtypeReduction); } + // Return true if the given node is 'x' in an 'x.length', x.push(value)', 'x.unshift(value)' or + // 'x[n] = value' operation, where 'n' is an expression of type any, undefined, or a number-like type. function isEvolvingArrayOperationTarget(node) { var root = getReferenceRoot(node); var parent = root.parent; - var isLengthPushOrUnshift = parent.kind === 185 && (parent.name.escapedText === "length" || - parent.parent.kind === 187 && ts.isPushOrUnshiftIdentifier(parent.name)); - var isElementAssignment = parent.kind === 186 && + var isLengthPushOrUnshift = parent.kind === 185 /* PropertyAccessExpression */ && (parent.name.escapedText === "length" || + parent.parent.kind === 187 /* CallExpression */ && ts.isPushOrUnshiftIdentifier(parent.name)); + var isElementAssignment = parent.kind === 186 /* ElementAccessExpression */ && parent.expression === root && - parent.parent.kind === 200 && - parent.parent.operatorToken.kind === 58 && + parent.parent.kind === 200 /* BinaryExpression */ && + parent.parent.operatorToken.kind === 58 /* EqualsToken */ && parent.parent.left === parent && !ts.isAssignmentTarget(parent.parent) && - isTypeAssignableToKind(getTypeOfExpression(parent.argumentExpression), 168); + isTypeAssignableToKind(getTypeOfExpression(parent.argumentExpression), 168 /* NumberLike */); return isLengthPushOrUnshift || isElementAssignment; } function maybeTypePredicateCall(node) { @@ -36089,11 +41656,11 @@ var ts; return links.maybeTypePredicate; } function getMaybeTypePredicate(node) { - if (node.expression.kind !== 97) { + if (node.expression.kind !== 97 /* SuperKeyword */) { var funcType = checkNonNullExpression(node.expression); if (funcType !== silentNeverType) { var apparentType = getApparentType(funcType); - return apparentType !== errorType && ts.some(getSignaturesOfType(apparentType, 0), signatureHasTypePredicate); + return apparentType !== errorType && ts.some(getSignaturesOfType(apparentType, 0 /* Call */), signatureHasTypePredicate); } } return false; @@ -36111,19 +41678,25 @@ var ts; if (flowAnalysisDisabled) { return errorType; } - if (!reference.flowNode || !couldBeUninitialized && !(declaredType.flags & 33492479)) { + if (!reference.flowNode || !couldBeUninitialized && !(declaredType.flags & 33492479 /* Narrowable */)) { return declaredType; } var sharedFlowStart = sharedFlowCount; var evolvedType = getTypeFromFlowType(getTypeAtFlowNode(reference.flowNode)); sharedFlowCount = sharedFlowStart; - var resultType = ts.getObjectFlags(evolvedType) & 256 && isEvolvingArrayOperationTarget(reference) ? anyArrayType : finalizeEvolvingArrayType(evolvedType); - if (reference.parent && reference.parent.kind === 209 && getTypeWithFacts(resultType, 524288).flags & 32768) { + // When the reference is 'x' in an 'x.length', 'x.push(value)', 'x.unshift(value)' or x[n] = value' operation, + // we give type 'any[]' to 'x' instead of using the type determined by control flow analysis such that operations + // on empty arrays are possible without implicit any errors and new element types can be inferred without + // type mismatch errors. + var resultType = ts.getObjectFlags(evolvedType) & 256 /* EvolvingArray */ && isEvolvingArrayOperationTarget(reference) ? anyArrayType : finalizeEvolvingArrayType(evolvedType); + if (reference.parent && reference.parent.kind === 209 /* NonNullExpression */ && getTypeWithFacts(resultType, 524288 /* NEUndefinedOrNull */).flags & 32768 /* Never */) { return declaredType; } return resultType; function getTypeAtFlowNode(flow) { if (flowDepth === 2500) { + // We have made 2500 recursive invocations. To avoid overflowing the call stack we report an error + // and disable further control flow analysis in the containing function or module body. flowAnalysisDisabled = true; reportFlowControlError(reference); return errorType; @@ -36131,7 +41704,10 @@ var ts; flowDepth++; while (true) { var flags = flow.flags; - if (flags & 1024) { + if (flags & 1024 /* Shared */) { + // We cache results of flow type resolution for shared nodes that were previously visited in + // the same getFlowTypeOfReference invocation. A node is considered shared when it is the + // antecedent of more than one node. for (var i = sharedFlowStart; i < sharedFlowCount; i++) { if (sharedFlowNodes[i] === flow) { flowDepth--; @@ -36140,56 +41716,64 @@ var ts; } } var type = void 0; - if (flags & 4096) { + if (flags & 4096 /* AfterFinally */) { + // block flow edge: finally -> pre-try (for larger explanation check comment in binder.ts - bindTryStatement flow.locked = true; type = getTypeAtFlowNode(flow.antecedent); flow.locked = false; } - else if (flags & 2048) { + else if (flags & 2048 /* PreFinally */) { + // locked pre-finally flows are filtered out in getTypeAtFlowBranchLabel + // so here just redirect to antecedent flow = flow.antecedent; continue; } - else if (flags & 16) { + else if (flags & 16 /* Assignment */) { type = getTypeAtFlowAssignment(flow); if (!type) { flow = flow.antecedent; continue; } } - else if (flags & 96) { + else if (flags & 96 /* Condition */) { type = getTypeAtFlowCondition(flow); } - else if (flags & 128) { + else if (flags & 128 /* SwitchClause */) { type = getTypeAtSwitchClause(flow); } - else if (flags & 12) { + else if (flags & 12 /* Label */) { if (flow.antecedents.length === 1) { flow = flow.antecedents[0]; continue; } - type = flags & 4 ? + type = flags & 4 /* BranchLabel */ ? getTypeAtFlowBranchLabel(flow) : getTypeAtFlowLoopLabel(flow); } - else if (flags & 256) { + else if (flags & 256 /* ArrayMutation */) { type = getTypeAtFlowArrayMutation(flow); if (!type) { flow = flow.antecedent; continue; } } - else if (flags & 2) { + else if (flags & 2 /* Start */) { + // Check if we should continue with the control flow of the containing function. var container = flow.container; - if (container && container !== flowContainer && reference.kind !== 185 && reference.kind !== 99) { + if (container && container !== flowContainer && reference.kind !== 185 /* PropertyAccessExpression */ && reference.kind !== 99 /* ThisKeyword */) { flow = container.flowNode; continue; } + // At the top of the flow we have the initial type. type = initialType; } else { + // Unreachable code errors are reported in the binding phase. Here we + // simply return the non-auto declared type to reduce follow-on errors. type = convertAutoToAny(declaredType); } - if (flags & 1024) { + if (flags & 1024 /* Shared */) { + // Record visited node and the associated type in the cache. sharedFlowNodes[sharedFlowCount] = flow; sharedFlowTypes[sharedFlowCount] = type; sharedFlowCount++; @@ -36200,8 +41784,10 @@ var ts; } function getTypeAtFlowAssignment(flow) { var node = flow.node; + // Assignments only narrow the computed type if the declared type is a union type. Thus, we + // only need to evaluate the assigned type if the declared type is a union type. if (isMatchingReference(reference, node)) { - if (ts.getAssignmentTargetKind(node) === 2) { + if (ts.getAssignmentTargetKind(node) === 2 /* Compound */) { var flowType = getTypeAtFlowNode(flow.antecedent); return createFlowType(getBaseTypeOfLiteralType(getTypeFromFlowType(flowType)), isIncomplete(flowType)); } @@ -36212,28 +41798,33 @@ var ts; var assignedType = getBaseTypeOfLiteralType(getInitialOrAssignedType(node)); return isTypeAssignableTo(assignedType, declaredType) ? assignedType : anyArrayType; } - if (declaredType.flags & 262144) { + if (declaredType.flags & 262144 /* Union */) { return getAssignmentReducedType(declaredType, getInitialOrAssignedType(node)); } return declaredType; } + // We didn't have a direct match. However, if the reference is a dotted name, this + // may be an assignment to a left hand part of the reference. For example, for a + // reference 'x.y.z', we may be at an assignment to 'x.y' or 'x'. In that case, + // return the declared type. if (containsMatchingReference(reference, node)) { return declaredType; } + // Assignment doesn't affect reference return undefined; } function getTypeAtFlowArrayMutation(flow) { if (declaredType === autoType || declaredType === autoArrayType) { var node = flow.node; - var expr = node.kind === 187 ? + var expr = node.kind === 187 /* CallExpression */ ? node.expression.expression : node.left.expression; if (isMatchingReference(reference, getReferenceCandidate(expr))) { var flowType = getTypeAtFlowNode(flow.antecedent); var type = getTypeFromFlowType(flowType); - if (ts.getObjectFlags(type) & 256) { + if (ts.getObjectFlags(type) & 256 /* EvolvingArray */) { var evolvedType_1 = type; - if (node.kind === 187) { + if (node.kind === 187 /* CallExpression */) { for (var _i = 0, _a = node.arguments; _i < _a.length; _i++) { var arg = _a[_i]; evolvedType_1 = addEvolvingArrayElementType(evolvedType_1, arg); @@ -36241,7 +41832,7 @@ var ts; } else { var indexType = getTypeOfExpression(node.left.argumentExpression); - if (isTypeAssignableToKind(indexType, 168)) { + if (isTypeAssignableToKind(indexType, 168 /* NumberLike */)) { evolvedType_1 = addEvolvingArrayElementType(evolvedType_1, node.right); } } @@ -36255,17 +41846,24 @@ var ts; function getTypeAtFlowCondition(flow) { var flowType = getTypeAtFlowNode(flow.antecedent); var type = getTypeFromFlowType(flowType); - if (type.flags & 32768) { + if (type.flags & 32768 /* Never */) { return flowType; } - var assumeTrue = (flow.flags & 32) !== 0; + // If we have an antecedent type (meaning we're reachable in some way), we first + // attempt to narrow the antecedent type. If that produces the never type, and if + // the antecedent type is incomplete (i.e. a transient type in a loop), then we + // take the type guard as an indication that control *could* reach here once we + // have the complete type. We proceed by switching to the silent never type which + // doesn't report errors when operators are applied to it. Note that this is the + // *only* place a silent never type is ever generated. + var assumeTrue = (flow.flags & 32 /* TrueCondition */) !== 0; var nonEvolvingType = finalizeEvolvingArrayType(type); var narrowedType = narrowType(nonEvolvingType, flow.expression, assumeTrue); if (narrowedType === nonEvolvingType) { return flowType; } var incomplete = isIncomplete(flowType); - var resultType = incomplete && narrowedType.flags & 32768 ? silentNeverType : narrowedType; + var resultType = incomplete && narrowedType.flags & 32768 /* Never */ ? silentNeverType : narrowedType; return createFlowType(resultType, incomplete); } function getTypeAtSwitchClause(flow) { @@ -36286,15 +41884,25 @@ var ts; var seenIncomplete = false; for (var _i = 0, _a = flow.antecedents; _i < _a.length; _i++) { var antecedent = _a[_i]; - if (antecedent.flags & 2048 && antecedent.lock.locked) { + if (antecedent.flags & 2048 /* PreFinally */ && antecedent.lock.locked) { + // if flow correspond to branch from pre-try to finally and this branch is locked - this means that + // we initially have started following the flow outside the finally block. + // in this case we should ignore this branch. continue; } var flowType = getTypeAtFlowNode(antecedent); var type = getTypeFromFlowType(flowType); + // If the type at a particular antecedent path is the declared type and the + // reference is known to always be assigned (i.e. when declared and initial types + // are the same), there is no reason to process more antecedents since the only + // possible outcome is subtypes that will be removed in the final union type anyway. if (type === declaredType && declaredType === initialType) { return type; } ts.pushIfUnique(antecedentTypes, type); + // If an antecedent type is not a subset of the declared type, we need to perform + // subtype reduction. This happens when a "foreign" type is injected into the control + // flow using the instanceof operator or a user defined type predicate. if (!isTypeSubsetOf(type, declaredType)) { subtypeReduction = true; } @@ -36302,13 +41910,16 @@ var ts; seenIncomplete = true; } } - return createFlowType(getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction ? 2 : 1), seenIncomplete); + return createFlowType(getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction ? 2 /* Subtype */ : 1 /* Literal */), seenIncomplete); } function getTypeAtFlowLoopLabel(flow) { + // If we have previously computed the control flow type for the reference at + // this flow loop junction, return the cached type. var id = getFlowNodeId(flow); var cache = flowLoopCaches[id] || (flowLoopCaches[id] = ts.createMap()); if (!key) { key = getFlowCacheKey(reference); + // No cache key is generated when binding patterns are in unnarrowable situations if (!key) { return declaredType; } @@ -36317,11 +41928,21 @@ var ts; if (cached) { return cached; } + // If this flow loop junction and reference are already being processed, return + // the union of the types computed for each branch so far, marked as incomplete. + // It is possible to see an empty array in cases where loops are nested and the + // back edge of the outer loop reaches an inner loop that is already being analyzed. + // In such cases we restart the analysis of the inner loop, which will then see + // a non-empty in-process array for the outer loop and eventually terminate because + // the first antecedent of a loop junction is always the non-looping control flow + // path that leads to the top. for (var i = flowLoopStart; i < flowLoopCount; i++) { if (flowLoopNodes[i] === flow && flowLoopKeys[i] === key && flowLoopTypes[i].length) { - return createFlowType(getUnionOrEvolvingArrayType(flowLoopTypes[i], 1), true); + return createFlowType(getUnionOrEvolvingArrayType(flowLoopTypes[i], 1 /* Literal */), /*incomplete*/ true); } } + // Add the flow loop junction and reference to the in-process stack and analyze + // each antecedent code path. var antecedentTypes = []; var subtypeReduction = false; var firstAntecedentType; @@ -36337,28 +41958,39 @@ var ts; firstAntecedentType = flowType; } var type = getTypeFromFlowType(flowType); + // If we see a value appear in the cache it is a sign that control flow analysis + // was restarted and completed by checkExpressionCached. We can simply pick up + // the resulting type and bail out. var cached_1 = cache.get(key); if (cached_1) { return cached_1; } ts.pushIfUnique(antecedentTypes, type); + // If an antecedent type is not a subset of the declared type, we need to perform + // subtype reduction. This happens when a "foreign" type is injected into the control + // flow using the instanceof operator or a user defined type predicate. if (!isTypeSubsetOf(type, declaredType)) { subtypeReduction = true; } + // If the type at a particular antecedent path is the declared type there is no + // reason to process more antecedents since the only possible outcome is subtypes + // that will be removed in the final union type anyway. if (type === declaredType) { break; } } - var result = getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction ? 2 : 1); + // The result is incomplete if the first antecedent (the non-looping control flow path) + // is incomplete. + var result = getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction ? 2 /* Subtype */ : 1 /* Literal */); if (isIncomplete(firstAntecedentType)) { - return createFlowType(result, true); + return createFlowType(result, /*incomplete*/ true); } cache.set(key, result); return result; } function isMatchingReferenceDiscriminant(expr, computedType) { - return expr.kind === 185 && - computedType.flags & 262144 && + return expr.kind === 185 /* PropertyAccessExpression */ && + computedType.flags & 262144 /* Union */ && isMatchingReference(reference, expr.expression) && isDiscriminantProperty(computedType, expr.name.escapedText); } @@ -36370,10 +42002,10 @@ var ts; } function narrowTypeByTruthiness(type, expr, assumeTrue) { if (isMatchingReference(reference, expr)) { - return getTypeWithFacts(type, assumeTrue ? 1048576 : 2097152); + return getTypeWithFacts(type, assumeTrue ? 1048576 /* Truthy */ : 2097152 /* Falsy */); } if (isMatchingReferenceDiscriminant(expr, declaredType)) { - return narrowTypeByDiscriminant(type, expr, function (t) { return getTypeWithFacts(t, assumeTrue ? 1048576 : 2097152); }); + return narrowTypeByDiscriminant(type, expr, function (t) { return getTypeWithFacts(t, assumeTrue ? 1048576 /* Truthy */ : 2097152 /* Falsy */); }); } if (containsMatchingReferenceDiscriminant(reference, expr)) { return declaredType; @@ -36381,17 +42013,17 @@ var ts; return type; } function isTypePresencePossible(type, propName, assumeTrue) { - if (getIndexInfoOfType(type, 0)) { + if (getIndexInfoOfType(type, 0 /* String */)) { return true; } var prop = getPropertyOfType(type, propName); if (prop) { - return prop.flags & 16777216 ? true : assumeTrue; + return prop.flags & 16777216 /* Optional */ ? true : assumeTrue; } return !assumeTrue; } function narrowByInKeyword(type, literal, assumeTrue) { - if ((type.flags & (262144 | 131072)) || (type.flags & 65536 && type.isThisType)) { + if ((type.flags & (262144 /* Union */ | 131072 /* Object */)) || (type.flags & 65536 /* TypeParameter */ && type.isThisType)) { var propName_1 = ts.escapeLeadingUnderscores(literal.text); return filterType(type, function (t) { return isTypePresencePossible(t, propName_1, assumeTrue); }); } @@ -36399,19 +42031,19 @@ var ts; } function narrowTypeByBinaryExpression(type, expr, assumeTrue) { switch (expr.operatorToken.kind) { - case 58: + case 58 /* EqualsToken */: return narrowTypeByTruthiness(type, expr.left, assumeTrue); - case 32: - case 33: - case 34: - case 35: + case 32 /* EqualsEqualsToken */: + case 33 /* ExclamationEqualsToken */: + case 34 /* EqualsEqualsEqualsToken */: + case 35 /* ExclamationEqualsEqualsToken */: var operator_1 = expr.operatorToken.kind; var left_1 = getReferenceCandidate(expr.left); var right_1 = getReferenceCandidate(expr.right); - if (left_1.kind === 195 && ts.isStringLiteralLike(right_1)) { + if (left_1.kind === 195 /* TypeOfExpression */ && ts.isStringLiteralLike(right_1)) { return narrowTypeByTypeof(type, left_1, operator_1, right_1, assumeTrue); } - if (right_1.kind === 195 && ts.isStringLiteralLike(left_1)) { + if (right_1.kind === 195 /* TypeOfExpression */ && ts.isStringLiteralLike(left_1)) { return narrowTypeByTypeof(type, right_1, operator_1, left_1, assumeTrue); } if (isMatchingReference(reference, left_1)) { @@ -36430,45 +42062,45 @@ var ts; return declaredType; } break; - case 93: + case 93 /* InstanceOfKeyword */: return narrowTypeByInstanceof(type, expr, assumeTrue); - case 92: + case 92 /* InKeyword */: var target = getReferenceCandidate(expr.right); if (ts.isStringLiteralLike(expr.left) && isMatchingReference(reference, target)) { return narrowByInKeyword(type, expr.left, assumeTrue); } break; - case 26: + case 26 /* CommaToken */: return narrowType(type, expr.right, assumeTrue); } return type; } function narrowTypeByEquality(type, operator, value, assumeTrue) { - if (type.flags & 1) { + if (type.flags & 1 /* Any */) { return type; } - if (operator === 33 || operator === 35) { + if (operator === 33 /* ExclamationEqualsToken */ || operator === 35 /* ExclamationEqualsEqualsToken */) { assumeTrue = !assumeTrue; } var valueType = getTypeOfExpression(value); - if (valueType.flags & 24576) { + if (valueType.flags & 24576 /* Nullable */) { if (!strictNullChecks) { return type; } - var doubleEquals = operator === 32 || operator === 33; + var doubleEquals = operator === 32 /* EqualsEqualsToken */ || operator === 33 /* ExclamationEqualsToken */; var facts = doubleEquals ? - assumeTrue ? 65536 : 524288 : - valueType.flags & 16384 ? - assumeTrue ? 32768 : 262144 : - assumeTrue ? 16384 : 131072; + assumeTrue ? 65536 /* EQUndefinedOrNull */ : 524288 /* NEUndefinedOrNull */ : + valueType.flags & 16384 /* Null */ ? + assumeTrue ? 32768 /* EQNull */ : 262144 /* NENull */ : + assumeTrue ? 16384 /* EQUndefined */ : 131072 /* NEUndefined */; return getTypeWithFacts(type, facts); } - if (type.flags & 16909315) { + if (type.flags & 16909315 /* NotUnionOrUnit */) { return type; } if (assumeTrue) { var narrowedType = filterType(type, function (t) { return areTypesComparable(t, valueType); }); - return narrowedType.flags & 32768 ? type : replacePrimitivesWithLiterals(narrowedType, valueType); + return narrowedType.flags & 32768 /* Never */ ? type : replacePrimitivesWithLiterals(narrowedType, valueType); } if (isUnitType(valueType)) { var regularType_1 = getRegularTypeOfLiteralType(valueType); @@ -36477,26 +42109,32 @@ var ts; return type; } function narrowTypeByTypeof(type, typeOfExpr, operator, literal, assumeTrue) { + // We have '==', '!=', '====', or !==' operator with 'typeof xxx' and string literal operands var target = getReferenceCandidate(typeOfExpr.expression); if (!isMatchingReference(reference, target)) { + // For a reference of the form 'x.y', a 'typeof x === ...' type guard resets the + // narrowed type of 'y' to its declared type. if (containsMatchingReference(reference, target)) { return declaredType; } return type; } - if (operator === 33 || operator === 35) { + if (operator === 33 /* ExclamationEqualsToken */ || operator === 35 /* ExclamationEqualsEqualsToken */) { assumeTrue = !assumeTrue; } - if (type.flags & 1 && literal.text === "function") { + if (type.flags & 1 /* Any */ && literal.text === "function") { return type; } - if (assumeTrue && !(type.flags & 262144)) { + if (assumeTrue && !(type.flags & 262144 /* Union */)) { + // We narrow a non-union type to an exact primitive type if the non-union type + // is a supertype of that primitive type. For example, type 'any' can be narrowed + // to one of the primitive types. var targetType = literal.text === "function" ? globalFunctionType : typeofTypesByName.get(literal.text); if (targetType) { if (isTypeSubtypeOf(targetType, type)) { return targetType; } - if (type.flags & 15794176) { + if (type.flags & 15794176 /* Instantiable */) { var constraint = getBaseConstraintOfType(type) || anyType; if (isTypeSubtypeOf(targetType, constraint)) { return getIntersectionType([type, targetType]); @@ -36505,11 +42143,12 @@ var ts; } } var facts = assumeTrue ? - typeofEQFacts.get(literal.text) || 64 : - typeofNEFacts.get(literal.text) || 8192; + typeofEQFacts.get(literal.text) || 64 /* TypeofEQHostObject */ : + typeofNEFacts.get(literal.text) || 8192 /* TypeofNEHostObject */; return getTypeWithFacts(type, facts); } function narrowTypeBySwitchOnDiscriminant(type, switchStatement, clauseStart, clauseEnd) { + // We only narrow if all case expressions specify values with unit types var switchTypes = getSwitchClauseTypes(switchStatement); if (!switchTypes.length) { return type; @@ -36517,22 +42156,25 @@ var ts; var clauseTypes = switchTypes.slice(clauseStart, clauseEnd); var hasDefaultClause = clauseStart === clauseEnd || ts.contains(clauseTypes, neverType); var discriminantType = getUnionType(clauseTypes); - var caseType = discriminantType.flags & 32768 ? neverType : + var caseType = discriminantType.flags & 32768 /* Never */ ? neverType : replacePrimitivesWithLiterals(filterType(type, function (t) { return areTypesComparable(discriminantType, t); }), discriminantType); if (!hasDefaultClause) { return caseType; } var defaultType = filterType(type, function (t) { return !(isUnitType(t) && ts.contains(switchTypes, getRegularTypeOfLiteralType(t))); }); - return caseType.flags & 32768 ? defaultType : getUnionType([caseType, defaultType]); + return caseType.flags & 32768 /* Never */ ? defaultType : getUnionType([caseType, defaultType]); } function narrowTypeByInstanceof(type, expr, assumeTrue) { var left = getReferenceCandidate(expr.left); if (!isMatchingReference(reference, left)) { + // For a reference of the form 'x.y', an 'x instanceof T' type guard resets the + // narrowed type of 'y' to its declared type. if (containsMatchingReference(reference, left)) { return declaredType; } return type; } + // Check that right operand is a function type with a prototype property var rightType = getTypeOfExpression(expr.right); if (!isTypeSubtypeOf(rightType, globalFunctionType)) { return type; @@ -36540,21 +42182,24 @@ var ts; var targetType; var prototypeProperty = getPropertyOfType(rightType, "prototype"); if (prototypeProperty) { + // Target type is type of the prototype property var prototypePropertyType = getTypeOfSymbol(prototypeProperty); if (!isTypeAny(prototypePropertyType)) { targetType = prototypePropertyType; } } + // Don't narrow from 'any' if the target type is exactly 'Object' or 'Function' if (isTypeAny(type) && (targetType === globalObjectType || targetType === globalFunctionType)) { return type; } if (!targetType) { + // Target type is type of construct signature var constructSignatures = void 0; - if (ts.getObjectFlags(rightType) & 2) { + if (ts.getObjectFlags(rightType) & 2 /* Interface */) { constructSignatures = resolveDeclaredMembers(rightType).declaredConstructSignatures; } - else if (ts.getObjectFlags(rightType) & 16) { - constructSignatures = getSignaturesOfType(rightType, 1); + else if (ts.getObjectFlags(rightType) & 16 /* Anonymous */) { + constructSignatures = getSignaturesOfType(rightType, 1 /* Construct */); } if (constructSignatures && constructSignatures.length) { targetType = getUnionType(ts.map(constructSignatures, function (signature) { return getReturnTypeOfSignature(getErasedSignature(signature)); })); @@ -36569,12 +42214,19 @@ var ts; if (!assumeTrue) { return filterType(type, function (t) { return !isRelated(t, candidate); }); } - if (type.flags & 262144) { + // If the current type is a union type, remove all constituents that couldn't be instances of + // the candidate type. If one or more constituents remain, return a union of those. + if (type.flags & 262144 /* Union */) { var assignableType = filterType(type, function (t) { return isRelated(t, candidate); }); - if (!(assignableType.flags & 32768)) { + if (!(assignableType.flags & 32768 /* Never */)) { return assignableType; } } + // If the candidate type is a subtype of the target type, narrow to the candidate type. + // Otherwise, if the target type is assignable to the candidate type, keep the target type. + // Otherwise, if the candidate type is assignable to the target type, narrow to the candidate + // type. Otherwise, the types are completely unrelated, so narrow to an intersection of the + // two types. return isTypeSubtypeOf(candidate, type) ? candidate : isTypeAssignableTo(type, candidate) ? type : isTypeAssignableTo(candidate, type) ? candidate : @@ -36589,6 +42241,7 @@ var ts; if (!predicate) { return type; } + // Don't narrow from 'any' if the predicate type is exactly 'Object' or 'Function' if (isTypeAny(type) && (predicate.type === globalObjectType || predicate.type === globalFunctionType)) { return type; } @@ -36605,7 +42258,7 @@ var ts; } else { var invokedExpression = ts.skipParentheses(callExpression.expression); - if (invokedExpression.kind === 186 || invokedExpression.kind === 185) { + if (invokedExpression.kind === 186 /* ElementAccessExpression */ || invokedExpression.kind === 185 /* PropertyAccessExpression */) { var accessExpression = invokedExpression; var possibleReference = ts.skipParentheses(accessExpression.expression); if (isMatchingReference(reference, possibleReference)) { @@ -36618,21 +42271,23 @@ var ts; } return type; } + // Narrow the given type based on the given expression having the assumed boolean value. The returned type + // will be a subtype or the same type as the argument. function narrowType(type, expr, assumeTrue) { switch (expr.kind) { - case 71: - case 99: - case 97: - case 185: + case 71 /* Identifier */: + case 99 /* ThisKeyword */: + case 97 /* SuperKeyword */: + case 185 /* PropertyAccessExpression */: return narrowTypeByTruthiness(type, expr, assumeTrue); - case 187: + case 187 /* CallExpression */: return narrowTypeByTypePredicate(type, expr, assumeTrue); - case 191: + case 191 /* ParenthesizedExpression */: return narrowType(type, expr.expression, assumeTrue); - case 200: + case 200 /* BinaryExpression */: return narrowTypeByBinaryExpression(type, expr, assumeTrue); - case 198: - if (expr.operator === 51) { + case 198 /* PrefixUnaryExpression */: + if (expr.operator === 51 /* ExclamationToken */) { return narrowType(type, expr.operand, !assumeTrue); } break; @@ -36642,7 +42297,11 @@ var ts; } function getTypeOfSymbolAtLocation(symbol, location) { symbol = symbol.exportSymbol || symbol; - if (location.kind === 71) { + // If we have an identifier or a property access at the given location, if the location is + // an dotted name expression, and if the location is not an assignment target, obtain the type + // of the expression (which will reflect control flow analysis). If the expression indeed + // resolved to the given symbol, return the narrowed type. + if (location.kind === 71 /* Identifier */) { if (ts.isRightSideOfQualifiedNameOrPropertyAccess(location)) { location = location.parent; } @@ -36653,21 +42312,27 @@ var ts; } } } + // The location isn't a reference to the given symbol, meaning we're being asked + // a hypothetical question of what type the symbol would have if there was a reference + // to it at the given location. Since we have no control flow information for the + // hypothetical reference (control flow information is created and attached by the + // binder), we simply return the declared type of the symbol. return getTypeOfSymbol(symbol); } function getControlFlowContainer(node) { return ts.findAncestor(node.parent, function (node) { return ts.isFunctionLike(node) && !ts.getImmediatelyInvokedFunctionExpression(node) || - node.kind === 240 || - node.kind === 274 || - node.kind === 152; + node.kind === 240 /* ModuleBlock */ || + node.kind === 274 /* SourceFile */ || + node.kind === 152 /* PropertyDeclaration */; }); } + // Check if a parameter is assigned anywhere within its declaring function. function isParameterAssigned(symbol) { var func = ts.getRootDeclaration(symbol.valueDeclaration).parent; var links = getNodeLinks(func); - if (!(links.flags & 4194304)) { - links.flags |= 4194304; + if (!(links.flags & 4194304 /* AssignmentsMarked */)) { + links.flags |= 4194304 /* AssignmentsMarked */; if (!hasParentWithAssignmentsMarked(func)) { markParameterAssignments(func); } @@ -36675,13 +42340,13 @@ var ts; return symbol.isAssigned || false; } function hasParentWithAssignmentsMarked(node) { - return !!ts.findAncestor(node.parent, function (node) { return ts.isFunctionLike(node) && !!(getNodeLinks(node).flags & 4194304); }); + return !!ts.findAncestor(node.parent, function (node) { return ts.isFunctionLike(node) && !!(getNodeLinks(node).flags & 4194304 /* AssignmentsMarked */); }); } function markParameterAssignments(node) { - if (node.kind === 71) { + if (node.kind === 71 /* Identifier */) { if (ts.isAssignmentTarget(node)) { var symbol = getResolvedSymbol(node); - if (symbol.valueDeclaration && ts.getRootDeclaration(symbol.valueDeclaration).kind === 149) { + if (symbol.valueDeclaration && ts.getRootDeclaration(symbol.valueDeclaration).kind === 149 /* Parameter */) { symbol.isAssigned = true; } } @@ -36691,34 +42356,39 @@ var ts; } } function isConstVariable(symbol) { - return symbol.flags & 3 && (getDeclarationNodeFlagsFromSymbol(symbol) & 2) !== 0 && getTypeOfSymbol(symbol) !== autoArrayType; + return symbol.flags & 3 /* Variable */ && (getDeclarationNodeFlagsFromSymbol(symbol) & 2 /* Const */) !== 0 && getTypeOfSymbol(symbol) !== autoArrayType; } + /** remove undefined from the annotated type of a parameter when there is an initializer (that doesn't include undefined) */ function removeOptionalityFromDeclaredType(declaredType, declaration) { var annotationIncludesUndefined = strictNullChecks && - declaration.kind === 149 && + declaration.kind === 149 /* Parameter */ && declaration.initializer && - getFalsyFlags(declaredType) & 8192 && - !(getFalsyFlags(checkExpression(declaration.initializer)) & 8192); - return annotationIncludesUndefined ? getTypeWithFacts(declaredType, 131072) : declaredType; + getFalsyFlags(declaredType) & 8192 /* Undefined */ && + !(getFalsyFlags(checkExpression(declaration.initializer)) & 8192 /* Undefined */); + return annotationIncludesUndefined ? getTypeWithFacts(declaredType, 131072 /* NEUndefined */) : declaredType; } function isConstraintPosition(node) { var parent = node.parent; - return parent.kind === 185 || - parent.kind === 187 && parent.expression === node || - parent.kind === 186 && parent.expression === node || - parent.kind === 182 && parent.name === node && !!parent.initializer; + return parent.kind === 185 /* PropertyAccessExpression */ || + parent.kind === 187 /* CallExpression */ && parent.expression === node || + parent.kind === 186 /* ElementAccessExpression */ && parent.expression === node || + parent.kind === 182 /* BindingElement */ && parent.name === node && !!parent.initializer; } function typeHasNullableConstraint(type) { - return type.flags & 14745600 && maybeTypeOfKind(getBaseConstraintOfType(type) || emptyObjectType, 24576); + return type.flags & 14745600 /* InstantiableNonPrimitive */ && maybeTypeOfKind(getBaseConstraintOfType(type) || emptyObjectType, 24576 /* Nullable */); } function getConstraintForLocation(type, node) { + // When a node is the left hand expression of a property access, element access, or call expression, + // and the type of the node includes type variables with constraints that are nullable, we fetch the + // apparent type of the node *before* performing control flow analysis such that narrowings apply to + // the constraint type. if (type && isConstraintPosition(node) && forEachType(type, typeHasNullableConstraint)) { return mapType(getWidenedType(type), getBaseConstraintOrType); } return type; } function markAliasReferenced(symbol, location) { - if (isNonLocalAlias(symbol, 67216319) && !isInTypeQuery(location) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(symbol))) { + if (isNonLocalAlias(symbol, /*excludes*/ 67216319 /* Value */) && !isInTypeQuery(location) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(symbol))) { markAliasSymbolAsReferenced(symbol); } } @@ -36727,48 +42397,62 @@ var ts; if (symbol === unknownSymbol) { return errorType; } + // As noted in ECMAScript 6 language spec, arrow functions never have an arguments objects. + // Although in down-level emit of arrow function, we emit it using function expression which means that + // arguments objects will be bound to the inner object; emitting arrow function natively in ES6, arguments objects + // will be bound to non-arrow function that contain this arrow function. This results in inconsistent behavior. + // To avoid that we will give an error to users if they use arguments objects in arrow function so that they + // can explicitly bound arguments objects if (symbol === argumentsSymbol) { var container = ts.getContainingFunction(node); - if (languageVersion < 2) { - if (container.kind === 193) { + if (languageVersion < 2 /* ES2015 */) { + if (container.kind === 193 /* ArrowFunction */) { error(node, ts.Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression); } - else if (ts.hasModifier(container, 256)) { + else if (ts.hasModifier(container, 256 /* Async */)) { error(node, ts.Diagnostics.The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_using_a_standard_function_or_method); } } - getNodeLinks(container).flags |= 8192; + getNodeLinks(container).flags |= 8192 /* CaptureArguments */; return getTypeOfSymbol(symbol); } + // We should only mark aliases as referenced if there isn't a local value declaration + // for the symbol. Also, don't mark any property access expression LHS - checkPropertyAccessExpression will handle that if (!(node.parent && ts.isPropertyAccessExpression(node.parent) && node.parent.expression === node)) { markAliasReferenced(symbol, node); } var localOrExportSymbol = getExportSymbolOfValueSymbolIfExported(symbol); var declaration = localOrExportSymbol.valueDeclaration; - if (localOrExportSymbol.flags & 32) { - if (declaration.kind === 235 + if (localOrExportSymbol.flags & 32 /* Class */) { + // Due to the emit for class decorators, any reference to the class from inside of the class body + // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind + // behavior of class names in ES6. + if (declaration.kind === 235 /* ClassDeclaration */ && ts.nodeIsDecorated(declaration)) { var container = ts.getContainingClass(node); while (container !== undefined) { if (container === declaration && container.name !== node) { - getNodeLinks(declaration).flags |= 8388608; - getNodeLinks(node).flags |= 16777216; + getNodeLinks(declaration).flags |= 8388608 /* ClassWithConstructorReference */; + getNodeLinks(node).flags |= 16777216 /* ConstructorReferenceInClass */; break; } container = ts.getContainingClass(container); } } - else if (declaration.kind === 205) { - var container = ts.getThisContainer(node, false); - while (container.kind !== 274) { + else if (declaration.kind === 205 /* ClassExpression */) { + // When we emit a class expression with static members that contain a reference + // to the constructor in the initializer, we will need to substitute that + // binding with an alias as the class name is not in scope. + var container = ts.getThisContainer(node, /*includeArrowFunctions*/ false); + while (container.kind !== 274 /* SourceFile */) { if (container.parent === declaration) { - if (container.kind === 152 && ts.hasModifier(container, 32)) { - getNodeLinks(declaration).flags |= 8388608; - getNodeLinks(node).flags |= 16777216; + if (container.kind === 152 /* PropertyDeclaration */ && ts.hasModifier(container, 32 /* Static */)) { + getNodeLinks(declaration).flags |= 8388608 /* ClassWithConstructorReference */; + getNodeLinks(node).flags |= 16777216 /* ConstructorReferenceInClass */; } break; } - container = ts.getThisContainer(container, false); + container = ts.getThisContainer(container, /*includeArrowFunctions*/ false); } } } @@ -36776,8 +42460,8 @@ var ts; var type = getConstraintForLocation(getTypeOfSymbol(localOrExportSymbol), node); var assignmentKind = ts.getAssignmentTargetKind(node); if (assignmentKind) { - if (!(localOrExportSymbol.flags & 3) && - !(ts.isInJavaScriptFile(node) && localOrExportSymbol.flags & 512)) { + if (!(localOrExportSymbol.flags & 3 /* Variable */) && + !(ts.isInJavaScriptFile(node) && localOrExportSymbol.flags & 512 /* ValueModule */)) { error(node, ts.Diagnostics.Cannot_assign_to_0_because_it_is_not_a_variable, symbolToString(symbol)); return errorType; } @@ -36786,9 +42470,11 @@ var ts; return errorType; } } - var isAlias = localOrExportSymbol.flags & 2097152; - if (localOrExportSymbol.flags & 3) { - if (assignmentKind === 1) { + var isAlias = localOrExportSymbol.flags & 2097152 /* Alias */; + // We only narrow variables and parameters occurring in a non-assignment position. For all other + // entities we simply return the declared type. + if (localOrExportSymbol.flags & 3 /* Variable */) { + if (assignmentKind === 1 /* Definite */) { return type; } } @@ -36801,26 +42487,38 @@ var ts; if (!declaration) { return type; } - var isParameter = ts.getRootDeclaration(declaration).kind === 149; + // The declaration container is the innermost function that encloses the declaration of the variable + // or parameter. The flow container is the innermost function starting with which we analyze the control + // flow graph to determine the control flow based type. + var isParameter = ts.getRootDeclaration(declaration).kind === 149 /* Parameter */; var declarationContainer = getControlFlowContainer(declaration); var flowContainer = getControlFlowContainer(node); var isOuterVariable = flowContainer !== declarationContainer; var isSpreadDestructuringAsignmentTarget = node.parent && node.parent.parent && ts.isSpreadAssignment(node.parent) && isDestructuringAssignmentTarget(node.parent.parent); - while (flowContainer !== declarationContainer && (flowContainer.kind === 192 || - flowContainer.kind === 193 || ts.isObjectLiteralOrClassExpressionMethod(flowContainer)) && + // When the control flow originates in a function expression or arrow function and we are referencing + // a const variable or parameter from an outer function, we extend the origin of the control flow + // analysis to include the immediately enclosing function. + while (flowContainer !== declarationContainer && (flowContainer.kind === 192 /* FunctionExpression */ || + flowContainer.kind === 193 /* ArrowFunction */ || ts.isObjectLiteralOrClassExpressionMethod(flowContainer)) && (isConstVariable(localOrExportSymbol) || isParameter && !isParameterAssigned(localOrExportSymbol))) { flowContainer = getControlFlowContainer(flowContainer); } + // We only look for uninitialized variables in strict null checking mode, and only when we can analyze + // the entire control flow graph from the variable's declaration (i.e. when the flow container and + // declaration container are the same). var assumeInitialized = isParameter || isAlias || isOuterVariable || isSpreadDestructuringAsignmentTarget || - type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & 3) !== 0 || - isInTypeQuery(node) || node.parent.kind === 252) || - node.parent.kind === 209 || - declaration.kind === 232 && declaration.exclamationToken || - declaration.flags & 4194304; + type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & 3 /* AnyOrUnknown */) !== 0 || + isInTypeQuery(node) || node.parent.kind === 252 /* ExportSpecifier */) || + node.parent.kind === 209 /* NonNullExpression */ || + declaration.kind === 232 /* VariableDeclaration */ && declaration.exclamationToken || + declaration.flags & 4194304 /* Ambient */; var initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, declaration) : type) : type === autoType || type === autoArrayType ? undefinedType : getOptionalType(type); var flowType = getFlowTypeOfReference(node, type, initialType, flowContainer, !assumeInitialized); + // A variable is considered uninitialized when it is possible to analyze the entire control flow graph + // from declaration to use, and when the variable's declared type doesn't include undefined but the + // control flow based type does include undefined. if (type === autoType || type === autoArrayType) { if (flowType === autoType || flowType === autoArrayType) { if (noImplicitAny) { @@ -36830,8 +42528,9 @@ var ts; return convertAutoToAny(flowType); } } - else if (!assumeInitialized && !(getFalsyFlags(type) & 8192) && getFalsyFlags(flowType) & 8192) { + else if (!assumeInitialized && !(getFalsyFlags(type) & 8192 /* Undefined */) && getFalsyFlags(flowType) & 8192 /* Undefined */) { error(node, ts.Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol)); + // Return the declared type to reduce follow-on errors return type; } return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType; @@ -36840,17 +42539,21 @@ var ts; return !!ts.findAncestor(node, function (n) { return n === threshold ? "quit" : ts.isFunctionLike(n); }); } function checkNestedBlockScopedBinding(node, symbol) { - if (languageVersion >= 2 || - (symbol.flags & (2 | 32)) === 0 || - symbol.valueDeclaration.parent.kind === 269) { + if (languageVersion >= 2 /* ES2015 */ || + (symbol.flags & (2 /* BlockScopedVariable */ | 32 /* Class */)) === 0 || + symbol.valueDeclaration.parent.kind === 269 /* CatchClause */) { return; } + // 1. walk from the use site up to the declaration and check + // if there is anything function like between declaration and use-site (is binding/class is captured in function). + // 2. walk from the declaration up to the boundary of lexical environment and check + // if there is an iteration statement in between declaration and boundary (is binding/class declared inside iteration statement) var container = ts.getEnclosingBlockScopeContainer(symbol.valueDeclaration); var usedInFunction = isInsideFunction(node.parent, container); var current = container; var containedInIterationStatement = false; while (current && !ts.nodeStartsNewLexicalEnvironment(current)) { - if (ts.isIterationStatement(current, false)) { + if (ts.isIterationStatement(current, /*lookInLabeledStatements*/ false)) { containedInIterationStatement = true; break; } @@ -36858,45 +42561,53 @@ var ts; } if (containedInIterationStatement) { if (usedInFunction) { - getNodeLinks(current).flags |= 65536; + // mark iteration statement as containing block-scoped binding captured in some function + getNodeLinks(current).flags |= 65536 /* LoopWithCapturedBlockScopedBinding */; } - if (container.kind === 220 && - ts.getAncestor(symbol.valueDeclaration, 233).parent === container && + // mark variables that are declared in loop initializer and reassigned inside the body of ForStatement. + // if body of ForStatement will be converted to function then we'll need a extra machinery to propagate reassigned values back. + if (container.kind === 220 /* ForStatement */ && + ts.getAncestor(symbol.valueDeclaration, 233 /* VariableDeclarationList */).parent === container && isAssignedInBodyOfForStatement(node, container)) { - getNodeLinks(symbol.valueDeclaration).flags |= 2097152; + getNodeLinks(symbol.valueDeclaration).flags |= 2097152 /* NeedsLoopOutParameter */; } - getNodeLinks(symbol.valueDeclaration).flags |= 262144; + // set 'declared inside loop' bit on the block-scoped binding + getNodeLinks(symbol.valueDeclaration).flags |= 262144 /* BlockScopedBindingInLoop */; } if (usedInFunction) { - getNodeLinks(symbol.valueDeclaration).flags |= 131072; + getNodeLinks(symbol.valueDeclaration).flags |= 131072 /* CapturedBlockScopedBinding */; } } function isAssignedInBodyOfForStatement(node, container) { + // skip parenthesized nodes var current = node; - while (current.parent.kind === 191) { + while (current.parent.kind === 191 /* ParenthesizedExpression */) { current = current.parent; } + // check if node is used as LHS in some assignment expression var isAssigned = false; if (ts.isAssignmentTarget(current)) { isAssigned = true; } - else if ((current.parent.kind === 198 || current.parent.kind === 199)) { + else if ((current.parent.kind === 198 /* PrefixUnaryExpression */ || current.parent.kind === 199 /* PostfixUnaryExpression */)) { var expr = current.parent; - isAssigned = expr.operator === 43 || expr.operator === 44; + isAssigned = expr.operator === 43 /* PlusPlusToken */ || expr.operator === 44 /* MinusMinusToken */; } if (!isAssigned) { return false; } + // at this point we know that node is the target of assignment + // now check that modification happens inside the statement part of the ForStatement return !!ts.findAncestor(current, function (n) { return n === container ? "quit" : n === container.statement; }); } function captureLexicalThis(node, container) { - getNodeLinks(node).flags |= 2; - if (container.kind === 152 || container.kind === 155) { + getNodeLinks(node).flags |= 2 /* LexicalThis */; + if (container.kind === 152 /* PropertyDeclaration */ || container.kind === 155 /* Constructor */) { var classNode = container.parent; - getNodeLinks(classNode).flags |= 4; + getNodeLinks(classNode).flags |= 4 /* CaptureThis */; } else { - getNodeLinks(container).flags |= 4; + getNodeLinks(container).flags |= 4 /* CaptureThis */; } } function findFirstSuperCall(n) { @@ -36908,14 +42619,26 @@ var ts; } return ts.forEachChild(n, findFirstSuperCall); } + /** + * Return a cached result if super-statement is already found. + * Otherwise, find a super statement in a given constructor function and cache the result in the node-links of the constructor + * + * @param constructor constructor-function to look for super statement + */ function getSuperCallInConstructor(constructor) { var links = getNodeLinks(constructor); + // Only trying to find super-call if we haven't yet tried to find one. Once we try, we will record the result if (links.hasSuperCall === undefined) { links.superCall = findFirstSuperCall(constructor.body); links.hasSuperCall = links.superCall ? true : false; } return links.superCall; } + /** + * Check if the given class-declaration extends null then return true. + * Otherwise, return false + * @param classDecl a class declaration to check if it extends null + */ function classDeclarationExtendsNull(classDecl) { var classSymbol = getSymbolOfNode(classDecl); var classInstanceType = getDeclaredTypeOfSymbol(classSymbol); @@ -36925,42 +42648,60 @@ var ts; function checkThisBeforeSuper(node, container, diagnosticMessage) { var containingClassDecl = container.parent; var baseTypeNode = ts.getClassExtendsHeritageClauseElement(containingClassDecl); + // If a containing class does not have extends clause or the class extends null + // skip checking whether super statement is called before "this" accessing. if (baseTypeNode && !classDeclarationExtendsNull(containingClassDecl)) { var superCall = getSuperCallInConstructor(container); + // We should give an error in the following cases: + // - No super-call + // - "this" is accessing before super-call. + // i.e super(this) + // this.x; super(); + // We want to make sure that super-call is done before accessing "this" so that + // "this" is not accessed as a parameter of the super-call. if (!superCall || superCall.end > node.pos) { + // In ES6, super inside constructor of class-declaration has to precede "this" accessing error(node, diagnosticMessage); } } } function checkThisExpression(node) { - var container = ts.getThisContainer(node, true); + // Stop at the first arrow function so that we can + // tell whether 'this' needs to be captured. + var container = ts.getThisContainer(node, /* includeArrowFunctions */ true); var needToCaptureLexicalThis = false; - if (container.kind === 155) { + if (container.kind === 155 /* Constructor */) { checkThisBeforeSuper(node, container, ts.Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class); } - if (container.kind === 193) { - container = ts.getThisContainer(container, false); - needToCaptureLexicalThis = (languageVersion < 2); + // Now skip arrow functions to get the "real" owner of 'this'. + if (container.kind === 193 /* ArrowFunction */) { + container = ts.getThisContainer(container, /* includeArrowFunctions */ false); + // When targeting es6, arrow function lexically bind "this" so we do not need to do the work of binding "this" in emitted code + needToCaptureLexicalThis = (languageVersion < 2 /* ES2015 */); } switch (container.kind) { - case 239: + case 239 /* ModuleDeclaration */: error(node, ts.Diagnostics.this_cannot_be_referenced_in_a_module_or_namespace_body); + // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks break; - case 238: + case 238 /* EnumDeclaration */: error(node, ts.Diagnostics.this_cannot_be_referenced_in_current_location); + // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks break; - case 155: + case 155 /* Constructor */: if (isInConstructorArgumentInitializer(node, container)) { error(node, ts.Diagnostics.this_cannot_be_referenced_in_constructor_arguments); + // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks } break; - case 152: - case 151: - if (ts.hasModifier(container, 32)) { + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + if (ts.hasModifier(container, 32 /* Static */)) { error(node, ts.Diagnostics.this_cannot_be_referenced_in_a_static_property_initializer); + // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks } break; - case 147: + case 147 /* ComputedPropertyName */: error(node, ts.Diagnostics.this_cannot_be_referenced_in_a_computed_property_name); break; } @@ -36969,23 +42710,28 @@ var ts; } var type = tryGetThisTypeAt(node, container); if (!type && noImplicitThis) { + // With noImplicitThis, functions may not reference 'this' if it has type 'any' error(node, ts.Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation); } return type || anyType; } function tryGetThisTypeAt(node, container) { - if (container === void 0) { container = ts.getThisContainer(node, false); } + if (container === void 0) { container = ts.getThisContainer(node, /*includeArrowFunctions*/ false); } if (ts.isFunctionLike(container) && (!isInParameterInitializerBeforeContainingFunction(node) || ts.getThisParameter(container))) { - if (container.kind === 192 && - container.parent.kind === 200 && - ts.getSpecialPropertyAssignmentKind(container.parent) === 3) { - var className = container.parent - .left - .expression - .expression; + // Note: a parameter initializer should refer to class-this unless function-this is explicitly annotated. + // If this is a function in a JS file, it might be a class method. Check if it's the RHS + // of a x.prototype.y = function [name]() { .... } + if (container.kind === 192 /* FunctionExpression */ && + container.parent.kind === 200 /* BinaryExpression */ && + ts.getSpecialPropertyAssignmentKind(container.parent) === 3 /* PrototypeProperty */) { + // Get the 'x' of 'x.prototype.y = f' (here, 'f' is 'container') + var className = container.parent // x.prototype.y = f + .left // x.prototype.y + .expression // x.prototype + .expression; // x var classSymbol = checkExpression(className).symbol; - if (classSymbol && classSymbol.members && (classSymbol.flags & 16)) { + if (classSymbol && classSymbol.members && (classSymbol.flags & 16 /* Function */)) { return getFlowTypeOfReference(node, getInferredClassType(classSymbol)); } } @@ -36996,7 +42742,7 @@ var ts; } if (ts.isClassLike(container.parent)) { var symbol = getSymbolOfNode(container.parent); - var type = ts.hasModifier(container, 32) ? getTypeOfSymbol(symbol) : getDeclaredTypeOfSymbol(symbol).thisType; + var type = ts.hasModifier(container, 32 /* Static */) ? getTypeOfSymbol(symbol) : getDeclaredTypeOfSymbol(symbol).thisType; return getFlowTypeOfReference(node, type); } if (ts.isInJavaScriptFile(node)) { @@ -37008,7 +42754,7 @@ var ts; } function getTypeForThisExpressionFromJSDoc(node) { var jsdocType = ts.getJSDocType(node); - if (jsdocType && jsdocType.kind === 284) { + if (jsdocType && jsdocType.kind === 284 /* JSDocFunctionType */) { var jsDocFunctionType = jsdocType; if (jsDocFunctionType.parameters.length > 0 && jsDocFunctionType.parameters[0].name && @@ -37022,29 +42768,35 @@ var ts; } } function isInConstructorArgumentInitializer(node, constructorDecl) { - return !!ts.findAncestor(node, function (n) { return n === constructorDecl ? "quit" : n.kind === 149; }); + return !!ts.findAncestor(node, function (n) { return n === constructorDecl ? "quit" : n.kind === 149 /* Parameter */; }); } function checkSuperExpression(node) { - var isCallExpression = node.parent.kind === 187 && node.parent.expression === node; - var container = ts.getSuperContainer(node, true); + var isCallExpression = node.parent.kind === 187 /* CallExpression */ && node.parent.expression === node; + var container = ts.getSuperContainer(node, /*stopOnFunctions*/ true); var needToCaptureLexicalThis = false; + // adjust the container reference in case if super is used inside arrow functions with arbitrarily deep nesting if (!isCallExpression) { - while (container && container.kind === 193) { - container = ts.getSuperContainer(container, true); - needToCaptureLexicalThis = languageVersion < 2; + while (container && container.kind === 193 /* ArrowFunction */) { + container = ts.getSuperContainer(container, /*stopOnFunctions*/ true); + needToCaptureLexicalThis = languageVersion < 2 /* ES2015 */; } } var canUseSuperExpression = isLegalUsageOfSuperExpression(container); var nodeCheckFlag = 0; if (!canUseSuperExpression) { - var current = ts.findAncestor(node, function (n) { return n === container ? "quit" : n.kind === 147; }); - if (current && current.kind === 147) { + // issue more specific error if super is used in computed property name + // class A { foo() { return "1" }} + // class B { + // [super.foo()]() {} + // } + var current = ts.findAncestor(node, function (n) { return n === container ? "quit" : n.kind === 147 /* ComputedPropertyName */; }); + if (current && current.kind === 147 /* ComputedPropertyName */) { error(node, ts.Diagnostics.super_cannot_be_referenced_in_a_computed_property_name); } else if (isCallExpression) { error(node, ts.Diagnostics.Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors); } - else if (!container || !container.parent || !(ts.isClassLike(container.parent) || container.parent.kind === 184)) { + else if (!container || !container.parent || !(ts.isClassLike(container.parent) || container.parent.kind === 184 /* ObjectLiteralExpression */)) { error(node, ts.Diagnostics.super_can_only_be_referenced_in_members_of_derived_classes_or_object_literal_expressions); } else { @@ -37052,36 +42804,97 @@ var ts; } return errorType; } - if (!isCallExpression && container.kind === 155) { + if (!isCallExpression && container.kind === 155 /* Constructor */) { checkThisBeforeSuper(node, container, ts.Diagnostics.super_must_be_called_before_accessing_a_property_of_super_in_the_constructor_of_a_derived_class); } - if (ts.hasModifier(container, 32) || isCallExpression) { - nodeCheckFlag = 512; + if (ts.hasModifier(container, 32 /* Static */) || isCallExpression) { + nodeCheckFlag = 512 /* SuperStatic */; } else { - nodeCheckFlag = 256; + nodeCheckFlag = 256 /* SuperInstance */; } getNodeLinks(node).flags |= nodeCheckFlag; - if (container.kind === 154 && ts.hasModifier(container, 256)) { + // Due to how we emit async functions, we need to specialize the emit for an async method that contains a `super` reference. + // This is due to the fact that we emit the body of an async function inside of a generator function. As generator + // functions cannot reference `super`, we emit a helper inside of the method body, but outside of the generator. This helper + // uses an arrow function, which is permitted to reference `super`. + // + // There are two primary ways we can access `super` from within an async method. The first is getting the value of a property + // or indexed access on super, either as part of a right-hand-side expression or call expression. The second is when setting the value + // of a property or indexed access, either as part of an assignment expression or destructuring assignment. + // + // The simplest case is reading a value, in which case we will emit something like the following: + // + // // ts + // ... + // async asyncMethod() { + // let x = await super.asyncMethod(); + // return x; + // } + // ... + // + // // js + // ... + // asyncMethod() { + // const _super = name => super[name]; + // return __awaiter(this, arguments, Promise, function *() { + // let x = yield _super("asyncMethod").call(this); + // return x; + // }); + // } + // ... + // + // The more complex case is when we wish to assign a value, especially as part of a destructuring assignment. As both cases + // are legal in ES6, but also likely less frequent, we emit the same more complex helper for both scenarios: + // + // // ts + // ... + // async asyncMethod(ar: Promise) { + // [super.a, super.b] = await ar; + // } + // ... + // + // // js + // ... + // asyncMethod(ar) { + // const _super = (function (geti, seti) { + // const cache = Object.create(null); + // return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } }); + // })(name => super[name], (name, value) => super[name] = value); + // return __awaiter(this, arguments, Promise, function *() { + // [_super("a").value, _super("b").value] = yield ar; + // }); + // } + // ... + // + // This helper creates an object with a "value" property that wraps the `super` property or indexed access for both get and set. + // This is required for destructuring assignments, as a call expression cannot be used as the target of a destructuring assignment + // while a property access can. + if (container.kind === 154 /* MethodDeclaration */ && ts.hasModifier(container, 256 /* Async */)) { if (ts.isSuperProperty(node.parent) && ts.isAssignmentTarget(node.parent)) { - getNodeLinks(container).flags |= 4096; + getNodeLinks(container).flags |= 4096 /* AsyncMethodWithSuperBinding */; } else { - getNodeLinks(container).flags |= 2048; + getNodeLinks(container).flags |= 2048 /* AsyncMethodWithSuper */; } } 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 (container.parent.kind === 184) { - if (languageVersion < 2) { + if (container.parent.kind === 184 /* ObjectLiteralExpression */) { + if (languageVersion < 2 /* ES2015 */) { error(node, ts.Diagnostics.super_is_only_allowed_in_members_of_object_literal_expressions_when_option_target_is_ES2015_or_higher); return errorType; } else { + // for object literal assume that type of 'super' is 'any' return anyType; } } + // at this point the only legal case for parent is ClassLikeDeclaration var classLikeDeclaration = container.parent; if (!ts.getClassExtendsHeritageClauseElement(classLikeDeclaration)) { error(node, ts.Diagnostics.super_can_only_be_referenced_in_a_derived_class); @@ -37092,11 +42905,12 @@ var ts; if (!baseClassType) { return errorType; } - if (container.kind === 155 && isInConstructorArgumentInitializer(node, container)) { + if (container.kind === 155 /* Constructor */ && isInConstructorArgumentInitializer(node, container)) { + // issue custom error message for super property access in constructor arguments (to be aligned with old compiler) error(node, ts.Diagnostics.super_cannot_be_referenced_in_constructor_arguments); return errorType; } - return nodeCheckFlag === 512 + return nodeCheckFlag === 512 /* SuperStatic */ ? getBaseConstructorTypeOfClass(classType) : getTypeWithThisArgument(baseClassType, classType.thisType); function isLegalUsageOfSuperExpression(container) { @@ -37104,24 +42918,31 @@ var ts; return false; } if (isCallExpression) { - return container.kind === 155; + // TS 1.0 SPEC (April 2014): 4.8.1 + // Super calls are only permitted in constructors of derived classes + return container.kind === 155 /* Constructor */; } else { - if (ts.isClassLike(container.parent) || container.parent.kind === 184) { - if (ts.hasModifier(container, 32)) { - return container.kind === 154 || - container.kind === 153 || - container.kind === 156 || - container.kind === 157; + // TS 1.0 SPEC (April 2014) + // 'super' property access is allowed + // - In a constructor, instance member function, instance member accessor, or instance member variable initializer where this references a derived class instance + // - In a static member function or static member accessor + // topmost container must be something that is directly nested in the class declaration\object literal expression + if (ts.isClassLike(container.parent) || container.parent.kind === 184 /* ObjectLiteralExpression */) { + if (ts.hasModifier(container, 32 /* Static */)) { + return container.kind === 154 /* MethodDeclaration */ || + container.kind === 153 /* MethodSignature */ || + container.kind === 156 /* GetAccessor */ || + container.kind === 157 /* SetAccessor */; } else { - return container.kind === 154 || - container.kind === 153 || - container.kind === 156 || - container.kind === 157 || - container.kind === 152 || - container.kind === 151 || - container.kind === 155; + return container.kind === 154 /* MethodDeclaration */ || + container.kind === 153 /* MethodSignature */ || + container.kind === 156 /* GetAccessor */ || + container.kind === 157 /* SetAccessor */ || + container.kind === 152 /* PropertyDeclaration */ || + container.kind === 151 /* PropertySignature */ || + container.kind === 155 /* Constructor */; } } } @@ -37129,22 +42950,22 @@ var ts; } } function getContainingObjectLiteral(func) { - return (func.kind === 154 || - func.kind === 156 || - func.kind === 157) && func.parent.kind === 184 ? func.parent : - func.kind === 192 && func.parent.kind === 270 ? func.parent.parent : + return (func.kind === 154 /* MethodDeclaration */ || + func.kind === 156 /* GetAccessor */ || + func.kind === 157 /* SetAccessor */) && func.parent.kind === 184 /* ObjectLiteralExpression */ ? func.parent : + func.kind === 192 /* FunctionExpression */ && func.parent.kind === 270 /* PropertyAssignment */ ? func.parent.parent : undefined; } function getThisTypeArgument(type) { - return ts.getObjectFlags(type) & 4 && type.target === globalThisType ? type.typeArguments[0] : undefined; + return ts.getObjectFlags(type) & 4 /* Reference */ && type.target === globalThisType ? type.typeArguments[0] : undefined; } function getThisTypeFromContextualType(type) { return mapType(type, function (t) { - return t.flags & 524288 ? ts.forEach(t.types, getThisTypeArgument) : getThisTypeArgument(t); + return t.flags & 524288 /* Intersection */ ? ts.forEach(t.types, getThisTypeArgument) : getThisTypeArgument(t); }); } function getContextualThisParameterType(func) { - if (func.kind === 193) { + if (func.kind === 193 /* ArrowFunction */) { return undefined; } if (isContextSensitiveFunctionOrObjectLiteralMethod(func)) { @@ -37160,6 +42981,9 @@ var ts; if (noImplicitThis || inJs) { var containingLiteral = getContainingObjectLiteral(func); if (containingLiteral) { + // We have an object literal method. Check if the containing object literal has a contextual type + // that includes a ThisType. If so, T is the contextual type for 'this'. We continue looking in + // any directly enclosing object literals. var contextualType = getApparentTypeOfContextualType(containingLiteral); var literal = containingLiteral; var type = contextualType; @@ -37168,19 +42992,25 @@ var ts; if (thisType) { return instantiateType(thisType, getContextualMapper(containingLiteral)); } - if (literal.parent.kind !== 270) { + if (literal.parent.kind !== 270 /* PropertyAssignment */) { break; } literal = literal.parent.parent; type = getApparentTypeOfContextualType(literal); } + // There was no contextual ThisType for the containing object literal, so the contextual type + // for 'this' is the non-null form of the contextual type for the containing object literal or + // the type of the object literal itself. return contextualType ? getNonNullableType(contextualType) : checkExpressionCached(containingLiteral); } + // In an assignment of the form 'obj.xxx = function(...)' or 'obj[xxx] = function(...)', the + // contextual type for 'this' is 'obj'. var parent = func.parent; - if (parent.kind === 200 && parent.operatorToken.kind === 58) { + if (parent.kind === 200 /* BinaryExpression */ && parent.operatorToken.kind === 58 /* EqualsToken */) { var target = parent.left; - if (target.kind === 185 || target.kind === 186) { + if (target.kind === 185 /* PropertyAccessExpression */ || target.kind === 186 /* ElementAccessExpression */) { var expression = target.expression; + // Don't contextually type `this` as `exports` in `exports.Point = function(x, y) { this.x = x; this.y = y; }` if (inJs && ts.isIdentifier(expression)) { var sourceFile = ts.getSourceFileOfNode(parent); if (sourceFile.commonJsModuleIndicator && getResolvedSymbol(expression) === sourceFile.symbol) { @@ -37193,6 +43023,7 @@ var ts; } return undefined; } + // Return contextual type of parameter or undefined if no contextual type is available function getContextuallyTypedParameterType(parameter) { var func = parameter.parent; if (!isContextSensitiveFunctionOrObjectLiteralMethod(func)) { @@ -37223,12 +43054,13 @@ var ts; var len = func.parameters.length - (funcHasRestParameters ? 1 : 0); var indexOfParameter = func.parameters.indexOf(parameter); if (ts.getThisParameter(func) !== undefined && !contextualSignature.thisParameter) { - ts.Debug.assert(indexOfParameter !== 0); + ts.Debug.assert(indexOfParameter !== 0); // Otherwise we should not have called `getContextuallyTypedParameterType`. indexOfParameter -= 1; } if (indexOfParameter < len) { return getTypeAtPosition(contextualSignature, indexOfParameter); } + // If last parameter is contextually rest parameter get its type if (funcHasRestParameters && indexOfParameter === (func.parameters.length - 1) && isRestParameterIndex(contextualSignature, func.parameters.length - 1)) { @@ -37236,6 +43068,14 @@ var ts; } } } + // In a variable, parameter or property declaration with a type annotation, + // the contextual type of an initializer expression is the type of the variable, parameter or property. + // Otherwise, in a parameter declaration of a contextually typed function expression, + // the contextual type of an initializer expression is the contextual type of the parameter. + // Otherwise, in a variable or parameter declaration with a binding pattern name, + // the contextual type of an initializer expression is the type implied by the binding pattern. + // Otherwise, in a binding pattern inside a variable or parameter declaration, + // the contextual type of an initializer expression is the type annotation of the containing declaration, if present. function getContextualTypeForInitializerExpression(node) { var declaration = node.parent; if (ts.hasInitializer(declaration) && node === declaration.initializer) { @@ -37243,19 +43083,19 @@ var ts; if (typeNode) { return getTypeFromTypeNode(typeNode); } - if (declaration.kind === 149) { + if (declaration.kind === 149 /* Parameter */) { var type = getContextuallyTypedParameterType(declaration); if (type) { return type; } } if (ts.isBindingPattern(declaration.name)) { - return getTypeFromBindingPattern(declaration.name, true, false); + return getTypeFromBindingPattern(declaration.name, /*includePatternInType*/ true, /*reportErrors*/ false); } if (ts.isBindingPattern(declaration.parent)) { var parentDeclaration = declaration.parent.parent; var name = declaration.propertyName || declaration.name; - if (parentDeclaration.kind !== 182) { + if (parentDeclaration.kind !== 182 /* BindingElement */) { var parentTypeNode = ts.getEffectiveTypeAnnotationNode(parentDeclaration); if (parentTypeNode && !ts.isBindingPattern(name)) { var text = ts.getTextOfPropertyName(name); @@ -37272,13 +43112,13 @@ var ts; var func = ts.getContainingFunction(node); if (func) { var functionFlags = ts.getFunctionFlags(func); - if (functionFlags & 1) { + if (functionFlags & 1 /* Generator */) { // AsyncGenerator function or Generator function return undefined; } var contextualReturnType = getContextualReturnType(func); - return functionFlags & 2 - ? contextualReturnType && getAwaitedTypeOfPromise(contextualReturnType) - : contextualReturnType; + return functionFlags & 2 /* Async */ + ? contextualReturnType && getAwaitedTypeOfPromise(contextualReturnType) // Async function + : contextualReturnType; // Regular function } return undefined; } @@ -37290,7 +43130,7 @@ var ts; if (contextualReturnType) { return node.asteriskToken ? contextualReturnType - : getIteratedTypeOfGenerator(contextualReturnType, (functionFlags & 2) !== 0); + : getIteratedTypeOfGenerator(contextualReturnType, (functionFlags & 2 /* Async */) !== 0); } } return undefined; @@ -37309,28 +43149,35 @@ var ts; return false; } function getContextualReturnType(functionDecl) { - if (functionDecl.kind === 155 || + // If the containing function has a return type annotation, is a constructor, or is a get accessor whose + // corresponding set accessor has a type annotation, return statements in the function are contextually typed + if (functionDecl.kind === 155 /* Constructor */ || ts.getEffectiveReturnTypeNode(functionDecl) || isGetAccessorWithAnnotatedSetAccessor(functionDecl)) { return getReturnTypeOfSignature(getSignatureFromDeclaration(functionDecl)); } + // Otherwise, if the containing function is contextually typed by a function type with exactly one call signature + // and that call signature is non-generic, return statements are contextually typed by the return type of the signature var signature = getContextualSignatureForFunctionLikeDeclaration(functionDecl); if (signature && !isResolvingReturnTypeOfSignature(signature)) { return getReturnTypeOfSignature(signature); } return undefined; } + // In a typed function call, an argument or substitution expression is contextually typed by the type of the corresponding parameter. function getContextualTypeForArgument(callTarget, arg) { - var args = getEffectiveCallArguments(callTarget); - var argIndex = args.indexOf(arg); + var args = getEffectiveCallArguments(callTarget); // TODO: GH#18217 + var argIndex = args.indexOf(arg); // -1 for e.g. the expression of a CallExpression, or the tag of a TaggedTemplateExpression return argIndex === -1 ? undefined : getContextualTypeForArgumentAtIndex(callTarget, argIndex); } function getContextualTypeForArgumentAtIndex(callTarget, argIndex) { + // If we're already in the process of resolving the given signature, don't resolve again as + // that could cause infinite recursion. Instead, return anySignature. var signature = getNodeLinks(callTarget).resolvedSignature === resolvingSignature ? resolvingSignature : getResolvedSignature(callTarget); return getTypeAtPosition(signature, argIndex); } function getContextualTypeForSubstitutionExpression(template, substitutionExpression) { - if (template.parent.kind === 189) { + if (template.parent.kind === 189 /* TaggedTemplateExpression */) { return getContextualTypeForArgument(template.parent, substitutionExpression); } return undefined; @@ -37339,31 +43186,38 @@ var ts; var binaryExpression = node.parent; var left = binaryExpression.left, operatorToken = binaryExpression.operatorToken, right = binaryExpression.right; switch (operatorToken.kind) { - case 58: + case 58 /* EqualsToken */: return node === right && isContextSensitiveAssignment(binaryExpression) ? getTypeOfExpression(left) : undefined; - case 54: + case 54 /* BarBarToken */: + // When an || expression has a contextual type, the operands are contextually typed by that type. When an || + // expression has no contextual type, the right operand is contextually typed by the type of the left operand, + // except for the special case of Javascript declarations of the form `namespace.prop = namespace.prop || {}` var type = getContextualType(binaryExpression); return !type && node === right && !ts.isDefaultedJavascriptInitializer(binaryExpression) ? getTypeOfExpression(left) : type; - case 53: - case 26: + case 53 /* AmpersandAmpersandToken */: + case 26 /* CommaToken */: return node === right ? getContextualType(binaryExpression) : undefined; default: return undefined; } } + // In an assignment expression, the right operand is contextually typed by the type of the left operand. + // Don't do this for special property assignments to avoid circularity. function isContextSensitiveAssignment(binaryExpression) { var kind = ts.getSpecialPropertyAssignmentKind(binaryExpression); switch (kind) { - case 0: + case 0 /* None */: return true; - case 5: + case 5 /* Property */: + // If `binaryExpression.left` was assigned a symbol, then this is a new declaration; otherwise it is an assignment to an existing declaration. + // See `bindStaticPropertyAssignment` in `binder.ts`. return !binaryExpression.left.symbol; - case 1: - case 2: - case 3: - case 4: - case 6: + case 1 /* ExportsProperty */: + case 2 /* ModuleExports */: + case 3 /* PrototypeProperty */: + case 4 /* ThisProperty */: + case 6 /* Prototype */: return false; default: return ts.Debug.assertNever(kind); @@ -37371,19 +43225,24 @@ var ts; } function getTypeOfPropertyOfContextualType(type, name) { return mapType(type, function (t) { - var prop = t.flags & 917504 ? getPropertyOfType(t, name) : undefined; + var prop = t.flags & 917504 /* StructuredType */ ? getPropertyOfType(t, name) : undefined; return prop ? getTypeOfSymbol(prop) : undefined; - }, true); + }, /*noReductions*/ true); } function getIndexTypeOfContextualType(type, kind) { - return mapType(type, function (t) { return getIndexTypeOfStructuredType(t, kind); }, true); + return mapType(type, function (t) { return getIndexTypeOfStructuredType(t, kind); }, /*noReductions*/ true); } + // Return true if the given contextual type is a tuple-like type function contextualTypeIsTupleLikeType(type) { - return !!(type.flags & 262144 ? ts.forEach(type.types, isTupleLikeType) : isTupleLikeType(type)); + return !!(type.flags & 262144 /* Union */ ? ts.forEach(type.types, isTupleLikeType) : isTupleLikeType(type)); } + // In an object literal contextually typed by a type T, the contextual type of a property assignment is the type of + // the matching property in T, if one exists. Otherwise, it is the type of the numeric index signature in T, if one + // exists. Otherwise, it is the type of the string index signature in T, if one exists. function getContextualTypeForObjectLiteralMethod(node) { ts.Debug.assert(ts.isObjectLiteralMethod(node)); - if (node.flags & 8388608) { + if (node.flags & 8388608 /* InWithStatement */) { + // We cannot answer semantic questions within a with block, do not proceed any further return undefined; } return getContextualTypeForObjectLiteralElement(node); @@ -37393,28 +43252,37 @@ var ts; var type = getApparentTypeOfContextualType(objectLiteral); if (type) { if (!hasNonBindableDynamicName(element)) { + // For a (non-symbol) computed property, there is no reason to look up the name + // in the type. It will just be "__computed", which does not appear in any + // SymbolTable. var symbolName_1 = getSymbolOfNode(element).escapedName; var propertyType = getTypeOfPropertyOfContextualType(type, symbolName_1); if (propertyType) { return propertyType; } } - return isNumericName(element.name) && getIndexTypeOfContextualType(type, 1) || - getIndexTypeOfContextualType(type, 0); + return isNumericName(element.name) && getIndexTypeOfContextualType(type, 1 /* Number */) || + getIndexTypeOfContextualType(type, 0 /* String */); } return undefined; } + // In an array literal contextually typed by a type T, the contextual type of an element expression at index N is + // the type of the property with the numeric name N in T, if one exists. Otherwise, if T has a numeric index signature, + // it is the type of the numeric index signature in T. Otherwise, in ES6 and higher, the contextual type is the iterated + // type of T. function getContextualTypeForElementExpression(arrayContextualType, index) { return arrayContextualType && (getTypeOfPropertyOfContextualType(arrayContextualType, "" + index) - || getIndexTypeOfContextualType(arrayContextualType, 1) - || getIteratedTypeOrElementType(arrayContextualType, undefined, false, false, false)); + || getIndexTypeOfContextualType(arrayContextualType, 1 /* Number */) + || getIteratedTypeOrElementType(arrayContextualType, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false, /*checkAssignability*/ false)); } + // In a contextually typed conditional expression, the true/false expressions are contextually typed by the same type. function getContextualTypeForConditionalOperand(node) { var conditional = node.parent; return node === conditional.whenTrue || node === conditional.whenFalse ? getContextualType(conditional) : undefined; } function getContextualTypeForChildJsxExpression(node) { var attributesType = getApparentTypeOfContextualType(node.openingElement.tagName); + // JSX expression is in children of JSX Element, we will look for an "children" atttribute (we get the name from JSX.ElementAttributesProperty) var jsxChildrenPropertyName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(node)); return attributesType && !isTypeAny(attributesType) && jsxChildrenPropertyName && jsxChildrenPropertyName !== "" ? getTypeOfPropertyOfContextualType(attributesType, jsxChildrenPropertyName) : undefined; } @@ -37427,6 +43295,9 @@ var ts; : undefined; } function getContextualTypeForJsxAttribute(attribute) { + // When we trying to resolve JsxOpeningLikeElement as a stateless function element, we will already give its attributes a contextual type + // which is a type of the parameter of the signature we are trying out. + // If there is no contextual type (e.g. we are trying to resolve stateful component), get attributes type from resolving element's tagName if (ts.isJsxAttribute(attribute)) { var attributesType = getApparentTypeOfContextualType(attribute.parent); if (!attributesType || isTypeAny(attributesType)) { @@ -37438,44 +43309,50 @@ var ts; return getContextualType(attribute.parent); } } + // Return true if the given expression is possibly a discriminant value. We limit the kinds of + // expressions we check to those that don't depend on their contextual type in order not to cause + // recursive (and possibly infinite) invocations of getContextualType. function isPossiblyDiscriminantValue(node) { switch (node.kind) { - case 9: - case 8: - case 13: - case 101: - case 86: - case 95: - case 71: + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: + case 13 /* NoSubstitutionTemplateLiteral */: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: + case 95 /* NullKeyword */: + case 71 /* Identifier */: return true; - case 185: - case 191: + case 185 /* PropertyAccessExpression */: + case 191 /* ParenthesizedExpression */: return isPossiblyDiscriminantValue(node.expression); } return false; } + // Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily + // be "pushed" onto a node using the contextualType property. function getApparentTypeOfContextualType(node) { var contextualType = getContextualType(node); contextualType = contextualType && mapType(contextualType, getApparentType); - if (!(contextualType && contextualType.flags & 262144 && ts.isObjectLiteralExpression(node))) { + if (!(contextualType && contextualType.flags & 262144 /* Union */ && ts.isObjectLiteralExpression(node))) { return contextualType; } + // Keep the below up-to-date with the work done within `isRelatedTo` by `findMatchingDiscriminantType` var match; propLoop: for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { var prop = _a[_i]; if (!prop.symbol) continue; - if (prop.kind !== 270) + if (prop.kind !== 270 /* PropertyAssignment */) continue; if (isPossiblyDiscriminantValue(prop.initializer) && isDiscriminantProperty(contextualType, prop.symbol.escapedName)) { var discriminatingType = checkExpression(prop.initializer); for (var _b = 0, _c = contextualType.types; _b < _c.length; _b++) { var type = _c[_b]; var targetType = getTypeOfPropertyOfType(type, prop.symbol.escapedName); - if (targetType && checkTypeAssignableTo(discriminatingType, targetType, undefined)) { + if (targetType && checkTypeAssignableTo(discriminatingType, targetType, /*errorNode*/ undefined)) { if (match) { if (type === match) - continue; + continue; // Finding multiple fields which discriminate to the same type is fine match = undefined; break propLoop; } @@ -37486,8 +43363,26 @@ var ts; } return match || contextualType; } + /** + * Woah! Do you really want to use this function? + * + * Unless you're trying to get the *non-apparent* type for a + * value-literal type or you're authoring relevant portions of this algorithm, + * you probably meant to use 'getApparentTypeOfContextualType'. + * Otherwise this may not be very useful. + * + * In cases where you *are* working on this function, you should understand + * when it is appropriate to use 'getContextualType' and 'getApparentTypeOfContextualType'. + * + * - Use 'getContextualType' when you are simply going to propagate the result to the expression. + * - Use 'getApparentTypeOfContextualType' when you're going to need the members of the type. + * + * @param node the expression whose contextual type will be returned. + * @returns the contextual type of an expression. + */ function getContextualType(node) { - if (node.flags & 8388608) { + if (node.flags & 8388608 /* InWithStatement */) { + // We cannot answer semantic questions within a with block, do not proceed any further return undefined; } if (node.contextualType) { @@ -37495,51 +43390,52 @@ var ts; } var parent = node.parent; switch (parent.kind) { - case 232: - case 149: - case 152: - case 151: - case 182: + case 232 /* VariableDeclaration */: + case 149 /* Parameter */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 182 /* BindingElement */: return getContextualTypeForInitializerExpression(node); - case 193: - case 225: + case 193 /* ArrowFunction */: + case 225 /* ReturnStatement */: return getContextualTypeForReturnExpression(node); - case 203: + case 203 /* YieldExpression */: return getContextualTypeForYieldOperand(parent); - case 187: - case 188: + case 187 /* CallExpression */: + case 188 /* NewExpression */: return getContextualTypeForArgument(parent, node); - case 190: - case 208: + case 190 /* TypeAssertionExpression */: + case 208 /* AsExpression */: return getTypeFromTypeNode(parent.type); - case 200: + case 200 /* BinaryExpression */: return getContextualTypeForBinaryOperand(node); - case 270: - case 271: + case 270 /* PropertyAssignment */: + case 271 /* ShorthandPropertyAssignment */: return getContextualTypeForObjectLiteralElement(parent); - case 272: + case 272 /* SpreadAssignment */: return getApparentTypeOfContextualType(parent.parent); - case 183: { + case 183 /* ArrayLiteralExpression */: { var arrayLiteral = parent; var type = getApparentTypeOfContextualType(arrayLiteral); return getContextualTypeForElementExpression(type, ts.indexOfNode(arrayLiteral.elements, node)); } - case 201: + case 201 /* ConditionalExpression */: return getContextualTypeForConditionalOperand(node); - case 211: - ts.Debug.assert(parent.parent.kind === 202); + case 211 /* TemplateSpan */: + ts.Debug.assert(parent.parent.kind === 202 /* TemplateExpression */); return getContextualTypeForSubstitutionExpression(parent.parent, node); - case 191: { + case 191 /* ParenthesizedExpression */: { + // Like in `checkParenthesizedExpression`, an `/** @type {xyz} */` comment before a parenthesized expression acts as a type cast. var tag = ts.isInJavaScriptFile(parent) ? ts.getJSDocTypeTag(parent) : undefined; return tag ? getTypeFromTypeNode(tag.typeExpression.type) : getContextualType(parent); } - case 265: + case 265 /* JsxExpression */: return getContextualTypeForJsxExpression(parent); - case 262: - case 264: + case 262 /* JsxAttribute */: + case 264 /* JsxSpreadAttribute */: return getContextualTypeForJsxAttribute(parent); - case 257: - case 256: + case 257 /* JsxOpeningElement */: + case 256 /* JsxSelfClosingElement */: return getContextualJsxElementAttributesType(parent); } return undefined; @@ -37554,16 +43450,22 @@ var ts; } var valueType = checkExpression(node.tagName); if (isTypeAny(valueType)) { + // Short-circuit if the class tag is using an element type 'any' return anyType; } var isJs = ts.isInJavaScriptFile(node); return mapType(valueType, function (t) { return getJsxSignaturesParameterTypes(t, isJs, node); }); } function getJsxSignaturesParameterTypes(valueType, isJs, context) { - if (valueType.flags & 4) { + // If the elemType is a string type, we have to return anyType to prevent an error downstream as we will try to find construct or call signature of the type + if (valueType.flags & 4 /* String */) { return anyType; } - else if (valueType.flags & 64) { + else if (valueType.flags & 64 /* StringLiteral */) { + // If the elemType is a stringLiteral type, we can then provide a check to make sure that the string literal type is one of the Jsx intrinsic element type + // For example: + // var CustomTag: "h1" = "h1"; + // Hello World var intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements, context); if (intrinsicElementsType !== errorType) { var stringLiteralTypeName = valueType.value; @@ -37571,19 +43473,22 @@ var ts; if (intrinsicProp) { return getTypeOfSymbol(intrinsicProp); } - var indexSignatureType = getIndexTypeOfType(intrinsicElementsType, 0); + var indexSignatureType = getIndexTypeOfType(intrinsicElementsType, 0 /* String */); if (indexSignatureType) { return indexSignatureType; } } return anyType; } - var signatures = getSignaturesOfType(valueType, 1); + // Resolve the signatures, preferring constructor + var signatures = getSignaturesOfType(valueType, 1 /* Construct */); var ctor = true; if (signatures.length === 0) { - signatures = getSignaturesOfType(valueType, 0); + // No construct signatures, try call signatures + signatures = getSignaturesOfType(valueType, 0 /* Call */); ctor = false; if (signatures.length === 0) { + // We found no signatures at all, which is an error return errorType; } } @@ -37600,7 +43505,7 @@ var ts; links.resolvedSignatures.set(cacheKey, resolvingSignaturesArray); links.resolvedSignatures.set(cacheKey, signatures = instantiateJsxSignatures(context, signatures)); } - return getUnionType(ts.map(signatures, ctor ? function (t) { return getJsxPropsTypeFromClassType(t, isJs, context, false); } : function (t) { return getJsxPropsTypeFromCallSignature(t, context); }), 0); + return getUnionType(ts.map(signatures, ctor ? function (t) { return getJsxPropsTypeFromClassType(t, isJs, context, /*reportErrors*/ false); } : function (t) { return getJsxPropsTypeFromCallSignature(t, context); }), 0 /* None */); } function getJsxPropsTypeFromCallSignature(sig, context) { var propsType = getTypeOfFirstParameterOfSignatureWithFallback(sig, emptyObjectType); @@ -37617,20 +43522,26 @@ var ts; function getJsxPropsTypeFromClassType(sig, isJs, context, reportErrors) { var forcedLookupLocation = getJsxElementPropertiesName(getJsxNamespaceAt(context)); var attributesType = forcedLookupLocation === undefined + // If there is no type ElementAttributesProperty, return the type of the first parameter of the signature, which should be the props type ? getTypeOfFirstParameterOfSignatureWithFallback(sig, emptyObjectType) : forcedLookupLocation === "" + // If there is no e.g. 'props' member in ElementAttributesProperty, use the element class type instead ? getReturnTypeOfSignature(sig) + // Otherwise get the type of the property on the signature return type : getJsxPropsTypeForSignatureFromMember(sig, forcedLookupLocation); if (!attributesType) { + // There is no property named 'props' on this instance type if (reportErrors && !!forcedLookupLocation && !!ts.length(context.attributes.properties)) { error(context, ts.Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, ts.unescapeLeadingUnderscores(forcedLookupLocation)); } return emptyObjectType; } else if (isTypeAny(attributesType)) { + // Props is of type 'any' or unknown return attributesType; } else { + // Normal case -- add in IntrinsicClassElements and IntrinsicElements var apparentAttributesType = attributesType; var intrinsicClassAttribs = getJsxType(JsxNames.IntrinsicClassAttributes, context); if (intrinsicClassAttribs !== errorType) { @@ -37647,8 +43558,10 @@ var ts; return apparentAttributesType; } } + // If the given type is an object or union type with a single signature, and if that signature has at + // least as many parameters as the given function, return the signature. Otherwise return undefined. function getContextualCallSignature(type, node) { - var signatures = getSignaturesOfType(type, 0); + var signatures = getSignaturesOfType(type, 0 /* Call */); if (signatures.length === 1) { var signature = signatures[0]; if (!isAritySmaller(signature, node)) { @@ -37656,6 +43569,7 @@ var ts; } } } + /** If the contextual signature has fewer parameters than the function expression, do not use it */ function isAritySmaller(signature, target) { var targetParameterCount = 0; for (; targetParameterCount < target.parameters.length; targetParameterCount++) { @@ -37671,9 +43585,10 @@ var ts; return sourceLength < targetParameterCount; } function isFunctionExpressionOrArrowFunction(node) { - return node.kind === 192 || node.kind === 193; + return node.kind === 192 /* FunctionExpression */ || node.kind === 193 /* ArrowFunction */; } function getContextualSignatureForFunctionLikeDeclaration(node) { + // Only function expressions, arrow functions, and object literal methods are contextually typed. return isFunctionExpressionOrArrowFunction(node) || ts.isObjectLiteralMethod(node) ? getContextualSignature(node) : undefined; @@ -37683,8 +43598,13 @@ var ts; getContextualTypeForObjectLiteralMethod(node) : getApparentTypeOfContextualType(node); } + // Return the contextual signature for a given expression node. A contextual type provides a + // contextual signature if it has a single call signature and if that call signature is non-generic. + // If the contextual type is a union type, get the signature from each type possible and if they are + // all identical ignoring their return type, the result is same signature but with return type as + // union type of return types from these signatures function getContextualSignature(node) { - ts.Debug.assert(node.kind !== 154 || ts.isObjectLiteralMethod(node)); + ts.Debug.assert(node.kind !== 154 /* MethodDeclaration */ || ts.isObjectLiteralMethod(node)); var type; if (ts.isInJavaScriptFile(node)) { var jsdoc = ts.getJSDocType(node); @@ -37698,7 +43618,7 @@ var ts; if (!type) { return undefined; } - if (!(type.flags & 262144)) { + if (!(type.flags & 262144 /* Union */)) { return getContextualCallSignature(type, node); } var signatureList; @@ -37708,16 +43628,20 @@ var ts; var signature = getContextualCallSignature(current, node); if (signature) { if (!signatureList) { + // This signature will contribute to contextual union signature signatureList = [signature]; } - else if (!compareSignaturesIdentical(signatureList[0], signature, false, true, true, compareTypesIdentical)) { + else if (!compareSignaturesIdentical(signatureList[0], signature, /*partialMatch*/ false, /*ignoreThisTypes*/ true, /*ignoreReturnTypes*/ true, compareTypesIdentical)) { + // Signatures aren't identical, do not use return undefined; } else { + // Use this signature for contextual union signature signatureList.push(signature); } } } + // Result is union of signatures collected (return type is union of return types of this signature set) var result; if (signatureList) { result = cloneSignature(signatureList[0]); @@ -37726,15 +43650,15 @@ var ts; return result; } function checkSpreadExpression(node, checkMode) { - if (languageVersion < 2 && compilerOptions.downlevelIteration) { - checkExternalEmitHelpers(node, 1536); + if (languageVersion < 2 /* ES2015 */ && compilerOptions.downlevelIteration) { + checkExternalEmitHelpers(node, 1536 /* SpreadIncludes */); } var arrayOrIterableType = checkExpression(node.expression, checkMode); - return checkIteratedTypeOrElementType(arrayOrIterableType, node.expression, false, false); + return checkIteratedTypeOrElementType(arrayOrIterableType, node.expression, /*allowStringInput*/ false, /*allowAsyncIterables*/ false); } function hasDefaultValue(node) { - return (node.kind === 182 && !!node.initializer) || - (node.kind === 200 && node.operatorToken.kind === 58); + return (node.kind === 182 /* BindingElement */ && !!node.initializer) || + (node.kind === 200 /* BinaryExpression */ && node.operatorToken.kind === 58 /* EqualsToken */); } function checkArrayLiteral(node, checkMode) { var elements = node.elements; @@ -37744,10 +43668,22 @@ var ts; var contextualType = getApparentTypeOfContextualType(node); for (var index = 0; index < elements.length; index++) { var e = elements[index]; - if (inDestructuringPattern && e.kind === 204) { + if (inDestructuringPattern && e.kind === 204 /* SpreadElement */) { + // Given the following situation: + // var c: {}; + // [...c] = ["", 0]; + // + // c is represented in the tree as a spread element in an array literal. + // But c really functions as a rest element, and its purpose is to provide + // a contextual type for the right hand side of the assignment. Therefore, + // instead of calling checkExpression on "...c", which will give an error + // if c is not iterable/array-like, we need to act as if we are trying to + // get the contextual element type from it. So we do something similar to + // getContextualTypeForElementExpression, which will crucially not error + // if there is no index type / iterated type. var restArrayType = checkExpression(e.expression, checkMode); - var restElementType = getIndexTypeOfType(restArrayType, 1) || - getIteratedTypeOrElementType(restArrayType, undefined, false, false, false); + var restElementType = getIndexTypeOfType(restArrayType, 1 /* Number */) || + getIteratedTypeOrElementType(restArrayType, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false, /*checkAssignability*/ false); if (restElementType) { elementTypes.push(restElementType); } @@ -37757,9 +43693,11 @@ var ts; var type = checkExpressionForMutableLocation(e, checkMode, elementContextualType); elementTypes.push(type); } - hasSpreadElement = hasSpreadElement || e.kind === 204; + hasSpreadElement = hasSpreadElement || e.kind === 204 /* SpreadElement */; } if (!hasSpreadElement) { + // If array literal is actually a destructuring pattern, mark it as an implied type. We do this such + // that we get the same behavior for "var [x, y] = []" and "[x, y] = []". if (inDestructuringPattern && elementTypes.length) { var type = cloneTypeReference(createTupleType(elementTypes)); type.pattern = node; @@ -37767,7 +43705,9 @@ var ts; } if (contextualType && contextualTypeIsTupleLikeType(contextualType)) { var pattern = contextualType.pattern; - if (pattern && (pattern.kind === 181 || pattern.kind === 183)) { + // If array literal is contextually typed by a binding pattern or an assignment pattern, pad the resulting + // tuple type with the corresponding binding or assignment element types to make the lengths equal. + if (pattern && (pattern.kind === 181 /* ArrayBindingPattern */ || pattern.kind === 183 /* ArrayLiteralExpression */)) { var patternElements = pattern.elements; for (var i = elementTypes.length; i < patternElements.length; i++) { var patternElement = patternElements[i]; @@ -37775,7 +43715,7 @@ var ts; elementTypes.push(contextualType.typeArguments[i]); } else { - if (patternElement.kind !== 206) { + if (patternElement.kind !== 206 /* OmittedExpression */) { error(patternElement, ts.Diagnostics.Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value); } elementTypes.push(strictNullChecks ? implicitNeverType : undefinedWideningType); @@ -37788,42 +43728,67 @@ var ts; } } return createArrayType(elementTypes.length ? - getUnionType(elementTypes, 2) : + getUnionType(elementTypes, 2 /* Subtype */) : strictNullChecks ? implicitNeverType : undefinedWideningType); } function isNumericName(name) { switch (name.kind) { - case 147: + case 147 /* ComputedPropertyName */: return isNumericComputedName(name); - case 71: + case 71 /* Identifier */: return isNumericLiteralName(name.escapedText); - case 8: - case 9: + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: return isNumericLiteralName(name.text); default: return false; } } function isNumericComputedName(name) { - return isTypeAssignableToKind(checkComputedPropertyName(name), 168); + // It seems odd to consider an expression of type Any to result in a numeric name, + // but this behavior is consistent with checkIndexedAccess + return isTypeAssignableToKind(checkComputedPropertyName(name), 168 /* NumberLike */); } function isInfinityOrNaNString(name) { return name === "Infinity" || name === "-Infinity" || name === "NaN"; } function isNumericLiteralName(name) { + // The intent of numeric names is that + // - they are names with text in a numeric form, and that + // - setting properties/indexing with them is always equivalent to doing so with the numeric literal 'numLit', + // acquired by applying the abstract 'ToNumber' operation on the name's text. + // + // The subtlety is in the latter portion, as we cannot reliably say that anything that looks like a numeric literal is a numeric name. + // In fact, it is the case that the text of the name must be equal to 'ToString(numLit)' for this to hold. + // + // Consider the property name '"0xF00D"'. When one indexes with '0xF00D', they are actually indexing with the value of 'ToString(0xF00D)' + // according to the ECMAScript specification, so it is actually as if the user indexed with the string '"61453"'. + // Thus, the text of all numeric literals equivalent to '61543' such as '0xF00D', '0xf00D', '0170015', etc. are not valid numeric names + // because their 'ToString' representation is not equal to their original text. + // This is motivated by ECMA-262 sections 9.3.1, 9.8.1, 11.1.5, and 11.2.1. + // + // Here, we test whether 'ToString(ToNumber(name))' is exactly equal to 'name'. + // The '+' prefix operator is equivalent here to applying the abstract ToNumber operation. + // Applying the 'toString()' method on a number gives us the abstract ToString operation on a number. + // + // Note that this accepts the values 'Infinity', '-Infinity', and 'NaN', and that this is intentional. + // This is desired behavior, because when indexing with them as numeric entities, you are indexing + // with the strings '"Infinity"', '"-Infinity"', and '"NaN"' respectively. return (+name).toString() === name; } function checkComputedPropertyName(node) { var links = getNodeLinks(node.expression); if (!links.resolvedType) { links.resolvedType = checkExpression(node.expression); - if (links.resolvedType.flags & 24576 || - !isTypeAssignableToKind(links.resolvedType, 68 | 168 | 3072) && + // This will allow types number, string, symbol or any. It will also allow enums, the unknown + // type, and any union of these types (like string | number). + if (links.resolvedType.flags & 24576 /* Nullable */ || + !isTypeAssignableToKind(links.resolvedType, 68 /* StringLike */ | 168 /* NumberLike */ | 3072 /* ESSymbolLike */) && !isTypeAssignableTo(links.resolvedType, stringNumberSymbolType)) { error(node, ts.Diagnostics.A_computed_property_name_must_be_of_type_string_number_symbol_or_any); } else { - checkThatExpressionIsProperSymbolReference(node.expression, links.resolvedType, true); + checkThatExpressionIsProperSymbolReference(node.expression, links.resolvedType, /*reportError*/ true); } } return links.resolvedType; @@ -37831,23 +43796,24 @@ var ts; function getObjectLiteralIndexInfo(propertyNodes, offset, properties, kind) { var propTypes = []; for (var i = 0; i < properties.length; i++) { - if (kind === 0 || isNumericName(propertyNodes[i + offset].name)) { + if (kind === 0 /* String */ || isNumericName(propertyNodes[i + offset].name)) { propTypes.push(getTypeOfSymbol(properties[i])); } } - var unionType = propTypes.length ? getUnionType(propTypes, 2) : undefinedType; - return createIndexInfo(unionType, false); + var unionType = propTypes.length ? getUnionType(propTypes, 2 /* Subtype */) : undefinedType; + return createIndexInfo(unionType, /*isReadonly*/ false); } function checkObjectLiteral(node, checkMode) { var inDestructuringPattern = ts.isAssignmentTarget(node); + // Grammar checking checkGrammarObjectLiteralExpression(node, inDestructuringPattern); var propertiesTable; var propertiesArray = []; var spread = emptyObjectType; - var propagatedFlags = 33554432; + var propagatedFlags = 33554432 /* FreshLiteral */; var contextualType = getApparentTypeOfContextualType(node); var contextualTypeHasPattern = contextualType && contextualType.pattern && - (contextualType.pattern.kind === 180 || contextualType.pattern.kind === 184); + (contextualType.pattern.kind === 180 /* ObjectBindingPattern */ || contextualType.pattern.kind === 184 /* ObjectLiteralExpression */); var isInJSFile = ts.isInJavaScriptFile(node) && !ts.isInJsonFile(node); var isJSObjectLiteral = !contextualType && isInJSFile; var typeFlags = 0; @@ -37859,13 +43825,13 @@ var ts; for (var i = 0; i < node.properties.length; i++) { var memberDecl = node.properties[i]; var member = getSymbolOfNode(memberDecl); - var computedNameType = memberDecl.name && memberDecl.name.kind === 147 && !ts.isWellKnownSymbolSyntactically(memberDecl.name.expression) ? + var computedNameType = memberDecl.name && memberDecl.name.kind === 147 /* ComputedPropertyName */ && !ts.isWellKnownSymbolSyntactically(memberDecl.name.expression) ? checkComputedPropertyName(memberDecl.name) : undefined; - if (memberDecl.kind === 270 || - memberDecl.kind === 271 || + if (memberDecl.kind === 270 /* PropertyAssignment */ || + memberDecl.kind === 271 /* ShorthandPropertyAssignment */ || ts.isObjectLiteralMethod(memberDecl)) { - var type = memberDecl.kind === 270 ? checkPropertyAssignment(memberDecl, checkMode) : - memberDecl.kind === 271 ? checkExpressionForMutableLocation(memberDecl.name, checkMode) : + var type = memberDecl.kind === 270 /* PropertyAssignment */ ? checkPropertyAssignment(memberDecl, checkMode) : + memberDecl.kind === 271 /* ShorthandPropertyAssignment */ ? checkExpressionForMutableLocation(memberDecl.name, checkMode) : checkObjectLiteralMethod(memberDecl, checkMode); if (isInJSFile) { var jsDocType = getTypeForDeclarationFromJSDocComment(memberDecl); @@ -37875,27 +43841,31 @@ var ts; } } typeFlags |= type.flags; - var nameType = computedNameType && computedNameType.flags & 2240 ? + var nameType = computedNameType && computedNameType.flags & 2240 /* StringOrNumberLiteralOrUnique */ ? computedNameType : undefined; var prop = nameType ? - createSymbol(4 | member.flags, getLateBoundNameFromType(nameType), 1024) : - createSymbol(4 | member.flags, member.escapedName); + createSymbol(4 /* Property */ | member.flags, getLateBoundNameFromType(nameType), 1024 /* Late */) : + createSymbol(4 /* Property */ | member.flags, member.escapedName); if (nameType) { prop.nameType = nameType; } if (inDestructuringPattern) { - var isOptional = (memberDecl.kind === 270 && hasDefaultValue(memberDecl.initializer)) || - (memberDecl.kind === 271 && memberDecl.objectAssignmentInitializer); + // If object literal is an assignment pattern and if the assignment pattern specifies a default value + // for the property, make the property optional. + var isOptional = (memberDecl.kind === 270 /* PropertyAssignment */ && hasDefaultValue(memberDecl.initializer)) || + (memberDecl.kind === 271 /* ShorthandPropertyAssignment */ && memberDecl.objectAssignmentInitializer); if (isOptional) { - prop.flags |= 16777216; + prop.flags |= 16777216 /* Optional */; } } - else if (contextualTypeHasPattern && !(ts.getObjectFlags(contextualType) & 512)) { + else if (contextualTypeHasPattern && !(ts.getObjectFlags(contextualType) & 512 /* ObjectLiteralPatternWithComputedProperties */)) { + // If object literal is contextually typed by the implied type of a binding pattern, and if the + // binding pattern specifies a default value for the property, make the property optional. var impliedProp = getPropertyOfType(contextualType, member.escapedName); if (impliedProp) { - prop.flags |= impliedProp.flags & 16777216; + prop.flags |= impliedProp.flags & 16777216 /* Optional */; } - else if (!compilerOptions.suppressExcessPropertyErrors && !getIndexInfoOfType(contextualType, 0)) { + else if (!compilerOptions.suppressExcessPropertyErrors && !getIndexInfoOfType(contextualType, 0 /* String */)) { error(memberDecl.name, ts.Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1, symbolToString(member), typeToString(contextualType)); } } @@ -37908,12 +43878,12 @@ var ts; prop.target = member; member = prop; } - else if (memberDecl.kind === 272) { - if (languageVersion < 2) { - checkExternalEmitHelpers(memberDecl, 2); + else if (memberDecl.kind === 272 /* SpreadAssignment */) { + if (languageVersion < 2 /* ES2015 */) { + checkExternalEmitHelpers(memberDecl, 2 /* Assign */); } if (propertiesArray.length > 0) { - spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, propagatedFlags, 0); + spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, propagatedFlags, /*objectFlags*/ 0); propertiesArray = []; propertiesTable = ts.createSymbolTable(); hasComputedStringProperty = false; @@ -37925,15 +43895,20 @@ var ts; error(memberDecl, ts.Diagnostics.Spread_types_may_only_be_created_from_object_types); return errorType; } - spread = getSpreadType(spread, type, node.symbol, propagatedFlags, 0); + spread = getSpreadType(spread, type, node.symbol, propagatedFlags, /*objectFlags*/ 0); offset = i + 1; continue; } else { - ts.Debug.assert(memberDecl.kind === 156 || memberDecl.kind === 157); + // TypeScript 1.0 spec (April 2014) + // A get accessor declaration is processed in the same manner as + // an ordinary function declaration(section 6.1) with no parameters. + // A set accessor declaration is processed in the same manner + // as an ordinary function declaration with a single parameter and a Void return type. + ts.Debug.assert(memberDecl.kind === 156 /* GetAccessor */ || memberDecl.kind === 157 /* SetAccessor */); checkNodeDeferred(memberDecl); } - if (computedNameType && !(computedNameType.flags & 2240)) { + if (computedNameType && !(computedNameType.flags & 2240 /* StringOrNumberLiteralOrUnique */)) { if (isTypeAssignableTo(computedNameType, stringNumberSymbolType)) { if (isTypeAssignableTo(computedNameType, numberType)) { hasComputedNumberProperty = true; @@ -37951,11 +43926,13 @@ var ts; } propertiesArray.push(member); } + // If object literal is contextually typed by the implied type of a binding pattern, augment the result + // type with those properties for which the binding pattern specifies a default value. if (contextualTypeHasPattern) { for (var _i = 0, _a = getPropertiesOfType(contextualType); _i < _a.length; _i++) { var prop = _a[_i]; if (!propertiesTable.get(prop.escapedName) && !(spread && getPropertyOfType(spread, prop.escapedName))) { - if (!(prop.flags & 16777216)) { + if (!(prop.flags & 16777216 /* Optional */)) { error(prop.valueDeclaration || prop.bindingElement, ts.Diagnostics.Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value); } propertiesTable.set(prop.escapedName, prop); @@ -37965,42 +43942,44 @@ var ts; } if (spread !== emptyObjectType) { if (propertiesArray.length > 0) { - spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, propagatedFlags, 0); + spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, propagatedFlags, /*objectFlags*/ 0); } return spread; } return createObjectLiteralType(); function createObjectLiteralType() { - var stringIndexInfo = isJSObjectLiteral ? jsObjectLiteralIndexInfo : hasComputedStringProperty ? getObjectLiteralIndexInfo(node.properties, offset, propertiesArray, 0) : undefined; - var numberIndexInfo = hasComputedNumberProperty && !isJSObjectLiteral ? getObjectLiteralIndexInfo(node.properties, offset, propertiesArray, 1) : undefined; + var stringIndexInfo = isJSObjectLiteral ? jsObjectLiteralIndexInfo : hasComputedStringProperty ? getObjectLiteralIndexInfo(node.properties, offset, propertiesArray, 0 /* String */) : undefined; + var numberIndexInfo = hasComputedNumberProperty && !isJSObjectLiteral ? getObjectLiteralIndexInfo(node.properties, offset, propertiesArray, 1 /* Number */) : undefined; var result = createAnonymousType(node.symbol, propertiesTable, ts.emptyArray, ts.emptyArray, stringIndexInfo, numberIndexInfo); - var freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : 33554432; - result.flags |= 268435456 | freshObjectLiteralFlag | (typeFlags & 939524096); - result.objectFlags |= 128; + var freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : 33554432 /* FreshLiteral */; + result.flags |= 268435456 /* ContainsObjectLiteral */ | freshObjectLiteralFlag | (typeFlags & 939524096 /* PropagatingFlags */); + result.objectFlags |= 128 /* ObjectLiteral */; if (patternWithComputedProperties) { - result.objectFlags |= 512; + result.objectFlags |= 512 /* ObjectLiteralPatternWithComputedProperties */; } if (inDestructuringPattern) { result.pattern = node; } - if (!(result.flags & 24576)) { - propagatedFlags |= (result.flags & 939524096); + if (!(result.flags & 24576 /* Nullable */)) { + propagatedFlags |= (result.flags & 939524096 /* PropagatingFlags */); } return result; } } function isValidSpreadType(type) { - return !!(type.flags & (3 | 16777216) || - getFalsyFlags(type) & 29120 && isValidSpreadType(removeDefinitelyFalsyTypes(type)) || - type.flags & 131072 && !isGenericMappedType(type) || - type.flags & 786432 && ts.every(type.types, isValidSpreadType)); + return !!(type.flags & (3 /* AnyOrUnknown */ | 16777216 /* NonPrimitive */) || + getFalsyFlags(type) & 29120 /* DefinitelyFalsy */ && isValidSpreadType(removeDefinitelyFalsyTypes(type)) || + type.flags & 131072 /* Object */ && !isGenericMappedType(type) || + type.flags & 786432 /* UnionOrIntersection */ && ts.every(type.types, isValidSpreadType)); } function checkJsxSelfClosingElement(node, checkMode) { checkJsxOpeningLikeElementOrOpeningFragment(node, checkMode); return getJsxElementTypeAt(node) || anyType; } function checkJsxElement(node, checkMode) { + // Check attributes checkJsxOpeningLikeElementOrOpeningFragment(node.openingElement, checkMode); + // Perform resolution on the closing tag so that rename/go to definition/etc work if (isJsxIntrinsicIdentifier(node.closingElement.tagName)) { getIntrinsicTagSymbol(node.closingElement); } @@ -38011,22 +43990,30 @@ var ts; } function checkJsxFragment(node, checkMode) { checkJsxOpeningLikeElementOrOpeningFragment(node.openingFragment, checkMode); - if (compilerOptions.jsx === 2 && (compilerOptions.jsxFactory || ts.getSourceFileOfNode(node).pragmas.has("jsx"))) { + if (compilerOptions.jsx === 2 /* React */ && (compilerOptions.jsxFactory || ts.getSourceFileOfNode(node).pragmas.has("jsx"))) { error(node, compilerOptions.jsxFactory ? ts.Diagnostics.JSX_fragment_is_not_supported_when_using_jsxFactory : ts.Diagnostics.JSX_fragment_is_not_supported_when_using_an_inline_JSX_factory_pragma); } return getJsxElementTypeAt(node) || anyType; } + /** + * Returns true iff the JSX element name would be a valid JS identifier, ignoring restrictions about keywords not being identifiers + */ function isUnhyphenatedJsxName(name) { + // - is the only character supported in JSX attribute names that isn't valid in JavaScript identifiers return !ts.stringContains(name, "-"); } + /** + * Returns true iff React would emit this tag name as a string rather than an identifier or qualified name + */ function isJsxIntrinsicIdentifier(tagName) { + // TODO (yuisu): comment switch (tagName.kind) { - case 185: - case 99: + case 185 /* PropertyAccessExpression */: + case 99 /* ThisKeyword */: return false; - case 71: + case 71 /* Identifier */: return ts.isIntrinsicJsxName(tagName.escapedText); default: return ts.Debug.fail(); @@ -38035,8 +44022,17 @@ var ts; function checkJsxAttribute(node, checkMode) { return node.initializer ? checkExpressionForMutableLocation(node.initializer, checkMode) - : trueType; + : trueType; // is sugar for } + /** + * Get attributes type of the JSX opening-like element. The result is from resolving "attributes" property of the opening-like element. + * + * @param openingLikeElement a JSX opening-like element + * @param filter a function to remove attributes that will not participate in checking whether attributes are assignable + * @return an anonymous type (similar to the one returned by checkObjectLiteral) in which its properties are attributes property. + * @remarks Because this function calls getSpreadType, it needs to use the same checks as checkObjectLiteral, + * which also calls getSpreadType. + */ function createJsxAttributesTypeFromAttributesProperty(openingLikeElement, checkMode) { var attributes = openingLikeElement.attributes; var attributesTable = ts.createSymbolTable(); @@ -38050,7 +44046,7 @@ var ts; var member = attributeDecl.symbol; if (ts.isJsxAttribute(attributeDecl)) { var exprType = checkJsxAttribute(attributeDecl, checkMode); - var attributeSymbol = createSymbol(4 | 33554432 | member.flags, member.escapedName); + var attributeSymbol = createSymbol(4 /* Property */ | 33554432 /* Transient */ | member.flags, member.escapedName); attributeSymbol.declarations = member.declarations; attributeSymbol.parent = member.parent; if (member.valueDeclaration) { @@ -38064,9 +44060,9 @@ var ts; } } else { - ts.Debug.assert(attributeDecl.kind === 264); + ts.Debug.assert(attributeDecl.kind === 264 /* JsxSpreadAttribute */); if (attributesTable.size > 0) { - spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, 0, 4096); + spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, /*typeFlags*/ 0, 4096 /* JsxAttributes */); attributesTable = ts.createSymbolTable(); } var exprType = checkExpressionCached(attributeDecl.expression, checkMode); @@ -38074,7 +44070,7 @@ var ts; hasSpreadAnyType = true; } if (isValidSpreadType(exprType)) { - spread = getSpreadType(spread, exprType, openingLikeElement.symbol, 0, 4096); + spread = getSpreadType(spread, exprType, openingLikeElement.symbol, /*typeFlags*/ 0, 4096 /* JsxAttributes */); } else { typeToIntersect = typeToIntersect ? getIntersectionType([typeToIntersect, exprType]) : exprType; @@ -38083,23 +44079,29 @@ var ts; } if (!hasSpreadAnyType) { if (attributesTable.size > 0) { - spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, 0, 4096); + spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, /*typeFlags*/ 0, 4096 /* JsxAttributes */); } } - var parent = openingLikeElement.parent.kind === 255 ? openingLikeElement.parent : undefined; + // Handle children attribute + var parent = openingLikeElement.parent.kind === 255 /* JsxElement */ ? openingLikeElement.parent : undefined; + // We have to check that openingElement of the parent is the one we are visiting as this may not be true for selfClosingElement if (parent && parent.openingElement === openingLikeElement && parent.children.length > 0) { var childrenTypes = checkJsxChildren(parent, checkMode); if (!hasSpreadAnyType && jsxChildrenPropertyName && jsxChildrenPropertyName !== "") { + // Error if there is a attribute named "children" explicitly specified and children element. + // This is because children element will overwrite the value from attributes. + // Note: we will not warn "children" attribute overwritten if "children" attribute is specified in object spread. if (explicitlySpecifyChildrenAttribute) { error(attributes, ts.Diagnostics._0_are_specified_twice_The_attribute_named_0_will_be_overwritten, ts.unescapeLeadingUnderscores(jsxChildrenPropertyName)); } - var childrenPropSymbol = createSymbol(4 | 33554432, jsxChildrenPropertyName); + // If there are children in the body of JSX element, create dummy attribute "children" with the union of children types so that it will pass the attribute checking process + var childrenPropSymbol = createSymbol(4 /* Property */ | 33554432 /* Transient */, jsxChildrenPropertyName); childrenPropSymbol.type = childrenTypes.length === 1 ? childrenTypes[0] : createArrayType(getUnionType(childrenTypes)); var childPropMap = ts.createSymbolTable(); childPropMap.set(jsxChildrenPropertyName, childrenPropSymbol); - spread = getSpreadType(spread, createAnonymousType(attributes.symbol, childPropMap, ts.emptyArray, ts.emptyArray, undefined, undefined), attributes.symbol, 0, 4096); + spread = getSpreadType(spread, createAnonymousType(attributes.symbol, childPropMap, ts.emptyArray, ts.emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined), attributes.symbol, /*typeFlags*/ 0, 4096 /* JsxAttributes */); } } if (hasSpreadAnyType) { @@ -38109,10 +44111,15 @@ var ts; return getIntersectionType([typeToIntersect, spread]); } return typeToIntersect || (spread === emptyObjectType ? createJsxAttributesType() : spread); + /** + * Create anonymous type from given attributes symbol table. + * @param symbol a symbol of JsxAttributes containing attributes corresponding to attributesTable + * @param attributesTable a symbol table of attributes property + */ function createJsxAttributesType() { - var result = createAnonymousType(attributes.symbol, attributesTable, ts.emptyArray, ts.emptyArray, undefined, undefined); - result.flags |= 268435456; - result.objectFlags |= 128 | 4096; + var result = createAnonymousType(attributes.symbol, attributesTable, ts.emptyArray, ts.emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined); + result.flags |= 268435456 /* ContainsObjectLiteral */; + result.objectFlags |= 128 /* ObjectLiteral */ | 4096 /* JsxAttributes */; return result; } } @@ -38120,7 +44127,9 @@ var ts; var childrenTypes = []; for (var _i = 0, _a = node.children; _i < _a.length; _i++) { var child = _a[_i]; - if (child.kind === 10) { + // In React, JSX text that contains only whitespaces will be ignored so we don't want to type-check that + // because then type of children property will have constituent of string type. + if (child.kind === 10 /* JsxText */) { if (!child.containsOnlyWhiteSpaces) { childrenTypes.push(stringType); } @@ -38131,32 +44140,46 @@ var ts; } return childrenTypes; } + /** + * Check attributes property of opening-like element. This function is called during chooseOverload to get call signature of a JSX opening-like element. + * (See "checkApplicableSignatureForJsxOpeningLikeElement" for how the function is used) + * @param node a JSXAttributes to be resolved of its type + */ function checkJsxAttributes(node, checkMode) { return createJsxAttributesTypeFromAttributesProperty(node.parent, checkMode); } function getJsxType(name, location) { var namespace = getJsxNamespaceAt(location); var exports = namespace && getExportsOfSymbol(namespace); - var typeSymbol = exports && getSymbol(exports, name, 67901928); + var typeSymbol = exports && getSymbol(exports, name, 67901928 /* Type */); return typeSymbol ? getDeclaredTypeOfSymbol(typeSymbol) : errorType; } + /** + * Looks up an intrinsic tag name and returns a symbol that either points to an intrinsic + * property (in which case nodeLinks.jsxFlags will be IntrinsicNamedElement) or an intrinsic + * string index signature (in which case nodeLinks.jsxFlags will be IntrinsicIndexedElement). + * May also return unknownSymbol if both of these lookups fail. + */ function getIntrinsicTagSymbol(node) { var links = getNodeLinks(node); if (!links.resolvedSymbol) { var intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements, node); if (intrinsicElementsType !== errorType) { + // Property case if (!ts.isIdentifier(node.tagName)) return ts.Debug.fail(); var intrinsicProp = getPropertyOfType(intrinsicElementsType, node.tagName.escapedText); if (intrinsicProp) { - links.jsxFlags |= 1; + links.jsxFlags |= 1 /* IntrinsicNamedElement */; return links.resolvedSymbol = intrinsicProp; } - var indexSignatureType = getIndexTypeOfType(intrinsicElementsType, 0); + // Intrinsic string indexer case + var indexSignatureType = getIndexTypeOfType(intrinsicElementsType, 0 /* String */); if (indexSignatureType) { - links.jsxFlags |= 2; + links.jsxFlags |= 2 /* IntrinsicIndexedElement */; return links.resolvedSymbol = intrinsicElementsType.symbol; } + // Wasn't found error(node, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.idText(node.tagName), "JSX." + JsxNames.IntrinsicElements); return links.resolvedSymbol = unknownSymbol; } @@ -38177,7 +44200,7 @@ var ts; var signature = signatures_3[_i]; if (signature.typeParameters) { var isJavascript = ts.isInJavaScriptFile(node); - var typeArgumentInstantiated = getJsxSignatureTypeArgumentInstantiation(signature, node, isJavascript, false); + var typeArgumentInstantiated = getJsxSignatureTypeArgumentInstantiation(signature, node, isJavascript, /*reportErrors*/ false); if (typeArgumentInstantiated) { hasTypeArgumentError = false; instantiatedSignatures.push(typeArgumentInstantiated); @@ -38186,7 +44209,7 @@ var ts; if (node.typeArguments && hasCorrectTypeArgumentArity(signature, node.typeArguments)) { candidateForTypeArgumentError = signature; } - var inferenceContext = createInferenceContext(signature.typeParameters, signature, isJavascript ? 4 : 0); + var inferenceContext = createInferenceContext(signature.typeParameters, signature, /*flags*/ isJavascript ? 4 /* AnyDefault */ : 0 /* None */); var typeArguments = inferJsxTypeArguments(signature, node, inferenceContext); instantiatedSignatures.push(getSignatureInstantiation(signature, typeArguments, isJavascript)); } @@ -38197,8 +44220,9 @@ var ts; } if (node.typeArguments && hasTypeArgumentError) { if (candidateForTypeArgumentError) { - checkTypeArguments(candidateForTypeArgumentError, node.typeArguments, true); + checkTypeArguments(candidateForTypeArgumentError, node.typeArguments, /*reportErrors*/ true); } + // Length check to avoid issuing an arity error on length=0, the "Type argument list cannot be empty" grammar error alone is fine else if (node.typeArguments.length !== 0) { diagnostics.add(getTypeArgumentArityError(node, signatures, node.typeArguments)); } @@ -38221,32 +44245,52 @@ var ts; } function getJsxNamespaceAt(location) { var namespaceName = getJsxNamespace(location); - var resolvedNamespace = resolveName(location, namespaceName, 1920, undefined, namespaceName, false); + var resolvedNamespace = resolveName(location, namespaceName, 1920 /* Namespace */, /*diagnosticMessage*/ undefined, namespaceName, /*isUse*/ false); if (resolvedNamespace) { - var candidate = getSymbol(getExportsOfSymbol(resolveSymbol(resolvedNamespace)), JsxNames.JSX, 1920); + var candidate = getSymbol(getExportsOfSymbol(resolveSymbol(resolvedNamespace)), JsxNames.JSX, 1920 /* Namespace */); if (candidate) { return candidate; } } - return getGlobalSymbol(JsxNames.JSX, 1920, undefined); + // JSX global fallback + return getGlobalSymbol(JsxNames.JSX, 1920 /* Namespace */, /*diagnosticMessage*/ undefined); // TODO: GH#18217 } + /** + * Look into JSX namespace and then look for container with matching name as nameOfAttribPropContainer. + * Get a single property from that container if existed. Report an error if there are more than one property. + * + * @param nameOfAttribPropContainer a string of value JsxNames.ElementAttributesPropertyNameContainer or JsxNames.ElementChildrenAttributeNameContainer + * if other string is given or the container doesn't exist, return undefined. + */ function getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer, jsxNamespace) { - var jsxElementAttribPropInterfaceSym = jsxNamespace && getSymbol(jsxNamespace.exports, nameOfAttribPropContainer, 67901928); + // JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [symbol] + var jsxElementAttribPropInterfaceSym = jsxNamespace && getSymbol(jsxNamespace.exports, nameOfAttribPropContainer, 67901928 /* Type */); + // JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [type] var jsxElementAttribPropInterfaceType = jsxElementAttribPropInterfaceSym && getDeclaredTypeOfSymbol(jsxElementAttribPropInterfaceSym); + // The properties of JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute var propertiesOfJsxElementAttribPropInterface = jsxElementAttribPropInterfaceType && getPropertiesOfType(jsxElementAttribPropInterfaceType); if (propertiesOfJsxElementAttribPropInterface) { + // Element Attributes has zero properties, so the element attributes type will be the class instance type if (propertiesOfJsxElementAttribPropInterface.length === 0) { return ""; } + // Element Attributes has one property, so the element attributes type will be the type of the corresponding + // property of the class instance type else if (propertiesOfJsxElementAttribPropInterface.length === 1) { return propertiesOfJsxElementAttribPropInterface[0].escapedName; } else if (propertiesOfJsxElementAttribPropInterface.length > 1) { + // More than one property on ElementAttributesProperty is an error error(jsxElementAttribPropInterfaceSym.declarations[0], ts.Diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, ts.unescapeLeadingUnderscores(nameOfAttribPropContainer)); } } return undefined; } + /// e.g. "props" for React.d.ts, + /// or 'undefined' if ElementAttributesProperty doesn't exist (which means all + /// non-intrinsic elements' attributes type is 'any'), + /// or '' if it has 0 properties (which means every + /// non-intrinsic elements' attributes type is the element instance type) function getJsxElementPropertiesName(jsxNamespace) { return getNameFromJsxElementAttributesContainer(JsxNames.ElementAttributesPropertyNameContainer, jsxNamespace); } @@ -38257,7 +44301,7 @@ var ts; if (!propsType) { return undefined; } - if (propsType.flags & 524288) { + if (propsType.flags & 524288 /* Intersection */) { var propsApparentType = []; for (var _i = 0, _a = propsType.types; _i < _a.length; _i++) { var t = _a[_i]; @@ -38267,17 +44311,29 @@ var ts; } return getApparentType(propsType); } + /** + * Get JSX attributes type by trying to resolve openingLikeElement as a stateless function component. + * Return only attributes type of successfully resolved call signature. + * This function assumes that the caller handled other possible element type of the JSX element (e.g. stateful component) + * Unlike tryGetAllJsxStatelessFunctionAttributesType, this function is a default behavior of type-checkers. + * @param openingLikeElement a JSX opening-like element to find attributes type + * @param elementType a type of the opening-like element. This elementType can't be an union type + * @param elemInstanceType an element instance type (the result of newing or invoking this tag) + * @param elementClassType a JSX-ElementClass type. This is a result of looking up ElementClass interface in the JSX global + */ function defaultTryGetJsxStatelessFunctionAttributesType(openingLikeElement, elementType, elemInstanceType, elementClassType) { - ts.Debug.assert(!(elementType.flags & 262144)); + ts.Debug.assert(!(elementType.flags & 262144 /* Union */)); if (!elementClassType || !isTypeAssignableTo(elemInstanceType, elementClassType)) { var jsxStatelessElementType = getJsxStatelessElementTypeAt(openingLikeElement); if (jsxStatelessElementType) { - var callSignature = getResolvedJsxStatelessFunctionSignature(openingLikeElement, elementType, undefined); + // We don't call getResolvedSignature here because we have already resolve the type of JSX Element. + var callSignature = getResolvedJsxStatelessFunctionSignature(openingLikeElement, elementType, /*candidatesOutArray*/ undefined); if (callSignature !== unknownSignature) { var callReturnType = callSignature && getReturnTypeOfSignature(callSignature); var paramType = callReturnType && (callSignature.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(callSignature.parameters[0])); paramType = getApparentTypeOfJsxPropsType(paramType); if (callReturnType && isTypeAssignableTo(callReturnType, jsxStatelessElementType)) { + // Intersect in JSX.IntrinsicAttributes if it exists var intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes, openingLikeElement); if (intrinsicAttributes !== errorType) { paramType = intersectTypes(intrinsicAttributes, paramType); @@ -38289,11 +44345,23 @@ var ts; } return undefined; } + /** + * Get JSX attributes type by trying to resolve openingLikeElement as a stateless function component. + * Return all attributes type of resolved call signature including candidate signatures. + * This function assumes that the caller handled other possible element type of the JSX element. + * This function is a behavior used by language service when looking up completion in JSX element. + * @param openingLikeElement a JSX opening-like element to find attributes type + * @param elementType a type of the opening-like element. This elementType can't be an union type + * @param elemInstanceType an element instance type (the result of newing or invoking this tag) + * @param elementClassType a JSX-ElementClass type. This is a result of looking up ElementClass interface in the JSX global + */ function tryGetAllJsxStatelessFunctionAttributesType(openingLikeElement, elementType, elemInstanceType, elementClassType) { - ts.Debug.assert(!(elementType.flags & 262144)); + ts.Debug.assert(!(elementType.flags & 262144 /* Union */)); if (!elementClassType || !isTypeAssignableTo(elemInstanceType, elementClassType)) { + // Is this is a stateless function component? See if its single signature's return type is assignable to the JSX Element Type var jsxStatelessElementType = getJsxStatelessElementTypeAt(openingLikeElement); if (jsxStatelessElementType) { + // We don't call getResolvedSignature because here we have already resolve the type of JSX Element. var candidatesOutArray = []; getResolvedJsxStatelessFunctionSignature(openingLikeElement, elementType, candidatesOutArray); var result = void 0; @@ -38301,6 +44369,7 @@ var ts; for (var _i = 0, candidatesOutArray_1 = candidatesOutArray; _i < candidatesOutArray_1.length; _i++) { var candidate = candidatesOutArray_1[_i]; var callReturnType = getReturnTypeOfSignature(candidate); + // TODO: GH#18217: callReturnType should always be defined... var paramType = callReturnType && (candidate.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(candidate.parameters[0])); paramType = getApparentTypeOfJsxPropsType(paramType); if (callReturnType && isTypeAssignableTo(callReturnType, jsxStatelessElementType)) { @@ -38309,7 +44378,7 @@ var ts; var attribute = _b[_a]; if (ts.isJsxAttribute(attribute) && isUnhyphenatedJsxName(attribute.name.escapedText) && - !getPropertyOfType(paramType, attribute.name.escapedText)) { + !getPropertyOfType(paramType, attribute.name.escapedText)) { // TODO: GH#18217 shouldBeCandidate = false; break; } @@ -38320,9 +44389,11 @@ var ts; allMatchingAttributesType = intersectTypes(allMatchingAttributesType, paramType); } } + // If we can't find any matching, just return everything. if (!result) { result = allMatchingAttributesType; } + // Intersect in JSX.IntrinsicAttributes if it exists var intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes, openingLikeElement); if (intrinsicAttributes !== errorType) { result = intersectTypes(intrinsicAttributes, result); @@ -38345,34 +44416,62 @@ var ts; return links.resolvedSignatures.get(cacheKey); } links.resolvedSignatures.set(cacheKey, resolvingSignaturesArray); - var signatures = getSignaturesOfType(elementType, 1); + // Resolve the signatures, preferring constructor + var signatures = getSignaturesOfType(elementType, 1 /* Construct */); if (signatures.length === 0) { - signatures = getSignaturesOfType(elementType, 0); + // No construct signatures, try call signatures + signatures = getSignaturesOfType(elementType, 0 /* Call */); if (signatures.length === 0) { + // We found no signatures at all, which is an error if (reportErrors) { error(openingLikeElement.tagName, ts.Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, ts.getTextOfNode(openingLikeElement.tagName)); } return; } } + // Instantiate in context of source type var results = instantiateJsxSignatures(openingLikeElement, signatures); links.resolvedSignatures.set(cacheKey, results); return results; } + /** + * Resolve attributes type of the given opening-like element. The attributes type is a type of attributes associated with the given elementType. + * For instance: + * declare function Foo(attr: { p1: string}): JSX.Element; + * ; // This function will try resolve "Foo" and return an attributes type of "Foo" which is "{ p1: string }" + * + * The function is intended to initially be called from getAttributesTypeFromJsxOpeningLikeElement which already handle JSX-intrinsic-element.. + * This function will try to resolve custom JSX attributes type in following order: string literal, stateless function, and stateful component + * + * @param openingLikeElement a non-intrinsic JSXOPeningLikeElement + * @param shouldIncludeAllStatelessAttributesType a boolean indicating whether to include all attributes types from all stateless function signature + * @param sourceAttributesType Is the attributes type the user passed, and is used to create inferences in the target type if present + * @param elementType an instance type of the given opening-like element. If undefined, the function will check type openinglikeElement's tagname. + * @param elementClassType a JSX-ElementClass type. This is a result of looking up ElementClass interface in the JSX global (imported from react.d.ts) + * @return attributes type if able to resolve the type of node + * anyType if there is no type ElementAttributesProperty or there is an error + * emptyObjectType if there is no "prop" in the element instance type + */ function resolveCustomJsxElementAttributesType(openingLikeElement, shouldIncludeAllStatelessAttributesType, elementType, elementClassType) { - if (elementType.flags & 262144) { + if (elementType.flags & 262144 /* Union */) { var types = elementType.types; return getUnionType(types.map(function (type) { return resolveCustomJsxElementAttributesType(openingLikeElement, shouldIncludeAllStatelessAttributesType, type, elementClassType); - }), 2); + }), 2 /* Subtype */); } + // Shortcircuit any if (isTypeAny(elementType)) { return elementType; } - else if (elementType.flags & 4) { + // If the elemType is a string type, we have to return anyType to prevent an error downstream as we will try to find construct or call signature of the type + else if (elementType.flags & 4 /* String */) { return anyType; } - else if (elementType.flags & 64) { + else if (elementType.flags & 64 /* StringLiteral */) { + // If the elemType is a stringLiteral type, we can then provide a check to make sure that the string literal type is one of the Jsx intrinsic element type + // For example: + // var CustomTag: "h1" = "h1"; + // Hello World var intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements, openingLikeElement); if (intrinsicElementsType !== errorType) { var stringLiteralTypeName = elementType.value; @@ -38380,41 +44479,51 @@ var ts; if (intrinsicProp) { return getTypeOfSymbol(intrinsicProp); } - var indexSignatureType = getIndexTypeOfType(intrinsicElementsType, 0); + var indexSignatureType = getIndexTypeOfType(intrinsicElementsType, 0 /* String */); if (indexSignatureType) { return indexSignatureType; } error(openingLikeElement, ts.Diagnostics.Property_0_does_not_exist_on_type_1, stringLiteralTypeName, "JSX." + JsxNames.IntrinsicElements); } + // If we need to report an error, we already done so here. So just return any to prevent any more error downstream return anyType; } - var instantiatedSignatures = getInstantiatedJsxSignatures(openingLikeElement, elementType, true); + // Get the element instance type (the result of newing or invoking this tag) + var instantiatedSignatures = getInstantiatedJsxSignatures(openingLikeElement, elementType, /*reportErrors*/ true); if (!ts.length(instantiatedSignatures)) { return errorType; } - var elemInstanceType = getUnionType(instantiatedSignatures.map(getReturnTypeOfSignature), 2); + var elemInstanceType = getUnionType(instantiatedSignatures.map(getReturnTypeOfSignature), 2 /* Subtype */); + // If we should include all stateless attributes type, then get all attributes type from all stateless function signature. + // Otherwise get only attributes type from the signature picked by choose-overload logic. var statelessAttributesType = shouldIncludeAllStatelessAttributesType ? tryGetAllJsxStatelessFunctionAttributesType(openingLikeElement, elementType, elemInstanceType, elementClassType) : defaultTryGetJsxStatelessFunctionAttributesType(openingLikeElement, elementType, elemInstanceType, elementClassType); if (statelessAttributesType) { return statelessAttributesType; } + // Issue an error if this return type isn't assignable to JSX.ElementClass if (elementClassType) { checkTypeRelatedTo(elemInstanceType, elementClassType, assignableRelation, openingLikeElement, ts.Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements); } var isJs = ts.isInJavaScriptFile(openingLikeElement); - return getUnionType(instantiatedSignatures.map(function (sig) { return getJsxPropsTypeFromClassType(sig, isJs, openingLikeElement, true); })); + return getUnionType(instantiatedSignatures.map(function (sig) { return getJsxPropsTypeFromClassType(sig, isJs, openingLikeElement, /*reportErrors*/ true); })); } + /** + * Get attributes type of the given intrinsic opening-like Jsx element by resolving the tag name. + * The function is intended to be called from a function which has checked that the opening element is an intrinsic element. + * @param node an intrinsic JSX opening-like element + */ function getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node) { ts.Debug.assert(isJsxIntrinsicIdentifier(node.tagName)); var links = getNodeLinks(node); if (!links.resolvedJsxElementAttributesType) { var symbol = getIntrinsicTagSymbol(node); - if (links.jsxFlags & 1) { + if (links.jsxFlags & 1 /* IntrinsicNamedElement */) { return links.resolvedJsxElementAttributesType = getTypeOfSymbol(symbol); } - else if (links.jsxFlags & 2) { - return links.resolvedJsxElementAttributesType = getIndexInfoOfSymbol(symbol, 0).type; + else if (links.jsxFlags & 2 /* IntrinsicIndexedElement */) { + return links.resolvedJsxElementAttributesType = getIndexInfoOfSymbol(symbol, 0 /* String */).type; } else { return links.resolvedJsxElementAttributesType = errorType; @@ -38422,25 +44531,48 @@ var ts; } return links.resolvedJsxElementAttributesType; } + /** + * Get attributes type of the given custom opening-like JSX element. + * This function is intended to be called from a caller that handles intrinsic JSX element already. + * @param node a custom JSX opening-like element + * @param shouldIncludeAllStatelessAttributesType a boolean value used by language service to get all possible attributes type from an overload stateless function component + */ function getCustomJsxElementAttributesType(node, shouldIncludeAllStatelessAttributesType) { return resolveCustomJsxElementAttributesType(node, shouldIncludeAllStatelessAttributesType, checkExpression(node.tagName), getJsxElementClassTypeAt(node)); } + /** + * Get all possible attributes type, especially from an overload stateless function component, of the given JSX opening-like element. + * This function is called by language service (see: completions-tryGetGlobalSymbols). + * @param node a JSX opening-like element to get attributes type for + */ function getAllAttributesTypeFromJsxOpeningLikeElement(node) { if (isJsxIntrinsicIdentifier(node.tagName)) { return getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node); } else { - return getCustomJsxElementAttributesType(node, true); + // Because in language service, the given JSX opening-like element may be incomplete and therefore, + // we can't resolve to exact signature if the element is a stateless function component so the best thing to do is return all attributes type from all overloads. + return getCustomJsxElementAttributesType(node, /*shouldIncludeAllStatelessAttributesType*/ true); } } + /** + * Get the attributes type, which indicates the attributes that are valid on the given JSXOpeningLikeElement. + * @param node a JSXOpeningLikeElement node + * @return an attributes type of the given node + */ function getAttributesTypeFromJsxOpeningLikeElement(node) { if (isJsxIntrinsicIdentifier(node.tagName)) { return getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node); } else { - return getCustomJsxElementAttributesType(node, false); + return getCustomJsxElementAttributesType(node, /*shouldIncludeAllStatelessAttributesType*/ false); } } + /** + * Given a JSX attribute, returns the symbol for the corresponds property + * of the element attributes type. Will return unknownSymbol for attributes + * that have no matching element attributes type property. + */ function getJsxAttributePropertySymbol(attrib) { var attributesType = getAttributesTypeFromJsxOpeningLikeElement(attrib.parent.parent); var prop = getPropertyOfType(attributesType, attrib.name.escapedText); @@ -38461,12 +44593,16 @@ var ts; return getUnionType([jsxElementType, nullType]); } } + /** + * Returns all the properties of the Jsx.IntrinsicElements interface + */ function getJsxIntrinsicTagNamesAt(location) { var intrinsics = getJsxType(JsxNames.IntrinsicElements, location); return intrinsics ? getPropertiesOfType(intrinsics) : ts.emptyArray; } function checkJsxPreconditions(errorNode) { - if ((compilerOptions.jsx || 0) === 0) { + // Preconditions for using JSX + if ((compilerOptions.jsx || 0 /* None */) === 0 /* None */) { error(errorNode, ts.Diagnostics.Cannot_use_JSX_unless_the_jsx_flag_is_provided); } if (getJsxElementTypeAt(errorNode) === undefined) { @@ -38481,13 +44617,18 @@ var ts; checkGrammarJsxElement(node); } checkJsxPreconditions(node); - var reactRefErr = diagnostics && compilerOptions.jsx === 2 ? ts.Diagnostics.Cannot_find_name_0 : undefined; + // The reactNamespace/jsxFactory's root symbol should be marked as 'used' so we don't incorrectly elide its import. + // And if there is no reactNamespace/jsxFactory's symbol in scope when targeting React emit, we should issue an error. + var reactRefErr = diagnostics && compilerOptions.jsx === 2 /* React */ ? ts.Diagnostics.Cannot_find_name_0 : undefined; var reactNamespace = getJsxNamespace(node); var reactLocation = isNodeOpeningLikeElement ? node.tagName : node; - var reactSym = resolveName(reactLocation, reactNamespace, 67216319, reactRefErr, reactNamespace, true); + var reactSym = resolveName(reactLocation, reactNamespace, 67216319 /* Value */, reactRefErr, reactNamespace, /*isUse*/ true); if (reactSym) { - reactSym.isReferenced = 67108863; - if (reactSym.flags & 2097152 && !isConstEnumOrConstEnumOnlyModule(resolveAlias(reactSym))) { + // Mark local symbol as referenced here because it might not have been marked + // if jsx emit was not react as there wont be error being emitted + reactSym.isReferenced = 67108863 /* All */; + // If react symbol is alias, mark it as refereced + if (reactSym.flags & 2097152 /* Alias */ && !isConstEnumOrConstEnumOnlyModule(resolveAlias(reactSym))) { markAliasSymbolAsReferenced(reactSym); } } @@ -38498,17 +44639,31 @@ var ts; checkJsxChildren(node.parent); } } + /** + * Check if a property with the given name is known anywhere in the given type. In an object type, a property + * is considered known if + * 1. the object type is empty and the check is for assignability, or + * 2. if the object type has index signatures, or + * 3. if the property is actually declared in the object type + * (this means that 'toString', for example, is not usually a known property). + * 4. In a union or intersection type, + * a property is considered known if it is known in any constituent type. + * @param targetType a type to search a given name in + * @param name a property name to search + * @param isComparingJsxAttributes a boolean flag indicating whether we are searching in JsxAttributesType + */ function isKnownProperty(targetType, name, isComparingJsxAttributes) { - if (targetType.flags & 131072) { + if (targetType.flags & 131072 /* Object */) { var resolved = resolveStructuredTypeMembers(targetType); if (resolved.stringIndexInfo || resolved.numberIndexInfo && isNumericLiteralName(name) || getPropertyOfObjectType(targetType, name) || isComparingJsxAttributes && !isUnhyphenatedJsxName(name)) { + // For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known. return true; } } - else if (targetType.flags & 786432) { + else if (targetType.flags & 786432 /* UnionOrIntersection */) { for (var _i = 0, _a = targetType.types; _i < _a.length; _i++) { var t = _a[_i]; if (isKnownProperty(t, name, isComparingJsxAttributes)) { @@ -38518,12 +44673,30 @@ var ts; } return false; } + /** + * Check whether the given attributes of JSX opening-like element is assignable to the tagName attributes. + * Get the attributes type of the opening-like element through resolving the tagName, "target attributes" + * Check assignablity between given attributes property, "source attributes", and the "target attributes" + * @param openingLikeElement an opening-like JSX element to check its JSXAttributes + */ function checkJsxAttributesAssignableToTagNameAttributes(openingLikeElement, checkMode) { + // The function involves following steps: + // 1. Figure out expected attributes type by resolving tagName of the JSX opening-like element, targetAttributesType. + // During these steps, we will try to resolve the tagName as intrinsic name, stateless function, stateful component (in the order) + // 2. Solved JSX attributes type given by users, sourceAttributesType, which is by resolving "attributes" property of the JSX opening-like element. + // 3. Check if the two are assignable to each other + // targetAttributesType is a type of an attribute from resolving tagName of an opening-like JSX element. var targetAttributesType = isJsxIntrinsicIdentifier(openingLikeElement.tagName) ? getIntrinsicAttributesTypeFromJsxOpeningLikeElement(openingLikeElement) : - getCustomJsxElementAttributesType(openingLikeElement, false); + getCustomJsxElementAttributesType(openingLikeElement, /*shouldIncludeAllStatelessAttributesType*/ false); + // sourceAttributesType is a type of an attributes properties. + // i.e
+ // attr1 and attr2 are treated as JSXAttributes attached in the JsxOpeningLikeElement as "attributes". var sourceAttributesType = createJsxAttributesTypeFromAttributesProperty(openingLikeElement, checkMode); + // Check if sourceAttributesType assignable to targetAttributesType though this check will allow excess properties var isSourceAttributeTypeAssignableToTarget = isTypeAssignableTo(sourceAttributesType, targetAttributesType); + // After we check for assignability, we will do another pass to check that all explicitly specified attributes have correct name corresponding in targetAttributeType. + // This will allow excess properties in spread type as it is very common pattern to spread outer attributes into React component in its render method. if (isSourceAttributeTypeAssignableToTarget && !isTypeAny(sourceAttributesType) && !isTypeAny(targetAttributesType)) { for (var _i = 0, _a = openingLikeElement.attributes.properties; _i < _a.length; _i++) { var attribute = _a[_i]; @@ -38532,13 +44705,15 @@ var ts; } var attrName = attribute.name; var isNotIgnoredJsxProperty = (isUnhyphenatedJsxName(ts.idText(attrName)) || !!(getPropertyOfType(targetAttributesType, attrName.escapedText))); - if (isNotIgnoredJsxProperty && !isKnownProperty(targetAttributesType, attrName.escapedText, true)) { + if (isNotIgnoredJsxProperty && !isKnownProperty(targetAttributesType, attrName.escapedText, /*isComparingJsxAttributes*/ true)) { error(attribute, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.idText(attrName), typeToString(targetAttributesType)); + // We break here so that errors won't be cascading break; } } } else if (!isSourceAttributeTypeAssignableToTarget) { + // Assignability failure - check each prop individually, and if that fails, fall back on the bad error span if (ts.length(openingLikeElement.attributes.properties)) { var reportedError = false; var _loop_8 = function (prop) { @@ -38547,8 +44722,9 @@ var ts; var name = ts.idText(prop.name); var sourcePropType = getIndexedAccessType(sourceAttributesType, getLiteralType(name)); var targetPropType = getIndexedAccessType(targetAttributesType, getLiteralType(name)); - var rootChain = function () { return ts.chainDiagnosticMessages(undefined, ts.Diagnostics.Types_of_property_0_are_incompatible, name); }; - if (!checkTypeAssignableTo(sourcePropType, targetPropType, prop, undefined, rootChain)) { + var rootChain = function () { return ts.chainDiagnosticMessages( + /*details*/ undefined, ts.Diagnostics.Types_of_property_0_are_incompatible, name); }; + if (!checkTypeAssignableTo(sourcePropType, targetPropType, prop, /*headMessage*/ undefined, rootChain)) { reportedError = true; } }; @@ -38560,6 +44736,7 @@ var ts; return; } } + // Report fallback error on just the component name checkTypeAssignableTo(sourceAttributesType, targetAttributesType, openingLikeElement.tagName); } } @@ -38575,56 +44752,86 @@ var ts; return errorType; } } + // If a symbol is a synthesized symbol with no value declaration, we assume it is a property. Example of this are the synthesized + // '.prototype' property as well as synthesized tuple index properties. function getDeclarationKindFromSymbol(s) { - return s.valueDeclaration ? s.valueDeclaration.kind : 152; + return s.valueDeclaration ? s.valueDeclaration.kind : 152 /* PropertyDeclaration */; } function getDeclarationNodeFlagsFromSymbol(s) { return s.valueDeclaration ? ts.getCombinedNodeFlags(s.valueDeclaration) : 0; } + /** + * Return whether this symbol is a member of a prototype somewhere + * Note that this is not tracked well within the compiler, so the answer may be incorrect. + */ function isPrototypeProperty(symbol) { - if (symbol.flags & 8192 || ts.getCheckFlags(symbol) & 4) { + if (symbol.flags & 8192 /* Method */ || ts.getCheckFlags(symbol) & 4 /* SyntheticMethod */) { return true; } if (ts.isInJavaScriptFile(symbol.valueDeclaration)) { var parent = symbol.valueDeclaration.parent; return parent && ts.isBinaryExpression(parent) && - ts.getSpecialPropertyAssignmentKind(parent) === 3; + ts.getSpecialPropertyAssignmentKind(parent) === 3 /* PrototypeProperty */; } } + /** + * Check whether the requested property access is valid. + * Returns true if node is a valid property access, and false otherwise. + * @param node The node to be checked. + * @param left The left hand side of the property access (e.g.: the super in `super.foo`). + * @param type The type of left. + * @param prop The symbol for the right hand side of the property access. + */ function checkPropertyAccessibility(node, left, type, prop) { var flags = ts.getDeclarationModifierFlagsFromSymbol(prop); - var errorNode = node.kind === 185 || node.kind === 232 ? + var errorNode = node.kind === 185 /* PropertyAccessExpression */ || node.kind === 232 /* VariableDeclaration */ ? node.name : - node.kind === 179 ? + node.kind === 179 /* ImportType */ ? node : node.right; - if (ts.getCheckFlags(prop) & 256) { + if (ts.getCheckFlags(prop) & 256 /* ContainsPrivate */) { + // Synthetic property with private constituent property error(errorNode, ts.Diagnostics.Property_0_has_conflicting_declarations_and_is_inaccessible_in_type_1, symbolToString(prop), typeToString(type)); return false; } - if (left.kind === 97) { - if (languageVersion < 2) { + if (left.kind === 97 /* SuperKeyword */) { + // TS 1.0 spec (April 2014): 4.8.2 + // - In a constructor, instance member function, instance member accessor, or + // instance member variable initializer where this references a derived class instance, + // a super property access is permitted and must specify a public instance member function of the base class. + // - In a static member function or static member accessor + // where this references the constructor function object of a derived class, + // a super property access is permitted and must specify a public static member function of the base class. + if (languageVersion < 2 /* ES2015 */) { if (symbolHasNonMethodDeclaration(prop)) { error(errorNode, ts.Diagnostics.Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword); return false; } } - if (flags & 128) { + if (flags & 128 /* Abstract */) { + // A method cannot be accessed in a super property access if the method is abstract. + // This error could mask a private property access error. But, a member + // cannot simultaneously be private and abstract, so this will trigger an + // additional error elsewhere. error(errorNode, ts.Diagnostics.Abstract_method_0_in_class_1_cannot_be_accessed_via_super_expression, symbolToString(prop), typeToString(getDeclaringClass(prop))); return false; } } - if ((flags & 128) && ts.isThisProperty(node) && symbolHasNonMethodDeclaration(prop)) { + // Referencing abstract properties within their own constructors is not allowed + if ((flags & 128 /* Abstract */) && ts.isThisProperty(node) && symbolHasNonMethodDeclaration(prop)) { var declaringClassDeclaration = ts.getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)); if (declaringClassDeclaration && isNodeWithinConstructorOfClass(node, declaringClassDeclaration)) { - error(errorNode, ts.Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, symbolToString(prop), ts.getTextOfIdentifierOrLiteral(declaringClassDeclaration.name)); + error(errorNode, ts.Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, symbolToString(prop), ts.getTextOfIdentifierOrLiteral(declaringClassDeclaration.name)); // TODO: GH#18217 return false; } } - if (!(flags & 24)) { + // Public properties are otherwise accessible. + if (!(flags & 24 /* NonPublicAccessibilityModifier */)) { return true; } - if (flags & 8) { + // Property is known to be private or protected at this point + // Private property is accessible if the property is within the declaring class + if (flags & 8 /* Private */) { var declaringClassDeclaration = ts.getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)); if (!isNodeWithinClass(node, declaringClassDeclaration)) { error(errorNode, ts.Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, symbolToString(prop), typeToString(getDeclaringClass(prop))); @@ -38632,27 +44839,36 @@ var ts; } return true; } - if (left.kind === 97) { + // Property is known to be protected at this point + // All protected properties of a supertype are accessible in a super access + if (left.kind === 97 /* SuperKeyword */) { return true; } + // Find the first enclosing class that has the declaring classes of the protected constituents + // of the property as base classes var enclosingClass = forEachEnclosingClass(node, function (enclosingDeclaration) { var enclosingClass = getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingDeclaration)); return isClassDerivedFromDeclaringClasses(enclosingClass, prop) ? enclosingClass : undefined; }); + // A protected property is accessible if the property is within the declaring class or classes derived from it if (!enclosingClass) { + // allow PropertyAccessibility if context is in function with this parameter + // static member access is disallow var thisParameter = void 0; - if (flags & 32 || !(thisParameter = getThisParameterFromNodeContext(node)) || !thisParameter.type) { + if (flags & 32 /* Static */ || !(thisParameter = getThisParameterFromNodeContext(node)) || !thisParameter.type) { error(errorNode, ts.Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, symbolToString(prop), typeToString(getDeclaringClass(prop) || type)); return false; } var thisType = getTypeFromTypeNode(thisParameter.type); - enclosingClass = ((thisType.flags & 65536) ? getConstraintFromTypeParameter(thisType) : thisType); + enclosingClass = ((thisType.flags & 65536 /* TypeParameter */) ? getConstraintFromTypeParameter(thisType) : thisType); } - if (flags & 32) { + // No further restrictions for static properties + if (flags & 32 /* Static */) { return true; } - if (type.flags & 65536) { - type = type.isThisType ? getConstraintOfTypeParameter(type) : getBaseConstraintOfType(type); + if (type.flags & 65536 /* TypeParameter */) { + // get the original type -- represented as the type constraint of the 'this' type + type = type.isThisType ? getConstraintOfTypeParameter(type) : getBaseConstraintOfType(type); // TODO: GH#18217 Use a different variable that's allowed to be undefined } if (!type || !hasBaseType(type, enclosingClass)) { error(errorNode, ts.Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1, symbolToString(prop), typeToString(enclosingClass)); @@ -38661,31 +44877,31 @@ var ts; return true; } function getThisParameterFromNodeContext(node) { - var thisContainer = ts.getThisContainer(node, false); + var thisContainer = ts.getThisContainer(node, /* includeArrowFunctions */ false); return thisContainer && ts.isFunctionLike(thisContainer) ? ts.getThisParameter(thisContainer) : undefined; } function symbolHasNonMethodDeclaration(symbol) { return forEachProperty(symbol, function (prop) { var propKind = getDeclarationKindFromSymbol(prop); - return propKind !== 154 && propKind !== 153; + return propKind !== 154 /* MethodDeclaration */ && propKind !== 153 /* MethodSignature */; }); } function checkNonNullExpression(node, nullDiagnostic, undefinedDiagnostic, nullOrUndefinedDiagnostic) { return checkNonNullType(checkExpression(node), node, nullDiagnostic, undefinedDiagnostic, nullOrUndefinedDiagnostic); } function checkNonNullType(type, node, nullDiagnostic, undefinedDiagnostic, nullOrUndefinedDiagnostic) { - if (type.flags & 2) { + if (type.flags & 2 /* Unknown */) { error(node, ts.Diagnostics.Object_is_of_type_unknown); return errorType; } - var kind = (strictNullChecks ? getFalsyFlags(type) : type.flags) & 24576; + var kind = (strictNullChecks ? getFalsyFlags(type) : type.flags) & 24576 /* Nullable */; if (kind) { - error(node, kind & 8192 ? kind & 16384 ? + error(node, kind & 8192 /* Undefined */ ? kind & 16384 /* Null */ ? (nullOrUndefinedDiagnostic || ts.Diagnostics.Object_is_possibly_null_or_undefined) : (undefinedDiagnostic || ts.Diagnostics.Object_is_possibly_undefined) : (nullDiagnostic || ts.Diagnostics.Object_is_possibly_null)); var t = getNonNullableType(type); - return t.flags & (24576 | 32768) ? errorType : t; + return t.flags & (24576 /* Nullable */ | 32768 /* Never */) ? errorType : t; } return type; } @@ -38712,10 +44928,10 @@ var ts; markAliasReferenced(parentSymbol, node); } if (!prop) { - var indexInfo = getIndexInfoOfType(apparentType, 0); + var indexInfo = getIndexInfoOfType(apparentType, 0 /* String */); if (!(indexInfo && indexInfo.type)) { if (right.escapedText && !checkAndReportErrorForExtendingInterface(node)) { - reportNonexistentProperty(right, leftType.flags & 65536 && leftType.isThisType ? apparentType : leftType); + reportNonexistentProperty(right, leftType.flags & 65536 /* TypeParameter */ && leftType.isThisType ? apparentType : leftType); } return errorType; } @@ -38726,7 +44942,7 @@ var ts; } else { checkPropertyNotUsedBeforeDeclaration(prop, node, right); - markPropertyAsReferenced(prop, node, left.kind === 99); + markPropertyAsReferenced(prop, node, left.kind === 99 /* ThisKeyword */); getNodeLinks(node).resolvedSymbol = prop; checkPropertyAccessibility(node, left, apparentType, prop); if (assignmentKind) { @@ -38737,24 +44953,32 @@ var ts; } propType = getConstraintForLocation(getTypeOfSymbol(prop), node); } - if (node.kind !== 185 || - assignmentKind === 1 || - prop && !(prop.flags & (3 | 4 | 98304)) && !(prop.flags & 8192 && propType.flags & 262144)) { + // Only compute control flow type if this is a property access expression that isn't an + // assignment target, and the referenced property was declared as a variable, property, + // accessor, or optional method. + if (node.kind !== 185 /* PropertyAccessExpression */ || + assignmentKind === 1 /* Definite */ || + prop && !(prop.flags & (3 /* Variable */ | 4 /* Property */ | 98304 /* Accessor */)) && !(prop.flags & 8192 /* Method */ && propType.flags & 262144 /* Union */)) { return propType; } + // If strict null checks and strict property initialization checks are enabled, if we have + // a this.xxx property access, if the property is an instance property without an initializer, + // and if we are in a constructor of the same class as the property declaration, assume that + // the property is uninitialized at the top of the control flow. var assumeUninitialized = false; - if (strictNullChecks && strictPropertyInitialization && left.kind === 99) { + if (strictNullChecks && strictPropertyInitialization && left.kind === 99 /* ThisKeyword */) { var declaration = prop && prop.valueDeclaration; if (declaration && isInstancePropertyWithoutInitializer(declaration)) { var flowContainer = getControlFlowContainer(node); - if (flowContainer.kind === 155 && flowContainer.parent === declaration.parent) { + if (flowContainer.kind === 155 /* Constructor */ && flowContainer.parent === declaration.parent) { assumeUninitialized = true; } } } var flowType = getFlowTypeOfReference(node, propType, assumeUninitialized ? getOptionalType(propType) : propType); - if (assumeUninitialized && !(getFalsyFlags(propType) & 8192) && getFalsyFlags(flowType) & 8192) { - error(right, ts.Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(prop)); + if (assumeUninitialized && !(getFalsyFlags(propType) & 8192 /* Undefined */) && getFalsyFlags(flowType) & 8192 /* Undefined */) { + error(right, ts.Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(prop)); // TODO: GH#18217 + // Return the declared type to reduce follow-on errors return propType; } return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType; @@ -38769,9 +44993,9 @@ var ts; && !isPropertyDeclaredInAncestorClass(prop)) { error(right, ts.Diagnostics.Block_scoped_variable_0_used_before_its_declaration, ts.idText(right)); } - else if (valueDeclaration.kind === 235 && - node.parent.kind !== 162 && - !(valueDeclaration.flags & 4194304) && + else if (valueDeclaration.kind === 235 /* ClassDeclaration */ && + node.parent.kind !== 162 /* TypeReference */ && + !(valueDeclaration.flags & 4194304 /* Ambient */) && !isBlockScopedNameDeclaredBeforeUse(valueDeclaration, right)) { error(right, ts.Diagnostics.Class_0_used_before_its_declaration, ts.idText(right)); } @@ -38779,17 +45003,22 @@ var ts; function isInPropertyInitializer(node) { return !!ts.findAncestor(node, function (node) { switch (node.kind) { - case 152: + case 152 /* PropertyDeclaration */: return true; - case 270: + case 270 /* PropertyAssignment */: + // We might be in `a = { b: this.b }`, so keep looking. See `tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts`. return false; default: return ts.isExpressionNode(node) ? false : "quit"; } }); } + /** + * It's possible that "prop.valueDeclaration" is a local declaration, but the property was also declared in a superclass. + * In that case we won't consider it used before its declaration, because it gets its value from the superclass' declaration. + */ function isPropertyDeclaredInAncestorClass(prop) { - if (!(prop.parent.flags & 32)) { + if (!(prop.parent.flags & 32 /* Class */)) { return false; } var classType = getTypeOfSymbol(prop.parent); @@ -38813,7 +45042,7 @@ var ts; } function reportNonexistentProperty(propNode, containingType) { var errorInfo; - if (containingType.flags & 262144 && !(containingType.flags & 32764)) { + if (containingType.flags & 262144 /* Union */ && !(containingType.flags & 32764 /* Primitive */)) { for (var _i = 0, _a = containingType.types; _i < _a.length; _i++) { var subtype = _a[_i]; if (!getPropertyOfType(subtype, propNode.escapedText)) { @@ -38838,22 +45067,40 @@ var ts; diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(propNode, errorInfo)); } function getSuggestionForNonexistentProperty(node, containingType) { - var suggestion = getSpellingSuggestionForName(ts.idText(node), getPropertiesOfType(containingType), 67216319); + var suggestion = getSpellingSuggestionForName(ts.idText(node), getPropertiesOfType(containingType), 67216319 /* Value */); return suggestion && ts.symbolName(suggestion); } function getSuggestionForNonexistentSymbol(location, outerName, meaning) { ts.Debug.assert(outerName !== undefined, "outername should always be defined"); - var result = resolveNameHelper(location, outerName, meaning, undefined, outerName, false, false, function (symbols, name, meaning) { + var result = resolveNameHelper(location, outerName, meaning, /*nameNotFoundMessage*/ undefined, outerName, /*isUse*/ false, /*excludeGlobals*/ false, function (symbols, name, meaning) { ts.Debug.assertEqual(outerName, name, "name should equal outerName"); var symbol = getSymbol(symbols, name, meaning); + // Sometimes the symbol is found when location is a return type of a function: `typeof x` and `x` is declared in the body of the function + // So the table *contains* `x` but `x` isn't actually in scope. + // However, resolveNameHelper will continue and call this callback again, so we'll eventually get a correct suggestion. return symbol || getSpellingSuggestionForName(ts.unescapeLeadingUnderscores(name), ts.arrayFrom(symbols.values()), meaning); }); return result && ts.symbolName(result); } function getSuggestionForNonexistentModule(name, targetModule) { - var suggestion = targetModule.exports && getSpellingSuggestionForName(ts.idText(name), getExportsOfModuleAsArray(targetModule), 2623475); + var suggestion = targetModule.exports && getSpellingSuggestionForName(ts.idText(name), getExportsOfModuleAsArray(targetModule), 2623475 /* ModuleMember */); return suggestion && ts.symbolName(suggestion); } + /** + * Given a name and a list of symbols whose names are *not* equal to the name, return a spelling suggestion if there is one that is close enough. + * Names less than length 3 only check for case-insensitive equality, not levenshtein distance. + * + * If there is a candidate that's the same except for case, return that. + * If there is a candidate that's within one edit of the name, return that. + * Otherwise, return the candidate with the smallest Levenshtein distance, + * except for candidates: + * * With no name + * * Whose meaning doesn't match the `meaning` parameter. + * * Whose length differs from the target name by more than 0.34 of the length of the name. + * * Whose levenshtein distance is more than 0.4 of the length of the name + * (0.4 allows 1 substitution/transposition for every 5 characters, + * and 1 insertion/deletion at 3 characters) + */ function getSpellingSuggestionForName(name, symbols, meaning) { return ts.getSpellingSuggestion(name, symbols, getCandidateName); function getCandidateName(candidate) { @@ -38862,37 +45109,38 @@ var ts; } } function markPropertyAsReferenced(prop, nodeForCheckWriteOnly, isThisAccess) { - if (!prop || !(prop.flags & 106500) || !prop.valueDeclaration || !ts.hasModifier(prop.valueDeclaration, 8)) { + if (!prop || !(prop.flags & 106500 /* ClassMember */) || !prop.valueDeclaration || !ts.hasModifier(prop.valueDeclaration, 8 /* Private */)) { return; } - if (nodeForCheckWriteOnly && ts.isWriteOnlyAccess(nodeForCheckWriteOnly) && !(prop.flags & 65536 && !(prop.flags & 32768))) { + if (nodeForCheckWriteOnly && ts.isWriteOnlyAccess(nodeForCheckWriteOnly) && !(prop.flags & 65536 /* SetAccessor */ && !(prop.flags & 32768 /* GetAccessor */))) { return; } if (isThisAccess) { + // Find any FunctionLikeDeclaration because those create a new 'this' binding. But this should only matter for methods (or getters/setters). var containingMethod = ts.findAncestor(nodeForCheckWriteOnly, ts.isFunctionLikeDeclaration); if (containingMethod && containingMethod.symbol === prop) { return; } } - (ts.getCheckFlags(prop) & 1 ? getSymbolLinks(prop).target : prop).isReferenced = 67108863; + (ts.getCheckFlags(prop) & 1 /* Instantiated */ ? getSymbolLinks(prop).target : prop).isReferenced = 67108863 /* All */; } function isValidPropertyAccess(node, propertyName) { switch (node.kind) { - case 185: + case 185 /* PropertyAccessExpression */: return isValidPropertyAccessWithType(node, node.expression, propertyName, getWidenedType(checkExpression(node.expression))); - case 146: + case 146 /* QualifiedName */: return isValidPropertyAccessWithType(node, node.left, propertyName, getWidenedType(checkExpression(node.left))); - case 179: + case 179 /* ImportType */: return isValidPropertyAccessWithType(node, node, propertyName, getTypeFromTypeNode(node)); } } function isValidPropertyAccessForCompletions(node, type, property) { - return isValidPropertyAccessWithType(node, node.kind === 179 ? node : node.expression, property.escapedName, type) - && (!(property.flags & 8192) || isValidMethodAccess(property, type)); + return isValidPropertyAccessWithType(node, node.kind === 179 /* ImportType */ ? node : node.expression, property.escapedName, type) + && (!(property.flags & 8192 /* Method */) || isValidMethodAccess(property, type)); } function isValidMethodAccess(method, actualThisType) { var propType = getTypeOfPropertyOfType(actualThisType, method.escapedName); - var signatures = getSignaturesOfType(getNonNullableType(propType), 0); + var signatures = getSignaturesOfType(getNonNullableType(propType), 0 /* Call */); ts.Debug.assert(signatures.length !== 0); return signatures.some(function (sig) { var signatureThisType = getThisTypeOfSignature(sig); @@ -38903,7 +45151,7 @@ var ts; if (!sig.typeParameters) { return signatureThisType; } - var context = createInferenceContext(sig.typeParameters, sig, 0); + var context = createInferenceContext(sig.typeParameters, sig, 0 /* None */); inferTypes(context.inferences, actualThisType, signatureThisType); return instantiateType(signatureThisType, createSignatureTypeMapper(sig, getInferredTypes(context))); } @@ -38913,33 +45161,44 @@ var ts; } var prop = getPropertyOfType(type, propertyName); return prop ? checkPropertyAccessibility(node, left, type, prop) - : ts.isInJavaScriptFile(node) && (type.flags & 262144) !== 0 && type.types.some(function (elementType) { return isValidPropertyAccessWithType(node, left, propertyName, elementType); }); + // In js files properties of unions are allowed in completion + : ts.isInJavaScriptFile(node) && (type.flags & 262144 /* Union */) !== 0 && type.types.some(function (elementType) { return isValidPropertyAccessWithType(node, left, propertyName, elementType); }); } + /** + * Return the symbol of the for-in variable declared or referenced by the given for-in statement. + */ function getForInVariableSymbol(node) { var initializer = node.initializer; - if (initializer.kind === 233) { + if (initializer.kind === 233 /* VariableDeclarationList */) { var variable = initializer.declarations[0]; if (variable && !ts.isBindingPattern(variable.name)) { return getSymbolOfNode(variable); } } - else if (initializer.kind === 71) { + else if (initializer.kind === 71 /* Identifier */) { return getResolvedSymbol(initializer); } return undefined; } + /** + * Return true if the given type is considered to have numeric property names. + */ function hasNumericPropertyNames(type) { - return getIndexTypeOfType(type, 1) && !getIndexTypeOfType(type, 0); + return getIndexTypeOfType(type, 1 /* Number */) && !getIndexTypeOfType(type, 0 /* String */); } + /** + * Return true if given node is an expression consisting of an identifier (possibly parenthesized) + * that references a for-in variable for an object with numeric property names. + */ function isForInVariableForNumericPropertyNames(expr) { var e = ts.skipParentheses(expr); - if (e.kind === 71) { + if (e.kind === 71 /* Identifier */) { var symbol = getResolvedSymbol(e); - if (symbol.flags & 3) { + if (symbol.flags & 3 /* Variable */) { var child = expr; var node = expr.parent; while (node) { - if (node.kind === 221 && + if (node.kind === 221 /* ForInStatement */ && child === node.statement && getForInVariableSymbol(node) === symbol && hasNumericPropertyNames(getTypeOfExpression(node.expression))) { @@ -38957,7 +45216,7 @@ var ts; var indexExpression = node.argumentExpression; if (!indexExpression) { var sourceFile = ts.getSourceFileOfNode(node); - if (node.parent.kind === 188 && node.parent.expression === node) { + if (node.parent.kind === 188 /* NewExpression */ && node.parent.expression === node) { var start = ts.skipTrivia(sourceFile.text, node.expression.end); var end = node.end; grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead); @@ -38973,7 +45232,7 @@ var ts; if (objectType === errorType || objectType === silentNeverType) { return objectType; } - if (isConstEnumObjectType(objectType) && indexExpression.kind !== 9) { + if (isConstEnumObjectType(objectType) && indexExpression.kind !== 9 /* StringLiteral */) { error(indexExpression, ts.Diagnostics.A_const_enum_member_can_only_be_accessed_using_a_string_literal); return errorType; } @@ -38981,24 +45240,29 @@ var ts; } function checkThatExpressionIsProperSymbolReference(expression, expressionType, reportError) { if (expressionType === errorType) { + // There is already an error, so no need to report one. return false; } if (!ts.isWellKnownSymbolSyntactically(expression)) { return false; } - if ((expressionType.flags & 3072) === 0) { + // Make sure the property type is the primitive symbol type + if ((expressionType.flags & 3072 /* ESSymbolLike */) === 0) { if (reportError) { error(expression, ts.Diagnostics.A_computed_property_name_of_the_form_0_must_be_of_type_symbol, ts.getTextOfNode(expression)); } return false; } + // The name is Symbol., so make sure Symbol actually resolves to the + // global Symbol object var leftHandSide = expression.expression; var leftHandSideSymbol = getResolvedSymbol(leftHandSide); if (!leftHandSideSymbol) { return false; } - var globalESSymbol = getGlobalESSymbolConstructorSymbol(true); + var globalESSymbol = getGlobalESSymbolConstructorSymbol(/*reportErrors*/ true); if (!globalESSymbol) { + // Already errored when we tried to look up the symbol return false; } if (leftHandSideSymbol !== globalESSymbol) { @@ -39010,16 +45274,19 @@ var ts; return true; } function callLikeExpressionMayHaveTypeArguments(node) { + // TODO: Also include tagged templates (https://github.com/Microsoft/TypeScript/issues/11947) return ts.isCallOrNewExpression(node); } function resolveUntypedCall(node) { if (callLikeExpressionMayHaveTypeArguments(node)) { + // Check type arguments even though we will give an error that untyped calls may not accept type arguments. + // This gets us diagnostics for the type arguments and marks them as referenced. ts.forEach(node.typeArguments, checkSourceElement); } - if (node.kind === 189) { + if (node.kind === 189 /* TaggedTemplateExpression */) { checkExpression(node.template); } - else if (node.kind !== 150) { + else if (node.kind !== 150 /* Decorator */) { ts.forEach(node.arguments, function (argument) { checkExpression(argument); }); @@ -39030,6 +45297,14 @@ var ts; resolveUntypedCall(node); return unknownSignature; } + // Re-order candidate signatures into the result array. Assumes the result array to be empty. + // The candidate list orders groups in reverse, but within a group signatures are kept in declaration order + // A nit here is that we reorder only signatures that belong to the same symbol, + // so order how inherited signatures are processed is still preserved. + // interface A { (x: string): void } + // interface B extends A { (x: 'foo'): string } + // const b: B; + // b('foo') // <- here overloads should be processed as [(x:'foo'): string, (x: string): void] function reorderCandidates(signatures, result) { var lastParent; var lastSymbol; @@ -39052,13 +45327,20 @@ var ts; } } else { + // current declaration belongs to a different symbol + // set cutoffIndex so re-orderings in the future won't change result set from 0 to cutoffIndex index = cutoffIndex = result.length; lastParent = parent; } lastSymbol = symbol; + // specialized signatures always need to be placed before non-specialized signatures regardless + // of the cutoff position; see GH#1133 if (signature.hasLiteralTypes) { specializedIndex++; spliceIndex = specializedIndex; + // The cutoff index always needs to be greater than or equal to the specialized signature index + // in order to prevent non-specialized signatures from being added before a specialized + // signature. cutoffIndex++; } else { @@ -39070,7 +45352,7 @@ var ts; function getSpreadArgumentIndex(args) { for (var i = 0; i < args.length; i++) { var arg = args[i]; - if (arg && arg.kind === 204) { + if (arg && arg.kind === 204 /* SpreadElement */) { return i; } } @@ -39078,36 +45360,46 @@ var ts; } function hasCorrectArity(node, args, signature, signatureHelpTrailingComma) { if (signatureHelpTrailingComma === void 0) { signatureHelpTrailingComma = false; } - var argCount; - var typeArguments; - var callIsIncomplete = false; + var argCount; // Apparent number of arguments we will have in this call + var typeArguments; // Type arguments (undefined if none) + var callIsIncomplete = false; // In incomplete call we want to be lenient when we have too few arguments var spreadArgIndex = -1; if (ts.isJsxOpeningLikeElement(node)) { + // The arity check will be done in "checkApplicableSignatureForJsxOpeningLikeElement". return true; } - if (node.kind === 189) { + if (node.kind === 189 /* TaggedTemplateExpression */) { + // Even if the call is incomplete, we'll have a missing expression as our last argument, + // so we can say the count is just the arg list length argCount = args.length; typeArguments = node.typeArguments; - if (node.template.kind === 202) { - var lastSpan = ts.last(node.template.templateSpans); + if (node.template.kind === 202 /* TemplateExpression */) { + // If a tagged template expression lacks a tail literal, the call is incomplete. + // Specifically, a template only can end in a TemplateTail or a Missing literal. + var lastSpan = ts.last(node.template.templateSpans); // we should always have at least one span. callIsIncomplete = ts.nodeIsMissing(lastSpan.literal) || !!lastSpan.literal.isUnterminated; } else { + // If the template didn't end in a backtick, or its beginning occurred right prior to EOF, + // then this might actually turn out to be a TemplateHead in the future; + // so we consider the call to be incomplete. var templateLiteral = node.template; - ts.Debug.assert(templateLiteral.kind === 13); + ts.Debug.assert(templateLiteral.kind === 13 /* NoSubstitutionTemplateLiteral */); callIsIncomplete = !!templateLiteral.isUnterminated; } } - else if (node.kind === 150) { + else if (node.kind === 150 /* Decorator */) { typeArguments = undefined; - argCount = getEffectiveArgumentCount(node, undefined, signature); + argCount = getEffectiveArgumentCount(node, /*args*/ undefined, signature); } else { if (!node.arguments) { - ts.Debug.assert(node.kind === 188); + // This only happens when we have something of the form: 'new C' + ts.Debug.assert(node.kind === 188 /* NewExpression */); return signature.minArgumentCount === 0; } argCount = signatureHelpTrailingComma ? args.length + 1 : args.length; + // If we are missing the close parenthesis, the call is incomplete. callIsIncomplete = node.arguments.end === node.end; typeArguments = node.typeArguments; spreadArgIndex = getSpreadArgumentIndex(args); @@ -39115,24 +45407,30 @@ var ts; if (!hasCorrectTypeArgumentArity(signature, typeArguments)) { return false; } + // If a spread argument is present, check that it corresponds to a rest parameter or at least that it's in the valid range. if (spreadArgIndex >= 0) { return isRestParameterIndex(signature, spreadArgIndex) || signature.minArgumentCount <= spreadArgIndex && spreadArgIndex < signature.parameters.length; } + // Too many arguments implies incorrect arity. if (!signature.hasRestParameter && argCount > signature.parameters.length) { return false; } + // If the call is incomplete, we should skip the lower bound check. var hasEnoughArguments = argCount >= signature.minArgumentCount; return callIsIncomplete || hasEnoughArguments; } function hasCorrectTypeArgumentArity(signature, typeArguments) { + // If the user supplied type arguments, but the number of type arguments does not match + // the declared number of type parameters, the call has an incorrect arity. var numTypeParameters = ts.length(signature.typeParameters); var minTypeArgumentCount = getMinTypeArgumentCount(signature.typeParameters); return !typeArguments || (typeArguments.length >= minTypeArgumentCount && typeArguments.length <= numTypeParameters); } + // If type has a single call signature and no other members, return that signature. Otherwise, return undefined. function getSingleCallSignature(type) { - if (type.flags & 131072) { + if (type.flags & 131072 /* Object */) { var resolved = resolveStructuredTypeMembers(type); if (resolved.callSignatures.length === 1 && resolved.constructSignatures.length === 0 && resolved.properties.length === 0 && !resolved.stringIndexInfo && !resolved.numberIndexInfo) { @@ -39141,42 +45439,66 @@ var ts; } return undefined; } + // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) function instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper, compareTypes) { - var context = createInferenceContext(signature.typeParameters, signature, 1, compareTypes); + var context = createInferenceContext(signature.typeParameters, signature, 1 /* InferUnionTypes */, compareTypes); forEachMatchingParameterType(contextualSignature, signature, function (source, target) { + // Type parameters from outer context referenced by source type are fixed by instantiation of the source type inferTypes(context.inferences, instantiateType(source, contextualMapper || identityMapper), target); }); if (!contextualMapper) { - inferTypes(context.inferences, getReturnTypeOfSignature(contextualSignature), getReturnTypeOfSignature(signature), 8); + inferTypes(context.inferences, getReturnTypeOfSignature(contextualSignature), getReturnTypeOfSignature(signature), 8 /* ReturnType */); } return getSignatureInstantiation(signature, getInferredTypes(context), ts.isInJavaScriptFile(contextualSignature.declaration)); } function inferJsxTypeArguments(signature, node, context) { + // Skip context sensitive pass var skipContextParamType = getTypeAtPosition(signature, 0); var checkAttrTypeSkipContextSensitive = checkExpressionWithContextualType(node.attributes, skipContextParamType, identityMapper); inferTypes(context.inferences, checkAttrTypeSkipContextSensitive, skipContextParamType); + // Standard pass var paramType = getTypeAtPosition(signature, 0); var checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, context); inferTypes(context.inferences, checkAttrType, paramType); return getInferredTypes(context); } function inferTypeArguments(node, signature, args, excludeArgument, context) { + // Clear out all the inference results from the last time inferTypeArguments was called on this context for (var _i = 0, _a = context.inferences; _i < _a.length; _i++) { var inference = _a[_i]; + // As an optimization, we don't have to clear (and later recompute) inferred types + // for type parameters that have already been fixed on the previous call to inferTypeArguments. + // It would be just as correct to reset all of them. But then we'd be repeating the same work + // for the type parameters that were fixed, namely the work done by getInferredType. if (!inference.isFixed) { inference.inferredType = undefined; } } - if (node.kind !== 150) { + // If a contextual type is available, infer from that type to the return type of the call expression. For + // example, given a 'function wrap(cb: (x: T) => U): (x: T) => U' and a call expression + // 'let f: (x: string) => number = wrap(s => s.length)', we infer from the declared type of 'f' to the + // return type of 'wrap'. + if (node.kind !== 150 /* Decorator */) { var contextualType = getContextualType(node); if (contextualType) { + // We clone the contextual mapper to avoid disturbing a resolution in progress for an + // outer call expression. Effectively we just want a snapshot of whatever has been + // inferred for any outer call expression so far. var instantiatedType = instantiateType(contextualType, cloneTypeMapper(getContextualMapper(node))); + // If the contextual type is a generic function type with a single call signature, we + // instantiate the type with its own type parameters and type arguments. This ensures that + // the type parameters are not erased to type any during type inference such that they can + // be inferred as actual types from the contextual type. For example: + // declare function arrayMap(f: (x: T) => U): (a: T[]) => U[]; + // const boxElements: (a: A[]) => { value: A }[] = arrayMap(value => ({ value })); + // Above, the type of the 'value' parameter is inferred to be 'A'. var contextualSignature = getSingleCallSignature(instantiatedType); var inferenceSourceType = contextualSignature && contextualSignature.typeParameters ? getOrCreateTypeFromSignature(getSignatureInstantiation(contextualSignature, contextualSignature.typeParameters, ts.isInJavaScriptFile(node))) : instantiatedType; var inferenceTargetType = getReturnTypeOfSignature(signature); - inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, 8); + // Inferences made from return types have lower priority than all other inferences. + inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, 8 /* ReturnType */); } } var thisType = getThisTypeOfSignature(signature); @@ -39185,21 +45507,34 @@ var ts; var thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType; inferTypes(context.inferences, thisArgumentType, thisType); } + // We perform two passes over the arguments. In the first pass we infer from all arguments, but use + // wildcards for all context sensitive function expressions. var argCount = getEffectiveArgumentCount(node, args, signature); for (var i = 0; i < argCount; i++) { var arg = getEffectiveArgument(node, args, i); - if (arg === undefined || arg.kind !== 206) { + // If the effective argument is 'undefined', then it is an argument that is present but is synthetic. + if (arg === undefined || arg.kind !== 206 /* OmittedExpression */) { var paramType = getTypeAtPosition(signature, i); var argType = getEffectiveArgumentType(node, i); + // If the effective argument type is 'undefined', there is no synthetic type + // for the argument. In that case, we should check the argument. if (argType === undefined) { + // For context sensitive arguments we pass the identityMapper, which is a signal to treat all + // context sensitive function expressions as wildcards var mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : context; argType = checkExpressionWithContextualType(arg, paramType, mapper); } inferTypes(context.inferences, argType, paramType); } } + // In the second pass we visit only context sensitive arguments, and only those that aren't excluded, this + // time treating function expressions normally (which may cause previously inferred type arguments to be fixed + // as we construct types for contextually typed parameters) + // Decorators will not have `excludeArgument`, as their arguments cannot be contextually typed. + // Tagged template expressions will always have `undefined` for `excludeArgument[0]`. if (excludeArgument) { for (var i = 0; i < argCount; i++) { + // No need to check for omitted args and template expressions, their exclusion value is always undefined if (excludeArgument[i] === false) { var arg = args[i]; var paramType = getTypeAtPosition(signature, i); @@ -39219,7 +45554,7 @@ var ts; var constraint = getConstraintOfTypeParameter(typeParameters[i]); if (!constraint) continue; - var errorInfo = reportErrors && headMessage ? (function () { return ts.chainDiagnosticMessages(undefined, ts.Diagnostics.Type_0_does_not_satisfy_the_constraint_1); }) : undefined; + var errorInfo = reportErrors && headMessage ? (function () { return ts.chainDiagnosticMessages(/*details*/ undefined, ts.Diagnostics.Type_0_does_not_satisfy_the_constraint_1); }) : undefined; var typeArgumentHeadMessage = headMessage || ts.Diagnostics.Type_0_does_not_satisfy_the_constraint_1; if (!mapper) { mapper = createTypeMapper(typeParameters, typeArgumentTypes); @@ -39231,14 +45566,29 @@ var ts; } return typeArgumentTypes; } + /** + * Check if the given signature can possibly be a signature called by the JSX opening-like element. + * @param node a JSX opening-like element we are trying to figure its call signature + * @param signature a candidate signature we are trying whether it is a call signature + * @param relation a relationship to check parameter and argument type + * @param excludeArgument + */ function checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation) { - var callIsIncomplete = node.attributes.end === node.end; + // JSX opening-like element has correct arity for stateless-function component if the one of the following condition is true: + // 1. callIsIncomplete + // 2. attributes property has same number of properties as the parameter object type. + // We can figure that out by resolving attributes property and check number of properties in the resolved type + // If the call has correct arity, we will then check if the argument type and parameter type is assignable + var callIsIncomplete = node.attributes.end === node.end; // If we are missing the close "/>", the call is incomplete if (callIsIncomplete) { return true; } var headMessage = ts.Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1; + // Stateless function components can have maximum of three arguments: "props", "context", and "updater". + // However "context" and "updater" are implicit and can't be specify by users. Only the first parameter, props, + // can be specified by users through attributes property. var paramType = getTypeAtPosition(signature, 0); - var attributesType = checkExpressionWithContextualType(node.attributes, paramType, undefined); + var attributesType = checkExpressionWithContextualType(node.attributes, paramType, /*contextualMapper*/ undefined); var argProperties = getPropertiesOfType(attributesType); for (var _i = 0, argProperties_1 = argProperties; _i < argProperties_1.length; _i++) { var arg = argProperties_1[_i]; @@ -39246,14 +45596,17 @@ var ts; return false; } } - return checkTypeRelatedTo(attributesType, paramType, relation, undefined, headMessage); + return checkTypeRelatedTo(attributesType, paramType, relation, /*errorNode*/ undefined, headMessage); } function checkApplicableSignature(node, args, signature, relation, excludeArgument, reportErrors) { if (ts.isJsxOpeningLikeElement(node)) { return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation); } var thisType = getThisTypeOfSignature(signature); - if (thisType && thisType !== voidType && node.kind !== 188) { + if (thisType && thisType !== voidType && node.kind !== 188 /* NewExpression */) { + // If the called expression is not of the form `x.f` or `x["f"]`, then sourceType = voidType + // If the signature's 'this' type is voidType, then the check is skipped -- anything is compatible. + // If the expression is a new expression, then the check is skipped. var thisArgumentNode = getThisArgumentOfCall(node); var thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType; var errorNode = reportErrors ? (thisArgumentNode || node) : undefined; @@ -39266,11 +45619,19 @@ var ts; var argCount = getEffectiveArgumentCount(node, args, signature); for (var i = 0; i < argCount; i++) { var arg = getEffectiveArgument(node, args, i); - if (arg === undefined || arg.kind !== 206) { + // If the effective argument is 'undefined', then it is an argument that is present but is synthetic. + if (arg === undefined || arg.kind !== 206 /* OmittedExpression */) { + // Check spread elements against rest type (from arity check we know spread argument corresponds to a rest parameter) var paramType = getTypeAtPosition(signature, i); + // If the effective argument type is undefined, there is no synthetic type for the argument. + // In that case, we should check the argument. var argType = getEffectiveArgumentType(node, i) || checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined); + // If one or more arguments are still excluded (as indicated by a non-null excludeArgument parameter), + // we obtain the regular type of any object literal arguments because we may not have inferred complete + // parameter types yet and therefore excess property checks may yield false positives (see #17041). var checkArgType = excludeArgument ? getRegularTypeOfObjectLiteral(argType) : argType; + // Use argument expression as error location when reporting errors var errorNode = reportErrors ? getEffectiveArgumentErrorNode(node, i, arg) : undefined; if (!checkTypeRelatedTo(checkArgType, paramType, relation, errorNode, headMessage)) { return false; @@ -39279,26 +45640,41 @@ var ts; } return true; } + /** + * Returns the this argument in calls like x.f(...) and x[f](...). Undefined otherwise. + */ function getThisArgumentOfCall(node) { - if (node.kind === 187) { + if (node.kind === 187 /* CallExpression */) { var callee = ts.skipOuterExpressions(node.expression); - if (callee.kind === 185 || callee.kind === 186) { + if (callee.kind === 185 /* PropertyAccessExpression */ || callee.kind === 186 /* ElementAccessExpression */) { return callee.expression; } } } + /** + * Returns the effective arguments for an expression that works like a function invocation. + * + * If 'node' is a CallExpression or a NewExpression, then its argument list is returned. + * If 'node' is a TaggedTemplateExpression, a new argument list is constructed from the substitution + * expressions, where the first element of the list is `undefined`. + * If 'node' is a Decorator, the argument list will be `undefined`, and its arguments and types + * will be supplied from calls to `getEffectiveArgumentCount` and `getEffectiveArgumentType`. + */ function getEffectiveCallArguments(node) { - if (node.kind === 189) { + if (node.kind === 189 /* TaggedTemplateExpression */) { var template = node.template; - var args_4 = [undefined]; - if (template.kind === 202) { + var args_4 = [undefined]; // TODO: GH#18217 + if (template.kind === 202 /* TemplateExpression */) { ts.forEach(template.templateSpans, function (span) { args_4.push(span.expression); }); } return args_4; } - else if (node.kind === 150) { + else if (node.kind === 150 /* Decorator */) { + // For a decorator, we return undefined as we will determine + // the number and types of arguments for a decorator using + // `getEffectiveArgumentCount` and `getEffectiveArgumentType` below. return undefined; } else if (ts.isJsxOpeningLikeElement(node)) { @@ -39308,22 +45684,45 @@ var ts; return node.arguments || ts.emptyArray; } } + /** + * Returns the effective argument count for a node that works like a function invocation. + * If 'node' is a Decorator, the number of arguments is derived from the decoration + * target and the signature: + * If 'node.target' is a class declaration or class expression, the effective argument + * count is 1. + * If 'node.target' is a parameter declaration, the effective argument count is 3. + * If 'node.target' is a property declaration, the effective argument count is 2. + * If 'node.target' is a method or accessor declaration, the effective argument count + * is 3, although it can be 2 if the signature only accepts two arguments, allowing + * us to match a property decorator. + * Otherwise, the argument count is the length of the 'args' array. + */ function getEffectiveArgumentCount(node, args, signature) { - if (node.kind === 150) { + if (node.kind === 150 /* Decorator */) { switch (node.parent.kind) { - case 235: - case 205: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + // A class decorator will have one argument (see `ClassDecorator` in core.d.ts) return 1; - case 152: + case 152 /* PropertyDeclaration */: + // A property declaration decorator will have two arguments (see + // `PropertyDecorator` in core.d.ts) return 2; - case 154: - case 156: - case 157: - if (languageVersion === 0) { + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + // A method or accessor declaration decorator will have two or three arguments (see + // `PropertyDecorator` and `MethodDecorator` in core.d.ts) + // If we are emitting decorators for ES3, we will only pass two arguments. + if (languageVersion === 0 /* ES3 */) { return 2; } + // If the method decorator signature only accepts a target and a key, we will only + // type check those arguments. return signature.parameters.length >= 3 ? 3 : 2; - case 149: + case 149 /* Parameter */: + // A parameter declaration decorator will have three arguments (see + // `ParameterDecorator` in core.d.ts) return 3; default: return ts.Debug.fail(); @@ -39333,53 +45732,97 @@ var ts; return args.length; } } + /** + * Returns the effective type of the first argument to a decorator. + * If 'node' is a class declaration or class expression, the effective argument type + * is the type of the static side of the class. + * If 'node' is a parameter declaration, the effective argument type is either the type + * of the static or instance side of the class for the parameter's parent method, + * depending on whether the method is declared static. + * For a constructor, the type is always the type of the static side of the class. + * If 'node' is a property, method, or accessor declaration, the effective argument + * type is the type of the static or instance side of the parent class for class + * element, depending on whether the element is declared static. + */ function getEffectiveDecoratorFirstArgumentType(node) { - if (node.kind === 235) { + // The first argument to a decorator is its `target`. + if (node.kind === 235 /* ClassDeclaration */) { + // For a class decorator, the `target` is the type of the class (e.g. the + // "static" or "constructor" side of the class) var classSymbol = getSymbolOfNode(node); return getTypeOfSymbol(classSymbol); } - if (node.kind === 149) { + if (node.kind === 149 /* Parameter */) { + // For a parameter decorator, the `target` is the parent type of the + // parameter's containing method. node = node.parent; - if (node.kind === 155) { + if (node.kind === 155 /* Constructor */) { var classSymbol = getSymbolOfNode(node); return getTypeOfSymbol(classSymbol); } } - if (node.kind === 152 || - node.kind === 154 || - node.kind === 156 || - node.kind === 157) { + if (node.kind === 152 /* PropertyDeclaration */ || + node.kind === 154 /* MethodDeclaration */ || + node.kind === 156 /* GetAccessor */ || + node.kind === 157 /* SetAccessor */) { + // For a property or method decorator, the `target` is the + // "static"-side type of the parent of the member if the member is + // declared "static"; otherwise, it is the "instance"-side type of the + // parent of the member. return getParentTypeOfClassElement(node); } ts.Debug.fail("Unsupported decorator target."); return errorType; } + /** + * Returns the effective type for the second argument to a decorator. + * If 'node' is a parameter, its effective argument type is one of the following: + * If 'node.parent' is a constructor, the effective argument type is 'any', as we + * will emit `undefined`. + * If 'node.parent' is a member with an identifier, numeric, or string literal name, + * the effective argument type will be a string literal type for the member name. + * If 'node.parent' is a computed property name, the effective argument type will + * either be a symbol type or the string type. + * If 'node' is a member with an identifier, numeric, or string literal name, the + * effective argument type will be a string literal type for the member name. + * If 'node' is a computed property name, the effective argument type will either + * be a symbol type or the string type. + * A class decorator does not have a second argument type. + */ function getEffectiveDecoratorSecondArgumentType(node) { - if (node.kind === 235) { + // The second argument to a decorator is its `propertyKey` + if (node.kind === 235 /* ClassDeclaration */) { ts.Debug.fail("Class decorators should not have a second synthetic argument."); return errorType; } - if (node.kind === 149) { + if (node.kind === 149 /* Parameter */) { node = node.parent; - if (node.kind === 155) { + if (node.kind === 155 /* Constructor */) { + // For a constructor parameter decorator, the `propertyKey` will be `undefined`. return anyType; } + // For a non-constructor parameter decorator, the `propertyKey` will be either + // a string or a symbol, based on the name of the parameter's containing method. } - if (node.kind === 152 || - node.kind === 154 || - node.kind === 156 || - node.kind === 157) { + if (node.kind === 152 /* PropertyDeclaration */ || + node.kind === 154 /* MethodDeclaration */ || + node.kind === 156 /* GetAccessor */ || + node.kind === 157 /* SetAccessor */) { + // The `propertyKey` for a property or method decorator will be a + // string literal type if the member name is an identifier, number, or string; + // otherwise, if the member name is a computed property name it will + // be either string or symbol. var element = node; var name = element.name; switch (name.kind) { - case 71: + case 71 /* Identifier */: return getLiteralType(ts.idText(name)); - case 8: - case 9: + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: return getLiteralType(name.text); - case 147: + case 147 /* ComputedPropertyName */: var nameType = checkComputedPropertyName(name); - if (isTypeAssignableToKind(nameType, 3072)) { + if (isTypeAssignableToKind(nameType, 3072 /* ESSymbolLike */)) { return nameType; } else { @@ -39393,27 +45836,42 @@ var ts; ts.Debug.fail("Unsupported decorator target."); return errorType; } + /** + * Returns the effective argument type for the third argument to a decorator. + * If 'node' is a parameter, the effective argument type is the number type. + * If 'node' is a method or accessor, the effective argument type is a + * `TypedPropertyDescriptor` instantiated with the type of the member. + * Class and property decorators do not have a third effective argument. + */ function getEffectiveDecoratorThirdArgumentType(node) { - if (node.kind === 235) { + // The third argument to a decorator is either its `descriptor` for a method decorator + // or its `parameterIndex` for a parameter decorator + if (node.kind === 235 /* ClassDeclaration */) { ts.Debug.fail("Class decorators should not have a third synthetic argument."); return errorType; } - if (node.kind === 149) { + if (node.kind === 149 /* Parameter */) { + // The `parameterIndex` for a parameter decorator is always a number return numberType; } - if (node.kind === 152) { + if (node.kind === 152 /* PropertyDeclaration */) { ts.Debug.fail("Property decorators should not have a third synthetic argument."); return errorType; } - if (node.kind === 154 || - node.kind === 156 || - node.kind === 157) { - var propertyType = getTypeOfNode(node); + if (node.kind === 154 /* MethodDeclaration */ || + node.kind === 156 /* GetAccessor */ || + node.kind === 157 /* SetAccessor */) { + // The `descriptor` for a method decorator will be a `TypedPropertyDescriptor` + // for the type of the member. + var propertyType = getTypeOfNode(node); // TODO: GH#18217 return createTypedPropertyDescriptorType(propertyType); } ts.Debug.fail("Unsupported decorator target."); return errorType; } + /** + * Returns the effective argument type for the provided argument to a decorator. + */ function getEffectiveDecoratorArgumentType(node, argIndex) { if (argIndex === 0) { return getEffectiveDecoratorFirstArgumentType(node.parent); @@ -39427,27 +45885,44 @@ var ts; ts.Debug.fail("Decorators should not have a fourth synthetic argument."); return errorType; } + /** + * Gets the effective argument type for an argument in a call expression. + */ function getEffectiveArgumentType(node, argIndex) { - if (node.kind === 150) { + // Decorators provide special arguments, a tagged template expression provides + // a special first argument, and string literals get string literal types + // unless we're reporting errors + if (node.kind === 150 /* Decorator */) { return getEffectiveDecoratorArgumentType(node, argIndex); } - else if (argIndex === 0 && node.kind === 189) { + else if (argIndex === 0 && node.kind === 189 /* TaggedTemplateExpression */) { return getGlobalTemplateStringsArrayType(); } + // This is not a synthetic argument, so we return 'undefined' + // to signal that the caller needs to check the argument. return undefined; } + /** + * Gets the effective argument expression for an argument in a call expression. + */ function getEffectiveArgument(node, args, argIndex) { - if (node.kind === 150 || - (argIndex === 0 && node.kind === 189)) { + // For a decorator or the first argument of a tagged template expression we return undefined. + if (node.kind === 150 /* Decorator */ || + (argIndex === 0 && node.kind === 189 /* TaggedTemplateExpression */)) { return undefined; } return args[argIndex]; } + /** + * Gets the error node to use when reporting errors for an effective argument. + */ function getEffectiveArgumentErrorNode(node, argIndex, arg) { - if (node.kind === 150) { + if (node.kind === 150 /* Decorator */) { + // For a decorator, we use the expression of the decorator for error reporting. return node.expression; } - else if (argIndex === 0 && node.kind === 189) { + else if (argIndex === 0 && node.kind === 189 /* TaggedTemplateExpression */) { + // For a the first argument of a tagged template expression, we use the template of the tag for error reporting. return node.template; } else { @@ -39466,27 +45941,45 @@ var ts; return ts.createDiagnosticForNodeArray(ts.getSourceFileOfNode(node), typeArguments, ts.Diagnostics.Expected_0_type_arguments_but_got_1, paramCount, typeArguments.length); } function resolveCall(node, signatures, candidatesOutArray, fallbackError) { - var isTaggedTemplate = node.kind === 189; - var isDecorator = node.kind === 150; + var isTaggedTemplate = node.kind === 189 /* TaggedTemplateExpression */; + var isDecorator = node.kind === 150 /* Decorator */; var isJsxOpeningOrSelfClosingElement = ts.isJsxOpeningLikeElement(node); var typeArguments; if (!isDecorator) { typeArguments = node.typeArguments; - if (isTaggedTemplate || isJsxOpeningOrSelfClosingElement || node.expression.kind !== 97) { + // We already perform checking on the type arguments on the class declaration itself. + if (isTaggedTemplate || isJsxOpeningOrSelfClosingElement || node.expression.kind !== 97 /* SuperKeyword */) { ts.forEach(typeArguments, checkSourceElement); } } var candidates = candidatesOutArray || []; + // reorderCandidates fills up the candidates array directly reorderCandidates(signatures, candidates); if (!candidates.length) { diagnostics.add(ts.createDiagnosticForNode(node, ts.Diagnostics.Call_target_does_not_contain_any_signatures)); return resolveErrorCall(node); } var args = getEffectiveCallArguments(node); + // The following applies to any value of 'excludeArgument[i]': + // - true: the argument at 'i' is susceptible to a one-time permanent contextual typing. + // - undefined: the argument at 'i' is *not* susceptible to permanent contextual typing. + // - false: the argument at 'i' *was* and *has been* permanently contextually typed. + // + // The idea is that we will perform type argument inference & assignability checking once + // without using the susceptible parameters that are functions, and once more for each of those + // parameters, contextually typing each as we go along. + // + // For a tagged template, then the first argument be 'undefined' if necessary + // because it represents a TemplateStringsArray. + // + // For a decorator, no arguments are susceptible to contextual typing due to the fact + // decorators are applied to a declaration by the emitter, and not to an expression. var isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters; var excludeArgument; var excludeCount = 0; if (!isDecorator && !isSingleNonGenericCandidate) { + // We do not need to call `getEffectiveArgumentCount` here as it only + // applies when calculating the number of arguments for a decorator. for (var i = isTaggedTemplate ? 1 : 0; i < args.length; i++) { if (isContextSensitive(args[i])) { if (!excludeArgument) { @@ -39497,10 +45990,43 @@ var ts; } } } + // The following variables are captured and modified by calls to chooseOverload. + // If overload resolution or type argument inference fails, we want to report the + // best error possible. The best error is one which says that an argument was not + // assignable to a parameter. This implies that everything else about the overload + // was fine. So if there is any overload that is only incorrect because of an + // argument, we will report an error on that one. + // + // function foo(s: string): void; + // function foo(n: number): void; // Report argument error on this overload + // function foo(): void; + // foo(true); + // + // If none of the overloads even made it that far, there are two possibilities. + // There was a problem with type arguments for some overload, in which case + // report an error on that. Or none of the overloads even had correct arity, + // in which case give an arity error. + // + // function foo(x: T): void; // Report type argument error + // function foo(): void; + // foo(0); + // var candidateForArgumentError; var candidateForTypeArgumentError; var result; - var signatureHelpTrailingComma = candidatesOutArray && node.kind === 187 && node.arguments.hasTrailingComma; + // If we are in signature help, a trailing comma indicates that we intend to provide another argument, + // so we will only accept overloads with arity at least 1 higher than the current number of provided arguments. + var signatureHelpTrailingComma = candidatesOutArray && node.kind === 187 /* CallExpression */ && node.arguments.hasTrailingComma; + // Section 4.12.1: + // if the candidate list contains one or more signatures for which the type of each argument + // expression is a subtype of each corresponding parameter type, the return type of the first + // of those signatures becomes the return type of the function call. + // Otherwise, the return type of the first signature in the candidate list becomes the return + // type of the function call. + // + // Whether the call is an error is determined by assignability of the arguments. The subtype pass + // is just important for choosing the best signature. So in the case where there is only one + // signature, the subtype pass is useless. So skipping it is an optimization. if (candidates.length > 1) { result = chooseOverload(candidates, subtypeRelation, signatureHelpTrailingComma); } @@ -39510,14 +46036,24 @@ var ts; if (result) { return result; } + // No signatures were applicable. Now report errors based on the last applicable signature with + // no arguments excluded from assignability checks. + // If candidate is undefined, it means that no candidates had a suitable arity. In that case, + // skip the checkApplicableSignature check. if (candidateForArgumentError) { if (isJsxOpeningOrSelfClosingElement) { + // We do not report any error here because any error will be handled in "resolveCustomJsxElementAttributesType". return candidateForArgumentError; } - checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, undefined, true); + // excludeArgument is undefined, in this case also equivalent to [undefined, undefined, ...] + // The importance of excludeArgument is to prevent us from typing function expression parameters + // in arguments too early. If possible, we'd like to only type them once we know the correct + // overload. However, this matters for the case where the call is correct. When the call is + // an error, we don't need to exclude any arguments, although it would cause no harm to do so. + checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true); } else if (candidateForTypeArgumentError) { - checkTypeArguments(candidateForTypeArgumentError, node.typeArguments, true, fallbackError); + checkTypeArguments(candidateForTypeArgumentError, node.typeArguments, /*reportErrors*/ true, fallbackError); } else if (typeArguments && ts.every(signatures, function (sig) { return ts.length(sig.typeParameters) !== typeArguments.length; })) { diagnostics.add(getTypeArgumentArityError(node, signatures, typeArguments)); @@ -39548,13 +46084,21 @@ var ts; else if (fallbackError) { diagnostics.add(ts.createDiagnosticForNode(node, fallbackError)); } + // No signature was applicable. We have already reported the errors for the invalid signature. + // If this is a type resolution session, e.g. Language Service, try to get better information than anySignature. + // Pick the longest signature. This way we can get a contextual type for cases like: + // declare function f(a: { xa: number; xb: number; }, b: number); + // f({ | + // Also, use explicitly-supplied type arguments if they are provided, so we can get a contextual signature in cases like: + // declare function f(k: keyof T); + // f(" if (!produceDiagnostics) { - ts.Debug.assert(candidates.length > 0); + ts.Debug.assert(candidates.length > 0); // Else would have exited above. var bestIndex = getLongestCandidateIndex(candidates, apparentArgumentCount === undefined ? args.length : apparentArgumentCount); var candidate = candidates[bestIndex]; var typeParameters = candidate.typeParameters; if (typeParameters && callLikeExpressionMayHaveTypeArguments(node) && node.typeArguments) { - var typeArguments_1 = node.typeArguments.map(getTypeOfNode); + var typeArguments_1 = node.typeArguments.map(getTypeOfNode); // TODO: GH#18217 while (typeArguments_1.length > typeParameters.length) { typeArguments_1.pop(); } @@ -39577,7 +46121,7 @@ var ts; if (!hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) { return undefined; } - if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, false)) { + if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) { candidateForArgumentError = candidate; return undefined; } @@ -39590,14 +46134,14 @@ var ts; } var candidate = void 0; var inferenceContext = originalCandidate.typeParameters ? - createInferenceContext(originalCandidate.typeParameters, originalCandidate, ts.isInJavaScriptFile(node) ? 4 : 0) : + createInferenceContext(originalCandidate.typeParameters, originalCandidate, /*flags*/ ts.isInJavaScriptFile(node) ? 4 /* AnyDefault */ : 0 /* None */) : undefined; while (true) { candidate = originalCandidate; if (candidate.typeParameters) { var typeArgumentTypes = void 0; if (typeArguments) { - var typeArgumentResult = checkTypeArguments(candidate, typeArguments, false); + var typeArgumentResult = checkTypeArguments(candidate, typeArguments, /*reportErrors*/ false); if (typeArgumentResult) { typeArgumentTypes = typeArgumentResult; } @@ -39612,7 +46156,7 @@ var ts; var isJavascript = ts.isInJavaScriptFile(candidate.declaration); candidate = getSignatureInstantiation(candidate, typeArgumentTypes, isJavascript); } - if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, false)) { + if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) { candidateForArgumentError = candidate; break; } @@ -39622,7 +46166,7 @@ var ts; } excludeCount--; if (excludeCount > 0) { - excludeArgument[excludeArgument.indexOf(true)] = false; + excludeArgument[excludeArgument.indexOf(/*value*/ true)] = false; } else { excludeArgument = undefined; @@ -39648,13 +46192,15 @@ var ts; return maxParamsIndex; } function resolveCallExpression(node, candidatesOutArray) { - if (node.expression.kind === 97) { + if (node.expression.kind === 97 /* SuperKeyword */) { var superType = checkSuperExpression(node.expression); if (isTypeAny(superType)) { - ts.forEach(node.arguments, checkExpresionNoReturn); + ts.forEach(node.arguments, checkExpresionNoReturn); // Still visit arguments so they get marked for visibility, etc return anySignature; } if (superType !== errorType) { + // In super call, the candidate signatures are the matching arity signatures of the base constructor function instantiated + // with the type arguments specified in the extends clause. var baseTypeNode = ts.getClassExtendsHeritageClauseElement(ts.getContainingClass(node)); if (baseTypeNode) { var baseConstructors = getInstantiatedConstructorsForTypeArguments(superType, baseTypeNode.typeArguments, baseTypeNode); @@ -39669,33 +46215,52 @@ var ts; } var apparentType = getApparentType(funcType); if (apparentType === errorType) { + // Another error has already been reported return resolveErrorCall(node); } - var callSignatures = getSignaturesOfType(apparentType, 0); - var constructSignatures = getSignaturesOfType(apparentType, 1); + // Technically, this signatures list may be incomplete. We are taking the apparent type, + // but we are not including call signatures that may have been added to the Object or + // Function interface, since they have none by default. This is a bit of a leap of faith + // that the user will not add any. + var callSignatures = getSignaturesOfType(apparentType, 0 /* Call */); + var constructSignatures = getSignaturesOfType(apparentType, 1 /* Construct */); + // TS 1.0 Spec: 4.12 + // In an untyped function call no TypeArgs are permitted, Args can be any argument list, no contextual + // types are provided for the argument expressions, and the result is always of type Any. if (isUntypedFunctionCall(funcType, apparentType, callSignatures.length, constructSignatures.length)) { + // The unknownType indicates that an error already occurred (and was reported). No + // need to report another error in this case. if (funcType !== errorType && node.typeArguments) { error(node, ts.Diagnostics.Untyped_function_calls_may_not_accept_type_arguments); } return resolveUntypedCall(node); } + // If FuncExpr's apparent type(section 3.8.1) is a function type, the call is a typed function call. + // TypeScript employs overload resolution in typed function calls in order to support functions + // with multiple call signatures. if (!callSignatures.length) { if (constructSignatures.length) { error(node, ts.Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); } else { - invocationError(node, apparentType, 0); + invocationError(node, apparentType, 0 /* Call */); } return resolveErrorCall(node); } return resolveCall(node, callSignatures, candidatesOutArray); } + /** + * TS 1.0 spec: 4.12 + * If FuncExpr is of type Any, or of an object type that has no call or construct signatures + * but is a subtype of the Function interface, the call is an untyped function call. + */ function isUntypedFunctionCall(funcType, apparentFuncType, numCallSignatures, numConstructSignatures) { - return isTypeAny(funcType) || isTypeAny(apparentFuncType) && funcType.flags & 65536 || - !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & (262144 | 32768)) && isTypeAssignableTo(funcType, globalFunctionType); + // We exclude union types because we may have a union of function types that happen to have no common signatures. + return isTypeAny(funcType) || isTypeAny(apparentFuncType) && funcType.flags & 65536 /* TypeParameter */ || + !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & (262144 /* Union */ | 32768 /* Never */)) && isTypeAssignableTo(funcType, globalFunctionType); } function resolveNewExpression(node, candidatesOutArray) { - if (node.arguments && languageVersion < 1) { + if (node.arguments && languageVersion < 1 /* ES5 */) { var spreadIndex = getSpreadArgumentIndex(node.arguments); if (spreadIndex >= 0) { error(node.arguments[spreadIndex], ts.Diagnostics.Spread_operator_in_new_expressions_is_only_available_when_targeting_ECMAScript_5_and_higher); @@ -39705,29 +46270,50 @@ var ts; if (expressionType === silentNeverType) { return silentNeverSignature; } + // If expressionType's apparent type(section 3.8.1) is an object type with one or + // more construct signatures, the expression is processed in the same manner as a + // function call, but using the construct signatures as the initial set of candidate + // signatures for overload resolution. The result type of the function call becomes + // the result type of the operation. expressionType = getApparentType(expressionType); if (expressionType === errorType) { + // Another error has already been reported return resolveErrorCall(node); } + // TS 1.0 spec: 4.11 + // If expressionType is of type Any, Args can be any argument + // list and the result of the operation is of type Any. if (isTypeAny(expressionType)) { if (node.typeArguments) { error(node, ts.Diagnostics.Untyped_function_calls_may_not_accept_type_arguments); } return resolveUntypedCall(node); } - var constructSignatures = getSignaturesOfType(expressionType, 1); + // Technically, this signatures list may be incomplete. We are taking the apparent type, + // but we are not including construct signatures that may have been added to the Object or + // Function interface, since they have none by default. This is a bit of a leap of faith + // that the user will not add any. + var constructSignatures = getSignaturesOfType(expressionType, 1 /* Construct */); if (constructSignatures.length) { if (!isConstructorAccessible(node, constructSignatures[0])) { return resolveErrorCall(node); } + // If the expression is a class of abstract type, then it cannot be instantiated. + // Note, only class declarations can be declared abstract. + // In the case of a merged class-module or class-interface declaration, + // only the class declaration node will have the Abstract flag set. var valueDecl = expressionType.symbol && ts.getClassLikeDeclarationOfSymbol(expressionType.symbol); - if (valueDecl && ts.hasModifier(valueDecl, 128)) { + if (valueDecl && ts.hasModifier(valueDecl, 128 /* Abstract */)) { error(node, ts.Diagnostics.Cannot_create_an_instance_of_an_abstract_class); return resolveErrorCall(node); } return resolveCall(node, constructSignatures, candidatesOutArray); } - var callSignatures = getSignaturesOfType(expressionType, 0); + // If expressionType's apparent type is an object type with no construct signatures but + // one or more call signatures, the expression is processed as a function call. A compile-time + // error occurs if the result of the function call is not Void. The type of the result of the + // operation is Any. It is an error to have a Void this type. + var callSignatures = getSignaturesOfType(expressionType, 0 /* Call */); if (callSignatures.length) { var signature = resolveCall(node, callSignatures, candidatesOutArray); if (!isJavaScriptConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) { @@ -39738,7 +46324,7 @@ var ts; } return signature; } - invocationError(node, expressionType, 1); + invocationError(node, expressionType, 1 /* Construct */); return resolveErrorCall(node); } function isConstructorAccessible(node, signature) { @@ -39746,12 +46332,14 @@ var ts; return true; } var declaration = signature.declaration; - var modifiers = ts.getSelectedModifierFlags(declaration, 24); + var modifiers = ts.getSelectedModifierFlags(declaration, 24 /* NonPublicAccessibilityModifier */); + // Public constructor is accessible. if (!modifiers) { return true; } var declaringClassDeclaration = ts.getClassLikeDeclarationOfSymbol(declaration.parent.symbol); var declaringClass = getDeclaredTypeOfSymbol(declaration.parent.symbol); + // A private or protected constructor can only be instantiated within its own class (or a subclass, for protected) if (!isNodeWithinClass(node, declaringClassDeclaration)) { var containingClass = ts.getContainingClass(node); if (containingClass) { @@ -39759,17 +46347,17 @@ var ts; var baseTypes = getBaseTypes(containingType); while (baseTypes.length) { var baseType = baseTypes[0]; - if (modifiers & 16 && + if (modifiers & 16 /* Protected */ && baseType.symbol === declaration.parent.symbol) { return true; } baseTypes = getBaseTypes(baseType); } } - if (modifiers & 8) { + if (modifiers & 8 /* Private */) { error(node, ts.Diagnostics.Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration, typeToString(declaringClass)); } - if (modifiers & 16) { + if (modifiers & 16 /* Protected */) { error(node, ts.Diagnostics.Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration, typeToString(declaringClass)); } return false; @@ -39777,7 +46365,7 @@ var ts; return true; } function invocationError(node, apparentType, kind) { - invocationErrorRecovery(apparentType, kind, error(node, kind === 0 + invocationErrorRecovery(apparentType, kind, error(node, kind === 0 /* Call */ ? ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures : ts.Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature, typeToString(apparentType))); } @@ -39786,6 +46374,8 @@ var ts; return; } var importNode = getSymbolLinks(apparentType.symbol).originatingImport; + // Create a diagnostic on the originating import if possible onto which we can attach a quickfix + // An import call expression cannot be rewritten into another form to correct the error - the only solution is to use `.default` at the use-site if (importNode && !ts.isImportCall(importNode)) { var sigs = getSignaturesOfType(getTypeOfSymbol(getSymbolLinks(apparentType.symbol).target), kind); if (!sigs || !sigs.length) @@ -39798,73 +46388,95 @@ var ts; var tagType = checkExpression(node.tag); var apparentType = getApparentType(tagType); if (apparentType === errorType) { + // Another error has already been reported return resolveErrorCall(node); } - var callSignatures = getSignaturesOfType(apparentType, 0); - var constructSignatures = getSignaturesOfType(apparentType, 1); + var callSignatures = getSignaturesOfType(apparentType, 0 /* Call */); + var constructSignatures = getSignaturesOfType(apparentType, 1 /* Construct */); if (isUntypedFunctionCall(tagType, apparentType, callSignatures.length, constructSignatures.length)) { return resolveUntypedCall(node); } if (!callSignatures.length) { - invocationError(node, apparentType, 0); + invocationError(node, apparentType, 0 /* Call */); return resolveErrorCall(node); } return resolveCall(node, callSignatures, candidatesOutArray); } + /** + * Gets the localized diagnostic head message to use for errors when resolving a decorator as a call expression. + */ function getDiagnosticHeadMessageForDecoratorResolution(node) { switch (node.parent.kind) { - case 235: - case 205: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: return ts.Diagnostics.Unable_to_resolve_signature_of_class_decorator_when_called_as_an_expression; - case 149: + case 149 /* Parameter */: return ts.Diagnostics.Unable_to_resolve_signature_of_parameter_decorator_when_called_as_an_expression; - case 152: + case 152 /* PropertyDeclaration */: return ts.Diagnostics.Unable_to_resolve_signature_of_property_decorator_when_called_as_an_expression; - case 154: - case 156: - case 157: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return ts.Diagnostics.Unable_to_resolve_signature_of_method_decorator_when_called_as_an_expression; default: return ts.Debug.fail(); } } + /** + * Resolves a decorator as if it were a call expression. + */ function resolveDecorator(node, candidatesOutArray) { var funcType = checkExpression(node.expression); var apparentType = getApparentType(funcType); if (apparentType === errorType) { return resolveErrorCall(node); } - var callSignatures = getSignaturesOfType(apparentType, 0); - var constructSignatures = getSignaturesOfType(apparentType, 1); + var callSignatures = getSignaturesOfType(apparentType, 0 /* Call */); + var constructSignatures = getSignaturesOfType(apparentType, 1 /* Construct */); if (isUntypedFunctionCall(funcType, apparentType, callSignatures.length, constructSignatures.length)) { return resolveUntypedCall(node); } if (isPotentiallyUncalledDecorator(node, callSignatures)) { - var nodeStr = ts.getTextOfNode(node.expression, false); + var nodeStr = ts.getTextOfNode(node.expression, /*includeTrivia*/ false); error(node, ts.Diagnostics._0_accepts_too_few_arguments_to_be_used_as_a_decorator_here_Did_you_mean_to_call_it_first_and_write_0, nodeStr); return resolveErrorCall(node); } var headMessage = getDiagnosticHeadMessageForDecoratorResolution(node); if (!callSignatures.length) { - var errorInfo = ts.chainDiagnosticMessages(undefined, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType)); + var errorInfo = ts.chainDiagnosticMessages(/*details*/ undefined, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType)); errorInfo = ts.chainDiagnosticMessages(errorInfo, headMessage); var diag = ts.createDiagnosticForNodeFromMessageChain(node, errorInfo); diagnostics.add(diag); - invocationErrorRecovery(apparentType, 0, diag); + invocationErrorRecovery(apparentType, 0 /* Call */, diag); return resolveErrorCall(node); } return resolveCall(node, callSignatures, candidatesOutArray, headMessage); } + /** + * Sometimes, we have a decorator that could accept zero arguments, + * but is receiving too many arguments as part of the decorator invocation. + * In those cases, a user may have meant to *call* the expression before using it as a decorator. + */ function isPotentiallyUncalledDecorator(decorator, signatures) { return signatures.length && ts.every(signatures, function (signature) { return signature.minArgumentCount === 0 && !signature.hasRestParameter && - signature.parameters.length < getEffectiveArgumentCount(decorator, undefined, signature); + signature.parameters.length < getEffectiveArgumentCount(decorator, /*args*/ undefined, signature); }); } + /** + * This function is similar to getResolvedSignature but is exclusively for trying to resolve JSX stateless-function component. + * The main reason we have to use this function instead of getResolvedSignature because, the caller of this function will already check the type of openingLikeElement's tagName + * and pass the type as elementType. The elementType can not be a union (as such case should be handled by the caller of this function) + * Note: at this point, we are still not sure whether the opening-like element is a stateless function component or not. + * @param openingLikeElement an opening-like JSX element to try to resolve as JSX stateless function + * @param elementType an element type of the opneing-like element by checking opening-like element's tagname. + * @param candidatesOutArray an array of signature to be filled in by the function. It is passed by signature help in the language service; + * the function will fill it up with appropriate candidate signatures + */ function getResolvedJsxStatelessFunctionSignature(openingLikeElement, elementType, candidatesOutArray) { - ts.Debug.assert(!(elementType.flags & 262144)); - var callSignatures = elementType && getSignaturesOfType(elementType, 0); + ts.Debug.assert(!(elementType.flags & 262144 /* Union */)); + var callSignatures = elementType && getSignaturesOfType(elementType, 0 /* Call */); if (callSignatures && callSignatures.length > 0) { return resolveCall(openingLikeElement, callSignatures, candidatesOutArray); } @@ -39872,16 +46484,17 @@ var ts; } function resolveSignature(node, candidatesOutArray) { switch (node.kind) { - case 187: + case 187 /* CallExpression */: return resolveCallExpression(node, candidatesOutArray); - case 188: + case 188 /* NewExpression */: return resolveNewExpression(node, candidatesOutArray); - case 189: + case 189 /* TaggedTemplateExpression */: return resolveTaggedTemplateExpression(node, candidatesOutArray); - case 150: + case 150 /* Decorator */: return resolveDecorator(node, candidatesOutArray); - case 257: - case 256: + case 257 /* JsxOpeningElement */: + case 256 /* JsxSelfClosingElement */: + // This code-path is called by language service var exprTypes = checkExpression(node.tagName); return forEachType(exprTypes, function (exprType) { var sfcResult = getResolvedJsxStatelessFunctionSignature(node, exprType, candidatesOutArray); @@ -39897,21 +46510,41 @@ var ts; } throw ts.Debug.assertNever(node, "Branch in 'resolveSignature' should be unreachable."); } + /** + * Resolve a signature of a given call-like expression. + * @param node a call-like expression to try resolve a signature for + * @param candidatesOutArray an array of signature to be filled in by the function. It is passed by signature help in the language service; + * the function will fill it up with appropriate candidate signatures + * @return a signature of the call-like expression or undefined if one can't be found + */ function getResolvedSignature(node, candidatesOutArray) { var links = getNodeLinks(node); + // If getResolvedSignature has already been called, we will have cached the resolvedSignature. + // However, it is possible that either candidatesOutArray was not passed in the first time, + // or that a different candidatesOutArray was passed in. Therefore, we need to redo the work + // to correctly fill the candidatesOutArray. var cached = links.resolvedSignature; if (cached && cached !== resolvingSignature && !candidatesOutArray) { return cached; } links.resolvedSignature = resolvingSignature; var result = resolveSignature(node, candidatesOutArray); + // If signature resolution originated in control flow type analysis (for example to compute the + // assigned type in a flow assignment) we don't cache the result as it may be based on temporary + // types from the control flow analysis. links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached; return result; } + /** + * Indicates whether a declaration can be treated as a constructor in a JavaScript + * file. + */ function isJavaScriptConstructor(node) { if (node && ts.isInJavaScriptFile(node)) { + // If the node has a @class tag, treat it like a constructor. if (ts.getJSDocClassTag(node)) return true; + // If the symbol of the node has members, treat it like a constructor. var symbol = ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) ? getSymbolOfNode(node) : ts.isVariableDeclaration(node) && node.initializer && ts.isFunctionExpression(node.initializer) ? getSymbolOfNode(node.initializer) : undefined; @@ -39950,10 +46583,10 @@ var ts; return false; } var parent = node.parent; - while (parent && parent.kind === 185) { + while (parent && parent.kind === 185 /* PropertyAccessExpression */) { parent = parent.parent; } - if (parent && ts.isBinaryExpression(parent) && ts.isPrototypeAccess(parent.left) && parent.operatorToken.kind === 58) { + if (parent && ts.isBinaryExpression(parent) && ts.isPrototypeAccess(parent.left) && parent.operatorToken.kind === 58 /* EqualsToken */) { var right = ts.getInitializerOfBinaryExpression(parent); return ts.isObjectLiteralExpression(right) && right; } @@ -39961,31 +46594,41 @@ var ts; function getInferredClassType(symbol) { var links = getSymbolLinks(symbol); if (!links.inferredClassType) { - links.inferredClassType = createAnonymousType(symbol, getMembersOfSymbol(symbol) || emptySymbols, ts.emptyArray, ts.emptyArray, undefined, undefined); + links.inferredClassType = createAnonymousType(symbol, getMembersOfSymbol(symbol) || emptySymbols, ts.emptyArray, ts.emptyArray, /*stringIndexType*/ undefined, /*numberIndexType*/ undefined); } return links.inferredClassType; } function isInferredClassType(type) { return type.symbol - && ts.getObjectFlags(type) & 16 + && ts.getObjectFlags(type) & 16 /* Anonymous */ && getSymbolLinks(type.symbol).inferredClassType === type; } + /** + * Syntactically and semantically checks a call or new expression. + * @param node The call/new expression to be checked. + * @returns On success, the expression's signature's return type. On failure, anyType. + */ function checkCallExpression(node) { if (!checkGrammarTypeArguments(node, node.typeArguments)) checkGrammarArguments(node.arguments); var signature = getResolvedSignature(node); - if (node.expression.kind === 97) { + if (node.expression.kind === 97 /* SuperKeyword */) { return voidType; } - if (node.kind === 188) { + if (node.kind === 188 /* NewExpression */) { var declaration = signature.declaration; if (declaration && - declaration.kind !== 155 && - declaration.kind !== 159 && - declaration.kind !== 164 && + declaration.kind !== 155 /* Constructor */ && + declaration.kind !== 159 /* ConstructSignature */ && + declaration.kind !== 164 /* ConstructorType */ && !ts.isJSDocConstructSignature(declaration)) { + // When resolved signature is a call signature (and not a construct signature) the result type is any, unless + // the declaring function had members created through 'x.prototype.y = expr' or 'this.y = expr' psuedodeclarations + // in a JS file + // Note:JS inferred classes might come from a variable declaration instead of a function declaration. + // In this case, using getResolvedSymbol directly is required to avoid losing the members from the declaration. var funcSymbol = checkExpression(node.expression).symbol; - if (!funcSymbol && node.expression.kind === 71) { + if (!funcSymbol && node.expression.kind === 71 /* Identifier */) { funcSymbol = getResolvedSymbol(node.expression); } var type = funcSymbol && getJavaScriptClassType(funcSymbol); @@ -39998,11 +46641,14 @@ var ts; return anyType; } } + // In JavaScript files, calls to any identifier 'require' are treated as external module imports if (ts.isInJavaScriptFile(node) && isCommonJsRequire(node)) { return resolveExternalModuleTypeByLiteral(node.arguments[0]); } var returnType = getReturnTypeOfSignature(signature); - if (returnType.flags & 3072 && isSymbolOrSymbolForCall(node)) { + // Treat any call to the global 'Symbol' function that is part of a const variable or readonly property + // as a fresh unique symbol literal type. + if (returnType.flags & 3072 /* ESSymbolLike */ && isSymbolOrSymbolForCall(node)) { return getESSymbolLikeTypeForNode(ts.walkUpParenthesizedExpressions(node.parent)); } var jsAssignmentType; @@ -40027,13 +46673,15 @@ var ts; if (!ts.isIdentifier(left) || left.escapedText !== "Symbol") { return false; } - var globalESSymbol = getGlobalESSymbolConstructorSymbol(false); + // make sure `Symbol` is the global symbol + var globalESSymbol = getGlobalESSymbolConstructorSymbol(/*reportErrors*/ false); if (!globalESSymbol) { return false; } - return globalESSymbol === resolveName(left, "Symbol", 67216319, undefined, undefined, false); + return globalESSymbol === resolveName(left, "Symbol", 67216319 /* Value */, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); } function checkImportCallExpression(node) { + // Check grammar of dynamic import if (!checkGrammarArguments(node.arguments)) checkGrammarImportCallExpression(node); if (node.arguments.length === 0) { @@ -40041,15 +46689,17 @@ var ts; } var specifier = node.arguments[0]; var specifierType = checkExpressionCached(specifier); + // Even though multiple arugments is grammatically incorrect, type-check extra arguments for completion for (var i = 1; i < node.arguments.length; ++i) { checkExpressionCached(node.arguments[i]); } - if (specifierType.flags & 8192 || specifierType.flags & 16384 || !isTypeAssignableTo(specifierType, stringType)) { + if (specifierType.flags & 8192 /* Undefined */ || specifierType.flags & 16384 /* Null */ || !isTypeAssignableTo(specifierType, stringType)) { error(specifier, ts.Diagnostics.Dynamic_import_s_specifier_must_be_of_type_string_but_here_has_type_0, typeToString(specifierType)); } + // resolveExternalModuleName will return undefined if the moduleReferenceExpression is not a string literal var moduleSymbol = resolveExternalModuleName(node, specifier); if (moduleSymbol) { - var esModuleSymbol = resolveESModuleSymbol(moduleSymbol, specifier, true); + var esModuleSymbol = resolveESModuleSymbol(moduleSymbol, specifier, /*dontRecursivelyResolve*/ true); if (esModuleSymbol) { return createPromiseReturnType(node, getTypeWithSyntheticDefaultImportType(getTypeOfSymbol(esModuleSymbol), esModuleSymbol, moduleSymbol)); } @@ -40061,16 +46711,16 @@ var ts; var synthType = type; if (!synthType.syntheticType) { var file = ts.find(originalSymbol.declarations, ts.isSourceFile); - var hasSyntheticDefault = canHaveSyntheticDefault(file, originalSymbol, false); + var hasSyntheticDefault = canHaveSyntheticDefault(file, originalSymbol, /*dontResolveAlias*/ false); if (hasSyntheticDefault) { var memberTable = ts.createSymbolTable(); - var newSymbol = createSymbol(2097152, "default"); + var newSymbol = createSymbol(2097152 /* Alias */, "default" /* Default */); newSymbol.target = resolveSymbol(symbol); - memberTable.set("default", newSymbol); - var anonymousSymbol = createSymbol(2048, "__type"); - var defaultContainingObject = createAnonymousType(anonymousSymbol, memberTable, ts.emptyArray, ts.emptyArray, undefined, undefined); + memberTable.set("default" /* Default */, newSymbol); + var anonymousSymbol = createSymbol(2048 /* TypeLiteral */, "__type" /* Type */); + var defaultContainingObject = createAnonymousType(anonymousSymbol, memberTable, ts.emptyArray, ts.emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined); anonymousSymbol.type = defaultContainingObject; - synthType.syntheticType = isValidSpreadType(type) ? getSpreadType(type, defaultContainingObject, anonymousSymbol, 0, 0) : defaultContainingObject; + synthType.syntheticType = isValidSpreadType(type) ? getSpreadType(type, defaultContainingObject, anonymousSymbol, /*typeFLags*/ 0, /*objectFlags*/ 0) : defaultContainingObject; } else { synthType.syntheticType = type; @@ -40081,33 +46731,36 @@ var ts; return type; } function isCommonJsRequire(node) { - if (!ts.isRequireCall(node, true)) { + if (!ts.isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true)) { return false; } + // Make sure require is not a local function if (!ts.isIdentifier(node.expression)) return ts.Debug.fail(); - var resolvedRequire = resolveName(node.expression, node.expression.escapedText, 67216319, undefined, undefined, true); + var resolvedRequire = resolveName(node.expression, node.expression.escapedText, 67216319 /* Value */, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); // TODO: GH#18217 if (resolvedRequire === requireSymbol) { return true; } - if (resolvedRequire.flags & 2097152) { + // project includes symbol named 'require' - make sure that it is ambient and local non-alias + if (resolvedRequire.flags & 2097152 /* Alias */) { return false; } - var targetDeclarationKind = resolvedRequire.flags & 16 - ? 234 - : resolvedRequire.flags & 3 - ? 232 - : 0; - if (targetDeclarationKind !== 0) { + var targetDeclarationKind = resolvedRequire.flags & 16 /* Function */ + ? 234 /* FunctionDeclaration */ + : resolvedRequire.flags & 3 /* Variable */ + ? 232 /* VariableDeclaration */ + : 0 /* Unknown */; + if (targetDeclarationKind !== 0 /* Unknown */) { var decl = ts.getDeclarationOfKind(resolvedRequire, targetDeclarationKind); - return !!decl && !!(decl.flags & 4194304); + // function/variable declaration should be ambient + return !!decl && !!(decl.flags & 4194304 /* Ambient */); } return false; } function checkTaggedTemplateExpression(node) { checkGrammarTypeArguments(node, node.typeArguments); - if (languageVersion < 2) { - checkExternalEmitHelpers(node, 65536); + if (languageVersion < 2 /* ES2015 */) { + checkExternalEmitHelpers(node, 65536 /* MakeTemplateObject */); } return getReturnTypeOfSignature(getResolvedSignature(node)); } @@ -40131,10 +46784,10 @@ var ts; } function checkMetaProperty(node) { checkGrammarMetaProperty(node); - if (node.keywordToken === 94) { + if (node.keywordToken === 94 /* NewKeyword */) { return checkNewTargetMetaProperty(node); } - if (node.keywordToken === 91) { + if (node.keywordToken === 91 /* ImportKeyword */) { return checkImportMetaProperty(node); } return ts.Debug.assertNever(node.keywordToken); @@ -40145,7 +46798,7 @@ var ts; error(node, ts.Diagnostics.Meta_property_0_is_only_allowed_in_the_body_of_a_function_declaration_function_expression_or_constructor, "new.target"); return errorType; } - else if (container.kind === 155) { + else if (container.kind === 155 /* Constructor */) { var symbol = getSymbolOfNode(container.parent); return getTypeOfSymbol(symbol); } @@ -40155,11 +46808,11 @@ var ts; } } function checkImportMetaProperty(node) { - if (languageVersion < 6 || moduleKind < ts.ModuleKind.ESNext) { + if (languageVersion < 6 /* ESNext */ || moduleKind < ts.ModuleKind.ESNext) { error(node, ts.Diagnostics.The_import_meta_meta_property_is_only_allowed_using_ESNext_for_the_target_and_module_compiler_options); } var file = ts.getSourceFileOfNode(node); - ts.Debug.assert(!!(file.flags & 1048576), "Containing file is missing import meta node flag."); + ts.Debug.assert(!!(file.flags & 1048576 /* PossiblyContainsImportMeta */), "Containing file is missing import meta node flag."); ts.Debug.assert(!!file.externalModuleIndicator, "Containing file should be a module."); return node.name.escapedText === "meta" ? getGlobalImportMetaType() : errorType; } @@ -40202,7 +46855,7 @@ var ts; var parameter = signature.thisParameter; if (!parameter || parameter.valueDeclaration && !parameter.valueDeclaration.type) { if (!parameter) { - signature.thisParameter = createSymbolWithType(context.thisParameter, undefined); + signature.thisParameter = createSymbolWithType(context.thisParameter, /*type*/ undefined); } assignTypeToParameterAndFixTypeParameters(signature.thisParameter, getTypeOfSymbol(context.thisParameter)); } @@ -40216,6 +46869,7 @@ var ts; } } if (signature.hasRestParameter && isRestParameterIndex(context, signature.parameters.length - 1)) { + // parameter might be a transient symbol generated by use of `arguments` in the function body. var parameter = ts.last(signature.parameters); if (isTransientSymbol(parameter) || !ts.getEffectiveTypeAnnotationNode(parameter.valueDeclaration)) { var contextualParameterType = getTypeOfSymbol(ts.last(context.parameters)); @@ -40223,11 +46877,13 @@ var ts; } } } + // When contextual typing assigns a type to a parameter that contains a binding pattern, we also need to push + // the destructured type into the contained binding elements. function assignBindingElementTypes(pattern) { for (var _i = 0, _a = pattern.elements; _i < _a.length; _i++) { var element = _a[_i]; if (!ts.isOmittedExpression(element)) { - if (element.name.kind === 71) { + if (element.name.kind === 71 /* Identifier */) { getSymbolLinks(getSymbolOfNode(element)).type = getTypeForBindingElement(element); } else { @@ -40241,7 +46897,8 @@ var ts; if (!links.type) { links.type = contextualType; var decl = parameter.valueDeclaration; - if (decl.name.kind !== 71) { + if (decl.name.kind !== 71 /* Identifier */) { + // if inference didn't come up with anything but {}, fall back to the binding pattern if present. if (links.type === emptyObjectType) { links.type = getTypeFromBindingPattern(decl.name); } @@ -40250,8 +46907,10 @@ var ts; } } function createPromiseType(promisedType) { - var globalPromiseType = getGlobalPromiseType(true); + // creates a `Promise` type where `T` is the promisedType argument + var globalPromiseType = getGlobalPromiseType(/*reportErrors*/ true); if (globalPromiseType !== emptyGenericType) { + // if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type promisedType = getAwaitedType(promisedType) || emptyObjectType; return createTypeReference(globalPromiseType, [promisedType]); } @@ -40265,7 +46924,7 @@ var ts; ts.Diagnostics.An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option); return errorType; } - else if (!getGlobalPromiseConstructorSymbol(true)) { + else if (!getGlobalPromiseConstructorSymbol(/*reportErrors*/ true)) { error(func, ts.isImportCall(func) ? ts.Diagnostics.A_dynamic_import_call_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option : ts.Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option); @@ -40278,20 +46937,24 @@ var ts; } var functionFlags = ts.getFunctionFlags(func); var type; - if (func.body.kind !== 213) { + if (func.body.kind !== 213 /* Block */) { type = checkExpressionCached(func.body, checkMode); - if (functionFlags & 2) { - type = checkAwaitedType(type, func, ts.Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); + if (functionFlags & 2 /* Async */) { + // From within an async function you can return either a non-promise value or a promise. Any + // Promise/A+ compatible implementation will always assimilate any foreign promise, so the + // return type of the body should be unwrapped to its awaited type, which we will wrap in + // the native Promise type later in this function. + type = checkAwaitedType(type, /*errorNode*/ func, ts.Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); } } else { var types = checkAndAggregateReturnExpressionTypes(func, checkMode); - if (functionFlags & 1) { + if (functionFlags & 1 /* Generator */) { // Generator or AsyncGenerator function types = ts.concatenate(checkAndAggregateYieldOperandTypes(func, checkMode), types); if (!types || types.length === 0) { - var iterableIteratorAny = functionFlags & 2 - ? createAsyncIterableIteratorType(anyType) - : createIterableIteratorType(anyType); + var iterableIteratorAny = functionFlags & 2 /* Async */ + ? createAsyncIterableIteratorType(anyType) // AsyncGenerator function + : createIterableIteratorType(anyType); // Generator function if (noImplicitAny) { error(func.asteriskToken, ts.Diagnostics.Generator_implicitly_has_type_0_because_it_does_not_yield_any_values_Consider_supplying_a_return_type, typeToString(iterableIteratorAny)); } @@ -40300,17 +46963,20 @@ var ts; } else { if (!types) { - return functionFlags & 2 - ? createPromiseReturnType(func, neverType) - : neverType; + // For an async function, the return type will not be never, but rather a Promise for never. + return functionFlags & 2 /* Async */ + ? createPromiseReturnType(func, neverType) // Async function + : neverType; // Normal function } if (types.length === 0) { - return functionFlags & 2 - ? createPromiseReturnType(func, voidType) - : voidType; + // For an async function, the return type will not be void, but rather a Promise for void. + return functionFlags & 2 /* Async */ + ? createPromiseReturnType(func, voidType) // Async function + : voidType; // Normal function } } - type = getUnionType(types, 2); + // Return a union of the return expression types. + type = getUnionType(types, 2 /* Subtype */); } var contextualSignature = getContextualSignatureForFunctionLikeDeclaration(func); if (!contextualSignature) { @@ -40321,14 +46987,14 @@ var ts; contextualSignature === getSignatureFromDeclaration(func) ? type : getReturnTypeOfSignature(contextualSignature); if (contextualType) { - switch (functionFlags & 3) { - case 3: - contextualType = getIteratedTypeOfGenerator(contextualType, true); + switch (functionFlags & 3 /* AsyncGenerator */) { + case 3 /* AsyncGenerator */: + contextualType = getIteratedTypeOfGenerator(contextualType, /*isAsyncGenerator*/ true); break; - case 1: - contextualType = getIteratedTypeOfGenerator(contextualType, false); + case 1 /* Generator */: + contextualType = getIteratedTypeOfGenerator(contextualType, /*isAsyncGenerator*/ false); break; - case 2: + case 2 /* Async */: contextualType = getPromisedTypeOfPromise(contextualType); break; } @@ -40336,12 +47002,15 @@ var ts; type = getWidenedLiteralLikeTypeForContextualType(type, contextualType); } var widenedType = getWidenedType(type); - switch (functionFlags & 3) { - case 3: + switch (functionFlags & 3 /* AsyncGenerator */) { + case 3 /* AsyncGenerator */: return createAsyncIterableIteratorType(widenedType); - case 1: + case 1 /* Generator */: return createIterableIteratorType(widenedType); - case 2: + case 2 /* Async */: + // From within an async function you can return either a non-promise value or a promise. Any + // Promise/A+ compatible implementation will always assimilate any foreign promise, so the + // return type of the body is awaited type of the body, wrapped in a native Promise type. return createPromiseType(widenedType); default: return widenedType; @@ -40349,7 +47018,7 @@ var ts; } function checkAndAggregateYieldOperandTypes(func, checkMode) { var aggregatedTypes = []; - var isAsync = (ts.getFunctionFlags(func) & 2) !== 0; + var isAsync = (ts.getFunctionFlags(func) & 2 /* Async */) !== 0; ts.forEachYieldExpression(func.body, function (yieldExpression) { ts.pushIfUnique(aggregatedTypes, getYieldedTypeOfYieldExpression(yieldExpression, isAsync, checkMode)); }); @@ -40358,7 +47027,8 @@ var ts; function getYieldedTypeOfYieldExpression(node, isAsync, checkMode) { var errorNode = node.expression || node; var expressionType = node.expression ? checkExpressionCached(node.expression, checkMode) : undefinedWideningType; - var yieldedType = node.asteriskToken ? checkIteratedTypeOrElementType(expressionType, errorNode, false, isAsync) : expressionType; + // A `yield*` expression effectively yields everything that its operand yields + var yieldedType = node.asteriskToken ? checkIteratedTypeOrElementType(expressionType, errorNode, /*allowStringInput*/ false, isAsync) : expressionType; return !isAsync ? yieldedType : getAwaitedType(yieldedType, errorNode, node.asteriskToken ? ts.Diagnostics.Type_of_iterated_elements_of_a_yield_Asterisk_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member : ts.Diagnostics.Type_of_yield_operand_in_an_async_generator_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); @@ -40378,14 +47048,15 @@ var ts; return eachTypeContainedIn(mapType(type, getRegularTypeOfLiteralType), switchTypes); } function functionHasImplicitReturn(func) { - if (!(func.flags & 128)) { + if (!(func.flags & 128 /* HasImplicitReturn */)) { return false; } - if (ts.some(func.body.statements, function (statement) { return statement.kind === 227 && isExhaustiveSwitchStatement(statement); })) { + if (ts.some(func.body.statements, function (statement) { return statement.kind === 227 /* SwitchStatement */ && isExhaustiveSwitchStatement(statement); })) { return false; } return true; } + /** NOTE: Return value of `[]` means a different thing than `undefined`. `[]` means func returns `void`, `undefined` means it returns `never`. */ function checkAndAggregateReturnExpressionTypes(func, checkMode) { var functionFlags = ts.getFunctionFlags(func); var aggregatedTypes = []; @@ -40395,10 +47066,14 @@ var ts; var expr = returnStatement.expression; if (expr) { var type = checkExpressionCached(expr, checkMode); - if (functionFlags & 2) { + if (functionFlags & 2 /* Async */) { + // From within an async function you can return either a non-promise value or a promise. Any + // Promise/A+ compatible implementation will always assimilate any foreign promise, so the + // return type of the body should be unwrapped to its awaited type, which should be wrapped in + // the native Promise type by the caller. type = checkAwaitedType(type, func, ts.Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); } - if (type.flags & 32768) { + if (type.flags & 32768 /* Never */) { hasReturnOfTypeNever = true; } ts.pushIfUnique(aggregatedTypes, type); @@ -40412,36 +47087,52 @@ var ts; } if (strictNullChecks && aggregatedTypes.length && hasReturnWithNoExpression && !(isJavaScriptConstructor(func) && aggregatedTypes.some(function (t) { return t.symbol === func.symbol; }))) { + // Javascript "callable constructors", containing eg `if (!(this instanceof A)) return new A()` should not add undefined ts.pushIfUnique(aggregatedTypes, undefinedType); } return aggregatedTypes; } function mayReturnNever(func) { switch (func.kind) { - case 192: - case 193: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: return true; - case 154: - return func.parent.kind === 184; + case 154 /* MethodDeclaration */: + return func.parent.kind === 184 /* ObjectLiteralExpression */; default: return false; } } + /** + * TypeScript Specification 1.0 (6.3) - July 2014 + * An explicitly typed function whose return type isn't the Void type, + * the Any type, or a union type containing the Void or Any type as a constituent + * must have at least one return statement somewhere in its body. + * An exception to this rule is if the function implementation consists of a single 'throw' statement. + * + * @param returnType - return type of the function, can be undefined if return type is not explicitly specified + */ function checkAllCodePathsInNonVoidFunctionReturnOrThrow(func, returnType) { if (!produceDiagnostics) { return; } - if (returnType && maybeTypeOfKind(returnType, 3 | 4096)) { + // Functions with with an explicitly specified 'void' or 'any' return type don't need any return expressions. + if (returnType && maybeTypeOfKind(returnType, 3 /* AnyOrUnknown */ | 4096 /* Void */)) { return; } - if (func.kind === 153 || ts.nodeIsMissing(func.body) || func.body.kind !== 213 || !functionHasImplicitReturn(func)) { + // If all we have is a function signature, or an arrow function with an expression body, then there is nothing to check. + // also if HasImplicitReturn flag is not set this means that all codepaths in function body end with return or throw + if (func.kind === 153 /* MethodSignature */ || ts.nodeIsMissing(func.body) || func.body.kind !== 213 /* Block */ || !functionHasImplicitReturn(func)) { return; } - var hasExplicitReturn = func.flags & 256; - if (returnType && returnType.flags & 32768) { + var hasExplicitReturn = func.flags & 256 /* HasExplicitReturn */; + if (returnType && returnType.flags & 32768 /* Never */) { error(ts.getEffectiveReturnTypeNode(func), ts.Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point); } else if (returnType && !hasExplicitReturn) { + // minimal check: function has syntactic return type annotation and no explicit return statements in the body + // this function does not conform to the specification. + // NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present error(ts.getEffectiveReturnTypeNode(func), ts.Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value); } else if (returnType && strictNullChecks && !isTypeAssignableTo(undefinedType, returnType)) { @@ -40449,6 +47140,9 @@ var ts; } else if (compilerOptions.noImplicitReturns) { if (!returnType) { + // If return type annotation is omitted check if function has any explicit return statements. + // If it does not have any - its inferred return type is void - don't do any checks. + // Otherwise get inferred return type from function body and report error only if it is not void / anytype if (!hasExplicitReturn) { return; } @@ -40461,12 +47155,14 @@ var ts; } } function checkFunctionExpressionOrObjectLiteralMethod(node, checkMode) { - ts.Debug.assert(node.kind !== 154 || ts.isObjectLiteralMethod(node)); - if (checkMode === 1 && isContextSensitive(node)) { + ts.Debug.assert(node.kind !== 154 /* MethodDeclaration */ || ts.isObjectLiteralMethod(node)); + // The identityMapper object is used to indicate that function expressions are wildcards + if (checkMode === 1 /* SkipContextSensitive */ && isContextSensitive(node)) { return anyFunctionType; } + // Grammar checking var hasGrammarError = checkGrammarFunctionLikeDeclaration(node); - if (!hasGrammarError && node.kind === 192) { + if (!hasGrammarError && node.kind === 192 /* FunctionExpression */) { checkGrammarForGenerator(node); } var links = getNodeLinks(node); @@ -40474,15 +47170,19 @@ var ts; if (isTypeAny(type)) { return type; } - if (!(links.flags & 1024)) { + // Check if function expression is contextually typed and assign parameter types if so. + if (!(links.flags & 1024 /* ContextChecked */)) { var contextualSignature = getContextualSignature(node); - if (!(links.flags & 1024)) { - links.flags |= 1024; + // If a type check is started at a function expression that is an argument of a function call, obtaining the + // contextual type may recursively get back to here during overload resolution of the call. If so, we will have + // already assigned contextual types. + if (!(links.flags & 1024 /* ContextChecked */)) { + links.flags |= 1024 /* ContextChecked */; if (contextualSignature) { - var signature = getSignaturesOfType(type, 0)[0]; + var signature = getSignaturesOfType(type, 0 /* Call */)[0]; if (isContextSensitive(node)) { var contextualMapper = getContextualMapper(node); - if (checkMode === 2) { + if (checkMode === 2 /* Inferential */) { inferFromAnnotatedParameters(signature, contextualSignature, contextualMapper); } var instantiatedContextualSignature = contextualMapper === identityMapper ? @@ -40503,31 +47203,42 @@ var ts; return type; } function checkFunctionExpressionOrObjectLiteralMethodDeferred(node) { - ts.Debug.assert(node.kind !== 154 || ts.isObjectLiteralMethod(node)); + ts.Debug.assert(node.kind !== 154 /* MethodDeclaration */ || ts.isObjectLiteralMethod(node)); var functionFlags = ts.getFunctionFlags(node); var returnTypeNode = ts.getEffectiveReturnTypeNode(node); var returnOrPromisedType = returnTypeNode && - ((functionFlags & 3) === 2 ? - checkAsyncFunctionReturnType(node) : - getTypeFromTypeNode(returnTypeNode)); - if ((functionFlags & 1) === 0) { + ((functionFlags & 3 /* AsyncGenerator */) === 2 /* Async */ ? + checkAsyncFunctionReturnType(node) : // Async function + getTypeFromTypeNode(returnTypeNode)); // AsyncGenerator function, Generator function, or normal function + if ((functionFlags & 1 /* Generator */) === 0) { // Async function or normal function + // return is not necessary in the body of generators checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType); } if (node.body) { if (!returnTypeNode) { + // There are some checks that are only performed in getReturnTypeFromBody, that may produce errors + // we need. An example is the noImplicitAny errors resulting from widening the return expression + // of a function. Because checking of function expression bodies is deferred, there was never an + // appropriate time to do this during the main walk of the file (see the comment at the top of + // checkFunctionExpressionBodies). So it must be done now. getReturnTypeOfSignature(getSignatureFromDeclaration(node)); } - if (node.body.kind === 213) { + if (node.body.kind === 213 /* Block */) { checkSourceElement(node.body); } else { + // From within an async function you can return either a non-promise value or a promise. Any + // Promise/A+ compatible implementation will always assimilate any foreign promise, so we + // should not be checking assignability of a promise to the return type. Instead, we need to + // check assignability of the awaited type of the expression body against the promised type of + // its return type annotation. var exprType = checkExpression(node.body); if (returnOrPromisedType) { - if ((functionFlags & 3) === 2) { + if ((functionFlags & 3 /* AsyncGenerator */) === 2 /* Async */) { // Async function var awaitedType = checkAwaitedType(exprType, node.body, ts.Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); checkTypeAssignableTo(awaitedType, returnOrPromisedType, node.body); } - else { + else { // Normal function checkTypeAssignableTo(exprType, returnOrPromisedType, node.body); } } @@ -40535,28 +47246,39 @@ var ts; } } function checkArithmeticOperandType(operand, type, diagnostic) { - if (!isTypeAssignableToKind(type, 168)) { + if (!isTypeAssignableToKind(type, 168 /* NumberLike */)) { error(operand, diagnostic); return false; } return true; } function isReadonlySymbol(symbol) { - return !!(ts.getCheckFlags(symbol) & 8 || - symbol.flags & 4 && ts.getDeclarationModifierFlagsFromSymbol(symbol) & 64 || - symbol.flags & 3 && getDeclarationNodeFlagsFromSymbol(symbol) & 2 || - symbol.flags & 98304 && !(symbol.flags & 65536) || - symbol.flags & 8); + // The following symbols are considered read-only: + // Properties with a 'readonly' modifier + // Variables declared with 'const' + // Get accessors without matching set accessors + // Enum members + // Unions and intersections of the above (unions and intersections eagerly set isReadonly on creation) + return !!(ts.getCheckFlags(symbol) & 8 /* Readonly */ || + symbol.flags & 4 /* Property */ && ts.getDeclarationModifierFlagsFromSymbol(symbol) & 64 /* Readonly */ || + symbol.flags & 3 /* Variable */ && getDeclarationNodeFlagsFromSymbol(symbol) & 2 /* Const */ || + symbol.flags & 98304 /* Accessor */ && !(symbol.flags & 65536 /* SetAccessor */) || + symbol.flags & 8 /* EnumMember */); } function isReferenceToReadonlyEntity(expr, symbol) { if (isReadonlySymbol(symbol)) { - if (symbol.flags & 4 && - (expr.kind === 185 || expr.kind === 186) && - expr.expression.kind === 99) { + // Allow assignments to readonly properties within constructors of the same class declaration. + if (symbol.flags & 4 /* Property */ && + (expr.kind === 185 /* PropertyAccessExpression */ || expr.kind === 186 /* ElementAccessExpression */) && + expr.expression.kind === 99 /* ThisKeyword */) { + // Look for if this is the constructor for the class that `symbol` is a property of. var func = ts.getContainingFunction(expr); - if (!(func && func.kind === 155)) { + if (!(func && func.kind === 155 /* Constructor */)) { return true; } + // If func.parent is a class and symbol is a (readonly) property of that class, or + // if func is a constructor and symbol is a (readonly) parameter property declared in it, + // then symbol is writeable here. return !(func.parent === symbol.valueDeclaration.parent || func === symbol.valueDeclaration.parent); } return true; @@ -40564,21 +47286,22 @@ var ts; return false; } function isReferenceThroughNamespaceImport(expr) { - if (expr.kind === 185 || expr.kind === 186) { + if (expr.kind === 185 /* PropertyAccessExpression */ || expr.kind === 186 /* ElementAccessExpression */) { var node = ts.skipParentheses(expr.expression); - if (node.kind === 71) { + if (node.kind === 71 /* Identifier */) { var symbol = getNodeLinks(node).resolvedSymbol; - if (symbol.flags & 2097152) { + if (symbol.flags & 2097152 /* Alias */) { var declaration = getDeclarationOfAliasSymbol(symbol); - return !!declaration && declaration.kind === 246; + return !!declaration && declaration.kind === 246 /* NamespaceImport */; } } } return false; } function checkReferenceExpression(expr, invalidReferenceMessage) { - var node = ts.skipOuterExpressions(expr, 2 | 1); - if (node.kind !== 71 && node.kind !== 185 && node.kind !== 186) { + // References are combinations of identifiers, parentheses, and property accesses. + var node = ts.skipOuterExpressions(expr, 2 /* Assertions */ | 1 /* Parentheses */); + if (node.kind !== 71 /* Identifier */ && node.kind !== 185 /* PropertyAccessExpression */ && node.kind !== 186 /* ElementAccessExpression */) { error(expr, invalidReferenceMessage); return false; } @@ -40587,7 +47310,7 @@ var ts; function checkDeleteExpression(node) { checkExpression(node.expression); var expr = ts.skipParentheses(node.expression); - if (expr.kind !== 185 && expr.kind !== 186) { + if (expr.kind !== 185 /* PropertyAccessExpression */ && expr.kind !== 186 /* ElementAccessExpression */) { error(expr, ts.Diagnostics.The_operand_of_a_delete_operator_must_be_a_property_reference); return booleanType; } @@ -40607,8 +47330,9 @@ var ts; return undefinedWideningType; } function checkAwaitExpression(node) { + // Grammar checking if (produceDiagnostics) { - if (!(node.flags & 16384)) { + if (!(node.flags & 16384 /* AwaitContext */)) { grammarErrorOnFirstToken(node, ts.Diagnostics.await_expression_is_only_allowed_within_an_async_function); } if (isInParameterInitializerBeforeContainingFunction(node)) { @@ -40623,32 +47347,33 @@ var ts; if (operandType === silentNeverType) { return silentNeverType; } - if (node.operand.kind === 8) { - if (node.operator === 38) { + if (node.operand.kind === 8 /* NumericLiteral */) { + if (node.operator === 38 /* MinusToken */) { return getFreshTypeOfLiteralType(getLiteralType(-node.operand.text)); } - else if (node.operator === 37) { + else if (node.operator === 37 /* PlusToken */) { return getFreshTypeOfLiteralType(getLiteralType(+node.operand.text)); } } switch (node.operator) { - case 37: - case 38: - case 52: + case 37 /* PlusToken */: + case 38 /* MinusToken */: + case 52 /* TildeToken */: checkNonNullType(operandType, node.operand); - if (maybeTypeOfKind(operandType, 3072)) { + if (maybeTypeOfKind(operandType, 3072 /* ESSymbolLike */)) { error(node.operand, ts.Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, ts.tokenToString(node.operator)); } return numberType; - case 51: - var facts = getTypeFacts(operandType) & (1048576 | 2097152); - return facts === 1048576 ? falseType : - facts === 2097152 ? trueType : + case 51 /* ExclamationToken */: + var facts = getTypeFacts(operandType) & (1048576 /* Truthy */ | 2097152 /* Falsy */); + return facts === 1048576 /* Truthy */ ? falseType : + facts === 2097152 /* Falsy */ ? trueType : booleanType; - case 43: - case 44: + case 43 /* PlusPlusToken */: + case 44 /* MinusMinusToken */: var ok = checkArithmeticOperandType(node.operand, checkNonNullType(operandType, node.operand), ts.Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type); if (ok) { + // run check only if former checks succeeded to avoid reporting cascading errors checkReferenceExpression(node.operand, ts.Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access); } return numberType; @@ -40662,15 +47387,18 @@ var ts; } var ok = checkArithmeticOperandType(node.operand, checkNonNullType(operandType, node.operand), ts.Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type); if (ok) { + // run check only if former checks succeeded to avoid reporting cascading errors checkReferenceExpression(node.operand, ts.Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access); } return numberType; } + // Return true if type might be of the given kind. A union or intersection type might be of a given + // kind if at least one constituent type is of the given kind. function maybeTypeOfKind(type, kind) { - if (type.flags & kind & ~134217728 || kind & 134217728 && isGenericMappedType(type)) { + if (type.flags & kind & ~134217728 /* GenericMappedType */ || kind & 134217728 /* GenericMappedType */ && isGenericMappedType(type)) { return true; } - if (type.flags & 786432) { + if (type.flags & 786432 /* UnionOrIntersection */) { var types = type.types; for (var _i = 0, types_16 = types; _i < types_16.length; _i++) { var t = types_16[_i]; @@ -40685,38 +47413,44 @@ var ts; if (source.flags & kind) { return true; } - if (strict && source.flags & (3 | 4096 | 8192 | 16384)) { + if (strict && source.flags & (3 /* AnyOrUnknown */ | 4096 /* Void */ | 8192 /* Undefined */ | 16384 /* Null */)) { return false; } - return !!(kind & 168) && isTypeAssignableTo(source, numberType) || - !!(kind & 68) && isTypeAssignableTo(source, stringType) || - !!(kind & 272) && isTypeAssignableTo(source, booleanType) || - !!(kind & 4096) && isTypeAssignableTo(source, voidType) || - !!(kind & 32768) && isTypeAssignableTo(source, neverType) || - !!(kind & 16384) && isTypeAssignableTo(source, nullType) || - !!(kind & 8192) && isTypeAssignableTo(source, undefinedType) || - !!(kind & 1024) && isTypeAssignableTo(source, esSymbolType) || - !!(kind & 16777216) && isTypeAssignableTo(source, nonPrimitiveType); + return !!(kind & 168 /* NumberLike */) && isTypeAssignableTo(source, numberType) || + !!(kind & 68 /* StringLike */) && isTypeAssignableTo(source, stringType) || + !!(kind & 272 /* BooleanLike */) && isTypeAssignableTo(source, booleanType) || + !!(kind & 4096 /* Void */) && isTypeAssignableTo(source, voidType) || + !!(kind & 32768 /* Never */) && isTypeAssignableTo(source, neverType) || + !!(kind & 16384 /* Null */) && isTypeAssignableTo(source, nullType) || + !!(kind & 8192 /* Undefined */) && isTypeAssignableTo(source, undefinedType) || + !!(kind & 1024 /* ESSymbol */) && isTypeAssignableTo(source, esSymbolType) || + !!(kind & 16777216 /* NonPrimitive */) && isTypeAssignableTo(source, nonPrimitiveType); } function allTypesAssignableToKind(source, kind, strict) { - return source.flags & 262144 ? + return source.flags & 262144 /* Union */ ? ts.every(source.types, function (subType) { return allTypesAssignableToKind(subType, kind, strict); }) : isTypeAssignableToKind(source, kind, strict); } function isConstEnumObjectType(type) { - return !!(ts.getObjectFlags(type) & 16) && !!type.symbol && isConstEnumSymbol(type.symbol); + return !!(ts.getObjectFlags(type) & 16 /* Anonymous */) && !!type.symbol && isConstEnumSymbol(type.symbol); } function isConstEnumSymbol(symbol) { - return (symbol.flags & 128) !== 0; + return (symbol.flags & 128 /* ConstEnum */) !== 0; } function checkInstanceOfExpression(left, right, leftType, rightType) { if (leftType === silentNeverType || rightType === silentNeverType) { return silentNeverType; } + // TypeScript 1.0 spec (April 2014): 4.15.4 + // The instanceof operator requires the left operand to be of type Any, an object type, or a type parameter type, + // and the right operand to be of type Any, a subtype of the 'Function' interface type, or have a call or construct signature. + // The result is always of the Boolean primitive type. + // NOTE: do not raise error if leftType is unknown as related error was already reported if (!isTypeAny(leftType) && - allTypesAssignableToKind(leftType, 32764)) { + allTypesAssignableToKind(leftType, 32764 /* Primitive */)) { error(left, ts.Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); } + // NOTE: do not raise error if right is unknown as related error was already reported if (!(isTypeAny(rightType) || typeHasCallOrConstructSignatures(rightType) || isTypeSubtypeOf(rightType, globalFunctionType))) { error(right, ts.Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type); } @@ -40728,10 +47462,14 @@ var ts; } leftType = checkNonNullType(leftType, left); rightType = checkNonNullType(rightType, right); - if (!(isTypeComparableTo(leftType, stringType) || isTypeAssignableToKind(leftType, 168 | 3072))) { + // TypeScript 1.0 spec (April 2014): 4.15.5 + // The in operator requires the left operand to be of type Any, the String primitive type, or the Number primitive type, + // and the right operand to be of type Any, an object type, or a type parameter type. + // The result is always of the Boolean primitive type. + if (!(isTypeComparableTo(leftType, stringType) || isTypeAssignableToKind(leftType, 168 /* NumberLike */ | 3072 /* ESSymbolLike */))) { error(left, ts.Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol); } - if (!isTypeAssignableToKind(rightType, 16777216 | 14745600)) { + if (!isTypeAssignableToKind(rightType, 16777216 /* NonPrimitive */ | 14745600 /* InstantiableNonPrimitive */)) { error(right, ts.Diagnostics.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); } return booleanType; @@ -40747,10 +47485,11 @@ var ts; } return sourceType; } + /** Note: If property cannot be a SpreadAssignment, then allProperties does not need to be provided */ function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType, property, allProperties) { - if (property.kind === 270 || property.kind === 271) { + if (property.kind === 270 /* PropertyAssignment */ || property.kind === 271 /* ShorthandPropertyAssignment */) { var name = property.name; - if (name.kind === 147) { + if (name.kind === 147 /* ComputedPropertyName */) { checkComputedPropertyName(name); } if (isComputedNonLiteralName(name)) { @@ -40760,13 +47499,14 @@ var ts; var type = isTypeAny(objectLiteralType) ? objectLiteralType : getTypeOfPropertyOfType(objectLiteralType, text) || - isNumericLiteralName(text) && getIndexTypeOfType(objectLiteralType, 1) || - getIndexTypeOfType(objectLiteralType, 0); + isNumericLiteralName(text) && getIndexTypeOfType(objectLiteralType, 1 /* Number */) || + getIndexTypeOfType(objectLiteralType, 0 /* String */); if (type) { - if (property.kind === 271) { + if (property.kind === 271 /* ShorthandPropertyAssignment */) { return checkDestructuringAssignment(property, type); } else { + // non-shorthand property assignments should always have initializers return checkDestructuringAssignment(property.initializer, type); } } @@ -40774,9 +47514,9 @@ var ts; error(name, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(objectLiteralType), ts.declarationNameToString(name)); } } - else if (property.kind === 272) { - if (languageVersion < 6) { - checkExternalEmitHelpers(property, 4); + else if (property.kind === 272 /* SpreadAssignment */) { + if (languageVersion < 6 /* ESNext */) { + checkExternalEmitHelpers(property, 4 /* Rest */); } var nonRestNames = []; if (allProperties) { @@ -40794,10 +47534,13 @@ var ts; } function checkArrayLiteralAssignment(node, sourceType, checkMode) { var elements = node.elements; - if (languageVersion < 2 && compilerOptions.downlevelIteration) { - checkExternalEmitHelpers(node, 512); + if (languageVersion < 2 /* ES2015 */ && compilerOptions.downlevelIteration) { + checkExternalEmitHelpers(node, 512 /* Read */); } - var elementType = checkIteratedTypeOrElementType(sourceType, node, false, false) || errorType; + // This elementType will be used if the specific property corresponding to this index is not + // present (aka the tuple element property). This call also checks that the parentType is in + // fact an iterable or array (depending on target language). + var elementType = checkIteratedTypeOrElementType(sourceType, node, /*allowStringInput*/ false, /*allowAsyncIterables*/ false) || errorType; for (var i = 0; i < elements.length; i++) { checkArrayLiteralDestructuringElementAssignment(node, sourceType, i, elementType, checkMode); } @@ -40806,8 +47549,8 @@ var ts; function checkArrayLiteralDestructuringElementAssignment(node, sourceType, elementIndex, elementType, checkMode) { var elements = node.elements; var element = elements[elementIndex]; - if (element.kind !== 206) { - if (element.kind !== 204) { + if (element.kind !== 206 /* OmittedExpression */) { + if (element.kind !== 204 /* SpreadElement */) { var propName = "" + elementIndex; var type = isTypeAny(sourceType) ? sourceType @@ -40818,6 +47561,8 @@ var ts; return checkDestructuringAssignment(element, type, checkMode); } else { + // We still need to check element expression here because we may need to set appropriate flag on the expression + // such as NodeCheckFlags.LexicalThis on "this"expression. checkExpression(element); if (isTupleType(sourceType)) { error(element, ts.Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(sourceType), getTypeReferenceArity(sourceType), elements.length); @@ -40833,7 +47578,7 @@ var ts; } else { var restExpression = element.expression; - if (restExpression.kind === 200 && restExpression.operatorToken.kind === 58) { + if (restExpression.kind === 200 /* BinaryExpression */ && restExpression.operatorToken.kind === 58 /* EqualsToken */) { error(restExpression.operatorToken, ts.Diagnostics.A_rest_element_cannot_have_an_initializer); } else { @@ -40847,12 +47592,14 @@ var ts; } function checkDestructuringAssignment(exprOrAssignment, sourceType, checkMode) { var target; - if (exprOrAssignment.kind === 271) { + if (exprOrAssignment.kind === 271 /* ShorthandPropertyAssignment */) { var prop = exprOrAssignment; if (prop.objectAssignmentInitializer) { + // In strict null checking mode, if a default value of a non-undefined type is specified, remove + // undefined from the final type. if (strictNullChecks && - !(getFalsyFlags(checkExpression(prop.objectAssignmentInitializer)) & 8192)) { - sourceType = getTypeWithFacts(sourceType, 131072); + !(getFalsyFlags(checkExpression(prop.objectAssignmentInitializer)) & 8192 /* Undefined */)) { + sourceType = getTypeWithFacts(sourceType, 131072 /* NEUndefined */); } checkBinaryLikeExpression(prop.name, prop.equalsToken, prop.objectAssignmentInitializer, checkMode); } @@ -40861,80 +47608,91 @@ var ts; else { target = exprOrAssignment; } - if (target.kind === 200 && target.operatorToken.kind === 58) { + if (target.kind === 200 /* BinaryExpression */ && target.operatorToken.kind === 58 /* EqualsToken */) { checkBinaryExpression(target, checkMode); target = target.left; } - if (target.kind === 184) { + if (target.kind === 184 /* ObjectLiteralExpression */) { return checkObjectLiteralAssignment(target, sourceType); } - if (target.kind === 183) { + if (target.kind === 183 /* ArrayLiteralExpression */) { return checkArrayLiteralAssignment(target, sourceType, checkMode); } return checkReferenceAssignment(target, sourceType, checkMode); } function checkReferenceAssignment(target, sourceType, checkMode) { var targetType = checkExpression(target, checkMode); - var error = target.parent.kind === 272 ? + var error = target.parent.kind === 272 /* SpreadAssignment */ ? ts.Diagnostics.The_target_of_an_object_rest_assignment_must_be_a_variable_or_a_property_access : ts.Diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access; if (checkReferenceExpression(target, error)) { - checkTypeAssignableTo(sourceType, targetType, target, undefined); + checkTypeAssignableTo(sourceType, targetType, target, /*headMessage*/ undefined); } return sourceType; } + /** + * This is a *shallow* check: An expression is side-effect-free if the + * evaluation of the expression *itself* cannot produce side effects. + * For example, x++ / 3 is side-effect free because the / operator + * does not have side effects. + * The intent is to "smell test" an expression for correctness in positions where + * its value is discarded (e.g. the left side of the comma operator). + */ function isSideEffectFree(node) { node = ts.skipParentheses(node); switch (node.kind) { - case 71: - case 9: - case 12: - case 189: - case 202: - case 13: - case 8: - case 101: - case 86: - case 95: - case 140: - case 192: - case 205: - case 193: - case 183: - case 184: - case 195: - case 209: - case 256: - case 255: + case 71 /* Identifier */: + case 9 /* StringLiteral */: + case 12 /* RegularExpressionLiteral */: + case 189 /* TaggedTemplateExpression */: + case 202 /* TemplateExpression */: + case 13 /* NoSubstitutionTemplateLiteral */: + case 8 /* NumericLiteral */: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: + case 95 /* NullKeyword */: + case 140 /* UndefinedKeyword */: + case 192 /* FunctionExpression */: + case 205 /* ClassExpression */: + case 193 /* ArrowFunction */: + case 183 /* ArrayLiteralExpression */: + case 184 /* ObjectLiteralExpression */: + case 195 /* TypeOfExpression */: + case 209 /* NonNullExpression */: + case 256 /* JsxSelfClosingElement */: + case 255 /* JsxElement */: return true; - case 201: + case 201 /* ConditionalExpression */: return isSideEffectFree(node.whenTrue) && isSideEffectFree(node.whenFalse); - case 200: + case 200 /* BinaryExpression */: if (ts.isAssignmentOperator(node.operatorToken.kind)) { return false; } return isSideEffectFree(node.left) && isSideEffectFree(node.right); - case 198: - case 199: + case 198 /* PrefixUnaryExpression */: + case 199 /* PostfixUnaryExpression */: + // Unary operators ~, !, +, and - have no side effects. + // The rest do. switch (node.operator) { - case 51: - case 37: - case 38: - case 52: + case 51 /* ExclamationToken */: + case 37 /* PlusToken */: + case 38 /* MinusToken */: + case 52 /* TildeToken */: return true; } return false; - case 196: - case 190: - case 208: + // Some forms listed here for clarity + case 196 /* VoidExpression */: // Explicit opt-out + case 190 /* TypeAssertionExpression */: // Not SEF, but can produce useful type warnings + case 208 /* AsExpression */: // Not SEF, but can produce useful type warnings default: return false; } } function isTypeEqualityComparableTo(source, target) { - return (target.flags & 24576) !== 0 || isTypeComparableTo(source, target); + return (target.flags & 24576 /* Nullable */) !== 0 || isTypeComparableTo(source, target); } function checkBinaryExpression(node, checkMode) { if (ts.isInJavaScriptFile(node) && ts.getAssignedJavascriptInitializer(node)) { @@ -40944,46 +47702,49 @@ var ts; } function checkBinaryLikeExpression(left, operatorToken, right, checkMode, errorNode) { var operator = operatorToken.kind; - if (operator === 58 && (left.kind === 184 || left.kind === 183)) { + if (operator === 58 /* EqualsToken */ && (left.kind === 184 /* ObjectLiteralExpression */ || left.kind === 183 /* ArrayLiteralExpression */)) { return checkDestructuringAssignment(left, checkExpression(right, checkMode), checkMode); } var leftType = checkExpression(left, checkMode); var rightType = checkExpression(right, checkMode); switch (operator) { - case 39: - case 40: - case 61: - case 62: - case 41: - case 63: - case 42: - case 64: - case 38: - case 60: - case 45: - case 65: - case 46: - case 66: - case 47: - case 67: - case 49: - case 69: - case 50: - case 70: - case 48: - case 68: + case 39 /* AsteriskToken */: + case 40 /* AsteriskAsteriskToken */: + case 61 /* AsteriskEqualsToken */: + case 62 /* AsteriskAsteriskEqualsToken */: + case 41 /* SlashToken */: + case 63 /* SlashEqualsToken */: + case 42 /* PercentToken */: + case 64 /* PercentEqualsToken */: + case 38 /* MinusToken */: + case 60 /* MinusEqualsToken */: + case 45 /* LessThanLessThanToken */: + case 65 /* LessThanLessThanEqualsToken */: + case 46 /* GreaterThanGreaterThanToken */: + case 66 /* GreaterThanGreaterThanEqualsToken */: + case 47 /* GreaterThanGreaterThanGreaterThanToken */: + case 67 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + case 49 /* BarToken */: + case 69 /* BarEqualsToken */: + case 50 /* CaretToken */: + case 70 /* CaretEqualsToken */: + case 48 /* AmpersandToken */: + case 68 /* AmpersandEqualsToken */: if (leftType === silentNeverType || rightType === silentNeverType) { return silentNeverType; } leftType = checkNonNullType(leftType, left); rightType = checkNonNullType(rightType, right); var suggestedOperator = void 0; - if ((leftType.flags & 272) && - (rightType.flags & 272) && + // if a user tries to apply a bitwise operator to 2 boolean operands + // try and return them a helpful suggestion + if ((leftType.flags & 272 /* BooleanLike */) && + (rightType.flags & 272 /* BooleanLike */) && (suggestedOperator = getSuggestedBooleanOperator(operatorToken.kind)) !== undefined) { error(errorNode || operatorToken, ts.Diagnostics.The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead, ts.tokenToString(operatorToken.kind), ts.tokenToString(suggestedOperator)); } else { + // otherwise just check each operand separately and report errors as normal var leftOk = checkArithmeticOperandType(left, leftType, ts.Diagnostics.The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type); var rightOk = checkArithmeticOperandType(right, rightType, ts.Diagnostics.The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type); if (leftOk && rightOk) { @@ -40991,25 +47752,31 @@ var ts; } } return numberType; - case 37: - case 59: + case 37 /* PlusToken */: + case 59 /* PlusEqualsToken */: if (leftType === silentNeverType || rightType === silentNeverType) { return silentNeverType; } - if (!isTypeAssignableToKind(leftType, 68) && !isTypeAssignableToKind(rightType, 68)) { + if (!isTypeAssignableToKind(leftType, 68 /* StringLike */) && !isTypeAssignableToKind(rightType, 68 /* StringLike */)) { leftType = checkNonNullType(leftType, left); rightType = checkNonNullType(rightType, right); } var resultType = void 0; - if (isTypeAssignableToKind(leftType, 168, true) && isTypeAssignableToKind(rightType, 168, true)) { + if (isTypeAssignableToKind(leftType, 168 /* NumberLike */, /*strict*/ true) && isTypeAssignableToKind(rightType, 168 /* NumberLike */, /*strict*/ true)) { + // Operands of an enum type are treated as having the primitive type Number. + // If both operands are of the Number primitive type, the result is of the Number primitive type. resultType = numberType; } - else if (isTypeAssignableToKind(leftType, 68, true) || isTypeAssignableToKind(rightType, 68, true)) { + else if (isTypeAssignableToKind(leftType, 68 /* StringLike */, /*strict*/ true) || isTypeAssignableToKind(rightType, 68 /* StringLike */, /*strict*/ true)) { + // If one or both operands are of the String primitive type, the result is of the String primitive type. resultType = stringType; } else if (isTypeAny(leftType) || isTypeAny(rightType)) { + // Otherwise, the result is of type Any. + // NOTE: unknown type here denotes error type. Old compiler treated this case as any type so do we. resultType = leftType === errorType || rightType === errorType ? errorType : anyType; } + // Symbols are not allowed at all in arithmetic expressions if (resultType && !checkForDisallowedESSymbolOperand(operator)) { return resultType; } @@ -41017,14 +47784,14 @@ var ts; reportOperatorError(); return anyType; } - if (operator === 59) { + if (operator === 59 /* PlusEqualsToken */) { checkAssignmentOperator(resultType); } return resultType; - case 27: - case 29: - case 30: - case 31: + case 27 /* LessThanToken */: + case 29 /* GreaterThanToken */: + case 30 /* LessThanEqualsToken */: + case 31 /* GreaterThanEqualsToken */: if (checkForDisallowedESSymbolOperand(operator)) { leftType = getBaseTypeOfLiteralType(checkNonNullType(leftType, left)); rightType = getBaseTypeOfLiteralType(checkNonNullType(rightType, right)); @@ -41033,10 +47800,10 @@ var ts; } } return booleanType; - case 32: - case 33: - case 34: - case 35: + case 32 /* EqualsEqualsToken */: + case 33 /* ExclamationEqualsToken */: + case 34 /* EqualsEqualsEqualsToken */: + case 35 /* ExclamationEqualsEqualsToken */: var leftIsLiteral = isLiteralType(leftType); var rightIsLiteral = isLiteralType(rightType); if (!leftIsLiteral || !rightIsLiteral) { @@ -41047,19 +47814,19 @@ var ts; reportOperatorError(); } return booleanType; - case 93: + case 93 /* InstanceOfKeyword */: return checkInstanceOfExpression(left, right, leftType, rightType); - case 92: + case 92 /* InKeyword */: return checkInExpression(left, right, leftType, rightType); - case 53: - return getTypeFacts(leftType) & 1048576 ? + case 53 /* AmpersandAmpersandToken */: + return getTypeFacts(leftType) & 1048576 /* Truthy */ ? getUnionType([extractDefinitelyFalsyTypes(strictNullChecks ? leftType : getBaseTypeOfLiteralType(rightType)), rightType]) : leftType; - case 54: - return getTypeFacts(leftType) & 2097152 ? - getUnionType([removeDefinitelyFalsyTypes(leftType), rightType], 2) : + case 54 /* BarBarToken */: + return getTypeFacts(leftType) & 2097152 /* Falsy */ ? + getUnionType([removeDefinitelyFalsyTypes(leftType), rightType], 2 /* Subtype */) : leftType; - case 58: + case 58 /* EqualsToken */: var special = ts.getSpecialPropertyAssignmentKind(left.parent); checkSpecialAssignment(special, right); if (isJSSpecialPropertyAssignment(special)) { @@ -41069,7 +47836,7 @@ var ts; checkAssignmentOperator(rightType); return getRegularTypeOfObjectLiteral(rightType); } - case 26: + case 26 /* CommaToken */: if (!compilerOptions.allowUnreachableCode && isSideEffectFree(left) && !isEvalNode(right)) { error(left, ts.Diagnostics.Left_side_of_comma_operator_is_unused_and_has_no_side_effects); } @@ -41078,14 +47845,14 @@ var ts; return ts.Debug.fail(); } function checkSpecialAssignment(special, right) { - if (special === 2) { + if (special === 2 /* ModuleExports */) { var rightType_1 = checkExpression(right, checkMode); for (var _i = 0, _a = getPropertiesOfObjectType(rightType_1); _i < _a.length; _i++) { var prop = _a[_i]; var propType = getTypeOfSymbol(prop); - if (propType.symbol && propType.symbol.flags & 32) { + if (propType.symbol && propType.symbol.flags & 32 /* Class */) { var name = prop.escapedName; - var symbol = resolveName(prop.valueDeclaration, name, 67901928, undefined, name, false); + var symbol = resolveName(prop.valueDeclaration, name, 67901928 /* Type */, undefined, name, /*isUse*/ false); if (symbol && symbol.declarations.some(ts.isJSDocTypedefTag)) { grammarErrorOnNode(symbol.declarations[0], ts.Diagnostics.Duplicate_identifier_0, ts.unescapeLeadingUnderscores(name)); return grammarErrorOnNode(prop.valueDeclaration, ts.Diagnostics.Duplicate_identifier_0, ts.unescapeLeadingUnderscores(name)); @@ -41095,11 +47862,12 @@ var ts; } } function isEvalNode(node) { - return node.kind === 71 && node.escapedText === "eval"; + return node.kind === 71 /* Identifier */ && node.escapedText === "eval"; } + // Return true if there was no error, false if there was an error. function checkForDisallowedESSymbolOperand(operator) { - var offendingSymbolOperand = maybeTypeOfKind(leftType, 3072) ? left : - maybeTypeOfKind(rightType, 3072) ? right : + var offendingSymbolOperand = maybeTypeOfKind(leftType, 3072 /* ESSymbolLike */) ? left : + maybeTypeOfKind(rightType, 3072 /* ESSymbolLike */) ? right : undefined; if (offendingSymbolOperand) { error(offendingSymbolOperand, ts.Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, ts.tokenToString(operator)); @@ -41109,35 +47877,42 @@ var ts; } function getSuggestedBooleanOperator(operator) { switch (operator) { - case 49: - case 69: - return 54; - case 50: - case 70: - return 35; - case 48: - case 68: - return 53; + case 49 /* BarToken */: + case 69 /* BarEqualsToken */: + return 54 /* BarBarToken */; + case 50 /* CaretToken */: + case 70 /* CaretEqualsToken */: + return 35 /* ExclamationEqualsEqualsToken */; + case 48 /* AmpersandToken */: + case 68 /* AmpersandEqualsToken */: + return 53 /* AmpersandAmpersandToken */; default: return undefined; } } function checkAssignmentOperator(valueType) { if (produceDiagnostics && ts.isAssignmentOperator(operator)) { + // TypeScript 1.0 spec (April 2014): 4.17 + // An assignment of the form + // VarExpr = ValueExpr + // requires VarExpr to be classified as a reference + // A compound assignment furthermore requires VarExpr to be classified as a reference (section 4.1) + // and the type of the non-compound operation to be assignable to the type of VarExpr. if (checkReferenceExpression(left, ts.Diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access) && (!ts.isIdentifier(left) || ts.unescapeLeadingUnderscores(left.escapedText) !== "exports")) { - checkTypeAssignableTo(valueType, leftType, left, undefined); + // to avoid cascading errors check assignability only if 'isReference' check succeeded and no errors were reported + checkTypeAssignableTo(valueType, leftType, left, /*headMessage*/ undefined); } } } function isJSSpecialPropertyAssignment(special) { switch (special) { - case 1: - case 2: - case 5: - case 6: - case 3: - case 4: + case 1 /* ExportsProperty */: + case 2 /* ModuleExports */: + case 5 /* Property */: + case 6 /* Prototype */: + case 3 /* PrototypeProperty */: + case 4 /* ThisProperty */: var symbol = getSymbolOfNode(left); var init = ts.getAssignedJavascriptInitializer(right); return init && ts.isObjectLiteralExpression(init) && @@ -41166,8 +47941,9 @@ var ts; return false; } function checkYieldExpression(node) { + // Grammar checking if (produceDiagnostics) { - if (!(node.flags & 4096) || isYieldExpressionInClass(node)) { + if (!(node.flags & 4096 /* YieldContext */) || isYieldExpressionInClass(node)) { grammarErrorOnFirstToken(node, ts.Diagnostics.A_yield_expression_is_only_allowed_in_a_generator_body); } if (isInParameterInitializerBeforeContainingFunction(node)) { @@ -41178,45 +47954,58 @@ var ts; if (!func) return anyType; var functionFlags = ts.getFunctionFlags(func); - if (!(functionFlags & 1)) { + if (!(functionFlags & 1 /* Generator */)) { + // If the user's code is syntactically correct, the func should always have a star. After all, we are in a yield context. return anyType; } if (node.asteriskToken) { - if ((functionFlags & 3) === 3 && - languageVersion < 6) { - checkExternalEmitHelpers(node, 26624); + // Async generator functions prior to ESNext require the __await, __asyncDelegator, + // and __asyncValues helpers + if ((functionFlags & 3 /* AsyncGenerator */) === 3 /* AsyncGenerator */ && + languageVersion < 6 /* ESNext */) { + checkExternalEmitHelpers(node, 26624 /* AsyncDelegatorIncludes */); } - if ((functionFlags & 3) === 1 && - languageVersion < 2 && compilerOptions.downlevelIteration) { - checkExternalEmitHelpers(node, 256); + // Generator functions prior to ES2015 require the __values helper + if ((functionFlags & 3 /* AsyncGenerator */) === 1 /* Generator */ && + languageVersion < 2 /* ES2015 */ && compilerOptions.downlevelIteration) { + checkExternalEmitHelpers(node, 256 /* Values */); } } - var isAsync = (functionFlags & 2) !== 0; - var yieldedType = getYieldedTypeOfYieldExpression(node, isAsync); + var isAsync = (functionFlags & 2 /* Async */) !== 0; + var yieldedType = getYieldedTypeOfYieldExpression(node, isAsync); // TODO: GH#18217 + // There is no point in doing an assignability check if the function + // has no explicit return type because the return type is directly computed + // from the yield expressions. var returnType = ts.getEffectiveReturnTypeNode(func); if (returnType) { var signatureElementType = getIteratedTypeOfGenerator(getTypeFromTypeNode(returnType), isAsync) || anyType; - checkTypeAssignableTo(yieldedType, signatureElementType, node.expression || node, undefined); + checkTypeAssignableTo(yieldedType, signatureElementType, node.expression || node, /*headMessage*/ undefined); } + // Both yield and yield* expressions have type 'any' return anyType; } function checkConditionalExpression(node, checkMode) { checkExpression(node.condition); var type1 = checkExpression(node.whenTrue, checkMode); var type2 = checkExpression(node.whenFalse, checkMode); - return getUnionType([type1, type2], 2); + return getUnionType([type1, type2], 2 /* Subtype */); } function checkTemplateExpression(node) { + // We just want to check each expressions, but we are unconcerned with + // the type of each expression, as any value may be coerced into a string. + // It is worth asking whether this is what we really want though. + // A place where we actually *are* concerned with the expressions' types are + // in tagged templates. ts.forEach(node.templateSpans, function (templateSpan) { - if (maybeTypeOfKind(checkExpression(templateSpan.expression), 3072)) { + if (maybeTypeOfKind(checkExpression(templateSpan.expression), 3072 /* ESSymbolLike */)) { error(templateSpan.expression, ts.Diagnostics.Type_0_cannot_be_converted_to_type_1, typeToString(esSymbolType), typeToString(stringType)); } }); return stringType; } function getContextNode(node) { - if (node.kind === 263) { - return node.parent.parent; + if (node.kind === 263 /* JsxAttributes */) { + return node.parent.parent; // Needs to be the root JsxElement, so it encompasses the attributes _and_ the children (which are essentially part of the attributes) } return node; } @@ -41226,8 +48015,8 @@ var ts; var saveContextualMapper = context.contextualMapper; context.contextualType = contextualType; context.contextualMapper = contextualMapper; - var checkMode = contextualMapper === identityMapper ? 1 : - contextualMapper ? 2 : 3; + var checkMode = contextualMapper === identityMapper ? 1 /* SkipContextSensitive */ : + contextualMapper ? 2 /* Inferential */ : 3 /* Contextual */; var result = checkExpression(node, checkMode); context.contextualType = saveContextualType; context.contextualMapper = saveContextualMapper; @@ -41239,6 +48028,9 @@ var ts; if (checkMode) { return checkExpression(node, checkMode); } + // When computing a type that we're going to cache, we need to ignore any ongoing control flow + // analysis because variables may have transient types in indeterminable states. Moving flowLoopStart + // to the top of the stack ensures all transient types are computed from a known point. var saveFlowLoopStart = flowLoopStart; flowLoopStart = flowLoopCount; links.resolvedType = checkExpression(node, checkMode); @@ -41248,16 +48040,16 @@ var ts; } function isTypeAssertion(node) { node = ts.skipParentheses(node); - return node.kind === 190 || node.kind === 208; + return node.kind === 190 /* TypeAssertionExpression */ || node.kind === 208 /* AsExpression */; } function checkDeclarationInitializer(declaration) { var initializer = ts.getEffectiveInitializer(declaration); - var type = getTypeOfExpression(initializer, true); - var widened = ts.getCombinedNodeFlags(declaration) & 2 || - (ts.getCombinedModifierFlags(declaration) & 64 && !ts.isParameterPropertyDeclaration(declaration)) || + var type = getTypeOfExpression(initializer, /*cache*/ true); + var widened = ts.getCombinedNodeFlags(declaration) & 2 /* Const */ || + (ts.getCombinedModifierFlags(declaration) & 64 /* Readonly */ && !ts.isParameterPropertyDeclaration(declaration)) || isTypeAssertion(initializer) ? type : getWidenedLiteralType(type); if (ts.isInJavaScriptFile(declaration)) { - if (widened.flags & 24576) { + if (widened.flags & 24576 /* Nullable */) { if (noImplicitAny) { reportImplicitAnyError(declaration, anyType); } @@ -41274,21 +48066,26 @@ var ts; } function isLiteralOfContextualType(candidateType, contextualType) { if (contextualType) { - if (contextualType.flags & 786432) { + if (contextualType.flags & 786432 /* UnionOrIntersection */) { var types = contextualType.types; return ts.some(types, function (t) { return isLiteralOfContextualType(candidateType, t); }); } - if (contextualType.flags & 14745600) { + if (contextualType.flags & 14745600 /* InstantiableNonPrimitive */) { + // If the contextual type is a type variable constrained to a primitive type, consider + // this a literal context for literals of that primitive type. For example, given a + // type parameter 'T extends string', infer string literal types for T. var constraint = getBaseConstraintOfType(contextualType) || emptyObjectType; - return maybeTypeOfKind(constraint, 4) && maybeTypeOfKind(candidateType, 64) || - maybeTypeOfKind(constraint, 8) && maybeTypeOfKind(candidateType, 128) || - maybeTypeOfKind(constraint, 1024) && maybeTypeOfKind(candidateType, 2048) || + return maybeTypeOfKind(constraint, 4 /* String */) && maybeTypeOfKind(candidateType, 64 /* StringLiteral */) || + maybeTypeOfKind(constraint, 8 /* Number */) && maybeTypeOfKind(candidateType, 128 /* NumberLiteral */) || + maybeTypeOfKind(constraint, 1024 /* ESSymbol */) && maybeTypeOfKind(candidateType, 2048 /* UniqueESSymbol */) || isLiteralOfContextualType(candidateType, constraint); } - return !!(contextualType.flags & (64 | 1048576) && maybeTypeOfKind(candidateType, 64) || - contextualType.flags & 128 && maybeTypeOfKind(candidateType, 128) || - contextualType.flags & 256 && maybeTypeOfKind(candidateType, 256) || - contextualType.flags & 2048 && maybeTypeOfKind(candidateType, 2048)); + // If the contextual type is a literal of a particular primitive type, we consider this a + // literal context for all literals of that primitive type. + return !!(contextualType.flags & (64 /* StringLiteral */ | 1048576 /* Index */) && maybeTypeOfKind(candidateType, 64 /* StringLiteral */) || + contextualType.flags & 128 /* NumberLiteral */ && maybeTypeOfKind(candidateType, 128 /* NumberLiteral */) || + contextualType.flags & 256 /* BooleanLiteral */ && maybeTypeOfKind(candidateType, 256 /* BooleanLiteral */) || + contextualType.flags & 2048 /* UniqueESSymbol */ && maybeTypeOfKind(candidateType, 2048 /* UniqueESSymbol */)); } return false; } @@ -41301,21 +48098,28 @@ var ts; getWidenedLiteralLikeTypeForContextualType(type, contextualType); } function checkPropertyAssignment(node, checkMode) { - if (node.name.kind === 147) { + // Do not use hasDynamicName here, because that returns false for well known symbols. + // We want to perform checkComputedPropertyName for all computed properties, including + // well known symbols. + if (node.name.kind === 147 /* ComputedPropertyName */) { checkComputedPropertyName(node.name); } return checkExpressionForMutableLocation(node.initializer, checkMode); } function checkObjectLiteralMethod(node, checkMode) { + // Grammar checking checkGrammarMethod(node); - if (node.name.kind === 147) { + // Do not use hasDynamicName here, because that returns false for well known symbols. + // We want to perform checkComputedPropertyName for all computed properties, including + // well known symbols. + if (node.name.kind === 147 /* ComputedPropertyName */) { checkComputedPropertyName(node.name); } var uninstantiatedType = checkFunctionExpressionOrObjectLiteralMethod(node, checkMode); return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode); } function instantiateTypeWithSingleGenericCallSignature(node, type, checkMode) { - if (checkMode === 2) { + if (checkMode === 2 /* Inferential */) { var signature = getSingleCallSignature(type); if (signature && signature.typeParameters) { var contextualType = getApparentTypeOfContextualType(node); @@ -41329,16 +48133,34 @@ var ts; } return type; } + /** + * Returns the type of an expression. Unlike checkExpression, this function is simply concerned + * with computing the type and may not fully check all contained sub-expressions for errors. + * A cache argument of true indicates that if the function performs a full type check, it is ok + * to cache the result. + */ function getTypeOfExpression(node, cache) { - if (node.kind === 187 && node.expression.kind !== 97 && !ts.isRequireCall(node, true) && !isSymbolOrSymbolForCall(node)) { + // Optimize for the common case of a call to a function with a single non-generic call + // signature where we can just fetch the return type without checking the arguments. + if (node.kind === 187 /* CallExpression */ && node.expression.kind !== 97 /* SuperKeyword */ && !ts.isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true) && !isSymbolOrSymbolForCall(node)) { var funcType = checkNonNullExpression(node.expression); var signature = getSingleCallSignature(funcType); if (signature && !signature.typeParameters) { return getReturnTypeOfSignature(signature); } } + // Otherwise simply call checkExpression. Ideally, the entire family of checkXXX functions + // should have a parameter that indicates whether full error checking is required such that + // we can perform the optimizations locally. return cache ? checkExpressionCached(node) : checkExpression(node); } + /** + * Returns the type of an expression. Unlike checkExpression, this function is simply concerned + * with computing the type and may not fully check all contained sub-expressions for errors. + * It is intended for uses where you know there is no contextual type, + * and requesting the contextual type might cause a circularity or other bad behaviour. + * It sets the contextual type of the node to any before calling getTypeOfExpression. + */ function getContextFreeTypeOfExpression(node) { var saveContextualType = node.contextualType; node.contextualType = anyType; @@ -41349,9 +48171,16 @@ var ts; function checkExpresionNoReturn(node) { checkExpression(node); } + // Checks an expression and returns its type. The contextualMapper parameter serves two purposes: When + // contextualMapper is not undefined and not equal to the identityMapper function object it indicates that the + // expression is being inferentially typed (section 4.15.2 in spec) and provides the type mapper to use in + // conjunction with the generic contextual type. When contextualMapper is equal to the identityMapper function + // object, it serves as an indicator that all contained function and arrow expressions should be considered to + // have the wildcard function type; this form of type check is used during overload resolution to exclude + // contextually typed function and arrow expressions in the initial phase. function checkExpression(node, checkMode) { var type; - if (node.kind === 146) { + if (node.kind === 146 /* QualifiedName */) { type = checkQualifiedName(node); } else { @@ -41359,10 +48188,14 @@ var ts; type = instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode); } if (isConstEnumObjectType(type)) { - var ok = (node.parent.kind === 185 && node.parent.expression === node) || - (node.parent.kind === 186 && node.parent.expression === node) || - ((node.kind === 71 || node.kind === 146) && isInRightSideOfImportOrExportAssignment(node) || - (node.parent.kind === 165 && node.parent.exprName === node)); + // enum object type for const enums are only permitted in: + // - 'left' in property access + // - 'object' in indexed access + // - target in rhs of import statement + var ok = (node.parent.kind === 185 /* PropertyAccessExpression */ && node.parent.expression === node) || + (node.parent.kind === 186 /* ElementAccessExpression */ && node.parent.expression === node) || + ((node.kind === 71 /* Identifier */ || node.kind === 146 /* QualifiedName */) && isInRightSideOfImportOrExportAssignment(node) || + (node.parent.kind === 165 /* TypeQuery */ && node.parent.exprName === node)); if (!ok) { error(node, ts.Diagnostics.const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment_or_type_query); } @@ -41378,96 +48211,99 @@ var ts; } function checkExpressionWorker(node, checkMode) { switch (node.kind) { - case 71: + case 71 /* Identifier */: return checkIdentifier(node); - case 99: + case 99 /* ThisKeyword */: return checkThisExpression(node); - case 97: + case 97 /* SuperKeyword */: return checkSuperExpression(node); - case 95: + case 95 /* NullKeyword */: return nullWideningType; - case 13: - case 9: + case 13 /* NoSubstitutionTemplateLiteral */: + case 9 /* StringLiteral */: return getFreshTypeOfLiteralType(getLiteralType(node.text)); - case 8: + case 8 /* NumericLiteral */: checkGrammarNumericLiteral(node); return getFreshTypeOfLiteralType(getLiteralType(+node.text)); - case 101: + case 101 /* TrueKeyword */: return trueType; - case 86: + case 86 /* FalseKeyword */: return falseType; - case 202: + case 202 /* TemplateExpression */: return checkTemplateExpression(node); - case 12: + case 12 /* RegularExpressionLiteral */: return globalRegExpType; - case 183: + case 183 /* ArrayLiteralExpression */: return checkArrayLiteral(node, checkMode); - case 184: + case 184 /* ObjectLiteralExpression */: return checkObjectLiteral(node, checkMode); - case 185: + case 185 /* PropertyAccessExpression */: return checkPropertyAccessExpression(node); - case 186: + case 186 /* ElementAccessExpression */: return checkIndexedAccess(node); - case 187: - if (node.expression.kind === 91) { + case 187 /* CallExpression */: + if (node.expression.kind === 91 /* ImportKeyword */) { return checkImportCallExpression(node); } - case 188: + /* falls through */ + case 188 /* NewExpression */: return checkCallExpression(node); - case 189: + case 189 /* TaggedTemplateExpression */: return checkTaggedTemplateExpression(node); - case 191: + case 191 /* ParenthesizedExpression */: return checkParenthesizedExpression(node, checkMode); - case 205: + case 205 /* ClassExpression */: return checkClassExpression(node); - case 192: - case 193: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: return checkFunctionExpressionOrObjectLiteralMethod(node, checkMode); - case 195: + case 195 /* TypeOfExpression */: return checkTypeOfExpression(node); - case 190: - case 208: + case 190 /* TypeAssertionExpression */: + case 208 /* AsExpression */: return checkAssertion(node); - case 209: + case 209 /* NonNullExpression */: return checkNonNullAssertion(node); - case 210: + case 210 /* MetaProperty */: return checkMetaProperty(node); - case 194: + case 194 /* DeleteExpression */: return checkDeleteExpression(node); - case 196: + case 196 /* VoidExpression */: return checkVoidExpression(node); - case 197: + case 197 /* AwaitExpression */: return checkAwaitExpression(node); - case 198: + case 198 /* PrefixUnaryExpression */: return checkPrefixUnaryExpression(node); - case 199: + case 199 /* PostfixUnaryExpression */: return checkPostfixUnaryExpression(node); - case 200: + case 200 /* BinaryExpression */: return checkBinaryExpression(node, checkMode); - case 201: + case 201 /* ConditionalExpression */: return checkConditionalExpression(node, checkMode); - case 204: + case 204 /* SpreadElement */: return checkSpreadExpression(node, checkMode); - case 206: + case 206 /* OmittedExpression */: return undefinedWideningType; - case 203: + case 203 /* YieldExpression */: return checkYieldExpression(node); - case 265: + case 265 /* JsxExpression */: return checkJsxExpression(node, checkMode); - case 255: + case 255 /* JsxElement */: return checkJsxElement(node, checkMode); - case 256: + case 256 /* JsxSelfClosingElement */: return checkJsxSelfClosingElement(node, checkMode); - case 259: + case 259 /* JsxFragment */: return checkJsxFragment(node, checkMode); - case 263: + case 263 /* JsxAttributes */: return checkJsxAttributes(node, checkMode); - case 257: + case 257 /* JsxOpeningElement */: ts.Debug.fail("Shouldn't ever directly check a JsxOpeningElement"); } return errorType; } + // DECLARATION AND STATEMENT TYPE CHECKING function checkTypeParameter(node) { + // Grammar Checking if (node.expression) { grammarErrorOnFirstToken(node.expression, ts.Diagnostics.Type_expected); } @@ -41490,11 +48326,15 @@ var ts; } } function checkParameter(node) { + // Grammar checking + // It is a SyntaxError if the Identifier "eval" or the Identifier "arguments" occurs as the + // Identifier in a PropertySetParameterList of a PropertyAssignment that is contained in strict code + // or if its FunctionBody is strict code(11.1.5). checkGrammarDecoratorsAndModifiers(node); checkVariableLikeDeclaration(node); var func = ts.getContainingFunction(node); - if (ts.hasModifier(node, 92)) { - if (!(func.kind === 155 && ts.nodeIsPresent(func.body))) { + if (ts.hasModifier(node, 92 /* ParameterPropertyModifier */)) { + if (!(func.kind === 155 /* Constructor */ && ts.nodeIsPresent(func.body))) { error(node, ts.Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation); } } @@ -41505,10 +48345,12 @@ var ts; if (func.parameters.indexOf(node) !== 0) { error(node, ts.Diagnostics.A_0_parameter_must_be_the_first_parameter, node.name.escapedText); } - if (func.kind === 155 || func.kind === 159 || func.kind === 164) { + if (func.kind === 155 /* Constructor */ || func.kind === 159 /* ConstructSignature */ || func.kind === 164 /* ConstructorType */) { error(node, ts.Diagnostics.A_constructor_cannot_have_a_this_parameter); } } + // Only check rest parameter type if it's not a binding pattern. Since binding patterns are + // not allowed in a rest parameter, we already have an error from checkGrammarParameterList. if (node.dotDotDotToken && !ts.isBindingPattern(node.name) && !isArrayType(getTypeOfSymbol(node.symbol))) { error(node, ts.Diagnostics.A_rest_parameter_must_be_of_an_array_type); } @@ -41517,7 +48359,7 @@ var ts; if (parameterList) { for (var i = 0; i < parameterList.length; i++) { var param = parameterList[i]; - if (param.name.kind === 71 && param.name.escapedText === parameter.escapedText) { + if (param.name.kind === 71 /* Identifier */ && param.name.escapedText === parameter.escapedText) { return i; } } @@ -41527,6 +48369,7 @@ var ts; function checkTypePredicate(node) { var parent = getTypePredicateParent(node); if (!parent) { + // The parent must not be valid. error(node, ts.Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods); return; } @@ -41545,8 +48388,10 @@ var ts; error(parameterName, ts.Diagnostics.A_type_predicate_cannot_reference_a_rest_parameter); } else { - var leadingError = function () { return ts.chainDiagnosticMessages(undefined, ts.Diagnostics.A_type_predicate_s_type_must_be_assignable_to_its_parameter_s_type); }; - checkTypeAssignableTo(typePredicate.type, getTypeOfNode(parent.parameters[typePredicate.parameterIndex]), node.type, undefined, leadingError); + var leadingError = function () { return ts.chainDiagnosticMessages(/*details*/ undefined, ts.Diagnostics.A_type_predicate_s_type_must_be_assignable_to_its_parameter_s_type); }; + checkTypeAssignableTo(typePredicate.type, getTypeOfNode(parent.parameters[typePredicate.parameterIndex]), // TODO: GH#18217 + node.type, + /*headMessage*/ undefined, leadingError); } } else if (parameterName) { @@ -41567,13 +48412,13 @@ var ts; } function getTypePredicateParent(node) { switch (node.parent.kind) { - case 193: - case 158: - case 234: - case 192: - case 163: - case 154: - case 153: + case 193 /* ArrowFunction */: + case 158 /* CallSignature */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 163 /* FunctionType */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: var parent = node.parent; if (node === parent.type) { return parent; @@ -41587,11 +48432,11 @@ var ts; continue; } var name = element.name; - if (name.kind === 71 && name.escapedText === predicateVariableName) { + if (name.kind === 71 /* Identifier */ && name.escapedText === predicateVariableName) { error(predicateVariableNode, ts.Diagnostics.A_type_predicate_cannot_reference_element_0_in_a_binding_pattern, predicateVariableName); return true; } - else if (name.kind === 181 || name.kind === 180) { + else if (name.kind === 181 /* ArrayBindingPattern */ || name.kind === 180 /* ObjectBindingPattern */) { if (checkIfTypePredicateVariableIsDeclaredInBindingPattern(name, predicateVariableNode, predicateVariableName)) { return true; } @@ -41599,28 +48444,35 @@ var ts; } } function checkSignatureDeclaration(node) { - if (node.kind === 160) { + // Grammar checking + if (node.kind === 160 /* IndexSignature */) { checkGrammarIndexSignature(node); } - else if (node.kind === 163 || node.kind === 234 || node.kind === 164 || - node.kind === 158 || node.kind === 155 || - node.kind === 159) { + // TODO (yuisu): Remove this check in else-if when SyntaxKind.Construct is moved and ambient context is handled + else if (node.kind === 163 /* FunctionType */ || node.kind === 234 /* FunctionDeclaration */ || node.kind === 164 /* ConstructorType */ || + node.kind === 158 /* CallSignature */ || node.kind === 155 /* Constructor */ || + node.kind === 159 /* ConstructSignature */) { checkGrammarFunctionLikeDeclaration(node); } var functionFlags = ts.getFunctionFlags(node); - if (!(functionFlags & 4)) { - if ((functionFlags & 3) === 3 && languageVersion < 6) { - checkExternalEmitHelpers(node, 6144); + if (!(functionFlags & 4 /* Invalid */)) { + // Async generators prior to ESNext require the __await and __asyncGenerator helpers + if ((functionFlags & 3 /* AsyncGenerator */) === 3 /* AsyncGenerator */ && languageVersion < 6 /* ESNext */) { + checkExternalEmitHelpers(node, 6144 /* AsyncGeneratorIncludes */); } - if ((functionFlags & 3) === 2 && languageVersion < 4) { - checkExternalEmitHelpers(node, 64); + // Async functions prior to ES2017 require the __awaiter helper + if ((functionFlags & 3 /* AsyncGenerator */) === 2 /* Async */ && languageVersion < 4 /* ES2017 */) { + checkExternalEmitHelpers(node, 64 /* Awaiter */); } - if ((functionFlags & 3) !== 0 && languageVersion < 2) { - checkExternalEmitHelpers(node, 128); + // Generator functions, Async functions, and Async Generator functions prior to + // ES2015 require the __generator helper + if ((functionFlags & 3 /* AsyncGenerator */) !== 0 /* Normal */ && languageVersion < 2 /* ES2015 */) { + checkExternalEmitHelpers(node, 128 /* Generator */); } } checkTypeParameters(node.typeParameters); ts.forEach(node.parameters, checkParameter); + // TODO(rbuckton): Should we start checking JSDoc types? if (node.type) { checkSourceElement(node.type); } @@ -41629,34 +48481,40 @@ var ts; var returnTypeNode = ts.getEffectiveReturnTypeNode(node); if (noImplicitAny && !returnTypeNode) { switch (node.kind) { - case 159: + case 159 /* ConstructSignature */: error(node, ts.Diagnostics.Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type); break; - case 158: + case 158 /* CallSignature */: error(node, ts.Diagnostics.Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type); break; } } if (returnTypeNode) { var functionFlags_1 = ts.getFunctionFlags(node); - if ((functionFlags_1 & (4 | 1)) === 1) { + if ((functionFlags_1 & (4 /* Invalid */ | 1 /* Generator */)) === 1 /* Generator */) { var returnType = getTypeFromTypeNode(returnTypeNode); if (returnType === voidType) { error(returnTypeNode, ts.Diagnostics.A_generator_cannot_have_a_void_type_annotation); } else { - var generatorElementType = getIteratedTypeOfGenerator(returnType, (functionFlags_1 & 2) !== 0) || anyType; - var iterableIteratorInstantiation = functionFlags_1 & 2 - ? createAsyncIterableIteratorType(generatorElementType) - : createIterableIteratorType(generatorElementType); + var generatorElementType = getIteratedTypeOfGenerator(returnType, (functionFlags_1 & 2 /* Async */) !== 0) || anyType; + var iterableIteratorInstantiation = functionFlags_1 & 2 /* Async */ + ? createAsyncIterableIteratorType(generatorElementType) // AsyncGenerator function + : createIterableIteratorType(generatorElementType); // Generator function + // Naively, one could check that IterableIterator is assignable to the return type annotation. + // However, that would not catch the error in the following case. + // + // interface BadGenerator extends Iterable, Iterator { } + // function* g(): BadGenerator { } // Iterable and Iterator have different types! + // checkTypeAssignableTo(iterableIteratorInstantiation, returnType, returnTypeNode); } } - else if ((functionFlags_1 & 3) === 2) { + else if ((functionFlags_1 & 3 /* AsyncGenerator */) === 2 /* Async */) { checkAsyncFunctionReturnType(node); } } - if (node.kind !== 160 && node.kind !== 284) { + if (node.kind !== 160 /* IndexSignature */ && node.kind !== 284 /* JSDocFunctionType */) { registerForUnusedIdentifiersCheck(node); } } @@ -41673,32 +48531,32 @@ var ts; var staticNames = ts.createUnderscoreEscapedMap(); for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var member = _a[_i]; - if (member.kind === 155) { + if (member.kind === 155 /* Constructor */) { for (var _b = 0, _c = member.parameters; _b < _c.length; _b++) { var param = _c[_b]; if (ts.isParameterPropertyDeclaration(param) && !ts.isBindingPattern(param.name)) { - addName(instanceNames, param.name, param.name.escapedText, 3); + addName(instanceNames, param.name, param.name.escapedText, 3 /* Property */); } } } else { - var isStatic = ts.hasModifier(member, 32); + var isStatic = ts.hasModifier(member, 32 /* Static */); var names = isStatic ? staticNames : instanceNames; var name = member.name; var memberName = name && ts.getPropertyNameForPropertyNameNode(name); if (name && memberName) { switch (member.kind) { - case 156: - addName(names, name, memberName, 1); + case 156 /* GetAccessor */: + addName(names, name, memberName, 1 /* Getter */); break; - case 157: - addName(names, name, memberName, 2); + case 157 /* SetAccessor */: + addName(names, name, memberName, 2 /* Setter */); break; - case 152: - addName(names, name, memberName, 3); + case 152 /* PropertyDeclaration */: + addName(names, name, memberName, 3 /* Property */); break; - case 154: - addName(names, name, memberName, 4); + case 154 /* MethodDeclaration */: + addName(names, name, memberName, 4 /* Method */); break; } } @@ -41707,8 +48565,8 @@ var ts; function addName(names, location, name, meaning) { var prev = names.get(name); if (prev) { - if (prev & 4) { - if (meaning !== 4) { + if (prev & 4 /* Method */) { + if (meaning !== 4 /* Method */) { error(location, ts.Diagnostics.Duplicate_identifier_0, ts.getTextOfNode(location)); } } @@ -41724,11 +48582,22 @@ var ts; } } } + /** + * Static members being set on a constructor function may conflict with built-in properties + * of Function. Esp. in ECMAScript 5 there are non-configurable and non-writable + * built-in properties. This check issues a transpile error when a class has a static + * member with the same name as a non-writable built-in property. + * + * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.3 + * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.5 + * @see http://www.ecma-international.org/ecma-262/6.0/#sec-properties-of-the-function-constructor + * @see http://www.ecma-international.org/ecma-262/6.0/#sec-function-instances + */ function checkClassForStaticPropertyNameConflicts(node) { for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var member = _a[_i]; var memberNameNode = member.name; - var isStatic = ts.hasModifier(member, 32); + var isStatic = ts.hasModifier(member, 32 /* Static */); if (isStatic && memberNameNode) { var memberName = ts.getPropertyNameForPropertyNameNode(memberNameNode); switch (memberName) { @@ -41749,15 +48618,15 @@ var ts; var names = ts.createMap(); for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var member = _a[_i]; - if (member.kind === 151) { + if (member.kind === 151 /* PropertySignature */) { var memberName = void 0; var name = member.name; switch (name.kind) { - case 9: - case 8: + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: memberName = name.text; break; - case 71: + case 71 /* Identifier */: memberName = ts.idText(name); break; default: @@ -41774,12 +48643,17 @@ var ts; } } function checkTypeForDuplicateIndexSignatures(node) { - if (node.kind === 236) { + if (node.kind === 236 /* InterfaceDeclaration */) { var nodeSymbol = getSymbolOfNode(node); + // in case of merging interface declaration it is possible that we'll enter this check procedure several times for every declaration + // to prevent this run check only for the first declaration of a given kind if (nodeSymbol.declarations.length > 0 && nodeSymbol.declarations[0] !== node) { return; } } + // TypeScript 1.0 spec (April 2014) + // 3.7.4: An object type can contain at most one string index signature and one numeric index signature. + // 8.5: A class declaration can have at most one string index member declaration and one numeric index member declaration var indexSymbol = getIndexSymbol(getSymbolOfNode(node)); if (indexSymbol) { var seenNumericIndexer = false; @@ -41789,7 +48663,7 @@ var ts; var declaration = decl; if (declaration.parameters.length === 1 && declaration.parameters[0].type) { switch (declaration.parameters[0].type.kind) { - case 137: + case 137 /* StringKeyword */: if (!seenStringIndexer) { seenStringIndexer = true; } @@ -41797,7 +48671,7 @@ var ts; error(declaration, ts.Diagnostics.Duplicate_string_index_signature); } break; - case 134: + case 134 /* NumberKeyword */: if (!seenNumericIndexer) { seenNumericIndexer = true; } @@ -41811,28 +48685,37 @@ var ts; } } function checkPropertyDeclaration(node) { + // Grammar checking if (!checkGrammarDecoratorsAndModifiers(node) && !checkGrammarProperty(node)) checkGrammarComputedPropertyName(node.name); checkVariableLikeDeclaration(node); } function checkMethodDeclaration(node) { + // Grammar checking if (!checkGrammarMethod(node)) checkGrammarComputedPropertyName(node.name); + // Grammar checking for modifiers is done inside the function checkGrammarFunctionLikeDeclaration checkFunctionOrMethodDeclaration(node); - if (ts.hasModifier(node, 128) && node.kind === 154 && node.body) { + // Abstract methods cannot have an implementation. + // Extra checks are to avoid reporting multiple errors relating to the "abstractness" of the node. + if (ts.hasModifier(node, 128 /* Abstract */) && node.kind === 154 /* MethodDeclaration */ && node.body) { error(node, ts.Diagnostics.Method_0_cannot_have_an_implementation_because_it_is_marked_abstract, ts.declarationNameToString(node.name)); } } function checkConstructorDeclaration(node) { + // Grammar check on signature of constructor and modifier of the constructor is done in checkSignatureDeclaration function. checkSignatureDeclaration(node); + // Grammar check for checking only related to constructorDeclaration if (!checkGrammarConstructorTypeParameters(node)) checkGrammarConstructorTypeAnnotation(node); checkSourceElement(node.body); var symbol = getSymbolOfNode(node); var firstDeclaration = ts.getDeclarationOfKind(symbol, node.kind); + // Only type check the symbol once if (node === firstDeclaration) { checkFunctionOrConstructorSymbol(symbol); } + // exit early in the case of signature - super checks are not relevant to them if (ts.nodeIsMissing(node.body)) { return; } @@ -41840,10 +48723,13 @@ var ts; return; } function isInstancePropertyWithInitializer(n) { - return n.kind === 152 && - !ts.hasModifier(n, 32) && + return n.kind === 152 /* PropertyDeclaration */ && + !ts.hasModifier(n, 32 /* Static */) && !!n.initializer; } + // TS 1.0 spec (April 2014): 8.3.2 + // Constructors of classes with no extends clause may not contain super calls, whereas + // constructors of derived classes must contain at least one super call somewhere in their function body. var containingClassDecl = node.parent; if (ts.getClassExtendsHeritageClauseElement(containingClassDecl)) { captureLexicalThis(node.parent, containingClassDecl); @@ -41853,14 +48739,21 @@ var ts; if (classExtendsNull) { error(superCall, ts.Diagnostics.A_constructor_cannot_contain_a_super_call_when_its_class_extends_null); } + // The first statement in the body of a constructor (excluding prologue directives) must be a super call + // if both of the following are true: + // - The containing class is a derived class. + // - The constructor declares parameter properties + // or the containing class declares instance member variables with initializers. var superCallShouldBeFirst = ts.some(node.parent.members, isInstancePropertyWithInitializer) || - ts.some(node.parameters, function (p) { return ts.hasModifier(p, 92); }); + ts.some(node.parameters, function (p) { return ts.hasModifier(p, 92 /* ParameterPropertyModifier */); }); + // Skip past any prologue directives to find the first statement + // to ensure that it was a super call. if (superCallShouldBeFirst) { var statements = node.body.statements; var superCallStatement = void 0; for (var _i = 0, statements_2 = statements; _i < statements_2.length; _i++) { var statement = statements_2[_i]; - if (statement.kind === 216 && ts.isSuperCall(statement.expression)) { + if (statement.kind === 216 /* ExpressionStatement */ && ts.isSuperCall(statement.expression)) { superCallStatement = statement; break; } @@ -41880,38 +48773,46 @@ var ts; } function checkAccessorDeclaration(node) { if (produceDiagnostics) { + // Grammar checking accessors if (!checkGrammarFunctionLikeDeclaration(node) && !checkGrammarAccessor(node)) checkGrammarComputedPropertyName(node.name); checkDecorators(node); checkSignatureDeclaration(node); - if (node.kind === 156) { - if (!(node.flags & 4194304) && ts.nodeIsPresent(node.body) && (node.flags & 128)) { - if (!(node.flags & 256)) { + if (node.kind === 156 /* GetAccessor */) { + if (!(node.flags & 4194304 /* Ambient */) && ts.nodeIsPresent(node.body) && (node.flags & 128 /* HasImplicitReturn */)) { + if (!(node.flags & 256 /* HasExplicitReturn */)) { error(node.name, ts.Diagnostics.A_get_accessor_must_return_a_value); } } } - if (node.name.kind === 147) { + // Do not use hasDynamicName here, because that returns false for well known symbols. + // We want to perform checkComputedPropertyName for all computed properties, including + // well known symbols. + if (node.name.kind === 147 /* ComputedPropertyName */) { checkComputedPropertyName(node.name); } if (!hasNonBindableDynamicName(node)) { - var otherKind = node.kind === 156 ? 157 : 156; + // TypeScript 1.0 spec (April 2014): 8.4.3 + // Accessors for the same member name must specify the same accessibility. + var otherKind = node.kind === 156 /* GetAccessor */ ? 157 /* SetAccessor */ : 156 /* GetAccessor */; var otherAccessor = ts.getDeclarationOfKind(getSymbolOfNode(node), otherKind); if (otherAccessor) { var nodeFlags = ts.getModifierFlags(node); var otherFlags = ts.getModifierFlags(otherAccessor); - if ((nodeFlags & 28) !== (otherFlags & 28)) { + if ((nodeFlags & 28 /* AccessibilityModifier */) !== (otherFlags & 28 /* AccessibilityModifier */)) { error(node.name, ts.Diagnostics.Getter_and_setter_accessors_do_not_agree_in_visibility); } - if ((nodeFlags & 128) !== (otherFlags & 128)) { + if ((nodeFlags & 128 /* Abstract */) !== (otherFlags & 128 /* Abstract */)) { error(node.name, ts.Diagnostics.Accessors_must_both_be_abstract_or_non_abstract); } + // TypeScript 1.0 spec (April 2014): 4.5 + // If both accessors include type annotations, the specified types must be identical. checkAccessorDeclarationTypesIdentical(node, otherAccessor, getAnnotatedAccessorType, ts.Diagnostics.get_and_set_accessor_must_have_the_same_type); checkAccessorDeclarationTypesIdentical(node, otherAccessor, getThisTypeOfDeclaration, ts.Diagnostics.get_and_set_accessor_must_have_the_same_this_type); } } var returnType = getTypeOfAccessors(getSymbolOfNode(node)); - if (node.kind === 156) { + if (node.kind === 156 /* GetAccessor */) { checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnType); } } @@ -41951,20 +48852,21 @@ var ts; if (type !== errorType) { var symbol = getNodeLinks(node).resolvedSymbol; if (symbol) { - return symbol.flags & 524288 && getSymbolLinks(symbol).typeParameters || - (ts.getObjectFlags(type) & 4 ? type.target.localTypeParameters : undefined); + return symbol.flags & 524288 /* TypeAlias */ && getSymbolLinks(symbol).typeParameters || + (ts.getObjectFlags(type) & 4 /* Reference */ ? type.target.localTypeParameters : undefined); } } return undefined; } function checkTypeReferenceNode(node) { checkGrammarTypeArguments(node, node.typeArguments); - if (node.kind === 162 && node.typeName.jsdocDotPos !== undefined && !ts.isInJavaScriptFile(node) && !ts.isInJSDoc(node)) { + if (node.kind === 162 /* TypeReference */ && node.typeName.jsdocDotPos !== undefined && !ts.isInJavaScriptFile(node) && !ts.isInJSDoc(node)) { grammarErrorAtPos(node, node.typeName.jsdocDotPos, 1, ts.Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments); } var type = getTypeFromTypeReference(node); if (type !== errorType) { if (node.typeArguments) { + // Do type argument local checks only if referenced type is successfully resolved ts.forEach(node.typeArguments, checkSourceElement); if (produceDiagnostics) { var typeParameters = getTypeParametersForTypeReference(node); @@ -41973,7 +48875,7 @@ var ts; } } } - if (type.flags & 32 && getNodeLinks(node).resolvedSymbol.flags & 8) { + if (type.flags & 32 /* Enum */ && getNodeLinks(node).resolvedSymbol.flags & 8 /* EnumMember */) { error(node, ts.Diagnostics.Enum_type_0_has_members_with_initializers_that_are_not_literals, typeToString(type)); } } @@ -41982,7 +48884,7 @@ var ts; var typeReferenceNode = ts.tryCast(node.parent, ts.isTypeReferenceType); if (!typeReferenceNode) return undefined; - var typeParameters = getTypeParametersForTypeReference(typeReferenceNode); + var typeParameters = getTypeParametersForTypeReference(typeReferenceNode); // TODO: GH#18217 var constraint = getConstraintOfTypeParameter(typeParameters[typeReferenceNode.typeArguments.indexOf(node)]); return constraint && instantiateType(constraint, createTypeMapper(typeParameters, getEffectiveTypeArguments(typeReferenceNode, typeParameters))); } @@ -42002,6 +48904,7 @@ var ts; checkSourceElement(node.elementType); } function checkTupleType(node) { + // Grammar checking var hasErrorFromDisallowedTrailingComma = checkGrammarForDisallowedTrailingComma(node.elementTypes); if (!hasErrorFromDisallowedTrailingComma && node.elementTypes.length === 0) { grammarErrorOnNode(node, ts.Diagnostics.A_tuple_type_element_list_cannot_be_empty); @@ -42012,19 +48915,22 @@ var ts; ts.forEach(node.types, checkSourceElement); } function checkIndexedAccessIndexType(type, accessNode) { - if (!(type.flags & 2097152)) { + if (!(type.flags & 2097152 /* IndexedAccess */)) { return type; } + // Check if the index type is assignable to 'keyof T' for the object type. var objectType = type.objectType; var indexType = type.indexType; - if (isTypeAssignableTo(indexType, getIndexType(objectType, false))) { - if (accessNode.kind === 186 && ts.isAssignmentTarget(accessNode) && - ts.getObjectFlags(objectType) & 32 && getMappedTypeModifiers(objectType) & 1) { + if (isTypeAssignableTo(indexType, getIndexType(objectType, /*stringsOnly*/ false))) { + if (accessNode.kind === 186 /* ElementAccessExpression */ && ts.isAssignmentTarget(accessNode) && + ts.getObjectFlags(objectType) & 32 /* Mapped */ && getMappedTypeModifiers(objectType) & 1 /* IncludeReadonly */) { error(accessNode, ts.Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(objectType)); } return type; } - if (getIndexInfoOfType(getApparentType(objectType), 1) && isTypeAssignableToKind(indexType, 168)) { + // Check if we're indexing with a numeric type and if either object or index types + // is a generic type with a constraint that has a numeric index signature. + if (getIndexInfoOfType(getApparentType(objectType), 1 /* Number */) && isTypeAssignableToKind(indexType, 168 /* NumberLike */)) { return type; } error(accessNode, ts.Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(objectType)); @@ -42053,7 +48959,7 @@ var ts; ts.forEachChild(node, checkSourceElement); } function checkInferType(node) { - if (!ts.findAncestor(node, function (n) { return n.parent && n.parent.kind === 171 && n.parent.extendsType === n; })) { + if (!ts.findAncestor(node, function (n) { return n.parent && n.parent.kind === 171 /* ConditionalType */ && n.parent.extendsType === n; })) { grammarErrorOnNode(node, ts.Diagnostics.infer_declarations_are_only_permitted_in_the_extends_clause_of_a_conditional_type); } checkSourceElement(node.typeParameter); @@ -42063,18 +48969,21 @@ var ts; getTypeFromTypeNode(node); } function isPrivateWithinAmbient(node) { - return ts.hasModifier(node, 8) && !!(node.flags & 4194304); + return ts.hasModifier(node, 8 /* Private */) && !!(node.flags & 4194304 /* Ambient */); } function getEffectiveDeclarationFlags(n, flagsToCheck) { var flags = ts.getCombinedModifierFlags(n); - if (n.parent.kind !== 236 && - n.parent.kind !== 235 && - n.parent.kind !== 205 && - n.flags & 4194304) { - if (!(flags & 2) && !(ts.isModuleBlock(n.parent) && ts.isModuleDeclaration(n.parent.parent) && ts.isGlobalScopeAugmentation(n.parent.parent))) { - flags |= 1; + // children of classes (even ambient classes) should not be marked as ambient or export + // because those flags have no useful semantics there. + if (n.parent.kind !== 236 /* InterfaceDeclaration */ && + n.parent.kind !== 235 /* ClassDeclaration */ && + n.parent.kind !== 205 /* ClassExpression */ && + n.flags & 4194304 /* Ambient */) { + if (!(flags & 2 /* Ambient */) && !(ts.isModuleBlock(n.parent) && ts.isModuleDeclaration(n.parent.parent) && ts.isGlobalScopeAugmentation(n.parent.parent))) { + // It is nested in an ambient context, which means it is automatically exported + flags |= 1 /* Export */; } - flags |= 2; + flags |= 2 /* Ambient */; } return flags & flagsToCheck; } @@ -42083,25 +48992,32 @@ var ts; return; } function getCanonicalOverload(overloads, implementation) { + // Consider the canonical set of flags to be the flags of the bodyDeclaration or the first declaration + // Error on all deviations from this canonical set of flags + // The caveat is that if some overloads are defined in lib.d.ts, we don't want to + // report the errors on those. To achieve this, we will say that the implementation is + // the canonical signature only if it is in the same container as the first overload var implementationSharesContainerWithFirstOverload = implementation !== undefined && implementation.parent === overloads[0].parent; return implementationSharesContainerWithFirstOverload ? implementation : overloads[0]; } function checkFlagAgreementBetweenOverloads(overloads, implementation, flagsToCheck, someOverloadFlags, allOverloadFlags) { + // Error if some overloads have a flag that is not shared by all overloads. To find the + // deviations, we XOR someOverloadFlags with allOverloadFlags var someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags; if (someButNotAllOverloadFlags !== 0) { var canonicalFlags_1 = getEffectiveDeclarationFlags(getCanonicalOverload(overloads, implementation), flagsToCheck); ts.forEach(overloads, function (o) { var deviation = getEffectiveDeclarationFlags(o, flagsToCheck) ^ canonicalFlags_1; - if (deviation & 1) { + if (deviation & 1 /* Export */) { error(ts.getNameOfDeclaration(o), ts.Diagnostics.Overload_signatures_must_all_be_exported_or_non_exported); } - else if (deviation & 2) { + else if (deviation & 2 /* Ambient */) { error(ts.getNameOfDeclaration(o), ts.Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient); } - else if (deviation & (8 | 16)) { + else if (deviation & (8 /* Private */ | 16 /* Protected */)) { error(ts.getNameOfDeclaration(o) || o, ts.Diagnostics.Overload_signatures_must_all_be_public_private_or_protected); } - else if (deviation & 128) { + else if (deviation & 128 /* Abstract */) { error(ts.getNameOfDeclaration(o), ts.Diagnostics.Overload_signatures_must_all_be_abstract_or_non_abstract); } }); @@ -42118,8 +49034,8 @@ var ts; }); } } - var flagsToCheck = 1 | 2 | 8 | 16 | 128; - var someNodeFlags = 0; + var flagsToCheck = 1 /* Export */ | 2 /* Ambient */ | 8 /* Private */ | 16 /* Protected */ | 128 /* Abstract */; + var someNodeFlags = 0 /* None */; var allNodeFlags = flagsToCheck; var someHaveQuestionToken = false; var allHaveQuestionToken = true; @@ -42128,7 +49044,7 @@ var ts; var lastSeenNonAmbientDeclaration; var previousDeclaration; var declarations = symbol.declarations; - var isConstructor = (symbol.flags & 16384) !== 0; + var isConstructor = (symbol.flags & 16384 /* Constructor */) !== 0; function reportImplementationExpectedError(node) { if (node.name && ts.nodeIsMissing(node.name)) { return; @@ -42142,17 +49058,24 @@ var ts; seen = c === node; } }); + // We may be here because of some extra nodes between overloads that could not be parsed into a valid node. + // In this case the subsequent node is not really consecutive (.pos !== node.end), and we must ignore it here. if (subsequentNode && subsequentNode.pos === node.end) { if (subsequentNode.kind === node.kind) { var errorNode_1 = subsequentNode.name || subsequentNode; + // TODO: GH#17345: These are methods, so handle computed name case. (`Always allowing computed property names is *not* the correct behavior!) var subsequentName = subsequentNode.name; if (node.name && subsequentName && (ts.isComputedPropertyName(node.name) && ts.isComputedPropertyName(subsequentName) || !ts.isComputedPropertyName(node.name) && !ts.isComputedPropertyName(subsequentName) && ts.getEscapedTextOfIdentifierOrLiteral(node.name) === ts.getEscapedTextOfIdentifierOrLiteral(subsequentName))) { - var reportError = (node.kind === 154 || node.kind === 153) && - ts.hasModifier(node, 32) !== ts.hasModifier(subsequentNode, 32); + var reportError = (node.kind === 154 /* MethodDeclaration */ || node.kind === 153 /* MethodSignature */) && + ts.hasModifier(node, 32 /* Static */) !== ts.hasModifier(subsequentNode, 32 /* Static */); + // we can get here in two cases + // 1. mixed static and instance class members + // 2. something with the same name was defined before the set of overloads that prevents them from merging + // here we'll report error only for the first case since for second we should already report error in binder if (reportError) { - var diagnostic = ts.hasModifier(node, 32) ? ts.Diagnostics.Function_overload_must_be_static : ts.Diagnostics.Function_overload_must_not_be_static; + var diagnostic = ts.hasModifier(node, 32 /* Static */) ? ts.Diagnostics.Function_overload_must_be_static : ts.Diagnostics.Function_overload_must_not_be_static; error(errorNode_1, diagnostic); } return; @@ -42168,7 +49091,9 @@ var ts; error(errorNode, ts.Diagnostics.Constructor_implementation_is_missing); } else { - if (ts.hasModifier(node, 128)) { + // Report different errors regarding non-consecutive blocks of declarations depending on whether + // the node in question is abstract. + if (ts.hasModifier(node, 128 /* Abstract */)) { error(errorNode, ts.Diagnostics.All_declarations_of_an_abstract_method_must_be_consecutive); } else { @@ -42181,12 +49106,19 @@ var ts; for (var _i = 0, declarations_4 = declarations; _i < declarations_4.length; _i++) { var current = declarations_4[_i]; var node = current; - var inAmbientContext = node.flags & 4194304; - var inAmbientContextOrInterface = node.parent.kind === 236 || node.parent.kind === 166 || inAmbientContext; + var inAmbientContext = node.flags & 4194304 /* Ambient */; + var inAmbientContextOrInterface = node.parent.kind === 236 /* InterfaceDeclaration */ || node.parent.kind === 166 /* TypeLiteral */ || inAmbientContext; if (inAmbientContextOrInterface) { + // check if declarations are consecutive only if they are non-ambient + // 1. ambient declarations can be interleaved + // i.e. this is legal + // declare function foo(); + // declare function bar(); + // declare function foo(); + // 2. mixing ambient and non-ambient declarations is a separate error that will be reported - do not want to report an extra one previousDeclaration = undefined; } - if (node.kind === 234 || node.kind === 154 || node.kind === 153 || node.kind === 155) { + if (node.kind === 234 /* FunctionDeclaration */ || node.kind === 154 /* MethodDeclaration */ || node.kind === 153 /* MethodSignature */ || node.kind === 155 /* Constructor */) { var currentNodeFlags = getEffectiveDeclarationFlags(node, flagsToCheck); someNodeFlags |= currentNodeFlags; allNodeFlags &= currentNodeFlags; @@ -42227,8 +49159,9 @@ var ts; error(ts.getNameOfDeclaration(declaration), ts.Diagnostics.Duplicate_function_implementation); }); } + // Abstract methods can't have an implementation -- in particular, they don't need one. if (lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body && - !ts.hasModifier(lastSeenNonAmbientDeclaration, 128) && !lastSeenNonAmbientDeclaration.questionToken) { + !ts.hasModifier(lastSeenNonAmbientDeclaration, 128 /* Abstract */) && !lastSeenNonAmbientDeclaration.questionToken) { reportImplementationExpectedError(lastSeenNonAmbientDeclaration); } if (hasOverloads) { @@ -42251,25 +49184,30 @@ var ts; if (!produceDiagnostics) { return; } + // if localSymbol is defined on node then node itself is exported - check is required var symbol = node.localSymbol; if (!symbol) { + // local symbol is undefined => this declaration is non-exported. + // however symbol might contain other declarations that are exported symbol = getSymbolOfNode(node); if (!symbol.exportSymbol) { + // this is a pure local symbol (all declarations are non-exported) - no need to check anything return; } } + // run the check only for the first declaration in the list if (ts.getDeclarationOfKind(symbol, node.kind) !== node) { return; } - var exportedDeclarationSpaces = 0; - var nonExportedDeclarationSpaces = 0; - var defaultExportedDeclarationSpaces = 0; + var exportedDeclarationSpaces = 0 /* None */; + var nonExportedDeclarationSpaces = 0 /* None */; + var defaultExportedDeclarationSpaces = 0 /* None */; for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var d = _a[_i]; var declarationSpaces = getDeclarationSpaces(d); - var effectiveDeclarationFlags = getEffectiveDeclarationFlags(d, 1 | 512); - if (effectiveDeclarationFlags & 1) { - if (effectiveDeclarationFlags & 512) { + var effectiveDeclarationFlags = getEffectiveDeclarationFlags(d, 1 /* Export */ | 512 /* Default */); + if (effectiveDeclarationFlags & 1 /* Export */) { + if (effectiveDeclarationFlags & 512 /* Default */) { defaultExportedDeclarationSpaces |= declarationSpaces; } else { @@ -42280,14 +49218,17 @@ var ts; nonExportedDeclarationSpaces |= declarationSpaces; } } + // Spaces for anything not declared a 'default export'. var nonDefaultExportedDeclarationSpaces = exportedDeclarationSpaces | nonExportedDeclarationSpaces; var commonDeclarationSpacesForExportsAndLocals = exportedDeclarationSpaces & nonExportedDeclarationSpaces; var commonDeclarationSpacesForDefaultAndNonDefault = defaultExportedDeclarationSpaces & nonDefaultExportedDeclarationSpaces; if (commonDeclarationSpacesForExportsAndLocals || commonDeclarationSpacesForDefaultAndNonDefault) { + // declaration spaces for exported and non-exported declarations intersect for (var _b = 0, _c = symbol.declarations; _b < _c.length; _b++) { var d = _c[_b]; var declarationSpaces = getDeclarationSpaces(d); var name = ts.getNameOfDeclaration(d); + // Only error on the declarations that contributed to the intersecting spaces. if (declarationSpaces & commonDeclarationSpacesForDefaultAndNonDefault) { error(name, ts.Diagnostics.Merged_declaration_0_cannot_include_a_default_export_declaration_Consider_adding_a_separate_export_default_0_declaration_instead, ts.declarationNameToString(name)); } @@ -42306,37 +49247,41 @@ var ts; function getDeclarationSpaces(decl) { var d = decl; switch (d.kind) { - case 236: - case 237: - case 298: - case 292: - return 2; - case 239: - return ts.isAmbientModule(d) || ts.getModuleInstanceState(d) !== 0 - ? 4 | 1 - : 4; - case 235: - case 238: - return 2 | 1; - case 274: - return 2 | 1 | 4; - case 249: + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: + // A jsdoc typedef and callback are, by definition, type aliases + case 298 /* JSDocTypedefTag */: + case 292 /* JSDocCallbackTag */: + return 2 /* ExportType */; + case 239 /* ModuleDeclaration */: + return ts.isAmbientModule(d) || ts.getModuleInstanceState(d) !== 0 /* NonInstantiated */ + ? 4 /* ExportNamespace */ | 1 /* ExportValue */ + : 4 /* ExportNamespace */; + case 235 /* ClassDeclaration */: + case 238 /* EnumDeclaration */: + return 2 /* ExportType */ | 1 /* ExportValue */; + case 274 /* SourceFile */: + return 2 /* ExportType */ | 1 /* ExportValue */ | 4 /* ExportNamespace */; + case 249 /* ExportAssignment */: + // Export assigned entity name expressions act as aliases and should fall through, otherwise they export values if (!ts.isEntityNameExpression(d.expression)) { - return 1; + return 1 /* ExportValue */; } d = d.expression; - case 243: - case 246: - case 245: - var result_3 = 0; + /* falls through */ + // The below options all declare an Alias, which is allowed to merge with other values within the importing module + case 243 /* ImportEqualsDeclaration */: + case 246 /* NamespaceImport */: + case 245 /* ImportClause */: + var result_3 = 0 /* None */; var target = resolveAlias(getSymbolOfNode(d)); ts.forEach(target.declarations, function (d) { result_3 |= getDeclarationSpaces(d); }); return result_3; - case 232: - case 182: - case 234: - case 248: - return 1; + case 232 /* VariableDeclaration */: + case 182 /* BindingElement */: + case 234 /* FunctionDeclaration */: + case 248 /* ImportSpecifier */: // https://github.com/Microsoft/TypeScript/pull/7591 + return 1 /* ExportValue */; default: return ts.Debug.fail(ts.Debug.showSyntaxKind(d)); } @@ -42346,7 +49291,21 @@ var ts; var promisedType = getPromisedTypeOfPromise(type, errorNode); return promisedType && getAwaitedType(promisedType, errorNode, diagnosticMessage); } + /** + * Gets the "promised type" of a promise. + * @param type The type of the promise. + * @remarks The "promised type" of a type is the type of the "value" parameter of the "onfulfilled" callback. + */ function getPromisedTypeOfPromise(promise, errorNode) { + // + // { // promise + // then( // thenFunction + // onfulfilled: ( // onfulfilledParameterType + // value: T // valueParameterType + // ) => any + // ): any; + // } + // if (isTypeAny(promise)) { return undefined; } @@ -42354,33 +49313,40 @@ var ts; if (typeAsPromise.promisedTypeOfPromise) { return typeAsPromise.promisedTypeOfPromise; } - if (isReferenceToType(promise, getGlobalPromiseType(false))) { + if (isReferenceToType(promise, getGlobalPromiseType(/*reportErrors*/ false))) { return typeAsPromise.promisedTypeOfPromise = promise.typeArguments[0]; } - var thenFunction = getTypeOfPropertyOfType(promise, "then"); + var thenFunction = getTypeOfPropertyOfType(promise, "then"); // TODO: GH#18217 if (isTypeAny(thenFunction)) { return undefined; } - var thenSignatures = thenFunction ? getSignaturesOfType(thenFunction, 0) : ts.emptyArray; + var thenSignatures = thenFunction ? getSignaturesOfType(thenFunction, 0 /* Call */) : ts.emptyArray; if (thenSignatures.length === 0) { if (errorNode) { error(errorNode, ts.Diagnostics.A_promise_must_have_a_then_method); } return undefined; } - var onfulfilledParameterType = getTypeWithFacts(getUnionType(ts.map(thenSignatures, getTypeOfFirstParameterOfSignature)), 524288); + var onfulfilledParameterType = getTypeWithFacts(getUnionType(ts.map(thenSignatures, getTypeOfFirstParameterOfSignature)), 524288 /* NEUndefinedOrNull */); if (isTypeAny(onfulfilledParameterType)) { return undefined; } - var onfulfilledParameterSignatures = getSignaturesOfType(onfulfilledParameterType, 0); + var onfulfilledParameterSignatures = getSignaturesOfType(onfulfilledParameterType, 0 /* Call */); if (onfulfilledParameterSignatures.length === 0) { if (errorNode) { error(errorNode, ts.Diagnostics.The_first_parameter_of_the_then_method_of_a_promise_must_be_a_callback); } return undefined; } - return typeAsPromise.promisedTypeOfPromise = getUnionType(ts.map(onfulfilledParameterSignatures, getTypeOfFirstParameterOfSignature), 2); + return typeAsPromise.promisedTypeOfPromise = getUnionType(ts.map(onfulfilledParameterSignatures, getTypeOfFirstParameterOfSignature), 2 /* Subtype */); } + /** + * Gets the "awaited type" of a type. + * @param type The type to await. + * @remarks The "awaited type" of an expression is its "promised type" if the expression is a + * Promise-like type; otherwise, it is the type of the expression. This is used to reflect + * The runtime behavior of the `await` keyword. + */ function checkAwaitedType(type, errorNode, diagnosticMessage) { return getAwaitedType(type, errorNode, diagnosticMessage) || errorType; } @@ -42392,7 +49358,7 @@ var ts; if (isTypeAny(type)) { return typeAsAwaitable.awaitedTypeOfType = type; } - if (type.flags & 262144) { + if (type.flags & 262144 /* Union */) { var types = void 0; for (var _i = 0, _a = type.types; _i < _a.length; _i++) { var constituentType = _a[_i]; @@ -42406,11 +49372,45 @@ var ts; var promisedType = getPromisedTypeOfPromise(type); if (promisedType) { if (type.id === promisedType.id || awaitedTypeStack.indexOf(promisedType.id) >= 0) { + // Verify that we don't have a bad actor in the form of a promise whose + // promised type is the same as the promise type, or a mutually recursive + // promise. If so, we return undefined as we cannot guess the shape. If this + // were the actual case in the JavaScript, this Promise would never resolve. + // + // An example of a bad actor with a singly-recursive promise type might + // be: + // + // interface BadPromise { + // then( + // onfulfilled: (value: BadPromise) => any, + // onrejected: (error: any) => any): BadPromise; + // } + // The above interface will pass the PromiseLike check, and return a + // promised type of `BadPromise`. Since this is a self reference, we + // don't want to keep recursing ad infinitum. + // + // An example of a bad actor in the form of a mutually-recursive + // promise type might be: + // + // interface BadPromiseA { + // then( + // onfulfilled: (value: BadPromiseB) => any, + // onrejected: (error: any) => any): BadPromiseB; + // } + // + // interface BadPromiseB { + // then( + // onfulfilled: (value: BadPromiseA) => any, + // onrejected: (error: any) => any): BadPromiseA; + // } + // if (errorNode) { error(errorNode, ts.Diagnostics.Type_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method); } return undefined; } + // Keep track of the type we're about to unwrap to avoid bad recursive promise types. + // See the comments above for more information. awaitedTypeStack.push(type.id); var awaitedType = getAwaitedType(promisedType, errorNode, diagnosticMessage); awaitedTypeStack.pop(); @@ -42419,8 +49419,23 @@ var ts; } return typeAsAwaitable.awaitedTypeOfType = awaitedType; } + // The type was not a promise, so it could not be unwrapped any further. + // As long as the type does not have a callable "then" property, it is + // safe to return the type; otherwise, an error will be reported in + // the call to getNonThenableType and we will return undefined. + // + // An example of a non-promise "thenable" might be: + // + // await { then(): void {} } + // + // The "thenable" does not match the minimal definition for a promise. When + // a Promise/A+-compatible or ES6 promise tries to adopt this value, the promise + // will never settle. We treat this as an error to help flag an early indicator + // of a runtime problem. If the user wants to return this value from an async + // function, they would need to wrap it in some other value. If they want it to + // be treated as a promise, they can cast to . var thenFunction = getTypeOfPropertyOfType(type, "then"); - if (thenFunction && getSignaturesOfType(thenFunction, 0).length > 0) { + if (thenFunction && getSignaturesOfType(thenFunction, 0 /* Call */).length > 0) { if (errorNode) { if (!diagnosticMessage) return ts.Debug.fail(); @@ -42430,20 +49445,60 @@ var ts; } return typeAsAwaitable.awaitedTypeOfType = type; } + /** + * Checks the return type of an async function to ensure it is a compatible + * Promise implementation. + * + * This checks that an async function has a valid Promise-compatible return type, + * and returns the *awaited type* of the promise. An async function has a valid + * Promise-compatible return type if the resolved value of the return type has a + * construct signature that takes in an `initializer` function that in turn supplies + * a `resolve` function as one of its arguments and results in an object with a + * callable `then` signature. + * + * @param node The signature to check + */ function checkAsyncFunctionReturnType(node) { - var returnTypeNode = ts.getEffectiveReturnTypeNode(node); + // As part of our emit for an async function, we will need to emit the entity name of + // the return type annotation as an expression. To meet the necessary runtime semantics + // for __awaiter, we must also check that the type of the declaration (e.g. the static + // side or "constructor" of the promise type) is compatible `PromiseConstructorLike`. + // + // An example might be (from lib.es6.d.ts): + // + // interface Promise { ... } + // interface PromiseConstructor { + // new (...): Promise; + // } + // declare var Promise: PromiseConstructor; + // + // When an async function declares a return type annotation of `Promise`, we + // need to get the type of the `Promise` variable declaration above, which would + // be `PromiseConstructor`. + // + // The same case applies to a class: + // + // declare class Promise { + // constructor(...); + // then(...): Promise; + // } + // + var returnTypeNode = ts.getEffectiveReturnTypeNode(node); // TODO: GH#18217 var returnType = getTypeFromTypeNode(returnTypeNode); - if (languageVersion >= 2) { + if (languageVersion >= 2 /* ES2015 */) { if (returnType === errorType) { return errorType; } - var globalPromiseType = getGlobalPromiseType(true); + var globalPromiseType = getGlobalPromiseType(/*reportErrors*/ true); if (globalPromiseType !== emptyGenericType && !isReferenceToType(returnType, globalPromiseType)) { + // The promise type was not a valid type reference to the global promise type, so we + // report an error and return the unknown type. error(returnTypeNode, ts.Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type); return errorType; } } else { + // Always mark the type node as referenced if it points to a value markTypeNodeAsReferenced(returnTypeNode); if (returnType === errorType) { return errorType; @@ -42453,10 +49508,10 @@ var ts; error(returnTypeNode, ts.Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, typeToString(returnType)); return errorType; } - var promiseConstructorSymbol = resolveEntityName(promiseConstructorName, 67216319, true); + var promiseConstructorSymbol = resolveEntityName(promiseConstructorName, 67216319 /* Value */, /*ignoreErrors*/ true); var promiseConstructorType = promiseConstructorSymbol ? getTypeOfSymbol(promiseConstructorSymbol) : errorType; if (promiseConstructorType === errorType) { - if (promiseConstructorName.kind === 71 && promiseConstructorName.escapedText === "Promise" && getTargetType(returnType) === getGlobalPromiseType(false)) { + if (promiseConstructorName.kind === 71 /* Identifier */ && promiseConstructorName.escapedText === "Promise" && getTargetType(returnType) === getGlobalPromiseType(/*reportErrors*/ false)) { error(returnTypeNode, ts.Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option); } else { @@ -42464,50 +49519,57 @@ var ts; } return errorType; } - var globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType(true); + var globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType(/*reportErrors*/ true); if (globalPromiseConstructorLikeType === emptyObjectType) { + // If we couldn't resolve the global PromiseConstructorLike type we cannot verify + // compatibility with __awaiter. error(returnTypeNode, ts.Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, ts.entityNameToString(promiseConstructorName)); return errorType; } if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, returnTypeNode, ts.Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value)) { return errorType; } + // Verify there is no local declaration that could collide with the promise constructor. var rootName = promiseConstructorName && getFirstIdentifier(promiseConstructorName); - var collidingSymbol = getSymbol(node.locals, rootName.escapedText, 67216319); + var collidingSymbol = getSymbol(node.locals, rootName.escapedText, 67216319 /* Value */); if (collidingSymbol) { error(collidingSymbol.valueDeclaration, ts.Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions, ts.idText(rootName), ts.entityNameToString(promiseConstructorName)); return errorType; } } + // Get and return the awaited type of the return type. return checkAwaitedType(returnType, node, ts.Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); } + /** Check a decorator */ function checkDecorator(node) { var signature = getResolvedSignature(node); var returnType = getReturnTypeOfSignature(signature); - if (returnType.flags & 1) { + if (returnType.flags & 1 /* Any */) { return; } var expectedReturnType; var headMessage = getDiagnosticHeadMessageForDecoratorResolution(node); var errorInfo; switch (node.parent.kind) { - case 235: + case 235 /* ClassDeclaration */: var classSymbol = getSymbolOfNode(node.parent); var classConstructorType = getTypeOfSymbol(classSymbol); expectedReturnType = getUnionType([classConstructorType, voidType]); break; - case 149: + case 149 /* Parameter */: expectedReturnType = voidType; - errorInfo = ts.chainDiagnosticMessages(undefined, ts.Diagnostics.The_return_type_of_a_parameter_decorator_function_must_be_either_void_or_any); + errorInfo = ts.chainDiagnosticMessages( + /*details*/ undefined, ts.Diagnostics.The_return_type_of_a_parameter_decorator_function_must_be_either_void_or_any); break; - case 152: + case 152 /* PropertyDeclaration */: expectedReturnType = voidType; - errorInfo = ts.chainDiagnosticMessages(undefined, ts.Diagnostics.The_return_type_of_a_property_decorator_function_must_be_either_void_or_any); + errorInfo = ts.chainDiagnosticMessages( + /*details*/ undefined, ts.Diagnostics.The_return_type_of_a_property_decorator_function_must_be_either_void_or_any); break; - case 154: - case 156: - case 157: - var methodType = getTypeOfNode(node.parent); + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + var methodType = getTypeOfNode(node.parent); // TODO: GH#18217 var descriptorType = createTypedPropertyDescriptorType(methodType); expectedReturnType = getUnionType([descriptorType, voidType]); break; @@ -42516,6 +49578,10 @@ var ts; } checkTypeAssignableTo(returnType, expectedReturnType, node, headMessage, function () { return errorInfo; }); } + /** + * If a TypeNode can be resolved to a value symbol imported from an external module, it is + * marked as referenced to prevent import elision. + */ function markTypeNodeAsReferenced(node) { markEntityNameOrEntityExpressionAsReference(node && ts.getEntityNameFromTypeNode(node)); } @@ -42523,15 +49589,22 @@ var ts; if (!typeName) return; var rootName = getFirstIdentifier(typeName); - var meaning = (typeName.kind === 71 ? 67901928 : 1920) | 2097152; - var rootSymbol = resolveName(rootName, rootName.escapedText, meaning, undefined, undefined, true); + var meaning = (typeName.kind === 71 /* Identifier */ ? 67901928 /* Type */ : 1920 /* Namespace */) | 2097152 /* Alias */; + var rootSymbol = resolveName(rootName, rootName.escapedText, meaning, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isRefernce*/ true); if (rootSymbol - && rootSymbol.flags & 2097152 + && rootSymbol.flags & 2097152 /* Alias */ && symbolIsValue(rootSymbol) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(rootSymbol))) { markAliasSymbolAsReferenced(rootSymbol); } } + /** + * This function marks the type used for metadata decorator as referenced if it is import + * from external module. + * This is different from markTypeNodeAsReferenced because it tries to simplify type nodes in + * union and intersection type + * @param node + */ function markDecoratorMedataDataTypeNodeAsReferenced(node) { var entityName = getEntityNameForDecoratorMetadata(node); if (entityName && ts.isEntityName(entityName)) { @@ -42541,25 +49614,32 @@ var ts; function getEntityNameForDecoratorMetadata(node) { if (node) { switch (node.kind) { - case 170: - case 169: + case 170 /* IntersectionType */: + case 169 /* UnionType */: var commonEntityName = void 0; for (var _i = 0, _a = node.types; _i < _a.length; _i++) { var typeNode = _a[_i]; - while (typeNode.kind === 173) { - typeNode = typeNode.type; + while (typeNode.kind === 173 /* ParenthesizedType */) { + typeNode = typeNode.type; // Skip parens if need be } - if (typeNode.kind === 131) { - continue; + if (typeNode.kind === 131 /* NeverKeyword */) { + continue; // Always elide `never` from the union/intersection if possible } - if (!strictNullChecks && (typeNode.kind === 95 || typeNode.kind === 140)) { - continue; + if (!strictNullChecks && (typeNode.kind === 95 /* NullKeyword */ || typeNode.kind === 140 /* UndefinedKeyword */)) { + continue; // Elide null and undefined from unions for metadata, just like what we did prior to the implementation of strict null checks } var individualEntityName = getEntityNameForDecoratorMetadata(typeNode); if (!individualEntityName) { + // Individual is something like string number + // So it would be serialized to either that type or object + // Safe to return here return undefined; } if (commonEntityName) { + // Note this is in sync with the transformation that happens for type node. + // Keep this in sync with serializeUnionOrIntersectionType + // Verify if they refer to same entity and is identifier + // return undefined if they dont match because we would emit object if (!ts.isIdentifier(commonEntityName) || !ts.isIdentifier(individualEntityName) || commonEntityName.escapedText !== individualEntityName.escapedText) { @@ -42571,9 +49651,9 @@ var ts; } } return commonEntityName; - case 173: + case 173 /* ParenthesizedType */: return getEntityNameForDecoratorMetadata(node.type); - case 162: + case 162 /* TypeReference */: return node.typeName; } } @@ -42582,10 +49662,13 @@ var ts; var typeNode = ts.getEffectiveTypeAnnotationNode(node); return ts.isRestParameter(node) ? ts.getRestParameterElementType(typeNode) : typeNode; } + /** Check the decorators of a node */ function checkDecorators(node) { if (!node.decorators) { return; } + // skip this check for nodes that cannot have decorators. These should have already had an error reported by + // checkGrammarDecorators. if (!ts.nodeCanBeDecorated(node, node.parent, node.parent.parent)) { return; } @@ -42593,14 +49676,15 @@ var ts; error(node, ts.Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_to_remove_this_warning); } var firstDecorator = node.decorators[0]; - checkExternalEmitHelpers(firstDecorator, 8); - if (node.kind === 149) { - checkExternalEmitHelpers(firstDecorator, 32); + checkExternalEmitHelpers(firstDecorator, 8 /* Decorate */); + if (node.kind === 149 /* Parameter */) { + checkExternalEmitHelpers(firstDecorator, 32 /* Param */); } if (compilerOptions.emitDecoratorMetadata) { - checkExternalEmitHelpers(firstDecorator, 16); + checkExternalEmitHelpers(firstDecorator, 16 /* Metadata */); + // we only need to perform these checks if we are emitting serialized type metadata for the target of a decorator. switch (node.kind) { - case 235: + case 235 /* ClassDeclaration */: var constructor = ts.getFirstConstructorWithBody(node); if (constructor) { for (var _i = 0, _a = constructor.parameters; _i < _a.length; _i++) { @@ -42609,19 +49693,19 @@ var ts; } } break; - case 154: - case 156: - case 157: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: for (var _b = 0, _c = node.parameters; _b < _c.length; _b++) { var parameter = _c[_b]; markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter)); } markDecoratorMedataDataTypeNodeAsReferenced(ts.getEffectiveReturnTypeNode(node)); break; - case 152: + case 152 /* PropertyDeclaration */: markDecoratorMedataDataTypeNodeAsReferenced(ts.getEffectiveTypeAnnotationNode(node)); break; - case 149: + case 149 /* Parameter */: markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(node)); var containingSignature = node.parent; for (var _d = 0, _e = containingSignature.parameters; _d < _e.length; _d++) { @@ -42643,6 +49727,7 @@ var ts; } function checkJSDocTypeAliasTag(node) { if (!node.typeExpression) { + // If the node had `@property` tags, `typeExpression` would have been set to the first property tag. error(node.name, ts.Diagnostics.JSDoc_typedef_tag_should_either_have_a_type_annotation_or_be_followed_by_property_or_member_tags); } if (node.name) { @@ -42657,18 +49742,21 @@ var ts; checkSourceElement(node.typeExpression); if (!ts.getParameterSymbolFromJSDoc(node)) { var decl = ts.getHostSignatureFromJSDoc(node); + // don't issue an error for invalid hosts -- just functions -- + // and give a better error message when the host function mentions `arguments` + // but the tag doesn't have an array type if (decl) { var i = ts.getJSDocTags(decl).filter(ts.isJSDocParameterTag).indexOf(node); if (i > -1 && i < decl.parameters.length && ts.isBindingPattern(decl.parameters[i].name)) { return; } if (!containsArgumentsReference(decl)) { - error(node.name, ts.Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name, ts.idText(node.name.kind === 146 ? node.name.right : node.name)); + error(node.name, ts.Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name, ts.idText(node.name.kind === 146 /* QualifiedName */ ? node.name.right : node.name)); } else if (ts.findLast(ts.getJSDocTags(decl), ts.isJSDocParameterTag) === node && node.typeExpression && node.typeExpression.type && !isArrayType(getTypeFromTypeNode(node.typeExpression.type))) { - error(node.name, ts.Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name_It_would_match_arguments_if_it_had_an_array_type, ts.idText(node.name.kind === 146 ? node.name.right : node.name)); + error(node.name, ts.Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name_It_would_match_arguments_if_it_had_an_array_type, ts.idText(node.name.kind === 146 /* QualifiedName */ ? node.name.right : node.name)); } } } @@ -42695,9 +49783,9 @@ var ts; } function getIdentifierFromEntityNameExpression(node) { switch (node.kind) { - case 71: + case 71 /* Identifier */: return node; - case 185: + case 185 /* PropertyAccessExpression */: return node.name; default: return undefined; @@ -42707,41 +49795,63 @@ var ts; checkDecorators(node); checkSignatureDeclaration(node); var functionFlags = ts.getFunctionFlags(node); - if (node.name && node.name.kind === 147) { + // Do not use hasDynamicName here, because that returns false for well known symbols. + // We want to perform checkComputedPropertyName for all computed properties, including + // well known symbols. + if (node.name && node.name.kind === 147 /* ComputedPropertyName */) { + // This check will account for methods in class/interface declarations, + // as well as accessors in classes/object literals checkComputedPropertyName(node.name); } if (!hasNonBindableDynamicName(node)) { + // first we want to check the local symbol that contain this declaration + // - if node.localSymbol !== undefined - this is current declaration is exported and localSymbol points to the local symbol + // - if node.localSymbol === undefined - this node is non-exported so we can just pick the result of getSymbolOfNode var symbol = getSymbolOfNode(node); var localSymbol = node.localSymbol || symbol; - var firstDeclaration = ts.find(localSymbol.declarations, function (declaration) { return declaration.kind === node.kind && !(declaration.flags & 65536); }); + // Since the javascript won't do semantic analysis like typescript, + // if the javascript file comes before the typescript file and both contain same name functions, + // checkFunctionOrConstructorSymbol wouldn't be called if we didnt ignore javascript function. + var firstDeclaration = ts.find(localSymbol.declarations, + // Get first non javascript function declaration + function (declaration) { return declaration.kind === node.kind && !(declaration.flags & 65536 /* JavaScriptFile */); }); + // Only type check the symbol once if (node === firstDeclaration) { checkFunctionOrConstructorSymbol(localSymbol); } if (symbol.parent) { + // run check once for the first declaration if (ts.getDeclarationOfKind(symbol, node.kind) === node) { + // run check on export symbol to check that modifiers agree across all exported declarations checkFunctionOrConstructorSymbol(symbol); } } } - var body = node.kind === 153 ? undefined : node.body; + var body = node.kind === 153 /* MethodSignature */ ? undefined : node.body; checkSourceElement(body); var returnTypeNode = ts.getEffectiveReturnTypeNode(node); - if ((functionFlags & 1) === 0) { - var returnOrPromisedType = returnTypeNode && (functionFlags & 2 - ? checkAsyncFunctionReturnType(node) - : getTypeFromTypeNode(returnTypeNode)); + if ((functionFlags & 1 /* Generator */) === 0) { // Async function or normal function + var returnOrPromisedType = returnTypeNode && (functionFlags & 2 /* Async */ + ? checkAsyncFunctionReturnType(node) // Async function + : getTypeFromTypeNode(returnTypeNode)); // normal function checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType); } if (produceDiagnostics && !returnTypeNode) { + // Report an implicit any error if there is no body, no explicit return type, and node is not a private method + // in an ambient context if (noImplicitAny && ts.nodeIsMissing(body) && !isPrivateWithinAmbient(node)) { reportImplicitAnyError(node, anyType); } - if (functionFlags & 1 && ts.nodeIsPresent(body)) { + if (functionFlags & 1 /* Generator */ && ts.nodeIsPresent(body)) { + // A generator with a body and no type annotation can still cause errors. It can error if the + // yielded values have no common supertype, or it can give an implicit any error if it has no + // yielded values. The only way to trigger these errors is to try checking its return type. getReturnTypeOfSignature(getSignatureFromDeclaration(node)); } } } function registerForUnusedIdentifiersCheck(node) { + // May be in a call such as getTypeOfNode that happened to call this. But potentiallyUnusedIdentifiers is only defined in the scope of `checkSourceFile`. if (produceDiagnostics) { var sourceFile = ts.getSourceFileOfNode(node); var potentiallyUnusedIdentifiers = allPotentiallyUnusedIdentifiers.get(sourceFile.path); @@ -42749,6 +49859,8 @@ var ts; potentiallyUnusedIdentifiers = []; allPotentiallyUnusedIdentifiers.set(sourceFile.path, potentiallyUnusedIdentifiers); } + // TODO: GH#22580 + // Debug.assert(addToSeen(seenPotentiallyUnusedIdentifiers, getNodeId(node)), "Adding potentially-unused identifier twice"); potentiallyUnusedIdentifiers.push(node); } } @@ -42756,41 +49868,41 @@ var ts; for (var _i = 0, potentiallyUnusedIdentifiers_1 = potentiallyUnusedIdentifiers; _i < potentiallyUnusedIdentifiers_1.length; _i++) { var node = potentiallyUnusedIdentifiers_1[_i]; switch (node.kind) { - case 235: - case 205: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: checkUnusedClassMembers(node, addDiagnostic); checkUnusedTypeParameters(node, addDiagnostic); break; - case 236: + case 236 /* InterfaceDeclaration */: checkUnusedTypeParameters(node, addDiagnostic); break; - case 274: - case 239: - case 213: - case 241: - case 220: - case 221: - case 222: + case 274 /* SourceFile */: + case 239 /* ModuleDeclaration */: + case 213 /* Block */: + case 241 /* CaseBlock */: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: checkUnusedLocalsAndParameters(node, addDiagnostic); break; - case 155: - case 192: - case 234: - case 193: - case 154: - case 156: - case 157: + case 155 /* Constructor */: + case 192 /* FunctionExpression */: + case 234 /* FunctionDeclaration */: + case 193 /* ArrowFunction */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: if (node.body) { checkUnusedLocalsAndParameters(node, addDiagnostic); } checkUnusedTypeParameters(node, addDiagnostic); break; - case 153: - case 158: - case 159: - case 163: - case 164: - case 237: + case 153 /* MethodSignature */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 237 /* TypeAliasDeclaration */: checkUnusedTypeParameters(node, addDiagnostic); break; default: @@ -42801,41 +49913,43 @@ var ts; function errorUnusedLocal(declaration, name, addDiagnostic) { var node = ts.getNameOfDeclaration(declaration) || declaration; var message = isTypeDeclaration(declaration) ? ts.Diagnostics._0_is_declared_but_never_used : ts.Diagnostics._0_is_declared_but_its_value_is_never_read; - addDiagnostic(0, ts.createDiagnosticForNode(node, message, name)); + addDiagnostic(0 /* Local */, ts.createDiagnosticForNode(node, message, name)); } function parameterNameStartsWithUnderscore(parameterName) { return parameterName && isIdentifierThatStartsWithUnderScore(parameterName); } function isIdentifierThatStartsWithUnderScore(node) { - return ts.isIdentifier(node) && ts.idText(node).charCodeAt(0) === 95; + return ts.isIdentifier(node) && ts.idText(node).charCodeAt(0) === 95 /* _ */; } function checkUnusedClassMembers(node, addDiagnostic) { - if (!(node.flags & 4194304)) { + if (!(node.flags & 4194304 /* Ambient */)) { for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var member = _a[_i]; switch (member.kind) { - case 154: - case 152: - case 156: - case 157: - if (member.kind === 157 && member.symbol.flags & 32768) { + case 154 /* MethodDeclaration */: + case 152 /* PropertyDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + if (member.kind === 157 /* SetAccessor */ && member.symbol.flags & 32768 /* GetAccessor */) { + // Already would have reported an error on the getter. break; } var symbol = getSymbolOfNode(member); - if (!symbol.isReferenced && ts.hasModifier(member, 8)) { - addDiagnostic(0, ts.createDiagnosticForNode(member.name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, symbolToString(symbol))); + if (!symbol.isReferenced && ts.hasModifier(member, 8 /* Private */)) { + addDiagnostic(0 /* Local */, ts.createDiagnosticForNode(member.name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, symbolToString(symbol))); } break; - case 155: + case 155 /* Constructor */: for (var _b = 0, _c = member.parameters; _b < _c.length; _b++) { var parameter = _c[_b]; - if (!parameter.symbol.isReferenced && ts.hasModifier(parameter, 8)) { - addDiagnostic(0, ts.createDiagnosticForNode(parameter.name, ts.Diagnostics.Property_0_is_declared_but_its_value_is_never_read, ts.symbolName(parameter.symbol))); + if (!parameter.symbol.isReferenced && ts.hasModifier(parameter, 8 /* Private */)) { + addDiagnostic(0 /* Local */, ts.createDiagnosticForNode(parameter.name, ts.Diagnostics.Property_0_is_declared_but_its_value_is_never_read, ts.symbolName(parameter.symbol))); } } break; - case 160: - case 212: + case 160 /* IndexSignature */: + case 212 /* SemicolonClassElement */: + // Can't be private break; default: ts.Debug.fail(); @@ -42844,12 +49958,14 @@ var ts; } } function checkUnusedTypeParameters(node, addDiagnostic) { + // Only report errors on the last declaration for the type parameter container; + // this ensures that all uses have been accounted for. var typeParameters = ts.getEffectiveTypeParameterDeclarations(node); - if (!(node.flags & 4194304) && ts.last(getSymbolOfNode(node).declarations) === node) { + if (!(node.flags & 4194304 /* Ambient */) && ts.last(getSymbolOfNode(node).declarations) === node) { for (var _i = 0, typeParameters_2 = typeParameters; _i < typeParameters_2.length; _i++) { var typeParameter = typeParameters_2[_i]; - if (!(getMergedSymbol(typeParameter.symbol).isReferenced & 262144) && !isIdentifierThatStartsWithUnderScore(typeParameter.name)) { - addDiagnostic(1, ts.createDiagnosticForNode(typeParameter.name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.symbolName(typeParameter.symbol))); + if (!(getMergedSymbol(typeParameter.symbol).isReferenced & 262144 /* TypeParameter */) && !isIdentifierThatStartsWithUnderScore(typeParameter.name)) { + addDiagnostic(1 /* Parameter */, ts.createDiagnosticForNode(typeParameter.name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.symbolName(typeParameter.symbol))); } } } @@ -42868,13 +49984,16 @@ var ts; return ts.tryCast(ts.getRootDeclaration(node), ts.isParameter); } function checkUnusedLocalsAndParameters(nodeWithLocals, addDiagnostic) { - if (nodeWithLocals.flags & 4194304) + if (nodeWithLocals.flags & 4194304 /* Ambient */) return; + // Ideally we could use the ImportClause directly as a key, but must wait until we have full ES6 maps. So must store key along with value. var unusedImports = ts.createMap(); var unusedDestructures = ts.createMap(); var unusedVariables = ts.createMap(); nodeWithLocals.locals.forEach(function (local) { - if (local.flags & 262144 ? !(local.flags & 3 && !(local.isReferenced & 3)) : local.isReferenced || local.exportSymbol) { + // If it's purely a type parameter, ignore, will be checked in `checkUnusedTypeParameters`. + // If it's a type parameter merged with a parameter, check if the parameter-side is used. + if (local.flags & 262144 /* TypeParameter */ ? !(local.flags & 3 /* Variable */ && !(local.isReferenced & 3 /* Variable */)) : local.isReferenced || local.exportSymbol) { return; } for (var _i = 0, _a = local.declarations; _i < _a.length; _i++) { @@ -42887,6 +50006,7 @@ var ts; addToGroup(unusedImports, importClauseFromImported(declaration), declaration, getNodeId); } else if (ts.isBindingElement(declaration) && ts.isObjectBindingPattern(declaration.parent)) { + // In `{ a, ...b }, `a` is considered used since it removes a property from `b`. `b` may still be unused though. var lastElement = ts.last(declaration.parent.elements); if (declaration === lastElement || !ts.last(declaration.parent.elements).dotDotDotToken) { addToGroup(unusedDestructures, declaration.parent, declaration, getNodeId); @@ -42900,7 +50020,7 @@ var ts; if (parameter) { var name = ts.getNameOfDeclaration(local.valueDeclaration); if (!ts.isParameterPropertyDeclaration(parameter) && !ts.parameterIsThisKeyword(parameter) && !parameterNameStartsWithUnderscore(name)) { - addDiagnostic(1, ts.createDiagnosticForNode(name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.symbolName(local))); + addDiagnostic(1 /* Parameter */, ts.createDiagnosticForNode(name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.symbolName(local))); } } else { @@ -42914,10 +50034,10 @@ var ts; var importDecl = importClause.parent; var nDeclarations = (importClause.name ? 1 : 0) + (importClause.namedBindings ? - (importClause.namedBindings.kind === 246 ? 1 : importClause.namedBindings.elements.length) + (importClause.namedBindings.kind === 246 /* NamespaceImport */ ? 1 : importClause.namedBindings.elements.length) : 0); if (nDeclarations === unuseds.length) { - addDiagnostic(0, unuseds.length === 1 + addDiagnostic(0 /* Local */, unuseds.length === 1 ? ts.createDiagnosticForNode(importDecl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.first(unuseds).name)) : ts.createDiagnosticForNode(importDecl, ts.Diagnostics.All_imports_in_import_declaration_are_unused)); } @@ -42930,9 +50050,9 @@ var ts; }); unusedDestructures.forEach(function (_a) { var bindingPattern = _a[0], bindingElements = _a[1]; - var kind = tryGetRootParameterDeclaration(bindingPattern.parent) ? 1 : 0; + var kind = tryGetRootParameterDeclaration(bindingPattern.parent) ? 1 /* Parameter */ : 0 /* Local */; if (bindingPattern.elements.length === bindingElements.length) { - if (bindingElements.length === 1 && bindingPattern.parent.kind === 232 && bindingPattern.parent.parent.kind === 233) { + if (bindingElements.length === 1 && bindingPattern.parent.kind === 232 /* VariableDeclaration */ && bindingPattern.parent.parent.kind === 233 /* VariableDeclarationList */) { addToGroup(unusedVariables, bindingPattern.parent.parent, bindingPattern.parent, getNodeId); } else { @@ -42951,37 +50071,38 @@ var ts; unusedVariables.forEach(function (_a) { var declarationList = _a[0], declarations = _a[1]; if (declarationList.declarations.length === declarations.length) { - addDiagnostic(0, declarations.length === 1 + addDiagnostic(0 /* Local */, declarations.length === 1 ? ts.createDiagnosticForNode(ts.first(declarations).name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(ts.first(declarations).name)) - : ts.createDiagnosticForNode(declarationList.parent.kind === 214 ? declarationList.parent : declarationList, ts.Diagnostics.All_variables_are_unused)); + : ts.createDiagnosticForNode(declarationList.parent.kind === 214 /* VariableStatement */ ? declarationList.parent : declarationList, ts.Diagnostics.All_variables_are_unused)); } else { for (var _i = 0, declarations_5 = declarations; _i < declarations_5.length; _i++) { var decl = declarations_5[_i]; - addDiagnostic(0, ts.createDiagnosticForNode(decl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(decl.name, ts.isIdentifier)))); + addDiagnostic(0 /* Local */, ts.createDiagnosticForNode(decl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(decl.name, ts.isIdentifier)))); } } }); } function bindingNameText(name) { switch (name.kind) { - case 71: + case 71 /* Identifier */: return ts.idText(name); - case 181: - case 180: + case 181 /* ArrayBindingPattern */: + case 180 /* ObjectBindingPattern */: return bindingNameText(ts.cast(ts.first(name.elements), ts.isBindingElement).name); default: return ts.Debug.assertNever(name); } } function isImportedDeclaration(node) { - return node.kind === 245 || node.kind === 248 || node.kind === 246; + return node.kind === 245 /* ImportClause */ || node.kind === 248 /* ImportSpecifier */ || node.kind === 246 /* NamespaceImport */; } function importClauseFromImported(decl) { - return decl.kind === 245 ? decl : decl.kind === 246 ? decl.parent : decl.parent.parent; + return decl.kind === 245 /* ImportClause */ ? decl : decl.kind === 246 /* NamespaceImport */ ? decl.parent : decl.parent.parent; } function checkBlock(node) { - if (node.kind === 213) { + // Grammar checking for SyntaxKind.Block + if (node.kind === 213 /* Block */) { checkGrammarStatementInAmbientContext(node); } if (ts.isFunctionOrModuleBlock(node)) { @@ -42997,7 +50118,8 @@ var ts; } } function checkCollisionWithArgumentsInGeneratedCode(node) { - if (languageVersion >= 2 || compilerOptions.noEmit || !ts.hasRestParameter(node) || node.flags & 4194304 || ts.nodeIsMissing(node.body)) { + // no rest parameters \ declaration context \ overload - no codegen impact + if (languageVersion >= 2 /* ES2015 */ || compilerOptions.noEmit || !ts.hasRestParameter(node) || node.flags & 4194304 /* Ambient */ || ts.nodeIsMissing(node.body)) { return; } ts.forEach(node.parameters, function (p) { @@ -43010,27 +50132,31 @@ var ts; if (!(identifier && identifier.escapedText === name)) { return false; } - if (node.kind === 152 || - node.kind === 151 || - node.kind === 154 || - node.kind === 153 || - node.kind === 156 || - node.kind === 157) { + if (node.kind === 152 /* PropertyDeclaration */ || + node.kind === 151 /* PropertySignature */ || + node.kind === 154 /* MethodDeclaration */ || + node.kind === 153 /* MethodSignature */ || + node.kind === 156 /* GetAccessor */ || + node.kind === 157 /* SetAccessor */) { + // it is ok to have member named '_super' or '_this' - member access is always qualified return false; } - if (node.flags & 4194304) { + if (node.flags & 4194304 /* Ambient */) { + // ambient context - no codegen impact return false; } var root = ts.getRootDeclaration(node); - if (root.kind === 149 && ts.nodeIsMissing(root.parent.body)) { + if (root.kind === 149 /* Parameter */ && ts.nodeIsMissing(root.parent.body)) { + // just an overload - no codegen impact return false; } return true; } + // this function will run after checking the source file so 'CaptureThis' is correct for all nodes function checkIfThisIsCapturedInEnclosingScope(node) { ts.findAncestor(node, function (current) { - if (getNodeCheckFlags(current) & 4) { - var isDeclaration_1 = node.kind !== 71; + if (getNodeCheckFlags(current) & 4 /* CaptureThis */) { + var isDeclaration_1 = node.kind !== 71 /* Identifier */; if (isDeclaration_1) { error(ts.getNameOfDeclaration(node), ts.Diagnostics.Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference); } @@ -43044,8 +50170,8 @@ var ts; } function checkIfNewTargetIsCapturedInEnclosingScope(node) { ts.findAncestor(node, function (current) { - if (getNodeCheckFlags(current) & 8) { - var isDeclaration_2 = node.kind !== 71; + if (getNodeCheckFlags(current) & 8 /* CaptureNewTarget */) { + var isDeclaration_2 = node.kind !== 71 /* Identifier */; if (isDeclaration_2) { error(ts.getNameOfDeclaration(node), ts.Diagnostics.Duplicate_identifier_newTarget_Compiler_uses_variable_declaration_newTarget_to_capture_new_target_meta_property_reference); } @@ -43058,57 +50184,96 @@ var ts; }); } function checkCollisionWithRequireExportsInGeneratedCode(node, name) { + // No need to check for require or exports for ES6 modules and later if (moduleKind >= ts.ModuleKind.ES2015 || compilerOptions.noEmit) { return; } if (!needCollisionCheckForIdentifier(node, name, "require") && !needCollisionCheckForIdentifier(node, name, "exports")) { return; } - if (ts.isModuleDeclaration(node) && ts.getModuleInstanceState(node) !== 1) { + // Uninstantiated modules shouldnt do this check + if (ts.isModuleDeclaration(node) && ts.getModuleInstanceState(node) !== 1 /* Instantiated */) { return; } + // In case of variable declaration, node.parent is variable statement so look at the variable statement's parent var parent = getDeclarationContainer(node); - if (parent.kind === 274 && ts.isExternalOrCommonJsModule(parent)) { + if (parent.kind === 274 /* SourceFile */ && ts.isExternalOrCommonJsModule(parent)) { + // If the declaration happens to be in external module, report error that require and exports are reserved keywords error(name, ts.Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module, ts.declarationNameToString(name), ts.declarationNameToString(name)); } } function checkCollisionWithGlobalPromiseInGeneratedCode(node, name) { - if (languageVersion >= 4 || compilerOptions.noEmit || !needCollisionCheckForIdentifier(node, name, "Promise")) { + if (languageVersion >= 4 /* ES2017 */ || compilerOptions.noEmit || !needCollisionCheckForIdentifier(node, name, "Promise")) { return; } - if (ts.isModuleDeclaration(node) && ts.getModuleInstanceState(node) !== 1) { + // Uninstantiated modules shouldnt do this check + if (ts.isModuleDeclaration(node) && ts.getModuleInstanceState(node) !== 1 /* Instantiated */) { return; } + // In case of variable declaration, node.parent is variable statement so look at the variable statement's parent var parent = getDeclarationContainer(node); - if (parent.kind === 274 && ts.isExternalOrCommonJsModule(parent) && parent.flags & 1024) { + if (parent.kind === 274 /* SourceFile */ && ts.isExternalOrCommonJsModule(parent) && parent.flags & 1024 /* HasAsyncFunctions */) { + // If the declaration happens to be in external module, report error that Promise is a reserved identifier. error(name, ts.Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module_containing_async_functions, ts.declarationNameToString(name), ts.declarationNameToString(name)); } } function checkVarDeclaredNamesNotShadowed(node) { - if ((ts.getCombinedNodeFlags(node) & 3) !== 0 || ts.isParameterDeclaration(node)) { + // - ScriptBody : StatementList + // It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList + // also occurs in the VarDeclaredNames of StatementList. + // - Block : { StatementList } + // It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList + // also occurs in the VarDeclaredNames of StatementList. + // Variable declarations are hoisted to the top of their function scope. They can shadow + // block scoped declarations, which bind tighter. this will not be flagged as duplicate definition + // by the binder as the declaration scope is different. + // A non-initialized declaration is a no-op as the block declaration will resolve before the var + // declaration. the problem is if the declaration has an initializer. this will act as a write to the + // block declared value. this is fine for let, but not const. + // Only consider declarations with initializers, uninitialized const declarations will not + // step on a let/const variable. + // Do not consider const and const declarations, as duplicate block-scoped declarations + // are handled by the binder. + // We are only looking for const declarations that step on let\const declarations from a + // different scope. e.g.: + // { + // const x = 0; // localDeclarationSymbol obtained after name resolution will correspond to this declaration + // const x = 0; // symbol for this declaration will be 'symbol' + // } + // skip block-scoped variables and parameters + if ((ts.getCombinedNodeFlags(node) & 3 /* BlockScoped */) !== 0 || ts.isParameterDeclaration(node)) { return; } - if (node.kind === 232 && !node.initializer) { + // skip variable declarations that don't have initializers + // NOTE: in ES6 spec initializer is required in variable declarations where name is binding pattern + // so we'll always treat binding elements as initialized + if (node.kind === 232 /* VariableDeclaration */ && !node.initializer) { return; } var symbol = getSymbolOfNode(node); - if (symbol.flags & 1) { + if (symbol.flags & 1 /* FunctionScopedVariable */) { if (!ts.isIdentifier(node.name)) return ts.Debug.fail(); - var localDeclarationSymbol = resolveName(node, node.name.escapedText, 3, undefined, undefined, false); + var localDeclarationSymbol = resolveName(node, node.name.escapedText, 3 /* Variable */, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); if (localDeclarationSymbol && localDeclarationSymbol !== symbol && - localDeclarationSymbol.flags & 2) { - if (getDeclarationNodeFlagsFromSymbol(localDeclarationSymbol) & 3) { - var varDeclList = ts.getAncestor(localDeclarationSymbol.valueDeclaration, 233); - var container = varDeclList.parent.kind === 214 && varDeclList.parent.parent + localDeclarationSymbol.flags & 2 /* BlockScopedVariable */) { + if (getDeclarationNodeFlagsFromSymbol(localDeclarationSymbol) & 3 /* BlockScoped */) { + var varDeclList = ts.getAncestor(localDeclarationSymbol.valueDeclaration, 233 /* VariableDeclarationList */); + var container = varDeclList.parent.kind === 214 /* VariableStatement */ && varDeclList.parent.parent ? varDeclList.parent.parent : undefined; + // names of block-scoped and function scoped variables can collide only + // if block scoped variable is defined in the function\module\source file scope (because of variable hoisting) var namesShareScope = container && - (container.kind === 213 && ts.isFunctionLike(container.parent) || - container.kind === 240 || - container.kind === 239 || - container.kind === 274); + (container.kind === 213 /* Block */ && ts.isFunctionLike(container.parent) || + container.kind === 240 /* ModuleBlock */ || + container.kind === 239 /* ModuleDeclaration */ || + container.kind === 274 /* SourceFile */); + // here we know that function scoped variable is shadowed by block scoped one + // if they are defined in the same scope - binder has already reported redeclaration error + // otherwise if variable has an initializer - show error that initialization will fail + // since LHS will be block scoped name instead of function scoped if (!namesShareScope) { var name = symbolToString(localDeclarationSymbol); error(node, ts.Diagnostics.Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1, name, name); @@ -43117,21 +50282,27 @@ var ts; } } } + // Check that a parameter initializer contains no references to parameters declared to the right of itself function checkParameterInitializer(node) { - if (ts.getRootDeclaration(node).kind !== 149) { + if (ts.getRootDeclaration(node).kind !== 149 /* Parameter */) { return; } var func = ts.getContainingFunction(node); visit(node.initializer); function visit(n) { if (ts.isTypeNode(n) || ts.isDeclarationName(n)) { + // do not dive in types + // skip declaration names (i.e. in object literal expressions) return; } - if (n.kind === 185) { + if (n.kind === 185 /* PropertyAccessExpression */) { + // skip property names in property access expression return visit(n.expression); } - else if (n.kind === 71) { - var symbol = resolveName(n, n.escapedText, 67216319 | 2097152, undefined, undefined, false); + else if (n.kind === 71 /* Identifier */) { + // check FunctionLikeDeclaration.locals (stores parameters\function local variable) + // if it contains entry with a specified name + var symbol = resolveName(n, n.escapedText, 67216319 /* Value */ | 2097152 /* Alias */, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); if (!symbol || symbol === unknownSymbol || !symbol.valueDeclaration) { return; } @@ -43139,24 +50310,32 @@ var ts; error(n, ts.Diagnostics.Parameter_0_cannot_be_referenced_in_its_initializer, ts.declarationNameToString(node.name)); return; } + // locals map for function contain both parameters and function locals + // so we need to do a bit of extra work to check if reference is legal var enclosingContainer = ts.getEnclosingBlockScopeContainer(symbol.valueDeclaration); if (enclosingContainer === func) { - if (symbol.valueDeclaration.kind === 149 || - symbol.valueDeclaration.kind === 182) { + if (symbol.valueDeclaration.kind === 149 /* Parameter */ || + symbol.valueDeclaration.kind === 182 /* BindingElement */) { + // it is ok to reference parameter in initializer if either + // - parameter is located strictly on the left of current parameter declaration if (symbol.valueDeclaration.pos < node.pos) { return; } + // - parameter is wrapped in function-like entity if (ts.findAncestor(n, function (current) { if (current === node.initializer) { return "quit"; } return ts.isFunctionLike(current.parent) || - (current.parent.kind === 152 && - !(ts.hasModifier(current.parent, 32)) && + // computed property names/initializers in instance property declaration of class like entities + // are executed in constructor and thus deferred + (current.parent.kind === 152 /* PropertyDeclaration */ && + !(ts.hasModifier(current.parent, 32 /* Static */)) && ts.isClassLike(current.parent.parent)); })) { return; } + // fall through to report error } error(n, ts.Diagnostics.Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it, ts.declarationNameToString(node.name), ts.declarationNameToString(n)); } @@ -43169,56 +50348,68 @@ var ts; function convertAutoToAny(type) { return type === autoType ? anyType : type === autoArrayType ? anyArrayType : type; } + // Check variable, parameter, or property declaration function checkVariableLikeDeclaration(node) { checkDecorators(node); if (!ts.isBindingElement(node)) { checkSourceElement(node.type); } + // JSDoc `function(string, string): string` syntax results in parameters with no name if (!node.name) { return; } - if (node.name.kind === 147) { + // For a computed property, just check the initializer and exit + // Do not use hasDynamicName here, because that returns false for well known symbols. + // We want to perform checkComputedPropertyName for all computed properties, including + // well known symbols. + if (node.name.kind === 147 /* ComputedPropertyName */) { checkComputedPropertyName(node.name); if (node.initializer) { checkExpressionCached(node.initializer); } } - if (node.kind === 182) { - if (node.parent.kind === 180 && languageVersion < 6) { - checkExternalEmitHelpers(node, 4); + if (node.kind === 182 /* BindingElement */) { + if (node.parent.kind === 180 /* ObjectBindingPattern */ && languageVersion < 6 /* ESNext */) { + checkExternalEmitHelpers(node, 4 /* Rest */); } - if (node.propertyName && node.propertyName.kind === 147) { + // check computed properties inside property names of binding elements + if (node.propertyName && node.propertyName.kind === 147 /* ComputedPropertyName */) { checkComputedPropertyName(node.propertyName); } + // check private/protected variable access var parent = node.parent.parent; var parentType = getTypeForBindingElementParent(parent); var name = node.propertyName || node.name; if (!ts.isBindingPattern(name)) { - var property = getPropertyOfType(parentType, ts.getTextOfPropertyName(name)); - markPropertyAsReferenced(property, undefined, false); + var property = getPropertyOfType(parentType, ts.getTextOfPropertyName(name)); // TODO: GH#18217 + markPropertyAsReferenced(property, /*nodeForCheckWriteOnly*/ undefined, /*isThisAccess*/ false); // A destructuring is never a write-only reference. if (parent.initializer && property) { checkPropertyAccessibility(parent, parent.initializer, parentType, property); } } } + // For a binding pattern, check contained binding elements if (ts.isBindingPattern(node.name)) { - if (node.name.kind === 181 && languageVersion < 2 && compilerOptions.downlevelIteration) { - checkExternalEmitHelpers(node, 512); + if (node.name.kind === 181 /* ArrayBindingPattern */ && languageVersion < 2 /* ES2015 */ && compilerOptions.downlevelIteration) { + checkExternalEmitHelpers(node, 512 /* Read */); } ts.forEach(node.name.elements, checkSourceElement); } - if (node.initializer && ts.getRootDeclaration(node).kind === 149 && ts.nodeIsMissing(ts.getContainingFunction(node).body)) { + // For a parameter declaration with an initializer, error and exit if the containing function doesn't have a body + if (node.initializer && ts.getRootDeclaration(node).kind === 149 /* Parameter */ && ts.nodeIsMissing(ts.getContainingFunction(node).body)) { error(node, ts.Diagnostics.A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation); return; } + // For a binding pattern, validate the initializer and exit if (ts.isBindingPattern(node.name)) { - if (node.initializer && node.parent.parent.kind !== 221) { + // Don't validate for-in initializer as it is already an error + if (node.initializer && node.parent.parent.kind !== 221 /* ForInStatement */) { var initializerType = checkExpressionCached(node.initializer); if (strictNullChecks && node.name.elements.length === 0) { checkNonNullType(initializerType, node); } else { - checkTypeAssignableTo(initializerType, getWidenedTypeForVariableLikeDeclaration(node), node, undefined); + checkTypeAssignableTo(initializerType, getWidenedTypeForVariableLikeDeclaration(node), node, /*headMessage*/ undefined); } checkParameterInitializer(node); } @@ -43227,36 +50418,41 @@ var ts; var symbol = getSymbolOfNode(node); var type = convertAutoToAny(getTypeOfSymbol(symbol)); if (node === symbol.valueDeclaration) { + // Node is the primary declaration of the symbol, just validate the initializer + // Don't validate for-in initializer as it is already an error var initializer = ts.getEffectiveInitializer(node); if (initializer) { var isJSObjectLiteralInitializer = ts.isInJavaScriptFile(node) && ts.isObjectLiteralExpression(initializer) && (initializer.properties.length === 0 || ts.isPrototypeAccess(node.name)) && ts.hasEntries(symbol.exports); - if (!isJSObjectLiteralInitializer && node.parent.parent.kind !== 221) { - checkTypeAssignableTo(checkExpressionCached(initializer), type, node, undefined); + if (!isJSObjectLiteralInitializer && node.parent.parent.kind !== 221 /* ForInStatement */) { + checkTypeAssignableTo(checkExpressionCached(initializer), type, node, /*headMessage*/ undefined); checkParameterInitializer(node); } } } else { + // Node is a secondary declaration, check that type is identical to primary declaration and check that + // initializer is consistent with type associated with the node var declarationType = convertAutoToAny(getWidenedTypeForVariableLikeDeclaration(node)); if (type !== errorType && declarationType !== errorType && !isTypeIdenticalTo(type, declarationType) && - !(symbol.flags & 67108864)) { + !(symbol.flags & 67108864 /* JSContainer */)) { errorNextVariableOrPropertyDeclarationMustHaveSameType(type, node, declarationType); } if (node.initializer) { - checkTypeAssignableTo(checkExpressionCached(node.initializer), declarationType, node, undefined); + checkTypeAssignableTo(checkExpressionCached(node.initializer), declarationType, node, /*headMessage*/ undefined); } if (!areDeclarationFlagsIdentical(node, symbol.valueDeclaration)) { error(ts.getNameOfDeclaration(symbol.valueDeclaration), ts.Diagnostics.All_declarations_of_0_must_have_identical_modifiers, ts.declarationNameToString(node.name)); error(node.name, ts.Diagnostics.All_declarations_of_0_must_have_identical_modifiers, ts.declarationNameToString(node.name)); } } - if (node.kind !== 152 && node.kind !== 151) { + if (node.kind !== 152 /* PropertyDeclaration */ && node.kind !== 151 /* PropertySignature */) { + // We know we don't have a binding pattern or computed name here checkExportsOnMergedDeclarations(node); - if (node.kind === 232 || node.kind === 182) { + if (node.kind === 232 /* VariableDeclaration */ || node.kind === 182 /* BindingElement */) { checkVarDeclaredNamesNotShadowed(node); } checkCollisionWithRequireExportsInGeneratedCode(node, node.name); @@ -43265,25 +50461,26 @@ var ts; } function errorNextVariableOrPropertyDeclarationMustHaveSameType(firstType, nextDeclaration, nextType) { var nextDeclarationName = ts.getNameOfDeclaration(nextDeclaration); - var message = nextDeclaration.kind === 152 || nextDeclaration.kind === 151 + var message = nextDeclaration.kind === 152 /* PropertyDeclaration */ || nextDeclaration.kind === 151 /* PropertySignature */ ? ts.Diagnostics.Subsequent_property_declarations_must_have_the_same_type_Property_0_must_be_of_type_1_but_here_has_type_2 : ts.Diagnostics.Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2; error(nextDeclarationName, message, ts.declarationNameToString(nextDeclarationName), typeToString(firstType), typeToString(nextType)); } function areDeclarationFlagsIdentical(left, right) { - if ((left.kind === 149 && right.kind === 232) || - (left.kind === 232 && right.kind === 149)) { + if ((left.kind === 149 /* Parameter */ && right.kind === 232 /* VariableDeclaration */) || + (left.kind === 232 /* VariableDeclaration */ && right.kind === 149 /* Parameter */)) { + // Differences in optionality between parameters and variables are allowed. return true; } if (ts.hasQuestionToken(left) !== ts.hasQuestionToken(right)) { return false; } - var interestingFlags = 8 | - 16 | - 256 | - 128 | - 64 | - 32; + var interestingFlags = 8 /* Private */ | + 16 /* Protected */ | + 256 /* Async */ | + 128 /* Abstract */ | + 64 /* Readonly */ | + 32 /* Static */; return ts.getSelectedModifierFlags(left, interestingFlags) === ts.getSelectedModifierFlags(right, interestingFlags); } function checkVariableDeclaration(node) { @@ -43295,41 +50492,47 @@ var ts; return checkVariableLikeDeclaration(node); } function checkVariableStatement(node) { + // Grammar checking if (!checkGrammarDecoratorsAndModifiers(node) && !checkGrammarVariableDeclarationList(node.declarationList)) checkGrammarForDisallowedLetOrConstStatement(node); ts.forEach(node.declarationList.declarations, checkSourceElement); } function checkExpressionStatement(node) { + // Grammar checking checkGrammarStatementInAmbientContext(node); checkExpression(node.expression); } function checkIfStatement(node) { + // Grammar checking checkGrammarStatementInAmbientContext(node); checkExpression(node.expression); checkSourceElement(node.thenStatement); - if (node.thenStatement.kind === 215) { + if (node.thenStatement.kind === 215 /* EmptyStatement */) { error(node.thenStatement, ts.Diagnostics.The_body_of_an_if_statement_cannot_be_the_empty_statement); } checkSourceElement(node.elseStatement); } function checkDoStatement(node) { + // Grammar checking checkGrammarStatementInAmbientContext(node); checkSourceElement(node.statement); checkExpression(node.expression); } function checkWhileStatement(node) { + // Grammar checking checkGrammarStatementInAmbientContext(node); checkExpression(node.expression); checkSourceElement(node.statement); } function checkForStatement(node) { + // Grammar checking if (!checkGrammarStatementInAmbientContext(node)) { - if (node.initializer && node.initializer.kind === 233) { + if (node.initializer && node.initializer.kind === 233 /* VariableDeclarationList */) { checkGrammarVariableDeclarationList(node.initializer); } } if (node.initializer) { - if (node.initializer.kind === 233) { + if (node.initializer.kind === 233 /* VariableDeclarationList */) { ts.forEach(node.initializer.declarations, checkVariableDeclaration); } else { @@ -43349,27 +50552,42 @@ var ts; checkGrammarForInOrForOfStatement(node); if (node.awaitModifier) { var functionFlags = ts.getFunctionFlags(ts.getContainingFunction(node)); - if ((functionFlags & (4 | 2)) === 2 && languageVersion < 6) { - checkExternalEmitHelpers(node, 16384); + if ((functionFlags & (4 /* Invalid */ | 2 /* Async */)) === 2 /* Async */ && languageVersion < 6 /* ESNext */) { + // for..await..of in an async function or async generator function prior to ESNext requires the __asyncValues helper + checkExternalEmitHelpers(node, 16384 /* ForAwaitOfIncludes */); } } - else if (compilerOptions.downlevelIteration && languageVersion < 2) { - checkExternalEmitHelpers(node, 256); + else if (compilerOptions.downlevelIteration && languageVersion < 2 /* ES2015 */) { + // for..of prior to ES2015 requires the __values helper when downlevelIteration is enabled + checkExternalEmitHelpers(node, 256 /* ForOfIncludes */); } - if (node.initializer.kind === 233) { + // Check the LHS and RHS + // If the LHS is a declaration, just check it as a variable declaration, which will in turn check the RHS + // via checkRightHandSideOfForOf. + // If the LHS is an expression, check the LHS, as a destructuring assignment or as a reference. + // Then check that the RHS is assignable to it. + if (node.initializer.kind === 233 /* VariableDeclarationList */) { checkForInOrForOfVariableDeclaration(node); } else { var varExpr = node.initializer; var iteratedType = checkRightHandSideOfForOf(node.expression, node.awaitModifier); - if (varExpr.kind === 183 || varExpr.kind === 184) { + // There may be a destructuring assignment on the left side + if (varExpr.kind === 183 /* ArrayLiteralExpression */ || varExpr.kind === 184 /* ObjectLiteralExpression */) { + // iteratedType may be undefined. In this case, we still want to check the structure of + // varExpr, in particular making sure it's a valid LeftHandSideExpression. But we'd like + // to short circuit the type relation checking as much as possible, so we pass the unknownType. checkDestructuringAssignment(varExpr, iteratedType || errorType); } else { var leftType = checkExpression(varExpr); checkReferenceExpression(varExpr, ts.Diagnostics.The_left_hand_side_of_a_for_of_statement_must_be_a_variable_or_a_property_access); + // iteratedType will be undefined if the rightType was missing properties/signatures + // required to get its iteratedType (like [Symbol.iterator] or next). This may be + // because we accessed properties from anyType, or it may have led to an error inside + // getElementTypeOfIterable. if (iteratedType) { - checkTypeAssignableTo(iteratedType, leftType, varExpr, undefined); + checkTypeAssignableTo(iteratedType, leftType, varExpr, /*headMessage*/ undefined); } } } @@ -43379,9 +50597,15 @@ var ts; } } function checkForInStatement(node) { + // Grammar checking checkGrammarForInOrForOfStatement(node); var rightType = checkNonNullExpression(node.expression); - if (node.initializer.kind === 233) { + // TypeScript 1.0 spec (April 2014): 5.4 + // In a 'for-in' statement of the form + // for (let VarDecl in Expr) Statement + // VarDecl must be a variable declaration without a type annotation that declares a variable of type Any, + // and Expr must be an expression of type Any, an object type, or a type parameter type. + if (node.initializer.kind === 233 /* VariableDeclarationList */) { var variable = node.initializer.declarations[0]; if (variable && ts.isBindingPattern(variable.name)) { error(variable.name, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern); @@ -43389,19 +50613,26 @@ var ts; checkForInOrForOfVariableDeclaration(node); } else { + // In a 'for-in' statement of the form + // for (Var in Expr) Statement + // Var must be an expression classified as a reference of type Any or the String primitive type, + // and Expr must be an expression of type Any, an object type, or a type parameter type. var varExpr = node.initializer; var leftType = checkExpression(varExpr); - if (varExpr.kind === 183 || varExpr.kind === 184) { + if (varExpr.kind === 183 /* ArrayLiteralExpression */ || varExpr.kind === 184 /* ObjectLiteralExpression */) { error(varExpr, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern); } else if (!isTypeAssignableTo(getIndexTypeOrString(rightType), leftType)) { error(varExpr, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any); } else { + // run check only former check succeeded to avoid cascading errors checkReferenceExpression(varExpr, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_must_be_a_variable_or_a_property_access); } } - if (rightType === neverType || !isTypeAssignableToKind(rightType, 16777216 | 14745600)) { + // unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved + // in this case error about missing name is already reported - do not report extra one + if (rightType === neverType || !isTypeAssignableToKind(rightType, 16777216 /* NonPrimitive */ | 14745600 /* InstantiableNonPrimitive */)) { error(node.expression, ts.Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter_but_here_has_type_0, typeToString(rightType)); } checkSourceElement(node.statement); @@ -43411,6 +50642,7 @@ var ts; } function checkForInOrForOfVariableDeclaration(iterationStatement) { var variableDeclarationList = iterationStatement.initializer; + // checkGrammarForInOrForOfStatement will check that there is exactly one declaration. if (variableDeclarationList.declarations.length >= 1) { var decl = variableDeclarationList.declarations[0]; checkVariableDeclaration(decl); @@ -43418,23 +50650,32 @@ var ts; } function checkRightHandSideOfForOf(rhsExpression, awaitModifier) { var expressionType = checkNonNullExpression(rhsExpression); - return checkIteratedTypeOrElementType(expressionType, rhsExpression, true, awaitModifier !== undefined); + return checkIteratedTypeOrElementType(expressionType, rhsExpression, /*allowStringInput*/ true, awaitModifier !== undefined); } function checkIteratedTypeOrElementType(inputType, errorNode, allowStringInput, allowAsyncIterables) { if (isTypeAny(inputType)) { return inputType; } - return getIteratedTypeOrElementType(inputType, errorNode, allowStringInput, allowAsyncIterables, true) || anyType; + return getIteratedTypeOrElementType(inputType, errorNode, allowStringInput, allowAsyncIterables, /*checkAssignability*/ true) || anyType; } + /** + * When consuming an iterable type in a for..of, spread, or iterator destructuring assignment + * we want to get the iterated type of an iterable for ES2015 or later, or the iterated type + * of a iterable (if defined globally) or element type of an array like for ES2015 or earlier. + */ function getIteratedTypeOrElementType(inputType, errorNode, allowStringInput, allowAsyncIterables, checkAssignability) { if (inputType === neverType) { - reportTypeNotIterableError(errorNode, inputType, allowAsyncIterables); + reportTypeNotIterableError(errorNode, inputType, allowAsyncIterables); // TODO: GH#18217 return undefined; } - var uplevelIteration = languageVersion >= 2; + var uplevelIteration = languageVersion >= 2 /* ES2015 */; var downlevelIteration = !uplevelIteration && compilerOptions.downlevelIteration; + // Get the iterated type of an `Iterable` or `IterableIterator` only in ES2015 + // or higher, when inside of an async generator or for-await-if, or when + // downlevelIteration is requested. if (uplevelIteration || downlevelIteration || allowAsyncIterables) { - var iteratedType = getIteratedTypeOfIterable(inputType, uplevelIteration ? errorNode : undefined, allowAsyncIterables, true, checkAssignability); + // We only report errors for an invalid iterable type in ES2015 or higher. + var iteratedType = getIteratedTypeOfIterable(inputType, uplevelIteration ? errorNode : undefined, allowAsyncIterables, /*allowSyncIterables*/ true, checkAssignability); if (iteratedType || uplevelIteration) { return iteratedType; } @@ -43442,33 +50683,45 @@ var ts; var arrayType = inputType; var reportedError = false; var hasStringConstituent = false; + // If strings are permitted, remove any string-like constituents from the array type. + // This allows us to find other non-string element types from an array unioned with + // a string. if (allowStringInput) { - if (arrayType.flags & 262144) { + if (arrayType.flags & 262144 /* Union */) { + // After we remove all types that are StringLike, we will know if there was a string constituent + // based on whether the result of filter is a new array. var arrayTypes = inputType.types; - var filteredTypes = ts.filter(arrayTypes, function (t) { return !(t.flags & 68); }); + var filteredTypes = ts.filter(arrayTypes, function (t) { return !(t.flags & 68 /* StringLike */); }); if (filteredTypes !== arrayTypes) { - arrayType = getUnionType(filteredTypes, 2); + arrayType = getUnionType(filteredTypes, 2 /* Subtype */); } } - else if (arrayType.flags & 68) { + else if (arrayType.flags & 68 /* StringLike */) { arrayType = neverType; } hasStringConstituent = arrayType !== inputType; if (hasStringConstituent) { - if (languageVersion < 1) { + if (languageVersion < 1 /* ES5 */) { if (errorNode) { error(errorNode, ts.Diagnostics.Using_a_string_in_a_for_of_statement_is_only_supported_in_ECMAScript_5_and_higher); reportedError = true; } } - if (arrayType.flags & 32768) { + // Now that we've removed all the StringLike types, if no constituents remain, then the entire + // arrayOrStringType was a string. + if (arrayType.flags & 32768 /* Never */) { return stringType; } } } if (!isArrayLikeType(arrayType)) { if (errorNode && !reportedError) { - var isIterable = !!getIteratedTypeOfIterable(inputType, undefined, allowAsyncIterables, true, checkAssignability); + // Which error we report depends on whether we allow strings or if there was a + // string constituent. For example, if the input type is number | string, we + // want to say that number is not an array type. But if the input was just + // number and string input is allowed, we want to say that number is not an + // array type or a string type. + var isIterable = !!getIteratedTypeOfIterable(inputType, /* errorNode */ undefined, allowAsyncIterables, /*allowSyncIterables*/ true, checkAssignability); var diagnostic = !allowStringInput || hasStringConstituent ? downlevelIteration ? ts.Diagnostics.Type_0_is_not_an_array_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator @@ -43484,15 +50737,54 @@ var ts; } return hasStringConstituent ? stringType : undefined; } - var arrayElementType = getIndexTypeOfType(arrayType, 1); + var arrayElementType = getIndexTypeOfType(arrayType, 1 /* Number */); if (hasStringConstituent && arrayElementType) { - if (arrayElementType.flags & 68) { + // This is just an optimization for the case where arrayOrStringType is string | string[] + if (arrayElementType.flags & 68 /* StringLike */) { return stringType; } - return getUnionType([arrayElementType, stringType], 2); + return getUnionType([arrayElementType, stringType], 2 /* Subtype */); } return arrayElementType; } + /** + * We want to treat type as an iterable, and get the type it is an iterable of. The iterable + * must have the following structure (annotated with the names of the variables below): + * + * { // iterable + * [Symbol.iterator]: { // iteratorMethod + * (): Iterator + * } + * } + * + * For an async iterable, we expect the following structure: + * + * { // iterable + * [Symbol.asyncIterator]: { // iteratorMethod + * (): AsyncIterator + * } + * } + * + * T is the type we are after. At every level that involves analyzing return types + * of signatures, we union the return types of all the signatures. + * + * Another thing to note is that at any step of this process, we could run into a dead end, + * meaning either the property is missing, or we run into the anyType. If either of these things + * happens, we return undefined to signal that we could not find the iterated type. If a property + * is missing, and the previous step did not result in 'any', then we also give an error if the + * caller requested it. Then the caller can decide what to do in the case where there is no iterated + * type. This is different from returning anyType, because that would signify that we have matched the + * whole pattern and that T (above) is 'any'. + * + * For a **for-of** statement, `yield*` (in a normal generator), spread, array + * destructuring, or normal generator we will only ever look for a `[Symbol.iterator]()` + * method. + * + * For an async generator we will only ever look at the `[Symbol.asyncIterator]()` method. + * + * For a **for-await-of** statement or a `yield*` in an async generator we will look for + * the `[Symbol.asyncIterator]()` method first, and then the `[Symbol.iterator]()` method. + */ function getIteratedTypeOfIterable(type, errorNode, allowAsyncIterables, allowSyncIterables, checkAssignability) { if (isTypeAny(type)) { return undefined; @@ -43504,8 +50796,10 @@ var ts; if (typeAsIterable.iteratedTypeOfAsyncIterable) { return typeAsIterable.iteratedTypeOfAsyncIterable; } - if (isReferenceToType(type, getGlobalAsyncIterableType(false)) || - isReferenceToType(type, getGlobalAsyncIterableIteratorType(false))) { + // As an optimization, if the type is an instantiation of the global `AsyncIterable` + // or the global `AsyncIterableIterator` then just grab its type argument. + if (isReferenceToType(type, getGlobalAsyncIterableType(/*reportErrors*/ false)) || + isReferenceToType(type, getGlobalAsyncIterableIteratorType(/*reportErrors*/ false))) { return typeAsIterable.iteratedTypeOfAsyncIterable = type.typeArguments[0]; } } @@ -43513,8 +50807,10 @@ var ts; if (typeAsIterable.iteratedTypeOfIterable) { return typeAsIterable.iteratedTypeOfIterable; } - if (isReferenceToType(type, getGlobalIterableType(false)) || - isReferenceToType(type, getGlobalIterableIteratorType(false))) { + // As an optimization, if the type is an instantiation of the global `Iterable` or + // `IterableIterator` then just grab its type argument. + if (isReferenceToType(type, getGlobalIterableType(/*reportErrors*/ false)) || + isReferenceToType(type, getGlobalIterableIteratorType(/*reportErrors*/ false))) { return typeAsIterable.iteratedTypeOfIterable = type.typeArguments[0]; } } @@ -43523,17 +50819,21 @@ var ts; if (isTypeAny(methodType)) { return undefined; } - var signatures = methodType ? getSignaturesOfType(methodType, 0) : undefined; + var signatures = methodType ? getSignaturesOfType(methodType, 0 /* Call */) : undefined; if (!ts.some(signatures)) { if (errorNode) { + // only report on the first error reportTypeNotIterableError(errorNode, type, allowAsyncIterables); errorNode = undefined; } return undefined; } - var returnType = getUnionType(ts.map(signatures, getReturnTypeOfSignature), 2); - var iteratedType = getIteratedTypeOfIterator(returnType, errorNode, !!asyncMethodType); + var returnType = getUnionType(ts.map(signatures, getReturnTypeOfSignature), 2 /* Subtype */); + var iteratedType = getIteratedTypeOfIterator(returnType, errorNode, /*isAsyncIterator*/ !!asyncMethodType); if (checkAssignability && errorNode && iteratedType) { + // If `checkAssignability` was specified, we were called from + // `checkIteratedTypeOrElementType`. As such, we need to validate that + // the type passed in is actually an Iterable. checkTypeAssignableTo(type, asyncMethodType ? createAsyncIterableType(iteratedType) : createIterableType(iteratedType), errorNode); @@ -43548,6 +50848,28 @@ var ts; ? ts.Diagnostics.Type_0_must_have_a_Symbol_asyncIterator_method_that_returns_an_async_iterator : ts.Diagnostics.Type_0_must_have_a_Symbol_iterator_method_that_returns_an_iterator, typeToString(type)); } + /** + * This function has very similar logic as getIteratedTypeOfIterable, except that it operates on + * Iterators instead of Iterables. Here is the structure: + * + * { // iterator + * next: { // nextMethod + * (): { // nextResult + * value: T // nextValue + * } + * } + * } + * + * For an async iterator, we expect the following structure: + * + * { // iterator + * next: { // nextMethod + * (): PromiseLike<{ // nextResult + * value: T // nextValue + * }> + * } + * } + */ function getIteratedTypeOfIterator(type, errorNode, isAsyncIterator) { if (isTypeAny(type)) { return undefined; @@ -43556,17 +50878,21 @@ var ts; if (isAsyncIterator ? typeAsIterator.iteratedTypeOfAsyncIterator : typeAsIterator.iteratedTypeOfIterator) { return isAsyncIterator ? typeAsIterator.iteratedTypeOfAsyncIterator : typeAsIterator.iteratedTypeOfIterator; } + // As an optimization, if the type is an instantiation of the global `Iterator` (for + // a non-async iterator) or the global `AsyncIterator` (for an async-iterator) then + // just grab its type argument. var getIteratorType = isAsyncIterator ? getGlobalAsyncIteratorType : getGlobalIteratorType; - if (isReferenceToType(type, getIteratorType(false))) { + if (isReferenceToType(type, getIteratorType(/*reportErrors*/ false))) { return isAsyncIterator ? typeAsIterator.iteratedTypeOfAsyncIterator = type.typeArguments[0] : typeAsIterator.iteratedTypeOfIterator = type.typeArguments[0]; } + // Both async and non-async iterators must have a `next` method. var nextMethod = getTypeOfPropertyOfType(type, "next"); if (isTypeAny(nextMethod)) { return undefined; } - var nextMethodSignatures = nextMethod ? getSignaturesOfType(nextMethod, 0) : ts.emptyArray; + var nextMethodSignatures = nextMethod ? getSignaturesOfType(nextMethod, 0 /* Call */) : ts.emptyArray; if (nextMethodSignatures.length === 0) { if (errorNode) { error(errorNode, isAsyncIterator @@ -43575,10 +50901,11 @@ var ts; } return undefined; } - var nextResult = getUnionType(ts.map(nextMethodSignatures, getReturnTypeOfSignature), 2); + var nextResult = getUnionType(ts.map(nextMethodSignatures, getReturnTypeOfSignature), 2 /* Subtype */); if (isTypeAny(nextResult)) { return undefined; } + // For an async iterator, we must get the awaited type of the return type. if (isAsyncIterator) { nextResult = getAwaitedTypeOfPromise(nextResult, errorNode, ts.Diagnostics.The_type_returned_by_the_next_method_of_an_async_iterator_must_be_a_promise_for_a_type_with_a_value_property); if (isTypeAny(nextResult)) { @@ -43598,28 +50925,37 @@ var ts; ? typeAsIterator.iteratedTypeOfAsyncIterator = nextValue : typeAsIterator.iteratedTypeOfIterator = nextValue; } + /** + * A generator may have a return type of `Iterator`, `Iterable`, or + * `IterableIterator`. An async generator may have a return type of `AsyncIterator`, + * `AsyncIterable`, or `AsyncIterableIterator`. This function can be used to extract + * the iterated type from this return type for contextual typing and verifying signatures. + */ function getIteratedTypeOfGenerator(returnType, isAsyncGenerator) { if (isTypeAny(returnType)) { return undefined; } - return getIteratedTypeOfIterable(returnType, undefined, isAsyncGenerator, !isAsyncGenerator, false) - || getIteratedTypeOfIterator(returnType, undefined, isAsyncGenerator); + return getIteratedTypeOfIterable(returnType, /*errorNode*/ undefined, /*allowAsyncIterables*/ isAsyncGenerator, /*allowSyncIterables*/ !isAsyncGenerator, /*checkAssignability*/ false) + || getIteratedTypeOfIterator(returnType, /*errorNode*/ undefined, isAsyncGenerator); } function checkBreakOrContinueStatement(node) { + // Grammar checking if (!checkGrammarStatementInAmbientContext(node)) checkGrammarBreakOrContinueStatement(node); + // TODO: Check that target label is valid } function isGetAccessorWithAnnotatedSetAccessor(node) { - return node.kind === 156 - && ts.getEffectiveSetAccessorTypeAnnotationNode(ts.getDeclarationOfKind(node.symbol, 157)) !== undefined; + return node.kind === 156 /* GetAccessor */ + && ts.getEffectiveSetAccessorTypeAnnotationNode(ts.getDeclarationOfKind(node.symbol, 157 /* SetAccessor */)) !== undefined; } function isUnwrappedReturnTypeVoidOrAny(func, returnType) { - var unwrappedReturnType = (ts.getFunctionFlags(func) & 3) === 2 - ? getPromisedTypeOfPromise(returnType) - : returnType; - return !!unwrappedReturnType && maybeTypeOfKind(unwrappedReturnType, 4096 | 3); + var unwrappedReturnType = (ts.getFunctionFlags(func) & 3 /* AsyncGenerator */) === 2 /* Async */ + ? getPromisedTypeOfPromise(returnType) // Async function + : returnType; // AsyncGenerator function, Generator function, or normal function + return !!unwrappedReturnType && maybeTypeOfKind(unwrappedReturnType, 4096 /* Void */ | 3 /* AnyOrUnknown */); } function checkReturnStatement(node) { + // Grammar checking if (checkGrammarStatementInAmbientContext(node)) { return; } @@ -43631,27 +50967,34 @@ var ts; var signature = getSignatureFromDeclaration(func); var returnType = getReturnTypeOfSignature(signature); var functionFlags = ts.getFunctionFlags(func); - var isGenerator = functionFlags & 1; - if (strictNullChecks || node.expression || returnType.flags & 32768) { + var isGenerator = functionFlags & 1 /* Generator */; + if (strictNullChecks || node.expression || returnType.flags & 32768 /* Never */) { var exprType = node.expression ? checkExpressionCached(node.expression) : undefinedType; - if (isGenerator) { + if (isGenerator) { // AsyncGenerator function or Generator function + // A generator does not need its return expressions checked against its return type. + // Instead, the yield expressions are checked against the element type. + // TODO: Check return types of generators when return type tracking is added + // for generators. return; } - else if (func.kind === 157) { + else if (func.kind === 157 /* SetAccessor */) { if (node.expression) { error(node, ts.Diagnostics.Setters_cannot_return_a_value); } } - else if (func.kind === 155) { + else if (func.kind === 155 /* Constructor */) { if (node.expression && !checkTypeAssignableTo(exprType, returnType, node)) { error(node, ts.Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class); } } else if (ts.getEffectiveReturnTypeNode(func) || isGetAccessorWithAnnotatedSetAccessor(func)) { - if (functionFlags & 2) { + if (functionFlags & 2 /* Async */) { // Async function var promisedType = getPromisedTypeOfPromise(returnType); var awaitedType = checkAwaitedType(exprType, node, ts.Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); if (promisedType) { + // If the function has a return type, but promisedType is + // undefined, an error will be reported in checkAsyncFunctionReturnType + // so we don't need to report one here. checkTypeAssignableTo(awaitedType, promisedType, node); } } @@ -43660,13 +51003,15 @@ var ts; } } } - else if (func.kind !== 155 && compilerOptions.noImplicitReturns && !isUnwrappedReturnTypeVoidOrAny(func, returnType) && !isGenerator) { + else if (func.kind !== 155 /* Constructor */ && compilerOptions.noImplicitReturns && !isUnwrappedReturnTypeVoidOrAny(func, returnType) && !isGenerator) { + // The function has a return type, but the return statement doesn't have an expression. error(node, ts.Diagnostics.Not_all_code_paths_return_a_value); } } function checkWithStatement(node) { + // Grammar checking for withStatement if (!checkGrammarStatementInAmbientContext(node)) { - if (node.flags & 16384) { + if (node.flags & 16384 /* AwaitContext */) { grammarErrorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_an_async_function_block); } } @@ -43679,13 +51024,15 @@ var ts; } } function checkSwitchStatement(node) { + // Grammar checking checkGrammarStatementInAmbientContext(node); var firstDefaultClause; var hasDuplicateDefaultClause = false; var expressionType = checkExpression(node.expression); var expressionIsLiteral = isLiteralType(expressionType); ts.forEach(node.caseBlock.clauses, function (clause) { - if (clause.kind === 267 && !hasDuplicateDefaultClause) { + // Grammar check for duplicate default clauses, skip if we already report duplicate default clause + if (clause.kind === 267 /* DefaultClause */ && !hasDuplicateDefaultClause) { if (firstDefaultClause === undefined) { firstDefaultClause = clause; } @@ -43697,7 +51044,10 @@ var ts; hasDuplicateDefaultClause = true; } } - if (produceDiagnostics && clause.kind === 266) { + if (produceDiagnostics && clause.kind === 266 /* CaseClause */) { + // TypeScript 1.0 spec (April 2014): 5.9 + // In a 'switch' statement, each 'case' expression must be of a type that is comparable + // to or from the type of the 'switch' expression. var caseType = checkExpression(clause.expression); var caseIsLiteral = isLiteralType(caseType); var comparedExpressionType = expressionType; @@ -43706,7 +51056,8 @@ var ts; comparedExpressionType = getBaseTypeOfLiteralType(expressionType); } if (!isTypeEqualityComparableTo(comparedExpressionType, caseType)) { - checkTypeComparableTo(caseType, comparedExpressionType, clause.expression, undefined); + // expressionType is not comparable to caseType, try the reversed check and report errors if it fails + checkTypeComparableTo(caseType, comparedExpressionType, clause.expression, /*headMessage*/ undefined); } } ts.forEach(clause.statements, checkSourceElement); @@ -43716,21 +51067,24 @@ var ts; } } function checkLabeledStatement(node) { + // Grammar checking if (!checkGrammarStatementInAmbientContext(node)) { ts.findAncestor(node.parent, function (current) { if (ts.isFunctionLike(current)) { return "quit"; } - if (current.kind === 228 && current.label.escapedText === node.label.escapedText) { + if (current.kind === 228 /* LabeledStatement */ && current.label.escapedText === node.label.escapedText) { grammarErrorOnNode(node.label, ts.Diagnostics.Duplicate_label_0, ts.getTextOfNode(node.label)); return true; } return false; }); } + // ensure that label is unique checkSourceElement(node.statement); } function checkThrowStatement(node) { + // Grammar checking if (!checkGrammarStatementInAmbientContext(node)) { if (node.expression === undefined) { grammarErrorAfterFirstToken(node, ts.Diagnostics.Line_break_not_permitted_here); @@ -43741,10 +51095,12 @@ var ts; } } function checkTryStatement(node) { + // Grammar checking checkGrammarStatementInAmbientContext(node); checkBlock(node.tryBlock); var catchClause = node.catchClause; if (catchClause) { + // Grammar checking if (catchClause.variableDeclaration) { if (catchClause.variableDeclaration.type) { grammarErrorOnFirstToken(catchClause.variableDeclaration.type, ts.Diagnostics.Catch_clause_variable_cannot_have_a_type_annotation); @@ -43757,7 +51113,7 @@ var ts; if (blockLocals_1) { ts.forEachKey(catchClause.locals, function (caughtName) { var blockLocal = blockLocals_1.get(caughtName); - if (blockLocal && (blockLocal.flags & 2) !== 0) { + if (blockLocal && (blockLocal.flags & 2 /* BlockScopedVariable */) !== 0) { grammarErrorOnNode(blockLocal.valueDeclaration, ts.Diagnostics.Cannot_redeclare_identifier_0_in_catch_clause, caughtName); } }); @@ -43771,25 +51127,28 @@ var ts; } } function checkIndexConstraints(type) { - var declaredNumberIndexer = getIndexDeclarationOfSymbol(type.symbol, 1); - var declaredStringIndexer = getIndexDeclarationOfSymbol(type.symbol, 0); - var stringIndexType = getIndexTypeOfType(type, 0); - var numberIndexType = getIndexTypeOfType(type, 1); + var declaredNumberIndexer = getIndexDeclarationOfSymbol(type.symbol, 1 /* Number */); + var declaredStringIndexer = getIndexDeclarationOfSymbol(type.symbol, 0 /* String */); + var stringIndexType = getIndexTypeOfType(type, 0 /* String */); + var numberIndexType = getIndexTypeOfType(type, 1 /* Number */); if (stringIndexType || numberIndexType) { ts.forEach(getPropertiesOfObjectType(type), function (prop) { var propType = getTypeOfSymbol(prop); - checkIndexConstraintForProperty(prop, propType, type, declaredStringIndexer, stringIndexType, 0); - checkIndexConstraintForProperty(prop, propType, type, declaredNumberIndexer, numberIndexType, 1); + checkIndexConstraintForProperty(prop, propType, type, declaredStringIndexer, stringIndexType, 0 /* String */); + checkIndexConstraintForProperty(prop, propType, type, declaredNumberIndexer, numberIndexType, 1 /* Number */); }); var classDeclaration = type.symbol.valueDeclaration; - if (ts.getObjectFlags(type) & 1 && ts.isClassLike(classDeclaration)) { + if (ts.getObjectFlags(type) & 1 /* Class */ && ts.isClassLike(classDeclaration)) { for (var _i = 0, _a = classDeclaration.members; _i < _a.length; _i++) { var member = _a[_i]; - if (!ts.hasModifier(member, 32) && hasNonBindableDynamicName(member)) { + // Only process instance properties with computed names here. + // Static properties cannot be in conflict with indexers, + // and properties with literal names were already checked. + if (!ts.hasModifier(member, 32 /* Static */) && hasNonBindableDynamicName(member)) { var symbol = getSymbolOfNode(member); var propType = getTypeOfSymbol(symbol); - checkIndexConstraintForProperty(symbol, propType, type, declaredStringIndexer, stringIndexType, 0); - checkIndexConstraintForProperty(symbol, propType, type, declaredNumberIndexer, numberIndexType, 1); + checkIndexConstraintForProperty(symbol, propType, type, declaredStringIndexer, stringIndexType, 0 /* String */); + checkIndexConstraintForProperty(symbol, propType, type, declaredNumberIndexer, numberIndexType, 1 /* Number */); } } } @@ -43797,38 +51156,46 @@ var ts; var errorNode; if (stringIndexType && numberIndexType) { errorNode = declaredNumberIndexer || declaredStringIndexer; - if (!errorNode && (ts.getObjectFlags(type) & 2)) { - var someBaseTypeHasBothIndexers = ts.forEach(getBaseTypes(type), function (base) { return getIndexTypeOfType(base, 0) && getIndexTypeOfType(base, 1); }); + // condition 'errorNode === undefined' may appear if types does not declare nor string neither number indexer + if (!errorNode && (ts.getObjectFlags(type) & 2 /* Interface */)) { + var someBaseTypeHasBothIndexers = ts.forEach(getBaseTypes(type), function (base) { return getIndexTypeOfType(base, 0 /* String */) && getIndexTypeOfType(base, 1 /* Number */); }); errorNode = someBaseTypeHasBothIndexers ? undefined : type.symbol.declarations[0]; } } - if (errorNode && !isTypeAssignableTo(numberIndexType, stringIndexType)) { + if (errorNode && !isTypeAssignableTo(numberIndexType, stringIndexType)) { // TODO: GH#18217 error(errorNode, ts.Diagnostics.Numeric_index_type_0_is_not_assignable_to_string_index_type_1, typeToString(numberIndexType), typeToString(stringIndexType)); } function checkIndexConstraintForProperty(prop, propertyType, containingType, indexDeclaration, indexType, indexKind) { + // ESSymbol properties apply to neither string nor numeric indexers. if (!indexType || ts.isKnownSymbol(prop)) { return; } var propDeclaration = prop.valueDeclaration; - if (indexKind === 1 && !(propDeclaration ? isNumericName(ts.getNameOfDeclaration(propDeclaration)) : isNumericLiteralName(prop.escapedName))) { + // index is numeric and property name is not valid numeric literal + if (indexKind === 1 /* Number */ && !(propDeclaration ? isNumericName(ts.getNameOfDeclaration(propDeclaration)) : isNumericLiteralName(prop.escapedName))) { return; } + // perform property check if property or indexer is declared in 'type' + // this allows us to rule out cases when both property and indexer are inherited from the base class var errorNode; if (propDeclaration && - (propDeclaration.kind === 200 || - ts.getNameOfDeclaration(propDeclaration).kind === 147 || + (propDeclaration.kind === 200 /* BinaryExpression */ || + ts.getNameOfDeclaration(propDeclaration).kind === 147 /* ComputedPropertyName */ || prop.parent === containingType.symbol)) { errorNode = propDeclaration; } else if (indexDeclaration) { errorNode = indexDeclaration; } - else if (ts.getObjectFlags(containingType) & 2) { + else if (ts.getObjectFlags(containingType) & 2 /* Interface */) { + // for interfaces property and indexer might be inherited from different bases + // check if any base class already has both property and indexer. + // check should be performed only if 'type' is the first type that brings property\indexer together var someBaseClassHasBothPropertyAndIndexer = ts.forEach(getBaseTypes(containingType), function (base) { return getPropertyOfObjectType(base, prop.escapedName) && getIndexTypeOfType(base, indexKind); }); errorNode = someBaseClassHasBothPropertyAndIndexer ? undefined : containingType.symbol.declarations[0]; } if (errorNode && !isTypeAssignableTo(propertyType, indexType)) { - var errorMessage = indexKind === 0 + var errorMessage = indexKind === 0 /* String */ ? ts.Diagnostics.Property_0_of_type_1_is_not_assignable_to_string_index_type_2 : ts.Diagnostics.Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2; error(errorNode, errorMessage, symbolToString(prop), typeToString(propertyType), typeToString(indexType)); @@ -43836,6 +51203,8 @@ var ts; } } function checkTypeNameIsReserved(name, message) { + // TS 1.0 spec (April 2014): 3.6.1 + // The predefined type keywords are reserved and cannot be used as names of user defined types. switch (name.escapedText) { case "any": case "unknown": @@ -43848,12 +51217,18 @@ var ts; error(name, message, name.escapedText); } } + /** + * The name cannot be used as 'Object' of user defined types with special target. + */ function checkClassNameCollisionWithObject(name) { - if (languageVersion === 1 && name.escapedText === "Object" + if (languageVersion === 1 /* ES5 */ && name.escapedText === "Object" && moduleKind !== ts.ModuleKind.ES2015 && moduleKind !== ts.ModuleKind.ESNext) { - error(name, ts.Diagnostics.Class_name_cannot_be_Object_when_targeting_ES5_with_module_0, ts.ModuleKind[moduleKind]); + error(name, ts.Diagnostics.Class_name_cannot_be_Object_when_targeting_ES5_with_module_0, ts.ModuleKind[moduleKind]); // https://github.com/Microsoft/TypeScript/issues/17494 } } + /** + * Check each type parameter and check that type parameters have no duplicate type parameter declarations + */ function checkTypeParameters(typeParameterDeclarations) { if (typeParameterDeclarations) { var seenDefault = false; @@ -43876,6 +51251,7 @@ var ts; } } } + /** Check that type parameter lists are identical across multiple declarations */ function checkTypeParameterListsIdentical(symbol) { if (symbol.declarations.length === 1) { return; @@ -43889,6 +51265,7 @@ var ts; } var type = getDeclaredTypeOfSymbol(symbol); if (!areTypeParametersIdentical(declarations, type.localTypeParameters)) { + // Report an error on every conflicting declaration. var name = symbolToString(symbol); for (var _i = 0, declarations_6 = declarations; _i < declarations_6.length; _i++) { var declaration = declarations_6[_i]; @@ -43902,6 +51279,7 @@ var ts; var minTypeArgumentCount = getMinTypeArgumentCount(targetParameters); for (var _i = 0, declarations_7 = declarations; _i < declarations_7.length; _i++) { var declaration = declarations_7[_i]; + // If this declaration has too few or too many type parameters, we report an error var sourceParameters = ts.getEffectiveTypeParameterDeclarations(declaration); var numTypeParameters = sourceParameters.length; if (numTypeParameters < minTypeArgumentCount || numTypeParameters > maxTypeArgumentCount) { @@ -43910,16 +51288,23 @@ var ts; for (var i = 0; i < numTypeParameters; i++) { var source = sourceParameters[i]; var target = targetParameters[i]; + // If the type parameter node does not have the same as the resolved type + // parameter at this position, we report an error. if (source.name.escapedText !== target.symbol.escapedName) { return false; } + // If the type parameter node does not have an identical constraint as the resolved + // type parameter at this position, we report an error. var sourceConstraint = source.constraint && getTypeFromTypeNode(source.constraint); var targetConstraint = getConstraintFromTypeParameter(target); if (sourceConstraint) { + // relax check if later interface augmentation has no constraint if (!targetConstraint || !isTypeIdenticalTo(sourceConstraint, targetConstraint)) { return false; } } + // If the type parameter node has a default and it is not identical to the default + // for the type parameter at this position, we report an error. var sourceDefault = source.default && getTypeFromTypeNode(source.default); var targetDefault = getDefaultFromTypeParameter(target); if (sourceDefault && targetDefault && !isTypeIdenticalTo(sourceDefault, targetDefault)) { @@ -43939,7 +51324,7 @@ var ts; registerForUnusedIdentifiersCheck(node); } function checkClassDeclaration(node) { - if (!node.name && !ts.hasModifier(node, 512)) { + if (!node.name && !ts.hasModifier(node, 512 /* Default */)) { grammarErrorOnFirstToken(node, ts.Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name); } checkClassLikeDeclaration(node); @@ -43953,7 +51338,7 @@ var ts; checkTypeNameIsReserved(node.name, ts.Diagnostics.Class_name_cannot_be_0); checkCollisionWithRequireExportsInGeneratedCode(node, node.name); checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name); - if (!(node.flags & 4194304)) { + if (!(node.flags & 4194304 /* Ambient */)) { checkClassNameCollisionWithObject(node.name); } } @@ -43965,13 +51350,14 @@ var ts; var staticType = getTypeOfSymbol(symbol); checkTypeParameterListsIdentical(symbol); checkClassForDuplicateDeclarations(node); - if (!(node.flags & 4194304)) { + // Only check for reserved static identifiers on non-ambient context. + if (!(node.flags & 4194304 /* Ambient */)) { checkClassForStaticPropertyNameConflicts(node); } var baseTypeNode = ts.getClassExtendsHeritageClauseElement(node); if (baseTypeNode) { - if (languageVersion < 2) { - checkExternalEmitHelpers(baseTypeNode.parent, 1); + if (languageVersion < 2 /* ES2015 */) { + checkExternalEmitHelpers(baseTypeNode.parent, 1 /* Extends */); } var baseTypes = getBaseTypes(type); if (baseTypes.length && produceDiagnostics) { @@ -43990,14 +51376,18 @@ var ts; } } var baseWithThis = getTypeWithThisArgument(baseType_1, type.thisType); - if (!checkTypeAssignableTo(typeWithThis, baseWithThis, undefined)) { + if (!checkTypeAssignableTo(typeWithThis, baseWithThis, /*errorNode*/ undefined)) { issueMemberSpecificError(node, typeWithThis, baseWithThis, ts.Diagnostics.Class_0_incorrectly_extends_base_class_1); } checkTypeAssignableTo(staticType, getTypeWithoutSignatures(staticBaseType), node.name || node, ts.Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1); - if (baseConstructorType.flags & 2162688 && !isMixinConstructorType(staticType)) { + if (baseConstructorType.flags & 2162688 /* TypeVariable */ && !isMixinConstructorType(staticType)) { error(node.name || node, ts.Diagnostics.A_mixin_class_must_have_a_constructor_with_a_single_rest_parameter_of_type_any); } - if (!(staticBaseType.symbol && staticBaseType.symbol.flags & 32) && !(baseConstructorType.flags & 2162688)) { + if (!(staticBaseType.symbol && staticBaseType.symbol.flags & 32 /* Class */) && !(baseConstructorType.flags & 2162688 /* TypeVariable */)) { + // When the static base type is a "class-like" constructor function (but not actually a class), we verify + // that all instantiated base constructor signatures return the same type. We can simply compare the type + // references (as opposed to checking the structure of the types) because elsewhere we have already checked + // that the base type is a class or interface type (and not, for example, an anonymous object type). var constructors = getInstantiatedConstructorsForTypeArguments(staticBaseType, baseTypeNode.typeArguments, baseTypeNode); if (ts.forEach(constructors, function (sig) { return getReturnTypeOfSignature(sig) !== baseType_1; })) { error(baseTypeNode.expression, ts.Diagnostics.Base_constructors_must_all_have_the_same_return_type); @@ -44018,11 +51408,11 @@ var ts; var t = getTypeFromTypeNode(typeRefNode); if (t !== errorType) { if (isValidBaseType(t)) { - var genericDiag = t.symbol && t.symbol.flags & 32 ? + var genericDiag = t.symbol && t.symbol.flags & 32 /* Class */ ? ts.Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass : ts.Diagnostics.Class_0_incorrectly_implements_interface_1; var baseWithThis = getTypeWithThisArgument(t, type.thisType); - if (!checkTypeAssignableTo(typeWithThis, baseWithThis, undefined)) { + if (!checkTypeAssignableTo(typeWithThis, baseWithThis, /*errorNode*/ undefined)) { issueMemberSpecificError(node, typeWithThis, baseWithThis, genericDiag); } } @@ -44040,6 +51430,7 @@ var ts; } } function issueMemberSpecificError(node, typeWithThis, baseWithThis, broadDiag) { + // iterate over all implemented properties and issue errors on each one which isn't compatible, rather than the class as a whole, if possible var issuedMemberError = false; var _loop_9 = function (member) { if (ts.hasStaticModifier(member)) { @@ -44050,8 +51441,9 @@ var ts; var prop = getPropertyOfType(typeWithThis, declaredProp.escapedName); var baseProp = getPropertyOfType(baseWithThis, declaredProp.escapedName); if (prop && baseProp) { - var rootChain = function () { return ts.chainDiagnosticMessages(undefined, ts.Diagnostics.Property_0_in_type_1_is_not_assignable_to_the_same_property_in_base_type_2, symbolToString(declaredProp), typeToString(typeWithThis), typeToString(baseWithThis)); }; - if (!checkTypeAssignableTo(getTypeOfSymbol(prop), getTypeOfSymbol(baseProp), member.name || member, undefined, rootChain)) { + var rootChain = function () { return ts.chainDiagnosticMessages( + /*details*/ undefined, ts.Diagnostics.Property_0_in_type_1_is_not_assignable_to_the_same_property_in_base_type_2, symbolToString(declaredProp), typeToString(typeWithThis), typeToString(baseWithThis)); }; + if (!checkTypeAssignableTo(getTypeOfSymbol(prop), getTypeOfSymbol(baseProp), member.name || member, /*message*/ undefined, rootChain)) { issuedMemberError = true; } } @@ -44062,14 +51454,15 @@ var ts; _loop_9(member); } if (!issuedMemberError) { + // check again with diagnostics to generate a less-specific error checkTypeAssignableTo(typeWithThis, baseWithThis, node.name || node, broadDiag); } } function checkBaseTypeAccessibility(type, node) { - var signatures = getSignaturesOfType(type, 1); + var signatures = getSignaturesOfType(type, 1 /* Construct */); if (signatures.length) { var declaration = signatures[0].declaration; - if (declaration && ts.hasModifier(declaration, 8)) { + if (declaration && ts.hasModifier(declaration, 8 /* Private */)) { var typeClassDeclaration = ts.getClassLikeDeclarationOfSymbol(type.symbol); if (!isNodeWithinClass(node, typeClassDeclaration)) { error(node, ts.Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, getFullyQualifiedName(type.symbol)); @@ -44078,29 +51471,52 @@ var ts; } } function getTargetSymbol(s) { - return ts.getCheckFlags(s) & 1 ? s.target : s; + // if symbol is instantiated its flags are not copied from the 'target' + // so we'll need to get back original 'target' symbol to work with correct set of flags + return ts.getCheckFlags(s) & 1 /* Instantiated */ ? s.target : s; } function getClassOrInterfaceDeclarationsOfSymbol(symbol) { return ts.filter(symbol.declarations, function (d) { - return d.kind === 235 || d.kind === 236; + return d.kind === 235 /* ClassDeclaration */ || d.kind === 236 /* InterfaceDeclaration */; }); } function checkKindsOfPropertyMemberOverrides(type, baseType) { + // TypeScript 1.0 spec (April 2014): 8.2.3 + // A derived class inherits all members from its base class it doesn't override. + // Inheritance means that a derived class implicitly contains all non - overridden members of the base class. + // Both public and private property members are inherited, but only public property members can be overridden. + // A property member in a derived class is said to override a property member in a base class + // when the derived class property member has the same name and kind(instance or static) + // as the base class property member. + // The type of an overriding property member must be assignable(section 3.8.4) + // to the type of the overridden property member, or otherwise a compile - time error occurs. + // Base class instance member functions can be overridden by derived class instance member functions, + // but not by other kinds of members. + // Base class instance member variables and accessors can be overridden by + // derived class instance member variables and accessors, but not by other kinds of members. + // NOTE: assignability is checked in checkClassDeclaration var baseProperties = getPropertiesOfType(baseType); for (var _i = 0, baseProperties_1 = baseProperties; _i < baseProperties_1.length; _i++) { var baseProperty = baseProperties_1[_i]; var base = getTargetSymbol(baseProperty); - if (base.flags & 4194304) { + if (base.flags & 4194304 /* Prototype */) { continue; } - var derived = getTargetSymbol(getPropertyOfObjectType(type, base.escapedName)); + var derived = getTargetSymbol(getPropertyOfObjectType(type, base.escapedName)); // TODO: GH#18217 var baseDeclarationFlags = ts.getDeclarationModifierFlagsFromSymbol(base); ts.Debug.assert(!!derived, "derived should point to something, even if it is the base class' declaration."); if (derived) { + // In order to resolve whether the inherited method was overridden in the base class or not, + // we compare the Symbols obtained. Since getTargetSymbol returns the symbol on the *uninstantiated* + // type declaration, derived and base resolve to the same symbol even in the case of generic classes. if (derived === base) { + // derived class inherits base without override/redeclaration var derivedClassDecl = ts.getClassLikeDeclarationOfSymbol(type.symbol); - if (baseDeclarationFlags & 128 && (!derivedClassDecl || !ts.hasModifier(derivedClassDecl, 128))) { - if (derivedClassDecl.kind === 205) { + // It is an error to inherit an abstract member without implementing it or being declared abstract. + // If there is no declaration for the derived class (as in the case of class expressions), + // then the class cannot be declared abstract. + if (baseDeclarationFlags & 128 /* Abstract */ && (!derivedClassDecl || !ts.hasModifier(derivedClassDecl, 128 /* Abstract */))) { + if (derivedClassDecl.kind === 205 /* ClassExpression */) { error(derivedClassDecl, ts.Diagnostics.Non_abstract_class_expression_does_not_implement_inherited_abstract_member_0_from_class_1, symbolToString(baseProperty), typeToString(baseType)); } else { @@ -44109,23 +51525,26 @@ var ts; } } else { + // derived overrides base. var derivedDeclarationFlags = ts.getDeclarationModifierFlagsFromSymbol(derived); - if (baseDeclarationFlags & 8 || derivedDeclarationFlags & 8) { + if (baseDeclarationFlags & 8 /* Private */ || derivedDeclarationFlags & 8 /* Private */) { + // either base or derived property is private - not override, skip it continue; } - if (isPrototypeProperty(base) || base.flags & 98308 && derived.flags & 98308) { + if (isPrototypeProperty(base) || base.flags & 98308 /* PropertyOrAccessor */ && derived.flags & 98308 /* PropertyOrAccessor */) { + // method is overridden with method or property/accessor is overridden with property/accessor - correct case continue; } var errorMessage = void 0; if (isPrototypeProperty(base)) { - if (derived.flags & 98304) { + if (derived.flags & 98304 /* Accessor */) { errorMessage = ts.Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor; } else { errorMessage = ts.Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_property; } } - else if (base.flags & 98304) { + else if (base.flags & 98304 /* Accessor */) { errorMessage = ts.Diagnostics.Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function; } else { @@ -44159,7 +51578,7 @@ var ts; ok = false; var typeName1 = typeToString(existing.containingType); var typeName2 = typeToString(base); - var errorInfo = ts.chainDiagnosticMessages(undefined, ts.Diagnostics.Named_property_0_of_types_1_and_2_are_not_identical, symbolToString(prop), typeName1, typeName2); + var errorInfo = ts.chainDiagnosticMessages(/*details*/ undefined, ts.Diagnostics.Named_property_0_of_types_1_and_2_are_not_identical, symbolToString(prop), typeName1, typeName2); errorInfo = ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.Interface_0_cannot_simultaneously_extend_types_1_and_2, typeToString(type), typeName1, typeName2); diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(typeNode, errorInfo)); } @@ -44169,7 +51588,7 @@ var ts; return ok; } function checkPropertyInitialization(node) { - if (!strictNullChecks || !strictPropertyInitialization || node.flags & 4194304) { + if (!strictNullChecks || !strictPropertyInitialization || node.flags & 4194304 /* Ambient */) { return; } var constructor = findConstructorDeclaration(node); @@ -44179,7 +51598,7 @@ var ts; var propName = member.name; if (ts.isIdentifier(propName)) { var type = getTypeOfSymbol(getSymbolOfNode(member)); - if (!(type.flags & 3 || getFalsyFlags(type) & 8192)) { + if (!(type.flags & 3 /* AnyOrUnknown */ || getFalsyFlags(type) & 8192 /* Undefined */)) { if (!constructor || !isPropertyInitializedInConstructor(propName, type, constructor)) { error(member.name, ts.Diagnostics.Property_0_has_no_initializer_and_is_not_definitely_assigned_in_the_constructor, ts.declarationNameToString(propName)); } @@ -44189,8 +51608,8 @@ var ts; } } function isInstancePropertyWithoutInitializer(node) { - return node.kind === 152 && - !ts.hasModifier(node, 32 | 128) && + return node.kind === 152 /* PropertyDeclaration */ && + !ts.hasModifier(node, 32 /* Static */ | 128 /* Abstract */) && !node.exclamationToken && !node.initializer; } @@ -44198,9 +51617,10 @@ var ts; var reference = ts.createPropertyAccess(ts.createThis(), propName); reference.flowNode = constructor.returnFlowNode; var flowType = getFlowTypeOfReference(reference, propType, getOptionalType(propType)); - return !(getFalsyFlags(flowType) & 8192); + return !(getFalsyFlags(flowType) & 8192 /* Undefined */); } function checkInterfaceDeclaration(node) { + // Grammar checking if (!checkGrammarDecoratorsAndModifiers(node)) checkGrammarInterfaceDeclaration(node); checkTypeParameters(node.typeParameters); @@ -44209,10 +51629,12 @@ var ts; checkExportsOnMergedDeclarations(node); var symbol = getSymbolOfNode(node); checkTypeParameterListsIdentical(symbol); - var firstInterfaceDecl = ts.getDeclarationOfKind(symbol, 236); + // Only check this symbol once + var firstInterfaceDecl = ts.getDeclarationOfKind(symbol, 236 /* InterfaceDeclaration */); if (node === firstInterfaceDecl) { var type = getDeclaredTypeOfSymbol(symbol); var typeWithThis = getTypeWithThisArgument(type); + // run subsequent checks only if first set succeeded if (checkInheritedPropertiesAreIdentical(type, node.name)) { for (var _i = 0, _a = getBaseTypes(type); _i < _a.length; _i++) { var baseType = _a[_i]; @@ -44236,6 +51658,7 @@ var ts; } } function checkTypeAliasDeclaration(node) { + // Grammar checking checkGrammarDecoratorsAndModifiers(node); checkTypeNameIsReserved(node.name, ts.Diagnostics.Type_alias_name_cannot_be_0); checkTypeParameters(node.typeParameters); @@ -44244,8 +51667,8 @@ var ts; } function computeEnumMemberValues(node) { var nodeLinks = getNodeLinks(node); - if (!(nodeLinks.flags & 16384)) { - nodeLinks.flags |= 16384; + if (!(nodeLinks.flags & 16384 /* EnumValuesComputed */)) { + nodeLinks.flags |= 16384 /* EnumValuesComputed */; var autoValue = 0; for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var member = _a[_i]; @@ -44268,9 +51691,15 @@ var ts; if (member.initializer) { return computeConstantValue(member); } - if (member.parent.flags & 4194304 && !ts.isConst(member.parent)) { + // In ambient enum declarations that specify no const modifier, enum member declarations that omit + // a value are considered computed members (as opposed to having auto-incremented values). + if (member.parent.flags & 4194304 /* Ambient */ && !ts.isConst(member.parent)) { return undefined; } + // If the member declaration specifies no value, the member is considered a constant enum member. + // If the member is the first member in the enum declaration, it is assigned the value zero. + // Otherwise, it is assigned the value of the immediately preceding member plus one, and an error + // occurs if the immediately preceding member is not a constant enum member. if (autoValue !== undefined) { return autoValue; } @@ -44281,7 +51710,7 @@ var ts; var enumKind = getEnumKind(getSymbolOfNode(member.parent)); var isConstEnum = ts.isConst(member.parent); var initializer = member.initializer; - var value = enumKind === 1 && !isLiteralEnumMember(member) ? undefined : evaluate(initializer); + var value = enumKind === 1 /* Literal */ && !isLiteralEnumMember(member) ? undefined : evaluate(initializer); if (value !== undefined) { if (isConstEnum && typeof value === "number" && !isFinite(value)) { error(initializer, isNaN(value) ? @@ -44289,76 +51718,77 @@ var ts; ts.Diagnostics.const_enum_member_initializer_was_evaluated_to_a_non_finite_value); } } - else if (enumKind === 1) { + else if (enumKind === 1 /* Literal */) { error(initializer, ts.Diagnostics.Computed_values_are_not_permitted_in_an_enum_with_string_valued_members); return 0; } else if (isConstEnum) { error(initializer, ts.Diagnostics.In_const_enum_declarations_member_initializer_must_be_constant_expression); } - else if (member.parent.flags & 4194304) { + else if (member.parent.flags & 4194304 /* Ambient */) { error(initializer, ts.Diagnostics.In_ambient_enum_declarations_member_initializer_must_be_constant_expression); } else { - checkTypeAssignableTo(checkExpression(initializer), getDeclaredTypeOfSymbol(getSymbolOfNode(member.parent)), initializer, undefined); + // Only here do we need to check that the initializer is assignable to the enum type. + checkTypeAssignableTo(checkExpression(initializer), getDeclaredTypeOfSymbol(getSymbolOfNode(member.parent)), initializer, /*headMessage*/ undefined); } return value; function evaluate(expr) { switch (expr.kind) { - case 198: + case 198 /* PrefixUnaryExpression */: var value_2 = evaluate(expr.operand); if (typeof value_2 === "number") { switch (expr.operator) { - case 37: return value_2; - case 38: return -value_2; - case 52: return ~value_2; + case 37 /* PlusToken */: return value_2; + case 38 /* MinusToken */: return -value_2; + case 52 /* TildeToken */: return ~value_2; } } break; - case 200: + case 200 /* BinaryExpression */: var left = evaluate(expr.left); var right = evaluate(expr.right); if (typeof left === "number" && typeof right === "number") { switch (expr.operatorToken.kind) { - case 49: return left | right; - case 48: return left & right; - case 46: return left >> right; - case 47: return left >>> right; - case 45: return left << right; - case 50: return left ^ right; - case 39: return left * right; - case 41: return left / right; - case 37: return left + right; - case 38: return left - right; - case 42: return left % right; - case 40: return Math.pow(left, right); + case 49 /* BarToken */: return left | right; + case 48 /* AmpersandToken */: return left & right; + case 46 /* GreaterThanGreaterThanToken */: return left >> right; + case 47 /* GreaterThanGreaterThanGreaterThanToken */: return left >>> right; + case 45 /* LessThanLessThanToken */: return left << right; + case 50 /* CaretToken */: return left ^ right; + case 39 /* AsteriskToken */: return left * right; + case 41 /* SlashToken */: return left / right; + case 37 /* PlusToken */: return left + right; + case 38 /* MinusToken */: return left - right; + case 42 /* PercentToken */: return left % right; + case 40 /* AsteriskAsteriskToken */: return Math.pow(left, right); } } - else if (typeof left === "string" && typeof right === "string" && expr.operatorToken.kind === 37) { + else if (typeof left === "string" && typeof right === "string" && expr.operatorToken.kind === 37 /* PlusToken */) { return left + right; } break; - case 9: + case 9 /* StringLiteral */: return expr.text; - case 8: + case 8 /* NumericLiteral */: checkGrammarNumericLiteral(expr); return +expr.text; - case 191: + case 191 /* ParenthesizedExpression */: return evaluate(expr.expression); - case 71: + case 71 /* Identifier */: var identifier = expr; if (isInfinityOrNaNString(identifier.escapedText)) { return +(identifier.escapedText); } return ts.nodeIsMissing(expr) ? 0 : evaluateEnumMember(expr, getSymbolOfNode(member.parent), identifier.escapedText); - case 186: - case 185: + case 186 /* ElementAccessExpression */: + case 185 /* PropertyAccessExpression */: var ex = expr; if (isConstantMemberAccess(ex)) { var type = getTypeOfExpression(ex.expression); - if (type.symbol && type.symbol.flags & 384) { + if (type.symbol && type.symbol.flags & 384 /* Enum */) { var name = void 0; - if (ex.kind === 185) { + if (ex.kind === 185 /* PropertyAccessExpression */) { name = ex.name.escapedText; } else { @@ -44389,15 +51819,16 @@ var ts; } } function isConstantMemberAccess(node) { - return node.kind === 71 || - node.kind === 185 && isConstantMemberAccess(node.expression) || - node.kind === 186 && isConstantMemberAccess(node.expression) && - node.argumentExpression.kind === 9; + return node.kind === 71 /* Identifier */ || + node.kind === 185 /* PropertyAccessExpression */ && isConstantMemberAccess(node.expression) || + node.kind === 186 /* ElementAccessExpression */ && isConstantMemberAccess(node.expression) && + node.argumentExpression.kind === 9 /* StringLiteral */; } function checkEnumDeclaration(node) { if (!produceDiagnostics) { return; } + // Grammar checking checkGrammarDecoratorsAndModifiers(node); checkTypeNameIsReserved(node.name, ts.Diagnostics.Enum_name_cannot_be_0); checkCollisionWithRequireExportsInGeneratedCode(node, node.name); @@ -44405,13 +51836,20 @@ var ts; checkExportsOnMergedDeclarations(node); computeEnumMemberValues(node); var enumIsConst = ts.isConst(node); - if (compilerOptions.isolatedModules && enumIsConst && node.flags & 4194304) { + if (compilerOptions.isolatedModules && enumIsConst && node.flags & 4194304 /* Ambient */) { error(node.name, ts.Diagnostics.Ambient_const_enums_are_not_allowed_when_the_isolatedModules_flag_is_provided); } + // Spec 2014 - Section 9.3: + // It isn't possible for one enum declaration to continue the automatic numbering sequence of another, + // and when an enum type has multiple declarations, only one declaration is permitted to omit a value + // for the first member. + // + // Only perform this check once per symbol var enumSymbol = getSymbolOfNode(node); var firstDeclaration = ts.getDeclarationOfKind(enumSymbol, node.kind); if (node === firstDeclaration) { if (enumSymbol.declarations.length > 1) { + // check that const is placed\omitted on all enum declarations ts.forEach(enumSymbol.declarations, function (decl) { if (ts.isConstEnumDeclaration(decl) !== enumIsConst) { error(ts.getNameOfDeclaration(decl), ts.Diagnostics.Enum_declarations_must_all_be_const_or_non_const); @@ -44420,7 +51858,8 @@ var ts; } var seenEnumMissingInitialInitializer_1 = false; ts.forEach(enumSymbol.declarations, function (declaration) { - if (declaration.kind !== 238) { + // return true if we hit a violation of the rule, false otherwise + if (declaration.kind !== 238 /* EnumDeclaration */) { return false; } var enumDeclaration = declaration; @@ -44443,9 +51882,9 @@ var ts; var declarations = symbol.declarations; for (var _i = 0, declarations_8 = declarations; _i < declarations_8.length; _i++) { var declaration = declarations_8[_i]; - if ((declaration.kind === 235 || - (declaration.kind === 234 && ts.nodeIsPresent(declaration.body))) && - !(declaration.flags & 4194304)) { + if ((declaration.kind === 235 /* ClassDeclaration */ || + (declaration.kind === 234 /* FunctionDeclaration */ && ts.nodeIsPresent(declaration.body))) && + !(declaration.flags & 4194304 /* Ambient */)) { return declaration; } } @@ -44466,8 +51905,9 @@ var ts; } function checkModuleDeclaration(node) { if (produceDiagnostics) { + // Grammar checking var isGlobalAugmentation = ts.isGlobalScopeAugmentation(node); - var inAmbientContext = node.flags & 4194304; + var inAmbientContext = node.flags & 4194304 /* Ambient */; if (isGlobalAugmentation && !inAmbientContext) { error(node.name, ts.Diagnostics.Augmentations_for_the_global_scope_should_have_declare_modifier_unless_they_appear_in_already_ambient_context); } @@ -44476,10 +51916,11 @@ var ts; ? ts.Diagnostics.An_ambient_module_declaration_is_only_allowed_at_the_top_level_in_a_file : ts.Diagnostics.A_namespace_declaration_is_only_allowed_in_a_namespace_or_module; if (checkGrammarModuleElementContext(node, contextErrorMessage)) { + // If we hit a module declaration in an illegal context, just bail out to avoid cascading errors. return; } if (!checkGrammarDecoratorsAndModifiers(node)) { - if (!inAmbientContext && node.name.kind === 9) { + if (!inAmbientContext && node.name.kind === 9 /* StringLiteral */) { grammarErrorOnNode(node.name, ts.Diagnostics.Only_ambient_modules_can_use_quoted_names); } } @@ -44489,7 +51930,8 @@ var ts; } checkExportsOnMergedDeclarations(node); var symbol = getSymbolOfNode(node); - if (symbol.flags & 512 + // The following checks only apply on a non-ambient instantiated module declaration. + if (symbol.flags & 512 /* ValueModule */ && symbol.declarations.length > 1 && !inAmbientContext && isInstantiatedModule(node, !!compilerOptions.preserveConstEnums || !!compilerOptions.isolatedModules)) { @@ -44502,15 +51944,22 @@ var ts; error(node.name, ts.Diagnostics.A_namespace_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged); } } - var mergedClass = ts.getDeclarationOfKind(symbol, 235); + // if the module merges with a class declaration in the same lexical scope, + // we need to track this to ensure the correct emit. + var mergedClass = ts.getDeclarationOfKind(symbol, 235 /* ClassDeclaration */); if (mergedClass && inSameLexicalScope(node, mergedClass)) { - getNodeLinks(node).flags |= 32768; + getNodeLinks(node).flags |= 32768 /* LexicalModuleMergesWithClass */; } } if (isAmbientExternalModule) { if (ts.isExternalModuleAugmentation(node)) { - var checkBody = isGlobalAugmentation || (getSymbolOfNode(node).flags & 33554432); + // body of the augmentation should be checked for consistency only if augmentation was applied to its target (either global scope or module) + // otherwise we'll be swamped in cascading errors. + // We can detect if augmentation was applied using following rules: + // - augmentation for a global scope is always applied + // - augmentation for some external module is applied if symbol for augmentation is merged (it was combined with target module). + var checkBody = isGlobalAugmentation || (getSymbolOfNode(node).flags & 33554432 /* Transient */); if (checkBody && node.body) { for (var _i = 0, _a = node.body.statements; _i < _a.length; _i++) { var statement = _a[_i]; @@ -44531,6 +51980,8 @@ var ts; error(node.name, ts.Diagnostics.Augmentations_for_the_global_scope_can_only_be_directly_nested_in_external_modules_or_ambient_module_declarations); } else { + // Node is not an augmentation and is not located on the script level. + // This means that this is declaration of ambient module that is located in other module or namespace which is prohibited. error(node.name, ts.Diagnostics.Ambient_modules_cannot_be_nested_in_other_modules_or_namespaces); } } @@ -44545,43 +51996,51 @@ var ts; } function checkModuleAugmentationElement(node, isGlobalAugmentation) { switch (node.kind) { - case 214: + case 214 /* VariableStatement */: + // error each individual name in variable statement instead of marking the entire variable statement for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) { var decl = _a[_i]; checkModuleAugmentationElement(decl, isGlobalAugmentation); } break; - case 249: - case 250: + case 249 /* ExportAssignment */: + case 250 /* ExportDeclaration */: grammarErrorOnFirstToken(node, ts.Diagnostics.Exports_and_export_assignments_are_not_permitted_in_module_augmentations); break; - case 243: - case 244: + case 243 /* ImportEqualsDeclaration */: + case 244 /* ImportDeclaration */: grammarErrorOnFirstToken(node, ts.Diagnostics.Imports_are_not_permitted_in_module_augmentations_Consider_moving_them_to_the_enclosing_external_module); break; - case 182: - case 232: + case 182 /* BindingElement */: + case 232 /* VariableDeclaration */: var name = node.name; if (ts.isBindingPattern(name)) { for (var _b = 0, _c = name.elements; _b < _c.length; _b++) { var el = _c[_b]; + // mark individual names in binding pattern checkModuleAugmentationElement(el, isGlobalAugmentation); } break; } - case 235: - case 238: - case 234: - case 236: - case 239: - case 237: + // falls through + case 235 /* ClassDeclaration */: + case 238 /* EnumDeclaration */: + case 234 /* FunctionDeclaration */: + case 236 /* InterfaceDeclaration */: + case 239 /* ModuleDeclaration */: + case 237 /* TypeAliasDeclaration */: if (isGlobalAugmentation) { return; } var symbol = getSymbolOfNode(node); if (symbol) { - var reportError = !(symbol.flags & 33554432); + // module augmentations cannot introduce new names on the top level scope of the module + // this is done it two steps + // 1. quick check - if symbol for node is not merged - this is local symbol to this augmentation - report error + // 2. main check - report error if value declaration of the parent symbol is module augmentation) + var reportError = !(symbol.flags & 33554432 /* Transient */); if (!reportError) { + // symbol should not originate in augmentation reportError = ts.isExternalModuleAugmentation(symbol.parent.declarations[0]); } } @@ -44590,38 +52049,45 @@ var ts; } function getFirstIdentifier(node) { switch (node.kind) { - case 71: + case 71 /* Identifier */: return node; - case 146: + case 146 /* QualifiedName */: do { node = node.left; - } while (node.kind !== 71); + } while (node.kind !== 71 /* Identifier */); return node; - case 185: + case 185 /* PropertyAccessExpression */: do { node = node.expression; - } while (node.kind !== 71); + } while (node.kind !== 71 /* Identifier */); return node; } } function checkExternalImportOrExportDeclaration(node) { var moduleName = ts.getExternalModuleName(node); if (!moduleName || ts.nodeIsMissing(moduleName)) { + // Should be a parse error. return false; } if (!ts.isStringLiteral(moduleName)) { error(moduleName, ts.Diagnostics.String_literal_expected); return false; } - var inAmbientExternalModule = node.parent.kind === 240 && ts.isAmbientModule(node.parent.parent); - if (node.parent.kind !== 274 && !inAmbientExternalModule) { - error(moduleName, node.kind === 250 ? + var inAmbientExternalModule = node.parent.kind === 240 /* ModuleBlock */ && ts.isAmbientModule(node.parent.parent); + if (node.parent.kind !== 274 /* SourceFile */ && !inAmbientExternalModule) { + error(moduleName, node.kind === 250 /* ExportDeclaration */ ? ts.Diagnostics.Export_declarations_are_not_permitted_in_a_namespace : ts.Diagnostics.Import_declarations_in_a_namespace_cannot_reference_a_module); return false; } if (inAmbientExternalModule && ts.isExternalModuleNameRelative(moduleName.text)) { + // we have already reported errors on top level imports\exports in external module augmentations in checkModuleDeclaration + // no need to do this again. if (!isTopLevelInExternalModuleAugmentation(node)) { + // TypeScript 1.0 spec (April 2013): 12.1.6 + // An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference + // other external modules only through top - level external module names. + // Relative external module names are not permitted. error(node, ts.Diagnostics.Import_or_export_declaration_in_an_ambient_module_declaration_cannot_reference_module_through_relative_module_name); return false; } @@ -44632,19 +52098,26 @@ var ts; var symbol = getSymbolOfNode(node); var target = resolveAlias(symbol); if (target !== unknownSymbol) { - var excludedMeanings = (symbol.flags & (67216319 | 1048576) ? 67216319 : 0) | - (symbol.flags & 67901928 ? 67901928 : 0) | - (symbol.flags & 1920 ? 1920 : 0); + // For external modules symbol represent local symbol for an alias. + // This local symbol will merge any other local declarations (excluding other aliases) + // and symbol.flags will contains combined representation for all merged declaration. + // Based on symbol.flags we can compute a set of excluded meanings (meaning that resolved alias should not have, + // otherwise it will conflict with some local declaration). Note that in addition to normal flags we include matching SymbolFlags.Export* + // in order to prevent collisions with declarations that were exported from the current module (they still contribute to local names). + var excludedMeanings = (symbol.flags & (67216319 /* Value */ | 1048576 /* ExportValue */) ? 67216319 /* Value */ : 0) | + (symbol.flags & 67901928 /* Type */ ? 67901928 /* Type */ : 0) | + (symbol.flags & 1920 /* Namespace */ ? 1920 /* Namespace */ : 0); if (target.flags & excludedMeanings) { - var message = node.kind === 252 ? + var message = node.kind === 252 /* ExportSpecifier */ ? ts.Diagnostics.Export_declaration_conflicts_with_exported_declaration_of_0 : ts.Diagnostics.Import_declaration_conflicts_with_local_declaration_of_0; error(node, message, symbolToString(symbol)); } + // Don't allow to re-export something with no value side when `--isolatedModules` is set. if (compilerOptions.isolatedModules - && node.kind === 252 - && !(target.flags & 67216319) - && !(node.flags & 4194304)) { + && node.kind === 252 /* ExportSpecifier */ + && !(target.flags & 67216319 /* Value */) + && !(node.flags & 4194304 /* Ambient */)) { error(node, ts.Diagnostics.Cannot_re_export_a_type_when_the_isolatedModules_flag_is_provided); } } @@ -44656,6 +52129,7 @@ var ts; } function checkImportDeclaration(node) { if (checkGrammarModuleElementContext(node, ts.Diagnostics.An_import_declaration_can_only_be_used_in_a_namespace_or_module)) { + // If we hit an import declaration in an illegal context, just bail out to avoid cascading errors. return; } if (!checkGrammarDecoratorsAndModifiers(node) && ts.hasModifiers(node)) { @@ -44668,7 +52142,7 @@ var ts; checkImportBinding(importClause); } if (importClause.namedBindings) { - if (importClause.namedBindings.kind === 246) { + if (importClause.namedBindings.kind === 246 /* NamespaceImport */) { checkImportBinding(importClause.namedBindings); } else { @@ -44683,30 +52157,33 @@ var ts; } function checkImportEqualsDeclaration(node) { if (checkGrammarModuleElementContext(node, ts.Diagnostics.An_import_declaration_can_only_be_used_in_a_namespace_or_module)) { + // If we hit an import declaration in an illegal context, just bail out to avoid cascading errors. return; } checkGrammarDecoratorsAndModifiers(node); if (ts.isInternalModuleImportEqualsDeclaration(node) || checkExternalImportOrExportDeclaration(node)) { checkImportBinding(node); - if (ts.hasModifier(node, 1)) { + if (ts.hasModifier(node, 1 /* Export */)) { markExportAsReferenced(node); } - if (node.moduleReference.kind !== 254) { + if (node.moduleReference.kind !== 254 /* ExternalModuleReference */) { var target = resolveAlias(getSymbolOfNode(node)); if (target !== unknownSymbol) { - if (target.flags & 67216319) { + if (target.flags & 67216319 /* Value */) { + // Target is a value symbol, check that it is not hidden by a local declaration with the same name var moduleName = getFirstIdentifier(node.moduleReference); - if (!(resolveEntityName(moduleName, 67216319 | 1920).flags & 1920)) { + if (!(resolveEntityName(moduleName, 67216319 /* Value */ | 1920 /* Namespace */).flags & 1920 /* Namespace */)) { error(moduleName, ts.Diagnostics.Module_0_is_hidden_by_a_local_declaration_with_the_same_name, ts.declarationNameToString(moduleName)); } } - if (target.flags & 67901928) { + if (target.flags & 67901928 /* Type */) { checkTypeNameIsReserved(node.name, ts.Diagnostics.Import_name_cannot_be_0); } } } else { - if (moduleKind >= ts.ModuleKind.ES2015 && !(node.flags & 4194304)) { + if (moduleKind >= ts.ModuleKind.ES2015 && !(node.flags & 4194304 /* Ambient */)) { + // Import equals declaration is deprecated in es6 or above grammarErrorOnNode(node, ts.Diagnostics.Import_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_import_d_from_mod_or_another_module_format_instead); } } @@ -44714,6 +52191,7 @@ var ts; } function checkExportDeclaration(node) { if (checkGrammarModuleElementContext(node, ts.Diagnostics.An_export_declaration_can_only_be_used_in_a_module)) { + // If we hit an export in an illegal context, just bail out to avoid cascading errors. return; } if (!checkGrammarDecoratorsAndModifiers(node) && ts.hasModifiers(node)) { @@ -44721,27 +52199,30 @@ var ts; } if (!node.moduleSpecifier || checkExternalImportOrExportDeclaration(node)) { if (node.exportClause) { + // export { x, y } + // export { x, y } from "foo" ts.forEach(node.exportClause.elements, checkExportSpecifier); - var inAmbientExternalModule = node.parent.kind === 240 && ts.isAmbientModule(node.parent.parent); - var inAmbientNamespaceDeclaration = !inAmbientExternalModule && node.parent.kind === 240 && - !node.moduleSpecifier && node.flags & 4194304; - if (node.parent.kind !== 274 && !inAmbientExternalModule && !inAmbientNamespaceDeclaration) { + var inAmbientExternalModule = node.parent.kind === 240 /* ModuleBlock */ && ts.isAmbientModule(node.parent.parent); + var inAmbientNamespaceDeclaration = !inAmbientExternalModule && node.parent.kind === 240 /* ModuleBlock */ && + !node.moduleSpecifier && node.flags & 4194304 /* Ambient */; + if (node.parent.kind !== 274 /* SourceFile */ && !inAmbientExternalModule && !inAmbientNamespaceDeclaration) { error(node, ts.Diagnostics.Export_declarations_are_not_permitted_in_a_namespace); } } else { + // export * from "foo" var moduleSymbol_2 = resolveExternalModuleName(node, node.moduleSpecifier); if (moduleSymbol_2 && hasExportAssignmentSymbol(moduleSymbol_2)) { error(node.moduleSpecifier, ts.Diagnostics.Module_0_uses_export_and_cannot_be_used_with_export_Asterisk, symbolToString(moduleSymbol_2)); } if (moduleKind !== ts.ModuleKind.System && moduleKind !== ts.ModuleKind.ES2015 && moduleKind !== ts.ModuleKind.ESNext) { - checkExternalEmitHelpers(node, 32768); + checkExternalEmitHelpers(node, 32768 /* ExportStar */); } } } } function checkGrammarModuleElementContext(node, errorMessage) { - var isInAppropriateContext = node.parent.kind === 274 || node.parent.kind === 240 || node.parent.kind === 239; + var isInAppropriateContext = node.parent.kind === 274 /* SourceFile */ || node.parent.kind === 240 /* ModuleBlock */ || node.parent.kind === 239 /* ModuleDeclaration */; if (!isInAppropriateContext) { grammarErrorOnFirstToken(node, errorMessage); } @@ -44750,11 +52231,13 @@ var ts; function checkExportSpecifier(node) { checkAliasSymbol(node); if (compilerOptions.declaration) { - collectLinkedAliases(node.propertyName || node.name, true); + collectLinkedAliases(node.propertyName || node.name, /*setVisibility*/ true); } if (!node.parent.parent.moduleSpecifier) { var exportedName = node.propertyName || node.name; - var symbol = resolveName(exportedName, exportedName.escapedText, 67216319 | 67901928 | 1920 | 2097152, undefined, undefined, true); + // find immediate value referenced by exported name (SymbolFlags.Alias is set so we don't chase down aliases) + var symbol = resolveName(exportedName, exportedName.escapedText, 67216319 /* Value */ | 67901928 /* Type */ | 1920 /* Namespace */ | 2097152 /* Alias */, + /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); if (symbol && (symbol === undefinedSymbol || isGlobalSourceFile(getDeclarationContainer(symbol.declarations[0])))) { error(exportedName, ts.Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, ts.idText(exportedName)); } @@ -44765,10 +52248,11 @@ var ts; } function checkExportAssignment(node) { if (checkGrammarModuleElementContext(node, ts.Diagnostics.An_export_assignment_can_only_be_used_in_a_module)) { + // If we hit an export assignment in an illegal context, just bail out to avoid cascading errors. return; } - var container = node.parent.kind === 274 ? node.parent : node.parent.parent; - if (container.kind === 239 && !ts.isAmbientModule(container)) { + var container = node.parent.kind === 274 /* SourceFile */ ? node.parent : node.parent.parent; + if (container.kind === 239 /* ModuleDeclaration */ && !ts.isAmbientModule(container)) { if (node.isExportEquals) { error(node, ts.Diagnostics.An_export_assignment_cannot_be_used_in_a_namespace); } @@ -44777,27 +52261,30 @@ var ts; } return; } + // Grammar checking if (!checkGrammarDecoratorsAndModifiers(node) && ts.hasModifiers(node)) { grammarErrorOnFirstToken(node, ts.Diagnostics.An_export_assignment_cannot_have_modifiers); } - if (node.expression.kind === 71) { + if (node.expression.kind === 71 /* Identifier */) { markExportAsReferenced(node); if (compilerOptions.declaration) { - collectLinkedAliases(node.expression, true); + collectLinkedAliases(node.expression, /*setVisibility*/ true); } } else { checkExpressionCached(node.expression); } checkExternalModuleExports(container); - if ((node.flags & 4194304) && !ts.isEntityNameExpression(node.expression)) { + if ((node.flags & 4194304 /* Ambient */) && !ts.isEntityNameExpression(node.expression)) { grammarErrorOnNode(node.expression, ts.Diagnostics.The_expression_of_an_export_assignment_must_be_an_identifier_or_qualified_name_in_an_ambient_context); } - if (node.isExportEquals && !(node.flags & 4194304)) { + if (node.isExportEquals && !(node.flags & 4194304 /* Ambient */)) { if (moduleKind >= ts.ModuleKind.ES2015) { + // export assignment is not supported in es6 modules grammarErrorOnNode(node, ts.Diagnostics.Export_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_export_default_or_another_module_format_instead); } else if (moduleKind === ts.ModuleKind.System) { + // system modules does not support export assignment grammarErrorOnNode(node, ts.Diagnostics.Export_assignment_is_not_supported_when_module_flag_is_system); } } @@ -44816,6 +52303,7 @@ var ts; error(declaration, ts.Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements); } } + // Checks for export * conflicts var exports_2 = getExportsOfModule(moduleSymbol); if (exports_2) { exports_2.forEach(function (_a, id) { @@ -44823,11 +52311,15 @@ var ts; if (id === "__export") { return; } - if (flags & (1920 | 64 | 384)) { + // ECMA262: 15.2.1.1 It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries. + // (TS Exceptions: namespaces, function overloads, enums, and interfaces) + if (flags & (1920 /* Namespace */ | 64 /* Interface */ | 384 /* Enum */)) { return; } var exportedDeclarationsCount = ts.countWhere(declarations, isNotOverloadAndNotAccessor); - if (flags & 524288 && exportedDeclarationsCount <= 2) { + if (flags & 524288 /* TypeAlias */ && exportedDeclarationsCount <= 2) { + // it is legal to merge type alias with other values + // so count should be either 1 (just type alias) or 2 (type alias + merged value) return; } if (exportedDeclarationsCount > 1) { @@ -44844,10 +52336,11 @@ var ts; } } function isNotAccessor(declaration) { + // Accessors check for their own matching duplicates, and in contexts where they are valid, there are already duplicate identifier checks return !ts.isAccessor(declaration); } function isNotOverload(declaration) { - return (declaration.kind !== 234 && declaration.kind !== 154) || + return (declaration.kind !== 234 /* FunctionDeclaration */ && declaration.kind !== 154 /* MethodDeclaration */) || !!declaration.body; } function checkSourceElement(node) { @@ -44862,152 +52355,155 @@ var ts; } var kind = node.kind; if (cancellationToken) { + // Only bother checking on a few construct kinds. We don't want to be excessively + // hitting the cancellation token on every node we check. switch (kind) { - case 239: - case 235: - case 236: - case 234: + case 239 /* ModuleDeclaration */: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + case 234 /* FunctionDeclaration */: cancellationToken.throwIfCancellationRequested(); } } switch (kind) { - case 148: + case 148 /* TypeParameter */: return checkTypeParameter(node); - case 149: + case 149 /* Parameter */: return checkParameter(node); - case 152: - case 151: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: return checkPropertyDeclaration(node); - case 163: - case 164: - case 158: - case 159: - case 160: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 160 /* IndexSignature */: return checkSignatureDeclaration(node); - case 154: - case 153: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: return checkMethodDeclaration(node); - case 155: + case 155 /* Constructor */: return checkConstructorDeclaration(node); - case 156: - case 157: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return checkAccessorDeclaration(node); - case 162: + case 162 /* TypeReference */: return checkTypeReferenceNode(node); - case 161: + case 161 /* TypePredicate */: return checkTypePredicate(node); - case 165: + case 165 /* TypeQuery */: return checkTypeQuery(node); - case 166: + case 166 /* TypeLiteral */: return checkTypeLiteral(node); - case 167: + case 167 /* ArrayType */: return checkArrayType(node); - case 168: + case 168 /* TupleType */: return checkTupleType(node); - case 169: - case 170: + case 169 /* UnionType */: + case 170 /* IntersectionType */: return checkUnionOrIntersectionType(node); - case 173: + case 173 /* ParenthesizedType */: return checkSourceElement(node.type); - case 175: + case 175 /* TypeOperator */: return checkTypeOperator(node); - case 171: + case 171 /* ConditionalType */: return checkConditionalType(node); - case 172: + case 172 /* InferType */: return checkInferType(node); - case 179: + case 179 /* ImportType */: return checkImportType(node); - case 290: + case 290 /* JSDocAugmentsTag */: return checkJSDocAugmentsTag(node); - case 298: - case 292: + case 298 /* JSDocTypedefTag */: + case 292 /* JSDocCallbackTag */: return checkJSDocTypeAliasTag(node); - case 296: + case 296 /* JSDocTypeTag */: return checkJSDocTypeTag(node); - case 293: + case 293 /* JSDocParameterTag */: return checkJSDocParameterTag(node); - case 284: + case 284 /* JSDocFunctionType */: checkSignatureDeclaration(node); - case 282: - case 281: - case 279: - case 280: - case 287: + // falls through + case 282 /* JSDocNonNullableType */: + case 281 /* JSDocNullableType */: + case 279 /* JSDocAllType */: + case 280 /* JSDocUnknownType */: + case 287 /* JSDocTypeLiteral */: checkJSDocTypeIsInJsFile(node); ts.forEachChild(node, checkSourceElement); return; - case 285: + case 285 /* JSDocVariadicType */: checkJSDocVariadicType(node); return; - case 278: + case 278 /* JSDocTypeExpression */: return checkSourceElement(node.type); - case 176: + case 176 /* IndexedAccessType */: return checkIndexedAccessType(node); - case 177: + case 177 /* MappedType */: return checkMappedType(node); - case 234: + case 234 /* FunctionDeclaration */: return checkFunctionDeclaration(node); - case 213: - case 240: + case 213 /* Block */: + case 240 /* ModuleBlock */: return checkBlock(node); - case 214: + case 214 /* VariableStatement */: return checkVariableStatement(node); - case 216: + case 216 /* ExpressionStatement */: return checkExpressionStatement(node); - case 217: + case 217 /* IfStatement */: return checkIfStatement(node); - case 218: + case 218 /* DoStatement */: return checkDoStatement(node); - case 219: + case 219 /* WhileStatement */: return checkWhileStatement(node); - case 220: + case 220 /* ForStatement */: return checkForStatement(node); - case 221: + case 221 /* ForInStatement */: return checkForInStatement(node); - case 222: + case 222 /* ForOfStatement */: return checkForOfStatement(node); - case 223: - case 224: + case 223 /* ContinueStatement */: + case 224 /* BreakStatement */: return checkBreakOrContinueStatement(node); - case 225: + case 225 /* ReturnStatement */: return checkReturnStatement(node); - case 226: + case 226 /* WithStatement */: return checkWithStatement(node); - case 227: + case 227 /* SwitchStatement */: return checkSwitchStatement(node); - case 228: + case 228 /* LabeledStatement */: return checkLabeledStatement(node); - case 229: + case 229 /* ThrowStatement */: return checkThrowStatement(node); - case 230: + case 230 /* TryStatement */: return checkTryStatement(node); - case 232: + case 232 /* VariableDeclaration */: return checkVariableDeclaration(node); - case 182: + case 182 /* BindingElement */: return checkBindingElement(node); - case 235: + case 235 /* ClassDeclaration */: return checkClassDeclaration(node); - case 236: + case 236 /* InterfaceDeclaration */: return checkInterfaceDeclaration(node); - case 237: + case 237 /* TypeAliasDeclaration */: return checkTypeAliasDeclaration(node); - case 238: + case 238 /* EnumDeclaration */: return checkEnumDeclaration(node); - case 239: + case 239 /* ModuleDeclaration */: return checkModuleDeclaration(node); - case 244: + case 244 /* ImportDeclaration */: return checkImportDeclaration(node); - case 243: + case 243 /* ImportEqualsDeclaration */: return checkImportEqualsDeclaration(node); - case 250: + case 250 /* ExportDeclaration */: return checkExportDeclaration(node); - case 249: + case 249 /* ExportAssignment */: return checkExportAssignment(node); - case 215: - case 231: + case 215 /* EmptyStatement */: + case 231 /* DebuggerStatement */: checkGrammarStatementInAmbientContext(node); return; - case 253: + case 253 /* MissingDeclaration */: return checkMissingDeclaration(node); } } @@ -45019,6 +52515,7 @@ var ts; function checkJSDocVariadicType(node) { checkJSDocTypeIsInJsFile(node); checkSourceElement(node.type); + // Only legal location is in the *last* parameter tag or last parameter of a JSDoc function. var parent = node.parent; if (ts.isParameter(parent) && ts.isJSDocFunctionType(parent.parent)) { if (ts.last(parent.parent.parameters) !== parent) { @@ -45036,6 +52533,7 @@ var ts; } var param = ts.getParameterSymbolFromJSDoc(paramTag); if (!param) { + // We will error in `checkJSDocParameterTag`. return; } var host = ts.getHostSignatureFromJSDoc(paramTag); @@ -45048,8 +52546,16 @@ var ts; var parent = node.parent; var paramTag = node.parent.parent; if (ts.isJSDocTypeExpression(node.parent) && ts.isJSDocParameterTag(paramTag)) { + // Else we will add a diagnostic, see `checkJSDocVariadicType`. var host_1 = ts.getHostSignatureFromJSDoc(paramTag); if (host_1) { + /* + Only return an array type if the corresponding parameter is marked as a rest parameter, or if there are no parameters. + So in the following situation we will not create an array type: + /** @param {...number} a * / + function f(a) {} + Because `a` will just be of type `number | undefined`. A synthetic `...args` will also be added, which *will* get an array type. + */ var lastParamDeclaration = ts.lastOrUndefined(host_1.parameters); var symbol = ts.getParameterSymbolFromJSDoc(paramTag); if (!lastParamDeclaration || @@ -45063,6 +52569,15 @@ var ts; } return addOptionality(type); } + // Function and class expression bodies are checked after all statements in the enclosing body. This is + // to ensure constructs like the following are permitted: + // const foo = function () { + // const s = foo(); + // return "hello"; + // } + // Here, performing a full type check of the body of the function expression whilst in the process of + // determining the type of foo would cause foo to be given type any because of the recursive reference. + // Delaying the type check of the body ensures foo has been assigned a type. function checkNodeDeferred(node) { if (deferredNodes) { deferredNodes.push(node); @@ -45072,17 +52587,17 @@ var ts; for (var _i = 0, _a = deferredNodes; _i < _a.length; _i++) { var node = _a[_i]; switch (node.kind) { - case 192: - case 193: - case 154: - case 153: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: checkFunctionExpressionOrObjectLiteralMethodDeferred(node); break; - case 156: - case 157: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: checkAccessorDeclaration(node); break; - case 205: + case 205 /* ClassExpression */: checkClassExpressionDeferred(node); break; } @@ -45096,9 +52611,9 @@ var ts; } function unusedIsError(kind) { switch (kind) { - case 0: + case 0 /* Local */: return !!compilerOptions.noUnusedLocals; - case 1: + case 1 /* Parameter */: return !!compilerOptions.noUnusedParameters; default: return ts.Debug.assertNever(kind); @@ -45107,12 +52622,17 @@ var ts; function getPotentiallyUnusedIdentifiers(sourceFile) { return allPotentiallyUnusedIdentifiers.get(sourceFile.path) || ts.emptyArray; } + // Fully type check a source file and collect the relevant diagnostics. function checkSourceFileWorker(node) { var links = getNodeLinks(node); - if (!(links.flags & 1)) { + if (!(links.flags & 1 /* TypeChecked */)) { + // If skipLibCheck is enabled, skip type checking if file is a declaration file. + // If skipDefaultLibCheck is enabled, skip type checking if file contains a + // '/// ' directive. if (compilerOptions.skipLibCheck && node.isDeclarationFile || compilerOptions.skipDefaultLibCheck && node.hasNoDefaultLib) { return; } + // Grammar checking checkGrammarSourceFile(node); ts.clear(potentialThisCollisions); ts.clear(potentialNewTargetCollisions); @@ -45141,11 +52661,14 @@ var ts; ts.forEach(potentialNewTargetCollisions, checkIfNewTargetIsCapturedInEnclosingScope); ts.clear(potentialNewTargetCollisions); } - links.flags |= 1; + links.flags |= 1 /* TypeChecked */; } } function getDiagnostics(sourceFile, ct) { try { + // Record the cancellation token so it can be checked later on during checkSourceElement. + // Do this in a finally block so we can ensure that it gets reset back to nothing after + // this call is done. cancellationToken = ct; return getDiagnosticsWorker(sourceFile); } @@ -45156,20 +52679,29 @@ var ts; function getDiagnosticsWorker(sourceFile) { throwIfNonDiagnosticsProducing(); if (sourceFile) { + // Some global diagnostics are deferred until they are needed and + // may not be reported in the firt call to getGlobalDiagnostics. + // We should catch these changes and report them. var previousGlobalDiagnostics = diagnostics.getGlobalDiagnostics(); var previousGlobalDiagnosticsSize = previousGlobalDiagnostics.length; checkSourceFile(sourceFile); var semanticDiagnostics = diagnostics.getDiagnostics(sourceFile.fileName); var currentGlobalDiagnostics = diagnostics.getGlobalDiagnostics(); if (currentGlobalDiagnostics !== previousGlobalDiagnostics) { + // If the arrays are not the same reference, new diagnostics were added. var deferredGlobalDiagnostics = ts.relativeComplement(previousGlobalDiagnostics, currentGlobalDiagnostics, ts.compareDiagnostics); return ts.concatenate(deferredGlobalDiagnostics, semanticDiagnostics); } else if (previousGlobalDiagnosticsSize === 0 && currentGlobalDiagnostics.length > 0) { + // If the arrays are the same reference, but the length has changed, a single + // new diagnostic was added as DiagnosticCollection attempts to reuse the + // same array. return ts.concatenate(currentGlobalDiagnostics, semanticDiagnostics); } return semanticDiagnostics; } + // Global diagnostics are always added when a file is not provided to + // getDiagnostics ts.forEach(host.getSourceFiles(), checkSourceFile); return diagnostics.getDiagnostics(); } @@ -45182,8 +52714,10 @@ var ts; throw new Error("Trying to get diagnostics from a type checker that does not produce them."); } } + // Language service support function getSymbolsInScope(location, meaning) { - if (location.flags & 8388608) { + if (location.flags & 8388608 /* InWithStatement */) { + // We cannot answer semantic questions within a with block, do not proceed any further return []; } var symbols = ts.createSymbolTable(); @@ -45196,24 +52730,31 @@ var ts; copySymbols(location.locals, meaning); } switch (location.kind) { - case 239: - copySymbols(getSymbolOfNode(location).exports, meaning & 2623475); + case 239 /* ModuleDeclaration */: + copySymbols(getSymbolOfNode(location).exports, meaning & 2623475 /* ModuleMember */); break; - case 238: - copySymbols(getSymbolOfNode(location).exports, meaning & 8); + case 238 /* EnumDeclaration */: + copySymbols(getSymbolOfNode(location).exports, meaning & 8 /* EnumMember */); break; - case 205: + case 205 /* ClassExpression */: var className = location.name; if (className) { copySymbol(location.symbol, meaning); } - case 235: - case 236: + // falls through + // this fall-through is necessary because we would like to handle + // type parameter inside class expression similar to how we handle it in classDeclaration and interface Declaration + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + // If we didn't come from static member of class or interface, + // 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 (!isStatic) { - copySymbols(getMembersOfSymbol(getSymbolOfNode(location)), meaning & 67901928); + copySymbols(getMembersOfSymbol(getSymbolOfNode(location)), meaning & 67901928 /* Type */); } break; - case 192: + case 192 /* FunctionExpression */: var funcName = location.name; if (funcName) { copySymbol(location.symbol, meaning); @@ -45223,14 +52764,24 @@ var ts; if (ts.introducesArgumentsExoticObject(location)) { copySymbol(argumentsSymbol, meaning); } - isStatic = ts.hasModifier(location, 32); + isStatic = ts.hasModifier(location, 32 /* Static */); location = location.parent; } copySymbols(globals, meaning); } + /** + * Copy the given symbol into symbol tables if the symbol has the given meaning + * and it doesn't already existed in the symbol table + * @param key a key for storing in symbol table; if undefined, use symbol.name + * @param symbol the symbol to be added into symbol table + * @param meaning meaning of symbol to filter by before adding to symbol table + */ function copySymbol(symbol, meaning) { if (ts.getCombinedLocalAndExportSymbolFlags(symbol) & meaning) { var id = symbol.escapedName; + // We will copy all symbol regardless of its reserved name because + // symbolsToArray will check whether the key is a reserved name and + // it will not copy symbol with reserved name to the array if (!symbols.has(id)) { symbols.set(id, symbol); } @@ -45245,33 +52796,34 @@ var ts; } } function isTypeDeclarationName(name) { - return name.kind === 71 && + return name.kind === 71 /* Identifier */ && isTypeDeclaration(name.parent) && name.parent.name === name; } function isTypeDeclaration(node) { switch (node.kind) { - case 148: - case 235: - case 236: - case 237: - case 238: + case 148 /* TypeParameter */: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 238 /* EnumDeclaration */: return true; default: return false; } } + // True if the given identifier is part of a type reference function isTypeReferenceIdentifier(node) { - while (node.parent.kind === 146) { + while (node.parent.kind === 146 /* QualifiedName */) { node = node.parent; } - return node.parent.kind === 162; + return node.parent.kind === 162 /* TypeReference */; } function isHeritageClauseElementIdentifier(node) { - while (node.parent.kind === 185) { + while (node.parent.kind === 185 /* PropertyAccessExpression */) { node = node.parent; } - return node.parent.kind === 207; + return node.parent.kind === 207 /* ExpressionWithTypeArguments */; } function forEachEnclosingClass(node, callback) { var result; @@ -45299,13 +52851,13 @@ var ts; return !!forEachEnclosingClass(node, function (n) { return n === classDeclaration; }); } function getLeftSideOfImportEqualsOrExportAssignment(nodeOnRightSide) { - while (nodeOnRightSide.parent.kind === 146) { + while (nodeOnRightSide.parent.kind === 146 /* QualifiedName */) { nodeOnRightSide = nodeOnRightSide.parent; } - if (nodeOnRightSide.parent.kind === 243) { + if (nodeOnRightSide.parent.kind === 243 /* ImportEqualsDeclaration */) { return nodeOnRightSide.parent.moduleReference === nodeOnRightSide ? nodeOnRightSide.parent : undefined; } - if (nodeOnRightSide.parent.kind === 249) { + if (nodeOnRightSide.parent.kind === 249 /* ExportAssignment */) { return nodeOnRightSide.parent.expression === nodeOnRightSide ? nodeOnRightSide.parent : undefined; } return undefined; @@ -45316,12 +52868,12 @@ var ts; function getSpecialPropertyAssignmentSymbolFromEntityName(entityName) { var specialPropertyAssignmentKind = ts.getSpecialPropertyAssignmentKind(entityName.parent.parent); switch (specialPropertyAssignmentKind) { - case 1: - case 3: + case 1 /* ExportsProperty */: + case 3 /* PrototypeProperty */: return getSymbolOfNode(entityName.parent); - case 4: - case 2: - case 5: + case 4 /* ThisProperty */: + case 2 /* ModuleExports */: + case 5 /* Property */: return getSymbolOfNode(entityName.parent.parent); } } @@ -45331,7 +52883,7 @@ var ts; node = parent; parent = parent.parent; } - if (parent && parent.kind === 179 && parent.qualifier === node) { + if (parent && parent.kind === 179 /* ImportType */ && parent.qualifier === node) { return parent; } return undefined; @@ -45341,23 +52893,27 @@ var ts; return getSymbolOfNode(entityName.parent); } if (ts.isInJavaScriptFile(entityName) && - entityName.parent.kind === 185 && + entityName.parent.kind === 185 /* PropertyAccessExpression */ && entityName.parent === entityName.parent.parent.left) { + // Check if this is a special property assignment var specialPropertyAssignmentSymbol = getSpecialPropertyAssignmentSymbolFromEntityName(entityName); if (specialPropertyAssignmentSymbol) { return specialPropertyAssignmentSymbol; } } - if (entityName.parent.kind === 249 && ts.isEntityNameExpression(entityName)) { - var success = resolveEntityName(entityName, 67216319 | 67901928 | 1920 | 2097152, true); + if (entityName.parent.kind === 249 /* ExportAssignment */ && ts.isEntityNameExpression(entityName)) { + // Even an entity name expression that doesn't resolve as an entityname may still typecheck as a property access expression + var success = resolveEntityName(entityName, + /*all meanings*/ 67216319 /* Value */ | 67901928 /* Type */ | 1920 /* Namespace */ | 2097152 /* Alias */, /*ignoreErrors*/ true); if (success && success !== unknownSymbol) { return success; } } else if (!ts.isPropertyAccessExpression(entityName) && isInRightSideOfImportOrExportAssignment(entityName)) { - var importEqualsDeclaration = ts.getAncestor(entityName, 243); + // Since we already checked for ExportAssignment, this really could only be an Import + var importEqualsDeclaration = ts.getAncestor(entityName, 243 /* ImportEqualsDeclaration */); ts.Debug.assert(importEqualsDeclaration !== undefined); - return getSymbolOfPartOfRightHandSideOfImportEquals(entityName, true); + return getSymbolOfPartOfRightHandSideOfImportEquals(entityName, /*dontResolveAlias*/ true); } if (!ts.isPropertyAccessExpression(entityName)) { var possibleImportNode = isImportTypeQualifierPart(entityName); @@ -45371,47 +52927,50 @@ var ts; entityName = entityName.parent; } if (isHeritageClauseElementIdentifier(entityName)) { - var meaning = 0; - if (entityName.parent.kind === 207) { - meaning = 67901928; + var meaning = 0 /* None */; + // In an interface or class, we're definitely interested in a type. + if (entityName.parent.kind === 207 /* ExpressionWithTypeArguments */) { + meaning = 67901928 /* Type */; + // In a class 'extends' clause we are also looking for a value. if (ts.isExpressionWithTypeArgumentsInClassExtendsClause(entityName.parent)) { - meaning |= 67216319; + meaning |= 67216319 /* Value */; } } else { - meaning = 1920; + meaning = 1920 /* Namespace */; } - meaning |= 2097152; + meaning |= 2097152 /* Alias */; var entityNameSymbol = ts.isEntityNameExpression(entityName) ? resolveEntityName(entityName, meaning) : undefined; if (entityNameSymbol) { return entityNameSymbol; } } - if (entityName.parent.kind === 293) { + if (entityName.parent.kind === 293 /* JSDocParameterTag */) { return ts.getParameterSymbolFromJSDoc(entityName.parent); } - if (entityName.parent.kind === 148 && entityName.parent.parent.kind === 297) { - ts.Debug.assert(!ts.isInJavaScriptFile(entityName)); + if (entityName.parent.kind === 148 /* TypeParameter */ && entityName.parent.parent.kind === 297 /* JSDocTemplateTag */) { + ts.Debug.assert(!ts.isInJavaScriptFile(entityName)); // Otherwise `isDeclarationName` would have been true. var typeParameter = ts.getTypeParameterFromJsDoc(entityName.parent); return typeParameter && typeParameter.symbol; } if (ts.isExpressionNode(entityName)) { if (ts.nodeIsMissing(entityName)) { + // Missing entity name. return undefined; } - if (entityName.kind === 71) { + if (entityName.kind === 71 /* Identifier */) { if (ts.isJSXTagName(entityName) && isJsxIntrinsicIdentifier(entityName)) { var symbol = getIntrinsicTagSymbol(entityName.parent); return symbol === unknownSymbol ? undefined : symbol; } - return resolveEntityName(entityName, 67216319, false, true); + return resolveEntityName(entityName, 67216319 /* Value */, /*ignoreErrors*/ false, /*dontResolveAlias*/ true); } - else if (entityName.kind === 185 || entityName.kind === 146) { + else if (entityName.kind === 185 /* PropertyAccessExpression */ || entityName.kind === 146 /* QualifiedName */) { var links = getNodeLinks(entityName); if (links.resolvedSymbol) { return links.resolvedSymbol; } - if (entityName.kind === 185) { + if (entityName.kind === 185 /* PropertyAccessExpression */) { checkPropertyAccessExpression(entityName); } else { @@ -45421,38 +52980,41 @@ var ts; } } else if (isTypeReferenceIdentifier(entityName)) { - var meaning = entityName.parent.kind === 162 ? 67901928 : 1920; - return resolveEntityName(entityName, meaning, false, true); + var meaning = entityName.parent.kind === 162 /* TypeReference */ ? 67901928 /* Type */ : 1920 /* Namespace */; + return resolveEntityName(entityName, meaning, /*ignoreErrors*/ false, /*dontResolveAlias*/ true); } - else if (entityName.parent.kind === 262) { + else if (entityName.parent.kind === 262 /* JsxAttribute */) { return getJsxAttributePropertySymbol(entityName.parent); } - if (entityName.parent.kind === 161) { - return resolveEntityName(entityName, 1); + if (entityName.parent.kind === 161 /* TypePredicate */) { + return resolveEntityName(entityName, /*meaning*/ 1 /* FunctionScopedVariable */); } + // Do we want to return undefined here? return undefined; } function getSymbolAtLocation(node) { - if (node.kind === 274) { + if (node.kind === 274 /* SourceFile */) { return ts.isExternalModule(node) ? getMergedSymbol(node.symbol) : undefined; } var parent = node.parent; var grandParent = parent.parent; - if (node.flags & 8388608) { + if (node.flags & 8388608 /* InWithStatement */) { + // We cannot answer semantic questions within a with block, do not proceed any further return undefined; } if (isDeclarationNameOrImportPropertyName(node)) { + // This is a declaration, call getSymbolOfNode return getSymbolOfNode(parent); } else if (ts.isLiteralComputedPropertyDeclarationName(node)) { return getSymbolOfNode(parent.parent); } - if (node.kind === 71) { + if (node.kind === 71 /* Identifier */) { if (isInRightSideOfImportOrExportAssignment(node)) { return getSymbolOfEntityNameOrPropertyAccessExpression(node); } - else if (parent.kind === 182 && - grandParent.kind === 180 && + else if (parent.kind === 182 /* BindingElement */ && + grandParent.kind === 180 /* ObjectBindingPattern */ && node === parent.propertyName) { var typeOfPattern = getTypeOfNode(grandParent); var propertyDeclaration = typeOfPattern && getPropertyOfType(typeOfPattern, node.escapedText); @@ -45462,12 +53024,12 @@ var ts; } } switch (node.kind) { - case 71: - case 185: - case 146: + case 71 /* Identifier */: + case 185 /* PropertyAccessExpression */: + case 146 /* QualifiedName */: return getSymbolOfEntityNameOrPropertyAccessExpression(node); - case 99: - var container = ts.getThisContainer(node, false); + case 99 /* ThisKeyword */: + var container = ts.getThisContainer(node, /*includeArrowFunctions*/ false); if (ts.isFunctionLike(container)) { var sig = getSignatureFromDeclaration(container); if (sig.thisParameter) { @@ -45477,54 +53039,64 @@ var ts; if (ts.isInExpressionContext(node)) { return checkExpression(node).symbol; } - case 174: + // falls through + case 174 /* ThisType */: return getTypeFromThisTypeNode(node).symbol; - case 97: + case 97 /* SuperKeyword */: return checkExpression(node).symbol; - case 123: + case 123 /* ConstructorKeyword */: + // constructor keyword for an overload, should take us to the definition if it exist var constructorDeclaration = node.parent; - if (constructorDeclaration && constructorDeclaration.kind === 155) { + if (constructorDeclaration && constructorDeclaration.kind === 155 /* Constructor */) { return constructorDeclaration.parent.symbol; } return undefined; - case 9: - case 13: + case 9 /* StringLiteral */: + case 13 /* NoSubstitutionTemplateLiteral */: + // 1). import x = require("./mo/*gotToDefinitionHere*/d") + // 2). External module name in an import declaration + // 3). Dynamic import call or require in javascript + // 4). type A = import("./f/*gotToDefinitionHere*/oo") if ((ts.isExternalModuleImportEqualsDeclaration(node.parent.parent) && ts.getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node) || - ((node.parent.kind === 244 || node.parent.kind === 250) && node.parent.moduleSpecifier === node) || - ((ts.isInJavaScriptFile(node) && ts.isRequireCall(node.parent, false)) || ts.isImportCall(node.parent)) || + ((node.parent.kind === 244 /* ImportDeclaration */ || node.parent.kind === 250 /* ExportDeclaration */) && node.parent.moduleSpecifier === node) || + ((ts.isInJavaScriptFile(node) && ts.isRequireCall(node.parent, /*checkArgumentIsStringLiteralLike*/ false)) || ts.isImportCall(node.parent)) || (ts.isLiteralTypeNode(node.parent) && ts.isLiteralImportTypeNode(node.parent.parent) && node.parent.parent.argument === node.parent)) { return resolveExternalModuleName(node, node); } - case 8: + // falls through + case 8 /* NumericLiteral */: + // index access var objectType = ts.isElementAccessExpression(parent) ? parent.argumentExpression === node ? getTypeOfExpression(parent.expression) : undefined : ts.isLiteralTypeNode(parent) && ts.isIndexedAccessTypeNode(grandParent) ? getTypeFromTypeNode(grandParent.objectType) : undefined; return objectType && getPropertyOfType(objectType, ts.escapeLeadingUnderscores(node.text)); - case 79: - case 89: - case 36: + case 79 /* DefaultKeyword */: + case 89 /* FunctionKeyword */: + case 36 /* EqualsGreaterThanToken */: return getSymbolOfNode(node.parent); - case 179: + case 179 /* ImportType */: return ts.isLiteralImportTypeNode(node) ? getSymbolAtLocation(node.argument.literal) : undefined; default: return undefined; } } function getShorthandAssignmentValueSymbol(location) { - if (location && location.kind === 271) { - return resolveEntityName(location.name, 67216319 | 2097152); + if (location && location.kind === 271 /* ShorthandPropertyAssignment */) { + return resolveEntityName(location.name, 67216319 /* Value */ | 2097152 /* Alias */); } return undefined; } + /** Returns the target of an export specifier without following aliases */ function getExportSpecifierLocalTargetSymbol(node) { return node.parent.parent.moduleSpecifier ? getExternalModuleMember(node.parent.parent, node) : - resolveEntityName(node.propertyName || node.name, 67216319 | 67901928 | 1920 | 2097152); + resolveEntityName(node.propertyName || node.name, 67216319 /* Value */ | 67901928 /* Type */ | 1920 /* Namespace */ | 2097152 /* Alias */); } function getTypeOfNode(node) { - if (node.flags & 8388608) { + if (node.flags & 8388608 /* InWithStatement */) { + // We cannot answer semantic questions within a with block, do not proceed any further return errorType; } if (ts.isPartOfTypeNode(node)) { @@ -45540,12 +53112,15 @@ var ts; return getRegularTypeOfExpression(node); } if (ts.isExpressionWithTypeArgumentsInClassExtendsClause(node)) { + // A SyntaxKind.ExpressionWithTypeArguments is considered a type node, except when it occurs in the + // extends clause of a class. We handle that case here. var classNode = ts.getContainingClass(node); var classType = getDeclaredTypeOfSymbol(getSymbolOfNode(classNode)); var baseType = getBaseTypes(classType)[0]; return baseType && getTypeWithThisArgument(baseType, classType.thisType); } if (isTypeDeclaration(node)) { + // In this case, we call getSymbolOfNode instead of getSymbolAtLocation because it is a declaration var symbol = getSymbolOfNode(node); return getDeclaredTypeOfSymbol(symbol); } @@ -45554,6 +53129,7 @@ var ts; return symbol && getDeclaredTypeOfSymbol(symbol); } if (ts.isDeclaration(node)) { + // In this case, we call getSymbolOfNode instead of getSymbolAtLocation because it is a declaration var symbol = getSymbolOfNode(node); return getTypeOfSymbol(symbol); } @@ -45562,7 +53138,7 @@ var ts; return symbol && getTypeOfSymbol(symbol); } if (ts.isBindingPattern(node)) { - return getTypeForVariableLikeDeclaration(node.parent, true); + return getTypeForVariableLikeDeclaration(node.parent, /*includeOptionality*/ true); } if (isInRightSideOfImportOrExportAssignment(node)) { var symbol = getSymbolAtLocation(node); @@ -45573,26 +53149,48 @@ var ts; } return errorType; } + // Gets the type of object literal or array literal of destructuring assignment. + // { a } from + // for ( { a } of elems) { + // } + // [ a ] from + // [a] = [ some array ...] function getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(expr) { - ts.Debug.assert(expr.kind === 184 || expr.kind === 183); - if (expr.parent.kind === 222) { + ts.Debug.assert(expr.kind === 184 /* ObjectLiteralExpression */ || expr.kind === 183 /* ArrayLiteralExpression */); + // If this is from "for of" + // for ( { a } of elems) { + // } + if (expr.parent.kind === 222 /* ForOfStatement */) { var iteratedType = checkRightHandSideOfForOf(expr.parent.expression, expr.parent.awaitModifier); return checkDestructuringAssignment(expr, iteratedType || errorType); } - if (expr.parent.kind === 200) { + // If this is from "for" initializer + // for ({a } = elems[0];.....) { } + if (expr.parent.kind === 200 /* BinaryExpression */) { var iteratedType = getTypeOfExpression(expr.parent.right); return checkDestructuringAssignment(expr, iteratedType || errorType); } - if (expr.parent.kind === 270) { + // If this is from nested object binding pattern + // for ({ skills: { primary, secondary } } = multiRobot, i = 0; i < 1; i++) { + if (expr.parent.kind === 270 /* PropertyAssignment */) { var typeOfParentObjectLiteral = getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(expr.parent.parent); - return checkObjectLiteralDestructuringPropertyAssignment(typeOfParentObjectLiteral || errorType, expr.parent); + return checkObjectLiteralDestructuringPropertyAssignment(typeOfParentObjectLiteral || errorType, expr.parent); // TODO: GH#18217 } - ts.Debug.assert(expr.parent.kind === 183); + // Array literal assignment - array destructuring pattern + ts.Debug.assert(expr.parent.kind === 183 /* ArrayLiteralExpression */); + // [{ property1: p1, property2 }] = elems; var typeOfArrayLiteral = getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(expr.parent); - var elementType = checkIteratedTypeOrElementType(typeOfArrayLiteral || errorType, expr.parent, false, false) || errorType; - return checkArrayLiteralDestructuringElementAssignment(expr.parent, typeOfArrayLiteral, expr.parent.elements.indexOf(expr), elementType || errorType); + var elementType = checkIteratedTypeOrElementType(typeOfArrayLiteral || errorType, expr.parent, /*allowStringInput*/ false, /*allowAsyncIterables*/ false) || errorType; + return checkArrayLiteralDestructuringElementAssignment(expr.parent, typeOfArrayLiteral, expr.parent.elements.indexOf(expr), elementType || errorType); // TODO: GH#18217 } + // Gets the property symbol corresponding to the property in destructuring assignment + // 'property1' from + // for ( { property1: a } of elems) { + // } + // 'property1' at location 'a' from: + // [a] = [ property1, property2 ] function getPropertySymbolOfDestructuringAssignment(location) { + // Get the type of the object or array literal and then look for property of given name in the type var typeOfObjectLiteral = getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(location.parent.parent); return typeOfObjectLiteral && getPropertyOfType(typeOfObjectLiteral, location.escapedText); } @@ -45602,12 +53200,18 @@ var ts; } return getRegularTypeOfLiteralType(getTypeOfExpression(expr)); } + /** + * Gets either the static or instance type of a class element, based on + * whether the element is declared as "static". + */ function getParentTypeOfClassElement(node) { var classSymbol = getSymbolOfNode(node.parent); - return ts.hasModifier(node, 32) + return ts.hasModifier(node, 32 /* Static */) ? getTypeOfSymbol(classSymbol) : getDeclaredTypeOfSymbol(classSymbol); } + // Return the list of properties of the given type, augmented with properties from Function + // if the type has call or construct signatures function getAugmentedPropertiesOfType(type) { type = getApparentType(type); var propsByName = ts.createSymbolTable(getPropertiesOfType(type)); @@ -45628,10 +53232,10 @@ var ts; return roots ? ts.flatMap(roots, getRootSymbols) : [symbol]; } function getImmediateRootSymbols(symbol) { - if (ts.getCheckFlags(symbol) & 6) { + if (ts.getCheckFlags(symbol) & 6 /* Synthetic */) { return ts.mapDefined(getSymbolLinks(symbol).containingType.types, function (type) { return getPropertyOfType(type, symbol.escapedName); }); } - else if (symbol.flags & 33554432) { + else if (symbol.flags & 33554432 /* Transient */) { var _a = symbol, leftSpread = _a.leftSpread, rightSpread = _a.rightSpread, syntheticOrigin = _a.syntheticOrigin; return leftSpread ? [leftSpread, rightSpread] : syntheticOrigin ? [syntheticOrigin] @@ -45647,11 +53251,12 @@ var ts; } return target; } + // Emitter support function isArgumentsLocalBinding(nodeIn) { if (!ts.isGeneratedIdentifier(nodeIn)) { var node = ts.getParseTreeNode(nodeIn, ts.isIdentifier); if (node) { - var isPropertyName_1 = node.parent.kind === 185 && node.parent.name === node; + var isPropertyName_1 = node.parent.kind === 185 /* PropertyAccessExpression */ && node.parent.name === node; return !isPropertyName_1 && getReferencedValueSymbol(node) === argumentsSymbol; } } @@ -45660,42 +53265,57 @@ var ts; function moduleExportsSomeValue(moduleReferenceExpression) { var moduleSymbol = resolveExternalModuleName(moduleReferenceExpression.parent, moduleReferenceExpression); if (!moduleSymbol || ts.isShorthandAmbientModuleSymbol(moduleSymbol)) { + // If the module is not found or is shorthand, assume that it may export a value. return true; } var hasExportAssignment = hasExportAssignmentSymbol(moduleSymbol); + // if module has export assignment then 'resolveExternalModuleSymbol' will return resolved symbol for export assignment + // otherwise it will return moduleSymbol itself moduleSymbol = resolveExternalModuleSymbol(moduleSymbol); var symbolLinks = getSymbolLinks(moduleSymbol); if (symbolLinks.exportsSomeValue === undefined) { + // for export assignments - check if resolved symbol for RHS is itself a value + // otherwise - check if at least one export is value symbolLinks.exportsSomeValue = hasExportAssignment - ? !!(moduleSymbol.flags & 67216319) + ? !!(moduleSymbol.flags & 67216319 /* Value */) : ts.forEachEntry(getExportsOfModule(moduleSymbol), isValue); } return symbolLinks.exportsSomeValue; function isValue(s) { s = resolveSymbol(s); - return s && !!(s.flags & 67216319); + return s && !!(s.flags & 67216319 /* Value */); } } function isNameOfModuleOrEnumDeclaration(node) { return ts.isModuleOrEnumDeclaration(node.parent) && node === node.parent.name; } + // When resolved as an expression identifier, if the given node references an exported entity, return the declaration + // node of the exported entity's container. Otherwise, return undefined. function getReferencedExportContainer(nodeIn, prefixLocals) { var node = ts.getParseTreeNode(nodeIn, ts.isIdentifier); if (node) { - var symbol = getReferencedValueSymbol(node, isNameOfModuleOrEnumDeclaration(node)); + // When resolving the export container for the name of a module or enum + // declaration, we need to start resolution at the declaration's container. + // Otherwise, we could incorrectly resolve the export container as the + // declaration if it contains an exported member with the same name. + var symbol = getReferencedValueSymbol(node, /*startInDeclarationContainer*/ isNameOfModuleOrEnumDeclaration(node)); if (symbol) { - if (symbol.flags & 1048576) { + if (symbol.flags & 1048576 /* ExportValue */) { + // If we reference an exported entity within the same module declaration, then whether + // we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the + // kinds that we do NOT prefix. var exportSymbol = getMergedSymbol(symbol.exportSymbol); - if (!prefixLocals && exportSymbol.flags & 944 && !(exportSymbol.flags & 3)) { + if (!prefixLocals && exportSymbol.flags & 944 /* ExportHasLocal */ && !(exportSymbol.flags & 3 /* Variable */)) { return undefined; } symbol = exportSymbol; } var parentSymbol_1 = getParentOfSymbol(symbol); if (parentSymbol_1) { - if (parentSymbol_1.flags & 512 && parentSymbol_1.valueDeclaration.kind === 274) { + if (parentSymbol_1.flags & 512 /* ValueModule */ && parentSymbol_1.valueDeclaration.kind === 274 /* SourceFile */) { var symbolFile = parentSymbol_1.valueDeclaration; var referenceFile = ts.getSourceFileOfNode(node); + // If `node` accesses an export and that export isn't in the same file, then symbol is a namespace export, so return undefined. var symbolIsUmdExport = symbolFile !== referenceFile; return symbolIsUmdExport ? undefined : symbolFile; } @@ -45704,30 +53324,50 @@ var ts; } } } + // When resolved as an expression identifier, if the given node references an import, return the declaration of + // that import. Otherwise, return undefined. function getReferencedImportDeclaration(nodeIn) { var node = ts.getParseTreeNode(nodeIn, ts.isIdentifier); if (node) { var symbol = getReferencedValueSymbol(node); - if (isNonLocalAlias(symbol, 67216319)) { + // We should only get the declaration of an alias if there isn't a local value + // declaration for the symbol + if (isNonLocalAlias(symbol, /*excludes*/ 67216319 /* Value */)) { return getDeclarationOfAliasSymbol(symbol); } } return undefined; } function isSymbolOfDeclarationWithCollidingName(symbol) { - if (symbol.flags & 418) { + if (symbol.flags & 418 /* BlockScoped */) { var links = getSymbolLinks(symbol); if (links.isDeclarationWithCollidingName === undefined) { var container = ts.getEnclosingBlockScopeContainer(symbol.valueDeclaration); if (ts.isStatementWithLocals(container)) { var nodeLinks_1 = getNodeLinks(symbol.valueDeclaration); - if (resolveName(container.parent, symbol.escapedName, 67216319, undefined, undefined, false)) { + if (resolveName(container.parent, symbol.escapedName, 67216319 /* Value */, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)) { + // redeclaration - always should be renamed links.isDeclarationWithCollidingName = true; } - else if (nodeLinks_1.flags & 131072) { - var isDeclaredInLoop = nodeLinks_1.flags & 262144; - var inLoopInitializer = ts.isIterationStatement(container, false); - var inLoopBodyBlock = container.kind === 213 && ts.isIterationStatement(container.parent, false); + else if (nodeLinks_1.flags & 131072 /* CapturedBlockScopedBinding */) { + // binding is captured in the function + // should be renamed if: + // - binding is not top level - top level bindings never collide with anything + // AND + // - binding is not declared in loop, should be renamed to avoid name reuse across siblings + // let a, b + // { let x = 1; a = () => x; } + // { let x = 100; b = () => x; } + // console.log(a()); // should print '1' + // console.log(b()); // should print '100' + // OR + // - binding is declared inside loop but not in inside initializer of iteration statement or directly inside loop body + // * variables from initializer are passed to rewritten loop body as parameters so they are not captured directly + // * variables that are declared immediately in loop body will become top level variable after loop is rewritten and thus + // they will not collide with anything + var isDeclaredInLoop = nodeLinks_1.flags & 262144 /* BlockScopedBindingInLoop */; + var inLoopInitializer = ts.isIterationStatement(container, /*lookInLabeledStatements*/ false); + var inLoopBodyBlock = container.kind === 213 /* Block */ && ts.isIterationStatement(container.parent, /*lookInLabeledStatements*/ false); links.isDeclarationWithCollidingName = !ts.isBlockScopedContainerTopLevel(container) && (!isDeclaredInLoop || (!inLoopInitializer && !inLoopBodyBlock)); } else { @@ -45739,6 +53379,9 @@ var ts; } return false; } + // When resolved as an expression identifier, if the given node references a nested block scoped entity with + // a name that either hides an existing name or might hide it when compiled downlevel, + // return the declaration of that entity. Otherwise, return undefined. function getReferencedDeclarationWithCollidingName(nodeIn) { if (!ts.isGeneratedIdentifier(nodeIn)) { var node = ts.getParseTreeNode(nodeIn, ts.isIdentifier); @@ -45751,6 +53394,8 @@ var ts; } return undefined; } + // Return true if the given node is a declaration of a nested block scoped entity with a name that either hides an + // existing name or might hide a name when compiled downlevel function isDeclarationWithCollidingName(nodeIn) { var node = ts.getParseTreeNode(nodeIn, ts.isDeclaration); if (node) { @@ -45763,18 +53408,18 @@ var ts; } function isValueAliasDeclaration(node) { switch (node.kind) { - case 243: - case 245: - case 246: - case 248: - case 252: + case 243 /* ImportEqualsDeclaration */: + case 245 /* ImportClause */: + case 246 /* NamespaceImport */: + case 248 /* ImportSpecifier */: + case 252 /* ExportSpecifier */: return isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol); - case 250: + case 250 /* ExportDeclaration */: var exportClause = node.exportClause; return !!exportClause && ts.some(exportClause.elements, isValueAliasDeclaration); - case 249: + case 249 /* ExportAssignment */: return node.expression - && node.expression.kind === 71 + && node.expression.kind === 71 /* Identifier */ ? isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol) : true; } @@ -45782,7 +53427,8 @@ var ts; } function isTopLevelValueImportEqualsWithEntityName(nodeIn) { var node = ts.getParseTreeNode(nodeIn, ts.isImportEqualsDeclaration); - if (node === undefined || node.parent.kind !== 274 || !ts.isInternalModuleImportEqualsDeclaration(node)) { + if (node === undefined || node.parent.kind !== 274 /* SourceFile */ || !ts.isInternalModuleImportEqualsDeclaration(node)) { + // parent is not source file or it is not reference to internal module return false; } var isValue = isAliasResolvedToValue(getSymbolOfNode(node)); @@ -45793,7 +53439,9 @@ var ts; if (target === unknownSymbol) { return true; } - return !!(target.flags & 67216319) && + // const enums and modules that contain only const enums are not considered values from the emit perspective + // unless 'preserveConstEnums' option is set to true + return !!(target.flags & 67216319 /* Value */) && (compilerOptions.preserveConstEnums || !isConstEnumOrConstEnumOnlyModule(target)); } function isConstEnumOrConstEnumOnlyModule(s) { @@ -45805,8 +53453,9 @@ var ts; if (symbol && getSymbolLinks(symbol).referenced) { return true; } - var target = getSymbolLinks(symbol).target; - if (target && ts.getModifierFlags(node) & 1 && target.flags & 67216319) { + var target = getSymbolLinks(symbol).target; // TODO: GH#18217 + if (target && ts.getModifierFlags(node) & 1 /* Export */ && target.flags & 67216319 /* Value */) { + // An `export import ... =` of a value symbol is always considered referenced return true; } } @@ -45818,10 +53467,21 @@ var ts; function isImplementationOfOverload(node) { if (ts.nodeIsPresent(node.body)) { if (ts.isGetAccessor(node) || ts.isSetAccessor(node)) - return false; + return false; // Get or set accessors can never be overload implementations, but can have up to 2 signatures var symbol = getSymbolOfNode(node); var signaturesOfSymbol = getSignaturesOfSymbol(symbol); + // If this function body corresponds to function with multiple signature, it is implementation of overload + // e.g.: function foo(a: string): string; + // function foo(a: number): number; + // function foo(a: any) { // This is implementation of the overloads + // return a; + // } return signaturesOfSymbol.length > 1 || + // If there is single signature for the symbol, it is overload if that signature isn't coming from the node + // e.g.: function foo(a: string): string; + // function foo(a: any) { // This is implementation of the overloads + // return a; + // } (signaturesOfSymbol.length === 1 && signaturesOfSymbol[0].declaration !== node); } return false; @@ -45831,13 +53491,13 @@ var ts; !isOptionalParameter(parameter) && !ts.isJSDocParameterTag(parameter) && !!parameter.initializer && - !ts.hasModifier(parameter, 92); + !ts.hasModifier(parameter, 92 /* ParameterPropertyModifier */); } function isOptionalUninitializedParameterProperty(parameter) { return strictNullChecks && isOptionalParameter(parameter) && !parameter.initializer && - ts.hasModifier(parameter, 92); + ts.hasModifier(parameter, 92 /* ParameterPropertyModifier */); } function getNodeCheckFlags(node) { return getNodeLinks(node).flags || 0; @@ -45848,19 +53508,20 @@ var ts; } function canHaveConstantValue(node) { switch (node.kind) { - case 273: - case 185: - case 186: + case 273 /* EnumMember */: + case 185 /* PropertyAccessExpression */: + case 186 /* ElementAccessExpression */: return true; } return false; } function getConstantValue(node) { - if (node.kind === 273) { + if (node.kind === 273 /* EnumMember */) { return getEnumMemberValue(node); } var symbol = getNodeLinks(node).resolvedSymbol; - if (symbol && (symbol.flags & 8)) { + if (symbol && (symbol.flags & 8 /* EnumMember */)) { + // inline property\index accesses only for const enums if (ts.isConstEnumDeclaration(symbol.valueDeclaration.parent)) { return getEnumMemberValue(symbol.valueDeclaration); } @@ -45868,9 +53529,10 @@ var ts; return undefined; } function isFunctionType(type) { - return !!(type.flags & 131072) && getSignaturesOfType(type, 0).length > 0; + return !!(type.flags & 131072 /* Object */) && getSignaturesOfType(type, 0 /* Call */).length > 0; } function getTypeReferenceSerializationKind(typeNameIn, location) { + // ensure both `typeName` and `location` are parse tree nodes. var typeName = ts.getParseTreeNode(typeNameIn, ts.isEntityName); if (!typeName) return ts.TypeReferenceSerializationKind.Unknown; @@ -45879,10 +53541,12 @@ var ts; if (!location) return ts.TypeReferenceSerializationKind.Unknown; } - var valueSymbol = resolveEntityName(typeName, 67216319, true, false, location); - var typeSymbol = resolveEntityName(typeName, 67901928, true, false, location); + // Resolve the symbol as a value to ensure the type can be reached at runtime during emit. + var valueSymbol = resolveEntityName(typeName, 67216319 /* Value */, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location); + // Resolve the symbol as a type so that we can provide a more useful hint for the type serializer. + var typeSymbol = resolveEntityName(typeName, 67901928 /* Type */, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location); if (valueSymbol && valueSymbol === typeSymbol) { - var globalPromiseSymbol = getGlobalPromiseConstructorSymbol(false); + var globalPromiseSymbol = getGlobalPromiseConstructorSymbol(/*reportErrors*/ false); if (globalPromiseSymbol && valueSymbol === globalPromiseSymbol) { return ts.TypeReferenceSerializationKind.Promise; } @@ -45891,6 +53555,7 @@ var ts; return ts.TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue; } } + // We might not be able to resolve type symbol so use unknown type in that case (eg error case) if (!typeSymbol) { return ts.TypeReferenceSerializationKind.Unknown; } @@ -45898,25 +53563,25 @@ var ts; if (type === errorType) { return ts.TypeReferenceSerializationKind.Unknown; } - else if (type.flags & 3) { + else if (type.flags & 3 /* AnyOrUnknown */) { return ts.TypeReferenceSerializationKind.ObjectType; } - else if (isTypeAssignableToKind(type, 4096 | 24576 | 32768)) { + else if (isTypeAssignableToKind(type, 4096 /* Void */ | 24576 /* Nullable */ | 32768 /* Never */)) { return ts.TypeReferenceSerializationKind.VoidNullableOrNeverType; } - else if (isTypeAssignableToKind(type, 272)) { + else if (isTypeAssignableToKind(type, 272 /* BooleanLike */)) { return ts.TypeReferenceSerializationKind.BooleanType; } - else if (isTypeAssignableToKind(type, 168)) { + else if (isTypeAssignableToKind(type, 168 /* NumberLike */)) { return ts.TypeReferenceSerializationKind.NumberLikeType; } - else if (isTypeAssignableToKind(type, 68)) { + else if (isTypeAssignableToKind(type, 68 /* StringLike */)) { return ts.TypeReferenceSerializationKind.StringLikeType; } else if (isTupleType(type)) { return ts.TypeReferenceSerializationKind.ArrayLikeType; } - else if (isTypeAssignableToKind(type, 3072)) { + else if (isTypeAssignableToKind(type, 3072 /* ESSymbolLike */)) { return ts.TypeReferenceSerializationKind.ESSymbolType; } else if (isFunctionType(type)) { @@ -45932,36 +53597,37 @@ var ts; function createTypeOfDeclaration(declarationIn, enclosingDeclaration, flags, tracker, addUndefined) { var declaration = ts.getParseTreeNode(declarationIn, ts.isVariableLikeOrAccessor); if (!declaration) { - return ts.createToken(119); + return ts.createToken(119 /* AnyKeyword */); } + // Get type of the symbol if this is the valid symbol otherwise get type at location var symbol = getSymbolOfNode(declaration); - var type = symbol && !(symbol.flags & (2048 | 131072)) + var type = symbol && !(symbol.flags & (2048 /* TypeLiteral */ | 131072 /* Signature */)) ? getWidenedLiteralType(getTypeOfSymbol(symbol)) : errorType; - if (type.flags & 2048 && + if (type.flags & 2048 /* UniqueESSymbol */ && type.symbol === symbol) { - flags |= 1048576; + flags |= 1048576 /* AllowUniqueESSymbolType */; } if (addUndefined) { type = getOptionalType(type); } - return nodeBuilder.typeToTypeNode(type, enclosingDeclaration, flags | 1024, tracker); + return nodeBuilder.typeToTypeNode(type, enclosingDeclaration, flags | 1024 /* MultilineObjectLiterals */, tracker); } function createReturnTypeOfSignatureDeclaration(signatureDeclarationIn, enclosingDeclaration, flags, tracker) { var signatureDeclaration = ts.getParseTreeNode(signatureDeclarationIn, ts.isFunctionLike); if (!signatureDeclaration) { - return ts.createToken(119); + return ts.createToken(119 /* AnyKeyword */); } var signature = getSignatureFromDeclaration(signatureDeclaration); - return nodeBuilder.typeToTypeNode(getReturnTypeOfSignature(signature), enclosingDeclaration, flags | 1024, tracker); + return nodeBuilder.typeToTypeNode(getReturnTypeOfSignature(signature), enclosingDeclaration, flags | 1024 /* MultilineObjectLiterals */, tracker); } function createTypeOfExpression(exprIn, enclosingDeclaration, flags, tracker) { var expr = ts.getParseTreeNode(exprIn, ts.isExpression); if (!expr) { - return ts.createToken(119); + return ts.createToken(119 /* AnyKeyword */); } var type = getWidenedType(getRegularTypeOfExpression(expr)); - return nodeBuilder.typeToTypeNode(type, enclosingDeclaration, flags | 1024, tracker); + return nodeBuilder.typeToTypeNode(type, enclosingDeclaration, flags | 1024 /* MultilineObjectLiterals */, tracker); } function hasGlobalName(name) { return globals.has(ts.escapeLeadingUnderscores(name)); @@ -45973,12 +53639,14 @@ var ts; } var location = reference; if (startInDeclarationContainer) { + // When resolving the name of a declaration as a value, we need to start resolution + // at a point outside of the declaration. var parent = reference.parent; if (ts.isDeclaration(parent) && reference === parent.name) { location = getDeclarationContainer(parent); } } - return resolveName(location, reference.escapedText, 67216319 | 1048576 | 2097152, undefined, undefined, true); + return resolveName(location, reference.escapedText, 67216319 /* Value */ | 1048576 /* ExportValue */ | 2097152 /* Alias */, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); } function getReferencedValueDeclaration(referenceIn) { if (!ts.isGeneratedIdentifier(referenceIn)) { @@ -45995,7 +53663,7 @@ var ts; function isLiteralConstDeclaration(node) { if (ts.isConst(node)) { var type = getTypeOfSymbol(getSymbolOfNode(node)); - return !!(type.flags & 192 && type.flags & 33554432); + return !!(type.flags & 192 /* StringOrNumberLiteral */ && type.flags & 33554432 /* FreshLiteral */); } return false; } @@ -46007,9 +53675,12 @@ var ts; return literalTypeToNode(type); } function createResolver() { + // this variable and functions that use it are deliberately moved here from the outer scope + // to avoid scope pollution var resolvedTypeReferenceDirectives = host.getResolvedTypeReferenceDirectives(); var fileToDirective; if (resolvedTypeReferenceDirectives) { + // populate reverse mapping: file path -> type reference directive that was resolved to this file fileToDirective = ts.createMap(); resolvedTypeReferenceDirectives.forEach(function (resolvedDirective, key) { if (!resolvedDirective || !resolvedDirective.resolvedFileName) { @@ -46026,11 +53697,13 @@ var ts; isDeclarationWithCollidingName: isDeclarationWithCollidingName, isValueAliasDeclaration: function (node) { node = ts.getParseTreeNode(node); + // Synthesized nodes are always treated like values. return node ? isValueAliasDeclaration(node) : true; }, hasGlobalName: hasGlobalName, isReferencedAliasDeclaration: function (node, checkChildren) { node = ts.getParseTreeNode(node); + // Synthesized nodes are always treated as referenced. return node ? isReferencedAliasDeclaration(node, checkChildren) : true; }, getNodeCheckFlags: function (node) { @@ -46065,17 +53738,17 @@ var ts; isLateBound: function (nodeIn) { var node = ts.getParseTreeNode(nodeIn, ts.isDeclaration); var symbol = node && getSymbolOfNode(node); - return !!(symbol && ts.getCheckFlags(symbol) & 1024); + return !!(symbol && ts.getCheckFlags(symbol) & 1024 /* Late */); }, getJsxFactoryEntity: function (location) { return location ? (getJsxNamespace(location), (ts.getSourceFileOfNode(location).localJsxFactory || _jsxFactoryEntity)) : _jsxFactoryEntity; }, getAllAccessorDeclarations: function (accessor) { - accessor = ts.getParseTreeNode(accessor, ts.isGetOrSetAccessorDeclaration); - var otherKind = accessor.kind === 157 ? 156 : 157; + accessor = ts.getParseTreeNode(accessor, ts.isGetOrSetAccessorDeclaration); // TODO: GH#18217 + var otherKind = accessor.kind === 157 /* SetAccessor */ ? 156 /* GetAccessor */ : 157 /* SetAccessor */; var otherAccessor = ts.getDeclarationOfKind(getSymbolOfNode(accessor), otherKind); var firstAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? otherAccessor : accessor; var secondAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? accessor : otherAccessor; - var setAccessor = accessor.kind === 157 ? accessor : otherAccessor; - var getAccessor = accessor.kind === 156 ? accessor : otherAccessor; + var setAccessor = accessor.kind === 157 /* SetAccessor */ ? accessor : otherAccessor; + var getAccessor = accessor.kind === 156 /* GetAccessor */ ? accessor : otherAccessor; return { firstAccessor: firstAccessor, secondAccessor: secondAccessor, @@ -46085,29 +53758,38 @@ var ts; } }; function isInHeritageClause(node) { - return node.parent && node.parent.kind === 207 && node.parent.parent && node.parent.parent.kind === 268; + return node.parent && node.parent.kind === 207 /* ExpressionWithTypeArguments */ && node.parent.parent && node.parent.parent.kind === 268 /* HeritageClause */; } + // defined here to avoid outer scope pollution function getTypeReferenceDirectivesForEntityName(node) { + // program does not have any files with type reference directives - bail out if (!fileToDirective) { return undefined; } - var meaning = 67901928 | 1920; - if ((node.kind === 71 && isInTypeQuery(node)) || (node.kind === 185 && !isInHeritageClause(node))) { - meaning = 67216319 | 1048576; + // property access can only be used as values, or types when within an expression with type arguments inside a heritage clause + // qualified names can only be used as types\namespaces + // identifiers are treated as values only if they appear in type queries + var meaning = 67901928 /* Type */ | 1920 /* Namespace */; + if ((node.kind === 71 /* Identifier */ && isInTypeQuery(node)) || (node.kind === 185 /* PropertyAccessExpression */ && !isInHeritageClause(node))) { + meaning = 67216319 /* Value */ | 1048576 /* ExportValue */; } - var symbol = resolveEntityName(node, meaning, true); + var symbol = resolveEntityName(node, meaning, /*ignoreErrors*/ true); return symbol && symbol !== unknownSymbol ? getTypeReferenceDirectivesForSymbol(symbol, meaning) : undefined; } + // defined here to avoid outer scope pollution function getTypeReferenceDirectivesForSymbol(symbol, meaning) { + // program does not have any files with type reference directives - bail out if (!fileToDirective) { return undefined; } if (!isSymbolFromTypeDeclarationFile(symbol)) { return undefined; } + // check what declarations in the symbol can contribute to the target meaning var typeReferenceDirectives; for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var decl = _a[_i]; + // check meaning of the local symbol to see if declaration needs to be analyzed further if (decl.symbol && decl.symbol.flags & meaning) { var file = ts.getSourceFileOfNode(decl); var typeReferenceDirective = fileToDirective.get(file.path); @@ -46115,6 +53797,7 @@ var ts; (typeReferenceDirectives || (typeReferenceDirectives = [])).push(typeReferenceDirective); } else { + // found at least one entry that does not originate from type reference directive return undefined; } } @@ -46122,9 +53805,12 @@ var ts; return typeReferenceDirectives; } function isSymbolFromTypeDeclarationFile(symbol) { + // bail out if symbol does not have associated declarations (i.e. this is transient symbol created for property in binding pattern) if (!symbol.declarations) { return false; } + // walk the parent chain for symbols to make sure that top level parent symbol is in the global scope + // external modules cannot define or contribute to type declaration files var current = symbol; while (true) { var parent = getParentOfSymbol(current); @@ -46135,9 +53821,10 @@ var ts; break; } } - if (current.valueDeclaration && current.valueDeclaration.kind === 274 && current.flags & 512) { + if (current.valueDeclaration && current.valueDeclaration.kind === 274 /* SourceFile */ && current.flags & 512 /* ValueModule */) { return false; } + // check that at least one declaration of top level symbol originates from type declaration file for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var decl = _a[_i]; var file = ts.getSourceFileOfNode(decl); @@ -46149,18 +53836,20 @@ var ts; } } function getExternalModuleFileFromDeclaration(declaration) { - var specifier = declaration.kind === 239 ? ts.tryCast(declaration.name, ts.isStringLiteral) : ts.getExternalModuleName(declaration); - var moduleSymbol = resolveExternalModuleNameWorker(specifier, specifier, undefined); + var specifier = declaration.kind === 239 /* ModuleDeclaration */ ? ts.tryCast(declaration.name, ts.isStringLiteral) : ts.getExternalModuleName(declaration); + var moduleSymbol = resolveExternalModuleNameWorker(specifier, specifier, /*moduleNotFoundError*/ undefined); // TODO: GH#18217 if (!moduleSymbol) { return undefined; } - return ts.getDeclarationOfKind(moduleSymbol, 274); + return ts.getDeclarationOfKind(moduleSymbol, 274 /* SourceFile */); } function initializeTypeChecker() { + // Bind all source files and propagate errors for (var _i = 0, _a = host.getSourceFiles(); _i < _a.length; _i++) { var file = _a[_i]; ts.bindSourceFile(file, compilerOptions); } + // Initialize global symbol table var augmentations; for (var _b = 0, _c = host.getSourceFiles(); _b < _c.length; _b++) { var file = _c[_b]; @@ -46174,6 +53863,7 @@ var ts; (augmentations || (augmentations = [])).push(file.moduleAugmentations); } if (file.symbol && file.symbol.globalExports) { + // Merge in UMD exports with first-in-wins semantics (see #9771) var source = file.symbol.globalExports; source.forEach(function (sourceSymbol, id) { if (!globals.has(id)) { @@ -46182,7 +53872,15 @@ var ts; }); } } + // We do global augmentations separately from module augmentations (and before creating global types) because they + // 1. Affect global types. We won't have the correct global types until global augmentations are merged. Also, + // 2. Module augmentation instantiation requires creating the type of a module, which, in turn, can require + // checking for an export or property on the module (if export=) which, in turn, can fall back to the + // apparent type of the module - either globalObjectType or globalFunctionType - which wouldn't exist if we + // did module augmentations prior to finalizing the global types. if (augmentations) { + // merge _global_ module augmentations. + // this needs to be done after global symbol table is initialized to make sure that all ambient modules are indexed for (var _d = 0, augmentations_1 = augmentations; _d < augmentations_1.length; _d++) { var list = augmentations_1[_d]; for (var _e = 0, list_1 = list; _e < list_1.length; _e++) { @@ -46193,26 +53891,31 @@ var ts; } } } + // Setup global builtins addToSymbolTable(globals, builtinGlobals, ts.Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0); getSymbolLinks(undefinedSymbol).type = undefinedWideningType; - getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments", 0, true); + getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments", /*arity*/ 0, /*reportErrors*/ true); getSymbolLinks(unknownSymbol).type = errorType; - globalArrayType = getGlobalType("Array", 1, true); - globalObjectType = getGlobalType("Object", 0, true); - globalFunctionType = getGlobalType("Function", 0, true); - globalStringType = getGlobalType("String", 0, true); - globalNumberType = getGlobalType("Number", 0, true); - globalBooleanType = getGlobalType("Boolean", 0, true); - globalRegExpType = getGlobalType("RegExp", 0, true); + // Initialize special types + globalArrayType = getGlobalType("Array", /*arity*/ 1, /*reportErrors*/ true); + globalObjectType = getGlobalType("Object", /*arity*/ 0, /*reportErrors*/ true); + globalFunctionType = getGlobalType("Function", /*arity*/ 0, /*reportErrors*/ true); + globalStringType = getGlobalType("String", /*arity*/ 0, /*reportErrors*/ true); + globalNumberType = getGlobalType("Number", /*arity*/ 0, /*reportErrors*/ true); + globalBooleanType = getGlobalType("Boolean", /*arity*/ 0, /*reportErrors*/ true); + globalRegExpType = getGlobalType("RegExp", /*arity*/ 0, /*reportErrors*/ true); anyArrayType = createArrayType(anyType); autoArrayType = createArrayType(autoType); if (autoArrayType === emptyObjectType) { + // autoArrayType is used as a marker, so even if global Array type is not defined, it needs to be a unique type autoArrayType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, undefined, undefined); } - globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray", 1); + globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray", /*arity*/ 1); anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType; - globalThisType = getGlobalTypeOrUndefined("ThisType", 1); + globalThisType = getGlobalTypeOrUndefined("ThisType", /*arity*/ 1); if (augmentations) { + // merge _nonglobal_ module augmentations. + // this needs to be done after global symbol table is initialized to make sure that all ambient modules are indexed for (var _f = 0, augmentations_2 = augmentations; _f < augmentations_2.length; _f++) { var list = augmentations_2[_f]; for (var _g = 0, list_2 = list; _g < list_2.length; _g++) { @@ -46227,14 +53930,14 @@ var ts; function checkExternalEmitHelpers(location, helpers) { if ((requestedExternalEmitHelpers & helpers) !== helpers && compilerOptions.importHelpers) { var sourceFile = ts.getSourceFileOfNode(location); - if (ts.isEffectiveExternalModule(sourceFile, compilerOptions) && !(location.flags & 4194304)) { + if (ts.isEffectiveExternalModule(sourceFile, compilerOptions) && !(location.flags & 4194304 /* Ambient */)) { var helpersModule = resolveHelpersModule(sourceFile, location); if (helpersModule !== unknownSymbol) { var uncheckedHelpers = helpers & ~requestedExternalEmitHelpers; - for (var helper = 1; helper <= 65536; helper <<= 1) { + for (var helper = 1 /* FirstEmitHelper */; helper <= 65536 /* LastEmitHelper */; helper <<= 1) { if (uncheckedHelpers & helper) { var name = getHelperName(helper); - var symbol = getSymbol(helpersModule.exports, ts.escapeLeadingUnderscores(name), 67216319); + var symbol = getSymbol(helpersModule.exports, ts.escapeLeadingUnderscores(name), 67216319 /* Value */); if (!symbol) { error(location, ts.Diagnostics.This_syntax_requires_an_imported_helper_named_1_but_module_0_has_no_exported_member_1, ts.externalHelpersModuleNameText, name); } @@ -46247,23 +53950,23 @@ var ts; } function getHelperName(helper) { switch (helper) { - case 1: return "__extends"; - case 2: return "__assign"; - case 4: return "__rest"; - case 8: return "__decorate"; - case 16: return "__metadata"; - case 32: return "__param"; - case 64: return "__awaiter"; - case 128: return "__generator"; - case 256: return "__values"; - case 512: return "__read"; - case 1024: return "__spread"; - case 2048: return "__await"; - case 4096: return "__asyncGenerator"; - case 8192: return "__asyncDelegator"; - case 16384: return "__asyncValues"; - case 32768: return "__exportStar"; - case 65536: return "__makeTemplateObject"; + case 1 /* Extends */: return "__extends"; + case 2 /* Assign */: return "__assign"; + case 4 /* Rest */: return "__rest"; + case 8 /* Decorate */: return "__decorate"; + case 16 /* Metadata */: return "__metadata"; + case 32 /* Param */: return "__param"; + case 64 /* Awaiter */: return "__awaiter"; + case 128 /* Generator */: return "__generator"; + case 256 /* Values */: return "__values"; + case 512 /* Read */: return "__read"; + case 1024 /* Spread */: return "__spread"; + case 2048 /* Await */: return "__await"; + case 4096 /* AsyncGenerator */: return "__asyncGenerator"; + case 8192 /* AsyncDelegator */: return "__asyncDelegator"; + case 16384 /* AsyncValues */: return "__asyncValues"; + case 32768 /* ExportStar */: return "__exportStar"; + case 65536 /* MakeTemplateObject */: return "__makeTemplateObject"; default: return ts.Debug.fail("Unrecognized helper"); } } @@ -46273,6 +53976,7 @@ var ts; } return externalHelpersModule; } + // GRAMMAR CHECKING function checkGrammarDecoratorsAndModifiers(node) { return checkGrammarDecorators(node) || checkGrammarModifiers(node); } @@ -46281,14 +53985,14 @@ var ts; return false; } if (!ts.nodeCanBeDecorated(node, node.parent, node.parent.parent)) { - if (node.kind === 154 && !ts.nodeIsPresent(node.body)) { + if (node.kind === 154 /* MethodDeclaration */ && !ts.nodeIsPresent(node.body)) { return grammarErrorOnFirstToken(node, ts.Diagnostics.A_decorator_can_only_decorate_a_method_implementation_not_an_overload); } else { return grammarErrorOnFirstToken(node, ts.Diagnostics.Decorators_are_not_valid_here); } } - else if (node.kind === 156 || node.kind === 157) { + else if (node.kind === 156 /* GetAccessor */ || node.kind === 157 /* SetAccessor */) { var accessors = ts.getAllAccessorDeclarations(node.parent.members, node); if (accessors.firstAccessor.decorators && node === accessors.secondAccessor) { return grammarErrorOnFirstToken(node, ts.Diagnostics.Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name); @@ -46302,44 +54006,44 @@ var ts; return quickResult; } var lastStatic, lastDeclare, lastAsync, lastReadonly; - var flags = 0; + var flags = 0 /* None */; for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { var modifier = _a[_i]; - if (modifier.kind !== 132) { - if (node.kind === 151 || node.kind === 153) { + if (modifier.kind !== 132 /* ReadonlyKeyword */) { + if (node.kind === 151 /* PropertySignature */ || node.kind === 153 /* MethodSignature */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_type_member, ts.tokenToString(modifier.kind)); } - if (node.kind === 160) { + if (node.kind === 160 /* IndexSignature */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_an_index_signature, ts.tokenToString(modifier.kind)); } } switch (modifier.kind) { - case 76: - if (node.kind !== 238 && node.parent.kind === 235) { - return grammarErrorOnNode(node, ts.Diagnostics.A_class_member_cannot_have_the_0_keyword, ts.tokenToString(76)); + case 76 /* ConstKeyword */: + if (node.kind !== 238 /* EnumDeclaration */ && node.parent.kind === 235 /* ClassDeclaration */) { + return grammarErrorOnNode(node, ts.Diagnostics.A_class_member_cannot_have_the_0_keyword, ts.tokenToString(76 /* ConstKeyword */)); } break; - case 114: - case 113: - case 112: + case 114 /* PublicKeyword */: + case 113 /* ProtectedKeyword */: + case 112 /* PrivateKeyword */: var text = visibilityToString(ts.modifierToFlag(modifier.kind)); - if (flags & 28) { + if (flags & 28 /* AccessibilityModifier */) { return grammarErrorOnNode(modifier, ts.Diagnostics.Accessibility_modifier_already_seen); } - else if (flags & 32) { + else if (flags & 32 /* Static */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, text, "static"); } - else if (flags & 64) { + else if (flags & 64 /* Readonly */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, text, "readonly"); } - else if (flags & 256) { + else if (flags & 256 /* Async */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, text, "async"); } - else if (node.parent.kind === 240 || node.parent.kind === 274) { + else if (node.parent.kind === 240 /* ModuleBlock */ || node.parent.kind === 274 /* SourceFile */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element, text); } - else if (flags & 128) { - if (modifier.kind === 112) { + else if (flags & 128 /* Abstract */) { + if (modifier.kind === 112 /* PrivateKeyword */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_with_1_modifier, text, "abstract"); } else { @@ -46348,152 +54052,157 @@ var ts; } flags |= ts.modifierToFlag(modifier.kind); break; - case 115: - if (flags & 32) { + case 115 /* StaticKeyword */: + if (flags & 32 /* Static */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "static"); } - else if (flags & 64) { + else if (flags & 64 /* Readonly */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "static", "readonly"); } - else if (flags & 256) { + else if (flags & 256 /* Async */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "static", "async"); } - else if (node.parent.kind === 240 || node.parent.kind === 274) { + else if (node.parent.kind === 240 /* ModuleBlock */ || node.parent.kind === 274 /* SourceFile */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element, "static"); } - else if (node.kind === 149) { + else if (node.kind === 149 /* Parameter */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "static"); } - else if (flags & 128) { + else if (flags & 128 /* Abstract */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "abstract"); } - flags |= 32; + flags |= 32 /* Static */; lastStatic = modifier; break; - case 132: - if (flags & 64) { + case 132 /* ReadonlyKeyword */: + if (flags & 64 /* Readonly */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "readonly"); } - else if (node.kind !== 152 && node.kind !== 151 && node.kind !== 160 && node.kind !== 149) { + else if (node.kind !== 152 /* PropertyDeclaration */ && node.kind !== 151 /* PropertySignature */ && node.kind !== 160 /* IndexSignature */ && node.kind !== 149 /* Parameter */) { + // If node.kind === SyntaxKind.Parameter, checkParameter report an error if it's not a parameter property. return grammarErrorOnNode(modifier, ts.Diagnostics.readonly_modifier_can_only_appear_on_a_property_declaration_or_index_signature); } - flags |= 64; + flags |= 64 /* Readonly */; lastReadonly = modifier; break; - case 84: - if (flags & 1) { + case 84 /* ExportKeyword */: + if (flags & 1 /* Export */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "export"); } - else if (flags & 2) { + else if (flags & 2 /* Ambient */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "export", "declare"); } - else if (flags & 128) { + else if (flags & 128 /* Abstract */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "export", "abstract"); } - else if (flags & 256) { + else if (flags & 256 /* Async */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "export", "async"); } - else if (node.parent.kind === 235) { + else if (node.parent.kind === 235 /* ClassDeclaration */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_class_element, "export"); } - else if (node.kind === 149) { + else if (node.kind === 149 /* Parameter */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "export"); } - flags |= 1; + flags |= 1 /* Export */; break; - case 79: - var container = node.parent.kind === 274 ? node.parent : node.parent.parent; - if (container.kind === 239 && !ts.isAmbientModule(container)) { + case 79 /* DefaultKeyword */: + var container = node.parent.kind === 274 /* SourceFile */ ? node.parent : node.parent.parent; + if (container.kind === 239 /* ModuleDeclaration */ && !ts.isAmbientModule(container)) { return grammarErrorOnNode(modifier, ts.Diagnostics.A_default_export_can_only_be_used_in_an_ECMAScript_style_module); } - flags |= 512; + flags |= 512 /* Default */; break; - case 124: - if (flags & 2) { + case 124 /* DeclareKeyword */: + if (flags & 2 /* Ambient */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "declare"); } - else if (flags & 256) { + else if (flags & 256 /* Async */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async"); } - else if (node.parent.kind === 235) { + else if (node.parent.kind === 235 /* ClassDeclaration */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_class_element, "declare"); } - else if (node.kind === 149) { + else if (node.kind === 149 /* Parameter */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "declare"); } - else if ((node.parent.flags & 4194304) && node.parent.kind === 240) { + else if ((node.parent.flags & 4194304 /* Ambient */) && node.parent.kind === 240 /* ModuleBlock */) { return grammarErrorOnNode(modifier, ts.Diagnostics.A_declare_modifier_cannot_be_used_in_an_already_ambient_context); } - flags |= 2; + flags |= 2 /* Ambient */; lastDeclare = modifier; break; - case 117: - if (flags & 128) { + case 117 /* AbstractKeyword */: + if (flags & 128 /* Abstract */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "abstract"); } - if (node.kind !== 235) { - if (node.kind !== 154 && - node.kind !== 152 && - node.kind !== 156 && - node.kind !== 157) { + if (node.kind !== 235 /* ClassDeclaration */) { + if (node.kind !== 154 /* MethodDeclaration */ && + node.kind !== 152 /* PropertyDeclaration */ && + node.kind !== 156 /* GetAccessor */ && + node.kind !== 157 /* SetAccessor */) { return grammarErrorOnNode(modifier, ts.Diagnostics.abstract_modifier_can_only_appear_on_a_class_method_or_property_declaration); } - if (!(node.parent.kind === 235 && ts.hasModifier(node.parent, 128))) { + if (!(node.parent.kind === 235 /* ClassDeclaration */ && ts.hasModifier(node.parent, 128 /* Abstract */))) { return grammarErrorOnNode(modifier, ts.Diagnostics.Abstract_methods_can_only_appear_within_an_abstract_class); } - if (flags & 32) { + if (flags & 32 /* Static */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "abstract"); } - if (flags & 8) { + if (flags & 8 /* Private */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "private", "abstract"); } } - flags |= 128; + flags |= 128 /* Abstract */; break; - case 120: - if (flags & 256) { + case 120 /* AsyncKeyword */: + if (flags & 256 /* Async */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "async"); } - else if (flags & 2 || node.parent.flags & 4194304) { + else if (flags & 2 /* Ambient */ || node.parent.flags & 4194304 /* Ambient */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async"); } - else if (node.kind === 149) { + else if (node.kind === 149 /* Parameter */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "async"); } - flags |= 256; + flags |= 256 /* Async */; lastAsync = modifier; break; } } - if (node.kind === 155) { - if (flags & 32) { + if (node.kind === 155 /* Constructor */) { + if (flags & 32 /* Static */) { return grammarErrorOnNode(lastStatic, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "static"); } - if (flags & 128) { - return grammarErrorOnNode(lastStatic, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "abstract"); + if (flags & 128 /* Abstract */) { + return grammarErrorOnNode(lastStatic, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "abstract"); // TODO: GH#18217 } - else if (flags & 256) { + else if (flags & 256 /* Async */) { return grammarErrorOnNode(lastAsync, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "async"); } - else if (flags & 64) { + else if (flags & 64 /* Readonly */) { return grammarErrorOnNode(lastReadonly, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "readonly"); } return false; } - else if ((node.kind === 244 || node.kind === 243) && flags & 2) { + else if ((node.kind === 244 /* ImportDeclaration */ || node.kind === 243 /* ImportEqualsDeclaration */) && flags & 2 /* Ambient */) { return grammarErrorOnNode(lastDeclare, ts.Diagnostics.A_0_modifier_cannot_be_used_with_an_import_declaration, "declare"); } - else if (node.kind === 149 && (flags & 92) && ts.isBindingPattern(node.name)) { + else if (node.kind === 149 /* Parameter */ && (flags & 92 /* ParameterPropertyModifier */) && ts.isBindingPattern(node.name)) { return grammarErrorOnNode(node, ts.Diagnostics.A_parameter_property_may_not_be_declared_using_a_binding_pattern); } - else if (node.kind === 149 && (flags & 92) && node.dotDotDotToken) { + else if (node.kind === 149 /* Parameter */ && (flags & 92 /* ParameterPropertyModifier */) && node.dotDotDotToken) { return grammarErrorOnNode(node, ts.Diagnostics.A_parameter_property_cannot_be_declared_using_a_rest_parameter); } - if (flags & 256) { + if (flags & 256 /* Async */) { return checkGrammarAsyncModifier(node, lastAsync); } return false; } + /** + * true | false: Early return this value from checkGrammarModifiers. + * undefined: Need to do full checking on the modifiers. + */ function reportObviousModifierErrors(node) { return !node.modifiers ? false @@ -46503,38 +54212,38 @@ var ts; } function shouldReportBadModifier(node) { switch (node.kind) { - case 156: - case 157: - case 155: - case 152: - case 151: - case 154: - case 153: - case 160: - case 239: - case 244: - case 243: - case 250: - case 249: - case 192: - case 193: - case 149: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 155 /* Constructor */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 160 /* IndexSignature */: + case 239 /* ModuleDeclaration */: + case 244 /* ImportDeclaration */: + case 243 /* ImportEqualsDeclaration */: + case 250 /* ExportDeclaration */: + case 249 /* ExportAssignment */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 149 /* Parameter */: return false; default: - if (node.parent.kind === 240 || node.parent.kind === 274) { + if (node.parent.kind === 240 /* ModuleBlock */ || node.parent.kind === 274 /* SourceFile */) { return false; } switch (node.kind) { - case 234: - return nodeHasAnyModifiersExcept(node, 120); - case 235: - return nodeHasAnyModifiersExcept(node, 117); - case 236: - case 214: - case 237: + case 234 /* FunctionDeclaration */: + return nodeHasAnyModifiersExcept(node, 120 /* AsyncKeyword */); + case 235 /* ClassDeclaration */: + return nodeHasAnyModifiersExcept(node, 117 /* AbstractKeyword */); + case 236 /* InterfaceDeclaration */: + case 214 /* VariableStatement */: + case 237 /* TypeAliasDeclaration */: return true; - case 238: - return nodeHasAnyModifiersExcept(node, 76); + case 238 /* EnumDeclaration */: + return nodeHasAnyModifiersExcept(node, 76 /* ConstKeyword */); default: ts.Debug.fail(); return false; @@ -46546,10 +54255,10 @@ var ts; } function checkGrammarAsyncModifier(node, asyncModifier) { switch (node.kind) { - case 154: - case 234: - case 192: - case 193: + case 154 /* MethodDeclaration */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: return false; } return grammarErrorOnNode(asyncModifier, ts.Diagnostics._0_modifier_cannot_be_used_here, "async"); @@ -46578,7 +54287,7 @@ var ts; if (i !== (parameterCount - 1)) { return grammarErrorOnNode(parameter.dotDotDotToken, ts.Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list); } - if (!(parameter.flags & 4194304)) { + if (!(parameter.flags & 4194304 /* Ambient */)) { // Allow `...foo,` in ambient declarations; see GH#23070 checkGrammarForDisallowedTrailingComma(parameters, ts.Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma); } if (ts.isBindingPattern(parameter.name)) { @@ -46603,6 +54312,7 @@ var ts; } } function checkGrammarFunctionLikeDeclaration(node) { + // Prevent cascading error by short-circuit var file = ts.getSourceFileOfNode(node); return checkGrammarDecoratorsAndModifiers(node) || checkGrammarTypeParameterList(node.typeParameters, file) || checkGrammarParameterList(node.parameters) || checkGrammarArrowFunction(node, file); @@ -46645,12 +54355,12 @@ var ts; if (!parameter.type) { return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_must_have_a_type_annotation); } - if (parameter.type.kind !== 137 && parameter.type.kind !== 134) { + if (parameter.type.kind !== 137 /* StringKeyword */ && parameter.type.kind !== 134 /* NumberKeyword */) { var type = getTypeFromTypeNode(parameter.type); - if (type.flags & 4 || type.flags & 8) { + if (type.flags & 4 /* String */ || type.flags & 8 /* Number */) { return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_type_cannot_be_a_type_alias_Consider_writing_0_Colon_1_Colon_2_instead, ts.getTextOfNode(parameter.name), typeToString(type), typeToString(getTypeFromTypeNode(node.type))); } - if (type.flags & 262144 && allTypesAssignableToKind(type, 64, true)) { + if (type.flags & 262144 /* Union */ && allTypesAssignableToKind(type, 64 /* StringLiteral */, /*strict*/ true)) { return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_type_cannot_be_a_union_type_Consider_using_a_mapped_object_type_instead); } return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_type_must_be_string_or_number); @@ -46661,6 +54371,7 @@ var ts; return false; } function checkGrammarIndexSignature(node) { + // Prevent cascading error by short-circuit return checkGrammarDecoratorsAndModifiers(node) || checkGrammarIndexSignatureParameters(node); } function checkGrammarForAtLeastOneTypeArgument(node, typeArguments) { @@ -46680,7 +54391,7 @@ var ts; if (args) { for (var _i = 0, args_5 = args; _i < args_5.length; _i++) { var arg = args_5[_i]; - if (arg.kind === 206) { + if (arg.kind === 206 /* OmittedExpression */) { return grammarErrorAtPos(arg, arg.pos, 0, ts.Diagnostics.Argument_expression_expected); } } @@ -46710,7 +54421,7 @@ var ts; if (!checkGrammarDecoratorsAndModifiers(node) && node.heritageClauses) { for (var _i = 0, _a = node.heritageClauses; _i < _a.length; _i++) { var heritageClause = _a[_i]; - if (heritageClause.token === 85) { + if (heritageClause.token === 85 /* ExtendsKeyword */) { if (seenExtendsClause) { return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.extends_clause_already_seen); } @@ -46723,12 +54434,13 @@ var ts; seenExtendsClause = true; } else { - ts.Debug.assert(heritageClause.token === 108); + ts.Debug.assert(heritageClause.token === 108 /* ImplementsKeyword */); if (seenImplementsClause) { return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.implements_clause_already_seen); } seenImplementsClause = true; } + // Grammar checking heritageClause inside class declaration checkGrammarHeritageClause(heritageClause); } } @@ -46738,37 +54450,39 @@ var ts; if (node.heritageClauses) { for (var _i = 0, _a = node.heritageClauses; _i < _a.length; _i++) { var heritageClause = _a[_i]; - if (heritageClause.token === 85) { + if (heritageClause.token === 85 /* ExtendsKeyword */) { if (seenExtendsClause) { return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.extends_clause_already_seen); } seenExtendsClause = true; } else { - ts.Debug.assert(heritageClause.token === 108); + ts.Debug.assert(heritageClause.token === 108 /* ImplementsKeyword */); return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.Interface_declaration_cannot_have_implements_clause); } + // Grammar checking heritageClause inside class declaration checkGrammarHeritageClause(heritageClause); } } return false; } function checkGrammarComputedPropertyName(node) { - if (node.kind !== 147) { + // If node is not a computedPropertyName, just skip the grammar checking + if (node.kind !== 147 /* ComputedPropertyName */) { return false; } var computedPropertyName = node; - if (computedPropertyName.expression.kind === 200 && computedPropertyName.expression.operatorToken.kind === 26) { + if (computedPropertyName.expression.kind === 200 /* BinaryExpression */ && computedPropertyName.expression.operatorToken.kind === 26 /* CommaToken */) { return grammarErrorOnNode(computedPropertyName.expression, ts.Diagnostics.A_comma_expression_is_not_allowed_in_a_computed_property_name); } return false; } function checkGrammarForGenerator(node) { if (node.asteriskToken) { - ts.Debug.assert(node.kind === 234 || - node.kind === 192 || - node.kind === 154); - if (node.flags & 4194304) { + ts.Debug.assert(node.kind === 234 /* FunctionDeclaration */ || + node.kind === 192 /* FunctionExpression */ || + node.kind === 154 /* MethodDeclaration */); + if (node.flags & 4194304 /* Ambient */) { return grammarErrorOnNode(node.asteriskToken, ts.Diagnostics.Generators_are_not_allowed_in_an_ambient_context); } if (!node.body) { @@ -46790,40 +54504,54 @@ var ts; var seen = ts.createUnderscoreEscapedMap(); for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { var prop = _a[_i]; - if (prop.kind === 272) { + if (prop.kind === 272 /* SpreadAssignment */) { continue; } var name = prop.name; - if (name.kind === 147) { + if (name.kind === 147 /* ComputedPropertyName */) { + // If the name is not a ComputedPropertyName, the grammar checking will skip it checkGrammarComputedPropertyName(name); } - if (prop.kind === 271 && !inDestructuring && prop.objectAssignmentInitializer) { + if (prop.kind === 271 /* ShorthandPropertyAssignment */ && !inDestructuring && prop.objectAssignmentInitializer) { + // having objectAssignmentInitializer is only valid in ObjectAssignmentPattern + // outside of destructuring it is a syntax error return grammarErrorOnNode(prop.equalsToken, ts.Diagnostics.can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment); } + // Modifiers are never allowed on properties except for 'async' on a method declaration if (prop.modifiers) { - for (var _b = 0, _c = prop.modifiers; _b < _c.length; _b++) { + for (var _b = 0, _c = prop.modifiers; _b < _c.length; _b++) { // TODO: GH#19955 var mod = _c[_b]; - if (mod.kind !== 120 || prop.kind !== 154) { + if (mod.kind !== 120 /* AsyncKeyword */ || prop.kind !== 154 /* MethodDeclaration */) { grammarErrorOnNode(mod, ts.Diagnostics._0_modifier_cannot_be_used_here, ts.getTextOfNode(mod)); } } } + // ECMA-262 11.1.5 Object Initializer + // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true + // a.This production is contained in strict code and IsDataDescriptor(previous) is true and + // IsDataDescriptor(propId.descriptor) is true. + // b.IsDataDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true. + // c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(propId.descriptor) is true. + // d.IsAccessorDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true + // and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields var currentKind = void 0; switch (prop.kind) { - case 270: - case 271: + case 270 /* PropertyAssignment */: + case 271 /* ShorthandPropertyAssignment */: + // Grammar checking for computedPropertyName and shorthandPropertyAssignment checkGrammarForInvalidQuestionMark(prop.questionToken, ts.Diagnostics.An_object_member_cannot_be_declared_optional); - if (name.kind === 8) { + if (name.kind === 8 /* NumericLiteral */) { checkGrammarNumericLiteral(name); } - case 154: - currentKind = 1; + // falls through + case 154 /* MethodDeclaration */: + currentKind = 1 /* Property */; break; - case 156: - currentKind = 2; + case 156 /* GetAccessor */: + currentKind = 2 /* GetAccessor */; break; - case 157: - currentKind = 4; + case 157 /* SetAccessor */: + currentKind = 4 /* SetAccessor */; break; default: throw ts.Debug.assertNever(prop, "Unexpected syntax kind:" + prop.kind); @@ -46837,11 +54565,11 @@ var ts; seen.set(effectiveName, currentKind); } else { - if (currentKind === 1 && existingKind === 1) { + if (currentKind === 1 /* Property */ && existingKind === 1 /* Property */) { grammarErrorOnNode(name, ts.Diagnostics.Duplicate_identifier_0, ts.getTextOfNode(name)); } - else if ((currentKind & 6) && (existingKind & 6)) { - if (existingKind !== 6 && currentKind !== existingKind) { + else if ((currentKind & 6 /* GetOrSetAccessor */) && (existingKind & 6 /* GetOrSetAccessor */)) { + if (existingKind !== 6 /* GetOrSetAccessor */ && currentKind !== existingKind) { seen.set(effectiveName, currentKind | existingKind); } else { @@ -46859,7 +54587,7 @@ var ts; var seen = ts.createUnderscoreEscapedMap(); for (var _i = 0, _a = node.attributes.properties; _i < _a.length; _i++) { var attr = _a[_i]; - if (attr.kind === 264) { + if (attr.kind === 264 /* JsxSpreadAttribute */) { continue; } var name = attr.name, initializer = attr.initializer; @@ -46869,7 +54597,7 @@ var ts; else { return grammarErrorOnNode(name, ts.Diagnostics.JSX_elements_cannot_have_multiple_attributes_with_the_same_name); } - if (initializer && initializer.kind === 265 && !initializer.expression) { + if (initializer && initializer.kind === 265 /* JsxExpression */ && !initializer.expression) { return grammarErrorOnNode(initializer, ts.Diagnostics.JSX_attributes_must_only_be_assigned_a_non_empty_expression); } } @@ -46878,33 +54606,40 @@ var ts; if (checkGrammarStatementInAmbientContext(forInOrOfStatement)) { return true; } - if (forInOrOfStatement.kind === 222 && forInOrOfStatement.awaitModifier) { - if ((forInOrOfStatement.flags & 16384) === 0) { + if (forInOrOfStatement.kind === 222 /* ForOfStatement */ && forInOrOfStatement.awaitModifier) { + if ((forInOrOfStatement.flags & 16384 /* AwaitContext */) === 0 /* None */) { return grammarErrorOnNode(forInOrOfStatement.awaitModifier, ts.Diagnostics.A_for_await_of_statement_is_only_allowed_within_an_async_function_or_async_generator); } } - if (forInOrOfStatement.initializer.kind === 233) { + if (forInOrOfStatement.initializer.kind === 233 /* VariableDeclarationList */) { var variableList = forInOrOfStatement.initializer; if (!checkGrammarVariableDeclarationList(variableList)) { var declarations = variableList.declarations; + // declarations.length can be zero if there is an error in variable declaration in for-of or for-in + // See http://www.ecma-international.org/ecma-262/6.0/#sec-for-in-and-for-of-statements for details + // For example: + // var let = 10; + // for (let of [1,2,3]) {} // this is invalid ES6 syntax + // for (let in [1,2,3]) {} // this is invalid ES6 syntax + // We will then want to skip on grammar checking on variableList declaration if (!declarations.length) { return false; } if (declarations.length > 1) { - var diagnostic = forInOrOfStatement.kind === 221 + var diagnostic = forInOrOfStatement.kind === 221 /* ForInStatement */ ? ts.Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement : ts.Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement; return grammarErrorOnFirstToken(variableList.declarations[1], diagnostic); } var firstDeclaration = declarations[0]; if (firstDeclaration.initializer) { - var diagnostic = forInOrOfStatement.kind === 221 + var diagnostic = forInOrOfStatement.kind === 221 /* ForInStatement */ ? ts.Diagnostics.The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer : ts.Diagnostics.The_variable_declaration_of_a_for_of_statement_cannot_have_an_initializer; return grammarErrorOnNode(firstDeclaration.name, diagnostic); } if (firstDeclaration.type) { - var diagnostic = forInOrOfStatement.kind === 221 + var diagnostic = forInOrOfStatement.kind === 221 /* ForInStatement */ ? ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation : ts.Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_use_a_type_annotation; return grammarErrorOnNode(firstDeclaration, diagnostic); @@ -46915,27 +54650,27 @@ var ts; } function checkGrammarAccessor(accessor) { var kind = accessor.kind; - if (languageVersion < 1) { + if (languageVersion < 1 /* ES5 */) { return grammarErrorOnNode(accessor.name, ts.Diagnostics.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher); } - else if (accessor.flags & 4194304) { + else if (accessor.flags & 4194304 /* Ambient */) { return grammarErrorOnNode(accessor.name, ts.Diagnostics.An_accessor_cannot_be_declared_in_an_ambient_context); } - else if (accessor.body === undefined && !ts.hasModifier(accessor, 128)) { + else if (accessor.body === undefined && !ts.hasModifier(accessor, 128 /* Abstract */)) { return grammarErrorAtPos(accessor, accessor.end - 1, ";".length, ts.Diagnostics._0_expected, "{"); } - else if (accessor.body && ts.hasModifier(accessor, 128)) { + else if (accessor.body && ts.hasModifier(accessor, 128 /* Abstract */)) { return grammarErrorOnNode(accessor, ts.Diagnostics.An_abstract_accessor_cannot_have_an_implementation); } else if (accessor.typeParameters) { return grammarErrorOnNode(accessor.name, ts.Diagnostics.An_accessor_cannot_have_type_parameters); } else if (!doesAccessorHaveCorrectParameterCount(accessor)) { - return grammarErrorOnNode(accessor.name, kind === 156 ? + return grammarErrorOnNode(accessor.name, kind === 156 /* GetAccessor */ ? ts.Diagnostics.A_get_accessor_cannot_have_parameters : ts.Diagnostics.A_set_accessor_must_have_exactly_one_parameter); } - else if (kind === 157) { + else if (kind === 157 /* SetAccessor */) { if (accessor.type) { return grammarErrorOnNode(accessor.name, ts.Diagnostics.A_set_accessor_cannot_have_a_return_type_annotation); } @@ -46954,41 +54689,45 @@ var ts; } return false; } + /** Does the accessor have the right number of parameters? + * A get accessor has no parameters or a single `this` parameter. + * A set accessor has one parameter or a `this` parameter and one more parameter. + */ function doesAccessorHaveCorrectParameterCount(accessor) { - return getAccessorThisParameter(accessor) || accessor.parameters.length === (accessor.kind === 156 ? 0 : 1); + return getAccessorThisParameter(accessor) || accessor.parameters.length === (accessor.kind === 156 /* GetAccessor */ ? 0 : 1); } function getAccessorThisParameter(accessor) { - if (accessor.parameters.length === (accessor.kind === 156 ? 1 : 2)) { + if (accessor.parameters.length === (accessor.kind === 156 /* GetAccessor */ ? 1 : 2)) { return ts.getThisParameter(accessor); } } function checkGrammarTypeOperatorNode(node) { - if (node.operator === 141) { - if (node.type.kind !== 138) { - return grammarErrorOnNode(node.type, ts.Diagnostics._0_expected, ts.tokenToString(138)); + if (node.operator === 141 /* UniqueKeyword */) { + if (node.type.kind !== 138 /* SymbolKeyword */) { + return grammarErrorOnNode(node.type, ts.Diagnostics._0_expected, ts.tokenToString(138 /* SymbolKeyword */)); } var parent = ts.walkUpParenthesizedTypes(node.parent); switch (parent.kind) { - case 232: + case 232 /* VariableDeclaration */: var decl = parent; - if (decl.name.kind !== 71) { + if (decl.name.kind !== 71 /* Identifier */) { return grammarErrorOnNode(node, ts.Diagnostics.unique_symbol_types_may_not_be_used_on_a_variable_declaration_with_a_binding_name); } if (!ts.isVariableDeclarationInVariableStatement(decl)) { return grammarErrorOnNode(node, ts.Diagnostics.unique_symbol_types_are_only_allowed_on_variables_in_a_variable_statement); } - if (!(decl.parent.flags & 2)) { + if (!(decl.parent.flags & 2 /* Const */)) { return grammarErrorOnNode(parent.name, ts.Diagnostics.A_variable_whose_type_is_a_unique_symbol_type_must_be_const); } break; - case 152: - if (!ts.hasModifier(parent, 32) || - !ts.hasModifier(parent, 64)) { + case 152 /* PropertyDeclaration */: + if (!ts.hasModifier(parent, 32 /* Static */) || + !ts.hasModifier(parent, 64 /* Readonly */)) { return grammarErrorOnNode(parent.name, ts.Diagnostics.A_property_of_a_class_whose_type_is_a_unique_symbol_type_must_be_both_static_and_readonly); } break; - case 151: - if (!ts.hasModifier(parent, 64)) { + case 151 /* PropertySignature */: + if (!ts.hasModifier(parent, 64 /* Readonly */)) { return grammarErrorOnNode(parent.name, ts.Diagnostics.A_property_of_an_interface_or_type_literal_whose_type_is_a_unique_symbol_type_must_be_readonly); } break; @@ -47006,9 +54745,10 @@ var ts; if (checkGrammarFunctionLikeDeclaration(node)) { return true; } - if (node.kind === 154) { - if (node.parent.kind === 184) { - if (node.modifiers && !(node.modifiers.length === 1 && ts.first(node.modifiers).kind === 120)) { + if (node.kind === 154 /* MethodDeclaration */) { + if (node.parent.kind === 184 /* ObjectLiteralExpression */) { + // We only disallow modifier on a method declaration if it is a property of object-literal-expression + if (node.modifiers && !(node.modifiers.length === 1 && ts.first(node.modifiers).kind === 120 /* AsyncKeyword */)) { return grammarErrorOnFirstToken(node, ts.Diagnostics.Modifiers_cannot_appear_here); } else if (checkGrammarForInvalidQuestionMark(node.questionToken, ts.Diagnostics.An_object_member_cannot_be_declared_optional)) { @@ -47023,17 +54763,22 @@ var ts; } } if (ts.isClassLike(node.parent)) { - if (node.flags & 4194304) { + // Technically, computed properties in ambient contexts is disallowed + // for property declarations and accessors too, not just methods. + // However, property declarations disallow computed names in general, + // and accessors are not allowed in ambient contexts in general, + // so this error only really matters for methods. + if (node.flags & 4194304 /* Ambient */) { return checkGrammarForInvalidDynamicName(node.name, ts.Diagnostics.A_computed_property_name_in_an_ambient_context_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type); } - else if (node.kind === 154 && !node.body) { + else if (node.kind === 154 /* MethodDeclaration */ && !node.body) { return checkGrammarForInvalidDynamicName(node.name, ts.Diagnostics.A_computed_property_name_in_a_method_overload_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type); } } - else if (node.parent.kind === 236) { + else if (node.parent.kind === 236 /* InterfaceDeclaration */) { return checkGrammarForInvalidDynamicName(node.name, ts.Diagnostics.A_computed_property_name_in_an_interface_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type); } - else if (node.parent.kind === 166) { + else if (node.parent.kind === 166 /* TypeLiteral */) { return checkGrammarForInvalidDynamicName(node.name, ts.Diagnostics.A_computed_property_name_in_a_type_literal_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type); } } @@ -47044,23 +54789,27 @@ var ts; return grammarErrorOnNode(node, ts.Diagnostics.Jump_target_cannot_cross_function_boundary); } switch (current.kind) { - case 228: + case 228 /* LabeledStatement */: if (node.label && current.label.escapedText === node.label.escapedText) { - var isMisplacedContinueLabel = node.kind === 223 - && !ts.isIterationStatement(current.statement, true); + // found matching label - verify that label usage is correct + // continue can only target labels that are on iteration statements + var isMisplacedContinueLabel = node.kind === 223 /* ContinueStatement */ + && !ts.isIterationStatement(current.statement, /*lookInLabeledStatement*/ true); if (isMisplacedContinueLabel) { return grammarErrorOnNode(node, ts.Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement); } return false; } break; - case 227: - if (node.kind === 224 && !node.label) { + case 227 /* SwitchStatement */: + if (node.kind === 224 /* BreakStatement */ && !node.label) { + // unlabeled break within switch statement - ok return false; } break; default: - if (ts.isIterationStatement(current, false) && !node.label) { + if (ts.isIterationStatement(current, /*lookInLabeledStatement*/ false) && !node.label) { + // unlabeled break or continue within iteration statement - ok return false; } break; @@ -47068,13 +54817,13 @@ var ts; current = current.parent; } if (node.label) { - var message = node.kind === 224 + var message = node.kind === 224 /* BreakStatement */ ? ts.Diagnostics.A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement : ts.Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement; return grammarErrorOnNode(node, message); } else { - var message = node.kind === 224 + var message = node.kind === 224 /* BreakStatement */ ? ts.Diagnostics.A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement : ts.Diagnostics.A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement; return grammarErrorOnNode(node, message); @@ -47087,25 +54836,26 @@ var ts; return grammarErrorOnNode(node, ts.Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern); } checkGrammarForDisallowedTrailingComma(elements, ts.Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma); - if (node.name.kind === 181 || node.name.kind === 180) { + if (node.name.kind === 181 /* ArrayBindingPattern */ || node.name.kind === 180 /* ObjectBindingPattern */) { return grammarErrorOnNode(node.name, ts.Diagnostics.A_rest_element_cannot_contain_a_binding_pattern); } if (node.propertyName) { return grammarErrorOnNode(node.name, ts.Diagnostics.A_rest_element_cannot_have_a_property_name); } if (node.initializer) { + // Error on equals token which immediately precedes the initializer return grammarErrorAtPos(node, node.initializer.pos - 1, 1, ts.Diagnostics.A_rest_element_cannot_have_an_initializer); } } } function isStringOrNumberLiteralExpression(expr) { - return expr.kind === 9 || expr.kind === 8 || - expr.kind === 198 && expr.operator === 38 && - expr.operand.kind === 8; + return expr.kind === 9 /* StringLiteral */ || expr.kind === 8 /* NumericLiteral */ || + expr.kind === 198 /* PrefixUnaryExpression */ && expr.operator === 38 /* MinusToken */ && + expr.operand.kind === 8 /* NumericLiteral */; } function checkGrammarVariableDeclaration(node) { - if (node.parent.parent.kind !== 221 && node.parent.parent.kind !== 222) { - if (node.flags & 4194304) { + if (node.parent.parent.kind !== 221 /* ForInStatement */ && node.parent.parent.kind !== 222 /* ForOfStatement */) { + if (node.flags & 4194304 /* Ambient */) { if (node.initializer) { if (ts.isConst(node) && !node.type) { if (!isStringOrNumberLiteralExpression(node.initializer)) { @@ -47113,11 +54863,13 @@ var ts; } } else { + // Error on equals token which immediate precedes the initializer var equalsTokenLength = "=".length; return grammarErrorAtPos(node, node.initializer.pos - equalsTokenLength, equalsTokenLength, ts.Diagnostics.Initializers_are_not_allowed_in_ambient_contexts); } } if (node.initializer && !(ts.isConst(node) && isStringOrNumberLiteralExpression(node.initializer))) { + // Error on equals token which immediate precedes the initializer var equalsTokenLength = "=".length; return grammarErrorAtPos(node, node.initializer.pos - equalsTokenLength, equalsTokenLength, ts.Diagnostics.Initializers_are_not_allowed_in_ambient_contexts); } @@ -47131,18 +54883,24 @@ var ts; } } } - if (node.exclamationToken && (node.parent.parent.kind !== 214 || !node.type || node.initializer || node.flags & 4194304)) { + if (node.exclamationToken && (node.parent.parent.kind !== 214 /* VariableStatement */ || !node.type || node.initializer || node.flags & 4194304 /* Ambient */)) { return grammarErrorOnNode(node.exclamationToken, ts.Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context); } if (compilerOptions.module !== ts.ModuleKind.ES2015 && compilerOptions.module !== ts.ModuleKind.ESNext && compilerOptions.module !== ts.ModuleKind.System && !compilerOptions.noEmit && - !(node.parent.parent.flags & 4194304) && ts.hasModifier(node.parent.parent, 1)) { + !(node.parent.parent.flags & 4194304 /* Ambient */) && ts.hasModifier(node.parent.parent, 1 /* Export */)) { checkESModuleMarker(node.name); } var checkLetConstNames = (ts.isLet(node) || ts.isConst(node)); + // 1. LexicalDeclaration : LetOrConst BindingList ; + // It is a Syntax Error if the BoundNames of BindingList contains "let". + // 2. ForDeclaration: ForDeclaration : LetOrConst ForBinding + // It is a Syntax Error if the BoundNames of ForDeclaration contains "let". + // It is a SyntaxError if a VariableDeclaration or VariableDeclarationNoIn occurs within strict code + // and its Identifier is eval or arguments return checkLetConstNames && checkGrammarNameInLetOrConstDeclarations(node.name); } function checkESModuleMarker(name) { - if (name.kind === 71) { + if (name.kind === 71 /* Identifier */) { if (ts.idText(name) === "__esModule") { return grammarErrorOnNode(name, ts.Diagnostics.Identifier_expected_esModule_is_reserved_as_an_exported_marker_when_transforming_ECMAScript_modules); } @@ -47159,8 +54917,8 @@ var ts; return false; } function checkGrammarNameInLetOrConstDeclarations(name) { - if (name.kind === 71) { - if (name.originalKeywordKind === 110) { + if (name.kind === 71 /* Identifier */) { + if (name.originalKeywordKind === 110 /* LetKeyword */) { return grammarErrorOnNode(name, ts.Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations); } } @@ -47187,15 +54945,15 @@ var ts; } function allowLetAndConstDeclarations(parent) { switch (parent.kind) { - case 217: - case 218: - case 219: - case 226: - case 220: - case 221: - case 222: + case 217 /* IfStatement */: + case 218 /* DoStatement */: + case 219 /* WhileStatement */: + case 226 /* WithStatement */: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: return false; - case 228: + case 228 /* LabeledStatement */: return allowLetAndConstDeclarations(parent.parent); } return true; @@ -47213,12 +54971,12 @@ var ts; function checkGrammarMetaProperty(node) { var escapedText = node.name.escapedText; switch (node.keywordToken) { - case 94: + case 94 /* NewKeyword */: if (escapedText !== "target") { return grammarErrorOnNode(node.name, ts.Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, node.name.escapedText, ts.tokenToString(node.keywordToken), "target"); } break; - case 91: + case 91 /* ImportKeyword */: if (escapedText !== "meta") { return grammarErrorOnNode(node.name, ts.Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, node.name.escapedText, ts.tokenToString(node.keywordToken), "meta"); } @@ -47272,7 +55030,7 @@ var ts; return true; } } - else if (node.parent.kind === 236) { + else if (node.parent.kind === 236 /* InterfaceDeclaration */) { if (checkGrammarForInvalidDynamicName(node.name, ts.Diagnostics.A_computed_property_name_in_an_interface_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type)) { return true; } @@ -47280,7 +55038,7 @@ var ts; return grammarErrorOnNode(node.initializer, ts.Diagnostics.An_interface_property_cannot_have_an_initializer); } } - else if (node.parent.kind === 166) { + else if (node.parent.kind === 166 /* TypeLiteral */) { if (checkGrammarForInvalidDynamicName(node.name, ts.Diagnostics.A_computed_property_name_in_a_type_literal_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type)) { return true; } @@ -47288,23 +55046,35 @@ var ts; return grammarErrorOnNode(node.initializer, ts.Diagnostics.A_type_literal_property_cannot_have_an_initializer); } } - if (node.flags & 4194304 && node.initializer) { + if (node.flags & 4194304 /* Ambient */ && node.initializer) { return grammarErrorOnFirstToken(node.initializer, ts.Diagnostics.Initializers_are_not_allowed_in_ambient_contexts); } if (ts.isPropertyDeclaration(node) && node.exclamationToken && (!ts.isClassLike(node.parent) || !node.type || node.initializer || - node.flags & 4194304 || ts.hasModifier(node, 32 | 128))) { + node.flags & 4194304 /* Ambient */ || ts.hasModifier(node, 32 /* Static */ | 128 /* Abstract */))) { return grammarErrorOnNode(node.exclamationToken, ts.Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context); } } function checkGrammarTopLevelElementForRequiredDeclareModifier(node) { - if (node.kind === 236 || - node.kind === 237 || - node.kind === 244 || - node.kind === 243 || - node.kind === 250 || - node.kind === 249 || - node.kind === 242 || - ts.hasModifier(node, 2 | 1 | 512)) { + // A declare modifier is required for any top level .d.ts declaration except export=, export default, export as namespace + // interfaces and imports categories: + // + // DeclarationElement: + // ExportAssignment + // export_opt InterfaceDeclaration + // export_opt TypeAliasDeclaration + // export_opt ImportDeclaration + // export_opt ExternalImportDeclaration + // export_opt AmbientDeclaration + // + // TODO: The spec needs to be amended to reflect this grammar. + if (node.kind === 236 /* InterfaceDeclaration */ || + node.kind === 237 /* TypeAliasDeclaration */ || + node.kind === 244 /* ImportDeclaration */ || + node.kind === 243 /* ImportEqualsDeclaration */ || + node.kind === 250 /* ExportDeclaration */ || + node.kind === 249 /* ExportAssignment */ || + node.kind === 242 /* NamespaceExportDeclaration */ || + ts.hasModifier(node, 2 /* Ambient */ | 1 /* Export */ | 512 /* Default */)) { return false; } return grammarErrorOnFirstToken(node, ts.Diagnostics.A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file); @@ -47312,7 +55082,7 @@ var ts; function checkGrammarTopLevelElementsForRequiredDeclareModifier(file) { for (var _i = 0, _a = file.statements; _i < _a.length; _i++) { var decl = _a[_i]; - if (ts.isDeclaration(decl) || decl.kind === 214) { + if (ts.isDeclaration(decl) || decl.kind === 214 /* VariableStatement */) { if (checkGrammarTopLevelElementForRequiredDeclareModifier(decl)) { return true; } @@ -47321,42 +55091,54 @@ var ts; return false; } function checkGrammarSourceFile(node) { - return !!(node.flags & 4194304) && checkGrammarTopLevelElementsForRequiredDeclareModifier(node); + return !!(node.flags & 4194304 /* Ambient */) && checkGrammarTopLevelElementsForRequiredDeclareModifier(node); } function checkGrammarStatementInAmbientContext(node) { - if (node.flags & 4194304) { + if (node.flags & 4194304 /* Ambient */) { + // An accessors is already reported about the ambient context if (ts.isAccessor(node.parent)) { return getNodeLinks(node).hasReportedStatementInAmbientContext = true; } + // Find containing block which is either Block, ModuleBlock, SourceFile var links = getNodeLinks(node); if (!links.hasReportedStatementInAmbientContext && ts.isFunctionLike(node.parent)) { return getNodeLinks(node).hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, ts.Diagnostics.An_implementation_cannot_be_declared_in_ambient_contexts); } - if (node.parent.kind === 213 || node.parent.kind === 240 || node.parent.kind === 274) { + // We are either parented by another statement, or some sort of block. + // If we're in a block, we only want to really report an error once + // to prevent noisiness. So use a bit on the block to indicate if + // this has already been reported, and don't report if it has. + // + if (node.parent.kind === 213 /* Block */ || node.parent.kind === 240 /* ModuleBlock */ || node.parent.kind === 274 /* SourceFile */) { var links_1 = getNodeLinks(node.parent); + // Check if the containing block ever report this error if (!links_1.hasReportedStatementInAmbientContext) { return links_1.hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, ts.Diagnostics.Statements_are_not_allowed_in_ambient_contexts); } } else { + // We must be parented by a statement. If so, there's no need + // to report the error as our parent will have already done it. + // Debug.assert(isStatement(node.parent)); } } return false; } function checkGrammarNumericLiteral(node) { - if (node.numericLiteralFlags & 32) { + // Grammar checking + if (node.numericLiteralFlags & 32 /* Octal */) { var diagnosticMessage = void 0; - if (languageVersion >= 1) { + if (languageVersion >= 1 /* ES5 */) { diagnosticMessage = ts.Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher_Use_the_syntax_0; } - else if (ts.isChildOfNodeWithKind(node, 178)) { + else if (ts.isChildOfNodeWithKind(node, 178 /* LiteralType */)) { diagnosticMessage = ts.Diagnostics.Octal_literal_types_must_use_ES2015_syntax_Use_the_syntax_0; } - else if (ts.isChildOfNodeWithKind(node, 273)) { + else if (ts.isChildOfNodeWithKind(node, 273 /* EnumMember */)) { diagnosticMessage = ts.Diagnostics.Octal_literals_are_not_allowed_in_enums_members_initializer_Use_the_syntax_0; } if (diagnosticMessage) { - var withMinus = ts.isPrefixUnaryExpression(node.parent) && node.parent.operator === 38; + var withMinus = ts.isPrefixUnaryExpression(node.parent) && node.parent.operator === 38 /* MinusToken */; var literal = (withMinus ? "-" : "") + "0o" + node.text; return grammarErrorOnNode(withMinus ? node.parent : node, diagnosticMessage, literal); } @@ -47367,7 +55149,7 @@ var ts; var sourceFile = ts.getSourceFileOfNode(node); if (!hasParseDiagnostics(sourceFile)) { var span = ts.getSpanOfTokenAtPosition(sourceFile, node.pos); - diagnostics.add(ts.createFileDiagnostic(sourceFile, ts.textSpanEnd(span), 0, message, arg0, arg1, arg2)); + diagnostics.add(ts.createFileDiagnostic(sourceFile, ts.textSpanEnd(span), /*length*/ 0, message, arg0, arg1, arg2)); return true; } return false; @@ -47376,6 +55158,7 @@ var ts; if (!ambientModulesCache) { ambientModulesCache = []; globals.forEach(function (global, sym) { + // No need to `unescapeLeadingUnderscores`, an escaped symbol is never an ambient module. if (ambientModuleSymbolRegex.test(sym)) { ambientModulesCache.push(global); } @@ -47394,6 +55177,8 @@ var ts; if (nodeArguments.length !== 1) { return grammarErrorOnNode(node, ts.Diagnostics.Dynamic_import_must_have_one_specifier_as_an_argument); } + // see: parseArgumentOrArrayLiteralElement...we use this function which parse arguments of callExpression to parse specifier for dynamic import. + // parseArgumentOrArrayLiteralElement allows spread element to be in an argument list which is not allowed as specifier in dynamic import. if (ts.isSpreadElement(nodeArguments[0])) { return grammarErrorOnNode(nodeArguments[0], ts.Diagnostics.Specifier_of_dynamic_import_cannot_be_spread_element); } @@ -47401,10 +55186,11 @@ var ts; } } ts.createTypeChecker = createTypeChecker; + /** Like 'isDeclarationName', but returns true for LHS of `import { x as y }` or `export { x as y }`. */ function isDeclarationNameOrImportPropertyName(name) { switch (name.parent.kind) { - case 248: - case 252: + case 248 /* ImportSpecifier */: + case 252 /* ExportSpecifier */: return ts.isIdentifier(name); default: return ts.isDeclarationName(name); @@ -47412,36 +55198,40 @@ var ts; } function isSomeImportDeclaration(decl) { switch (decl.kind) { - case 245: - case 243: - case 246: - case 248: + case 245 /* ImportClause */: // For default import + case 243 /* ImportEqualsDeclaration */: + case 246 /* NamespaceImport */: + case 248 /* ImportSpecifier */: // For rename import `x as y` return true; - case 71: - return decl.parent.kind === 248; + case 71 /* Identifier */: + // For regular import, `decl` is an Identifier under the ImportSpecifier. + return decl.parent.kind === 248 /* ImportSpecifier */; default: return false; } } var JsxNames; (function (JsxNames) { + // tslint:disable variable-name JsxNames.JSX = "JSX"; JsxNames.IntrinsicElements = "IntrinsicElements"; JsxNames.ElementClass = "ElementClass"; - JsxNames.ElementAttributesPropertyNameContainer = "ElementAttributesProperty"; + JsxNames.ElementAttributesPropertyNameContainer = "ElementAttributesProperty"; // TODO: Deprecate and remove support JsxNames.ElementChildrenAttributeNameContainer = "ElementChildrenAttribute"; JsxNames.Element = "Element"; JsxNames.IntrinsicAttributes = "IntrinsicAttributes"; JsxNames.IntrinsicClassAttributes = "IntrinsicClassAttributes"; + // tslint:enable variable-name })(JsxNames || (JsxNames = {})); })(ts || (ts = {})); var ts; (function (ts) { function createSynthesizedNode(kind) { var node = ts.createNode(kind, -1, -1); - node.flags |= 8; + node.flags |= 8 /* Synthesized */; return node; } + /* @internal */ function updateNode(updated, original) { if (updated !== original) { setOriginalNode(updated, original); @@ -47451,6 +55241,9 @@ var ts; return updated; } ts.updateNode = updateNode; + /** + * Make `elements` into a `NodeArray`. If `elements` is `undefined`, returns an empty `NodeArray`. + */ function createNodeArray(elements, hasTrailingComma) { if (!elements || elements === ts.emptyArray) { elements = []; @@ -47465,7 +55258,14 @@ var ts; return array; } ts.createNodeArray = createNodeArray; + /** + * Creates a shallow, memberwise clone of a node with no source map location. + */ + /* @internal */ function getSynthesizedClone(node) { + // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of + // the original node. We also need to exclude specific properties and only include own- + // properties (to skip members already defined on the shared prototype). if (node === undefined) { return node; } @@ -47498,20 +55298,20 @@ var ts; } ts.createLiteral = createLiteral; function createNumericLiteral(value) { - var node = createSynthesizedNode(8); + var node = createSynthesizedNode(8 /* NumericLiteral */); node.text = value; node.numericLiteralFlags = 0; return node; } ts.createNumericLiteral = createNumericLiteral; function createStringLiteral(text) { - var node = createSynthesizedNode(9); + var node = createSynthesizedNode(9 /* StringLiteral */); node.text = text; return node; } ts.createStringLiteral = createStringLiteral; function createRegularExpressionLiteral(text) { - var node = createSynthesizedNode(12); + var node = createSynthesizedNode(12 /* RegularExpressionLiteral */); node.text = text; return node; } @@ -47522,10 +55322,10 @@ var ts; return node; } function createIdentifier(text, typeArguments) { - var node = createSynthesizedNode(71); + var node = createSynthesizedNode(71 /* Identifier */); node.escapedText = ts.escapeLeadingUnderscores(text); - node.originalKeywordKind = text ? ts.stringToToken(text) : 0; - node.autoGenerateFlags = 0; + node.originalKeywordKind = text ? ts.stringToToken(text) : 0 /* Unknown */; + node.autoGenerateFlags = 0 /* None */; node.autoGenerateId = 0; if (typeArguments) { node.typeArguments = createNodeArray(typeArguments); @@ -47542,29 +55342,31 @@ var ts; var nextAutoGenerateId = 0; function createTempVariable(recordTempVariable, reservedInNestedScopes) { var name = createIdentifier(""); - name.autoGenerateFlags = 1; + name.autoGenerateFlags = 1 /* Auto */; name.autoGenerateId = nextAutoGenerateId; nextAutoGenerateId++; if (recordTempVariable) { recordTempVariable(name); } if (reservedInNestedScopes) { - name.autoGenerateFlags |= 8; + name.autoGenerateFlags |= 8 /* ReservedInNestedScopes */; } return name; } ts.createTempVariable = createTempVariable; + /** Create a unique temporary variable for use in a loop. */ function createLoopVariable() { var name = createIdentifier(""); - name.autoGenerateFlags = 2; + name.autoGenerateFlags = 2 /* Loop */; name.autoGenerateId = nextAutoGenerateId; nextAutoGenerateId++; return name; } ts.createLoopVariable = createLoopVariable; + /** Create a unique name based on the supplied text. */ function createUniqueName(text) { var name = createIdentifier(text); - name.autoGenerateFlags = 3; + name.autoGenerateFlags = 3 /* Unique */; name.autoGenerateId = nextAutoGenerateId; nextAutoGenerateId++; return name; @@ -47572,95 +55374,100 @@ var ts; ts.createUniqueName = createUniqueName; function createOptimisticUniqueName(text) { var name = createIdentifier(text); - name.autoGenerateFlags = 3 | 16; + name.autoGenerateFlags = 3 /* Unique */ | 16 /* Optimistic */; name.autoGenerateId = nextAutoGenerateId; nextAutoGenerateId++; return name; } ts.createOptimisticUniqueName = createOptimisticUniqueName; + /** Create a unique name based on the supplied text. This does not consider names injected by the transformer. */ function createFileLevelUniqueName(text) { var name = createOptimisticUniqueName(text); - name.autoGenerateFlags |= 32; + name.autoGenerateFlags |= 32 /* FileLevel */; return name; } ts.createFileLevelUniqueName = createFileLevelUniqueName; function getGeneratedNameForNode(node, flags) { var name = createIdentifier(ts.isIdentifier(node) ? ts.idText(node) : ""); - name.autoGenerateFlags = 4 | flags; + name.autoGenerateFlags = 4 /* Node */ | flags; name.autoGenerateId = nextAutoGenerateId; name.original = node; nextAutoGenerateId++; return name; } ts.getGeneratedNameForNode = getGeneratedNameForNode; + // Punctuation function createToken(token) { return createSynthesizedNode(token); } ts.createToken = createToken; + // Reserved words function createSuper() { - return createSynthesizedNode(97); + return createSynthesizedNode(97 /* SuperKeyword */); } ts.createSuper = createSuper; function createThis() { - return createSynthesizedNode(99); + return createSynthesizedNode(99 /* ThisKeyword */); } ts.createThis = createThis; function createNull() { - return createSynthesizedNode(95); + return createSynthesizedNode(95 /* NullKeyword */); } ts.createNull = createNull; function createTrue() { - return createSynthesizedNode(101); + return createSynthesizedNode(101 /* TrueKeyword */); } ts.createTrue = createTrue; function createFalse() { - return createSynthesizedNode(86); + return createSynthesizedNode(86 /* FalseKeyword */); } ts.createFalse = createFalse; + // Modifiers function createModifier(kind) { return createToken(kind); } ts.createModifier = createModifier; function createModifiersFromModifierFlags(flags) { var result = []; - if (flags & 1) { - result.push(createModifier(84)); + if (flags & 1 /* Export */) { + result.push(createModifier(84 /* ExportKeyword */)); } - if (flags & 2) { - result.push(createModifier(124)); + if (flags & 2 /* Ambient */) { + result.push(createModifier(124 /* DeclareKeyword */)); } - if (flags & 512) { - result.push(createModifier(79)); + if (flags & 512 /* Default */) { + result.push(createModifier(79 /* DefaultKeyword */)); } - if (flags & 2048) { - result.push(createModifier(76)); + if (flags & 2048 /* Const */) { + result.push(createModifier(76 /* ConstKeyword */)); } - if (flags & 4) { - result.push(createModifier(114)); + if (flags & 4 /* Public */) { + result.push(createModifier(114 /* PublicKeyword */)); } - if (flags & 8) { - result.push(createModifier(112)); + if (flags & 8 /* Private */) { + result.push(createModifier(112 /* PrivateKeyword */)); } - if (flags & 16) { - result.push(createModifier(113)); + if (flags & 16 /* Protected */) { + result.push(createModifier(113 /* ProtectedKeyword */)); } - if (flags & 128) { - result.push(createModifier(117)); + if (flags & 128 /* Abstract */) { + result.push(createModifier(117 /* AbstractKeyword */)); } - if (flags & 32) { - result.push(createModifier(115)); + if (flags & 32 /* Static */) { + result.push(createModifier(115 /* StaticKeyword */)); } - if (flags & 64) { - result.push(createModifier(132)); + if (flags & 64 /* Readonly */) { + result.push(createModifier(132 /* ReadonlyKeyword */)); } - if (flags & 256) { - result.push(createModifier(120)); + if (flags & 256 /* Async */) { + result.push(createModifier(120 /* AsyncKeyword */)); } return result; } ts.createModifiersFromModifierFlags = createModifiersFromModifierFlags; + // Names function createQualifiedName(left, right) { - var node = createSynthesizedNode(146); + var node = createSynthesizedNode(146 /* QualifiedName */); node.left = left; node.right = asName(right); return node; @@ -47674,13 +55481,13 @@ var ts; } ts.updateQualifiedName = updateQualifiedName; function parenthesizeForComputedName(expression) { - return (ts.isBinaryExpression(expression) && expression.operatorToken.kind === 26) || - expression.kind === 303 ? + return (ts.isBinaryExpression(expression) && expression.operatorToken.kind === 26 /* CommaToken */) || + expression.kind === 303 /* CommaListExpression */ ? createParen(expression) : expression; } function createComputedPropertyName(expression) { - var node = createSynthesizedNode(147); + var node = createSynthesizedNode(147 /* ComputedPropertyName */); node.expression = parenthesizeForComputedName(expression); return node; } @@ -47691,8 +55498,9 @@ var ts; : node; } ts.updateComputedPropertyName = updateComputedPropertyName; + // Signature elements function createTypeParameterDeclaration(name, constraint, defaultType) { - var node = createSynthesizedNode(148); + var node = createSynthesizedNode(148 /* TypeParameter */); node.name = asName(name); node.constraint = constraint; node.default = defaultType; @@ -47708,7 +55516,7 @@ var ts; } ts.updateTypeParameterDeclaration = updateTypeParameterDeclaration; function createParameter(decorators, modifiers, dotDotDotToken, name, questionToken, type, initializer) { - var node = createSynthesizedNode(149); + var node = createSynthesizedNode(149 /* Parameter */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.dotDotDotToken = dotDotDotToken; @@ -47732,7 +55540,7 @@ var ts; } ts.updateParameter = updateParameter; function createDecorator(expression) { - var node = createSynthesizedNode(150); + var node = createSynthesizedNode(150 /* Decorator */); node.expression = ts.parenthesizeForAccess(expression); return node; } @@ -47743,8 +55551,9 @@ var ts; : node; } ts.updateDecorator = updateDecorator; + // Type Elements function createPropertySignature(modifiers, name, questionToken, type, initializer) { - var node = createSynthesizedNode(151); + var node = createSynthesizedNode(151 /* PropertySignature */); node.modifiers = asNodeArray(modifiers); node.name = asName(name); node.questionToken = questionToken; @@ -47764,12 +55573,12 @@ var ts; } ts.updatePropertySignature = updatePropertySignature; function createProperty(decorators, modifiers, name, questionOrExclamationToken, type, initializer) { - var node = createSynthesizedNode(152); + var node = createSynthesizedNode(152 /* PropertyDeclaration */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.name = asName(name); - node.questionToken = questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === 55 ? questionOrExclamationToken : undefined; - node.exclamationToken = questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === 51 ? questionOrExclamationToken : undefined; + node.questionToken = questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === 55 /* QuestionToken */ ? questionOrExclamationToken : undefined; + node.exclamationToken = questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === 51 /* ExclamationToken */ ? questionOrExclamationToken : undefined; node.type = type; node.initializer = initializer; return node; @@ -47779,8 +55588,8 @@ var ts; return node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name - || node.questionToken !== (questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === 55 ? questionOrExclamationToken : undefined) - || node.exclamationToken !== (questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === 51 ? questionOrExclamationToken : undefined) + || node.questionToken !== (questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === 55 /* QuestionToken */ ? questionOrExclamationToken : undefined) + || node.exclamationToken !== (questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === 51 /* ExclamationToken */ ? questionOrExclamationToken : undefined) || node.type !== type || node.initializer !== initializer ? updateNode(createProperty(decorators, modifiers, name, questionOrExclamationToken, type, initializer), node) @@ -47788,7 +55597,7 @@ var ts; } ts.updateProperty = updateProperty; function createMethodSignature(typeParameters, parameters, type, name, questionToken) { - var node = createSignatureDeclaration(153, typeParameters, parameters, type); + var node = createSignatureDeclaration(153 /* MethodSignature */, typeParameters, parameters, type); node.name = asName(name); node.questionToken = questionToken; return node; @@ -47805,7 +55614,7 @@ var ts; } ts.updateMethodSignature = updateMethodSignature; function createMethod(decorators, modifiers, asteriskToken, name, questionToken, typeParameters, parameters, type, body) { - var node = createSynthesizedNode(154); + var node = createSynthesizedNode(154 /* MethodDeclaration */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.asteriskToken = asteriskToken; @@ -47833,7 +55642,7 @@ var ts; } ts.updateMethod = updateMethod; function createConstructor(decorators, modifiers, parameters, body) { - var node = createSynthesizedNode(155); + var node = createSynthesizedNode(155 /* Constructor */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.typeParameters = undefined; @@ -47853,7 +55662,7 @@ var ts; } ts.updateConstructor = updateConstructor; function createGetAccessor(decorators, modifiers, name, parameters, type, body) { - var node = createSynthesizedNode(156); + var node = createSynthesizedNode(156 /* GetAccessor */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.name = asName(name); @@ -47876,7 +55685,7 @@ var ts; } ts.updateGetAccessor = updateGetAccessor; function createSetAccessor(decorators, modifiers, name, parameters, body) { - var node = createSynthesizedNode(157); + var node = createSynthesizedNode(157 /* SetAccessor */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.name = asName(name); @@ -47897,7 +55706,7 @@ var ts; } ts.updateSetAccessor = updateSetAccessor; function createCallSignature(typeParameters, parameters, type) { - return createSignatureDeclaration(158, typeParameters, parameters, type); + return createSignatureDeclaration(158 /* CallSignature */, typeParameters, parameters, type); } ts.createCallSignature = createCallSignature; function updateCallSignature(node, typeParameters, parameters, type) { @@ -47905,7 +55714,7 @@ var ts; } ts.updateCallSignature = updateCallSignature; function createConstructSignature(typeParameters, parameters, type) { - return createSignatureDeclaration(159, typeParameters, parameters, type); + return createSignatureDeclaration(159 /* ConstructSignature */, typeParameters, parameters, type); } ts.createConstructSignature = createConstructSignature; function updateConstructSignature(node, typeParameters, parameters, type) { @@ -47913,7 +55722,7 @@ var ts; } ts.updateConstructSignature = updateConstructSignature; function createIndexSignature(decorators, modifiers, parameters, type) { - var node = createSynthesizedNode(160); + var node = createSynthesizedNode(160 /* IndexSignature */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.parameters = createNodeArray(parameters); @@ -47930,6 +55739,7 @@ var ts; : node; } ts.updateIndexSignature = updateIndexSignature; + /* @internal */ function createSignatureDeclaration(kind, typeParameters, parameters, type, typeArguments) { var node = createSynthesizedNode(kind); node.typeParameters = asNodeArray(typeParameters); @@ -47946,12 +55756,13 @@ var ts; ? updateNode(createSignatureDeclaration(node.kind, typeParameters, parameters, type), node) : node; } + // Types function createKeywordTypeNode(kind) { return createSynthesizedNode(kind); } ts.createKeywordTypeNode = createKeywordTypeNode; function createTypePredicateNode(parameterName, type) { - var node = createSynthesizedNode(161); + var node = createSynthesizedNode(161 /* TypePredicate */); node.parameterName = asName(parameterName); node.type = type; return node; @@ -47965,7 +55776,7 @@ var ts; } ts.updateTypePredicateNode = updateTypePredicateNode; function createTypeReferenceNode(typeName, typeArguments) { - var node = createSynthesizedNode(162); + var node = createSynthesizedNode(162 /* TypeReference */); node.typeName = asName(typeName); node.typeArguments = typeArguments && ts.parenthesizeTypeParameters(typeArguments); return node; @@ -47979,7 +55790,7 @@ var ts; } ts.updateTypeReferenceNode = updateTypeReferenceNode; function createFunctionTypeNode(typeParameters, parameters, type) { - return createSignatureDeclaration(163, typeParameters, parameters, type); + return createSignatureDeclaration(163 /* FunctionType */, typeParameters, parameters, type); } ts.createFunctionTypeNode = createFunctionTypeNode; function updateFunctionTypeNode(node, typeParameters, parameters, type) { @@ -47987,7 +55798,7 @@ var ts; } ts.updateFunctionTypeNode = updateFunctionTypeNode; function createConstructorTypeNode(typeParameters, parameters, type) { - return createSignatureDeclaration(164, typeParameters, parameters, type); + return createSignatureDeclaration(164 /* ConstructorType */, typeParameters, parameters, type); } ts.createConstructorTypeNode = createConstructorTypeNode; function updateConstructorTypeNode(node, typeParameters, parameters, type) { @@ -47995,7 +55806,7 @@ var ts; } ts.updateConstructorTypeNode = updateConstructorTypeNode; function createTypeQueryNode(exprName) { - var node = createSynthesizedNode(165); + var node = createSynthesizedNode(165 /* TypeQuery */); node.exprName = exprName; return node; } @@ -48007,7 +55818,7 @@ var ts; } ts.updateTypeQueryNode = updateTypeQueryNode; function createTypeLiteralNode(members) { - var node = createSynthesizedNode(166); + var node = createSynthesizedNode(166 /* TypeLiteral */); node.members = createNodeArray(members); return node; } @@ -48019,7 +55830,7 @@ var ts; } ts.updateTypeLiteralNode = updateTypeLiteralNode; function createArrayTypeNode(elementType) { - var node = createSynthesizedNode(167); + var node = createSynthesizedNode(167 /* ArrayType */); node.elementType = ts.parenthesizeArrayTypeMember(elementType); return node; } @@ -48031,7 +55842,7 @@ var ts; } ts.updateArrayTypeNode = updateArrayTypeNode; function createTupleTypeNode(elementTypes) { - var node = createSynthesizedNode(168); + var node = createSynthesizedNode(168 /* TupleType */); node.elementTypes = createNodeArray(elementTypes); return node; } @@ -48043,7 +55854,7 @@ var ts; } ts.updateTypleTypeNode = updateTypleTypeNode; function createUnionTypeNode(types) { - return createUnionOrIntersectionTypeNode(169, types); + return createUnionOrIntersectionTypeNode(169 /* UnionType */, types); } ts.createUnionTypeNode = createUnionTypeNode; function updateUnionTypeNode(node, types) { @@ -48051,7 +55862,7 @@ var ts; } ts.updateUnionTypeNode = updateUnionTypeNode; function createIntersectionTypeNode(types) { - return createUnionOrIntersectionTypeNode(170, types); + return createUnionOrIntersectionTypeNode(170 /* IntersectionType */, types); } ts.createIntersectionTypeNode = createIntersectionTypeNode; function updateIntersectionTypeNode(node, types) { @@ -48070,7 +55881,7 @@ var ts; : node; } function createConditionalTypeNode(checkType, extendsType, trueType, falseType) { - var node = createSynthesizedNode(171); + var node = createSynthesizedNode(171 /* ConditionalType */); node.checkType = ts.parenthesizeConditionalTypeMember(checkType); node.extendsType = ts.parenthesizeConditionalTypeMember(extendsType); node.trueType = trueType; @@ -48088,7 +55899,7 @@ var ts; } ts.updateConditionalTypeNode = updateConditionalTypeNode; function createInferTypeNode(typeParameter) { - var node = createSynthesizedNode(172); + var node = createSynthesizedNode(172 /* InferType */); node.typeParameter = typeParameter; return node; } @@ -48100,7 +55911,7 @@ var ts; } ts.updateInferTypeNode = updateInferTypeNode; function createImportTypeNode(argument, qualifier, typeArguments, isTypeOf) { - var node = createSynthesizedNode(179); + var node = createSynthesizedNode(179 /* ImportType */); node.argument = argument; node.qualifier = qualifier; node.typeArguments = asNodeArray(typeArguments); @@ -48118,7 +55929,7 @@ var ts; } ts.updateImportTypeNode = updateImportTypeNode; function createParenthesizedType(type) { - var node = createSynthesizedNode(173); + var node = createSynthesizedNode(173 /* ParenthesizedType */); node.type = type; return node; } @@ -48130,12 +55941,12 @@ var ts; } ts.updateParenthesizedType = updateParenthesizedType; function createThisTypeNode() { - return createSynthesizedNode(174); + return createSynthesizedNode(174 /* ThisType */); } ts.createThisTypeNode = createThisTypeNode; function createTypeOperatorNode(operatorOrType, type) { - var node = createSynthesizedNode(175); - node.operator = typeof operatorOrType === "number" ? operatorOrType : 128; + var node = createSynthesizedNode(175 /* TypeOperator */); + node.operator = typeof operatorOrType === "number" ? operatorOrType : 128 /* KeyOfKeyword */; node.type = ts.parenthesizeElementTypeMember(typeof operatorOrType === "number" ? type : operatorOrType); return node; } @@ -48145,7 +55956,7 @@ var ts; } ts.updateTypeOperatorNode = updateTypeOperatorNode; function createIndexedAccessTypeNode(objectType, indexType) { - var node = createSynthesizedNode(176); + var node = createSynthesizedNode(176 /* IndexedAccessType */); node.objectType = ts.parenthesizeElementTypeMember(objectType); node.indexType = indexType; return node; @@ -48159,7 +55970,7 @@ var ts; } ts.updateIndexedAccessTypeNode = updateIndexedAccessTypeNode; function createMappedTypeNode(readonlyToken, typeParameter, questionToken, type) { - var node = createSynthesizedNode(177); + var node = createSynthesizedNode(177 /* MappedType */); node.readonlyToken = readonlyToken; node.typeParameter = typeParameter; node.questionToken = questionToken; @@ -48177,7 +55988,7 @@ var ts; } ts.updateMappedTypeNode = updateMappedTypeNode; function createLiteralTypeNode(literal) { - var node = createSynthesizedNode(178); + var node = createSynthesizedNode(178 /* LiteralType */); node.literal = literal; return node; } @@ -48188,8 +55999,9 @@ var ts; : node; } ts.updateLiteralTypeNode = updateLiteralTypeNode; + // Binding Patterns function createObjectBindingPattern(elements) { - var node = createSynthesizedNode(180); + var node = createSynthesizedNode(180 /* ObjectBindingPattern */); node.elements = createNodeArray(elements); return node; } @@ -48201,7 +56013,7 @@ var ts; } ts.updateObjectBindingPattern = updateObjectBindingPattern; function createArrayBindingPattern(elements) { - var node = createSynthesizedNode(181); + var node = createSynthesizedNode(181 /* ArrayBindingPattern */); node.elements = createNodeArray(elements); return node; } @@ -48213,7 +56025,7 @@ var ts; } ts.updateArrayBindingPattern = updateArrayBindingPattern; function createBindingElement(dotDotDotToken, propertyName, name, initializer) { - var node = createSynthesizedNode(182); + var node = createSynthesizedNode(182 /* BindingElement */); node.dotDotDotToken = dotDotDotToken; node.propertyName = asName(propertyName); node.name = asName(name); @@ -48230,8 +56042,9 @@ var ts; : node; } ts.updateBindingElement = updateBindingElement; + // Expression function createArrayLiteral(elements, multiLine) { - var node = createSynthesizedNode(183); + var node = createSynthesizedNode(183 /* ArrayLiteralExpression */); node.elements = ts.parenthesizeListElements(createNodeArray(elements)); if (multiLine) node.multiLine = true; @@ -48245,7 +56058,7 @@ var ts; } ts.updateArrayLiteral = updateArrayLiteral; function createObjectLiteral(properties, multiLine) { - var node = createSynthesizedNode(184); + var node = createSynthesizedNode(184 /* ObjectLiteralExpression */); node.properties = createNodeArray(properties); if (multiLine) node.multiLine = true; @@ -48259,14 +56072,16 @@ var ts; } ts.updateObjectLiteral = updateObjectLiteral; function createPropertyAccess(expression, name) { - var node = createSynthesizedNode(185); + var node = createSynthesizedNode(185 /* PropertyAccessExpression */); node.expression = ts.parenthesizeForAccess(expression); - node.name = asName(name); - setEmitFlags(node, 131072); + node.name = asName(name); // TODO: GH#18217 + setEmitFlags(node, 131072 /* NoIndentation */); return node; } ts.createPropertyAccess = createPropertyAccess; function updatePropertyAccess(node, expression, name) { + // Because we are updating existed propertyAccess we want to inherit its emitFlags + // instead of using the default from createPropertyAccess return node.expression !== expression || node.name !== name ? updateNode(setEmitFlags(createPropertyAccess(expression, name), ts.getEmitFlags(node)), node) @@ -48274,7 +56089,7 @@ var ts; } ts.updatePropertyAccess = updatePropertyAccess; function createElementAccess(expression, index) { - var node = createSynthesizedNode(186); + var node = createSynthesizedNode(186 /* ElementAccessExpression */); node.expression = ts.parenthesizeForAccess(expression); node.argumentExpression = asExpression(index); return node; @@ -48288,7 +56103,7 @@ var ts; } ts.updateElementAccess = updateElementAccess; function createCall(expression, typeArguments, argumentsArray) { - var node = createSynthesizedNode(187); + var node = createSynthesizedNode(187 /* CallExpression */); node.expression = ts.parenthesizeForAccess(expression); node.typeArguments = asNodeArray(typeArguments); node.arguments = ts.parenthesizeListElements(createNodeArray(argumentsArray)); @@ -48304,7 +56119,7 @@ var ts; } ts.updateCall = updateCall; function createNew(expression, typeArguments, argumentsArray) { - var node = createSynthesizedNode(188); + var node = createSynthesizedNode(188 /* NewExpression */); node.expression = ts.parenthesizeForNew(expression); node.typeArguments = asNodeArray(typeArguments); node.arguments = argumentsArray ? ts.parenthesizeListElements(createNodeArray(argumentsArray)) : undefined; @@ -48320,7 +56135,7 @@ var ts; } ts.updateNew = updateNew; function createTaggedTemplate(tag, typeArgumentsOrTemplate, template) { - var node = createSynthesizedNode(189); + var node = createSynthesizedNode(189 /* TaggedTemplateExpression */); node.tag = ts.parenthesizeForAccess(tag); if (template) { node.typeArguments = asNodeArray(typeArgumentsOrTemplate); @@ -48343,7 +56158,7 @@ var ts; } ts.updateTaggedTemplate = updateTaggedTemplate; function createTypeAssertion(type, expression) { - var node = createSynthesizedNode(190); + var node = createSynthesizedNode(190 /* TypeAssertionExpression */); node.type = type; node.expression = ts.parenthesizePrefixOperand(expression); return node; @@ -48357,7 +56172,7 @@ var ts; } ts.updateTypeAssertion = updateTypeAssertion; function createParen(expression) { - var node = createSynthesizedNode(191); + var node = createSynthesizedNode(191 /* ParenthesizedExpression */); node.expression = expression; return node; } @@ -48369,7 +56184,7 @@ var ts; } ts.updateParen = updateParen; function createFunctionExpression(modifiers, asteriskToken, name, typeParameters, parameters, type, body) { - var node = createSynthesizedNode(192); + var node = createSynthesizedNode(192 /* FunctionExpression */); node.modifiers = asNodeArray(modifiers); node.asteriskToken = asteriskToken; node.name = asName(name); @@ -48393,12 +56208,12 @@ var ts; } ts.updateFunctionExpression = updateFunctionExpression; function createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body) { - var node = createSynthesizedNode(193); + var node = createSynthesizedNode(193 /* ArrowFunction */); node.modifiers = asNodeArray(modifiers); node.typeParameters = asNodeArray(typeParameters); node.parameters = createNodeArray(parameters); node.type = type; - node.equalsGreaterThanToken = equalsGreaterThanToken || createToken(36); + node.equalsGreaterThanToken = equalsGreaterThanToken || createToken(36 /* EqualsGreaterThanToken */); node.body = ts.parenthesizeConciseBody(body); return node; } @@ -48412,7 +56227,7 @@ var ts; } else { equalsGreaterThanToken = ts.cast(equalsGreaterThanTokenOrBody, function (n) { - return n.kind === 36; + return n.kind === 36 /* EqualsGreaterThanToken */; }); body = bodyOrUndefined; } @@ -48427,7 +56242,7 @@ var ts; } ts.updateArrowFunction = updateArrowFunction; function createDelete(expression) { - var node = createSynthesizedNode(194); + var node = createSynthesizedNode(194 /* DeleteExpression */); node.expression = ts.parenthesizePrefixOperand(expression); return node; } @@ -48439,7 +56254,7 @@ var ts; } ts.updateDelete = updateDelete; function createTypeOf(expression) { - var node = createSynthesizedNode(195); + var node = createSynthesizedNode(195 /* TypeOfExpression */); node.expression = ts.parenthesizePrefixOperand(expression); return node; } @@ -48451,7 +56266,7 @@ var ts; } ts.updateTypeOf = updateTypeOf; function createVoid(expression) { - var node = createSynthesizedNode(196); + var node = createSynthesizedNode(196 /* VoidExpression */); node.expression = ts.parenthesizePrefixOperand(expression); return node; } @@ -48463,7 +56278,7 @@ var ts; } ts.updateVoid = updateVoid; function createAwait(expression) { - var node = createSynthesizedNode(197); + var node = createSynthesizedNode(197 /* AwaitExpression */); node.expression = ts.parenthesizePrefixOperand(expression); return node; } @@ -48475,7 +56290,7 @@ var ts; } ts.updateAwait = updateAwait; function createPrefix(operator, operand) { - var node = createSynthesizedNode(198); + var node = createSynthesizedNode(198 /* PrefixUnaryExpression */); node.operator = operator; node.operand = ts.parenthesizePrefixOperand(operand); return node; @@ -48488,7 +56303,7 @@ var ts; } ts.updatePrefix = updatePrefix; function createPostfix(operand, operator) { - var node = createSynthesizedNode(199); + var node = createSynthesizedNode(199 /* PostfixUnaryExpression */); node.operand = ts.parenthesizePostfixOperand(operand); node.operator = operator; return node; @@ -48501,12 +56316,12 @@ var ts; } ts.updatePostfix = updatePostfix; function createBinary(left, operator, right) { - var node = createSynthesizedNode(200); + var node = createSynthesizedNode(200 /* BinaryExpression */); var operatorToken = asToken(operator); var operatorKind = operatorToken.kind; - node.left = ts.parenthesizeBinaryOperand(operatorKind, left, true, undefined); + node.left = ts.parenthesizeBinaryOperand(operatorKind, left, /*isLeftSideOfBinary*/ true, /*leftOperand*/ undefined); node.operatorToken = operatorToken; - node.right = ts.parenthesizeBinaryOperand(operatorKind, right, false, node.left); + node.right = ts.parenthesizeBinaryOperand(operatorKind, right, /*isLeftSideOfBinary*/ false, node.left); return node; } ts.createBinary = createBinary; @@ -48518,11 +56333,11 @@ var ts; } ts.updateBinary = updateBinary; function createConditional(condition, questionTokenOrWhenTrue, whenTrueOrWhenFalse, colonToken, whenFalse) { - var node = createSynthesizedNode(201); + var node = createSynthesizedNode(201 /* ConditionalExpression */); node.condition = ts.parenthesizeForConditionalHead(condition); - node.questionToken = whenFalse ? questionTokenOrWhenTrue : createToken(55); + node.questionToken = whenFalse ? questionTokenOrWhenTrue : createToken(55 /* QuestionToken */); node.whenTrue = ts.parenthesizeSubexpressionOfConditionalExpression(whenFalse ? whenTrueOrWhenFalse : questionTokenOrWhenTrue); - node.colonToken = whenFalse ? colonToken : createToken(56); + node.colonToken = whenFalse ? colonToken : createToken(56 /* ColonToken */); node.whenFalse = ts.parenthesizeSubexpressionOfConditionalExpression(whenFalse ? whenFalse : whenTrueOrWhenFalse); return node; } @@ -48548,7 +56363,7 @@ var ts; } ts.updateConditional = updateConditional; function createTemplateExpression(head, templateSpans) { - var node = createSynthesizedNode(202); + var node = createSynthesizedNode(202 /* TemplateExpression */); node.head = head; node.templateSpans = createNodeArray(templateSpans); return node; @@ -48562,33 +56377,33 @@ var ts; } ts.updateTemplateExpression = updateTemplateExpression; function createTemplateHead(text) { - var node = createSynthesizedNode(14); + var node = createSynthesizedNode(14 /* TemplateHead */); node.text = text; return node; } ts.createTemplateHead = createTemplateHead; function createTemplateMiddle(text) { - var node = createSynthesizedNode(15); + var node = createSynthesizedNode(15 /* TemplateMiddle */); node.text = text; return node; } ts.createTemplateMiddle = createTemplateMiddle; function createTemplateTail(text) { - var node = createSynthesizedNode(16); + var node = createSynthesizedNode(16 /* TemplateTail */); node.text = text; return node; } ts.createTemplateTail = createTemplateTail; function createNoSubstitutionTemplateLiteral(text) { - var node = createSynthesizedNode(13); + var node = createSynthesizedNode(13 /* NoSubstitutionTemplateLiteral */); node.text = text; return node; } ts.createNoSubstitutionTemplateLiteral = createNoSubstitutionTemplateLiteral; function createYield(asteriskTokenOrExpression, expression) { - var node = createSynthesizedNode(203); - node.asteriskToken = asteriskTokenOrExpression && asteriskTokenOrExpression.kind === 39 ? asteriskTokenOrExpression : undefined; - node.expression = asteriskTokenOrExpression && asteriskTokenOrExpression.kind !== 39 ? asteriskTokenOrExpression : expression; + var node = createSynthesizedNode(203 /* YieldExpression */); + node.asteriskToken = asteriskTokenOrExpression && asteriskTokenOrExpression.kind === 39 /* AsteriskToken */ ? asteriskTokenOrExpression : undefined; + node.expression = asteriskTokenOrExpression && asteriskTokenOrExpression.kind !== 39 /* AsteriskToken */ ? asteriskTokenOrExpression : expression; return node; } ts.createYield = createYield; @@ -48600,7 +56415,7 @@ var ts; } ts.updateYield = updateYield; function createSpread(expression) { - var node = createSynthesizedNode(204); + var node = createSynthesizedNode(204 /* SpreadElement */); node.expression = ts.parenthesizeExpressionForList(expression); return node; } @@ -48612,7 +56427,7 @@ var ts; } ts.updateSpread = updateSpread; function createClassExpression(modifiers, name, typeParameters, heritageClauses, members) { - var node = createSynthesizedNode(205); + var node = createSynthesizedNode(205 /* ClassExpression */); node.decorators = undefined; node.modifiers = asNodeArray(modifiers); node.name = asName(name); @@ -48633,11 +56448,11 @@ var ts; } ts.updateClassExpression = updateClassExpression; function createOmittedExpression() { - return createSynthesizedNode(206); + return createSynthesizedNode(206 /* OmittedExpression */); } ts.createOmittedExpression = createOmittedExpression; function createExpressionWithTypeArguments(typeArguments, expression) { - var node = createSynthesizedNode(207); + var node = createSynthesizedNode(207 /* ExpressionWithTypeArguments */); node.expression = ts.parenthesizeForAccess(expression); node.typeArguments = asNodeArray(typeArguments); return node; @@ -48651,7 +56466,7 @@ var ts; } ts.updateExpressionWithTypeArguments = updateExpressionWithTypeArguments; function createAsExpression(expression, type) { - var node = createSynthesizedNode(208); + var node = createSynthesizedNode(208 /* AsExpression */); node.expression = expression; node.type = type; return node; @@ -48665,7 +56480,7 @@ var ts; } ts.updateAsExpression = updateAsExpression; function createNonNullExpression(expression) { - var node = createSynthesizedNode(209); + var node = createSynthesizedNode(209 /* NonNullExpression */); node.expression = ts.parenthesizeForAccess(expression); return node; } @@ -48677,7 +56492,7 @@ var ts; } ts.updateNonNullExpression = updateNonNullExpression; function createMetaProperty(keywordToken, name) { - var node = createSynthesizedNode(210); + var node = createSynthesizedNode(210 /* MetaProperty */); node.keywordToken = keywordToken; node.name = name; return node; @@ -48689,8 +56504,9 @@ var ts; : node; } ts.updateMetaProperty = updateMetaProperty; + // Misc function createTemplateSpan(expression, literal) { - var node = createSynthesizedNode(211); + var node = createSynthesizedNode(211 /* TemplateSpan */); node.expression = expression; node.literal = literal; return node; @@ -48704,19 +56520,21 @@ var ts; } ts.updateTemplateSpan = updateTemplateSpan; function createSemicolonClassElement() { - return createSynthesizedNode(212); + return createSynthesizedNode(212 /* SemicolonClassElement */); } ts.createSemicolonClassElement = createSemicolonClassElement; + // Element function createBlock(statements, multiLine) { - var block = createSynthesizedNode(213); + var block = createSynthesizedNode(213 /* Block */); block.statements = createNodeArray(statements); if (multiLine) block.multiLine = multiLine; return block; } ts.createBlock = createBlock; + /* @internal */ function createExpressionStatement(expression) { - var node = createSynthesizedNode(216); + var node = createSynthesizedNode(216 /* ExpressionStatement */); node.expression = expression; return node; } @@ -48728,7 +56546,7 @@ var ts; } ts.updateBlock = updateBlock; function createVariableStatement(modifiers, declarationList) { - var node = createSynthesizedNode(214); + var node = createSynthesizedNode(214 /* VariableStatement */); node.decorators = undefined; node.modifiers = asNodeArray(modifiers); node.declarationList = ts.isArray(declarationList) ? createVariableDeclarationList(declarationList) : declarationList; @@ -48743,7 +56561,7 @@ var ts; } ts.updateVariableStatement = updateVariableStatement; function createEmptyStatement() { - return createSynthesizedNode(215); + return createSynthesizedNode(215 /* EmptyStatement */); } ts.createEmptyStatement = createEmptyStatement; function createStatement(expression) { @@ -48757,7 +56575,7 @@ var ts; } ts.updateStatement = updateStatement; function createIf(expression, thenStatement, elseStatement) { - var node = createSynthesizedNode(217); + var node = createSynthesizedNode(217 /* IfStatement */); node.expression = expression; node.thenStatement = thenStatement; node.elseStatement = elseStatement; @@ -48773,7 +56591,7 @@ var ts; } ts.updateIf = updateIf; function createDo(statement, expression) { - var node = createSynthesizedNode(218); + var node = createSynthesizedNode(218 /* DoStatement */); node.statement = statement; node.expression = expression; return node; @@ -48787,7 +56605,7 @@ var ts; } ts.updateDo = updateDo; function createWhile(expression, statement) { - var node = createSynthesizedNode(219); + var node = createSynthesizedNode(219 /* WhileStatement */); node.expression = expression; node.statement = statement; return node; @@ -48801,7 +56619,7 @@ var ts; } ts.updateWhile = updateWhile; function createFor(initializer, condition, incrementor, statement) { - var node = createSynthesizedNode(220); + var node = createSynthesizedNode(220 /* ForStatement */); node.initializer = initializer; node.condition = condition; node.incrementor = incrementor; @@ -48819,7 +56637,7 @@ var ts; } ts.updateFor = updateFor; function createForIn(initializer, expression, statement) { - var node = createSynthesizedNode(221); + var node = createSynthesizedNode(221 /* ForInStatement */); node.initializer = initializer; node.expression = expression; node.statement = statement; @@ -48835,7 +56653,7 @@ var ts; } ts.updateForIn = updateForIn; function createForOf(awaitModifier, initializer, expression, statement) { - var node = createSynthesizedNode(222); + var node = createSynthesizedNode(222 /* ForOfStatement */); node.awaitModifier = awaitModifier; node.initializer = initializer; node.expression = expression; @@ -48853,7 +56671,7 @@ var ts; } ts.updateForOf = updateForOf; function createContinue(label) { - var node = createSynthesizedNode(223); + var node = createSynthesizedNode(223 /* ContinueStatement */); node.label = asName(label); return node; } @@ -48865,7 +56683,7 @@ var ts; } ts.updateContinue = updateContinue; function createBreak(label) { - var node = createSynthesizedNode(224); + var node = createSynthesizedNode(224 /* BreakStatement */); node.label = asName(label); return node; } @@ -48877,7 +56695,7 @@ var ts; } ts.updateBreak = updateBreak; function createReturn(expression) { - var node = createSynthesizedNode(225); + var node = createSynthesizedNode(225 /* ReturnStatement */); node.expression = expression; return node; } @@ -48889,7 +56707,7 @@ var ts; } ts.updateReturn = updateReturn; function createWith(expression, statement) { - var node = createSynthesizedNode(226); + var node = createSynthesizedNode(226 /* WithStatement */); node.expression = expression; node.statement = statement; return node; @@ -48903,7 +56721,7 @@ var ts; } ts.updateWith = updateWith; function createSwitch(expression, caseBlock) { - var node = createSynthesizedNode(227); + var node = createSynthesizedNode(227 /* SwitchStatement */); node.expression = ts.parenthesizeExpressionForList(expression); node.caseBlock = caseBlock; return node; @@ -48917,7 +56735,7 @@ var ts; } ts.updateSwitch = updateSwitch; function createLabel(label, statement) { - var node = createSynthesizedNode(228); + var node = createSynthesizedNode(228 /* LabeledStatement */); node.label = asName(label); node.statement = statement; return node; @@ -48931,7 +56749,7 @@ var ts; } ts.updateLabel = updateLabel; function createThrow(expression) { - var node = createSynthesizedNode(229); + var node = createSynthesizedNode(229 /* ThrowStatement */); node.expression = expression; return node; } @@ -48943,7 +56761,7 @@ var ts; } ts.updateThrow = updateThrow; function createTry(tryBlock, catchClause, finallyBlock) { - var node = createSynthesizedNode(230); + var node = createSynthesizedNode(230 /* TryStatement */); node.tryBlock = tryBlock; node.catchClause = catchClause; node.finallyBlock = finallyBlock; @@ -48959,11 +56777,11 @@ var ts; } ts.updateTry = updateTry; function createDebuggerStatement() { - return createSynthesizedNode(231); + return createSynthesizedNode(231 /* DebuggerStatement */); } ts.createDebuggerStatement = createDebuggerStatement; function createVariableDeclaration(name, type, initializer) { - var node = createSynthesizedNode(232); + var node = createSynthesizedNode(232 /* VariableDeclaration */); node.name = asName(name); node.type = type; node.initializer = initializer !== undefined ? ts.parenthesizeExpressionForList(initializer) : undefined; @@ -48979,9 +56797,9 @@ var ts; } ts.updateVariableDeclaration = updateVariableDeclaration; function createVariableDeclarationList(declarations, flags) { - if (flags === void 0) { flags = 0; } - var node = createSynthesizedNode(233); - node.flags |= flags & 3; + if (flags === void 0) { flags = 0 /* None */; } + var node = createSynthesizedNode(233 /* VariableDeclarationList */); + node.flags |= flags & 3 /* BlockScoped */; node.declarations = createNodeArray(declarations); return node; } @@ -48993,7 +56811,7 @@ var ts; } ts.updateVariableDeclarationList = updateVariableDeclarationList; function createFunctionDeclaration(decorators, modifiers, asteriskToken, name, typeParameters, parameters, type, body) { - var node = createSynthesizedNode(234); + var node = createSynthesizedNode(234 /* FunctionDeclaration */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.asteriskToken = asteriskToken; @@ -49019,7 +56837,7 @@ var ts; } ts.updateFunctionDeclaration = updateFunctionDeclaration; function createClassDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members) { - var node = createSynthesizedNode(235); + var node = createSynthesizedNode(235 /* ClassDeclaration */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.name = asName(name); @@ -49041,7 +56859,7 @@ var ts; } ts.updateClassDeclaration = updateClassDeclaration; function createInterfaceDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members) { - var node = createSynthesizedNode(236); + var node = createSynthesizedNode(236 /* InterfaceDeclaration */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.name = asName(name); @@ -49063,7 +56881,7 @@ var ts; } ts.updateInterfaceDeclaration = updateInterfaceDeclaration; function createTypeAliasDeclaration(decorators, modifiers, name, typeParameters, type) { - var node = createSynthesizedNode(237); + var node = createSynthesizedNode(237 /* TypeAliasDeclaration */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.name = asName(name); @@ -49083,7 +56901,7 @@ var ts; } ts.updateTypeAliasDeclaration = updateTypeAliasDeclaration; function createEnumDeclaration(decorators, modifiers, name, members) { - var node = createSynthesizedNode(238); + var node = createSynthesizedNode(238 /* EnumDeclaration */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.name = asName(name); @@ -49101,9 +56919,9 @@ var ts; } ts.updateEnumDeclaration = updateEnumDeclaration; function createModuleDeclaration(decorators, modifiers, name, body, flags) { - if (flags === void 0) { flags = 0; } - var node = createSynthesizedNode(239); - node.flags |= flags & (16 | 4 | 512); + if (flags === void 0) { flags = 0 /* None */; } + var node = createSynthesizedNode(239 /* ModuleDeclaration */); + node.flags |= flags & (16 /* Namespace */ | 4 /* NestedNamespace */ | 512 /* GlobalAugmentation */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.name = name; @@ -49121,7 +56939,7 @@ var ts; } ts.updateModuleDeclaration = updateModuleDeclaration; function createModuleBlock(statements) { - var node = createSynthesizedNode(240); + var node = createSynthesizedNode(240 /* ModuleBlock */); node.statements = createNodeArray(statements); return node; } @@ -49133,7 +56951,7 @@ var ts; } ts.updateModuleBlock = updateModuleBlock; function createCaseBlock(clauses) { - var node = createSynthesizedNode(241); + var node = createSynthesizedNode(241 /* CaseBlock */); node.clauses = createNodeArray(clauses); return node; } @@ -49145,7 +56963,7 @@ var ts; } ts.updateCaseBlock = updateCaseBlock; function createNamespaceExportDeclaration(name) { - var node = createSynthesizedNode(242); + var node = createSynthesizedNode(242 /* NamespaceExportDeclaration */); node.name = asName(name); return node; } @@ -49157,7 +56975,7 @@ var ts; } ts.updateNamespaceExportDeclaration = updateNamespaceExportDeclaration; function createImportEqualsDeclaration(decorators, modifiers, name, moduleReference) { - var node = createSynthesizedNode(243); + var node = createSynthesizedNode(243 /* ImportEqualsDeclaration */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.name = asName(name); @@ -49175,7 +56993,7 @@ var ts; } ts.updateImportEqualsDeclaration = updateImportEqualsDeclaration; function createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier) { - var node = createSynthesizedNode(244); + var node = createSynthesizedNode(244 /* ImportDeclaration */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.importClause = importClause; @@ -49193,7 +57011,7 @@ var ts; } ts.updateImportDeclaration = updateImportDeclaration; function createImportClause(name, namedBindings) { - var node = createSynthesizedNode(245); + var node = createSynthesizedNode(245 /* ImportClause */); node.name = name; node.namedBindings = namedBindings; return node; @@ -49207,7 +57025,7 @@ var ts; } ts.updateImportClause = updateImportClause; function createNamespaceImport(name) { - var node = createSynthesizedNode(246); + var node = createSynthesizedNode(246 /* NamespaceImport */); node.name = name; return node; } @@ -49219,7 +57037,7 @@ var ts; } ts.updateNamespaceImport = updateNamespaceImport; function createNamedImports(elements) { - var node = createSynthesizedNode(247); + var node = createSynthesizedNode(247 /* NamedImports */); node.elements = createNodeArray(elements); return node; } @@ -49231,7 +57049,7 @@ var ts; } ts.updateNamedImports = updateNamedImports; function createImportSpecifier(propertyName, name) { - var node = createSynthesizedNode(248); + var node = createSynthesizedNode(248 /* ImportSpecifier */); node.propertyName = propertyName; node.name = name; return node; @@ -49245,11 +57063,11 @@ var ts; } ts.updateImportSpecifier = updateImportSpecifier; function createExportAssignment(decorators, modifiers, isExportEquals, expression) { - var node = createSynthesizedNode(249); + var node = createSynthesizedNode(249 /* ExportAssignment */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.isExportEquals = isExportEquals; - node.expression = isExportEquals ? ts.parenthesizeBinaryOperand(58, expression, false, undefined) : ts.parenthesizeDefaultExpression(expression); + node.expression = isExportEquals ? ts.parenthesizeBinaryOperand(58 /* EqualsToken */, expression, /*isLeftSideOfBinary*/ false, /*leftOperand*/ undefined) : ts.parenthesizeDefaultExpression(expression); return node; } ts.createExportAssignment = createExportAssignment; @@ -49262,7 +57080,7 @@ var ts; } ts.updateExportAssignment = updateExportAssignment; function createExportDeclaration(decorators, modifiers, exportClause, moduleSpecifier) { - var node = createSynthesizedNode(250); + var node = createSynthesizedNode(250 /* ExportDeclaration */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.exportClause = exportClause; @@ -49280,7 +57098,7 @@ var ts; } ts.updateExportDeclaration = updateExportDeclaration; function createNamedExports(elements) { - var node = createSynthesizedNode(251); + var node = createSynthesizedNode(251 /* NamedExports */); node.elements = createNodeArray(elements); return node; } @@ -49292,7 +57110,7 @@ var ts; } ts.updateNamedExports = updateNamedExports; function createExportSpecifier(propertyName, name) { - var node = createSynthesizedNode(252); + var node = createSynthesizedNode(252 /* ExportSpecifier */); node.propertyName = asName(propertyName); node.name = asName(name); return node; @@ -49305,8 +57123,9 @@ var ts; : node; } ts.updateExportSpecifier = updateExportSpecifier; + // Module references function createExternalModuleReference(expression) { - var node = createSynthesizedNode(254); + var node = createSynthesizedNode(254 /* ExternalModuleReference */); node.expression = expression; return node; } @@ -49317,8 +57136,9 @@ var ts; : node; } ts.updateExternalModuleReference = updateExternalModuleReference; + // JSX function createJsxElement(openingElement, children, closingElement) { - var node = createSynthesizedNode(255); + var node = createSynthesizedNode(255 /* JsxElement */); node.openingElement = openingElement; node.children = createNodeArray(children); node.closingElement = closingElement; @@ -49334,7 +57154,7 @@ var ts; } ts.updateJsxElement = updateJsxElement; function createJsxSelfClosingElement(tagName, typeArguments, attributes) { - var node = createSynthesizedNode(256); + var node = createSynthesizedNode(256 /* JsxSelfClosingElement */); node.tagName = tagName; node.typeArguments = typeArguments && createNodeArray(typeArguments); node.attributes = attributes; @@ -49350,7 +57170,7 @@ var ts; } ts.updateJsxSelfClosingElement = updateJsxSelfClosingElement; function createJsxOpeningElement(tagName, typeArguments, attributes) { - var node = createSynthesizedNode(257); + var node = createSynthesizedNode(257 /* JsxOpeningElement */); node.tagName = tagName; node.typeArguments = typeArguments && createNodeArray(typeArguments); node.attributes = attributes; @@ -49366,7 +57186,7 @@ var ts; } ts.updateJsxOpeningElement = updateJsxOpeningElement; function createJsxClosingElement(tagName) { - var node = createSynthesizedNode(258); + var node = createSynthesizedNode(258 /* JsxClosingElement */); node.tagName = tagName; return node; } @@ -49378,7 +57198,7 @@ var ts; } ts.updateJsxClosingElement = updateJsxClosingElement; function createJsxFragment(openingFragment, children, closingFragment) { - var node = createSynthesizedNode(259); + var node = createSynthesizedNode(259 /* JsxFragment */); node.openingFragment = openingFragment; node.children = createNodeArray(children); node.closingFragment = closingFragment; @@ -49394,7 +57214,7 @@ var ts; } ts.updateJsxFragment = updateJsxFragment; function createJsxAttribute(name, initializer) { - var node = createSynthesizedNode(262); + var node = createSynthesizedNode(262 /* JsxAttribute */); node.name = name; node.initializer = initializer; return node; @@ -49408,7 +57228,7 @@ var ts; } ts.updateJsxAttribute = updateJsxAttribute; function createJsxAttributes(properties) { - var node = createSynthesizedNode(263); + var node = createSynthesizedNode(263 /* JsxAttributes */); node.properties = createNodeArray(properties); return node; } @@ -49420,7 +57240,7 @@ var ts; } ts.updateJsxAttributes = updateJsxAttributes; function createJsxSpreadAttribute(expression) { - var node = createSynthesizedNode(264); + var node = createSynthesizedNode(264 /* JsxSpreadAttribute */); node.expression = expression; return node; } @@ -49432,7 +57252,7 @@ var ts; } ts.updateJsxSpreadAttribute = updateJsxSpreadAttribute; function createJsxExpression(dotDotDotToken, expression) { - var node = createSynthesizedNode(265); + var node = createSynthesizedNode(265 /* JsxExpression */); node.dotDotDotToken = dotDotDotToken; node.expression = expression; return node; @@ -49444,8 +57264,9 @@ var ts; : node; } ts.updateJsxExpression = updateJsxExpression; + // Clauses function createCaseClause(expression, statements) { - var node = createSynthesizedNode(266); + var node = createSynthesizedNode(266 /* CaseClause */); node.expression = ts.parenthesizeExpressionForList(expression); node.statements = createNodeArray(statements); return node; @@ -49459,7 +57280,7 @@ var ts; } ts.updateCaseClause = updateCaseClause; function createDefaultClause(statements) { - var node = createSynthesizedNode(267); + var node = createSynthesizedNode(267 /* DefaultClause */); node.statements = createNodeArray(statements); return node; } @@ -49471,7 +57292,7 @@ var ts; } ts.updateDefaultClause = updateDefaultClause; function createHeritageClause(token, types) { - var node = createSynthesizedNode(268); + var node = createSynthesizedNode(268 /* HeritageClause */); node.token = token; node.types = createNodeArray(types); return node; @@ -49484,7 +57305,7 @@ var ts; } ts.updateHeritageClause = updateHeritageClause; function createCatchClause(variableDeclaration, block) { - var node = createSynthesizedNode(269); + var node = createSynthesizedNode(269 /* CatchClause */); node.variableDeclaration = ts.isString(variableDeclaration) ? createVariableDeclaration(variableDeclaration) : variableDeclaration; node.block = block; return node; @@ -49497,8 +57318,9 @@ var ts; : node; } ts.updateCatchClause = updateCatchClause; + // Property assignments function createPropertyAssignment(name, initializer) { - var node = createSynthesizedNode(270); + var node = createSynthesizedNode(270 /* PropertyAssignment */); node.name = asName(name); node.questionToken = undefined; node.initializer = ts.parenthesizeExpressionForList(initializer); @@ -49513,7 +57335,7 @@ var ts; } ts.updatePropertyAssignment = updatePropertyAssignment; function createShorthandPropertyAssignment(name, objectAssignmentInitializer) { - var node = createSynthesizedNode(271); + var node = createSynthesizedNode(271 /* ShorthandPropertyAssignment */); node.name = asName(name); node.objectAssignmentInitializer = objectAssignmentInitializer !== undefined ? ts.parenthesizeExpressionForList(objectAssignmentInitializer) : undefined; return node; @@ -49527,8 +57349,8 @@ var ts; } ts.updateShorthandPropertyAssignment = updateShorthandPropertyAssignment; function createSpreadAssignment(expression) { - var node = createSynthesizedNode(272); - node.expression = expression !== undefined ? ts.parenthesizeExpressionForList(expression) : undefined; + var node = createSynthesizedNode(272 /* SpreadAssignment */); + node.expression = expression !== undefined ? ts.parenthesizeExpressionForList(expression) : undefined; // TODO: GH#18217 return node; } ts.createSpreadAssignment = createSpreadAssignment; @@ -49538,8 +57360,9 @@ var ts; : node; } ts.updateSpreadAssignment = updateSpreadAssignment; + // Enum function createEnumMember(name, initializer) { - var node = createSynthesizedNode(273); + var node = createSynthesizedNode(273 /* EnumMember */); node.name = asName(name); node.initializer = initializer && ts.parenthesizeExpressionForList(initializer); return node; @@ -49552,6 +57375,7 @@ var ts; : node; } ts.updateEnumMember = updateEnumMember; + // Top-level nodes function updateSourceFileNode(node, statements, isDeclarationFile, referencedFiles, typeReferences, hasNoDefaultLib, libReferences) { if (node.statements !== statements || (isDeclarationFile !== undefined && node.isDeclarationFile !== isDeclarationFile) || @@ -49559,7 +57383,7 @@ var ts; (typeReferences !== undefined && node.typeReferenceDirectives !== typeReferences) || (libReferences !== undefined && node.libReferenceDirectives !== libReferences) || (hasNoDefaultLib !== undefined && node.hasNoDefaultLib !== hasNoDefaultLib)) { - var updated = createSynthesizedNode(274); + var updated = createSynthesizedNode(274 /* SourceFile */); updated.flags |= node.flags; updated.statements = createNodeArray(statements); updated.endOfFileToken = node.endOfFileToken; @@ -49624,6 +57448,9 @@ var ts; return node; } ts.updateSourceFileNode = updateSourceFileNode; + /** + * Creates a shallow, memberwise clone of a node for mutation. + */ function getMutableClone(node) { var clone = getSynthesizedClone(node); clone.pos = node.pos; @@ -49632,29 +57459,54 @@ var ts; return clone; } ts.getMutableClone = getMutableClone; + // Transformation nodes + /** + * Creates a synthetic statement to act as a placeholder for a not-emitted statement in + * order to preserve comments. + * + * @param original The original statement. + */ function createNotEmittedStatement(original) { - var node = createSynthesizedNode(301); + var node = createSynthesizedNode(301 /* NotEmittedStatement */); node.original = original; setTextRange(node, original); return node; } ts.createNotEmittedStatement = createNotEmittedStatement; + /** + * Creates a synthetic element to act as a placeholder for the end of an emitted declaration in + * order to properly emit exports. + */ + /* @internal */ function createEndOfDeclarationMarker(original) { - var node = createSynthesizedNode(305); + var node = createSynthesizedNode(305 /* EndOfDeclarationMarker */); node.emitNode = {}; node.original = original; return node; } ts.createEndOfDeclarationMarker = createEndOfDeclarationMarker; + /** + * Creates a synthetic element to act as a placeholder for the beginning of a merged declaration in + * order to properly emit exports. + */ + /* @internal */ function createMergeDeclarationMarker(original) { - var node = createSynthesizedNode(304); + var node = createSynthesizedNode(304 /* MergeDeclarationMarker */); node.emitNode = {}; node.original = original; return node; } ts.createMergeDeclarationMarker = createMergeDeclarationMarker; + /** + * Creates a synthetic expression to act as a placeholder for a not-emitted expression in + * order to preserve comments or sourcemap positions. + * + * @param expression The inner expression to emit. + * @param original The original outer expression. + * @param location The location for the expression. Defaults to the positions from "original" if provided. + */ function createPartiallyEmittedExpression(expression, original) { - var node = createSynthesizedNode(302); + var node = createSynthesizedNode(302 /* PartiallyEmittedExpression */); node.expression = expression; node.original = original; setTextRange(node, original); @@ -49670,17 +57522,17 @@ var ts; ts.updatePartiallyEmittedExpression = updatePartiallyEmittedExpression; function flattenCommaElements(node) { if (ts.nodeIsSynthesized(node) && !ts.isParseTreeNode(node) && !node.original && !node.emitNode && !node.id) { - if (node.kind === 303) { + if (node.kind === 303 /* CommaListExpression */) { return node.elements; } - if (ts.isBinaryExpression(node) && node.operatorToken.kind === 26) { + if (ts.isBinaryExpression(node) && node.operatorToken.kind === 26 /* CommaToken */) { return [node.left, node.right]; } } return node; } function createCommaList(elements) { - var node = createSynthesizedNode(303); + var node = createSynthesizedNode(303 /* CommaListExpression */); node.elements = createNodeArray(ts.sameFlatMap(elements, flattenCommaElements)); return node; } @@ -49693,14 +57545,14 @@ var ts; ts.updateCommaList = updateCommaList; function createBundle(sourceFiles, prepends) { if (prepends === void 0) { prepends = ts.emptyArray; } - var node = ts.createNode(275); + var node = ts.createNode(275 /* Bundle */); node.prepends = prepends; node.sourceFiles = sourceFiles; return node; } ts.createBundle = createBundle; function createUnparsedSourceFile(text, mapPath, map) { - var node = ts.createNode(276); + var node = ts.createNode(276 /* UnparsedSource */); node.text = text; node.sourceMapPath = mapPath; node.sourceMapText = map; @@ -49708,7 +57560,7 @@ var ts; } ts.createUnparsedSourceFile = createUnparsedSourceFile; function createInputFiles(javascript, declaration, javascriptMapPath, javascriptMapText, declarationMapPath, declarationMapText) { - var node = ts.createNode(277); + var node = ts.createNode(277 /* InputFiles */); node.javascriptText = javascript; node.javascriptMapPath = javascriptMapPath; node.javascriptMapText = javascriptMapText; @@ -49727,55 +57579,70 @@ var ts; } ts.updateBundle = updateBundle; function createImmediatelyInvokedFunctionExpression(statements, param, paramValue) { - return createCall(createFunctionExpression(undefined, undefined, undefined, undefined, param ? [param] : [], undefined, createBlock(statements, true)), undefined, paramValue ? [paramValue] : []); + return createCall(createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ param ? [param] : [], + /*type*/ undefined, createBlock(statements, /*multiLine*/ true)), + /*typeArguments*/ undefined, + /*argumentsArray*/ paramValue ? [paramValue] : []); } ts.createImmediatelyInvokedFunctionExpression = createImmediatelyInvokedFunctionExpression; function createImmediatelyInvokedArrowFunction(statements, param, paramValue) { - return createCall(createArrowFunction(undefined, undefined, param ? [param] : [], undefined, undefined, createBlock(statements, true)), undefined, paramValue ? [paramValue] : []); + return createCall(createArrowFunction( + /*modifiers*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ param ? [param] : [], + /*type*/ undefined, + /*equalsGreaterThanToken*/ undefined, createBlock(statements, /*multiLine*/ true)), + /*typeArguments*/ undefined, + /*argumentsArray*/ paramValue ? [paramValue] : []); } ts.createImmediatelyInvokedArrowFunction = createImmediatelyInvokedArrowFunction; function createComma(left, right) { - return createBinary(left, 26, right); + return createBinary(left, 26 /* CommaToken */, right); } ts.createComma = createComma; function createLessThan(left, right) { - return createBinary(left, 27, right); + return createBinary(left, 27 /* LessThanToken */, right); } ts.createLessThan = createLessThan; function createAssignment(left, right) { - return createBinary(left, 58, right); + return createBinary(left, 58 /* EqualsToken */, right); } ts.createAssignment = createAssignment; function createStrictEquality(left, right) { - return createBinary(left, 34, right); + return createBinary(left, 34 /* EqualsEqualsEqualsToken */, right); } ts.createStrictEquality = createStrictEquality; function createStrictInequality(left, right) { - return createBinary(left, 35, right); + return createBinary(left, 35 /* ExclamationEqualsEqualsToken */, right); } ts.createStrictInequality = createStrictInequality; function createAdd(left, right) { - return createBinary(left, 37, right); + return createBinary(left, 37 /* PlusToken */, right); } ts.createAdd = createAdd; function createSubtract(left, right) { - return createBinary(left, 38, right); + return createBinary(left, 38 /* MinusToken */, right); } ts.createSubtract = createSubtract; function createPostfixIncrement(operand) { - return createPostfix(operand, 43); + return createPostfix(operand, 43 /* PlusPlusToken */); } ts.createPostfixIncrement = createPostfixIncrement; function createLogicalAnd(left, right) { - return createBinary(left, 53, right); + return createBinary(left, 53 /* AmpersandAmpersandToken */, right); } ts.createLogicalAnd = createLogicalAnd; function createLogicalOr(left, right) { - return createBinary(left, 54, right); + return createBinary(left, 54 /* BarBarToken */, right); } ts.createLogicalOr = createLogicalOr; function createLogicalNot(operand) { - return createPrefix(51, operand); + return createPrefix(51 /* ExclamationToken */, operand); } ts.createLogicalNot = createLogicalNot; function createVoidZero() { @@ -49783,13 +57650,14 @@ var ts; } ts.createVoidZero = createVoidZero; function createExportDefault(expression) { - return createExportAssignment(undefined, undefined, false, expression); + return createExportAssignment(/*decorators*/ undefined, /*modifiers*/ undefined, /*isExportEquals*/ false, expression); } ts.createExportDefault = createExportDefault; function createExternalModuleExport(exportName) { - return createExportDeclaration(undefined, undefined, createNamedExports([createExportSpecifier(undefined, exportName)])); + return createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([createExportSpecifier(/*propertyName*/ undefined, exportName)])); } ts.createExternalModuleExport = createExternalModuleExport; + // Utilities function asName(name) { return ts.isString(name) ? createIdentifier(name) : name; } @@ -49802,7 +57670,17 @@ var ts; function asToken(value) { return typeof value === "number" ? createToken(value) : value; } + /** + * Clears any EmitNode entries from parse-tree nodes. + * @param sourceFile A source file. + */ function disposeEmitNodes(sourceFile) { + // During transformation we may need to annotate a parse tree node with transient + // transformation properties. As parse tree nodes live longer than transformation + // nodes, we need to make sure we reclaim any memory allocated for custom ranges + // from these nodes to ensure we do not hold onto entire subtrees just for position + // information. We also need to reset these nodes to a pre-transformation state + // for incremental parsing scenarios so that we do not impact later emit. sourceFile = ts.getSourceFileOfNode(ts.getParseTreeNode(sourceFile)); var emitNode = sourceFile && sourceFile.emitNode; var annotatedNodes = emitNode && emitNode.annotatedNodes; @@ -49814,10 +57692,18 @@ var ts; } } ts.disposeEmitNodes = disposeEmitNodes; + /** + * Associates a node with the current transformation, initializing + * various transient transformation properties. + */ + /* @internal */ function getOrCreateEmitNode(node) { if (!node.emitNode) { if (ts.isParseTreeNode(node)) { - if (node.kind === 274) { + // To avoid holding onto transformation artifacts, we keep track of any + // parse tree node we are annotating. This allows us to clean them up after + // all transformations have completed. + if (node.kind === 274 /* SourceFile */) { return node.emitNode = { annotatedNodes: [node] }; } var sourceFile = ts.getSourceFileOfNode(node); @@ -49836,38 +57722,61 @@ var ts; return range; } ts.setTextRange = setTextRange; + /** + * Sets flags that control emit behavior of a node. + */ function setEmitFlags(node, emitFlags) { getOrCreateEmitNode(node).flags = emitFlags; return node; } ts.setEmitFlags = setEmitFlags; + /** + * Sets flags that control emit behavior of a node. + */ + /* @internal */ function addEmitFlags(node, emitFlags) { var emitNode = getOrCreateEmitNode(node); emitNode.flags = emitNode.flags | emitFlags; return node; } ts.addEmitFlags = addEmitFlags; + /** + * Gets a custom text range to use when emitting source maps. + */ function getSourceMapRange(node) { var emitNode = node.emitNode; return (emitNode && emitNode.sourceMapRange) || node; } ts.getSourceMapRange = getSourceMapRange; + /** + * Sets a custom text range to use when emitting source maps. + */ function setSourceMapRange(node, range) { getOrCreateEmitNode(node).sourceMapRange = range; return node; } ts.setSourceMapRange = setSourceMapRange; + // tslint:disable-next-line variable-name var SourceMapSource; + /** + * Create an external source map source file reference + */ function createSourceMapSource(fileName, text, skipTrivia) { return new (SourceMapSource || (SourceMapSource = ts.objectAllocator.getSourceMapSourceConstructor()))(fileName, text, skipTrivia); } ts.createSourceMapSource = createSourceMapSource; + /** + * Gets the TextRange to use for source maps for a token of a node. + */ function getTokenSourceMapRange(node, token) { var emitNode = node.emitNode; var tokenSourceMapRanges = emitNode && emitNode.tokenSourceMapRanges; return tokenSourceMapRanges && tokenSourceMapRanges[token]; } ts.getTokenSourceMapRange = getTokenSourceMapRange; + /** + * Sets the TextRange to use for source maps for a token of a node. + */ function setTokenSourceMapRange(node, token, range) { var emitNode = getOrCreateEmitNode(node); var tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = []); @@ -49875,21 +57784,35 @@ var ts; return node; } ts.setTokenSourceMapRange = setTokenSourceMapRange; + /** + * Gets a custom text range to use when emitting comments. + */ + /*@internal*/ function getStartsOnNewLine(node) { var emitNode = node.emitNode; return emitNode && emitNode.startsOnNewLine; } ts.getStartsOnNewLine = getStartsOnNewLine; + /** + * Sets a custom text range to use when emitting comments. + */ + /*@internal*/ function setStartsOnNewLine(node, newLine) { getOrCreateEmitNode(node).startsOnNewLine = newLine; return node; } ts.setStartsOnNewLine = setStartsOnNewLine; + /** + * Gets a custom text range to use when emitting comments. + */ function getCommentRange(node) { var emitNode = node.emitNode; return (emitNode && emitNode.commentRange) || node; } ts.getCommentRange = getCommentRange; + /** + * Sets a custom text range to use when emitting comments. + */ function setCommentRange(node, range) { getOrCreateEmitNode(node).commentRange = range; return node; @@ -49932,23 +57855,35 @@ var ts; return node; } ts.moveSyntheticComments = moveSyntheticComments; + /** + * Gets the constant value to emit for an expression. + */ function getConstantValue(node) { var emitNode = node.emitNode; return emitNode && emitNode.constantValue; } ts.getConstantValue = getConstantValue; + /** + * Sets the constant value to emit for an expression. + */ function setConstantValue(node, value) { var emitNode = getOrCreateEmitNode(node); emitNode.constantValue = value; return node; } ts.setConstantValue = setConstantValue; + /** + * Adds an EmitHelper to a node. + */ function addEmitHelper(node, helper) { var emitNode = getOrCreateEmitNode(node); emitNode.helpers = ts.append(emitNode.helpers, helper); return node; } ts.addEmitHelper = addEmitHelper; + /** + * Add EmitHelpers to a node. + */ function addEmitHelpers(node, helpers) { if (ts.some(helpers)) { var emitNode = getOrCreateEmitNode(node); @@ -49960,6 +57895,9 @@ var ts; return node; } ts.addEmitHelpers = addEmitHelpers; + /** + * Removes an EmitHelper from a node. + */ function removeEmitHelper(node, helper) { var emitNode = node.emitNode; if (emitNode) { @@ -49971,11 +57909,17 @@ var ts; return false; } ts.removeEmitHelper = removeEmitHelper; + /** + * Gets the EmitHelpers of a node. + */ function getEmitHelpers(node) { var emitNode = node.emitNode; return emitNode && emitNode.helpers; } ts.getEmitHelpers = getEmitHelpers; + /** + * Moves matching emit helpers from a source node to a target node. + */ function moveEmitHelpers(source, target, predicate) { var sourceEmitNode = source.emitNode; var sourceEmitHelpers = sourceEmitNode && sourceEmitNode.helpers; @@ -49998,15 +57942,16 @@ var ts; } } ts.moveEmitHelpers = moveEmitHelpers; + /* @internal */ function compareEmitHelpers(x, y) { if (x === y) - return 0; + return 0 /* EqualTo */; if (x.priority === y.priority) - return 0; + return 0 /* EqualTo */; if (x.priority === undefined) - return 1; + return 1 /* GreaterThan */; if (y.priority === undefined) - return -1; + return -1 /* LessThan */; return ts.compareValues(x.priority, y.priority); } ts.compareEmitHelpers = compareEmitHelpers; @@ -50024,6 +57969,7 @@ var ts; var flags = sourceEmitNode.flags, leadingComments = sourceEmitNode.leadingComments, trailingComments = sourceEmitNode.trailingComments, commentRange = sourceEmitNode.commentRange, sourceMapRange = sourceEmitNode.sourceMapRange, tokenSourceMapRanges = sourceEmitNode.tokenSourceMapRanges, constantValue = sourceEmitNode.constantValue, helpers = sourceEmitNode.helpers, startsOnNewLine = sourceEmitNode.startsOnNewLine; if (!destEmitNode) destEmitNode = {}; + // We are using `.slice()` here in case `destEmitNode.leadingComments` is pushed to later. if (leadingComments) destEmitNode.leadingComments = ts.addRange(leadingComments.slice(), destEmitNode.leadingComments); if (trailingComments) @@ -50053,6 +57999,7 @@ var ts; return destRanges; } })(ts || (ts = {})); +/* @internal */ (function (ts) { ts.nullTransformationContext = { enableEmitNotification: ts.noop, @@ -50088,19 +58035,21 @@ var ts; var expression = ts.setTextRange(ts.isIdentifier(memberName) ? ts.createPropertyAccess(target, memberName) : ts.createElementAccess(target, memberName), memberName); - ts.getOrCreateEmitNode(expression).flags |= 64; + ts.getOrCreateEmitNode(expression).flags |= 64 /* NoNestedSourceMaps */; return expression; } } ts.createMemberAccessForPropertyName = createMemberAccessForPropertyName; function createFunctionCall(func, thisArg, argumentsList, location) { - return ts.setTextRange(ts.createCall(ts.createPropertyAccess(func, "call"), undefined, [ + return ts.setTextRange(ts.createCall(ts.createPropertyAccess(func, "call"), + /*typeArguments*/ undefined, [ thisArg ].concat(argumentsList)), location); } ts.createFunctionCall = createFunctionCall; function createFunctionApply(func, thisArg, argumentsExpression, location) { - return ts.setTextRange(ts.createCall(ts.createPropertyAccess(func, "apply"), undefined, [ + return ts.setTextRange(ts.createCall(ts.createPropertyAccess(func, "apply"), + /*typeArguments*/ undefined, [ thisArg, argumentsExpression ]), location); @@ -50111,20 +58060,27 @@ var ts; if (start !== undefined) { argumentsList.push(typeof start === "number" ? ts.createLiteral(start) : start); } - return ts.createCall(ts.createPropertyAccess(array, "slice"), undefined, argumentsList); + return ts.createCall(ts.createPropertyAccess(array, "slice"), /*typeArguments*/ undefined, argumentsList); } ts.createArraySlice = createArraySlice; function createArrayConcat(array, values) { - return ts.createCall(ts.createPropertyAccess(array, "concat"), undefined, values); + return ts.createCall(ts.createPropertyAccess(array, "concat"), + /*typeArguments*/ undefined, values); } ts.createArrayConcat = createArrayConcat; function createMathPow(left, right, location) { - return ts.setTextRange(ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Math"), "pow"), undefined, [left, right]), location); + return ts.setTextRange(ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Math"), "pow"), + /*typeArguments*/ undefined, [left, right]), location); } ts.createMathPow = createMathPow; function createReactNamespace(reactNamespace, parent) { + // To ensure the emit resolver can properly resolve the namespace, we need to + // treat this identifier as if it were a source tree node by clearing the `Synthesized` + // flag and setting a parent node. var react = ts.createIdentifier(reactNamespace || "React"); - react.flags &= ~8; + react.flags &= ~8 /* Synthesized */; + // Set the parent that is in parse tree + // this makes sure that parent chain is intact for checker to traverse complete scope tree react.parent = ts.getParseTreeNode(parent); return react; } @@ -50164,7 +58120,8 @@ var ts; argumentsList.push(children[0]); } } - return ts.setTextRange(ts.createCall(createJsxFactoryExpression(jsxFactoryEntity, reactNamespace, parentElement), undefined, argumentsList), location); + return ts.setTextRange(ts.createCall(createJsxFactoryExpression(jsxFactoryEntity, reactNamespace, parentElement), + /*typeArguments*/ undefined, argumentsList), location); } ts.createExpressionForJsxElement = createExpressionForJsxElement; function createExpressionForJsxFragment(jsxFactoryEntity, reactNamespace, children, parentElement, location) { @@ -50183,11 +58140,13 @@ var ts; argumentsList.push(children[0]); } } - return ts.setTextRange(ts.createCall(createJsxFactoryExpression(jsxFactoryEntity, reactNamespace, parentElement), undefined, argumentsList), location); + return ts.setTextRange(ts.createCall(createJsxFactoryExpression(jsxFactoryEntity, reactNamespace, parentElement), + /*typeArguments*/ undefined, argumentsList), location); } ts.createExpressionForJsxFragment = createExpressionForJsxFragment; + // Helpers function getHelperName(name) { - return ts.setEmitFlags(ts.createIdentifier(name), 4096 | 2); + return ts.setEmitFlags(ts.createIdentifier(name), 4096 /* HelperName */ | 2 /* AdviseOnEmitNode */); } ts.getHelperName = getHelperName; var valuesHelper = { @@ -50197,7 +58156,8 @@ var ts; }; function createValuesHelper(context, expression, location) { context.requestEmitHelper(valuesHelper); - return ts.setTextRange(ts.createCall(getHelperName("__values"), undefined, [expression]), location); + return ts.setTextRange(ts.createCall(getHelperName("__values"), + /*typeArguments*/ undefined, [expression]), location); } ts.createValuesHelper = createValuesHelper; var readHelper = { @@ -50207,7 +58167,8 @@ var ts; }; function createReadHelper(context, iteratorRecord, count, location) { context.requestEmitHelper(readHelper); - return ts.setTextRange(ts.createCall(getHelperName("__read"), undefined, count !== undefined + return ts.setTextRange(ts.createCall(getHelperName("__read"), + /*typeArguments*/ undefined, count !== undefined ? [iteratorRecord, ts.createLiteral(count)] : [iteratorRecord]), location); } @@ -50220,18 +58181,23 @@ var ts; function createSpreadHelper(context, argumentList, location) { context.requestEmitHelper(readHelper); context.requestEmitHelper(spreadHelper); - return ts.setTextRange(ts.createCall(getHelperName("__spread"), undefined, argumentList), location); + return ts.setTextRange(ts.createCall(getHelperName("__spread"), + /*typeArguments*/ undefined, argumentList), location); } ts.createSpreadHelper = createSpreadHelper; + // Utilities function createForOfBindingStatement(node, boundValue) { if (ts.isVariableDeclarationList(node)) { var firstDeclaration = ts.first(node.declarations); - var updatedDeclaration = ts.updateVariableDeclaration(firstDeclaration, firstDeclaration.name, undefined, boundValue); - return ts.setTextRange(ts.createVariableStatement(undefined, ts.updateVariableDeclarationList(node, [updatedDeclaration])), node); + var updatedDeclaration = ts.updateVariableDeclaration(firstDeclaration, firstDeclaration.name, + /*typeNode*/ undefined, boundValue); + return ts.setTextRange(ts.createVariableStatement( + /*modifiers*/ undefined, ts.updateVariableDeclarationList(node, [updatedDeclaration])), + /*location*/ node); } else { - var updatedExpression = ts.setTextRange(ts.createAssignment(node, boundValue), node); - return ts.setTextRange(ts.createStatement(updatedExpression), node); + var updatedExpression = ts.setTextRange(ts.createAssignment(node, boundValue), /*location*/ node); + return ts.setTextRange(ts.createStatement(updatedExpression), /*location*/ node); } } ts.createForOfBindingStatement = createForOfBindingStatement; @@ -50240,7 +58206,7 @@ var ts; return ts.updateBlock(dest, ts.setTextRange(ts.createNodeArray([source].concat(dest.statements)), dest.statements)); } else { - return ts.createBlock(ts.createNodeArray([dest, source]), true); + return ts.createBlock(ts.createNodeArray([dest, source]), /*multiLine*/ true); } } ts.insertLeadingStatement = insertLeadingStatement; @@ -50248,7 +58214,7 @@ var ts; if (!outermostLabeledStatement) { return node; } - var updated = ts.updateLabel(outermostLabeledStatement, outermostLabeledStatement.label, outermostLabeledStatement.statement.kind === 228 + var updated = ts.updateLabel(outermostLabeledStatement, outermostLabeledStatement.label, outermostLabeledStatement.statement.kind === 228 /* LabeledStatement */ ? restoreEnclosingLabel(node, outermostLabeledStatement.statement) : node); if (afterRestoreLabelCallback) { @@ -50260,19 +58226,19 @@ var ts; function shouldBeCapturedInTempVariable(node, cacheIdentifiers) { var target = ts.skipParentheses(node); switch (target.kind) { - case 71: + case 71 /* Identifier */: return cacheIdentifiers; - case 99: - case 8: - case 9: + case 99 /* ThisKeyword */: + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: return false; - case 183: + case 183 /* ArrayLiteralExpression */: var elements = target.elements; if (elements.length === 0) { return false; } return true; - case 184: + case 184 /* ObjectLiteralExpression */: return target.properties.length > 0; default: return true; @@ -50280,27 +58246,28 @@ var ts; } function createCallBinding(expression, recordTempVariable, languageVersion, cacheIdentifiers) { if (cacheIdentifiers === void 0) { cacheIdentifiers = false; } - var callee = skipOuterExpressions(expression, 7); + var callee = skipOuterExpressions(expression, 7 /* All */); var thisArg; var target; if (ts.isSuperProperty(callee)) { thisArg = ts.createThis(); target = callee; } - else if (callee.kind === 97) { + else if (callee.kind === 97 /* SuperKeyword */) { thisArg = ts.createThis(); - target = languageVersion < 2 + target = languageVersion < 2 /* ES2015 */ ? ts.setTextRange(ts.createIdentifier("_super"), callee) : callee; } - else if (ts.getEmitFlags(callee) & 4096) { + else if (ts.getEmitFlags(callee) & 4096 /* HelperName */) { thisArg = ts.createVoidZero(); target = parenthesizeForAccess(callee); } else { switch (callee.kind) { - case 185: { + case 185 /* PropertyAccessExpression */: { if (shouldBeCapturedInTempVariable(callee.expression, cacheIdentifiers)) { + // for `a.b()` target is `(_a = a).b` and thisArg is `_a` thisArg = ts.createTempVariable(recordTempVariable); target = ts.createPropertyAccess(ts.setTextRange(ts.createAssignment(thisArg, callee.expression), callee.expression), callee.name); ts.setTextRange(target, callee); @@ -50311,8 +58278,9 @@ var ts; } break; } - case 186: { + case 186 /* ElementAccessExpression */: { if (shouldBeCapturedInTempVariable(callee.expression, cacheIdentifiers)) { + // for `a[b]()` target is `(_a = a)[b]` and thisArg is `_a` thisArg = ts.createTempVariable(recordTempVariable); target = ts.createElementAccess(ts.setTextRange(ts.createAssignment(thisArg, callee.expression), callee.expression), callee.argumentExpression); ts.setTextRange(target, callee); @@ -50324,6 +58292,7 @@ var ts; break; } default: { + // for `a()` target is `a` and thisArg is `void 0` thisArg = ts.createVoidZero(); target = parenthesizeForAccess(expression); break; @@ -50334,6 +58303,8 @@ var ts; } ts.createCallBinding = createCallBinding; function inlineExpressions(expressions) { + // Avoid deeply nested comma expressions as traversing them during emit can result in "Maximum call + // stack size exceeded" errors. return expressions.length > 10 ? ts.createCommaList(expressions) : ts.reduceLeft(expressions, ts.createComma); @@ -50364,14 +58335,14 @@ var ts; ts.createExpressionForPropertyName = createExpressionForPropertyName; function createExpressionForObjectLiteralElementLike(node, property, receiver) { switch (property.kind) { - case 156: - case 157: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return createExpressionForAccessorDeclaration(node.properties, property, receiver, !!node.multiLine); - case 270: + case 270 /* PropertyAssignment */: return createExpressionForPropertyAssignment(property, receiver); - case 271: + case 271 /* ShorthandPropertyAssignment */: return createExpressionForShorthandPropertyAssignment(property, receiver); - case 154: + case 154 /* MethodDeclaration */: return createExpressionForMethodDeclaration(property, receiver); } } @@ -50381,14 +58352,24 @@ var ts; if (property === firstAccessor) { var properties_9 = []; if (getAccessor) { - var getterFunction = ts.createFunctionExpression(getAccessor.modifiers, undefined, undefined, undefined, getAccessor.parameters, undefined, getAccessor.body); + var getterFunction = ts.createFunctionExpression(getAccessor.modifiers, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, getAccessor.parameters, + /*type*/ undefined, getAccessor.body // TODO: GH#18217 + ); ts.setTextRange(getterFunction, getAccessor); ts.setOriginalNode(getterFunction, getAccessor); var getter = ts.createPropertyAssignment("get", getterFunction); properties_9.push(getter); } if (setAccessor) { - var setterFunction = ts.createFunctionExpression(setAccessor.modifiers, undefined, undefined, undefined, setAccessor.parameters, undefined, setAccessor.body); + var setterFunction = ts.createFunctionExpression(setAccessor.modifiers, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, setAccessor.parameters, + /*type*/ undefined, setAccessor.body // TODO: GH#18217 + ); ts.setTextRange(setterFunction, setAccessor); ts.setOriginalNode(setterFunction, setAccessor); var setter = ts.createPropertyAssignment("set", setterFunction); @@ -50396,48 +58377,108 @@ var ts; } properties_9.push(ts.createPropertyAssignment("enumerable", ts.createTrue())); properties_9.push(ts.createPropertyAssignment("configurable", ts.createTrue())); - var expression = ts.setTextRange(ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Object"), "defineProperty"), undefined, [ + var expression = ts.setTextRange(ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Object"), "defineProperty"), + /*typeArguments*/ undefined, [ receiver, createExpressionForPropertyName(property.name), ts.createObjectLiteral(properties_9, multiLine) - ]), firstAccessor); + ]), + /*location*/ firstAccessor); return ts.aggregateTransformFlags(expression); } return undefined; } function createExpressionForPropertyAssignment(property, receiver) { - return ts.aggregateTransformFlags(ts.setOriginalNode(ts.setTextRange(ts.createAssignment(createMemberAccessForPropertyName(receiver, property.name, property.name), property.initializer), property), property)); + return ts.aggregateTransformFlags(ts.setOriginalNode(ts.setTextRange(ts.createAssignment(createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name), property.initializer), property), property)); } function createExpressionForShorthandPropertyAssignment(property, receiver) { - return ts.aggregateTransformFlags(ts.setOriginalNode(ts.setTextRange(ts.createAssignment(createMemberAccessForPropertyName(receiver, property.name, property.name), ts.getSynthesizedClone(property.name)), property), property)); + return ts.aggregateTransformFlags(ts.setOriginalNode(ts.setTextRange(ts.createAssignment(createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name), ts.getSynthesizedClone(property.name)), + /*location*/ property), + /*original*/ property)); } function createExpressionForMethodDeclaration(method, receiver) { - return ts.aggregateTransformFlags(ts.setOriginalNode(ts.setTextRange(ts.createAssignment(createMemberAccessForPropertyName(receiver, method.name, method.name), ts.setOriginalNode(ts.setTextRange(ts.createFunctionExpression(method.modifiers, method.asteriskToken, undefined, undefined, method.parameters, undefined, method.body), method), method)), method), method)); + return ts.aggregateTransformFlags(ts.setOriginalNode(ts.setTextRange(ts.createAssignment(createMemberAccessForPropertyName(receiver, method.name, /*location*/ method.name), ts.setOriginalNode(ts.setTextRange(ts.createFunctionExpression(method.modifiers, method.asteriskToken, + /*name*/ undefined, + /*typeParameters*/ undefined, method.parameters, + /*type*/ undefined, method.body // TODO: GH#18217 + ), + /*location*/ method), + /*original*/ method)), + /*location*/ method), + /*original*/ method)); } + /** + * Gets the internal name of a declaration. This is primarily used for declarations that can be + * referred to by name in the body of an ES5 class function body. An internal name will *never* + * be prefixed with an module or namespace export modifier like "exports." when emitted as an + * expression. An internal name will also *never* be renamed due to a collision with a block + * scoped variable. + * + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ function getInternalName(node, allowComments, allowSourceMaps) { - return getName(node, allowComments, allowSourceMaps, 16384 | 32768); + return getName(node, allowComments, allowSourceMaps, 16384 /* LocalName */ | 32768 /* InternalName */); } ts.getInternalName = getInternalName; + /** + * Gets whether an identifier should only be referred to by its internal name. + */ function isInternalName(node) { - return (ts.getEmitFlags(node) & 32768) !== 0; + return (ts.getEmitFlags(node) & 32768 /* InternalName */) !== 0; } ts.isInternalName = isInternalName; + /** + * Gets the local name of a declaration. This is primarily used for declarations that can be + * referred to by name in the declaration's immediate scope (classes, enums, namespaces). A + * local name will *never* be prefixed with an module or namespace export modifier like + * "exports." when emitted as an expression. + * + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ function getLocalName(node, allowComments, allowSourceMaps) { - return getName(node, allowComments, allowSourceMaps, 16384); + return getName(node, allowComments, allowSourceMaps, 16384 /* LocalName */); } ts.getLocalName = getLocalName; + /** + * Gets whether an identifier should only be referred to by its local name. + */ function isLocalName(node) { - return (ts.getEmitFlags(node) & 16384) !== 0; + return (ts.getEmitFlags(node) & 16384 /* LocalName */) !== 0; } ts.isLocalName = isLocalName; + /** + * Gets the export name of a declaration. This is primarily used for declarations that can be + * referred to by name in the declaration's immediate scope (classes, enums, namespaces). An + * export name will *always* be prefixed with an module or namespace export modifier like + * `"exports."` when emitted as an expression if the name points to an exported symbol. + * + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ function getExportName(node, allowComments, allowSourceMaps) { - return getName(node, allowComments, allowSourceMaps, 8192); + return getName(node, allowComments, allowSourceMaps, 8192 /* ExportName */); } ts.getExportName = getExportName; + /** + * Gets whether an identifier should only be referred to by its export representation if the + * name points to an exported symbol. + */ function isExportName(node) { - return (ts.getEmitFlags(node) & 8192) !== 0; + return (ts.getEmitFlags(node) & 8192 /* ExportName */) !== 0; } ts.isExportName = isExportName; + /** + * Gets the name of a declaration for use in declarations. + * + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ function getDeclarationName(node, allowComments, allowSourceMaps) { return getName(node, allowComments, allowSourceMaps); } @@ -50449,30 +58490,49 @@ var ts; var name = ts.getMutableClone(nodeName); emitFlags |= ts.getEmitFlags(nodeName); if (!allowSourceMaps) - emitFlags |= 48; + emitFlags |= 48 /* NoSourceMap */; if (!allowComments) - emitFlags |= 1536; + emitFlags |= 1536 /* NoComments */; if (emitFlags) ts.setEmitFlags(name, emitFlags); return name; } return ts.getGeneratedNameForNode(node); } + /** + * Gets the exported name of a declaration for use in expressions. + * + * An exported name will *always* be prefixed with an module or namespace export modifier like + * "exports." if the name points to an exported symbol. + * + * @param ns The namespace identifier. + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ function getExternalModuleOrNamespaceExportName(ns, node, allowComments, allowSourceMaps) { - if (ns && ts.hasModifier(node, 1)) { + if (ns && ts.hasModifier(node, 1 /* Export */)) { return getNamespaceMemberName(ns, getName(node), allowComments, allowSourceMaps); } return getExportName(node, allowComments, allowSourceMaps); } ts.getExternalModuleOrNamespaceExportName = getExternalModuleOrNamespaceExportName; + /** + * Gets a namespace-qualified name for use in expressions. + * + * @param ns The namespace identifier. + * @param name The name. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ function getNamespaceMemberName(ns, name, allowComments, allowSourceMaps) { var qualifiedName = ts.createPropertyAccess(ns, ts.nodeIsSynthesized(name) ? name : ts.getSynthesizedClone(name)); ts.setTextRange(qualifiedName, name); var emitFlags = 0; if (!allowSourceMaps) - emitFlags |= 48; + emitFlags |= 48 /* NoSourceMap */; if (!allowComments) - emitFlags |= 1536; + emitFlags |= 1536 /* NoComments */; if (emitFlags) ts.setEmitFlags(qualifiedName, emitFlags); return qualifiedName; @@ -50489,7 +58549,7 @@ var ts; ts.setOriginalNode(updated, node); ts.setTextRange(updated, node); if (ts.getStartsOnNewLine(node)) { - ts.setStartsOnNewLine(updated, true); + ts.setStartsOnNewLine(updated, /*newLine*/ true); } ts.aggregateTransformFlags(updated); return updated; @@ -50498,11 +58558,28 @@ var ts; function isUseStrictPrologue(node) { return ts.isStringLiteral(node.expression) && node.expression.text === "use strict"; } + /** + * Add any necessary prologue-directives into target statement-array. + * The function needs to be called during each transformation step. + * This function needs to be called whenever we transform the statement + * list of a source file, namespace, or function-like body. + * + * @param target: result statements array + * @param source: origin statements array + * @param ensureUseStrict: boolean determining whether the function need to add prologue-directives + * @param visitor: Optional callback used to visit any custom prologue directives. + */ function addPrologue(target, source, ensureUseStrict, visitor) { var offset = addStandardPrologue(target, source, ensureUseStrict); return addCustomPrologue(target, source, offset, visitor); } ts.addPrologue = addPrologue; + /** + * Add just the standard (string-expression) prologue-directives into target statement-array. + * The function needs to be called during each transformation step. + * This function needs to be called whenever we transform the statement + * list of a source file, namespace, or function-like body. + */ function addStandardPrologue(target, source, ensureUseStrict) { ts.Debug.assert(target.length === 0, "Prologue directives should be at the first statement in the target statements array"); var foundUseStrict = false; @@ -50531,7 +58608,7 @@ var ts; var numStatements = source.length; while (statementOffset !== undefined && statementOffset < numStatements) { var statement = source[statementOffset]; - if (ts.getEmitFlags(statement) & 1048576) { + if (ts.getEmitFlags(statement) & 1048576 /* CustomPrologue */) { ts.append(target, visitor ? ts.visitNode(statement, visitor, ts.isStatement) : statement); } else { @@ -50549,6 +58626,11 @@ var ts; && isUseStrictPrologue(firstStatement); } ts.startsWithUseStrict = startsWithUseStrict; + /** + * Ensures "use strict" directive is added + * + * @param statements An array of statements + */ function ensureUseStrict(statements) { var foundUseStrict = false; for (var _i = 0, statements_3 = statements; _i < statements_3.length; _i++) { @@ -50571,9 +58653,19 @@ var ts; return statements; } ts.ensureUseStrict = ensureUseStrict; + /** + * Wraps the operand to a BinaryExpression in parentheses if they are needed to preserve the intended + * order of operations. + * + * @param binaryOperator The operator for the BinaryExpression. + * @param operand The operand for the BinaryExpression. + * @param isLeftSideOfBinary A value indicating whether the operand is the left side of the + * BinaryExpression. + */ function parenthesizeBinaryOperand(binaryOperator, operand, isLeftSideOfBinary, leftOperand) { var skipped = ts.skipPartiallyEmittedExpressions(operand); - if (skipped.kind === 191) { + // If the resulting expression is already parenthesized, we do not need to do any further processing. + if (skipped.kind === 191 /* ParenthesizedExpression */) { return operand; } return binaryOperandNeedsParentheses(binaryOperator, operand, isLeftSideOfBinary, leftOperand) @@ -50581,55 +58673,131 @@ var ts; : operand; } ts.parenthesizeBinaryOperand = parenthesizeBinaryOperand; + /** + * Determines whether the operand to a BinaryExpression needs to be parenthesized. + * + * @param binaryOperator The operator for the BinaryExpression. + * @param operand The operand for the BinaryExpression. + * @param isLeftSideOfBinary A value indicating whether the operand is the left side of the + * BinaryExpression. + */ function binaryOperandNeedsParentheses(binaryOperator, operand, isLeftSideOfBinary, leftOperand) { - var binaryOperatorPrecedence = ts.getOperatorPrecedence(200, binaryOperator); - var binaryOperatorAssociativity = ts.getOperatorAssociativity(200, binaryOperator); + // If the operand has lower precedence, then it needs to be parenthesized to preserve the + // intent of the expression. For example, if the operand is `a + b` and the operator is + // `*`, then we need to parenthesize the operand to preserve the intended order of + // operations: `(a + b) * x`. + // + // If the operand has higher precedence, then it does not need to be parenthesized. For + // example, if the operand is `a * b` and the operator is `+`, then we do not need to + // parenthesize to preserve the intended order of operations: `a * b + x`. + // + // If the operand has the same precedence, then we need to check the associativity of + // the operator based on whether this is the left or right operand of the expression. + // + // For example, if `a / d` is on the right of operator `*`, we need to parenthesize + // to preserve the intended order of operations: `x * (a / d)` + // + // If `a ** d` is on the left of operator `**`, we need to parenthesize to preserve + // the intended order of operations: `(a ** b) ** c` + var binaryOperatorPrecedence = ts.getOperatorPrecedence(200 /* BinaryExpression */, binaryOperator); + var binaryOperatorAssociativity = ts.getOperatorAssociativity(200 /* BinaryExpression */, binaryOperator); var emittedOperand = ts.skipPartiallyEmittedExpressions(operand); var operandPrecedence = ts.getExpressionPrecedence(emittedOperand); switch (ts.compareValues(operandPrecedence, binaryOperatorPrecedence)) { - case -1: + case -1 /* LessThan */: + // If the operand is the right side of a right-associative binary operation + // and is a yield expression, then we do not need parentheses. if (!isLeftSideOfBinary - && binaryOperatorAssociativity === 1 - && operand.kind === 203) { + && binaryOperatorAssociativity === 1 /* Right */ + && operand.kind === 203 /* YieldExpression */) { return false; } return true; - case 1: + case 1 /* GreaterThan */: return false; - case 0: + case 0 /* EqualTo */: if (isLeftSideOfBinary) { - return binaryOperatorAssociativity === 1; + // No need to parenthesize the left operand when the binary operator is + // left associative: + // (a*b)/x -> a*b/x + // (a**b)/x -> a**b/x + // + // Parentheses are needed for the left operand when the binary operator is + // right associative: + // (a/b)**x -> (a/b)**x + // (a**b)**x -> (a**b)**x + return binaryOperatorAssociativity === 1 /* Right */; } else { if (ts.isBinaryExpression(emittedOperand) && emittedOperand.operatorToken.kind === binaryOperator) { + // No need to parenthesize the right operand when the binary operator and + // operand are the same and one of the following: + // x*(a*b) => x*a*b + // x|(a|b) => x|a|b + // x&(a&b) => x&a&b + // x^(a^b) => x^a^b if (operatorHasAssociativeProperty(binaryOperator)) { return false; } - if (binaryOperator === 37) { - var leftKind = leftOperand ? getLiteralKindOfBinaryPlusOperand(leftOperand) : 0; + // No need to parenthesize the right operand when the binary operator + // is plus (+) if both the left and right operands consist solely of either + // literals of the same kind or binary plus (+) expressions for literals of + // the same kind (recursively). + // "a"+(1+2) => "a"+(1+2) + // "a"+("b"+"c") => "a"+"b"+"c" + if (binaryOperator === 37 /* PlusToken */) { + var leftKind = leftOperand ? getLiteralKindOfBinaryPlusOperand(leftOperand) : 0 /* Unknown */; if (ts.isLiteralKind(leftKind) && leftKind === getLiteralKindOfBinaryPlusOperand(emittedOperand)) { return false; } } } + // No need to parenthesize the right operand when the operand is right + // associative: + // x/(a**b) -> x/a**b + // x**(a**b) -> x**a**b + // + // Parentheses are needed for the right operand when the operand is left + // associative: + // x/(a*b) -> x/(a*b) + // x**(a/b) -> x**(a/b) var operandAssociativity = ts.getExpressionAssociativity(emittedOperand); - return operandAssociativity === 0; + return operandAssociativity === 0 /* Left */; } } } + /** + * Determines whether a binary operator is mathematically associative. + * + * @param binaryOperator The binary operator. + */ function operatorHasAssociativeProperty(binaryOperator) { - return binaryOperator === 39 - || binaryOperator === 49 - || binaryOperator === 48 - || binaryOperator === 50; + // The following operators are associative in JavaScript: + // (a*b)*c -> a*(b*c) -> a*b*c + // (a|b)|c -> a|(b|c) -> a|b|c + // (a&b)&c -> a&(b&c) -> a&b&c + // (a^b)^c -> a^(b^c) -> a^b^c + // + // While addition is associative in mathematics, JavaScript's `+` is not + // guaranteed to be associative as it is overloaded with string concatenation. + return binaryOperator === 39 /* AsteriskToken */ + || binaryOperator === 49 /* BarToken */ + || binaryOperator === 48 /* AmpersandToken */ + || binaryOperator === 50 /* CaretToken */; } + /** + * This function determines whether an expression consists of a homogeneous set of + * literal expressions or binary plus expressions that all share the same literal kind. + * It is used to determine whether the right-hand operand of a binary plus expression can be + * emitted without parentheses. + */ function getLiteralKindOfBinaryPlusOperand(node) { node = ts.skipPartiallyEmittedExpressions(node); if (ts.isLiteralKind(node.kind)) { return node.kind; } - if (node.kind === 200 && node.operatorToken.kind === 37) { + if (node.kind === 200 /* BinaryExpression */ && node.operatorToken.kind === 37 /* PlusToken */) { if (node.cachedLiteralKind !== undefined) { return node.cachedLiteralKind; } @@ -50637,46 +58805,66 @@ var ts; var literalKind = ts.isLiteralKind(leftKind) && leftKind === getLiteralKindOfBinaryPlusOperand(node.right) ? leftKind - : 0; + : 0 /* Unknown */; node.cachedLiteralKind = literalKind; return literalKind; } - return 0; + return 0 /* Unknown */; } function parenthesizeForConditionalHead(condition) { - var conditionalPrecedence = ts.getOperatorPrecedence(201, 55); + var conditionalPrecedence = ts.getOperatorPrecedence(201 /* ConditionalExpression */, 55 /* QuestionToken */); var emittedCondition = ts.skipPartiallyEmittedExpressions(condition); var conditionPrecedence = ts.getExpressionPrecedence(emittedCondition); - if (ts.compareValues(conditionPrecedence, conditionalPrecedence) === -1) { + if (ts.compareValues(conditionPrecedence, conditionalPrecedence) === -1 /* LessThan */) { return ts.createParen(condition); } return condition; } ts.parenthesizeForConditionalHead = parenthesizeForConditionalHead; function parenthesizeSubexpressionOfConditionalExpression(e) { + // per ES grammar both 'whenTrue' and 'whenFalse' parts of conditional expression are assignment expressions + // so in case when comma expression is introduced as a part of previous transformations + // if should be wrapped in parens since comma operator has the lowest precedence var emittedExpression = ts.skipPartiallyEmittedExpressions(e); - return emittedExpression.kind === 200 && emittedExpression.operatorToken.kind === 26 || - emittedExpression.kind === 303 + return emittedExpression.kind === 200 /* BinaryExpression */ && emittedExpression.operatorToken.kind === 26 /* CommaToken */ || + emittedExpression.kind === 303 /* CommaListExpression */ ? ts.createParen(e) : e; } ts.parenthesizeSubexpressionOfConditionalExpression = parenthesizeSubexpressionOfConditionalExpression; + /** + * [Per the spec](https://tc39.github.io/ecma262/#prod-ExportDeclaration), `export default` accepts _AssigmentExpression_ but + * has a lookahead restriction for `function`, `async function`, and `class`. + * + * Basically, that means we need to parenthesize in the following cases: + * + * - BinaryExpression of CommaToken + * - CommaList (synthetic list of multiple comma expressions) + * - FunctionExpression + * - ClassExpression + */ function parenthesizeDefaultExpression(e) { var check = ts.skipPartiallyEmittedExpressions(e); - return (check.kind === 205 || - check.kind === 192 || - check.kind === 303 || - ts.isBinaryExpression(check) && check.operatorToken.kind === 26) + return (check.kind === 205 /* ClassExpression */ || + check.kind === 192 /* FunctionExpression */ || + check.kind === 303 /* CommaListExpression */ || + ts.isBinaryExpression(check) && check.operatorToken.kind === 26 /* CommaToken */) ? ts.createParen(e) : e; } ts.parenthesizeDefaultExpression = parenthesizeDefaultExpression; + /** + * Wraps an expression in parentheses if it is needed in order to use the expression + * as the expression of a NewExpression node. + * + * @param expression The Expression node. + */ function parenthesizeForNew(expression) { - var leftmostExpr = getLeftmostExpression(expression, true); + var leftmostExpr = getLeftmostExpression(expression, /*stopAtCallExpressions*/ true); switch (leftmostExpr.kind) { - case 187: + case 187 /* CallExpression */: return ts.createParen(expression); - case 188: + case 188 /* NewExpression */: return !leftmostExpr.arguments ? ts.createParen(expression) : expression; @@ -50684,10 +58872,22 @@ var ts; return parenthesizeForAccess(expression); } ts.parenthesizeForNew = parenthesizeForNew; + /** + * Wraps an expression in parentheses if it is needed in order to use the expression for + * property or element access. + * + * @param expr The expression node. + */ function parenthesizeForAccess(expression) { + // isLeftHandSideExpression is almost the correct criterion for when it is not necessary + // to parenthesize the expression before a dot. The known exception is: + // + // NewExpression: + // new C.x -> not the same as (new C).x + // var emittedExpression = ts.skipPartiallyEmittedExpressions(expression); if (ts.isLeftHandSideExpression(emittedExpression) - && (emittedExpression.kind !== 188 || emittedExpression.arguments)) { + && (emittedExpression.kind !== 188 /* NewExpression */ || emittedExpression.arguments)) { return expression; } return ts.setTextRange(ts.createParen(expression), expression); @@ -50725,7 +58925,7 @@ var ts; function parenthesizeExpressionForList(expression) { var emittedExpression = ts.skipPartiallyEmittedExpressions(expression); var expressionPrecedence = ts.getExpressionPrecedence(emittedExpression); - var commaPrecedence = ts.getOperatorPrecedence(200, 26); + var commaPrecedence = ts.getOperatorPrecedence(200 /* BinaryExpression */, 26 /* CommaToken */); return expressionPrecedence > commaPrecedence ? expression : ts.setTextRange(ts.createParen(expression), expression); @@ -50736,29 +58936,29 @@ var ts; if (ts.isCallExpression(emittedExpression)) { var callee = emittedExpression.expression; var kind = ts.skipPartiallyEmittedExpressions(callee).kind; - if (kind === 192 || kind === 193) { + if (kind === 192 /* FunctionExpression */ || kind === 193 /* ArrowFunction */) { var mutableCall = ts.getMutableClone(emittedExpression); mutableCall.expression = ts.setTextRange(ts.createParen(callee), callee); - return recreateOuterExpressions(expression, mutableCall, 4); + return recreateOuterExpressions(expression, mutableCall, 4 /* PartiallyEmittedExpressions */); } } - var leftmostExpressionKind = getLeftmostExpression(emittedExpression, false).kind; - if (leftmostExpressionKind === 184 || leftmostExpressionKind === 192) { + var leftmostExpressionKind = getLeftmostExpression(emittedExpression, /*stopAtCallExpressions*/ false).kind; + if (leftmostExpressionKind === 184 /* ObjectLiteralExpression */ || leftmostExpressionKind === 192 /* FunctionExpression */) { return ts.setTextRange(ts.createParen(expression), expression); } return expression; } ts.parenthesizeExpressionForExpressionStatement = parenthesizeExpressionForExpressionStatement; function parenthesizeConditionalTypeMember(member) { - return member.kind === 171 ? ts.createParenthesizedType(member) : member; + return member.kind === 171 /* ConditionalType */ ? ts.createParenthesizedType(member) : member; } ts.parenthesizeConditionalTypeMember = parenthesizeConditionalTypeMember; function parenthesizeElementTypeMember(member) { switch (member.kind) { - case 169: - case 170: - case 163: - case 164: + case 169 /* UnionType */: + case 170 /* IntersectionType */: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: return ts.createParenthesizedType(member); } return parenthesizeConditionalTypeMember(member); @@ -50766,9 +58966,9 @@ var ts; ts.parenthesizeElementTypeMember = parenthesizeElementTypeMember; function parenthesizeArrayTypeMember(member) { switch (member.kind) { - case 165: - case 175: - case 172: + case 165 /* TypeQuery */: + case 175 /* TypeOperator */: + case 172 /* InferType */: return ts.createParenthesizedType(member); } return parenthesizeElementTypeMember(member); @@ -50794,24 +58994,25 @@ var ts; function getLeftmostExpression(node, stopAtCallExpressions) { while (true) { switch (node.kind) { - case 199: + case 199 /* PostfixUnaryExpression */: node = node.operand; continue; - case 200: + case 200 /* BinaryExpression */: node = node.left; continue; - case 201: + case 201 /* ConditionalExpression */: node = node.condition; continue; - case 187: + case 187 /* CallExpression */: if (stopAtCallExpressions) { return node; } - case 186: - case 185: + // falls through + case 186 /* ElementAccessExpression */: + case 185 /* PropertyAccessExpression */: node = node.expression; continue; - case 302: + case 302 /* PartiallyEmittedExpression */: node = node.expression; continue; } @@ -50819,7 +59020,7 @@ var ts; } } function parenthesizeConciseBody(body) { - if (!ts.isBlock(body) && getLeftmostExpression(body, false).kind === 184) { + if (!ts.isBlock(body) && getLeftmostExpression(body, /*stopAtCallExpressions*/ false).kind === 184 /* ObjectLiteralExpression */) { return ts.setTextRange(ts.createParen(body), body); } return body; @@ -50833,32 +59034,32 @@ var ts; OuterExpressionKinds[OuterExpressionKinds["All"] = 7] = "All"; })(OuterExpressionKinds = ts.OuterExpressionKinds || (ts.OuterExpressionKinds = {})); function isOuterExpression(node, kinds) { - if (kinds === void 0) { kinds = 7; } + if (kinds === void 0) { kinds = 7 /* All */; } switch (node.kind) { - case 191: - return (kinds & 1) !== 0; - case 190: - case 208: - case 209: - return (kinds & 2) !== 0; - case 302: - return (kinds & 4) !== 0; + case 191 /* ParenthesizedExpression */: + return (kinds & 1 /* Parentheses */) !== 0; + case 190 /* TypeAssertionExpression */: + case 208 /* AsExpression */: + case 209 /* NonNullExpression */: + return (kinds & 2 /* Assertions */) !== 0; + case 302 /* PartiallyEmittedExpression */: + return (kinds & 4 /* PartiallyEmittedExpressions */) !== 0; } return false; } ts.isOuterExpression = isOuterExpression; function skipOuterExpressions(node, kinds) { - if (kinds === void 0) { kinds = 7; } + if (kinds === void 0) { kinds = 7 /* All */; } var previousNode; do { previousNode = node; - if (kinds & 1) { + if (kinds & 1 /* Parentheses */) { node = ts.skipParentheses(node); } - if (kinds & 2) { + if (kinds & 2 /* Assertions */) { node = skipAssertions(node); } - if (kinds & 4) { + if (kinds & 4 /* PartiallyEmittedExpressions */) { node = ts.skipPartiallyEmittedExpressions(node); } } while (previousNode !== node); @@ -50866,7 +59067,7 @@ var ts; } ts.skipOuterExpressions = skipOuterExpressions; function skipAssertions(node) { - while (ts.isAssertionExpression(node) || node.kind === 209) { + while (ts.isAssertionExpression(node) || node.kind === 209 /* NonNullExpression */) { node = node.expression; } return node; @@ -50874,15 +59075,29 @@ var ts; ts.skipAssertions = skipAssertions; function updateOuterExpression(outerExpression, expression) { switch (outerExpression.kind) { - case 191: return ts.updateParen(outerExpression, expression); - case 190: return ts.updateTypeAssertion(outerExpression, outerExpression.type, expression); - case 208: return ts.updateAsExpression(outerExpression, expression, outerExpression.type); - case 209: return ts.updateNonNullExpression(outerExpression, expression); - case 302: return ts.updatePartiallyEmittedExpression(outerExpression, expression); + case 191 /* ParenthesizedExpression */: return ts.updateParen(outerExpression, expression); + case 190 /* TypeAssertionExpression */: return ts.updateTypeAssertion(outerExpression, outerExpression.type, expression); + case 208 /* AsExpression */: return ts.updateAsExpression(outerExpression, expression, outerExpression.type); + case 209 /* NonNullExpression */: return ts.updateNonNullExpression(outerExpression, expression); + case 302 /* PartiallyEmittedExpression */: return ts.updatePartiallyEmittedExpression(outerExpression, expression); } } + /** + * Determines whether a node is a parenthesized expression that can be ignored when recreating outer expressions. + * + * A parenthesized expression can be ignored when all of the following are true: + * + * - It's `pos` and `end` are not -1 + * - It does not have a custom source map range + * - It does not have a custom comment range + * - It does not have synthetic leading or trailing comments + * + * If an outermost parenthesized expression is ignored, but the containing expression requires a parentheses around + * the expression to maintain precedence, a new parenthesized expression should be created automatically when + * the containing expression is created/updated. + */ function isIgnorableParen(node) { - return node.kind === 191 + return node.kind === 191 /* ParenthesizedExpression */ && ts.nodeIsSynthesized(node) && ts.nodeIsSynthesized(ts.getSourceMapRange(node)) && ts.nodeIsSynthesized(ts.getCommentRange(node)) @@ -50890,7 +59105,7 @@ var ts; && !ts.some(ts.getSyntheticTrailingComments(node)); } function recreateOuterExpressions(outerExpression, innerExpression, kinds) { - if (kinds === void 0) { kinds = 7; } + if (kinds === void 0) { kinds = 7 /* All */; } if (outerExpression && isOuterExpression(outerExpression, kinds) && !isIgnorableParen(outerExpression)) { return updateOuterExpression(outerExpression, recreateOuterExpressions(outerExpression.expression, innerExpression)); } @@ -50898,7 +59113,7 @@ var ts; } ts.recreateOuterExpressions = recreateOuterExpressions; function startOnNewLine(node) { - return ts.setStartsOnNewLine(node, true); + return ts.setStartsOnNewLine(node, /*newLine*/ true); } ts.startOnNewLine = startOnNewLine; function getExternalHelpersModuleName(node) { @@ -50938,24 +59153,35 @@ var ts; } } ts.getOrCreateExternalHelpersModuleNameIfNeeded = getOrCreateExternalHelpersModuleNameIfNeeded; + /** + * Get the name of that target module from an import or export declaration + */ function getLocalNameForExternalImport(node, sourceFile) { var namespaceDeclaration = ts.getNamespaceDeclarationNode(node); if (namespaceDeclaration && !ts.isDefaultImport(node)) { var name = namespaceDeclaration.name; return ts.isGeneratedIdentifier(name) ? name : ts.createIdentifier(ts.getSourceTextOfNodeFromSourceFile(sourceFile, name) || ts.idText(name)); } - if (node.kind === 244 && node.importClause) { + if (node.kind === 244 /* ImportDeclaration */ && node.importClause) { return ts.getGeneratedNameForNode(node); } - if (node.kind === 250 && node.moduleSpecifier) { + if (node.kind === 250 /* ExportDeclaration */ && node.moduleSpecifier) { return ts.getGeneratedNameForNode(node); } return undefined; } ts.getLocalNameForExternalImport = getLocalNameForExternalImport; + /** + * Get the name of a target module from an import/export declaration as should be written in the emitted output. + * The emitted output name can be different from the input if: + * 1. The module has a /// + * 2. --out or --outFile is used, making the name relative to the rootDir + * 3- The containing SourceFile has an entry in renamedDependencies for the import as requested by some module loaders (e.g. System). + * Otherwise, a new StringLiteral node representing the module name will be returned. + */ function getExternalModuleNameLiteral(importNode, sourceFile, host, resolver, compilerOptions) { - var moduleName = ts.getExternalModuleName(importNode); - if (moduleName.kind === 9) { + var moduleName = ts.getExternalModuleName(importNode); // TODO: GH#18217 + if (moduleName.kind === 9 /* StringLiteral */) { return tryGetModuleNameFromDeclaration(importNode, host, resolver, compilerOptions) || tryRenameExternalModule(moduleName, sourceFile) || ts.getSynthesizedClone(moduleName); @@ -50963,10 +59189,21 @@ var ts; return undefined; } ts.getExternalModuleNameLiteral = getExternalModuleNameLiteral; + /** + * 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, sourceFile) { var rename = sourceFile.renamedDependencies && sourceFile.renamedDependencies.get(moduleName.text); return rename && ts.createLiteral(rename); } + /** + * Get the name of a module as should be written in the emitted output. + * The emitted output name can be different from the input if: + * 1. The module has a /// + * 2. --out or --outFile is used, making the name relative to the rootDir + * Otherwise, a new StringLiteral node representing the module name will be returned. + */ function tryGetModuleNameFromFile(file, host, options) { if (!file) { return undefined; @@ -50983,66 +59220,140 @@ var ts; function tryGetModuleNameFromDeclaration(declaration, host, resolver, compilerOptions) { return tryGetModuleNameFromFile(resolver.getExternalModuleFileFromDeclaration(declaration), host, compilerOptions); } + /** + * Gets the initializer of an BindingOrAssignmentElement. + */ function getInitializerOfBindingOrAssignmentElement(bindingElement) { if (ts.isDeclarationBindingElement(bindingElement)) { + // `1` in `let { a = 1 } = ...` + // `1` in `let { a: b = 1 } = ...` + // `1` in `let { a: {b} = 1 } = ...` + // `1` in `let { a: [b] = 1 } = ...` + // `1` in `let [a = 1] = ...` + // `1` in `let [{a} = 1] = ...` + // `1` in `let [[a] = 1] = ...` return bindingElement.initializer; } if (ts.isPropertyAssignment(bindingElement)) { + // `1` in `({ a: b = 1 } = ...)` + // `1` in `({ a: {b} = 1 } = ...)` + // `1` in `({ a: [b] = 1 } = ...)` var initializer = bindingElement.initializer; - return ts.isAssignmentExpression(initializer, true) + return ts.isAssignmentExpression(initializer, /*excludeCompoundAssignment*/ true) ? initializer.right : undefined; } if (ts.isShorthandPropertyAssignment(bindingElement)) { + // `1` in `({ a = 1 } = ...)` return bindingElement.objectAssignmentInitializer; } - if (ts.isAssignmentExpression(bindingElement, true)) { + if (ts.isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) { + // `1` in `[a = 1] = ...` + // `1` in `[{a} = 1] = ...` + // `1` in `[[a] = 1] = ...` return bindingElement.right; } if (ts.isSpreadElement(bindingElement)) { + // Recovery consistent with existing emit. return getInitializerOfBindingOrAssignmentElement(bindingElement.expression); } } ts.getInitializerOfBindingOrAssignmentElement = getInitializerOfBindingOrAssignmentElement; + /** + * Gets the name of an BindingOrAssignmentElement. + */ function getTargetOfBindingOrAssignmentElement(bindingElement) { if (ts.isDeclarationBindingElement(bindingElement)) { + // `a` in `let { a } = ...` + // `a` in `let { a = 1 } = ...` + // `b` in `let { a: b } = ...` + // `b` in `let { a: b = 1 } = ...` + // `a` in `let { ...a } = ...` + // `{b}` in `let { a: {b} } = ...` + // `{b}` in `let { a: {b} = 1 } = ...` + // `[b]` in `let { a: [b] } = ...` + // `[b]` in `let { a: [b] = 1 } = ...` + // `a` in `let [a] = ...` + // `a` in `let [a = 1] = ...` + // `a` in `let [...a] = ...` + // `{a}` in `let [{a}] = ...` + // `{a}` in `let [{a} = 1] = ...` + // `[a]` in `let [[a]] = ...` + // `[a]` in `let [[a] = 1] = ...` return bindingElement.name; } if (ts.isObjectLiteralElementLike(bindingElement)) { switch (bindingElement.kind) { - case 270: + case 270 /* PropertyAssignment */: + // `b` in `({ a: b } = ...)` + // `b` in `({ a: b = 1 } = ...)` + // `{b}` in `({ a: {b} } = ...)` + // `{b}` in `({ a: {b} = 1 } = ...)` + // `[b]` in `({ a: [b] } = ...)` + // `[b]` in `({ a: [b] = 1 } = ...)` + // `b.c` in `({ a: b.c } = ...)` + // `b.c` in `({ a: b.c = 1 } = ...)` + // `b[0]` in `({ a: b[0] } = ...)` + // `b[0]` in `({ a: b[0] = 1 } = ...)` return getTargetOfBindingOrAssignmentElement(bindingElement.initializer); - case 271: + case 271 /* ShorthandPropertyAssignment */: + // `a` in `({ a } = ...)` + // `a` in `({ a = 1 } = ...)` return bindingElement.name; - case 272: + case 272 /* SpreadAssignment */: + // `a` in `({ ...a } = ...)` return getTargetOfBindingOrAssignmentElement(bindingElement.expression); } + // no target return undefined; } - if (ts.isAssignmentExpression(bindingElement, true)) { + if (ts.isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) { + // `a` in `[a = 1] = ...` + // `{a}` in `[{a} = 1] = ...` + // `[a]` in `[[a] = 1] = ...` + // `a.b` in `[a.b = 1] = ...` + // `a[0]` in `[a[0] = 1] = ...` return getTargetOfBindingOrAssignmentElement(bindingElement.left); } if (ts.isSpreadElement(bindingElement)) { + // `a` in `[...a] = ...` return getTargetOfBindingOrAssignmentElement(bindingElement.expression); } + // `a` in `[a] = ...` + // `{a}` in `[{a}] = ...` + // `[a]` in `[[a]] = ...` + // `a.b` in `[a.b] = ...` + // `a[0]` in `[a[0]] = ...` return bindingElement; } ts.getTargetOfBindingOrAssignmentElement = getTargetOfBindingOrAssignmentElement; + /** + * Determines whether an BindingOrAssignmentElement is a rest element. + */ function getRestIndicatorOfBindingOrAssignmentElement(bindingElement) { switch (bindingElement.kind) { - case 149: - case 182: + case 149 /* Parameter */: + case 182 /* BindingElement */: + // `...` in `let [...a] = ...` return bindingElement.dotDotDotToken; - case 204: - case 272: + case 204 /* SpreadElement */: + case 272 /* SpreadAssignment */: + // `...` in `[...a] = ...` return bindingElement; } return undefined; } ts.getRestIndicatorOfBindingOrAssignmentElement = getRestIndicatorOfBindingOrAssignmentElement; + /** + * Gets the property name of a BindingOrAssignmentElement + */ function getPropertyNameOfBindingOrAssignmentElement(bindingElement) { switch (bindingElement.kind) { - case 182: + case 182 /* BindingElement */: + // `a` in `let { a: b } = ...` + // `[a]` in `let { [a]: b } = ...` + // `"a"` in `let { "a": b } = ...` + // `1` in `let { 1: b } = ...` if (bindingElement.propertyName) { var propertyName = bindingElement.propertyName; return ts.isComputedPropertyName(propertyName) && ts.isStringOrNumericLiteral(propertyName.expression) @@ -51050,7 +59361,11 @@ var ts; : propertyName; } break; - case 270: + case 270 /* PropertyAssignment */: + // `a` in `({ a: b } = ...)` + // `[a]` in `({ [a]: b } = ...)` + // `"a"` in `({ "a": b } = ...)` + // `1` in `({ 1: b } = ...)` if (bindingElement.name) { var propertyName = bindingElement.name; return ts.isComputedPropertyName(propertyName) && ts.isStringOrNumericLiteral(propertyName.expression) @@ -51058,7 +59373,8 @@ var ts; : propertyName; } break; - case 272: + case 272 /* SpreadAssignment */: + // `a` in `({ ...a } = ...)` return bindingElement.name; } var target = getTargetOfBindingOrAssignmentElement(bindingElement); @@ -51070,13 +59386,19 @@ var ts; ts.Debug.fail("Invalid property name for binding element."); } ts.getPropertyNameOfBindingOrAssignmentElement = getPropertyNameOfBindingOrAssignmentElement; + /** + * Gets the elements of a BindingOrAssignmentPattern + */ function getElementsOfBindingOrAssignmentPattern(name) { switch (name.kind) { - case 180: - case 181: - case 183: + case 180 /* ObjectBindingPattern */: + case 181 /* ArrayBindingPattern */: + case 183 /* ArrayLiteralExpression */: + // `a` in `{a}` + // `a` in `[a]` return name.elements; - case 184: + case 184 /* ObjectLiteralExpression */: + // `a` in `{a}` return name.properties; } } @@ -51115,11 +59437,11 @@ var ts; ts.convertToObjectAssignmentElement = convertToObjectAssignmentElement; function convertToAssignmentPattern(node) { switch (node.kind) { - case 181: - case 183: + case 181 /* ArrayBindingPattern */: + case 183 /* ArrayLiteralExpression */: return convertToArrayAssignmentPattern(node); - case 180: - case 184: + case 180 /* ObjectBindingPattern */: + case 184 /* ObjectLiteralExpression */: return convertToObjectAssignmentPattern(node); } } @@ -51176,11 +59498,21 @@ var ts; return visitedNode; } ts.visitNode = visitNode; + /** + * Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place. + * + * @param nodes The NodeArray to visit. + * @param visitor The callback used to visit a Node. + * @param test A node test to execute for each node. + * @param start An optional value indicating the starting offset at which to start visiting. + * @param count An optional value indicating the maximum number of nodes to visit. + */ function visitNodes(nodes, visitor, test, start, count) { if (nodes === undefined || visitor === undefined) { return nodes; } var updated; + // Ensure start and count have valid values var length = nodes.length; if (start === undefined || start < 0) { start = 0; @@ -51189,14 +59521,19 @@ var ts; count = length - start; } if (start > 0 || count < length) { - updated = ts.createNodeArray([], nodes.hasTrailingComma && start + count === length); + // If we are not visiting all of the original nodes, we must always create a new array. + // Since this is a fragment of a node array, we do not copy over the previous location + // and will only copy over `hasTrailingComma` if we are including the last element. + updated = ts.createNodeArray([], /*hasTrailingComma*/ nodes.hasTrailingComma && start + count === length); } + // Visit each original node. for (var i = 0; i < count; i++) { var node = nodes[i + start]; ts.aggregateTransformFlags(node); var visited = node !== undefined ? visitor(node) : undefined; if (updated !== undefined || visited === undefined || visited !== node) { if (updated === undefined) { + // Ensure we have a copy of `nodes`, up to the current index. updated = ts.createNodeArray(nodes.slice(0, i), nodes.hasTrailingComma); ts.setTextRange(updated, nodes); } @@ -51220,6 +59557,10 @@ var ts; return updated || nodes; } ts.visitNodes = visitNodes; + /** + * Starts a new lexical environment and visits a statement list, ending the lexical environment + * and merging hoisted declarations upon completion. + */ function visitLexicalEnvironment(statements, visitor, context, start, ensureUseStrict) { context.startLexicalEnvironment(); statements = visitNodes(statements, visitor, ts.isStatement, start); @@ -51230,6 +59571,10 @@ var ts; return ts.setTextRange(ts.createNodeArray(ts.concatenate(declarations, statements)), statements); } ts.visitLexicalEnvironment = visitLexicalEnvironment; + /** + * Starts a new lexical environment and visits a parameter list, suspending the lexical + * environment upon completion. + */ function visitParameterList(nodes, visitor, context, nodesVisitor) { if (nodesVisitor === void 0) { nodesVisitor = visitNodes; } context.startLexicalEnvironment(); @@ -51256,268 +59601,291 @@ var ts; return undefined; } var kind = node.kind; - if ((kind > 0 && kind <= 145) || kind === 174) { + // No need to visit nodes with no children. + if ((kind > 0 /* FirstToken */ && kind <= 145 /* LastToken */) || kind === 174 /* ThisType */) { return node; } switch (kind) { - case 71: + // Names + case 71 /* Identifier */: return ts.updateIdentifier(node, nodesVisitor(node.typeArguments, visitor, isTypeNodeOrTypeParameterDeclaration)); - case 146: + case 146 /* QualifiedName */: return ts.updateQualifiedName(node, visitNode(node.left, visitor, ts.isEntityName), visitNode(node.right, visitor, ts.isIdentifier)); - case 147: + case 147 /* ComputedPropertyName */: return ts.updateComputedPropertyName(node, visitNode(node.expression, visitor, ts.isExpression)); - case 148: + // Signature elements + case 148 /* TypeParameter */: return ts.updateTypeParameterDeclaration(node, visitNode(node.name, visitor, ts.isIdentifier), visitNode(node.constraint, visitor, ts.isTypeNode), visitNode(node.default, visitor, ts.isTypeNode)); - case 149: + case 149 /* Parameter */: return ts.updateParameter(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.dotDotDotToken, tokenVisitor, ts.isToken), visitNode(node.name, visitor, ts.isBindingName), visitNode(node.questionToken, tokenVisitor, ts.isToken), visitNode(node.type, visitor, ts.isTypeNode), visitNode(node.initializer, visitor, ts.isExpression)); - case 150: + case 150 /* Decorator */: return ts.updateDecorator(node, visitNode(node.expression, visitor, ts.isExpression)); - case 151: + // Type elements + case 151 /* PropertySignature */: return ts.updatePropertySignature(node, nodesVisitor(node.modifiers, visitor, ts.isToken), visitNode(node.name, visitor, ts.isPropertyName), visitNode(node.questionToken, tokenVisitor, ts.isToken), visitNode(node.type, visitor, ts.isTypeNode), visitNode(node.initializer, visitor, ts.isExpression)); - case 152: + case 152 /* PropertyDeclaration */: return ts.updateProperty(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isPropertyName), visitNode(node.questionToken, tokenVisitor, ts.isToken), visitNode(node.type, visitor, ts.isTypeNode), visitNode(node.initializer, visitor, ts.isExpression)); - case 153: + case 153 /* MethodSignature */: return ts.updateMethodSignature(node, nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), nodesVisitor(node.parameters, visitor, ts.isParameterDeclaration), visitNode(node.type, visitor, ts.isTypeNode), visitNode(node.name, visitor, ts.isPropertyName), visitNode(node.questionToken, tokenVisitor, ts.isToken)); - case 154: + case 154 /* MethodDeclaration */: return ts.updateMethod(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.asteriskToken, tokenVisitor, ts.isToken), visitNode(node.name, visitor, ts.isPropertyName), visitNode(node.questionToken, tokenVisitor, ts.isToken), nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), visitParameterList(node.parameters, visitor, context, nodesVisitor), visitNode(node.type, visitor, ts.isTypeNode), visitFunctionBody(node.body, visitor, context)); - case 155: + case 155 /* Constructor */: return ts.updateConstructor(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitParameterList(node.parameters, visitor, context, nodesVisitor), visitFunctionBody(node.body, visitor, context)); - case 156: + case 156 /* GetAccessor */: return ts.updateGetAccessor(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isPropertyName), visitParameterList(node.parameters, visitor, context, nodesVisitor), visitNode(node.type, visitor, ts.isTypeNode), visitFunctionBody(node.body, visitor, context)); - case 157: + case 157 /* SetAccessor */: return ts.updateSetAccessor(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isPropertyName), visitParameterList(node.parameters, visitor, context, nodesVisitor), visitFunctionBody(node.body, visitor, context)); - case 158: + case 158 /* CallSignature */: return ts.updateCallSignature(node, nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), nodesVisitor(node.parameters, visitor, ts.isParameterDeclaration), visitNode(node.type, visitor, ts.isTypeNode)); - case 159: + case 159 /* ConstructSignature */: return ts.updateConstructSignature(node, nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), nodesVisitor(node.parameters, visitor, ts.isParameterDeclaration), visitNode(node.type, visitor, ts.isTypeNode)); - case 160: + case 160 /* IndexSignature */: return ts.updateIndexSignature(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), nodesVisitor(node.parameters, visitor, ts.isParameterDeclaration), visitNode(node.type, visitor, ts.isTypeNode)); - case 161: + // Types + case 161 /* TypePredicate */: return ts.updateTypePredicateNode(node, visitNode(node.parameterName, visitor), visitNode(node.type, visitor, ts.isTypeNode)); - case 162: + case 162 /* TypeReference */: return ts.updateTypeReferenceNode(node, visitNode(node.typeName, visitor, ts.isEntityName), nodesVisitor(node.typeArguments, visitor, ts.isTypeNode)); - case 163: + case 163 /* FunctionType */: return ts.updateFunctionTypeNode(node, nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), nodesVisitor(node.parameters, visitor, ts.isParameterDeclaration), visitNode(node.type, visitor, ts.isTypeNode)); - case 164: + case 164 /* ConstructorType */: return ts.updateConstructorTypeNode(node, nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), nodesVisitor(node.parameters, visitor, ts.isParameterDeclaration), visitNode(node.type, visitor, ts.isTypeNode)); - case 165: + case 165 /* TypeQuery */: return ts.updateTypeQueryNode(node, visitNode(node.exprName, visitor, ts.isEntityName)); - case 166: + case 166 /* TypeLiteral */: return ts.updateTypeLiteralNode(node, nodesVisitor(node.members, visitor, ts.isTypeElement)); - case 167: + case 167 /* ArrayType */: return ts.updateArrayTypeNode(node, visitNode(node.elementType, visitor, ts.isTypeNode)); - case 168: + case 168 /* TupleType */: return ts.updateTypleTypeNode(node, nodesVisitor(node.elementTypes, visitor, ts.isTypeNode)); - case 169: + case 169 /* UnionType */: return ts.updateUnionTypeNode(node, nodesVisitor(node.types, visitor, ts.isTypeNode)); - case 170: + case 170 /* IntersectionType */: return ts.updateIntersectionTypeNode(node, nodesVisitor(node.types, visitor, ts.isTypeNode)); - case 171: + case 171 /* ConditionalType */: return ts.updateConditionalTypeNode(node, visitNode(node.checkType, visitor, ts.isTypeNode), visitNode(node.extendsType, visitor, ts.isTypeNode), visitNode(node.trueType, visitor, ts.isTypeNode), visitNode(node.falseType, visitor, ts.isTypeNode)); - case 172: + case 172 /* InferType */: return ts.updateInferTypeNode(node, visitNode(node.typeParameter, visitor, ts.isTypeParameterDeclaration)); - case 179: + case 179 /* ImportType */: return ts.updateImportTypeNode(node, visitNode(node.argument, visitor, ts.isTypeNode), visitNode(node.qualifier, visitor, ts.isEntityName), visitNodes(node.typeArguments, visitor, ts.isTypeNode), node.isTypeOf); - case 173: + case 173 /* ParenthesizedType */: return ts.updateParenthesizedType(node, visitNode(node.type, visitor, ts.isTypeNode)); - case 175: + case 175 /* TypeOperator */: return ts.updateTypeOperatorNode(node, visitNode(node.type, visitor, ts.isTypeNode)); - case 176: + case 176 /* IndexedAccessType */: return ts.updateIndexedAccessTypeNode(node, visitNode(node.objectType, visitor, ts.isTypeNode), visitNode(node.indexType, visitor, ts.isTypeNode)); - case 177: + case 177 /* MappedType */: return ts.updateMappedTypeNode(node, visitNode(node.readonlyToken, tokenVisitor, ts.isToken), visitNode(node.typeParameter, visitor, ts.isTypeParameterDeclaration), visitNode(node.questionToken, tokenVisitor, ts.isToken), visitNode(node.type, visitor, ts.isTypeNode)); - case 178: + case 178 /* LiteralType */: return ts.updateLiteralTypeNode(node, visitNode(node.literal, visitor, ts.isExpression)); - case 180: + // Binding patterns + case 180 /* ObjectBindingPattern */: return ts.updateObjectBindingPattern(node, nodesVisitor(node.elements, visitor, ts.isBindingElement)); - case 181: + case 181 /* ArrayBindingPattern */: return ts.updateArrayBindingPattern(node, nodesVisitor(node.elements, visitor, ts.isArrayBindingElement)); - case 182: + case 182 /* BindingElement */: return ts.updateBindingElement(node, visitNode(node.dotDotDotToken, tokenVisitor, ts.isToken), visitNode(node.propertyName, visitor, ts.isPropertyName), visitNode(node.name, visitor, ts.isBindingName), visitNode(node.initializer, visitor, ts.isExpression)); - case 183: + // Expression + case 183 /* ArrayLiteralExpression */: return ts.updateArrayLiteral(node, nodesVisitor(node.elements, visitor, ts.isExpression)); - case 184: + case 184 /* ObjectLiteralExpression */: return ts.updateObjectLiteral(node, nodesVisitor(node.properties, visitor, ts.isObjectLiteralElementLike)); - case 185: + case 185 /* PropertyAccessExpression */: return ts.updatePropertyAccess(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.name, visitor, ts.isIdentifier)); - case 186: + case 186 /* ElementAccessExpression */: return ts.updateElementAccess(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.argumentExpression, visitor, ts.isExpression)); - case 187: + case 187 /* CallExpression */: return ts.updateCall(node, visitNode(node.expression, visitor, ts.isExpression), nodesVisitor(node.typeArguments, visitor, ts.isTypeNode), nodesVisitor(node.arguments, visitor, ts.isExpression)); - case 188: + case 188 /* NewExpression */: return ts.updateNew(node, visitNode(node.expression, visitor, ts.isExpression), nodesVisitor(node.typeArguments, visitor, ts.isTypeNode), nodesVisitor(node.arguments, visitor, ts.isExpression)); - case 189: + case 189 /* TaggedTemplateExpression */: return ts.updateTaggedTemplate(node, visitNode(node.tag, visitor, ts.isExpression), visitNodes(node.typeArguments, visitor, ts.isExpression), visitNode(node.template, visitor, ts.isTemplateLiteral)); - case 190: + case 190 /* TypeAssertionExpression */: return ts.updateTypeAssertion(node, visitNode(node.type, visitor, ts.isTypeNode), visitNode(node.expression, visitor, ts.isExpression)); - case 191: + case 191 /* ParenthesizedExpression */: return ts.updateParen(node, visitNode(node.expression, visitor, ts.isExpression)); - case 192: + case 192 /* FunctionExpression */: return ts.updateFunctionExpression(node, nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.asteriskToken, tokenVisitor, ts.isToken), visitNode(node.name, visitor, ts.isIdentifier), nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), visitParameterList(node.parameters, visitor, context, nodesVisitor), visitNode(node.type, visitor, ts.isTypeNode), visitFunctionBody(node.body, visitor, context)); - case 193: + case 193 /* ArrowFunction */: return ts.updateArrowFunction(node, nodesVisitor(node.modifiers, visitor, ts.isModifier), nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), visitParameterList(node.parameters, visitor, context, nodesVisitor), visitNode(node.type, visitor, ts.isTypeNode), visitNode(node.equalsGreaterThanToken, visitor, ts.isToken), visitFunctionBody(node.body, visitor, context)); - case 194: + case 194 /* DeleteExpression */: return ts.updateDelete(node, visitNode(node.expression, visitor, ts.isExpression)); - case 195: + case 195 /* TypeOfExpression */: return ts.updateTypeOf(node, visitNode(node.expression, visitor, ts.isExpression)); - case 196: + case 196 /* VoidExpression */: return ts.updateVoid(node, visitNode(node.expression, visitor, ts.isExpression)); - case 197: + case 197 /* AwaitExpression */: return ts.updateAwait(node, visitNode(node.expression, visitor, ts.isExpression)); - case 198: + case 198 /* PrefixUnaryExpression */: return ts.updatePrefix(node, visitNode(node.operand, visitor, ts.isExpression)); - case 199: + case 199 /* PostfixUnaryExpression */: return ts.updatePostfix(node, visitNode(node.operand, visitor, ts.isExpression)); - case 200: + case 200 /* BinaryExpression */: return ts.updateBinary(node, visitNode(node.left, visitor, ts.isExpression), visitNode(node.right, visitor, ts.isExpression), visitNode(node.operatorToken, visitor, ts.isToken)); - case 201: + case 201 /* ConditionalExpression */: return ts.updateConditional(node, visitNode(node.condition, visitor, ts.isExpression), visitNode(node.questionToken, visitor, ts.isToken), visitNode(node.whenTrue, visitor, ts.isExpression), visitNode(node.colonToken, visitor, ts.isToken), visitNode(node.whenFalse, visitor, ts.isExpression)); - case 202: + case 202 /* TemplateExpression */: return ts.updateTemplateExpression(node, visitNode(node.head, visitor, ts.isTemplateHead), nodesVisitor(node.templateSpans, visitor, ts.isTemplateSpan)); - case 203: + case 203 /* YieldExpression */: return ts.updateYield(node, visitNode(node.asteriskToken, tokenVisitor, ts.isToken), visitNode(node.expression, visitor, ts.isExpression)); - case 204: + case 204 /* SpreadElement */: return ts.updateSpread(node, visitNode(node.expression, visitor, ts.isExpression)); - case 205: + case 205 /* ClassExpression */: return ts.updateClassExpression(node, nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isIdentifier), nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), nodesVisitor(node.heritageClauses, visitor, ts.isHeritageClause), nodesVisitor(node.members, visitor, ts.isClassElement)); - case 207: + case 207 /* ExpressionWithTypeArguments */: return ts.updateExpressionWithTypeArguments(node, nodesVisitor(node.typeArguments, visitor, ts.isTypeNode), visitNode(node.expression, visitor, ts.isExpression)); - case 208: + case 208 /* AsExpression */: return ts.updateAsExpression(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.type, visitor, ts.isTypeNode)); - case 209: + case 209 /* NonNullExpression */: return ts.updateNonNullExpression(node, visitNode(node.expression, visitor, ts.isExpression)); - case 210: + case 210 /* MetaProperty */: return ts.updateMetaProperty(node, visitNode(node.name, visitor, ts.isIdentifier)); - case 211: + // Misc + case 211 /* TemplateSpan */: return ts.updateTemplateSpan(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.literal, visitor, ts.isTemplateMiddleOrTemplateTail)); - case 213: + // Element + case 213 /* Block */: return ts.updateBlock(node, nodesVisitor(node.statements, visitor, ts.isStatement)); - case 214: + case 214 /* VariableStatement */: return ts.updateVariableStatement(node, nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.declarationList, visitor, ts.isVariableDeclarationList)); - case 216: + case 216 /* ExpressionStatement */: return ts.updateStatement(node, visitNode(node.expression, visitor, ts.isExpression)); - case 217: + case 217 /* IfStatement */: return ts.updateIf(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.thenStatement, visitor, ts.isStatement, ts.liftToBlock), visitNode(node.elseStatement, visitor, ts.isStatement, ts.liftToBlock)); - case 218: + case 218 /* DoStatement */: return ts.updateDo(node, visitNode(node.statement, visitor, ts.isStatement, ts.liftToBlock), visitNode(node.expression, visitor, ts.isExpression)); - case 219: + case 219 /* WhileStatement */: return ts.updateWhile(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.statement, visitor, ts.isStatement, ts.liftToBlock)); - case 220: + case 220 /* ForStatement */: return ts.updateFor(node, visitNode(node.initializer, visitor, ts.isForInitializer), visitNode(node.condition, visitor, ts.isExpression), visitNode(node.incrementor, visitor, ts.isExpression), visitNode(node.statement, visitor, ts.isStatement, ts.liftToBlock)); - case 221: + case 221 /* ForInStatement */: return ts.updateForIn(node, visitNode(node.initializer, visitor, ts.isForInitializer), visitNode(node.expression, visitor, ts.isExpression), visitNode(node.statement, visitor, ts.isStatement, ts.liftToBlock)); - case 222: + case 222 /* ForOfStatement */: return ts.updateForOf(node, visitNode(node.awaitModifier, visitor, ts.isToken), visitNode(node.initializer, visitor, ts.isForInitializer), visitNode(node.expression, visitor, ts.isExpression), visitNode(node.statement, visitor, ts.isStatement, ts.liftToBlock)); - case 223: + case 223 /* ContinueStatement */: return ts.updateContinue(node, visitNode(node.label, visitor, ts.isIdentifier)); - case 224: + case 224 /* BreakStatement */: return ts.updateBreak(node, visitNode(node.label, visitor, ts.isIdentifier)); - case 225: + case 225 /* ReturnStatement */: return ts.updateReturn(node, visitNode(node.expression, visitor, ts.isExpression)); - case 226: + case 226 /* WithStatement */: return ts.updateWith(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.statement, visitor, ts.isStatement, ts.liftToBlock)); - case 227: + case 227 /* SwitchStatement */: return ts.updateSwitch(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.caseBlock, visitor, ts.isCaseBlock)); - case 228: + case 228 /* LabeledStatement */: return ts.updateLabel(node, visitNode(node.label, visitor, ts.isIdentifier), visitNode(node.statement, visitor, ts.isStatement, ts.liftToBlock)); - case 229: + case 229 /* ThrowStatement */: return ts.updateThrow(node, visitNode(node.expression, visitor, ts.isExpression)); - case 230: + case 230 /* TryStatement */: return ts.updateTry(node, visitNode(node.tryBlock, visitor, ts.isBlock), visitNode(node.catchClause, visitor, ts.isCatchClause), visitNode(node.finallyBlock, visitor, ts.isBlock)); - case 232: + case 232 /* VariableDeclaration */: return ts.updateVariableDeclaration(node, visitNode(node.name, visitor, ts.isBindingName), visitNode(node.type, visitor, ts.isTypeNode), visitNode(node.initializer, visitor, ts.isExpression)); - case 233: + case 233 /* VariableDeclarationList */: return ts.updateVariableDeclarationList(node, nodesVisitor(node.declarations, visitor, ts.isVariableDeclaration)); - case 234: + case 234 /* FunctionDeclaration */: return ts.updateFunctionDeclaration(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.asteriskToken, tokenVisitor, ts.isToken), visitNode(node.name, visitor, ts.isIdentifier), nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), visitParameterList(node.parameters, visitor, context, nodesVisitor), visitNode(node.type, visitor, ts.isTypeNode), visitFunctionBody(node.body, visitor, context)); - case 235: + case 235 /* ClassDeclaration */: return ts.updateClassDeclaration(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isIdentifier), nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), nodesVisitor(node.heritageClauses, visitor, ts.isHeritageClause), nodesVisitor(node.members, visitor, ts.isClassElement)); - case 236: + case 236 /* InterfaceDeclaration */: return ts.updateInterfaceDeclaration(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isIdentifier), nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), nodesVisitor(node.heritageClauses, visitor, ts.isHeritageClause), nodesVisitor(node.members, visitor, ts.isTypeElement)); - case 237: + case 237 /* TypeAliasDeclaration */: return ts.updateTypeAliasDeclaration(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isIdentifier), nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), visitNode(node.type, visitor, ts.isTypeNode)); - case 238: + case 238 /* EnumDeclaration */: return ts.updateEnumDeclaration(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isIdentifier), nodesVisitor(node.members, visitor, ts.isEnumMember)); - case 239: + case 239 /* ModuleDeclaration */: return ts.updateModuleDeclaration(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isIdentifier), visitNode(node.body, visitor, ts.isModuleBody)); - case 240: + case 240 /* ModuleBlock */: return ts.updateModuleBlock(node, nodesVisitor(node.statements, visitor, ts.isStatement)); - case 241: + case 241 /* CaseBlock */: return ts.updateCaseBlock(node, nodesVisitor(node.clauses, visitor, ts.isCaseOrDefaultClause)); - case 242: + case 242 /* NamespaceExportDeclaration */: return ts.updateNamespaceExportDeclaration(node, visitNode(node.name, visitor, ts.isIdentifier)); - case 243: + case 243 /* ImportEqualsDeclaration */: return ts.updateImportEqualsDeclaration(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isIdentifier), visitNode(node.moduleReference, visitor, ts.isModuleReference)); - case 244: + case 244 /* ImportDeclaration */: return ts.updateImportDeclaration(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.importClause, visitor, ts.isImportClause), visitNode(node.moduleSpecifier, visitor, ts.isExpression)); - case 245: + case 245 /* ImportClause */: return ts.updateImportClause(node, visitNode(node.name, visitor, ts.isIdentifier), visitNode(node.namedBindings, visitor, ts.isNamedImportBindings)); - case 246: + case 246 /* NamespaceImport */: return ts.updateNamespaceImport(node, visitNode(node.name, visitor, ts.isIdentifier)); - case 247: + case 247 /* NamedImports */: return ts.updateNamedImports(node, nodesVisitor(node.elements, visitor, ts.isImportSpecifier)); - case 248: + case 248 /* ImportSpecifier */: return ts.updateImportSpecifier(node, visitNode(node.propertyName, visitor, ts.isIdentifier), visitNode(node.name, visitor, ts.isIdentifier)); - case 249: + case 249 /* ExportAssignment */: return ts.updateExportAssignment(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.expression, visitor, ts.isExpression)); - case 250: + case 250 /* ExportDeclaration */: return ts.updateExportDeclaration(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.exportClause, visitor, ts.isNamedExports), visitNode(node.moduleSpecifier, visitor, ts.isExpression)); - case 251: + case 251 /* NamedExports */: return ts.updateNamedExports(node, nodesVisitor(node.elements, visitor, ts.isExportSpecifier)); - case 252: + case 252 /* ExportSpecifier */: return ts.updateExportSpecifier(node, visitNode(node.propertyName, visitor, ts.isIdentifier), visitNode(node.name, visitor, ts.isIdentifier)); - case 254: + // Module references + case 254 /* ExternalModuleReference */: return ts.updateExternalModuleReference(node, visitNode(node.expression, visitor, ts.isExpression)); - case 255: + // JSX + case 255 /* JsxElement */: return ts.updateJsxElement(node, visitNode(node.openingElement, visitor, ts.isJsxOpeningElement), nodesVisitor(node.children, visitor, ts.isJsxChild), visitNode(node.closingElement, visitor, ts.isJsxClosingElement)); - case 256: + case 256 /* JsxSelfClosingElement */: return ts.updateJsxSelfClosingElement(node, visitNode(node.tagName, visitor, ts.isJsxTagNameExpression), nodesVisitor(node.typeArguments, visitor, ts.isTypeNode), visitNode(node.attributes, visitor, ts.isJsxAttributes)); - case 257: + case 257 /* JsxOpeningElement */: return ts.updateJsxOpeningElement(node, visitNode(node.tagName, visitor, ts.isJsxTagNameExpression), nodesVisitor(node.typeArguments, visitor, ts.isTypeNode), visitNode(node.attributes, visitor, ts.isJsxAttributes)); - case 258: + case 258 /* JsxClosingElement */: return ts.updateJsxClosingElement(node, visitNode(node.tagName, visitor, ts.isJsxTagNameExpression)); - case 259: + case 259 /* JsxFragment */: return ts.updateJsxFragment(node, visitNode(node.openingFragment, visitor, ts.isJsxOpeningFragment), nodesVisitor(node.children, visitor, ts.isJsxChild), visitNode(node.closingFragment, visitor, ts.isJsxClosingFragment)); - case 262: + case 262 /* JsxAttribute */: return ts.updateJsxAttribute(node, visitNode(node.name, visitor, ts.isIdentifier), visitNode(node.initializer, visitor, ts.isStringLiteralOrJsxExpression)); - case 263: + case 263 /* JsxAttributes */: return ts.updateJsxAttributes(node, nodesVisitor(node.properties, visitor, ts.isJsxAttributeLike)); - case 264: + case 264 /* JsxSpreadAttribute */: return ts.updateJsxSpreadAttribute(node, visitNode(node.expression, visitor, ts.isExpression)); - case 265: + case 265 /* JsxExpression */: return ts.updateJsxExpression(node, visitNode(node.expression, visitor, ts.isExpression)); - case 266: + // Clauses + case 266 /* CaseClause */: return ts.updateCaseClause(node, visitNode(node.expression, visitor, ts.isExpression), nodesVisitor(node.statements, visitor, ts.isStatement)); - case 267: + case 267 /* DefaultClause */: return ts.updateDefaultClause(node, nodesVisitor(node.statements, visitor, ts.isStatement)); - case 268: + case 268 /* HeritageClause */: return ts.updateHeritageClause(node, nodesVisitor(node.types, visitor, ts.isExpressionWithTypeArguments)); - case 269: + case 269 /* CatchClause */: return ts.updateCatchClause(node, visitNode(node.variableDeclaration, visitor, ts.isVariableDeclaration), visitNode(node.block, visitor, ts.isBlock)); - case 270: + // Property assignments + case 270 /* PropertyAssignment */: return ts.updatePropertyAssignment(node, visitNode(node.name, visitor, ts.isPropertyName), visitNode(node.initializer, visitor, ts.isExpression)); - case 271: + case 271 /* ShorthandPropertyAssignment */: return ts.updateShorthandPropertyAssignment(node, visitNode(node.name, visitor, ts.isIdentifier), visitNode(node.objectAssignmentInitializer, visitor, ts.isExpression)); - case 272: + case 272 /* SpreadAssignment */: return ts.updateSpreadAssignment(node, visitNode(node.expression, visitor, ts.isExpression)); - case 273: + // Enum + case 273 /* EnumMember */: return ts.updateEnumMember(node, visitNode(node.name, visitor, ts.isPropertyName), visitNode(node.initializer, visitor, ts.isExpression)); - case 274: + // Top-level nodes + case 274 /* SourceFile */: return ts.updateSourceFileNode(node, visitLexicalEnvironment(node.statements, visitor, context)); - case 302: + // Transformation nodes + case 302 /* PartiallyEmittedExpression */: return ts.updatePartiallyEmittedExpression(node, visitNode(node.expression, visitor, ts.isExpression)); - case 303: + case 303 /* CommaListExpression */: return ts.updateCommaList(node, nodesVisitor(node.elements, visitor, ts.isExpression)); default: + // No need to visit nodes with no children. return node; } } ts.visitEachChild = visitEachChild; + /** + * Extracts the single node from a NodeArray. + * + * @param nodes The NodeArray. + */ function extractSingleNode(nodes) { ts.Debug.assert(nodes.length <= 1, "Too many nodes written to output."); return ts.singleOrUndefined(nodes); } })(ts || (ts = {})); +/* @internal */ (function (ts) { function reduceNode(node, f, initial) { return node ? f(initial, node) : initial; @@ -51525,6 +59893,14 @@ var ts; function reduceNodeArray(nodes, f, initial) { return nodes ? f(initial, nodes) : initial; } + /** + * Similar to `reduceLeft`, performs a reduction against each child of a node. + * NOTE: Unlike `forEachChild`, this does *not* visit every node. + * + * @param node The node containing the children to reduce. + * @param initial The initial value to supply to the reduction. + * @param f The callback function + */ function reduceEachChild(node, initial, cbNode, cbNodeArray) { if (node === undefined) { return initial; @@ -51532,52 +59908,59 @@ var ts; var reduceNodes = cbNodeArray ? reduceNodeArray : ts.reduceLeft; var cbNodes = cbNodeArray || cbNode; var kind = node.kind; - if ((kind > 0 && kind <= 145)) { + // No need to visit nodes with no children. + if ((kind > 0 /* FirstToken */ && kind <= 145 /* LastToken */)) { return initial; } - if ((kind >= 161 && kind <= 178)) { + // We do not yet support types. + if ((kind >= 161 /* TypePredicate */ && kind <= 178 /* LiteralType */)) { return initial; } var result = initial; switch (node.kind) { - case 212: - case 215: - case 206: - case 231: - case 301: + // Leaf nodes + case 212 /* SemicolonClassElement */: + case 215 /* EmptyStatement */: + case 206 /* OmittedExpression */: + case 231 /* DebuggerStatement */: + case 301 /* NotEmittedStatement */: + // No need to visit nodes with no children. break; - case 146: + // Names + case 146 /* QualifiedName */: result = reduceNode(node.left, cbNode, result); result = reduceNode(node.right, cbNode, result); break; - case 147: + case 147 /* ComputedPropertyName */: result = reduceNode(node.expression, cbNode, result); break; - case 149: + // Signature elements + case 149 /* Parameter */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); result = reduceNode(node.type, cbNode, result); result = reduceNode(node.initializer, cbNode, result); break; - case 150: + case 150 /* Decorator */: result = reduceNode(node.expression, cbNode, result); break; - case 151: + // Type member + case 151 /* PropertySignature */: result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); result = reduceNode(node.questionToken, cbNode, result); result = reduceNode(node.type, cbNode, result); result = reduceNode(node.initializer, cbNode, result); break; - case 152: + case 152 /* PropertyDeclaration */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); result = reduceNode(node.type, cbNode, result); result = reduceNode(node.initializer, cbNode, result); break; - case 154: + case 154 /* MethodDeclaration */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); @@ -51586,12 +59969,12 @@ var ts; result = reduceNode(node.type, cbNode, result); result = reduceNode(node.body, cbNode, result); break; - case 155: + case 155 /* Constructor */: result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNodes(node.parameters, cbNodes, result); result = reduceNode(node.body, cbNode, result); break; - case 156: + case 156 /* GetAccessor */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); @@ -51599,55 +59982,57 @@ var ts; result = reduceNode(node.type, cbNode, result); result = reduceNode(node.body, cbNode, result); break; - case 157: + case 157 /* SetAccessor */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); result = reduceNodes(node.parameters, cbNodes, result); result = reduceNode(node.body, cbNode, result); break; - case 180: - case 181: + // Binding patterns + case 180 /* ObjectBindingPattern */: + case 181 /* ArrayBindingPattern */: result = reduceNodes(node.elements, cbNodes, result); break; - case 182: + case 182 /* BindingElement */: result = reduceNode(node.propertyName, cbNode, result); result = reduceNode(node.name, cbNode, result); result = reduceNode(node.initializer, cbNode, result); break; - case 183: + // Expression + case 183 /* ArrayLiteralExpression */: result = reduceNodes(node.elements, cbNodes, result); break; - case 184: + case 184 /* ObjectLiteralExpression */: result = reduceNodes(node.properties, cbNodes, result); break; - case 185: + case 185 /* PropertyAccessExpression */: result = reduceNode(node.expression, cbNode, result); result = reduceNode(node.name, cbNode, result); break; - case 186: + case 186 /* ElementAccessExpression */: result = reduceNode(node.expression, cbNode, result); result = reduceNode(node.argumentExpression, cbNode, result); break; - case 187: + case 187 /* CallExpression */: result = reduceNode(node.expression, cbNode, result); result = reduceNodes(node.typeArguments, cbNodes, result); result = reduceNodes(node.arguments, cbNodes, result); break; - case 188: + case 188 /* NewExpression */: result = reduceNode(node.expression, cbNode, result); result = reduceNodes(node.typeArguments, cbNodes, result); result = reduceNodes(node.arguments, cbNodes, result); break; - case 189: + case 189 /* TaggedTemplateExpression */: result = reduceNode(node.tag, cbNode, result); result = reduceNode(node.template, cbNode, result); break; - case 190: + case 190 /* TypeAssertionExpression */: result = reduceNode(node.type, cbNode, result); result = reduceNode(node.expression, cbNode, result); break; - case 192: + case 192 /* FunctionExpression */: result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); result = reduceNodes(node.typeParameters, cbNodes, result); @@ -51655,121 +60040,123 @@ var ts; result = reduceNode(node.type, cbNode, result); result = reduceNode(node.body, cbNode, result); break; - case 193: + case 193 /* ArrowFunction */: result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNodes(node.typeParameters, cbNodes, result); result = reduceNodes(node.parameters, cbNodes, result); result = reduceNode(node.type, cbNode, result); result = reduceNode(node.body, cbNode, result); break; - case 191: - case 194: - case 195: - case 196: - case 197: - case 203: - case 204: - case 209: + case 191 /* ParenthesizedExpression */: + case 194 /* DeleteExpression */: + case 195 /* TypeOfExpression */: + case 196 /* VoidExpression */: + case 197 /* AwaitExpression */: + case 203 /* YieldExpression */: + case 204 /* SpreadElement */: + case 209 /* NonNullExpression */: result = reduceNode(node.expression, cbNode, result); break; - case 198: - case 199: + case 198 /* PrefixUnaryExpression */: + case 199 /* PostfixUnaryExpression */: result = reduceNode(node.operand, cbNode, result); break; - case 200: + case 200 /* BinaryExpression */: result = reduceNode(node.left, cbNode, result); result = reduceNode(node.right, cbNode, result); break; - case 201: + case 201 /* ConditionalExpression */: result = reduceNode(node.condition, cbNode, result); result = reduceNode(node.whenTrue, cbNode, result); result = reduceNode(node.whenFalse, cbNode, result); break; - case 202: + case 202 /* TemplateExpression */: result = reduceNode(node.head, cbNode, result); result = reduceNodes(node.templateSpans, cbNodes, result); break; - case 205: + case 205 /* ClassExpression */: result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); result = reduceNodes(node.typeParameters, cbNodes, result); result = reduceNodes(node.heritageClauses, cbNodes, result); result = reduceNodes(node.members, cbNodes, result); break; - case 207: + case 207 /* ExpressionWithTypeArguments */: result = reduceNode(node.expression, cbNode, result); result = reduceNodes(node.typeArguments, cbNodes, result); break; - case 208: + case 208 /* AsExpression */: result = reduceNode(node.expression, cbNode, result); result = reduceNode(node.type, cbNode, result); break; - case 211: + // Misc + case 211 /* TemplateSpan */: result = reduceNode(node.expression, cbNode, result); result = reduceNode(node.literal, cbNode, result); break; - case 213: + // Element + case 213 /* Block */: result = reduceNodes(node.statements, cbNodes, result); break; - case 214: + case 214 /* VariableStatement */: result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.declarationList, cbNode, result); break; - case 216: + case 216 /* ExpressionStatement */: result = reduceNode(node.expression, cbNode, result); break; - case 217: + case 217 /* IfStatement */: result = reduceNode(node.expression, cbNode, result); result = reduceNode(node.thenStatement, cbNode, result); result = reduceNode(node.elseStatement, cbNode, result); break; - case 218: + case 218 /* DoStatement */: result = reduceNode(node.statement, cbNode, result); result = reduceNode(node.expression, cbNode, result); break; - case 219: - case 226: + case 219 /* WhileStatement */: + case 226 /* WithStatement */: result = reduceNode(node.expression, cbNode, result); result = reduceNode(node.statement, cbNode, result); break; - case 220: + case 220 /* ForStatement */: result = reduceNode(node.initializer, cbNode, result); result = reduceNode(node.condition, cbNode, result); result = reduceNode(node.incrementor, cbNode, result); result = reduceNode(node.statement, cbNode, result); break; - case 221: - case 222: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: result = reduceNode(node.initializer, cbNode, result); result = reduceNode(node.expression, cbNode, result); result = reduceNode(node.statement, cbNode, result); break; - case 225: - case 229: + case 225 /* ReturnStatement */: + case 229 /* ThrowStatement */: result = reduceNode(node.expression, cbNode, result); break; - case 227: + case 227 /* SwitchStatement */: result = reduceNode(node.expression, cbNode, result); result = reduceNode(node.caseBlock, cbNode, result); break; - case 228: + case 228 /* LabeledStatement */: result = reduceNode(node.label, cbNode, result); result = reduceNode(node.statement, cbNode, result); break; - case 230: + case 230 /* TryStatement */: result = reduceNode(node.tryBlock, cbNode, result); result = reduceNode(node.catchClause, cbNode, result); result = reduceNode(node.finallyBlock, cbNode, result); break; - case 232: + case 232 /* VariableDeclaration */: result = reduceNode(node.name, cbNode, result); result = reduceNode(node.type, cbNode, result); result = reduceNode(node.initializer, cbNode, result); break; - case 233: + case 233 /* VariableDeclarationList */: result = reduceNodes(node.declarations, cbNodes, result); break; - case 234: + case 234 /* FunctionDeclaration */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); @@ -51778,7 +60165,7 @@ var ts; result = reduceNode(node.type, cbNode, result); result = reduceNode(node.body, cbNode, result); break; - case 235: + case 235 /* ClassDeclaration */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); @@ -51786,131 +60173,139 @@ var ts; result = reduceNodes(node.heritageClauses, cbNodes, result); result = reduceNodes(node.members, cbNodes, result); break; - case 238: + case 238 /* EnumDeclaration */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); result = reduceNodes(node.members, cbNodes, result); break; - case 239: + case 239 /* ModuleDeclaration */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); result = reduceNode(node.body, cbNode, result); break; - case 240: + case 240 /* ModuleBlock */: result = reduceNodes(node.statements, cbNodes, result); break; - case 241: + case 241 /* CaseBlock */: result = reduceNodes(node.clauses, cbNodes, result); break; - case 243: + case 243 /* ImportEqualsDeclaration */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); result = reduceNode(node.moduleReference, cbNode, result); break; - case 244: + case 244 /* ImportDeclaration */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.importClause, cbNode, result); result = reduceNode(node.moduleSpecifier, cbNode, result); break; - case 245: + case 245 /* ImportClause */: result = reduceNode(node.name, cbNode, result); result = reduceNode(node.namedBindings, cbNode, result); break; - case 246: + case 246 /* NamespaceImport */: result = reduceNode(node.name, cbNode, result); break; - case 247: - case 251: + case 247 /* NamedImports */: + case 251 /* NamedExports */: result = reduceNodes(node.elements, cbNodes, result); break; - case 248: - case 252: + case 248 /* ImportSpecifier */: + case 252 /* ExportSpecifier */: result = reduceNode(node.propertyName, cbNode, result); result = reduceNode(node.name, cbNode, result); break; - case 249: + case 249 /* ExportAssignment */: result = ts.reduceLeft(node.decorators, cbNode, result); result = ts.reduceLeft(node.modifiers, cbNode, result); result = reduceNode(node.expression, cbNode, result); break; - case 250: + case 250 /* ExportDeclaration */: result = ts.reduceLeft(node.decorators, cbNode, result); result = ts.reduceLeft(node.modifiers, cbNode, result); result = reduceNode(node.exportClause, cbNode, result); result = reduceNode(node.moduleSpecifier, cbNode, result); break; - case 254: + // Module references + case 254 /* ExternalModuleReference */: result = reduceNode(node.expression, cbNode, result); break; - case 255: + // JSX + case 255 /* JsxElement */: result = reduceNode(node.openingElement, cbNode, result); result = ts.reduceLeft(node.children, cbNode, result); result = reduceNode(node.closingElement, cbNode, result); break; - case 259: + case 259 /* JsxFragment */: result = reduceNode(node.openingFragment, cbNode, result); result = ts.reduceLeft(node.children, cbNode, result); result = reduceNode(node.closingFragment, cbNode, result); break; - case 256: - case 257: + case 256 /* JsxSelfClosingElement */: + case 257 /* JsxOpeningElement */: result = reduceNode(node.tagName, cbNode, result); result = reduceNode(node.attributes, cbNode, result); break; - case 263: + case 263 /* JsxAttributes */: result = reduceNodes(node.properties, cbNodes, result); break; - case 258: + case 258 /* JsxClosingElement */: result = reduceNode(node.tagName, cbNode, result); break; - case 262: + case 262 /* JsxAttribute */: result = reduceNode(node.name, cbNode, result); result = reduceNode(node.initializer, cbNode, result); break; - case 264: + case 264 /* JsxSpreadAttribute */: result = reduceNode(node.expression, cbNode, result); break; - case 265: + case 265 /* JsxExpression */: result = reduceNode(node.expression, cbNode, result); break; - case 266: + // Clauses + case 266 /* CaseClause */: result = reduceNode(node.expression, cbNode, result); - case 267: + // falls through + case 267 /* DefaultClause */: result = reduceNodes(node.statements, cbNodes, result); break; - case 268: + case 268 /* HeritageClause */: result = reduceNodes(node.types, cbNodes, result); break; - case 269: + case 269 /* CatchClause */: result = reduceNode(node.variableDeclaration, cbNode, result); result = reduceNode(node.block, cbNode, result); break; - case 270: + // Property assignments + case 270 /* PropertyAssignment */: result = reduceNode(node.name, cbNode, result); result = reduceNode(node.initializer, cbNode, result); break; - case 271: + case 271 /* ShorthandPropertyAssignment */: result = reduceNode(node.name, cbNode, result); result = reduceNode(node.objectAssignmentInitializer, cbNode, result); break; - case 272: + case 272 /* SpreadAssignment */: result = reduceNode(node.expression, cbNode, result); break; - case 273: + // Enum + case 273 /* EnumMember */: result = reduceNode(node.name, cbNode, result); result = reduceNode(node.initializer, cbNode, result); break; - case 274: + // Top-level nodes + case 274 /* SourceFile */: result = reduceNodes(node.statements, cbNodes, result); break; - case 302: + // Transformation nodes + case 302 /* PartiallyEmittedExpression */: result = reduceNode(node.expression, cbNode, result); break; - case 303: + case 303 /* CommaListExpression */: result = reduceNodes(node.elements, cbNodes, result); break; default: @@ -51928,21 +60323,36 @@ var ts; : ts.prependStatements(statements, declarations); } ts.mergeLexicalEnvironment = mergeLexicalEnvironment; + /** + * Lifts a NodeArray containing only Statement nodes to a block. + * + * @param nodes The NodeArray. + */ function liftToBlock(nodes) { Debug.assert(ts.every(nodes, ts.isStatement), "Cannot lift nodes to a Block."); return ts.singleOrUndefined(nodes) || ts.createBlock(nodes); } ts.liftToBlock = liftToBlock; + /** + * Aggregates the TransformFlags for a Node and its subtree. + */ function aggregateTransformFlags(node) { aggregateTransformFlagsForNode(node); return node; } ts.aggregateTransformFlags = aggregateTransformFlags; + /** + * Aggregates the TransformFlags for a Node and its subtree. The flags for the subtree are + * computed first, then the transform flags for the current node are computed from the subtree + * flags and the state of the current node. Finally, the transform flags of the node are + * returned, excluding any flags that should not be included in its parent node's subtree + * flags. + */ function aggregateTransformFlagsForNode(node) { if (node === undefined) { - return 0; + return 0 /* None */; } - if (node.transformFlags & 536870912) { + if (node.transformFlags & 536870912 /* HasComputedFlags */) { return node.transformFlags & ~ts.getTransformFlagsSubtreeExclusions(node.kind); } var subtreeFlags = aggregateTransformFlagsForSubtree(node); @@ -51950,24 +60360,34 @@ var ts; } function aggregateTransformFlagsForNodeArray(nodes) { if (nodes === undefined) { - return 0; + return 0 /* None */; } - var subtreeFlags = 0; - var nodeArrayFlags = 0; + var subtreeFlags = 0 /* None */; + var nodeArrayFlags = 0 /* None */; for (var _i = 0, nodes_3 = nodes; _i < nodes_3.length; _i++) { var node = nodes_3[_i]; subtreeFlags |= aggregateTransformFlagsForNode(node); - nodeArrayFlags |= node.transformFlags & ~536870912; + nodeArrayFlags |= node.transformFlags & ~536870912 /* HasComputedFlags */; } - nodes.transformFlags = nodeArrayFlags | 536870912; + nodes.transformFlags = nodeArrayFlags | 536870912 /* HasComputedFlags */; return subtreeFlags; } + /** + * Aggregates the transform flags for the subtree of a node. + */ function aggregateTransformFlagsForSubtree(node) { - if (ts.hasModifier(node, 2) || (ts.isTypeNode(node) && node.kind !== 207)) { - return 0; + // We do not transform ambient declarations or types, so there is no need to + // recursively aggregate transform flags. + if (ts.hasModifier(node, 2 /* Ambient */) || (ts.isTypeNode(node) && node.kind !== 207 /* ExpressionWithTypeArguments */)) { + return 0 /* None */; } - return reduceEachChild(node, 0, aggregateTransformFlagsForChildNode, aggregateTransformFlagsForChildNodes); + // Aggregate the transform flags of each child. + return reduceEachChild(node, 0 /* None */, aggregateTransformFlagsForChildNode, aggregateTransformFlagsForChildNodes); } + /** + * Aggregates the TransformFlags of a child node with the TransformFlags of its + * siblings. + */ function aggregateTransformFlagsForChildNode(transformFlags, node) { return transformFlags | aggregateTransformFlagsForNode(node); } @@ -51981,30 +60401,34 @@ var ts; return Debug.fail((message || "Unexpected node.") + "\r\nNode " + ts.formatSyntaxKind(node.kind) + " was unexpected.", failBadSyntaxKind); } Debug.failBadSyntaxKind = failBadSyntaxKind; - Debug.assertEachNode = Debug.shouldAssert(1) + Debug.assertEachNode = Debug.shouldAssert(1 /* Normal */) ? function (nodes, test, message) { return Debug.assert(test === undefined || ts.every(nodes, test), message || "Unexpected node.", function () { return "Node array did not pass test '" + Debug.getFunctionName(test) + "'."; }, Debug.assertEachNode); } : ts.noop; - Debug.assertNode = Debug.shouldAssert(1) + Debug.assertNode = Debug.shouldAssert(1 /* Normal */) ? function (node, test, message) { return Debug.assert(test === undefined || test(node), message || "Unexpected node.", function () { return "Node " + ts.formatSyntaxKind(node.kind) + " did not pass test '" + Debug.getFunctionName(test) + "'."; }, Debug.assertNode); } : ts.noop; - Debug.assertOptionalNode = Debug.shouldAssert(1) + Debug.assertOptionalNode = Debug.shouldAssert(1 /* Normal */) ? function (node, test, message) { return Debug.assert(test === undefined || node === undefined || test(node), message || "Unexpected node.", function () { return "Node " + ts.formatSyntaxKind(node.kind) + " did not pass test '" + Debug.getFunctionName(test) + "'."; }, Debug.assertOptionalNode); } : ts.noop; - Debug.assertOptionalToken = Debug.shouldAssert(1) + Debug.assertOptionalToken = Debug.shouldAssert(1 /* Normal */) ? function (node, kind, message) { return Debug.assert(kind === undefined || node === undefined || node.kind === kind, message || "Unexpected node.", function () { return "Node " + ts.formatSyntaxKind(node.kind) + " was not a '" + ts.formatSyntaxKind(kind) + "' token."; }, Debug.assertOptionalToken); } : ts.noop; - Debug.assertMissingNode = Debug.shouldAssert(1) + Debug.assertMissingNode = Debug.shouldAssert(1 /* Normal */) ? function (node, message) { return Debug.assert(node === undefined, message || "Unexpected node.", function () { return "Node " + ts.formatSyntaxKind(node.kind) + " was unexpected'."; }, Debug.assertMissingNode); } : ts.noop; + /** + * Injects debug information into frequently used types. + */ function enableDebugInfo() { if (isDebugInfoEnabled) return; + // Add additional properties in debug mode to assist with debugging. Object.defineProperties(ts.objectAllocator.getSymbolConstructor().prototype, { __debugFlags: { get: function () { return ts.formatSymbolFlags(this.flags); } } }); Object.defineProperties(ts.objectAllocator.getTypeConstructor().prototype, { __debugFlags: { get: function () { return ts.formatTypeFlags(this.flags); } }, - __debugObjectFlags: { get: function () { return this.flags & 131072 ? ts.formatObjectFlags(this.objectFlags) : ""; } }, + __debugObjectFlags: { get: function () { return this.flags & 131072 /* Object */ ? ts.formatObjectFlags(this.objectFlags) : ""; } }, __debugTypeToString: { value: function () { return this.checker.typeToString(this); } }, }); var nodeConstructors = [ @@ -52038,6 +60462,7 @@ var ts; Debug.enableDebugInfo = enableDebugInfo; })(Debug = ts.Debug || (ts.Debug = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { function createSourceFileLikeCache(host) { @@ -52049,7 +60474,8 @@ var ts; } if (!host.fileExists || !host.readFile || !host.fileExists(path)) return; - var text = host.readFile(path); + // And failing that, check the disk + var text = host.readFile(path); // TODO: GH#18217 var file = { text: text, lineMap: undefined, @@ -52064,6 +60490,7 @@ var ts; } ts.createSourceFileLikeCache = createSourceFileLikeCache; })(ts || (ts = {})); +/* @internal */ (function (ts) { var sourcemaps; (function (sourcemaps) { @@ -52085,12 +60512,13 @@ var ts; return loc; var targetIndex = ts.binarySearch(maps, { sourcePath: loc.fileName, sourcePosition: loc.position }, ts.identity, compareProcessedPositionSourcePositions); if (targetIndex < 0 && maps.length > 0) { + // if no exact match, closest is 2's compliment of result targetIndex = ~targetIndex; } if (!maps[targetIndex] || ts.comparePaths(loc.fileName, maps[targetIndex].sourcePath, sourceRoot) !== 0) { return loc; } - return { fileName: ts.toPath(map.file, sourceRoot, host.getCanonicalFileName), position: maps[targetIndex].emittedPosition }; + return { fileName: ts.toPath(map.file, sourceRoot, host.getCanonicalFileName), position: maps[targetIndex].emittedPosition }; // Closest pos } function getOriginalPosition(loc) { var maps = getGeneratedOrderedMappings(); @@ -52098,13 +60526,16 @@ var ts; return loc; var targetIndex = ts.binarySearch(maps, { emittedPosition: loc.position }, ts.identity, compareProcessedPositionEmittedPositions); if (targetIndex < 0 && maps.length > 0) { + // if no exact match, closest is 2's compliment of result targetIndex = ~targetIndex; } - return { fileName: ts.toPath(maps[targetIndex].sourcePath, sourceRoot, host.getCanonicalFileName), position: maps[targetIndex].sourcePosition }; + return { fileName: ts.toPath(maps[targetIndex].sourcePath, sourceRoot, host.getCanonicalFileName), position: maps[targetIndex].sourcePosition }; // Closest pos } function getSourceFileLike(fileName, location) { + // Lookup file in program, if provided var file = program && program.getSourceFile(fileName); if (!file) { + // Otherwise check the cache (which may hit disk) var path = ts.toPath(fileName, location, host.getCanonicalFileName); return fallbackCache.get(path); } @@ -52143,6 +60574,7 @@ var ts; } } sourcemaps.decode = decode; + /*@internal*/ function decodeMappings(map) { var state = { encodedText: map.mappings, @@ -52197,56 +60629,79 @@ var ts; function decodeSinglePosition(state) { while (state.decodingIndex < state.encodedText.length) { var char = state.encodedText.charCodeAt(state.decodingIndex); - if (char === 59) { + if (char === 59 /* semicolon */) { + // New line state.currentEmittedLine++; state.currentEmittedColumn = 0; state.decodingIndex++; continue; } - if (char === 44) { + if (char === 44 /* comma */) { + // Next entry is on same line - no action needed state.decodingIndex++; continue; } + // Read the current position + // 1. Column offset from prev read jsColumn state.currentEmittedColumn += base64VLQFormatDecode(); + // Incorrect emittedColumn dont support this map if (createErrorIfCondition(state.currentEmittedColumn < 0, "Invalid emittedColumn found")) { return false; } + // Dont support reading mappings that dont have information about original source and its line numbers if (createErrorIfCondition(isSourceMappingSegmentEnd(state.encodedText, state.decodingIndex), "Unsupported Error Format: No entries after emitted column")) { return false; } + // 2. Relative sourceIndex state.currentSourceIndex += base64VLQFormatDecode(); + // Incorrect sourceIndex dont support this map if (createErrorIfCondition(state.currentSourceIndex < 0, "Invalid sourceIndex found")) { return false; } + // Dont support reading mappings that dont have information about original source position if (createErrorIfCondition(isSourceMappingSegmentEnd(state.encodedText, state.decodingIndex), "Unsupported Error Format: No entries after sourceIndex")) { return false; } + // 3. Relative sourceLine 0 based state.currentSourceLine += base64VLQFormatDecode(); + // Incorrect sourceLine dont support this map if (createErrorIfCondition(state.currentSourceLine < 0, "Invalid sourceLine found")) { return false; } + // Dont support reading mappings that dont have information about original source and its line numbers if (createErrorIfCondition(isSourceMappingSegmentEnd(state.encodedText, state.decodingIndex), "Unsupported Error Format: No entries after emitted Line")) { return false; } + // 4. Relative sourceColumn 0 based state.currentSourceColumn += base64VLQFormatDecode(); + // Incorrect sourceColumn dont support this map if (createErrorIfCondition(state.currentSourceColumn < 0, "Invalid sourceLine found")) { return false; } + // 5. Check if there is name: if (!isSourceMappingSegmentEnd(state.encodedText, state.decodingIndex)) { if (state.currentNameIndex === undefined) { state.currentNameIndex = 0; } state.currentNameIndex += base64VLQFormatDecode(); + // Incorrect nameIndex dont support this map + // TODO: If we start using `name`s, issue errors when they aren't correct in the sourcemap + // if (createErrorIfCondition(state.currentNameIndex < 0 || state.currentNameIndex >= state.sourceMapNamesLength, "Invalid name index for the source map entry")) { + // return; + // } } + // Dont support reading mappings that dont have information about original source and its line numbers if (createErrorIfCondition(!isSourceMappingSegmentEnd(state.encodedText, state.decodingIndex), "Unsupported Error Format: There are more entries after " + (state.currentNameIndex === undefined ? "sourceColumn" : "nameIndex"))) { return false; } + // Entry should be complete return true; } - createErrorIfCondition(true, "No encoded entry found"); + createErrorIfCondition(/*condition*/ true, "No encoded entry found"); return false; function createErrorIfCondition(condition, errormsg) { if (state.error) { + // An error was already reported return true; } if (condition) { @@ -52260,17 +60715,23 @@ var ts; var value = 0; for (; moreDigits; state.decodingIndex++) { if (createErrorIfCondition(state.decodingIndex >= state.encodedText.length, "Error in decoding base64VLQFormatDecode, past the mapping string")) { - return undefined; + return undefined; // TODO: GH#18217 } + // 6 digit number var currentByte = base64FormatDecode(state.encodedText.charAt(state.decodingIndex)); + // If msb is set, we still have more bits to continue moreDigits = (currentByte & 32) !== 0; + // least significant 5 bits are the next msbs in the final value. value = value | ((currentByte & 31) << shiftCount); shiftCount += 5; } + // Least significant bit if 1 represents negative and rest of the msb is actual absolute value if ((value & 1) === 0) { + // + number value = value >> 1; } else { + // - number value = value >> 1; value = -value; } @@ -52282,11 +60743,12 @@ var ts; } function isSourceMappingSegmentEnd(encodedText, pos) { return (pos === encodedText.length || - encodedText.charCodeAt(pos) === 44 || - encodedText.charCodeAt(pos) === 59); + encodedText.charCodeAt(pos) === 44 /* comma */ || + encodedText.charCodeAt(pos) === 59 /* semicolon */); } })(sourcemaps = ts.sourcemaps || (ts.sourcemaps = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { function getOriginalNodeId(node) { @@ -52302,12 +60764,12 @@ var ts; return ts.some(node.elements, isNamedDefaultReference); } function isNamedDefaultReference(e) { - return e.propertyName !== undefined && e.propertyName.escapedText === "default"; + return e.propertyName !== undefined && e.propertyName.escapedText === "default" /* Default */; } function chainBundle(transformSourceFile) { return transformSourceFileOrBundle; function transformSourceFileOrBundle(node) { - return node.kind === 274 ? transformSourceFile(node) : transformBundle(node); + return node.kind === 274 /* SourceFile */ ? transformSourceFile(node) : transformBundle(node); } function transformBundle(node) { return ts.createBundle(ts.map(node.sourceFiles, transformSourceFile), node.prepends); @@ -52331,11 +60793,13 @@ var ts; defaultRefCount++; } } + // Import star is required if there's default named refs mixed with non-default refs, or if theres non-default refs and it has a default import return (defaultRefCount > 0 && defaultRefCount !== bindings.elements.length) || (!!(bindings.elements.length - defaultRefCount) && ts.isDefaultImport(node)); } ts.getImportNeedsImportStarHelper = getImportNeedsImportStarHelper; function getImportNeedsImportDefaultHelper(node) { - return !getImportNeedsImportStarHelper(node) && (ts.isDefaultImport(node) || (!!node.importClause && ts.isNamedImports(node.importClause.namedBindings) && containsDefaultReference(node.importClause.namedBindings))); + // Import default is needed if there's a default import or a default ref and no other refs (meaning an import star helper wasn't requested) + return !getImportNeedsImportStarHelper(node) && (ts.isDefaultImport(node) || (!!node.importClause && ts.isNamedImports(node.importClause.namedBindings) && containsDefaultReference(node.importClause.namedBindings))); // TODO: GH#18217 } ts.getImportNeedsImportDefaultHelper = getImportNeedsImportDefaultHelper; function collectExternalModuleInfo(sourceFile, resolver, compilerOptions) { @@ -52351,26 +60815,34 @@ var ts; for (var _i = 0, _a = sourceFile.statements; _i < _a.length; _i++) { var node = _a[_i]; switch (node.kind) { - case 244: + case 244 /* ImportDeclaration */: + // import "mod" + // import x from "mod" + // import * as x from "mod" + // import { x, y } from "mod" externalImports.push(node); hasImportStarOrImportDefault = hasImportStarOrImportDefault || getImportNeedsImportStarHelper(node) || getImportNeedsImportDefaultHelper(node); break; - case 243: - if (node.moduleReference.kind === 254) { + case 243 /* ImportEqualsDeclaration */: + if (node.moduleReference.kind === 254 /* ExternalModuleReference */) { + // import x = require("mod") externalImports.push(node); } break; - case 250: + case 250 /* ExportDeclaration */: if (node.moduleSpecifier) { if (!node.exportClause) { + // export * from "mod" externalImports.push(node); hasExportStarsToExportValues = true; } else { + // export { x, y } from "mod" externalImports.push(node); } } else { + // export { x, y } for (var _b = 0, _c = node.exportClause.elements; _b < _c.length; _b++) { var specifier = _c[_b]; if (!uniqueExports.get(ts.idText(specifier.name))) { @@ -52387,28 +60859,31 @@ var ts; } } break; - case 249: + case 249 /* ExportAssignment */: if (node.isExportEquals && !exportEquals) { + // export = x exportEquals = node; } break; - case 214: - if (ts.hasModifier(node, 1)) { + case 214 /* VariableStatement */: + if (ts.hasModifier(node, 1 /* Export */)) { for (var _d = 0, _e = node.declarationList.declarations; _d < _e.length; _d++) { var decl = _e[_d]; exportedNames = collectExportedVariableInfo(decl, uniqueExports, exportedNames); } } break; - case 234: - if (ts.hasModifier(node, 1)) { - if (ts.hasModifier(node, 512)) { + case 234 /* FunctionDeclaration */: + if (ts.hasModifier(node, 1 /* Export */)) { + if (ts.hasModifier(node, 512 /* Default */)) { + // export default function() { } if (!hasExportDefault) { multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), ts.getDeclarationName(node)); hasExportDefault = true; } } else { + // export function x() { } var name = node.name; if (!uniqueExports.get(ts.idText(name))) { multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name); @@ -52418,15 +60893,17 @@ var ts; } } break; - case 235: - if (ts.hasModifier(node, 1)) { - if (ts.hasModifier(node, 512)) { + case 235 /* ClassDeclaration */: + if (ts.hasModifier(node, 1 /* Export */)) { + if (ts.hasModifier(node, 512 /* Default */)) { + // export default class { } if (!hasExportDefault) { multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), ts.getDeclarationName(node)); hasExportDefault = true; } } else { + // export class x { } var name = node.name; if (name && !uniqueExports.get(ts.idText(name))) { multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name); @@ -52439,9 +60916,11 @@ var ts; } } var externalHelpersModuleName = ts.getOrCreateExternalHelpersModuleNameIfNeeded(sourceFile, compilerOptions, hasExportStarsToExportValues, hasImportStarOrImportDefault); - var externalHelpersImportDeclaration = externalHelpersModuleName && ts.createImportDeclaration(undefined, undefined, ts.createImportClause(undefined, ts.createNamespaceImport(externalHelpersModuleName)), ts.createLiteral(ts.externalHelpersModuleNameText)); + var externalHelpersImportDeclaration = externalHelpersModuleName && ts.createImportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, ts.createImportClause(/*name*/ undefined, ts.createNamespaceImport(externalHelpersModuleName)), ts.createLiteral(ts.externalHelpersModuleNameText)); if (externalHelpersImportDeclaration) { - ts.addEmitFlags(externalHelpersImportDeclaration, 67108864); + ts.addEmitFlags(externalHelpersImportDeclaration, 67108864 /* NeverApplyImportHelper */); externalImports.unshift(externalHelpersImportDeclaration); } return { externalImports: externalImports, exportSpecifiers: exportSpecifiers, exportEquals: exportEquals, hasExportStarsToExportValues: hasExportStarsToExportValues, exportedBindings: exportedBindings, exportedNames: exportedNames, externalHelpersImportDeclaration: externalHelpersImportDeclaration }; @@ -52465,6 +60944,7 @@ var ts; } return exportedNames; } + /** Use a sparse array as a multi-map. */ function multiMapSparseArrayAdd(map, key, value) { var values = map[key]; if (values) { @@ -52475,13 +60955,22 @@ var ts; } return values; } + /** + * Used in the module transformer to check if an expression is reasonably without sideeffect, + * and thus better to copy into multiple places rather than to cache in a temporary variable + * - this is mostly subjective beyond the requirement that the expression not be sideeffecting + */ function isSimpleCopiableExpression(expression) { return ts.isStringLiteralLike(expression) || - expression.kind === 8 || + expression.kind === 8 /* NumericLiteral */ || ts.isKeyword(expression.kind) || ts.isIdentifier(expression); } ts.isSimpleCopiableExpression = isSimpleCopiableExpression; + /** + * @param input Template string input strings + * @param args Names which need to be made file-level unique + */ function helperString(input) { var args = []; for (var _i = 1; _i < arguments.length; _i++) { @@ -52499,6 +60988,7 @@ var ts; } ts.helperString = helperString; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { var FlattenLevel; @@ -52506,6 +60996,17 @@ var ts; FlattenLevel[FlattenLevel["All"] = 0] = "All"; FlattenLevel[FlattenLevel["ObjectRest"] = 1] = "ObjectRest"; })(FlattenLevel = ts.FlattenLevel || (ts.FlattenLevel = {})); + /** + * Flattens a DestructuringAssignment or a VariableDeclaration to an expression. + * + * @param node The node to flatten. + * @param visitor An optional visitor used to visit initializers. + * @param context The transformation context. + * @param level Indicates the extent to which flattening should occur. + * @param needsValue An optional value indicating whether the value from the right-hand-side of + * the destructuring assignment is needed as part of a larger expression. + * @param createAssignmentCallback An optional callback used to create the assignment expression. + */ function flattenDestructuringAssignment(node, visitor, context, level, needsValue, createAssignmentCallback) { var location = node; var value; @@ -52537,16 +61038,30 @@ var ts; if (value) { value = ts.visitNode(value, visitor, ts.isExpression); if (ts.isIdentifier(value) && bindingOrAssignmentElementAssignsToName(node, value.escapedText)) { - value = ensureIdentifier(flattenContext, value, false, location); + // If the right-hand value of the assignment is also an assignment target then + // we need to cache the right-hand value. + value = ensureIdentifier(flattenContext, value, /*reuseIdentifierExpressions*/ false, location); } else if (needsValue) { - value = ensureIdentifier(flattenContext, value, true, location); + // If the right-hand value of the destructuring assignment needs to be preserved (as + // is the case when the destructuring assignment is part of a larger expression), + // then we need to cache the right-hand value. + // + // The source map location for the assignment should point to the entire binary + // expression. + value = ensureIdentifier(flattenContext, value, /*reuseIdentifierExpressions*/ true, location); } else if (ts.nodeIsSynthesized(node)) { + // Generally, the source map location for a destructuring assignment is the root + // expression. + // + // However, if the root expression is synthesized (as in the case + // of the initializer when transforming a ForOfStatement), then the source map + // location should point to the right-hand value of the expression. location = value; } } - flattenBindingOrAssignmentElement(flattenContext, node, value, location, ts.isDestructuringAssignment(node)); + flattenBindingOrAssignmentElement(flattenContext, node, value, location, /*skipInitializer*/ ts.isDestructuringAssignment(node)); if (value && needsValue) { if (!ts.some(expressions)) { return value; @@ -52555,7 +61070,9 @@ var ts; } return ts.aggregateTransformFlags(ts.inlineExpressions(expressions)) || ts.createOmittedExpression(); function emitExpression(expression) { - ts.setEmitFlags(expression, 64); + // NOTE: this completely disables source maps, but aligns with the behavior of + // `emitAssignment` in the old emitter. + ts.setEmitFlags(expression, 64 /* NoNestedSourceMaps */); ts.aggregateTransformFlags(expression); expressions = ts.append(expressions, expression); } @@ -52570,7 +61087,7 @@ var ts; } ts.flattenDestructuringAssignment = flattenDestructuringAssignment; function bindingOrAssignmentElementAssignsToName(element, escapedName) { - var target = ts.getTargetOfBindingOrAssignmentElement(element); + var target = ts.getTargetOfBindingOrAssignmentElement(element); // TODO: GH#18217 if (ts.isBindingOrAssignmentPattern(target)) { return bindingOrAssignmentPatternAssignsToName(target, escapedName); } @@ -52589,6 +61106,17 @@ var ts; } return false; } + /** + * Flattens a VariableDeclaration or ParameterDeclaration to one or more variable declarations. + * + * @param node The node to flatten. + * @param visitor An optional visitor used to visit initializers. + * @param context The transformation context. + * @param boundValue The value bound to the declaration. + * @param skipInitializer A value indicating whether to ignore the initializer of `node`. + * @param hoistTempVariables Indicates whether temporary variables should not be recorded in-line. + * @param level Indicates the extent to which flattening should occur. + */ function flattenDestructuringBinding(node, visitor, context, level, rval, hoistTempVariables, skipInitializer) { if (hoistTempVariables === void 0) { hoistTempVariables = false; } var pendingExpressions; @@ -52609,17 +61137,19 @@ var ts; if (ts.isVariableDeclaration(node)) { var initializer = ts.getInitializerOfBindingOrAssignmentElement(node); if (initializer && ts.isIdentifier(initializer) && bindingOrAssignmentElementAssignsToName(node, initializer.escapedText)) { - initializer = ensureIdentifier(flattenContext, initializer, false, initializer); + // If the right-hand value of the assignment is also an assignment target then + // we need to cache the right-hand value. + initializer = ensureIdentifier(flattenContext, initializer, /*reuseIdentifierExpressions*/ false, initializer); node = ts.updateVariableDeclaration(node, node.name, node.type, initializer); } } flattenBindingOrAssignmentElement(flattenContext, node, rval, node, skipInitializer); if (pendingExpressions) { - var temp = ts.createTempVariable(undefined); + var temp = ts.createTempVariable(/*recordTempVariable*/ undefined); if (hoistTempVariables) { var value = ts.inlineExpressions(pendingExpressions); pendingExpressions = undefined; - emitBindingOrAssignment(temp, value, undefined, undefined); + emitBindingOrAssignment(temp, value, /*location*/ undefined, /*original*/ undefined); } else { context.hoistVariableDeclaration(temp); @@ -52631,11 +61161,12 @@ var ts; } for (var _i = 0, pendingDeclarations_1 = pendingDeclarations; _i < pendingDeclarations_1.length; _i++) { var _a = pendingDeclarations_1[_i], pendingExpressions_1 = _a.pendingExpressions, name = _a.name, value = _a.value, location = _a.location, original = _a.original; - var variable = ts.createVariableDeclaration(name, undefined, pendingExpressions_1 ? ts.inlineExpressions(ts.append(pendingExpressions_1, value)) : value); + var variable = ts.createVariableDeclaration(name, + /*type*/ undefined, pendingExpressions_1 ? ts.inlineExpressions(ts.append(pendingExpressions_1, value)) : value); variable.original = original; ts.setTextRange(variable, location); if (ts.isIdentifier(name)) { - ts.setEmitFlags(variable, 64); + ts.setEmitFlags(variable, 64 /* NoNestedSourceMaps */); } ts.aggregateTransformFlags(variable); declarations.push(variable); @@ -52654,17 +61185,29 @@ var ts; } } ts.flattenDestructuringBinding = flattenDestructuringBinding; + /** + * Flattens a BindingOrAssignmentElement into zero or more bindings or assignments. + * + * @param flattenContext Options used to control flattening. + * @param element The element to flatten. + * @param value The current RHS value to assign to the element. + * @param location The location to use for source maps and comments. + * @param skipInitializer An optional value indicating whether to include the initializer + * for the element. + */ function flattenBindingOrAssignmentElement(flattenContext, element, value, location, skipInitializer) { if (!skipInitializer) { var initializer = ts.visitNode(ts.getInitializerOfBindingOrAssignmentElement(element), flattenContext.visitor, ts.isExpression); if (initializer) { + // Combine value and initializer value = value ? createDefaultValueCheck(flattenContext, value, initializer, location) : initializer; } else if (!value) { + // Use 'void 0' in absence of value and initializer value = ts.createVoidZero(); } } - var bindingTarget = ts.getTargetOfBindingOrAssignmentElement(element); + var bindingTarget = ts.getTargetOfBindingOrAssignmentElement(element); // TODO: GH#18217 if (ts.isObjectBindingOrAssignmentPattern(bindingTarget)) { flattenObjectBindingOrAssignmentPattern(flattenContext, element, bindingTarget, value, location); } @@ -52672,13 +61215,26 @@ var ts; flattenArrayBindingOrAssignmentPattern(flattenContext, element, bindingTarget, value, location); } else { - flattenContext.emitBindingOrAssignment(bindingTarget, value, location, element); + flattenContext.emitBindingOrAssignment(bindingTarget, value, location, /*original*/ element); // TODO: GH#18217 } } + /** + * Flattens an ObjectBindingOrAssignmentPattern into zero or more bindings or assignments. + * + * @param flattenContext Options used to control flattening. + * @param parent The parent element of the pattern. + * @param pattern The ObjectBindingOrAssignmentPattern to flatten. + * @param value The current RHS value to assign to the element. + * @param location The location to use for source maps and comments. + */ function flattenObjectBindingOrAssignmentPattern(flattenContext, parent, pattern, value, location) { var elements = ts.getElementsOfBindingOrAssignmentPattern(pattern); var 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. var reuseIdentifierExpressions = !ts.isDeclarationBindingElement(parent) || numElements !== 0; value = ensureIdentifier(flattenContext, value, reuseIdentifierExpressions, location); } @@ -52688,9 +61244,9 @@ var ts; var element = elements[i]; if (!ts.getRestIndicatorOfBindingOrAssignmentElement(element)) { var propertyName = ts.getPropertyNameOfBindingOrAssignmentElement(element); - if (flattenContext.level >= 1 - && !(element.transformFlags & (524288 | 1048576)) - && !(ts.getTargetOfBindingOrAssignmentElement(element).transformFlags & (524288 | 1048576)) + if (flattenContext.level >= 1 /* ObjectRest */ + && !(element.transformFlags & (524288 /* ContainsRest */ | 1048576 /* ContainsObjectRest */)) + && !(ts.getTargetOfBindingOrAssignmentElement(element).transformFlags & (524288 /* ContainsRest */ | 1048576 /* ContainsObjectRest */)) && !ts.isComputedPropertyName(propertyName)) { bindingElements = ts.append(bindingElements, element); } @@ -52703,7 +61259,7 @@ var ts; if (ts.isComputedPropertyName(propertyName)) { computedTempVariables = ts.append(computedTempVariables, rhsValue.argumentExpression); } - flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, element); + flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, /*location*/ element); } } else if (i === numElements - 1) { @@ -52711,7 +61267,7 @@ var ts; flattenContext.emitBindingOrAssignment(flattenContext.createObjectBindingOrAssignmentPattern(bindingElements), value, location, pattern); bindingElements = undefined; } - var rhsValue = createRestCall(flattenContext.context, value, elements, computedTempVariables, pattern); + var rhsValue = createRestCall(flattenContext.context, value, elements, computedTempVariables, pattern); // TODO: GH#18217 flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, element); } } @@ -52719,16 +61275,33 @@ var ts; flattenContext.emitBindingOrAssignment(flattenContext.createObjectBindingOrAssignmentPattern(bindingElements), value, location, pattern); } } + /** + * Flattens an ArrayBindingOrAssignmentPattern into zero or more bindings or assignments. + * + * @param flattenContext Options used to control flattening. + * @param parent The parent element of the pattern. + * @param pattern The ArrayBindingOrAssignmentPattern to flatten. + * @param value The current RHS value to assign to the element. + * @param location The location to use for source maps and comments. + */ function flattenArrayBindingOrAssignmentPattern(flattenContext, parent, pattern, value, location) { var elements = ts.getElementsOfBindingOrAssignmentPattern(pattern); var numElements = elements.length; - if (flattenContext.level < 1 && flattenContext.downlevelIteration) { + if (flattenContext.level < 1 /* ObjectRest */ && flattenContext.downlevelIteration) { + // Read the elements of the iterable into an array value = ensureIdentifier(flattenContext, ts.createReadHelper(flattenContext.context, value, numElements > 0 && ts.getRestIndicatorOfBindingOrAssignmentElement(elements[numElements - 1]) ? undefined - : numElements, location), false, location); + : numElements, location), + /*reuseIdentifierExpressions*/ false, location); } - else if (numElements !== 1 && (flattenContext.level < 1 || numElements === 0) + else if (numElements !== 1 && (flattenContext.level < 1 /* ObjectRest */ || numElements === 0) || ts.every(elements, ts.isOmittedExpression)) { + // 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. + // Or all the elements of the binding pattern are omitted expression such as "var [,] = [1,2]", + // then we will create temporary variable. var reuseIdentifierExpressions = !ts.isDeclarationBindingElement(parent) || numElements !== 0; value = ensureIdentifier(flattenContext, value, reuseIdentifierExpressions, location); } @@ -52736,9 +61309,11 @@ var ts; var restContainingElements; for (var i = 0; i < numElements; i++) { var element = elements[i]; - if (flattenContext.level >= 1) { - if (element.transformFlags & 1048576) { - var temp = ts.createTempVariable(undefined); + if (flattenContext.level >= 1 /* ObjectRest */) { + // If an array pattern contains an ObjectRest, we must cache the result so that we + // can perform the ObjectRest destructuring in a different declaration + if (element.transformFlags & 1048576 /* ContainsObjectRest */) { + var temp = ts.createTempVariable(/*recordTempVariable*/ undefined); if (flattenContext.hoistTempVariables) { flattenContext.context.hoistVariableDeclaration(temp); } @@ -52754,11 +61329,11 @@ var ts; } else if (!ts.getRestIndicatorOfBindingOrAssignmentElement(element)) { var rhsValue = ts.createElementAccess(value, i); - flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, element); + flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, /*location*/ element); } else if (i === numElements - 1) { var rhsValue = ts.createArraySlice(value, i); - flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, element); + flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, /*location*/ element); } } if (bindingElements) { @@ -52771,13 +61346,31 @@ var ts; } } } + /** + * Creates an expression used to provide a default value if a value is `undefined` at runtime. + * + * @param flattenContext Options used to control flattening. + * @param value The RHS value to test. + * @param defaultValue The default value to use if `value` is `undefined` at runtime. + * @param location The location to use for source maps and comments. + */ function createDefaultValueCheck(flattenContext, value, defaultValue, location) { - value = ensureIdentifier(flattenContext, value, true, location); + value = ensureIdentifier(flattenContext, value, /*reuseIdentifierExpressions*/ true, location); return ts.createConditional(ts.createTypeCheck(value, "undefined"), defaultValue, value); } + /** + * Creates either a PropertyAccessExpression or an ElementAccessExpression for the + * right-hand side of a transformed destructuring assignment. + * + * @link https://tc39.github.io/ecma262/#sec-runtime-semantics-keyeddestructuringassignmentevaluation + * + * @param flattenContext Options used to control flattening. + * @param value The RHS value that is the source of the property. + * @param propertyName The destructuring property name. + */ function createDestructuringPropertyAccess(flattenContext, value, propertyName) { if (ts.isComputedPropertyName(propertyName)) { - var argumentExpression = ensureIdentifier(flattenContext, ts.visitNode(propertyName.expression, flattenContext.visitor), false, propertyName); + var argumentExpression = ensureIdentifier(flattenContext, ts.visitNode(propertyName.expression, flattenContext.visitor), /*reuseIdentifierExpressions*/ false, /*location*/ propertyName); return ts.createElementAccess(value, argumentExpression); } else if (ts.isStringOrNumericLiteral(propertyName)) { @@ -52790,18 +61383,29 @@ var ts; return ts.createPropertyAccess(value, name); } } + /** + * Ensures that there exists a declared identifier whose value holds the given expression. + * This function is useful to ensure that the expression's value can be read from in subsequent expressions. + * Unless 'reuseIdentifierExpressions' is false, 'value' will be returned if it is just an identifier. + * + * @param flattenContext Options used to control flattening. + * @param value the expression whose value needs to be bound. + * @param reuseIdentifierExpressions true if identifier expressions can simply be returned; + * false if it is necessary to always emit an identifier. + * @param location The location to use for source maps and comments. + */ function ensureIdentifier(flattenContext, value, reuseIdentifierExpressions, location) { if (ts.isIdentifier(value) && reuseIdentifierExpressions) { return value; } else { - var temp = ts.createTempVariable(undefined); + var temp = ts.createTempVariable(/*recordTempVariable*/ undefined); if (flattenContext.hoistTempVariables) { flattenContext.context.hoistVariableDeclaration(temp); flattenContext.emitExpression(ts.setTextRange(ts.createAssignment(temp, value), location)); } else { - flattenContext.emitBindingOrAssignment(temp, value, location, undefined); + flattenContext.emitBindingOrAssignment(temp, value, location, /*original*/ undefined); } return temp; } @@ -52821,7 +61425,7 @@ var ts; return ts.createObjectLiteral(ts.map(elements, ts.convertToObjectAssignmentElement)); } function makeBindingElement(name) { - return ts.createBindingElement(undefined, undefined, name); + return ts.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, name); } function makeAssignmentElement(name) { return name; @@ -52831,6 +61435,9 @@ var ts; scoped: false, text: "\n var __rest = (this && this.__rest) || function (s, e) {\n var t = {};\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\n t[p] = s[p];\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)\n t[p[i]] = s[p[i]];\n return t;\n };" }; + /** Given value: o, propName: p, pattern: { a, b, ...p } from the original statement + * `{ a, b, ...p } = o`, create `p = __rest(o, ["a", "b"]);` + */ function createRestCall(context, value, elements, computedTempVariables, location) { context.requestEmitHelper(restHelper); var propertyNames = []; @@ -52841,6 +61448,7 @@ var ts; if (ts.isComputedPropertyName(propertyName)) { var temp = computedTempVariables[computedTempVariableOffset]; computedTempVariableOffset++; + // typeof _tmp === "symbol" ? _tmp : _tmp + "" propertyNames.push(ts.createConditional(ts.createTypeCheck(temp, "symbol"), temp, ts.createAdd(temp, ts.createLiteral("")))); } else { @@ -52848,19 +61456,27 @@ var ts; } } } - return ts.createCall(ts.getHelperName("__rest"), undefined, [ + return ts.createCall(ts.getHelperName("__rest"), + /*typeArguments*/ undefined, [ value, ts.setTextRange(ts.createArrayLiteral(propertyNames), location) ]); } })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { + /** + * Indicates whether to emit type metadata in the new format. + */ var USE_NEW_TYPE_METADATA_FORMAT = false; var TypeScriptSubstitutionFlags; (function (TypeScriptSubstitutionFlags) { + /** Enables substitutions for decorated classes. */ TypeScriptSubstitutionFlags[TypeScriptSubstitutionFlags["ClassAliases"] = 1] = "ClassAliases"; + /** Enables substitutions for namespace exports. */ TypeScriptSubstitutionFlags[TypeScriptSubstitutionFlags["NamespaceExports"] = 2] = "NamespaceExports"; + /* Enables substitutions for unqualified enum members */ TypeScriptSubstitutionFlags[TypeScriptSubstitutionFlags["NonQualifiedEnumMembers"] = 8] = "NonQualifiedEnumMembers"; })(TypeScriptSubstitutionFlags || (TypeScriptSubstitutionFlags = {})); var ClassFacts; @@ -52886,36 +61502,61 @@ var ts; var strictNullChecks = ts.getStrictOptionValue(compilerOptions, "strictNullChecks"); var languageVersion = ts.getEmitScriptTarget(compilerOptions); var moduleKind = ts.getEmitModuleKind(compilerOptions); + // Save the previous transformation hooks. var previousOnEmitNode = context.onEmitNode; var previousOnSubstituteNode = context.onSubstituteNode; + // Set new transformation hooks. context.onEmitNode = onEmitNode; context.onSubstituteNode = onSubstituteNode; - context.enableSubstitution(185); - context.enableSubstitution(186); + // Enable substitution for property/element access to emit const enum values. + context.enableSubstitution(185 /* PropertyAccessExpression */); + context.enableSubstitution(186 /* ElementAccessExpression */); + // These variables contain state that changes as we descend into the tree. var currentSourceFile; var currentNamespace; var currentNamespaceContainerName; var currentScope; var currentScopeFirstDeclarationsOfName; + /** + * Keeps track of whether expression substitution has been enabled for specific edge cases. + * They are persisted between each SourceFile transformation and should not be reset. + */ var enabledSubstitutions; + /** + * A map that keeps track of aliases created for classes with decorators to avoid issues + * with the double-binding behavior of classes. + */ var classAliases; + /** + * Keeps track of whether we are within any containing namespaces when performing + * just-in-time substitution while printing an expression identifier. + */ var applicableSubstitutions; + /** + * Tracks what computed name expressions originating from elided names must be inlined + * at the next execution site, in document order + */ var pendingExpressions; return transformSourceFileOrBundle; function transformSourceFileOrBundle(node) { - if (node.kind === 275) { + if (node.kind === 275 /* Bundle */) { return transformBundle(node); } return transformSourceFile(node); } function transformBundle(node) { return ts.createBundle(node.sourceFiles.map(transformSourceFile), ts.mapDefined(node.prepends, function (prepend) { - if (prepend.kind === 277) { + if (prepend.kind === 277 /* InputFiles */) { return ts.createUnparsedSourceFile(prepend.javascriptText, prepend.javascriptMapPath, prepend.javascriptMapText); } return prepend; })); } + /** + * Transform TypeScript-specific syntax in a SourceFile. + * + * @param node A SourceFile node. + */ function transformSourceFile(node) { if (node.isDeclarationFile) { return node; @@ -52926,61 +61567,100 @@ var ts; currentSourceFile = undefined; return visited; } + /** + * Visits a node, saving and restoring state variables on the stack. + * + * @param node The node to visit. + */ function saveStateAndInvoke(node, f) { + // Save state var savedCurrentScope = currentScope; var savedCurrentScopeFirstDeclarationsOfName = currentScopeFirstDeclarationsOfName; + // Handle state changes before visiting a node. onBeforeVisitNode(node); var visited = f(node); + // Restore state if (currentScope !== savedCurrentScope) { currentScopeFirstDeclarationsOfName = savedCurrentScopeFirstDeclarationsOfName; } currentScope = savedCurrentScope; return visited; } + /** + * Performs actions that should always occur immediately before visiting a node. + * + * @param node The node to visit. + */ function onBeforeVisitNode(node) { switch (node.kind) { - case 274: - case 241: - case 240: - case 213: + case 274 /* SourceFile */: + case 241 /* CaseBlock */: + case 240 /* ModuleBlock */: + case 213 /* Block */: currentScope = node; currentScopeFirstDeclarationsOfName = undefined; break; - case 235: - case 234: - if (ts.hasModifier(node, 2)) { + case 235 /* ClassDeclaration */: + case 234 /* FunctionDeclaration */: + if (ts.hasModifier(node, 2 /* Ambient */)) { break; } + // Record these declarations provided that they have a name. if (node.name) { recordEmittedDeclarationInScope(node); } else { - ts.Debug.assert(node.kind === 235 || ts.hasModifier(node, 512)); + // These nodes should always have names unless they are default-exports; + // however, class declaration parsing allows for undefined names, so syntactically invalid + // programs may also have an undefined name. + ts.Debug.assert(node.kind === 235 /* ClassDeclaration */ || ts.hasModifier(node, 512 /* Default */)); } break; } } + /** + * General-purpose node visitor. + * + * @param node The node to visit. + */ function visitor(node) { return saveStateAndInvoke(node, visitorWorker); } + /** + * Visits and possibly transforms any node. + * + * @param node The node to visit. + */ function visitorWorker(node) { - if (node.transformFlags & 1) { + if (node.transformFlags & 1 /* TypeScript */) { + // This node is explicitly marked as TypeScript, so we should transform the node. return visitTypeScript(node); } - else if (node.transformFlags & 2) { + else if (node.transformFlags & 2 /* ContainsTypeScript */) { + // This node contains TypeScript, so we should visit its children. return ts.visitEachChild(node, visitor, context); } return node; } + /** + * Specialized visitor that visits the immediate children of a SourceFile. + * + * @param node The node to visit. + */ function sourceElementVisitor(node) { return saveStateAndInvoke(node, sourceElementVisitorWorker); } + /** + * Specialized visitor that visits the immediate children of a SourceFile. + * + * @param node The node to visit. + */ function sourceElementVisitorWorker(node) { switch (node.kind) { - case 244: - case 243: - case 249: - case 250: + case 244 /* ImportDeclaration */: + case 243 /* ImportEqualsDeclaration */: + case 249 /* ExportAssignment */: + case 250 /* ExportDeclaration */: return visitEllidableStatement(node); default: return visitorWorker(node); @@ -52989,168 +61669,265 @@ var ts; function visitEllidableStatement(node) { var parsed = ts.getParseTreeNode(node); if (parsed !== node) { - if (node.transformFlags & 2) { + // If the node has been transformed by a `before` transformer, perform no ellision on it + // As the type information we would attempt to lookup to perform ellision is potentially unavailable for the synthesized nodes + // We do not reuse `visitorWorker`, as the ellidable statement syntax kinds are technically unrecognized by the switch-case in `visitTypeScript`, + // and will trigger debug failures when debug verbosity is turned up + if (node.transformFlags & 2 /* ContainsTypeScript */) { + // This node contains TypeScript, so we should visit its children. return ts.visitEachChild(node, visitor, context); } + // Otherwise, we can just return the node return node; } switch (node.kind) { - case 244: + case 244 /* ImportDeclaration */: return visitImportDeclaration(node); - case 243: + case 243 /* ImportEqualsDeclaration */: return visitImportEqualsDeclaration(node); - case 249: + case 249 /* ExportAssignment */: return visitExportAssignment(node); - case 250: + case 250 /* ExportDeclaration */: return visitExportDeclaration(node); default: ts.Debug.fail("Unhandled ellided statement"); } } + /** + * Specialized visitor that visits the immediate children of a namespace. + * + * @param node The node to visit. + */ function namespaceElementVisitor(node) { return saveStateAndInvoke(node, namespaceElementVisitorWorker); } + /** + * Specialized visitor that visits the immediate children of a namespace. + * + * @param node The node to visit. + */ function namespaceElementVisitorWorker(node) { - if (node.kind === 250 || - node.kind === 244 || - node.kind === 245 || - (node.kind === 243 && - node.moduleReference.kind === 254)) { + if (node.kind === 250 /* ExportDeclaration */ || + node.kind === 244 /* ImportDeclaration */ || + node.kind === 245 /* ImportClause */ || + (node.kind === 243 /* ImportEqualsDeclaration */ && + node.moduleReference.kind === 254 /* ExternalModuleReference */)) { + // do not emit ES6 imports and exports since they are illegal inside a namespace return undefined; } - else if (node.transformFlags & 1 || ts.hasModifier(node, 1)) { + else if (node.transformFlags & 1 /* TypeScript */ || ts.hasModifier(node, 1 /* Export */)) { + // This node is explicitly marked as TypeScript, or is exported at the namespace + // level, so we should transform the node. return visitTypeScript(node); } - else if (node.transformFlags & 2) { + else if (node.transformFlags & 2 /* ContainsTypeScript */) { + // This node contains TypeScript, so we should visit its children. return ts.visitEachChild(node, visitor, context); } return node; } + /** + * Specialized visitor that visits the immediate children of a class with TypeScript syntax. + * + * @param node The node to visit. + */ function classElementVisitor(node) { return saveStateAndInvoke(node, classElementVisitorWorker); } + /** + * Specialized visitor that visits the immediate children of a class with TypeScript syntax. + * + * @param node The node to visit. + */ function classElementVisitorWorker(node) { switch (node.kind) { - case 155: + case 155 /* Constructor */: + // TypeScript constructors are transformed in `visitClassDeclaration`. + // We elide them here as `visitorWorker` checks transform flags, which could + // erronously include an ES6 constructor without TypeScript syntax. return undefined; - case 152: - case 160: - case 156: - case 157: - case 154: + case 152 /* PropertyDeclaration */: + case 160 /* IndexSignature */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 154 /* MethodDeclaration */: + // Fallback to the default visit behavior. return visitorWorker(node); - case 212: + case 212 /* SemicolonClassElement */: return node; default: return ts.Debug.failBadSyntaxKind(node); } } function modifierVisitor(node) { - if (ts.modifierToFlag(node.kind) & 2270) { + if (ts.modifierToFlag(node.kind) & 2270 /* TypeScriptModifier */) { return undefined; } - else if (currentNamespace && node.kind === 84) { + else if (currentNamespace && node.kind === 84 /* ExportKeyword */) { return undefined; } return node; } + /** + * Branching visitor, visits a TypeScript syntax node. + * + * @param node The node to visit. + */ function visitTypeScript(node) { - if (ts.hasModifier(node, 2) && ts.isStatement(node)) { + if (ts.hasModifier(node, 2 /* Ambient */) && ts.isStatement(node)) { + // TypeScript ambient declarations are elided, but some comments may be preserved. + // See the implementation of `getLeadingComments` in comments.ts for more details. return ts.createNotEmittedStatement(node); } switch (node.kind) { - case 84: - case 79: + case 84 /* ExportKeyword */: + case 79 /* DefaultKeyword */: + // ES6 export and default modifiers are elided when inside a namespace. return currentNamespace ? undefined : node; - case 114: - case 112: - case 113: - case 117: - case 76: - case 124: - case 132: - case 167: - case 168: - case 166: - case 161: - case 148: - case 119: - case 142: - case 122: - case 137: - case 134: - case 131: - case 105: - case 138: - case 164: - case 163: - case 165: - case 162: - case 169: - case 170: - case 171: - case 173: - case 174: - case 175: - case 176: - case 177: - case 178: - case 160: - case 150: - case 237: + case 114 /* PublicKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: + case 117 /* AbstractKeyword */: + case 76 /* ConstKeyword */: + case 124 /* DeclareKeyword */: + case 132 /* ReadonlyKeyword */: + // TypeScript accessibility and readonly modifiers are elided. + case 167 /* ArrayType */: + case 168 /* TupleType */: + case 166 /* TypeLiteral */: + case 161 /* TypePredicate */: + case 148 /* TypeParameter */: + case 119 /* AnyKeyword */: + case 142 /* UnknownKeyword */: + case 122 /* BooleanKeyword */: + case 137 /* StringKeyword */: + case 134 /* NumberKeyword */: + case 131 /* NeverKeyword */: + case 105 /* VoidKeyword */: + case 138 /* SymbolKeyword */: + case 164 /* ConstructorType */: + case 163 /* FunctionType */: + case 165 /* TypeQuery */: + case 162 /* TypeReference */: + case 169 /* UnionType */: + case 170 /* IntersectionType */: + case 171 /* ConditionalType */: + case 173 /* ParenthesizedType */: + case 174 /* ThisType */: + case 175 /* TypeOperator */: + case 176 /* IndexedAccessType */: + case 177 /* MappedType */: + case 178 /* LiteralType */: + // TypeScript type nodes are elided. + case 160 /* IndexSignature */: + // TypeScript index signatures are elided. + case 150 /* Decorator */: + // TypeScript decorators are elided. They will be emitted as part of visitClassDeclaration. + case 237 /* TypeAliasDeclaration */: + // TypeScript type-only declarations are elided. return undefined; - case 152: + case 152 /* PropertyDeclaration */: + // TypeScript property declarations are elided. However their names are still visited, and can potentially be retained if they could have sideeffects return visitPropertyDeclaration(node); - case 242: + case 242 /* NamespaceExportDeclaration */: + // TypeScript namespace export declarations are elided. return undefined; - case 155: + case 155 /* Constructor */: return visitConstructor(node); - case 236: + case 236 /* InterfaceDeclaration */: + // TypeScript interfaces are elided, but some comments may be preserved. + // See the implementation of `getLeadingComments` in comments.ts for more details. return ts.createNotEmittedStatement(node); - case 235: + case 235 /* 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 return visitClassDeclaration(node); - case 205: + case 205 /* 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 return visitClassExpression(node); - case 268: + case 268 /* HeritageClause */: + // This is a heritage clause with TypeScript syntax extensions. + // + // TypeScript heritage clause extensions include: + // - `implements` clause return visitHeritageClause(node); - case 207: + case 207 /* ExpressionWithTypeArguments */: + // TypeScript supports type arguments on an expression in an `extends` heritage clause. return visitExpressionWithTypeArguments(node); - case 154: + case 154 /* MethodDeclaration */: + // TypeScript method declarations may have decorators, modifiers + // or type annotations. return visitMethodDeclaration(node); - case 156: + case 156 /* GetAccessor */: + // Get Accessors can have TypeScript modifiers, decorators, and type annotations. return visitGetAccessor(node); - case 157: + case 157 /* SetAccessor */: + // Set Accessors can have TypeScript modifiers and type annotations. return visitSetAccessor(node); - case 234: + case 234 /* FunctionDeclaration */: + // Typescript function declarations can have modifiers, decorators, and type annotations. return visitFunctionDeclaration(node); - case 192: + case 192 /* FunctionExpression */: + // TypeScript function expressions can have modifiers and type annotations. return visitFunctionExpression(node); - case 193: + case 193 /* ArrowFunction */: + // TypeScript arrow functions can have modifiers and type annotations. return visitArrowFunction(node); - case 149: + case 149 /* 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 + // - this parameters return visitParameter(node); - case 191: + case 191 /* ParenthesizedExpression */: + // ParenthesizedExpressions are TypeScript if their expression is a + // TypeAssertion or AsExpression return visitParenthesizedExpression(node); - case 190: - case 208: + case 190 /* TypeAssertionExpression */: + case 208 /* AsExpression */: + // TypeScript type assertions are removed, but their subtrees are preserved. return visitAssertionExpression(node); - case 187: + case 187 /* CallExpression */: return visitCallExpression(node); - case 188: + case 188 /* NewExpression */: return visitNewExpression(node); - case 189: + case 189 /* TaggedTemplateExpression */: return visitTaggedTemplateExpression(node); - case 209: + case 209 /* NonNullExpression */: + // TypeScript non-null expressions are removed, but their subtrees are preserved. return visitNonNullExpression(node); - case 238: + case 238 /* EnumDeclaration */: + // TypeScript enum declarations do not exist in ES6 and must be rewritten. return visitEnumDeclaration(node); - case 214: + case 214 /* VariableStatement */: + // TypeScript namespace exports for variable statements must be transformed. return visitVariableStatement(node); - case 232: + case 232 /* VariableDeclaration */: return visitVariableDeclaration(node); - case 239: + case 239 /* ModuleDeclaration */: + // TypeScript namespace declarations must be transformed. return visitModuleDeclaration(node); - case 243: + case 243 /* ImportEqualsDeclaration */: + // TypeScript namespace or external module import. return visitImportEqualsDeclaration(node); default: return ts.Debug.failBadSyntaxKind(node); @@ -53160,8 +61937,11 @@ var ts; var alwaysStrict = ts.getStrictOptionValue(compilerOptions, "alwaysStrict") && !(ts.isExternalModule(node) && moduleKind >= ts.ModuleKind.ES2015) && !ts.isJsonSourceFile(node); - return ts.updateSourceFileNode(node, ts.visitLexicalEnvironment(node.statements, sourceElementVisitor, context, 0, alwaysStrict)); + return ts.updateSourceFileNode(node, ts.visitLexicalEnvironment(node.statements, sourceElementVisitor, context, /*start*/ 0, alwaysStrict)); } + /** + * Tests whether we should emit a __decorate call for a class declaration. + */ function shouldEmitDecorateCallForClass(node) { if (node.decorators && node.decorators.length > 0) { return true; @@ -53172,68 +61952,104 @@ var ts; } return false; } + /** + * Tests whether we should emit a __decorate call for a parameter declaration. + */ function shouldEmitDecorateCallForParameter(parameter) { return parameter.decorators !== undefined && parameter.decorators.length > 0; } function getClassFacts(node, staticProperties) { - var facts = 0; + var facts = 0 /* None */; if (ts.some(staticProperties)) - facts |= 1; + facts |= 1 /* HasStaticInitializedProperties */; var extendsClauseElement = ts.getClassExtendsHeritageClauseElement(node); - if (extendsClauseElement && ts.skipOuterExpressions(extendsClauseElement.expression).kind !== 95) - facts |= 64; + if (extendsClauseElement && ts.skipOuterExpressions(extendsClauseElement.expression).kind !== 95 /* NullKeyword */) + facts |= 64 /* IsDerivedClass */; if (shouldEmitDecorateCallForClass(node)) - facts |= 2; + facts |= 2 /* HasConstructorDecorators */; if (ts.childIsDecorated(node)) - facts |= 4; + facts |= 4 /* HasMemberDecorators */; if (isExportOfNamespace(node)) - facts |= 8; + facts |= 8 /* IsExportOfNamespace */; else if (isDefaultExternalModuleExport(node)) - facts |= 32; + facts |= 32 /* IsDefaultExternalExport */; else if (isNamedExternalModuleExport(node)) - facts |= 16; - if (languageVersion <= 1 && (facts & 7)) - facts |= 128; + facts |= 16 /* IsNamedExternalExport */; + if (languageVersion <= 1 /* ES5 */ && (facts & 7 /* MayNeedImmediatelyInvokedFunctionExpression */)) + facts |= 128 /* UseImmediatelyInvokedFunctionExpression */; return facts; } + /** + * Transforms a class declaration with TypeScript syntax into compatible ES6. + * + * 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. + * + * @param node The node to transform. + */ function visitClassDeclaration(node) { var savedPendingExpressions = pendingExpressions; pendingExpressions = undefined; - var staticProperties = getInitializedProperties(node, true); + var staticProperties = getInitializedProperties(node, /*isStatic*/ true); var facts = getClassFacts(node, staticProperties); - if (facts & 128) { + if (facts & 128 /* UseImmediatelyInvokedFunctionExpression */) { context.startLexicalEnvironment(); } - var name = node.name || (facts & 5 ? ts.getGeneratedNameForNode(node) : undefined); - var classStatement = facts & 2 + var name = node.name || (facts & 5 /* NeedsName */ ? ts.getGeneratedNameForNode(node) : undefined); + var classStatement = facts & 2 /* HasConstructorDecorators */ ? createClassDeclarationHeadWithDecorators(node, name, facts) : createClassDeclarationHeadWithoutDecorators(node, name, facts); var statements = [classStatement]; + // Write any pending expressions from elided or moved computed property names if (ts.some(pendingExpressions)) { statements.push(ts.createStatement(ts.inlineExpressions(pendingExpressions))); } pendingExpressions = savedPendingExpressions; - if (facts & 1) { - addInitializedPropertyStatements(statements, staticProperties, facts & 128 ? ts.getInternalName(node) : ts.getLocalName(node)); + // 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. + if (facts & 1 /* HasStaticInitializedProperties */) { + addInitializedPropertyStatements(statements, staticProperties, facts & 128 /* UseImmediatelyInvokedFunctionExpression */ ? ts.getInternalName(node) : ts.getLocalName(node)); } - addClassElementDecorationStatements(statements, node, false); - addClassElementDecorationStatements(statements, node, true); + // Write any decorators of the node. + addClassElementDecorationStatements(statements, node, /*isStatic*/ false); + addClassElementDecorationStatements(statements, node, /*isStatic*/ true); addConstructorDecorationStatement(statements, node); - if (facts & 128) { - var closingBraceLocation = ts.createTokenRange(ts.skipTrivia(currentSourceFile.text, node.members.end), 18); + if (facts & 128 /* UseImmediatelyInvokedFunctionExpression */) { + // When we emit a TypeScript class down to ES5, we must wrap it in an IIFE so that the + // 'es2015' transformer can properly nest static initializers and decorators. The result + // looks something like: + // + // var C = function () { + // class C { + // } + // C.static_prop = 1; + // return C; + // }(); + // + var closingBraceLocation = ts.createTokenRange(ts.skipTrivia(currentSourceFile.text, node.members.end), 18 /* CloseBraceToken */); var localName = ts.getInternalName(node); + // The following partially-emitted expression exists purely to align our sourcemap + // emit with the original emitter. var outer = ts.createPartiallyEmittedExpression(localName); outer.end = closingBraceLocation.end; - ts.setEmitFlags(outer, 1536); + ts.setEmitFlags(outer, 1536 /* NoComments */); var statement = ts.createReturn(outer); statement.pos = closingBraceLocation.pos; - ts.setEmitFlags(statement, 1536 | 384); + ts.setEmitFlags(statement, 1536 /* NoComments */ | 384 /* NoTokenSourceMaps */); statements.push(statement); ts.prependStatements(statements, context.endLexicalEnvironment()); var iife = ts.createImmediatelyInvokedArrowFunction(statements); - ts.setEmitFlags(iife, 33554432); - var varStatement = ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.createVariableDeclaration(ts.getLocalName(node, false, false), undefined, iife) + ts.setEmitFlags(iife, 33554432 /* TypeScriptClassWrapper */); + var varStatement = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(ts.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ false), + /*type*/ undefined, iife) ])); ts.setOriginalNode(varStatement, node); ts.setCommentRange(varStatement, node); @@ -53241,75 +62057,205 @@ var ts; ts.startOnNewLine(varStatement); statements = [varStatement]; } - if (facts & 8) { + // If the class is exported as part of a TypeScript namespace, emit the namespace export. + // Otherwise, if the class was exported at the top level and was decorated, emit an export + // declaration or export default for the class. + if (facts & 8 /* IsExportOfNamespace */) { addExportMemberAssignment(statements, node); } - else if (facts & 128 || facts & 2) { - if (facts & 32) { - statements.push(ts.createExportDefault(ts.getLocalName(node, false, true))); + else if (facts & 128 /* UseImmediatelyInvokedFunctionExpression */ || facts & 2 /* HasConstructorDecorators */) { + if (facts & 32 /* IsDefaultExternalExport */) { + statements.push(ts.createExportDefault(ts.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true))); } - else if (facts & 16) { - statements.push(ts.createExternalModuleExport(ts.getLocalName(node, false, true))); + else if (facts & 16 /* IsNamedExternalExport */) { + statements.push(ts.createExternalModuleExport(ts.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true))); } } if (statements.length > 1) { + // Add a DeclarationMarker as a marker for the end of the declaration statements.push(ts.createEndOfDeclarationMarker(node)); - ts.setEmitFlags(classStatement, ts.getEmitFlags(classStatement) | 4194304); + ts.setEmitFlags(classStatement, ts.getEmitFlags(classStatement) | 4194304 /* HasEndOfDeclarationMarker */); } return ts.singleOrMany(statements); } + /** + * Transforms a non-decorated class declaration and appends the resulting statements. + * + * @param node A ClassDeclaration node. + * @param name The name of the class. + * @param facts Precomputed facts about the class. + */ function createClassDeclarationHeadWithoutDecorators(node, name, facts) { - var modifiers = !(facts & 128) + // ${modifiers} class ${name} ${heritageClauses} { + // ${members} + // } + // we do not emit modifiers on the declaration if we are emitting an IIFE + var modifiers = !(facts & 128 /* UseImmediatelyInvokedFunctionExpression */) ? ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier) : undefined; - var classDeclaration = ts.createClassDeclaration(undefined, modifiers, name, undefined, ts.visitNodes(node.heritageClauses, visitor, ts.isHeritageClause), transformClassMembers(node, (facts & 64) !== 0)); + var classDeclaration = ts.createClassDeclaration( + /*decorators*/ undefined, modifiers, name, + /*typeParameters*/ undefined, ts.visitNodes(node.heritageClauses, visitor, ts.isHeritageClause), transformClassMembers(node, (facts & 64 /* IsDerivedClass */) !== 0)); + // To better align with the old emitter, we should not emit a trailing source map + // entry if the class has static properties. var emitFlags = ts.getEmitFlags(node); - if (facts & 1) { - emitFlags |= 32; + if (facts & 1 /* HasStaticInitializedProperties */) { + emitFlags |= 32 /* NoTrailingSourceMap */; } ts.setTextRange(classDeclaration, node); ts.setOriginalNode(classDeclaration, node); ts.setEmitFlags(classDeclaration, emitFlags); return classDeclaration; } + /** + * Transforms a decorated class declaration and appends the resulting statements. If + * the class requires an alias to avoid issues with double-binding, the alias is returned. + */ function createClassDeclarationHeadWithDecorators(node, name, facts) { + // When we emit an ES6 class that has a class decorator, we must tailor the + // emit to certain specific cases. + // + // In the simplest case, we emit the class declaration as a let declaration, and + // evaluate decorators after the close of the class body: + // + // [Example 1] + // --------------------------------------------------------------------- + // TypeScript | Javascript + // --------------------------------------------------------------------- + // @dec | let C = class C { + // class C { | } + // } | C = __decorate([dec], C); + // --------------------------------------------------------------------- + // @dec | let C = class C { + // export class C { | } + // } | C = __decorate([dec], C); + // | export { C }; + // --------------------------------------------------------------------- + // + // If a class declaration contains a reference to itself *inside* of the class body, + // this introduces two bindings to the class: One outside of the class body, and one + // inside of the class body. If we apply decorators as in [Example 1] above, there + // is the possibility that the decorator `dec` will return a new value for the + // constructor, which would result in the binding inside of the class no longer + // pointing to the same reference as the binding outside of the class. + // + // As a result, we must instead rewrite all references to the class *inside* of the + // class body to instead point to a local temporary alias for the class: + // + // [Example 2] + // --------------------------------------------------------------------- + // TypeScript | Javascript + // --------------------------------------------------------------------- + // @dec | let C = C_1 = class C { + // class C { | static x() { return C_1.y; } + // static x() { return C.y; } | } + // static y = 1; | C.y = 1; + // } | C = C_1 = __decorate([dec], C); + // | var C_1; + // --------------------------------------------------------------------- + // @dec | let C = class C { + // export class C { | static x() { return C_1.y; } + // static x() { return C.y; } | } + // static y = 1; | C.y = 1; + // } | C = C_1 = __decorate([dec], C); + // | export { C }; + // | var C_1; + // --------------------------------------------------------------------- + // + // If a class declaration is the default export of a module, we instead emit + // the export after the decorated declaration: + // + // [Example 3] + // --------------------------------------------------------------------- + // TypeScript | Javascript + // --------------------------------------------------------------------- + // @dec | let default_1 = class { + // export default class { | } + // } | default_1 = __decorate([dec], default_1); + // | export default default_1; + // --------------------------------------------------------------------- + // @dec | let C = class C { + // export default class C { | } + // } | C = __decorate([dec], C); + // | export default C; + // --------------------------------------------------------------------- + // + // If the class declaration is the default export and a reference to itself + // inside of the class body, we must emit both an alias for the class *and* + // move the export after the declaration: + // + // [Example 4] + // --------------------------------------------------------------------- + // TypeScript | Javascript + // --------------------------------------------------------------------- + // @dec | let C = class C { + // export default class C { | static x() { return C_1.y; } + // static x() { return C.y; } | } + // static y = 1; | C.y = 1; + // } | C = C_1 = __decorate([dec], C); + // | export default C; + // | var C_1; + // --------------------------------------------------------------------- + // var location = ts.moveRangePastDecorators(node); var classAlias = getClassAliasIfNeeded(node); - var declName = ts.getLocalName(node, false, true); + var declName = ts.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); + // ... = class ${name} ${heritageClauses} { + // ${members} + // } var heritageClauses = ts.visitNodes(node.heritageClauses, visitor, ts.isHeritageClause); - var members = transformClassMembers(node, (facts & 64) !== 0); - var classExpression = ts.createClassExpression(undefined, name, undefined, heritageClauses, members); + var members = transformClassMembers(node, (facts & 64 /* IsDerivedClass */) !== 0); + var classExpression = ts.createClassExpression(/*modifiers*/ undefined, name, /*typeParameters*/ undefined, heritageClauses, members); ts.setOriginalNode(classExpression, node); ts.setTextRange(classExpression, location); - var statement = ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.createVariableDeclaration(declName, undefined, classAlias ? ts.createAssignment(classAlias, classExpression) : classExpression) - ], 1)); + // let ${name} = ${classExpression} where name is either declaredName if the class doesn't contain self-reference + // or decoratedClassAlias if the class contain self-reference. + var statement = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(declName, + /*type*/ undefined, classAlias ? ts.createAssignment(classAlias, classExpression) : classExpression) + ], 1 /* Let */)); ts.setOriginalNode(statement, node); ts.setTextRange(statement, location); ts.setCommentRange(statement, node); return statement; } + /** + * Transforms a class expression with TypeScript syntax into compatible ES6. + * + * 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. + * + * @param node The node to transform. + */ function visitClassExpression(node) { var savedPendingExpressions = pendingExpressions; pendingExpressions = undefined; - var staticProperties = getInitializedProperties(node, true); + var staticProperties = getInitializedProperties(node, /*isStatic*/ true); var heritageClauses = ts.visitNodes(node.heritageClauses, visitor, ts.isHeritageClause); - var members = transformClassMembers(node, ts.some(heritageClauses, function (c) { return c.token === 85; })); - var classExpression = ts.createClassExpression(undefined, node.name, undefined, heritageClauses, members); + var members = transformClassMembers(node, ts.some(heritageClauses, function (c) { return c.token === 85 /* ExtendsKeyword */; })); + var classExpression = ts.createClassExpression( + /*modifiers*/ undefined, node.name, + /*typeParameters*/ undefined, heritageClauses, members); ts.setOriginalNode(classExpression, node); ts.setTextRange(classExpression, node); if (ts.some(staticProperties) || ts.some(pendingExpressions)) { var expressions = []; - var isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & 8388608; + var isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & 8388608 /* ClassWithConstructorReference */; var temp = ts.createTempVariable(hoistVariableDeclaration, !!isClassWithConstructorReference); if (isClassWithConstructorReference) { + // record an alias as the class name is not in scope for statics. enableSubstitutionForClassAliases(); var alias = ts.getSynthesizedClone(temp); - alias.autoGenerateFlags &= ~8; + alias.autoGenerateFlags &= ~8 /* ReservedInNestedScopes */; classAliases[ts.getOriginalNodeId(node)] = alias; } - ts.setEmitFlags(classExpression, 65536 | ts.getEmitFlags(classExpression)); + // To preserve the behavior of the old emitter, we explicitly indent + // the body of a class with static initializers. + ts.setEmitFlags(classExpression, 65536 /* Indented */ | ts.getEmitFlags(classExpression)); expressions.push(ts.startOnNewLine(ts.createAssignment(temp, classExpression))); + // Add any pending expressions leftover from elided or relocated computed property names ts.addRange(expressions, ts.map(pendingExpressions, ts.startOnNewLine)); pendingExpressions = savedPendingExpressions; ts.addRange(expressions, generateInitializedPropertyExpressions(staticProperties, temp)); @@ -53319,6 +62265,12 @@ var ts; pendingExpressions = savedPendingExpressions; return classExpression; } + /** + * Transforms the members of a class. + * + * @param node The current class. + * @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'. + */ function transformClassMembers(node, isDerivedClass) { var members = []; var constructor = transformConstructor(node, isDerivedClass); @@ -53326,52 +62278,137 @@ var ts; members.push(constructor); } ts.addRange(members, ts.visitNodes(node.members, classElementVisitor, ts.isClassElement)); - return ts.setTextRange(ts.createNodeArray(members), node.members); + return ts.setTextRange(ts.createNodeArray(members), /*location*/ node.members); } + /** + * Transforms (or creates) a constructor for a class. + * + * @param node The current class. + * @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'. + */ function transformConstructor(node, isDerivedClass) { + // 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 var hasInstancePropertyWithInitializer = ts.forEach(node.members, isInstanceInitializedProperty); - var hasParameterPropertyAssignments = node.transformFlags & 262144; + var hasParameterPropertyAssignments = node.transformFlags & 262144 /* ContainsParameterPropertyAssignments */; var constructor = ts.getFirstConstructorWithBody(node); + // If the class does not contain nodes that require a synthesized constructor, + // accept the current constructor if it exists. if (!hasInstancePropertyWithInitializer && !hasParameterPropertyAssignments) { return ts.visitEachChild(constructor, visitor, context); } var parameters = transformConstructorParameters(constructor); var body = transformConstructorBody(node, constructor, isDerivedClass); - return ts.startOnNewLine(ts.setOriginalNode(ts.setTextRange(ts.createConstructor(undefined, undefined, parameters, body), constructor || node), constructor)); + // constructor(${parameters}) { + // ${body} + // } + return ts.startOnNewLine(ts.setOriginalNode(ts.setTextRange(ts.createConstructor( + /*decorators*/ undefined, + /*modifiers*/ undefined, parameters, body), constructor || node), constructor)); } + /** + * Transforms (or creates) the parameters for the constructor of a class with + * parameter property assignments or instance property initializers. + * + * @param constructor The constructor declaration. + */ function transformConstructorParameters(constructor) { + // The ES2015 spec specifies in 14.5.14. Runtime Semantics: ClassDefinitionEvaluation: + // If constructor is empty, then + // If ClassHeritag_eopt is present and protoParent is not null, then + // Let constructor be the result of parsing the source text + // constructor(...args) { super (...args);} + // using the syntactic grammar with the goal symbol MethodDefinition[~Yield]. + // Else, + // Let constructor be the result of parsing the source text + // constructor( ){ } + // using the syntactic grammar with the goal symbol MethodDefinition[~Yield]. + // + // While we could emit the '...args' rest parameter, certain later tools in the pipeline might + // downlevel the '...args' portion less efficiently by naively copying the contents of 'arguments' to an array. + // Instead, we'll avoid using a rest parameter and spread into the super call as + // 'super(...arguments)' instead of 'super(...args)', as you can see in "transformConstructorBody". return ts.visitParameterList(constructor && constructor.parameters, visitor, context) || []; } + /** + * Transforms (or creates) a constructor body for a class with parameter property + * assignments or instance property initializers. + * + * @param node The current class. + * @param constructor The current class constructor. + * @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'. + */ function transformConstructorBody(node, constructor, isDerivedClass) { var statements = []; var indexOfFirstStatement = 0; resumeLexicalEnvironment(); if (constructor) { indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements); + // Add parameters with property assignments. Transforms this: + // + // constructor (public x, public y) { + // } + // + // Into this: + // + // constructor (x, y) { + // this.x = x; + // this.y = y; + // } + // var propertyAssignments = getParametersWithPropertyAssignments(constructor); ts.addRange(statements, ts.map(propertyAssignments, transformParameterWithPropertyAssignment)); } else if (isDerivedClass) { - statements.push(ts.createStatement(ts.createCall(ts.createSuper(), undefined, [ts.createSpread(ts.createIdentifier("arguments"))]))); + // Add a synthetic `super` call: + // + // super(...arguments); + // + statements.push(ts.createStatement(ts.createCall(ts.createSuper(), + /*typeArguments*/ undefined, [ts.createSpread(ts.createIdentifier("arguments"))]))); } - var properties = getInitializedProperties(node, false); + // Add the property initializers. Transforms this: + // + // public x = 1; + // + // Into this: + // + // constructor() { + // this.x = 1; + // } + // + var properties = getInitializedProperties(node, /*isStatic*/ false); addInitializedPropertyStatements(statements, properties, ts.createThis()); if (constructor) { + // The class already had a constructor, so we should add the existing statements, skipping the initial super call. ts.addRange(statements, ts.visitNodes(constructor.body.statements, visitor, ts.isStatement, indexOfFirstStatement)); } + // End the lexical environment. statements = ts.mergeLexicalEnvironment(statements, endLexicalEnvironment()); - return ts.setTextRange(ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), constructor ? constructor.body.statements : node.members), true), constructor ? constructor.body : undefined); + return ts.setTextRange(ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), + /*location*/ constructor ? constructor.body.statements : node.members), + /*multiLine*/ true), + /*location*/ constructor ? constructor.body : undefined); } + /** + * Adds super call and preceding prologue directives into the list of statements. + * + * @param ctor The constructor node. + * @returns index of the statement that follows super call + */ function addPrologueDirectivesAndInitialSuperCall(ctor, result) { if (ctor.body) { var statements = ctor.body.statements; - var index = ts.addPrologue(result, statements, false, visitor); + // add prologue directives to the list (if any) + var index = ts.addPrologue(result, statements, /*ensureUseStrict*/ false, visitor); if (index === statements.length) { + // list contains nothing but prologue directives (or empty) - exit return index; } var statement = statements[index]; - if (statement.kind === 216 && ts.isSuperCall(statement.expression)) { + if (statement.kind === 216 /* ExpressionStatement */ && ts.isSuperCall(statement.expression)) { result.push(ts.visitNode(statement, visitor, ts.isStatement)); return index + 1; } @@ -53379,36 +62416,79 @@ var ts; } return 0; } + /** + * Gets all parameters of a constructor that should be transformed into property assignments. + * + * @param node The constructor node. + */ function getParametersWithPropertyAssignments(node) { return ts.filter(node.parameters, isParameterWithPropertyAssignment); } + /** + * Determines whether a parameter should be transformed into a property assignment. + * + * @param parameter The parameter node. + */ function isParameterWithPropertyAssignment(parameter) { - return ts.hasModifier(parameter, 92) + return ts.hasModifier(parameter, 92 /* ParameterPropertyModifier */) && ts.isIdentifier(parameter.name); } + /** + * Transforms a parameter into a property assignment statement. + * + * @param node The parameter declaration. + */ function transformParameterWithPropertyAssignment(node) { ts.Debug.assert(ts.isIdentifier(node.name)); var name = node.name; var propertyName = ts.getMutableClone(name); - ts.setEmitFlags(propertyName, 1536 | 48); + ts.setEmitFlags(propertyName, 1536 /* NoComments */ | 48 /* NoSourceMap */); var localName = ts.getMutableClone(name); - ts.setEmitFlags(localName, 1536); - return ts.startOnNewLine(ts.setEmitFlags(ts.setTextRange(ts.createStatement(ts.createAssignment(ts.setTextRange(ts.createPropertyAccess(ts.createThis(), propertyName), node.name), localName)), ts.moveRangePos(node, -1)), 1536)); + ts.setEmitFlags(localName, 1536 /* NoComments */); + return ts.startOnNewLine(ts.setEmitFlags(ts.setTextRange(ts.createStatement(ts.createAssignment(ts.setTextRange(ts.createPropertyAccess(ts.createThis(), propertyName), node.name), localName)), ts.moveRangePos(node, -1)), 1536 /* NoComments */)); } + /** + * Gets all property declarations with initializers on either the static or instance side of a class. + * + * @param node The class node. + * @param isStatic A value indicating whether to get properties from the static or instance side of the class. + */ function getInitializedProperties(node, isStatic) { return ts.filter(node.members, isStatic ? isStaticInitializedProperty : isInstanceInitializedProperty); } + /** + * Gets a value indicating whether a class element is a static property declaration with an initializer. + * + * @param member The class element node. + */ function isStaticInitializedProperty(member) { - return isInitializedProperty(member, true); + return isInitializedProperty(member, /*isStatic*/ true); } + /** + * Gets a value indicating whether a class element is an instance property declaration with an initializer. + * + * @param member The class element node. + */ function isInstanceInitializedProperty(member) { - return isInitializedProperty(member, false); + return isInitializedProperty(member, /*isStatic*/ false); } + /** + * Gets a value indicating whether a class element is either a static or an instance property declaration with an initializer. + * + * @param member The class element node. + * @param isStatic A value indicating whether the member should be a static or instance member. + */ function isInitializedProperty(member, isStatic) { - return member.kind === 152 - && isStatic === ts.hasModifier(member, 32) + return member.kind === 152 /* PropertyDeclaration */ + && isStatic === ts.hasModifier(member, 32 /* Static */) && member.initializer !== undefined; } + /** + * Generates assignment statements for property initializers. + * + * @param properties An array of property declarations to transform. + * @param receiver The receiver on which each property should be assigned. + */ function addInitializedPropertyStatements(statements, properties, receiver) { for (var _i = 0, properties_10 = properties; _i < properties_10.length; _i++) { var property = properties_10[_i]; @@ -53418,6 +62498,12 @@ var ts; statements.push(statement); } } + /** + * Generates assignment expressions for property initializers. + * + * @param properties An array of property declarations to transform. + * @param receiver The receiver on which each property should be assigned. + */ function generateInitializedPropertyExpressions(properties, receiver) { var expressions = []; for (var _i = 0, properties_11 = properties; _i < properties_11.length; _i++) { @@ -53430,27 +62516,66 @@ var ts; } return expressions; } + /** + * Transforms a property initializer into an assignment statement. + * + * @param property The property declaration. + * @param receiver The object receiving the property assignment. + */ function transformInitializedProperty(property, receiver) { + // We generate a name here in order to reuse the value cached by the relocated computed name expression (which uses the same generated name) var propertyName = ts.isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression) ? ts.updateComputedPropertyName(property.name, ts.getGeneratedNameForNode(property.name)) : property.name; var initializer = ts.visitNode(property.initializer, visitor, ts.isExpression); - var memberAccess = ts.createMemberAccessForPropertyName(receiver, propertyName, propertyName); + var memberAccess = ts.createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName); return ts.createAssignment(memberAccess, initializer); } + /** + * Gets either the static or instance members of a class that are decorated, or have + * parameters that are decorated. + * + * @param node The class containing the member. + * @param isStatic A value indicating whether to retrieve static or instance members of + * the class. + */ function getDecoratedClassElements(node, isStatic) { return ts.filter(node.members, isStatic ? function (m) { return isStaticDecoratedClassElement(m, node); } : function (m) { return isInstanceDecoratedClassElement(m, node); }); } + /** + * Determines whether a class member is a static member of a class that is decorated, or + * has parameters that are decorated. + * + * @param member The class member. + */ function isStaticDecoratedClassElement(member, parent) { - return isDecoratedClassElement(member, true, parent); + return isDecoratedClassElement(member, /*isStatic*/ true, parent); } + /** + * Determines whether a class member is an instance member of a class that is decorated, + * or has parameters that are decorated. + * + * @param member The class member. + */ function isInstanceDecoratedClassElement(member, parent) { - return isDecoratedClassElement(member, false, parent); + return isDecoratedClassElement(member, /*isStatic*/ false, parent); } + /** + * Determines whether a class member is either a static or an instance member of a class + * that is decorated, or has parameters that are decorated. + * + * @param member The class member. + */ function isDecoratedClassElement(member, isStatic, parent) { return ts.nodeOrChildIsDecorated(member, parent) - && isStatic === ts.hasModifier(member, 32); + && isStatic === ts.hasModifier(member, 32 /* Static */); } + /** + * Gets an array of arrays of decorators for the parameters of a function-like node. + * The offset into the result array should correspond to the offset of the parameter. + * + * @param node The function-like node. + */ function getDecoratorsOfParameters(node) { var decorators; if (node) { @@ -53467,6 +62592,12 @@ var ts; } return decorators; } + /** + * Gets an AllDecorators object containing the decorators for the class and the decorators for the + * parameters of the constructor of the class. + * + * @param node The class node. + */ function getAllDecoratorsOfConstructor(node) { var decorators = node.decorators; var parameters = getDecoratorsOfParameters(ts.getFirstConstructorWithBody(node)); @@ -53478,19 +62609,31 @@ var ts; parameters: parameters }; } + /** + * Gets an AllDecorators object containing the decorators for the member and its parameters. + * + * @param node The class node that contains the member. + * @param member The class member. + */ function getAllDecoratorsOfClassElement(node, member) { switch (member.kind) { - case 156: - case 157: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return getAllDecoratorsOfAccessors(node, member); - case 154: + case 154 /* MethodDeclaration */: return getAllDecoratorsOfMethod(member); - case 152: + case 152 /* PropertyDeclaration */: return getAllDecoratorsOfProperty(member); default: return undefined; } } + /** + * Gets an AllDecorators object containing the decorators for the accessor and its parameters. + * + * @param node The class node that contains the accessor. + * @param accessor The class accessor member. + */ function getAllDecoratorsOfAccessors(node, accessor) { if (!accessor.body) { return undefined; @@ -53507,6 +62650,11 @@ var ts; } return { decorators: decorators, parameters: parameters }; } + /** + * Gets an AllDecorators object containing the decorators for the method and its parameters. + * + * @param method The class method member. + */ function getAllDecoratorsOfMethod(method) { if (!method.body) { return undefined; @@ -53518,6 +62666,11 @@ var ts; } return { decorators: decorators, parameters: parameters }; } + /** + * Gets an AllDecorators object containing the decorators for the property. + * + * @param property The class property member. + */ function getAllDecoratorsOfProperty(property) { var decorators = property.decorators; if (!decorators) { @@ -53525,6 +62678,12 @@ var ts; } return { decorators: decorators }; } + /** + * Transforms all of the decorators for a declaration into an array of expressions. + * + * @param node The declaration node. + * @param allDecorators An object containing all of the decorators for the declaration. + */ function transformAllDecoratorsOfDeclaration(node, container, allDecorators) { if (!allDecorators) { return undefined; @@ -53535,9 +62694,25 @@ var ts; addTypeMetadata(node, container, decoratorExpressions); return decoratorExpressions; } + /** + * Generates statements used to apply decorators to either the static or instance members + * of a class. + * + * @param node The class node. + * @param isStatic A value indicating whether to generate statements for static or + * instance members. + */ function addClassElementDecorationStatements(statements, node, isStatic) { ts.addRange(statements, ts.map(generateClassElementDecorationExpressions(node, isStatic), expressionToStatement)); } + /** + * Generates expressions used to apply decorators to either the static or instance members + * of a class. + * + * @param node The class node. + * @param isStatic A value indicating whether to generate expressions for static or + * instance members. + */ function generateClassElementDecorationExpressions(node, isStatic) { var members = getDecoratedClassElements(node, isStatic); var expressions; @@ -53555,29 +62730,79 @@ var ts; } return expressions; } + /** + * Generates an expression used to evaluate class element decorators at runtime. + * + * @param node The class node that contains the member. + * @param member The class member. + */ function generateClassElementDecorationExpression(node, member) { var allDecorators = getAllDecoratorsOfClassElement(node, member); var decoratorExpressions = transformAllDecoratorsOfDeclaration(member, node, allDecorators); if (!decoratorExpressions) { return undefined; } + // 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: + // + // __decorate([ + // dec, + // __param(0, dec2), + // __metadata("design:type", Function), + // __metadata("design:paramtypes", [Object]), + // __metadata("design:returntype", void 0) + // ], C.prototype, "method", null); + // + // The emit for an accessor is: + // + // __decorate([ + // dec + // ], C.prototype, "accessor", null); + // + // The emit for a property is: + // + // __decorate([ + // dec + // ], C.prototype, "prop"); + // var prefix = getClassMemberPrefix(node, member); - var memberName = getExpressionForPropertyName(member, true); - var descriptor = languageVersion > 0 - ? member.kind === 152 + var memberName = getExpressionForPropertyName(member, /*generateNameForComputedPropertyName*/ true); + var descriptor = languageVersion > 0 /* ES3 */ + ? member.kind === 152 /* PropertyDeclaration */ + // We emit `void 0` here to indicate to `__decorate` that it can invoke `Object.defineProperty` directly, but that it + // should not invoke `Object.getOwnPropertyDescriptor`. ? ts.createVoidZero() + // We emit `null` here to indicate to `__decorate` that it can invoke `Object.getOwnPropertyDescriptor` directly. + // We have this extra argument here so that we can inject an explicit property descriptor at a later date. : ts.createNull() : undefined; var helper = createDecorateHelper(context, decoratorExpressions, prefix, memberName, descriptor, ts.moveRangePastDecorators(member)); - ts.setEmitFlags(helper, 1536); + ts.setEmitFlags(helper, 1536 /* NoComments */); return helper; } + /** + * Generates a __decorate helper call for a class constructor. + * + * @param node The class node. + */ function addConstructorDecorationStatement(statements, node) { var expression = generateConstructorDecorationExpression(node); if (expression) { statements.push(ts.setOriginalNode(ts.createStatement(expression), node)); } } + /** + * Generates a __decorate helper call for a class constructor. + * + * @param node The class node. + */ function generateConstructorDecorationExpression(node) { var allDecorators = getAllDecoratorsOfConstructor(node); var decoratorExpressions = transformAllDecoratorsOfDeclaration(node, node, allDecorators); @@ -53585,29 +62810,47 @@ var ts; return undefined; } var classAlias = classAliases && classAliases[ts.getOriginalNodeId(node)]; - var localName = ts.getLocalName(node, false, true); + var localName = ts.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); var decorate = createDecorateHelper(context, decoratorExpressions, localName); var expression = ts.createAssignment(localName, classAlias ? ts.createAssignment(classAlias, decorate) : decorate); - ts.setEmitFlags(expression, 1536); + ts.setEmitFlags(expression, 1536 /* NoComments */); ts.setSourceMapRange(expression, ts.moveRangePastDecorators(node)); return expression; } + /** + * Transforms a decorator into an expression. + * + * @param decorator The decorator node. + */ function transformDecorator(decorator) { return ts.visitNode(decorator.expression, visitor, ts.isExpression); } + /** + * Transforms the decorators of a parameter. + * + * @param decorators The decorators for the parameter at the provided offset. + * @param parameterOffset The offset of the parameter. + */ function transformDecoratorsOfParameter(decorators, parameterOffset) { var expressions; if (decorators) { expressions = []; for (var _i = 0, decorators_1 = decorators; _i < decorators_1.length; _i++) { var decorator = decorators_1[_i]; - var helper = createParamHelper(context, transformDecorator(decorator), parameterOffset, decorator.expression); - ts.setEmitFlags(helper, 1536); + var helper = createParamHelper(context, transformDecorator(decorator), parameterOffset, + /*location*/ decorator.expression); + ts.setEmitFlags(helper, 1536 /* NoComments */); expressions.push(helper); } } return expressions; } + /** + * Adds optional type metadata for a declaration. + * + * @param node The declaration node. + * @param decoratorExpressions The destination array to which to add new decorator expressions. + */ function addTypeMetadata(node, container, decoratorExpressions) { if (USE_NEW_TYPE_METADATA_FORMAT) { addNewTypeMetadata(node, container, decoratorExpressions); @@ -53633,57 +62876,88 @@ var ts; if (compilerOptions.emitDecoratorMetadata) { var properties = void 0; if (shouldAddTypeMetadata(node)) { - (properties || (properties = [])).push(ts.createPropertyAssignment("type", ts.createArrowFunction(undefined, undefined, [], undefined, ts.createToken(36), serializeTypeOfNode(node)))); + (properties || (properties = [])).push(ts.createPropertyAssignment("type", ts.createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, ts.createToken(36 /* EqualsGreaterThanToken */), serializeTypeOfNode(node)))); } if (shouldAddParamTypesMetadata(node)) { - (properties || (properties = [])).push(ts.createPropertyAssignment("paramTypes", ts.createArrowFunction(undefined, undefined, [], undefined, ts.createToken(36), serializeParameterTypesOfNode(node, container)))); + (properties || (properties = [])).push(ts.createPropertyAssignment("paramTypes", ts.createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, ts.createToken(36 /* EqualsGreaterThanToken */), serializeParameterTypesOfNode(node, container)))); } if (shouldAddReturnTypeMetadata(node)) { - (properties || (properties = [])).push(ts.createPropertyAssignment("returnType", ts.createArrowFunction(undefined, undefined, [], undefined, ts.createToken(36), serializeReturnTypeOfNode(node)))); + (properties || (properties = [])).push(ts.createPropertyAssignment("returnType", ts.createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, ts.createToken(36 /* EqualsGreaterThanToken */), serializeReturnTypeOfNode(node)))); } if (properties) { - decoratorExpressions.push(createMetadataHelper(context, "design:typeinfo", ts.createObjectLiteral(properties, true))); + decoratorExpressions.push(createMetadataHelper(context, "design:typeinfo", ts.createObjectLiteral(properties, /*multiLine*/ true))); } } } + /** + * 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. + * + * @param node The node to test. + */ function shouldAddTypeMetadata(node) { var kind = node.kind; - return kind === 154 - || kind === 156 - || kind === 157 - || kind === 152; + return kind === 154 /* MethodDeclaration */ + || kind === 156 /* GetAccessor */ + || kind === 157 /* SetAccessor */ + || kind === 152 /* PropertyDeclaration */; } + /** + * 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. + * + * @param node The node to test. + */ function shouldAddReturnTypeMetadata(node) { - return node.kind === 154; + return node.kind === 154 /* MethodDeclaration */; } + /** + * 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. + * + * @param node The node to test. + */ function shouldAddParamTypesMetadata(node) { switch (node.kind) { - case 235: - case 205: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: return ts.getFirstConstructorWithBody(node) !== undefined; - case 154: - case 156: - case 157: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return true; } return false; } + /** + * Serializes the type of a node for use with decorator type metadata. + * + * @param node The node that should have its type serialized. + */ function serializeTypeOfNode(node) { switch (node.kind) { - case 152: - case 149: - case 156: + case 152 /* PropertyDeclaration */: + case 149 /* Parameter */: + case 156 /* GetAccessor */: return serializeTypeNode(node.type); - case 157: + case 157 /* SetAccessor */: return serializeTypeNode(ts.getSetAccessorTypeAnnotationNode(node)); - case 235: - case 205: - case 154: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 154 /* MethodDeclaration */: return ts.createIdentifier("Function"); default: return ts.createVoidZero(); } } + /** + * Serializes the types of the parameters of a node for use with decorator type metadata. + * + * @param node The node that should have its parameter types serialized. + */ function serializeParameterTypesOfNode(node, container) { var valueDeclaration = ts.isClassLike(node) ? ts.getFirstConstructorWithBody(node) @@ -53710,7 +62984,7 @@ var ts; return ts.createArrayLiteral(expressions); } function getParametersOfDecoratedDeclaration(node, container) { - if (container && node.kind === 156) { + if (container && node.kind === 156 /* GetAccessor */) { var setAccessor = ts.getAllAccessorDeclarations(container.members, node).setAccessor; if (setAccessor) { return setAccessor.parameters; @@ -53718,6 +62992,11 @@ var ts; } return node.parameters; } + /** + * Serializes the return type of a node for use with decorator type metadata. + * + * @param node The node that should have its return type serialized. + */ function serializeReturnTypeOfNode(node) { if (ts.isFunctionLike(node) && node.type) { return serializeTypeNode(node.type); @@ -53727,63 +63006,81 @@ var ts; } return ts.createVoidZero(); } + /** + * Serializes a type node for use with decorator type metadata. + * + * Types are serialized in the following fashion: + * - Void types point to "undefined" (e.g. "void 0") + * - Function and Constructor types point to the global "Function" constructor. + * - Interface types with a call or construct signature types point to the global + * "Function" constructor. + * - Array and Tuple types point to the global "Array" constructor. + * - Type predicates and booleans point to the global "Boolean" constructor. + * - String literal types and strings point to the global "String" constructor. + * - Enum and number types point to the global "Number" constructor. + * - Symbol types point to the global "Symbol" constructor. + * - Type references to classes (or class-like variables) point to the constructor for the class. + * - Anything else points to the global "Object" constructor. + * + * @param node The type node to serialize. + */ function serializeTypeNode(node) { if (node === undefined) { return ts.createIdentifier("Object"); } switch (node.kind) { - case 105: - case 140: - case 95: - case 131: + case 105 /* VoidKeyword */: + case 140 /* UndefinedKeyword */: + case 95 /* NullKeyword */: + case 131 /* NeverKeyword */: return ts.createVoidZero(); - case 173: + case 173 /* ParenthesizedType */: return serializeTypeNode(node.type); - case 163: - case 164: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: return ts.createIdentifier("Function"); - case 167: - case 168: + case 167 /* ArrayType */: + case 168 /* TupleType */: return ts.createIdentifier("Array"); - case 161: - case 122: + case 161 /* TypePredicate */: + case 122 /* BooleanKeyword */: return ts.createIdentifier("Boolean"); - case 137: + case 137 /* StringKeyword */: return ts.createIdentifier("String"); - case 135: + case 135 /* ObjectKeyword */: return ts.createIdentifier("Object"); - case 178: + case 178 /* LiteralType */: switch (node.literal.kind) { - case 9: + case 9 /* StringLiteral */: return ts.createIdentifier("String"); - case 8: + case 8 /* NumericLiteral */: return ts.createIdentifier("Number"); - case 101: - case 86: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: return ts.createIdentifier("Boolean"); default: return ts.Debug.failBadSyntaxKind(node.literal); } - case 134: + case 134 /* NumberKeyword */: return ts.createIdentifier("Number"); - case 138: - return languageVersion < 2 + case 138 /* SymbolKeyword */: + return languageVersion < 2 /* ES2015 */ ? getGlobalSymbolNameWithFallback() : ts.createIdentifier("Symbol"); - case 162: + case 162 /* TypeReference */: return serializeTypeReferenceNode(node); - case 170: - case 169: + case 170 /* IntersectionType */: + case 169 /* UnionType */: return serializeUnionOrIntersectionType(node); - case 165: - case 175: - case 176: - case 177: - case 166: - case 119: - case 142: - case 174: - case 179: + case 165 /* TypeQuery */: + case 175 /* TypeOperator */: + case 176 /* IndexedAccessType */: + case 177 /* MappedType */: + case 166 /* TypeLiteral */: + case 119 /* AnyKeyword */: + case 142 /* UnknownKeyword */: + case 174 /* ThisType */: + case 179 /* ImportType */: break; default: return ts.Debug.failBadSyntaxKind(node); @@ -53791,23 +63088,29 @@ var ts; return ts.createIdentifier("Object"); } function serializeUnionOrIntersectionType(node) { + // Note when updating logic here also update getEntityNameForDecoratorMetadata + // so that aliases can be marked as referenced var serializedUnion; for (var _i = 0, _a = node.types; _i < _a.length; _i++) { var typeNode = _a[_i]; - while (typeNode.kind === 173) { - typeNode = typeNode.type; + while (typeNode.kind === 173 /* ParenthesizedType */) { + typeNode = typeNode.type; // Skip parens if need be } - if (typeNode.kind === 131) { - continue; + if (typeNode.kind === 131 /* NeverKeyword */) { + continue; // Always elide `never` from the union/intersection if possible } - if (!strictNullChecks && (typeNode.kind === 95 || typeNode.kind === 140)) { - continue; + if (!strictNullChecks && (typeNode.kind === 95 /* NullKeyword */ || typeNode.kind === 140 /* UndefinedKeyword */)) { + continue; // Elide null and undefined from unions for metadata, just like what we did prior to the implementation of strict null checks } var serializedIndividual = serializeTypeNode(typeNode); if (ts.isIdentifier(serializedIndividual) && serializedIndividual.escapedText === "Object") { + // One of the individual is global object, return immediately return serializedIndividual; } + // If there exists union that is not void 0 expression, check if the the common type is identifier. + // anything more complex and we will just default to Object else if (serializedUnion) { + // Different types if (!ts.isIdentifier(serializedUnion) || !ts.isIdentifier(serializedIndividual) || serializedUnion.escapedText !== serializedIndividual.escapedText) { @@ -53815,20 +63118,28 @@ var ts; } } else { + // Initialize the union type serializedUnion = serializedIndividual; } } - return serializedUnion || ts.createVoidZero(); + // If we were able to find common type, use it + return serializedUnion || ts.createVoidZero(); // Fallback is only hit if all union constituients are null/undefined/never } + /** + * Serializes a TypeReferenceNode to an appropriate JS constructor value for use with + * decorator type metadata. + * + * @param node The type reference node. + */ function serializeTypeReferenceNode(node) { var kind = resolver.getTypeReferenceSerializationKind(node.typeName, currentScope); switch (kind) { case ts.TypeReferenceSerializationKind.Unknown: - var serialized = serializeEntityNameAsExpression(node.typeName, true); + var serialized = serializeEntityNameAsExpression(node.typeName, /*useFallback*/ true); var temp = ts.createTempVariable(hoistVariableDeclaration); return ts.createLogicalOr(ts.createLogicalAnd(ts.createTypeCheck(ts.createAssignment(temp, serialized), "function"), temp), ts.createIdentifier("Object")); case ts.TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue: - return serializeEntityNameAsExpression(node.typeName, false); + return serializeEntityNameAsExpression(node.typeName, /*useFallback*/ false); case ts.TypeReferenceSerializationKind.VoidNullableOrNeverType: return ts.createVoidZero(); case ts.TypeReferenceSerializationKind.BooleanType: @@ -53840,7 +63151,7 @@ var ts; case ts.TypeReferenceSerializationKind.ArrayLikeType: return ts.createIdentifier("Array"); case ts.TypeReferenceSerializationKind.ESSymbolType: - return languageVersion < 2 + return languageVersion < 2 /* ES2015 */ ? getGlobalSymbolNameWithFallback() : ts.createIdentifier("Symbol"); case ts.TypeReferenceSerializationKind.TypeWithCallSignature: @@ -53853,42 +63164,73 @@ var ts; return ts.Debug.assertNever(kind); } } + /** + * Serializes an entity name as an expression for decorator type metadata. + * + * @param node The entity name to serialize. + * @param useFallback A value indicating whether to use logical operators to test for the + * entity name at runtime. + */ function serializeEntityNameAsExpression(node, useFallback) { switch (node.kind) { - case 71: + case 71 /* Identifier */: + // Create a clone of the name with a new parent, and treat it as if it were + // a source tree node for the purposes of the checker. var name = ts.getMutableClone(node); - name.flags &= ~8; + name.flags &= ~8 /* Synthesized */; name.original = undefined; - name.parent = ts.getParseTreeNode(currentScope); + name.parent = ts.getParseTreeNode(currentScope); // ensure the parent is set to a parse tree node. if (useFallback) { return ts.createLogicalAnd(ts.createStrictInequality(ts.createTypeOf(name), ts.createLiteral("undefined")), name); } return name; - case 146: + case 146 /* QualifiedName */: return serializeQualifiedNameAsExpression(node, useFallback); } } + /** + * Serializes an qualified name as an expression for decorator type metadata. + * + * @param node The qualified name to serialize. + * @param useFallback A value indicating whether to use logical operators to test for the + * qualified name at runtime. + */ function serializeQualifiedNameAsExpression(node, useFallback) { var left; - if (node.left.kind === 71) { + if (node.left.kind === 71 /* Identifier */) { left = serializeEntityNameAsExpression(node.left, useFallback); } else if (useFallback) { var temp = ts.createTempVariable(hoistVariableDeclaration); - left = ts.createLogicalAnd(ts.createAssignment(temp, serializeEntityNameAsExpression(node.left, true)), temp); + left = ts.createLogicalAnd(ts.createAssignment(temp, serializeEntityNameAsExpression(node.left, /*useFallback*/ true)), temp); } else { - left = serializeEntityNameAsExpression(node.left, false); + left = serializeEntityNameAsExpression(node.left, /*useFallback*/ false); } return ts.createPropertyAccess(left, node.right); } + /** + * Gets an expression that points to the global "Symbol" constructor at runtime if it is + * available. + */ function getGlobalSymbolNameWithFallback() { return ts.createConditional(ts.createTypeCheck(ts.createIdentifier("Symbol"), "function"), ts.createIdentifier("Symbol"), ts.createIdentifier("Object")); } + /** + * A simple inlinable expression is an expression which can be copied into multiple locations + * without risk of repeating any sideeffects and whose value could not possibly change between + * any such locations + */ function isSimpleInlineableExpression(expression) { return !ts.isIdentifier(expression) && ts.isSimpleCopiableExpression(expression) || ts.isWellKnownSymbolSyntactically(expression); } + /** + * Gets an expression that represents a property name. For a computed property, a + * name is generated for the node. + * + * @param member The member whose name should be converted into an expression. + */ function getExpressionForPropertyName(member, generateNameForComputedPropertyName) { var name = member.name; if (ts.isComputedPropertyName(name)) { @@ -53903,6 +63245,12 @@ var ts; return ts.getSynthesizedClone(name); } } + /** + * If the name is a computed property, this function transforms it, then either returns an expression which caches the + * value of the result or the expression itself if the value is either unused or safe to inline into multiple locations + * @param shouldHoist Does the expression need to be reused? (ie, for an initializer or a decorator) + * @param omitSimple Should expressions with no observable side-effects be elided? (ie, the expression is not hoisted for a decorator or initializer and is a literal) + */ function getPropertyNameExpressionIfNeeded(name, shouldHoist, omitSimple) { if (ts.isComputedPropertyName(name)) { var expression = ts.visitNode(name.expression, visitor, ts.isExpression); @@ -53916,10 +63264,18 @@ var ts; return (omitSimple && (inlinable || ts.isIdentifier(innerExpression))) ? undefined : expression; } } + /** + * Visits the property name of a class element, for use when emitting property + * initializers. For a computed property on a node with decorators, a temporary + * value is stored for later use. + * + * @param member The member whose name should be visited. + */ function visitPropertyNameOfClassElement(member) { var name = member.name; - var expr = getPropertyNameExpressionIfNeeded(name, ts.some(member.decorators), false); - if (expr) { + var expr = getPropertyNameExpressionIfNeeded(name, ts.some(member.decorators), /*omitSimple*/ false); + if (expr) { // expr only exists if `name` is a computed property name + // Inline any pending expressions from previous elided or relocated computed property name expressions in order to preserve execution order if (ts.some(pendingExpressions)) { expr = ts.inlineExpressions(pendingExpressions.concat([expr])); pendingExpressions.length = 0; @@ -53930,21 +63286,45 @@ var ts; return name; } } + /** + * Transforms a HeritageClause with TypeScript syntax. + * + * 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 that should be visited, but only allow a single type. + * + * @param node The HeritageClause to transform. + */ function visitHeritageClause(node) { - if (node.token === 85) { + if (node.token === 85 /* ExtendsKeyword */) { var types = ts.visitNodes(node.types, visitor, ts.isExpressionWithTypeArguments, 0, 1); - return ts.setTextRange(ts.createHeritageClause(85, types), node); + return ts.setTextRange(ts.createHeritageClause(85 /* ExtendsKeyword */, types), node); } return undefined; } + /** + * Transforms an ExpressionWithTypeArguments with TypeScript syntax. + * + * This function will only be called when one of the following conditions are met: + * - The node contains type arguments that should be elided. + * + * @param node The ExpressionWithTypeArguments to transform. + */ function visitExpressionWithTypeArguments(node) { - return ts.updateExpressionWithTypeArguments(node, undefined, ts.visitNode(node.expression, visitor, ts.isLeftHandSideExpression)); + return ts.updateExpressionWithTypeArguments(node, + /*typeArguments*/ undefined, ts.visitNode(node.expression, visitor, ts.isLeftHandSideExpression)); } + /** + * Determines whether to emit a function-like declaration. We should not emit the + * declaration if it does not have a body. + * + * @param node The declaration node. + */ function shouldEmitFunctionLikeDeclaration(node) { return !ts.nodeIsMissing(node.body); } function visitPropertyDeclaration(node) { - var expr = getPropertyNameExpressionIfNeeded(node.name, ts.some(node.decorators) || !!node.initializer, true); + var expr = getPropertyNameExpressionIfNeeded(node.name, ts.some(node.decorators) || !!node.initializer, /*omitSimple*/ true); if (expr && !isSimpleInlineableExpression(expr)) { (pendingExpressions || (pendingExpressions = [])).push(expr); } @@ -53956,47 +63336,107 @@ var ts; } return ts.updateConstructor(node, ts.visitNodes(node.decorators, visitor, ts.isDecorator), ts.visitNodes(node.modifiers, visitor, ts.isModifier), ts.visitParameterList(node.parameters, visitor, context), ts.visitFunctionBody(node.body, visitor, context)); } + /** + * Visits a method declaration of a class. + * + * This function will be called when one of the following conditions are met: + * - The node is an overload + * - The node is marked as abstract, public, private, protected, or readonly + * - The node has a computed property name + * + * @param node The method node. + */ function visitMethodDeclaration(node) { if (!shouldEmitFunctionLikeDeclaration(node)) { return undefined; } - var updated = ts.updateMethod(node, undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), node.asteriskToken, visitPropertyNameOfClassElement(node), undefined, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, ts.visitFunctionBody(node.body, visitor, context)); + var updated = ts.updateMethod(node, + /*decorators*/ undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), node.asteriskToken, visitPropertyNameOfClassElement(node), + /*questionToken*/ undefined, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, ts.visitFunctionBody(node.body, visitor, context)); if (updated !== node) { + // While we emit the source map for the node after skipping decorators and modifiers, + // we need to emit the comments for the original range. ts.setCommentRange(updated, node); ts.setSourceMapRange(updated, ts.moveRangePastDecorators(node)); } return updated; } + /** + * Determines whether to emit an accessor declaration. We should not emit the + * declaration if it does not have a body and is abstract. + * + * @param node The declaration node. + */ function shouldEmitAccessorDeclaration(node) { - return !(ts.nodeIsMissing(node.body) && ts.hasModifier(node, 128)); + return !(ts.nodeIsMissing(node.body) && ts.hasModifier(node, 128 /* Abstract */)); } + /** + * Visits a get accessor declaration of a class. + * + * This function will be called when one of the following conditions are met: + * - The node is marked as abstract, public, private, or protected + * - The node has a computed property name + * + * @param node The get accessor node. + */ function visitGetAccessor(node) { if (!shouldEmitAccessorDeclaration(node)) { return undefined; } - var updated = ts.updateGetAccessor(node, undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), visitPropertyNameOfClassElement(node), ts.visitParameterList(node.parameters, visitor, context), undefined, ts.visitFunctionBody(node.body, visitor, context) || ts.createBlock([])); + var updated = ts.updateGetAccessor(node, + /*decorators*/ undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), visitPropertyNameOfClassElement(node), ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, ts.visitFunctionBody(node.body, visitor, context) || ts.createBlock([])); if (updated !== node) { + // While we emit the source map for the node after skipping decorators and modifiers, + // we need to emit the comments for the original range. ts.setCommentRange(updated, node); ts.setSourceMapRange(updated, ts.moveRangePastDecorators(node)); } return updated; } + /** + * Visits a set accessor declaration of a class. + * + * This function will be called when one of the following conditions are met: + * - The node is marked as abstract, public, private, or protected + * - The node has a computed property name + * + * @param node The set accessor node. + */ function visitSetAccessor(node) { if (!shouldEmitAccessorDeclaration(node)) { return undefined; } - var updated = ts.updateSetAccessor(node, undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), visitPropertyNameOfClassElement(node), ts.visitParameterList(node.parameters, visitor, context), ts.visitFunctionBody(node.body, visitor, context) || ts.createBlock([])); + var updated = ts.updateSetAccessor(node, + /*decorators*/ undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), visitPropertyNameOfClassElement(node), ts.visitParameterList(node.parameters, visitor, context), ts.visitFunctionBody(node.body, visitor, context) || ts.createBlock([])); if (updated !== node) { + // While we emit the source map for the node after skipping decorators and modifiers, + // we need to emit the comments for the original range. ts.setCommentRange(updated, node); ts.setSourceMapRange(updated, ts.moveRangePastDecorators(node)); } return updated; } + /** + * Visits a function declaration. + * + * This function will be called when one of the following conditions are met: + * - The node is an overload + * - The node is exported from a TypeScript namespace + * - The node has decorators + * + * @param node The function node. + */ function visitFunctionDeclaration(node) { if (!shouldEmitFunctionLikeDeclaration(node)) { return ts.createNotEmittedStatement(node); } - var updated = ts.updateFunctionDeclaration(node, undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), node.asteriskToken, node.name, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, ts.visitFunctionBody(node.body, visitor, context) || ts.createBlock([])); + var updated = ts.updateFunctionDeclaration(node, + /*decorators*/ undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), node.asteriskToken, node.name, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, ts.visitFunctionBody(node.body, visitor, context) || ts.createBlock([])); if (isExportOfNamespace(node)) { var statements = [updated]; addExportMemberAssignment(statements, node); @@ -54004,33 +63444,73 @@ var ts; } return updated; } + /** + * Visits a function expression node. + * + * This function will be called when one of the following conditions are met: + * - The node has type annotations + * + * @param node The function expression node. + */ function visitFunctionExpression(node) { if (!shouldEmitFunctionLikeDeclaration(node)) { return ts.createOmittedExpression(); } - var updated = ts.updateFunctionExpression(node, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), node.asteriskToken, node.name, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, ts.visitFunctionBody(node.body, visitor, context) || ts.createBlock([])); + var updated = ts.updateFunctionExpression(node, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), node.asteriskToken, node.name, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, ts.visitFunctionBody(node.body, visitor, context) || ts.createBlock([])); return updated; } + /** + * @remarks + * This function will be called when one of the following conditions are met: + * - The node has type annotations + */ function visitArrowFunction(node) { - var updated = ts.updateArrowFunction(node, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, node.equalsGreaterThanToken, ts.visitFunctionBody(node.body, visitor, context)); + var updated = ts.updateArrowFunction(node, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, node.equalsGreaterThanToken, ts.visitFunctionBody(node.body, visitor, context)); return updated; } + /** + * Visits a parameter declaration node. + * + * This function will be called when one of the following conditions are met: + * - The node has an accessibility modifier. + * - The node has a questionToken. + * - The node's kind is ThisKeyword. + * + * @param node The parameter declaration node. + */ function visitParameter(node) { if (ts.parameterIsThisKeyword(node)) { return undefined; } - var parameter = ts.createParameter(undefined, undefined, node.dotDotDotToken, ts.visitNode(node.name, visitor, ts.isBindingName), undefined, undefined, ts.visitNode(node.initializer, visitor, ts.isExpression)); + var parameter = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, node.dotDotDotToken, ts.visitNode(node.name, visitor, ts.isBindingName), + /*questionToken*/ undefined, + /*type*/ undefined, ts.visitNode(node.initializer, visitor, ts.isExpression)); + // While we emit the source map for the node after skipping decorators and modifiers, + // we need to emit the comments for the original range. ts.setOriginalNode(parameter, node); ts.setTextRange(parameter, ts.moveRangePastModifiers(node)); ts.setCommentRange(parameter, node); ts.setSourceMapRange(parameter, ts.moveRangePastModifiers(node)); - ts.setEmitFlags(parameter.name, 32); + ts.setEmitFlags(parameter.name, 32 /* NoTrailingSourceMap */); return parameter; } + /** + * Visits a variable statement in a namespace. + * + * This function will be called when one of the following conditions are met: + * - The node is exported from a TypeScript namespace. + */ function visitVariableStatement(node) { if (isExportOfNamespace(node)) { var variables = ts.getInitializedVariables(node.declarationList); if (variables.length === 0) { + // elide statement if there are no initialized variables. return undefined; } return ts.setTextRange(ts.createStatement(ts.inlineExpressions(ts.map(variables, transformInitializedVariable))), node); @@ -54042,19 +63522,45 @@ var ts; function transformInitializedVariable(node) { var name = node.name; if (ts.isBindingPattern(name)) { - return ts.flattenDestructuringAssignment(node, visitor, context, 0, false, createNamespaceExportExpression); + return ts.flattenDestructuringAssignment(node, visitor, context, 0 /* All */, + /*needsValue*/ false, createNamespaceExportExpression); } else { - return ts.setTextRange(ts.createAssignment(getNamespaceMemberNameWithSourceMapsAndWithoutComments(name), ts.visitNode(node.initializer, visitor, ts.isExpression)), node); + return ts.setTextRange(ts.createAssignment(getNamespaceMemberNameWithSourceMapsAndWithoutComments(name), ts.visitNode(node.initializer, visitor, ts.isExpression)), + /*location*/ node); } } function visitVariableDeclaration(node) { - return ts.updateVariableDeclaration(node, ts.visitNode(node.name, visitor, ts.isBindingName), undefined, ts.visitNode(node.initializer, visitor, ts.isExpression)); + return ts.updateVariableDeclaration(node, ts.visitNode(node.name, visitor, ts.isBindingName), + /*type*/ undefined, ts.visitNode(node.initializer, visitor, ts.isExpression)); } + /** + * Visits a parenthesized expression that contains either a type assertion or an `as` + * expression. + * + * @param node The parenthesized expression node. + */ function visitParenthesizedExpression(node) { - var innerExpression = ts.skipOuterExpressions(node.expression, ~2); + var innerExpression = ts.skipOuterExpressions(node.expression, ~2 /* Assertions */); if (ts.isAssertionExpression(innerExpression)) { + // Make sure we consider all nested cast expressions, e.g.: + // (-A).x; var expression = ts.visitNode(node.expression, visitor, ts.isExpression); + // We have an expression of the form: (SubExpr). Emitting this as (SubExpr) + // is really not desirable. We would like to emit the subexpression as-is. Omitting + // the parentheses, however, could cause change in the semantics of the generated + // code if the casted expression has a lower precedence than the rest of the + // expression. + // + // To preserve comments, we return a "PartiallyEmittedExpression" here which will + // preserve the position information of the original expression. + // + // Due to the auto-parenthesization rules used by the visitor and factory functions + // we can safely elide the parentheses here, as a new synthetic + // ParenthesizedExpression will be inserted if we remove parentheses too + // aggressively. + // HOWEVER - if there are leading comments on the expression itself, to handle ASI + // correctly for return and throw, we must keep the parenthesis if (ts.length(ts.getLeadingCommentRangesOfNode(expression, currentSourceFile))) { return ts.updateParen(node, expression); } @@ -54071,48 +63577,93 @@ var ts; return ts.createPartiallyEmittedExpression(expression, node); } function visitCallExpression(node) { - return ts.updateCall(node, ts.visitNode(node.expression, visitor, ts.isExpression), undefined, ts.visitNodes(node.arguments, visitor, ts.isExpression)); + return ts.updateCall(node, ts.visitNode(node.expression, visitor, ts.isExpression), + /*typeArguments*/ undefined, ts.visitNodes(node.arguments, visitor, ts.isExpression)); } function visitNewExpression(node) { - return ts.updateNew(node, ts.visitNode(node.expression, visitor, ts.isExpression), undefined, ts.visitNodes(node.arguments, visitor, ts.isExpression)); + return ts.updateNew(node, ts.visitNode(node.expression, visitor, ts.isExpression), + /*typeArguments*/ undefined, ts.visitNodes(node.arguments, visitor, ts.isExpression)); } function visitTaggedTemplateExpression(node) { - return ts.updateTaggedTemplate(node, ts.visitNode(node.tag, visitor, ts.isExpression), undefined, ts.visitNode(node.template, visitor, ts.isExpression)); + return ts.updateTaggedTemplate(node, ts.visitNode(node.tag, visitor, ts.isExpression), + /*typeArguments*/ undefined, ts.visitNode(node.template, visitor, ts.isExpression)); } + /** + * Determines whether to emit an enum declaration. + * + * @param node The enum declaration node. + */ function shouldEmitEnumDeclaration(node) { return !ts.isConst(node) || compilerOptions.preserveConstEnums || compilerOptions.isolatedModules; } + /** + * Visits an enum declaration. + * + * This function will be called any time a TypeScript enum is encountered. + * + * @param node The enum declaration node. + */ function visitEnumDeclaration(node) { if (!shouldEmitEnumDeclaration(node)) { return undefined; } var statements = []; - var emitFlags = 2; + // We request to be advised when the printer is about to print this node. This allows + // us to set up the correct state for later substitutions. + var emitFlags = 2 /* AdviseOnEmitNode */; + // If needed, we should emit a variable declaration for the enum. If we emit + // a leading variable declaration, we should not emit leading comments for the + // enum body. if (addVarForEnumOrModuleDeclaration(statements, node)) { + // We should still emit the comments if we are emitting a system module. if (moduleKind !== ts.ModuleKind.System || currentScope !== currentSourceFile) { - emitFlags |= 512; + emitFlags |= 512 /* NoLeadingComments */; } } + // `parameterName` is the declaration name used inside of the enum. var parameterName = getNamespaceParameterName(node); + // `containerName` is the expression used inside of the enum for assignments. var containerName = getNamespaceContainerName(node); - var exportName = ts.hasModifier(node, 1) - ? ts.getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, false, true) - : ts.getLocalName(node, false, true); + // `exportName` is the expression used within this node's container for any exported references. + var exportName = ts.hasModifier(node, 1 /* Export */) + ? ts.getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, /*allowComments*/ false, /*allowSourceMaps*/ true) + : ts.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); + // x || (x = {}) + // exports.x || (exports.x = {}) var moduleArg = ts.createLogicalOr(exportName, ts.createAssignment(exportName, ts.createObjectLiteral())); if (hasNamespaceQualifiedExportName(node)) { - var localName = ts.getLocalName(node, false, true); + // `localName` is the expression used within this node's containing scope for any local references. + var localName = ts.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); + // x = (exports.x || (exports.x = {})) moduleArg = ts.createAssignment(localName, moduleArg); } - var enumStatement = ts.createStatement(ts.createCall(ts.createFunctionExpression(undefined, undefined, undefined, undefined, [ts.createParameter(undefined, undefined, undefined, parameterName)], undefined, transformEnumBody(node, containerName)), undefined, [moduleArg])); + // (function (x) { + // x[x["y"] = 0] = "y"; + // ... + // })(x || (x = {})); + var enumStatement = ts.createStatement(ts.createCall(ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)], + /*type*/ undefined, transformEnumBody(node, containerName)), + /*typeArguments*/ undefined, [moduleArg])); ts.setOriginalNode(enumStatement, node); ts.setTextRange(enumStatement, node); ts.setEmitFlags(enumStatement, emitFlags); statements.push(enumStatement); + // Add a DeclarationMarker for the enum to preserve trailing comments and mark + // the end of the declaration. statements.push(ts.createEndOfDeclarationMarker(node)); return statements; } + /** + * Transforms the body of an enum declaration. + * + * @param node The enum declaration node. + */ function transformEnumBody(node, localName) { var savedCurrentNamespaceLocalName = currentNamespaceContainerName; currentNamespaceContainerName = localName; @@ -54122,17 +63673,31 @@ var ts; ts.prependStatements(statements, endLexicalEnvironment()); ts.addRange(statements, members); currentNamespaceContainerName = savedCurrentNamespaceLocalName; - return ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), node.members), true); + return ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), /*location*/ node.members), + /*multiLine*/ true); } + /** + * Transforms an enum member into a statement. + * + * @param member The enum member node. + */ function transformEnumMember(member) { - var name = getExpressionForPropertyName(member, false); + // enums don't support computed properties + // we pass false as 'generateNameForComputedPropertyName' for a backward compatibility purposes + // old emitter always generate 'expression' part of the name as-is. + var name = getExpressionForPropertyName(member, /*generateNameForComputedPropertyName*/ false); var valueExpression = transformEnumMemberDeclarationValue(member); var innerAssignment = ts.createAssignment(ts.createElementAccess(currentNamespaceContainerName, name), valueExpression); - var outerAssignment = valueExpression.kind === 9 ? + var outerAssignment = valueExpression.kind === 9 /* StringLiteral */ ? innerAssignment : ts.createAssignment(ts.createElementAccess(currentNamespaceContainerName, innerAssignment), name); return ts.setTextRange(ts.createStatement(ts.setTextRange(outerAssignment, member)), member); } + /** + * Transforms the value of an enum member. + * + * @param member The enum member node. + */ function transformEnumMemberDeclarationValue(member) { var value = resolver.getConstantValue(member); if (value !== undefined) { @@ -54148,9 +63713,18 @@ var ts; } } } + /** + * Determines whether to elide a module declaration. + * + * @param node The module declaration node. + */ function shouldEmitModuleDeclaration(node) { return ts.isInstantiatedModule(node, !!compilerOptions.preserveConstEnums || !!compilerOptions.isolatedModules); } + /** + * Determines whether an exported declaration will have a qualified export name (e.g. `f.x` + * or `exports.x`). + */ function hasNamespaceQualifiedExportName(node) { return isExportOfNamespace(node) || (isExternalModuleExport(node) @@ -54158,6 +63732,10 @@ var ts; && moduleKind !== ts.ModuleKind.ESNext && moduleKind !== ts.ModuleKind.System); } + /** + * Records that a declaration was emitted in the current scope, if it was the first + * declaration for the provided symbol. + */ function recordEmittedDeclarationInScope(node) { if (!currentScopeFirstDeclarationsOfName) { currentScopeFirstDeclarationsOfName = ts.createUnderscoreEscapedMap(); @@ -54167,6 +63745,10 @@ var ts; currentScopeFirstDeclarationsOfName.set(name, node); } } + /** + * Determines whether a declaration is the first declaration with + * the same name emitted in the current scope. + */ function isFirstEmittedDeclarationInScope(node) { if (currentScopeFirstDeclarationsOfName) { var name = declaredNameInScope(node); @@ -54178,31 +63760,67 @@ var ts; ts.Debug.assertNode(node.name, ts.isIdentifier); return node.name.escapedText; } + /** + * Adds a leading VariableStatement for a enum or module declaration. + */ function addVarForEnumOrModuleDeclaration(statements, node) { + // Emit a variable statement for the module. We emit top-level enums as a `var` + // declaration to avoid static errors in global scripts scripts due to redeclaration. + // enums in any other scope are emitted as a `let` declaration. var statement = ts.createVariableStatement(ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), ts.createVariableDeclarationList([ - ts.createVariableDeclaration(ts.getLocalName(node, false, true)) - ], currentScope.kind === 274 ? 0 : 1)); + ts.createVariableDeclaration(ts.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true)) + ], currentScope.kind === 274 /* SourceFile */ ? 0 /* None */ : 1 /* Let */)); ts.setOriginalNode(statement, node); recordEmittedDeclarationInScope(node); if (isFirstEmittedDeclarationInScope(node)) { - if (node.kind === 238) { + // Adjust the source map emit to match the old emitter. + if (node.kind === 238 /* EnumDeclaration */) { ts.setSourceMapRange(statement.declarationList, node); } else { ts.setSourceMapRange(statement, node); } + // Trailing comments for module declaration should be emitted after the function closure + // instead of the variable statement: + // + // /** Module comment*/ + // module m1 { + // function foo4Export() { + // } + // } // trailing comment module + // + // Should emit: + // + // /** Module comment*/ + // var m1; + // (function (m1) { + // function foo4Export() { + // } + // })(m1 || (m1 = {})); // trailing comment module + // ts.setCommentRange(statement, node); - ts.setEmitFlags(statement, 1024 | 4194304); + ts.setEmitFlags(statement, 1024 /* NoTrailingComments */ | 4194304 /* HasEndOfDeclarationMarker */); statements.push(statement); return true; } else { + // For an EnumDeclaration or ModuleDeclaration that merges with a preceeding + // declaration we do not emit a leading variable declaration. To preserve the + // begin/end semantics of the declararation and to properly handle exports + // we wrap the leading variable declaration in a `MergeDeclarationMarker`. var mergeMarker = ts.createMergeDeclarationMarker(statement); - ts.setEmitFlags(mergeMarker, 1536 | 4194304); + ts.setEmitFlags(mergeMarker, 1536 /* NoComments */ | 4194304 /* HasEndOfDeclarationMarker */); statements.push(mergeMarker); return false; } } + /** + * Visits a module declaration node. + * + * This function will be called any time a TypeScript namespace (ModuleDeclaration) is encountered. + * + * @param node The module declaration node. + */ function visitModuleDeclaration(node) { if (!shouldEmitModuleDeclaration(node)) { return ts.createNotEmittedStatement(node); @@ -54210,30 +63828,59 @@ var ts; ts.Debug.assertNode(node.name, ts.isIdentifier, "A TypeScript namespace should have an Identifier name."); enableSubstitutionForNamespaceExports(); var statements = []; - var emitFlags = 2; + // We request to be advised when the printer is about to print this node. This allows + // us to set up the correct state for later substitutions. + var emitFlags = 2 /* AdviseOnEmitNode */; + // If needed, we should emit a variable declaration for the module. If we emit + // a leading variable declaration, we should not emit leading comments for the + // module body. if (addVarForEnumOrModuleDeclaration(statements, node)) { + // We should still emit the comments if we are emitting a system module. if (moduleKind !== ts.ModuleKind.System || currentScope !== currentSourceFile) { - emitFlags |= 512; + emitFlags |= 512 /* NoLeadingComments */; } } + // `parameterName` is the declaration name used inside of the namespace. var parameterName = getNamespaceParameterName(node); + // `containerName` is the expression used inside of the namespace for exports. var containerName = getNamespaceContainerName(node); - var exportName = ts.hasModifier(node, 1) - ? ts.getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, false, true) - : ts.getLocalName(node, false, true); + // `exportName` is the expression used within this node's container for any exported references. + var exportName = ts.hasModifier(node, 1 /* Export */) + ? ts.getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, /*allowComments*/ false, /*allowSourceMaps*/ true) + : ts.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); + // x || (x = {}) + // exports.x || (exports.x = {}) var moduleArg = ts.createLogicalOr(exportName, ts.createAssignment(exportName, ts.createObjectLiteral())); if (hasNamespaceQualifiedExportName(node)) { - var localName = ts.getLocalName(node, false, true); + // `localName` is the expression used within this node's containing scope for any local references. + var localName = ts.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); + // x = (exports.x || (exports.x = {})) moduleArg = ts.createAssignment(localName, moduleArg); } - var moduleStatement = ts.createStatement(ts.createCall(ts.createFunctionExpression(undefined, undefined, undefined, undefined, [ts.createParameter(undefined, undefined, undefined, parameterName)], undefined, transformModuleBody(node, containerName)), undefined, [moduleArg])); + // (function (x_1) { + // x_1.y = ...; + // })(x || (x = {})); + var moduleStatement = ts.createStatement(ts.createCall(ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)], + /*type*/ undefined, transformModuleBody(node, containerName)), + /*typeArguments*/ undefined, [moduleArg])); ts.setOriginalNode(moduleStatement, node); ts.setTextRange(moduleStatement, node); ts.setEmitFlags(moduleStatement, emitFlags); statements.push(moduleStatement); + // Add a DeclarationMarker for the namespace to preserve trailing comments and mark + // the end of the declaration. statements.push(ts.createEndOfDeclarationMarker(node)); return statements; } + /** + * Transforms the body of a module declaration. + * + * @param node The module declaration node. + */ function transformModuleBody(node, namespaceLocalName) { var savedCurrentNamespaceContainerName = currentNamespaceContainerName; var savedCurrentNamespace = currentNamespace; @@ -54246,7 +63893,7 @@ var ts; var statementsLocation; var blockLocation; var body = node.body; - if (body.kind === 240) { + if (body.kind === 240 /* ModuleBlock */) { saveStateAndInvoke(body, function (body) { return ts.addRange(statements, ts.visitNodes(body.statements, namespaceElementVisitor, ts.isStatement)); }); statementsLocation = body.statements; blockLocation = body; @@ -54268,76 +63915,172 @@ var ts; currentNamespaceContainerName = savedCurrentNamespaceContainerName; currentNamespace = savedCurrentNamespace; currentScopeFirstDeclarationsOfName = savedCurrentScopeFirstDeclarationsOfName; - var block = ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), statementsLocation), true); + var block = ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), + /*location*/ statementsLocation), + /*multiLine*/ true); ts.setTextRange(block, blockLocation); - if (body.kind !== 240) { - ts.setEmitFlags(block, ts.getEmitFlags(block) | 1536); + // namespace hello.hi.world { + // function foo() {} + // + // // TODO, blah + // } + // + // should be emitted as + // + // var hello; + // (function (hello) { + // var hi; + // (function (hi) { + // var world; + // (function (world) { + // function foo() { } + // // TODO, blah + // })(world = hi.world || (hi.world = {})); + // })(hi = hello.hi || (hello.hi = {})); + // })(hello || (hello = {})); + // We only want to emit comment on the namespace which contains block body itself, not the containing namespaces. + if (body.kind !== 240 /* ModuleBlock */) { + ts.setEmitFlags(block, ts.getEmitFlags(block) | 1536 /* NoComments */); } return block; } function getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration) { - if (moduleDeclaration.body.kind === 239) { + if (moduleDeclaration.body.kind === 239 /* ModuleDeclaration */) { var recursiveInnerModule = getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration.body); return recursiveInnerModule || moduleDeclaration.body; } } + /** + * Visits an import declaration, eliding it if it is not referenced. + * + * @param node The import declaration node. + */ function visitImportDeclaration(node) { if (!node.importClause) { + // Do not elide a side-effect only import declaration. + // import "foo"; return node; } + // Elide the declaration if the import clause was elided. var importClause = ts.visitNode(node.importClause, visitImportClause, ts.isImportClause); return importClause - ? ts.updateImportDeclaration(node, undefined, undefined, importClause, node.moduleSpecifier) + ? ts.updateImportDeclaration(node, + /*decorators*/ undefined, + /*modifiers*/ undefined, importClause, node.moduleSpecifier) : undefined; } + /** + * Visits an import clause, eliding it if it is not referenced. + * + * @param node The import clause node. + */ function visitImportClause(node) { + // Elide the import clause if we elide both its name and its named bindings. var name = resolver.isReferencedAliasDeclaration(node) ? node.name : undefined; var namedBindings = ts.visitNode(node.namedBindings, visitNamedImportBindings, ts.isNamedImportBindings); return (name || namedBindings) ? ts.updateImportClause(node, name, namedBindings) : undefined; } + /** + * Visits named import bindings, eliding it if it is not referenced. + * + * @param node The named import bindings node. + */ function visitNamedImportBindings(node) { - if (node.kind === 246) { + if (node.kind === 246 /* NamespaceImport */) { + // Elide a namespace import if it is not referenced. return resolver.isReferencedAliasDeclaration(node) ? node : undefined; } else { + // Elide named imports if all of its import specifiers are elided. var elements = ts.visitNodes(node.elements, visitImportSpecifier, ts.isImportSpecifier); return ts.some(elements) ? ts.updateNamedImports(node, elements) : undefined; } } + /** + * Visits an import specifier, eliding it if it is not referenced. + * + * @param node The import specifier node. + */ function visitImportSpecifier(node) { + // Elide an import specifier if it is not referenced. return resolver.isReferencedAliasDeclaration(node) ? node : undefined; } + /** + * Visits an export assignment, eliding it if it does not contain a clause that resolves + * to a value. + * + * @param node The export assignment node. + */ function visitExportAssignment(node) { + // Elide the export assignment if it does not reference a value. return resolver.isValueAliasDeclaration(node) ? ts.visitEachChild(node, visitor, context) : undefined; } + /** + * Visits an export declaration, eliding it if it does not contain a clause that resolves + * to a value. + * + * @param node The export declaration node. + */ function visitExportDeclaration(node) { if (!node.exportClause) { + // Elide a star export if the module it references does not export a value. return compilerOptions.isolatedModules || resolver.moduleExportsSomeValue(node.moduleSpecifier) ? node : undefined; } if (!resolver.isValueAliasDeclaration(node)) { + // Elide the export declaration if it does not export a value. return undefined; } + // Elide the export declaration if all of its named exports are elided. var exportClause = ts.visitNode(node.exportClause, visitNamedExports, ts.isNamedExports); return exportClause - ? ts.updateExportDeclaration(node, undefined, undefined, exportClause, node.moduleSpecifier) + ? ts.updateExportDeclaration(node, + /*decorators*/ undefined, + /*modifiers*/ undefined, exportClause, node.moduleSpecifier) : undefined; } + /** + * Visits named exports, eliding it if it does not contain an export specifier that + * resolves to a value. + * + * @param node The named exports node. + */ function visitNamedExports(node) { + // Elide the named exports if all of its export specifiers were elided. var elements = ts.visitNodes(node.elements, visitExportSpecifier, ts.isExportSpecifier); return ts.some(elements) ? ts.updateNamedExports(node, elements) : undefined; } + /** + * Visits an export specifier, eliding it if it does not resolve to a value. + * + * @param node The export specifier node. + */ function visitExportSpecifier(node) { + // Elide an export specifier if it does not reference a value. return resolver.isValueAliasDeclaration(node) ? node : undefined; } + /** + * Determines whether to emit an import equals declaration. + * + * @param node The import equals declaration node. + */ function shouldEmitImportEqualsDeclaration(node) { + // 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) || (!ts.isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node)); } + /** + * Visits an import equals declaration. + * + * @param node The import equals declaration node. + */ function visitImportEqualsDeclaration(node) { if (ts.isExternalModuleImportEqualsDeclaration(node)) { + // Elide external module `import=` if it is not referenced. return resolver.isReferencedAliasDeclaration(node) ? ts.visitEachChild(node, visitor, context) : undefined; @@ -54346,59 +64089,98 @@ var ts; return undefined; } var moduleReference = ts.createExpressionFromEntityName(node.moduleReference); - ts.setEmitFlags(moduleReference, 1536 | 2048); + ts.setEmitFlags(moduleReference, 1536 /* NoComments */ | 2048 /* NoNestedComments */); if (isNamedExternalModuleExport(node) || !isExportOfNamespace(node)) { + // export var ${name} = ${moduleReference}; + // var ${name} = ${moduleReference}; return ts.setOriginalNode(ts.setTextRange(ts.createVariableStatement(ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), ts.createVariableDeclarationList([ - ts.setOriginalNode(ts.createVariableDeclaration(node.name, undefined, moduleReference), node) + ts.setOriginalNode(ts.createVariableDeclaration(node.name, + /*type*/ undefined, moduleReference), node) ])), node), node); } else { + // exports.${name} = ${moduleReference}; return ts.setOriginalNode(createNamespaceExport(node.name, moduleReference, node), node); } } + /** + * Gets a value indicating whether the node is exported from a namespace. + * + * @param node The node to test. + */ function isExportOfNamespace(node) { - return currentNamespace !== undefined && ts.hasModifier(node, 1); + return currentNamespace !== undefined && ts.hasModifier(node, 1 /* Export */); } + /** + * Gets a value indicating whether the node is exported from an external module. + * + * @param node The node to test. + */ function isExternalModuleExport(node) { - return currentNamespace === undefined && ts.hasModifier(node, 1); + return currentNamespace === undefined && ts.hasModifier(node, 1 /* Export */); } + /** + * Gets a value indicating whether the node is a named export from an external module. + * + * @param node The node to test. + */ function isNamedExternalModuleExport(node) { return isExternalModuleExport(node) - && !ts.hasModifier(node, 512); + && !ts.hasModifier(node, 512 /* Default */); } + /** + * Gets a value indicating whether the node is the default export of an external module. + * + * @param node The node to test. + */ function isDefaultExternalModuleExport(node) { return isExternalModuleExport(node) - && ts.hasModifier(node, 512); + && ts.hasModifier(node, 512 /* Default */); } + /** + * Creates a statement for the provided expression. This is used in calls to `map`. + */ function expressionToStatement(expression) { return ts.createStatement(expression); } function addExportMemberAssignment(statements, node) { - var expression = ts.createAssignment(ts.getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, false, true), ts.getLocalName(node)); + var expression = ts.createAssignment(ts.getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, /*allowComments*/ false, /*allowSourceMaps*/ true), ts.getLocalName(node)); ts.setSourceMapRange(expression, ts.createRange(node.name ? node.name.pos : node.pos, node.end)); var statement = ts.createStatement(expression); ts.setSourceMapRange(statement, ts.createRange(-1, node.end)); statements.push(statement); } function createNamespaceExport(exportName, exportValue, location) { - return ts.setTextRange(ts.createStatement(ts.createAssignment(ts.getNamespaceMemberName(currentNamespaceContainerName, exportName, false, true), exportValue)), location); + return ts.setTextRange(ts.createStatement(ts.createAssignment(ts.getNamespaceMemberName(currentNamespaceContainerName, exportName, /*allowComments*/ false, /*allowSourceMaps*/ true), exportValue)), location); } function createNamespaceExportExpression(exportName, exportValue, location) { return ts.setTextRange(ts.createAssignment(getNamespaceMemberNameWithSourceMapsAndWithoutComments(exportName), exportValue), location); } function getNamespaceMemberNameWithSourceMapsAndWithoutComments(name) { - return ts.getNamespaceMemberName(currentNamespaceContainerName, name, false, true); + return ts.getNamespaceMemberName(currentNamespaceContainerName, name, /*allowComments*/ false, /*allowSourceMaps*/ true); } + /** + * Gets the declaration name used inside of a namespace or enum. + */ function getNamespaceParameterName(node) { var name = ts.getGeneratedNameForNode(node); ts.setSourceMapRange(name, node.name); return name; } + /** + * Gets the expression used to refer to a namespace or enum within the body + * of its declaration. + */ function getNamespaceContainerName(node) { return ts.getGeneratedNameForNode(node); } + /** + * Gets a local alias for a class declaration if it is a decorated class with an internal + * reference to the static side of the class. This is necessary to avoid issues with + * double-binding semantics for the class name. + */ function getClassAliasIfNeeded(node) { - if (resolver.getNodeCheckFlags(node) & 8388608) { + if (resolver.getNodeCheckFlags(node) & 8388608 /* ClassWithConstructorReference */) { enableSubstitutionForClassAliases(); var classAlias = ts.createUniqueName(node.name && !ts.isGeneratedIdentifier(node.name) ? ts.idText(node.name) : "default"); classAliases[ts.getOriginalNodeId(node)] = classAlias; @@ -54410,56 +64192,75 @@ var ts; return ts.createPropertyAccess(ts.getDeclarationName(node), "prototype"); } function getClassMemberPrefix(node, member) { - return ts.hasModifier(member, 32) + return ts.hasModifier(member, 32 /* Static */) ? ts.getDeclarationName(node) : getClassPrototype(node); } function enableSubstitutionForNonQualifiedEnumMembers() { - if ((enabledSubstitutions & 8) === 0) { - enabledSubstitutions |= 8; - context.enableSubstitution(71); + if ((enabledSubstitutions & 8 /* NonQualifiedEnumMembers */) === 0) { + enabledSubstitutions |= 8 /* NonQualifiedEnumMembers */; + context.enableSubstitution(71 /* Identifier */); } } function enableSubstitutionForClassAliases() { - if ((enabledSubstitutions & 1) === 0) { - enabledSubstitutions |= 1; - context.enableSubstitution(71); + if ((enabledSubstitutions & 1 /* ClassAliases */) === 0) { + enabledSubstitutions |= 1 /* ClassAliases */; + // We need to enable substitutions for identifiers. This allows us to + // substitute class names inside of a class declaration. + context.enableSubstitution(71 /* Identifier */); + // Keep track of class aliases. classAliases = []; } } function enableSubstitutionForNamespaceExports() { - if ((enabledSubstitutions & 2) === 0) { - enabledSubstitutions |= 2; - context.enableSubstitution(71); - context.enableSubstitution(271); - context.enableEmitNotification(239); + if ((enabledSubstitutions & 2 /* NamespaceExports */) === 0) { + enabledSubstitutions |= 2 /* NamespaceExports */; + // We need to enable substitutions for identifiers and shorthand property assignments. This allows us to + // substitute the names of exported members of a namespace. + context.enableSubstitution(71 /* Identifier */); + context.enableSubstitution(271 /* ShorthandPropertyAssignment */); + // We need to be notified when entering and exiting namespaces. + context.enableEmitNotification(239 /* ModuleDeclaration */); } } function isTransformedModuleDeclaration(node) { - return ts.getOriginalNode(node).kind === 239; + return ts.getOriginalNode(node).kind === 239 /* ModuleDeclaration */; } function isTransformedEnumDeclaration(node) { - return ts.getOriginalNode(node).kind === 238; + return ts.getOriginalNode(node).kind === 238 /* EnumDeclaration */; } + /** + * Hook for node emit. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emit A callback used to emit the node in the printer. + */ function onEmitNode(hint, node, emitCallback) { var savedApplicableSubstitutions = applicableSubstitutions; var savedCurrentSourceFile = currentSourceFile; if (ts.isSourceFile(node)) { currentSourceFile = node; } - if (enabledSubstitutions & 2 && isTransformedModuleDeclaration(node)) { - applicableSubstitutions |= 2; + if (enabledSubstitutions & 2 /* NamespaceExports */ && isTransformedModuleDeclaration(node)) { + applicableSubstitutions |= 2 /* NamespaceExports */; } - if (enabledSubstitutions & 8 && isTransformedEnumDeclaration(node)) { - applicableSubstitutions |= 8; + if (enabledSubstitutions & 8 /* NonQualifiedEnumMembers */ && isTransformedEnumDeclaration(node)) { + applicableSubstitutions |= 8 /* NonQualifiedEnumMembers */; } previousOnEmitNode(hint, node, emitCallback); applicableSubstitutions = savedApplicableSubstitutions; currentSourceFile = savedCurrentSourceFile; } + /** + * Hooks node substitutions. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to substitute. + */ function onSubstituteNode(hint, node) { node = previousOnSubstituteNode(hint, node); - if (hint === 1) { + if (hint === 1 /* Expression */) { return substituteExpression(node); } else if (ts.isShorthandPropertyAssignment(node)) { @@ -54468,10 +64269,12 @@ var ts; return node; } function substituteShorthandPropertyAssignment(node) { - if (enabledSubstitutions & 2) { + if (enabledSubstitutions & 2 /* NamespaceExports */) { var name = node.name; var exportedName = trySubstituteNamespaceExportedName(name); if (exportedName) { + // A shorthand property with an assignment initializer is probably part of a + // destructuring assignment if (node.objectAssignmentInitializer) { var initializer = ts.createAssignment(exportedName, node.objectAssignmentInitializer); return ts.setTextRange(ts.createPropertyAssignment(name, initializer), node); @@ -54483,11 +64286,11 @@ var ts; } function substituteExpression(node) { switch (node.kind) { - case 71: + case 71 /* Identifier */: return substituteExpressionIdentifier(node); - case 185: + case 185 /* PropertyAccessExpression */: return substitutePropertyAccessExpression(node); - case 186: + case 186 /* ElementAccessExpression */: return substituteElementAccessExpression(node); } return node; @@ -54498,11 +64301,16 @@ var ts; || node; } function trySubstituteClassAlias(node) { - if (enabledSubstitutions & 1) { - if (resolver.getNodeCheckFlags(node) & 16777216) { + if (enabledSubstitutions & 1 /* ClassAliases */) { + if (resolver.getNodeCheckFlags(node) & 16777216 /* ConstructorReferenceInClass */) { + // Due to the emit for class decorators, any reference to the class from inside of the class body + // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind + // behavior of class names in ES6. + // Also, when emitting statics for class expressions, we must substitute a class alias for + // constructor references in static property initializers. var declaration = resolver.getReferencedValueDeclaration(node); if (declaration) { - var classAlias = classAliases[declaration.id]; + var classAlias = classAliases[declaration.id]; // TODO: GH#18217 if (classAlias) { var clone_1 = ts.getSynthesizedClone(classAlias); ts.setSourceMapRange(clone_1, node); @@ -54515,13 +64323,17 @@ var ts; return undefined; } function trySubstituteNamespaceExportedName(node) { + // If this is explicitly a local name, do not substitute. if (enabledSubstitutions & applicableSubstitutions && !ts.isGeneratedIdentifier(node) && !ts.isLocalName(node)) { - var container = resolver.getReferencedExportContainer(node, false); - if (container && container.kind !== 274) { - var substitute = (applicableSubstitutions & 2 && container.kind === 239) || - (applicableSubstitutions & 8 && container.kind === 238); + // If we are nested within a namespace declaration, we may need to qualifiy + // an identifier that is exported from a merged namespace. + var container = resolver.getReferencedExportContainer(node, /*prefixLocals*/ false); + if (container && container.kind !== 274 /* SourceFile */) { + var substitute = (applicableSubstitutions & 2 /* NamespaceExports */ && container.kind === 239 /* ModuleDeclaration */) || + (applicableSubstitutions & 8 /* NonQualifiedEnumMembers */ && container.kind === 238 /* EnumDeclaration */); if (substitute) { - return ts.setTextRange(ts.createPropertyAccess(ts.getGeneratedNameForNode(container), node), node); + return ts.setTextRange(ts.createPropertyAccess(ts.getGeneratedNameForNode(container), node), + /*location*/ node); } } } @@ -54536,13 +64348,14 @@ var ts; function substituteConstantValue(node) { var constantValue = tryGetConstEnumValue(node); if (constantValue !== undefined) { + // track the constant value on the node for the printer in needsDotDotForPropertyAccess ts.setConstantValue(node, constantValue); var substitute = ts.createLiteral(constantValue); if (!compilerOptions.removeComments) { var propertyName = ts.isPropertyAccessExpression(node) ? ts.declarationNameToString(node.name) : ts.getTextOfNode(node.argumentExpression); - ts.addSyntheticTrailingComment(substitute, 3, " " + propertyName + " "); + ts.addSyntheticTrailingComment(substitute, 3 /* MultiLineCommentTrivia */, " " + propertyName + " "); } return substitute; } @@ -54558,7 +64371,7 @@ var ts; ts.transformTypeScript = transformTypeScript; function createDecorateHelper(context, decoratorExpressions, target, memberName, descriptor, location) { var argumentsArray = []; - argumentsArray.push(ts.createArrayLiteral(decoratorExpressions, true)); + argumentsArray.push(ts.createArrayLiteral(decoratorExpressions, /*multiLine*/ true)); argumentsArray.push(target); if (memberName) { argumentsArray.push(memberName); @@ -54567,7 +64380,8 @@ var ts; } } context.requestEmitHelper(decorateHelper); - return ts.setTextRange(ts.createCall(ts.getHelperName("__decorate"), undefined, argumentsArray), location); + return ts.setTextRange(ts.createCall(ts.getHelperName("__decorate"), + /*typeArguments*/ undefined, argumentsArray), location); } var decorateHelper = { name: "typescript:decorate", @@ -54577,7 +64391,8 @@ var ts; }; function createMetadataHelper(context, metadataKey, metadataValue) { context.requestEmitHelper(metadataHelper); - return ts.createCall(ts.getHelperName("__metadata"), undefined, [ + return ts.createCall(ts.getHelperName("__metadata"), + /*typeArguments*/ undefined, [ ts.createLiteral(metadataKey), metadataValue ]); @@ -54590,7 +64405,8 @@ var ts; }; function createParamHelper(context, expression, parameterOffset, location) { context.requestEmitHelper(paramHelper); - return ts.setTextRange(ts.createCall(ts.getHelperName("__param"), undefined, [ + return ts.setTextRange(ts.createCall(ts.getHelperName("__param"), + /*typeArguments*/ undefined, [ ts.createLiteral(parameterOffset), expression ]), location); @@ -54602,10 +64418,12 @@ var ts; text: "\n var __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n };" }; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { var ES2017SubstitutionFlags; (function (ES2017SubstitutionFlags) { + /** Enables substitutions for async methods with `super` calls. */ ES2017SubstitutionFlags[ES2017SubstitutionFlags["AsyncMethodsWithSuper"] = 1] = "AsyncMethodsWithSuper"; })(ES2017SubstitutionFlags || (ES2017SubstitutionFlags = {})); function transformES2017(context) { @@ -54613,11 +64431,21 @@ var ts; var resolver = context.getEmitResolver(); var compilerOptions = context.getCompilerOptions(); var languageVersion = ts.getEmitScriptTarget(compilerOptions); + /** + * Keeps track of whether expression substitution has been enabled for specific edge cases. + * They are persisted between each SourceFile transformation and should not be reset. + */ var enabledSubstitutions; + /** + * This keeps track of containers where `super` is valid, for use with + * just-in-time substitution for `super` expressions inside of async methods. + */ var enclosingSuperContainerFlags = 0; var enclosingFunctionParameterNames; + // Save the previous transformation hooks. var previousOnEmitNode = context.onEmitNode; var previousOnSubstituteNode = context.onSubstituteNode; + // Set new transformation hooks. context.onEmitNode = onEmitNode; context.onSubstituteNode = onSubstituteNode; return ts.chainBundle(transformSourceFile); @@ -54630,21 +64458,22 @@ var ts; return visited; } function visitor(node) { - if ((node.transformFlags & 16) === 0) { + if ((node.transformFlags & 16 /* ContainsES2017 */) === 0) { return node; } switch (node.kind) { - case 120: + case 120 /* AsyncKeyword */: + // ES2017 async modifier should be elided for targets < ES2017 return undefined; - case 197: + case 197 /* AwaitExpression */: return visitAwaitExpression(node); - case 154: + case 154 /* MethodDeclaration */: return visitMethodDeclaration(node); - case 234: + case 234 /* FunctionDeclaration */: return visitFunctionDeclaration(node); - case 192: + case 192 /* FunctionExpression */: return visitFunctionExpression(node); - case 193: + case 193 /* ArrowFunction */: return visitArrowFunction(node); default: return ts.visitEachChild(node, visitor, context); @@ -54653,27 +64482,27 @@ var ts; function asyncBodyVisitor(node) { if (ts.isNodeWithPossibleHoistedDeclaration(node)) { switch (node.kind) { - case 214: + case 214 /* VariableStatement */: return visitVariableStatementInAsyncBody(node); - case 220: + case 220 /* ForStatement */: return visitForStatementInAsyncBody(node); - case 221: + case 221 /* ForInStatement */: return visitForInStatementInAsyncBody(node); - case 222: + case 222 /* ForOfStatement */: return visitForOfStatementInAsyncBody(node); - case 269: + case 269 /* CatchClause */: return visitCatchClauseInAsyncBody(node); - case 213: - case 227: - case 241: - case 266: - case 267: - case 230: - case 218: - case 219: - case 217: - case 226: - case 228: + case 213 /* Block */: + case 227 /* SwitchStatement */: + case 241 /* CaseBlock */: + case 266 /* CaseClause */: + case 267 /* DefaultClause */: + case 230 /* TryStatement */: + case 218 /* DoStatement */: + case 219 /* WhileStatement */: + case 217 /* IfStatement */: + case 226 /* WithStatement */: + case 228 /* LabeledStatement */: return ts.visitEachChild(node, asyncBodyVisitor, context); default: return ts.Debug.assertNever(node, "Unhandled node."); @@ -54683,7 +64512,8 @@ var ts; } function visitCatchClauseInAsyncBody(node) { var catchClauseNames = ts.createUnderscoreEscapedMap(); - recordDeclarationName(node.variableDeclaration, catchClauseNames); + recordDeclarationName(node.variableDeclaration, catchClauseNames); // TODO: GH#18217 + // names declared in a catch variable are block scoped var catchClauseUnshadowedNames; catchClauseNames.forEach(function (_, escapedName) { if (enclosingFunctionParameterNames.has(escapedName)) { @@ -54706,47 +64536,98 @@ var ts; } function visitVariableStatementInAsyncBody(node) { if (isVariableDeclarationListWithCollidingName(node.declarationList)) { - var expression = visitVariableDeclarationListWithCollidingNames(node.declarationList, false); + var expression = visitVariableDeclarationListWithCollidingNames(node.declarationList, /*hasReceiver*/ false); return expression ? ts.createStatement(expression) : undefined; } return ts.visitEachChild(node, visitor, context); } function visitForInStatementInAsyncBody(node) { return ts.updateForIn(node, isVariableDeclarationListWithCollidingName(node.initializer) - ? visitVariableDeclarationListWithCollidingNames(node.initializer, true) + ? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ true) : ts.visitNode(node.initializer, visitor, ts.isForInitializer), ts.visitNode(node.expression, visitor, ts.isExpression), ts.visitNode(node.statement, asyncBodyVisitor, ts.isStatement, ts.liftToBlock)); } function visitForOfStatementInAsyncBody(node) { return ts.updateForOf(node, ts.visitNode(node.awaitModifier, visitor, ts.isToken), isVariableDeclarationListWithCollidingName(node.initializer) - ? visitVariableDeclarationListWithCollidingNames(node.initializer, true) + ? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ true) : ts.visitNode(node.initializer, visitor, ts.isForInitializer), ts.visitNode(node.expression, visitor, ts.isExpression), ts.visitNode(node.statement, asyncBodyVisitor, ts.isStatement, ts.liftToBlock)); } function visitForStatementInAsyncBody(node) { - var initializer = node.initializer; + var initializer = node.initializer; // TODO: GH#18217 return ts.updateFor(node, isVariableDeclarationListWithCollidingName(initializer) - ? visitVariableDeclarationListWithCollidingNames(initializer, false) + ? visitVariableDeclarationListWithCollidingNames(initializer, /*hasReceiver*/ false) : ts.visitNode(node.initializer, visitor, ts.isForInitializer), ts.visitNode(node.condition, visitor, ts.isExpression), ts.visitNode(node.incrementor, visitor, ts.isExpression), ts.visitNode(node.statement, asyncBodyVisitor, ts.isStatement, ts.liftToBlock)); } + /** + * Visits an AwaitExpression node. + * + * This function will be called any time a ES2017 await expression is encountered. + * + * @param node The node to visit. + */ function visitAwaitExpression(node) { - return ts.setOriginalNode(ts.setTextRange(ts.createYield(undefined, ts.visitNode(node.expression, visitor, ts.isExpression)), node), node); + return ts.setOriginalNode(ts.setTextRange(ts.createYield( + /*asteriskToken*/ undefined, ts.visitNode(node.expression, visitor, ts.isExpression)), node), node); } + /** + * Visits a MethodDeclaration node. + * + * This function will be called when one of the following conditions are met: + * - The node is marked as async + * + * @param node The node to visit. + */ function visitMethodDeclaration(node) { - return ts.updateMethod(node, undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), node.asteriskToken, node.name, undefined, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, ts.getFunctionFlags(node) & 2 + return ts.updateMethod(node, + /*decorators*/ undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), node.asteriskToken, node.name, + /*questionToken*/ undefined, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, ts.getFunctionFlags(node) & 2 /* Async */ ? transformAsyncFunctionBody(node) : ts.visitFunctionBody(node.body, visitor, context)); } + /** + * Visits a FunctionDeclaration node. + * + * This function will be called when one of the following conditions are met: + * - The node is marked async + * + * @param node The node to visit. + */ function visitFunctionDeclaration(node) { - return ts.updateFunctionDeclaration(node, undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), node.asteriskToken, node.name, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, ts.getFunctionFlags(node) & 2 + return ts.updateFunctionDeclaration(node, + /*decorators*/ undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), node.asteriskToken, node.name, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, ts.getFunctionFlags(node) & 2 /* Async */ ? transformAsyncFunctionBody(node) : ts.visitFunctionBody(node.body, visitor, context)); } + /** + * Visits a FunctionExpression node. + * + * This function will be called when one of the following conditions are met: + * - The node is marked async + * + * @param node The node to visit. + */ function visitFunctionExpression(node) { - return ts.updateFunctionExpression(node, ts.visitNodes(node.modifiers, visitor, ts.isModifier), node.asteriskToken, node.name, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, ts.getFunctionFlags(node) & 2 + return ts.updateFunctionExpression(node, ts.visitNodes(node.modifiers, visitor, ts.isModifier), node.asteriskToken, node.name, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, ts.getFunctionFlags(node) & 2 /* Async */ ? transformAsyncFunctionBody(node) : ts.visitFunctionBody(node.body, visitor, context)); } + /** + * Visits an ArrowFunction. + * + * This function will be called when one of the following conditions are met: + * - The node is marked async + * + * @param node The node to visit. + */ function visitArrowFunction(node) { - return ts.updateArrowFunction(node, ts.visitNodes(node.modifiers, visitor, ts.isModifier), undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, node.equalsGreaterThanToken, ts.getFunctionFlags(node) & 2 + return ts.updateArrowFunction(node, ts.visitNodes(node.modifiers, visitor, ts.isModifier), + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, node.equalsGreaterThanToken, ts.getFunctionFlags(node) & 2 /* Async */ ? transformAsyncFunctionBody(node) : ts.visitFunctionBody(node.body, visitor, context)); } @@ -54767,7 +64648,7 @@ var ts; function isVariableDeclarationListWithCollidingName(node) { return !!node && ts.isVariableDeclarationList(node) - && !(node.flags & 3) + && !(node.flags & 3 /* BlockScoped */) && node.declarations.some(collidesWithParameterName); } function visitVariableDeclarationListWithCollidingNames(node, hasReceiver) { @@ -54821,9 +64702,14 @@ var ts; resumeLexicalEnvironment(); var original = ts.getOriginalNode(node, ts.isFunctionLike); var nodeType = original.type; - var promiseConstructor = languageVersion < 2 ? getPromiseConstructor(nodeType) : undefined; - var isArrowFunction = node.kind === 193; - var hasLexicalArguments = (resolver.getNodeCheckFlags(node) & 8192) !== 0; + var promiseConstructor = languageVersion < 2 /* ES2015 */ ? getPromiseConstructor(nodeType) : undefined; + var isArrowFunction = node.kind === 193 /* ArrowFunction */; + var hasLexicalArguments = (resolver.getNodeCheckFlags(node) & 8192 /* CaptureArguments */) !== 0; + // 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. var savedEnclosingFunctionParameterNames = enclosingFunctionParameterNames; enclosingFunctionParameterNames = ts.createUnderscoreEscapedMap(); for (var _i = 0, _a = node.parameters; _i < _a.length; _i++) { @@ -54833,17 +64719,19 @@ var ts; var result; if (!isArrowFunction) { var statements = []; - var statementOffset = ts.addPrologue(statements, node.body.statements, false, visitor); + var statementOffset = ts.addPrologue(statements, node.body.statements, /*ensureUseStrict*/ false, visitor); statements.push(ts.createReturn(createAwaiterHelper(context, hasLexicalArguments, promiseConstructor, transformAsyncFunctionBodyWorker(node.body, statementOffset)))); ts.prependStatements(statements, endLexicalEnvironment()); - var block = ts.createBlock(statements, true); + var block = ts.createBlock(statements, /*multiLine*/ true); ts.setTextRange(block, node.body); - if (languageVersion >= 2) { - if (resolver.getNodeCheckFlags(node) & 4096) { + // Minor optimization, emit `_super` helper to capture `super` access in an arrow. + // This step isn't needed if we eventually transform this to ES5. + if (languageVersion >= 2 /* ES2015 */) { + if (resolver.getNodeCheckFlags(node) & 4096 /* AsyncMethodWithSuperBinding */) { enableSubstitutionForAsyncMethodsWithSuper(); ts.addEmitHelper(block, ts.advancedAsyncSuperHelper); } - else if (resolver.getNodeCheckFlags(node) & 2048) { + else if (resolver.getNodeCheckFlags(node) & 2048 /* AsyncMethodWithSuper */) { enableSubstitutionForAsyncMethodsWithSuper(); ts.addEmitHelper(block, ts.asyncSuperHelper); } @@ -54884,21 +64772,33 @@ var ts; return undefined; } function enableSubstitutionForAsyncMethodsWithSuper() { - if ((enabledSubstitutions & 1) === 0) { - enabledSubstitutions |= 1; - context.enableSubstitution(187); - context.enableSubstitution(185); - context.enableSubstitution(186); - context.enableEmitNotification(235); - context.enableEmitNotification(154); - context.enableEmitNotification(156); - context.enableEmitNotification(157); - context.enableEmitNotification(155); + if ((enabledSubstitutions & 1 /* AsyncMethodsWithSuper */) === 0) { + enabledSubstitutions |= 1 /* AsyncMethodsWithSuper */; + // We need to enable substitutions for call, property access, and element access + // if we need to rewrite super calls. + context.enableSubstitution(187 /* CallExpression */); + context.enableSubstitution(185 /* PropertyAccessExpression */); + context.enableSubstitution(186 /* ElementAccessExpression */); + // We need to be notified when entering and exiting declarations that bind super. + context.enableEmitNotification(235 /* ClassDeclaration */); + context.enableEmitNotification(154 /* MethodDeclaration */); + context.enableEmitNotification(156 /* GetAccessor */); + context.enableEmitNotification(157 /* SetAccessor */); + context.enableEmitNotification(155 /* Constructor */); } } + /** + * Hook for node emit. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emit A callback used to emit the node in the printer. + */ function onEmitNode(hint, node, emitCallback) { - if (enabledSubstitutions & 1 && isSuperContainer(node)) { - var superContainerFlags = resolver.getNodeCheckFlags(node) & (2048 | 4096); + // If we need to support substitutions for `super` in an async method, + // we should track it here. + if (enabledSubstitutions & 1 /* AsyncMethodsWithSuper */ && isSuperContainer(node)) { + var superContainerFlags = resolver.getNodeCheckFlags(node) & (2048 /* AsyncMethodWithSuper */ | 4096 /* AsyncMethodWithSuperBinding */); if (superContainerFlags !== enclosingSuperContainerFlags) { var savedEnclosingSuperContainerFlags = enclosingSuperContainerFlags; enclosingSuperContainerFlags = superContainerFlags; @@ -54909,32 +64809,38 @@ var ts; } previousOnEmitNode(hint, node, emitCallback); } + /** + * Hooks node substitutions. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to substitute. + */ function onSubstituteNode(hint, node) { node = previousOnSubstituteNode(hint, node); - if (hint === 1 && enclosingSuperContainerFlags) { + if (hint === 1 /* Expression */ && enclosingSuperContainerFlags) { return substituteExpression(node); } return node; } function substituteExpression(node) { switch (node.kind) { - case 185: + case 185 /* PropertyAccessExpression */: return substitutePropertyAccessExpression(node); - case 186: + case 186 /* ElementAccessExpression */: return substituteElementAccessExpression(node); - case 187: + case 187 /* CallExpression */: return substituteCallExpression(node); } return node; } function substitutePropertyAccessExpression(node) { - if (node.expression.kind === 97) { + if (node.expression.kind === 97 /* SuperKeyword */) { return createSuperAccessInAsyncMethod(ts.createLiteral(ts.idText(node.name)), node); } return node; } function substituteElementAccessExpression(node) { - if (node.expression.kind === 97) { + if (node.expression.kind === 97 /* SuperKeyword */) { return createSuperAccessInAsyncMethod(node.argumentExpression, node); } return node; @@ -54945,7 +64851,8 @@ var ts; var argumentExpression = ts.isPropertyAccessExpression(expression) ? substitutePropertyAccessExpression(expression) : substituteElementAccessExpression(expression); - return ts.createCall(ts.createPropertyAccess(argumentExpression, "call"), undefined, [ + return ts.createCall(ts.createPropertyAccess(argumentExpression, "call"), + /*typeArguments*/ undefined, [ ts.createThis() ].concat(node.arguments)); } @@ -54953,18 +64860,20 @@ var ts; } function isSuperContainer(node) { var kind = node.kind; - return kind === 235 - || kind === 155 - || kind === 154 - || kind === 156 - || kind === 157; + return kind === 235 /* ClassDeclaration */ + || kind === 155 /* Constructor */ + || kind === 154 /* MethodDeclaration */ + || kind === 156 /* GetAccessor */ + || kind === 157 /* SetAccessor */; } function createSuperAccessInAsyncMethod(argumentExpression, location) { - if (enclosingSuperContainerFlags & 4096) { - return ts.setTextRange(ts.createPropertyAccess(ts.createCall(ts.createFileLevelUniqueName("_super"), undefined, [argumentExpression]), "value"), location); + if (enclosingSuperContainerFlags & 4096 /* AsyncMethodWithSuperBinding */) { + return ts.setTextRange(ts.createPropertyAccess(ts.createCall(ts.createFileLevelUniqueName("_super"), + /*typeArguments*/ undefined, [argumentExpression]), "value"), location); } else { - return ts.setTextRange(ts.createCall(ts.createFileLevelUniqueName("_super"), undefined, [argumentExpression]), location); + return ts.setTextRange(ts.createCall(ts.createFileLevelUniqueName("_super"), + /*typeArguments*/ undefined, [argumentExpression]), location); } } } @@ -54977,9 +64886,16 @@ var ts; }; function createAwaiterHelper(context, hasLexicalArguments, promiseConstructor, body) { context.requestEmitHelper(awaiterHelper); - var generatorFunc = ts.createFunctionExpression(undefined, ts.createToken(39), undefined, undefined, [], undefined, body); - (generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= 262144 | 524288; - return ts.createCall(ts.getHelperName("__awaiter"), undefined, [ + var generatorFunc = ts.createFunctionExpression( + /*modifiers*/ undefined, ts.createToken(39 /* AsteriskToken */), + /*name*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ [], + /*type*/ undefined, body); + // Mark this node as originally an async function + (generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= 262144 /* AsyncFunctionBody */ | 524288 /* ReuseTempVariableScope */; + return ts.createCall(ts.getHelperName("__awaiter"), + /*typeArguments*/ undefined, [ ts.createThis(), hasLexicalArguments ? ts.createIdentifier("arguments") : ts.createVoidZero(), promiseConstructor ? ts.createExpressionFromEntityName(promiseConstructor) : ts.createVoidZero(), @@ -54997,10 +64913,12 @@ var ts; text: ts.helperString(__makeTemplateObject(["\n const ", " = (function (geti, seti) {\n const cache = Object.create(null);\n return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });\n })(name => super[name], (name, value) => super[name] = value);"], ["\n const ", " = (function (geti, seti) {\n const cache = Object.create(null);\n return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });\n })(name => super[name], (name, value) => super[name] = value);"]), "_super") }; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { var ESNextSubstitutionFlags; (function (ESNextSubstitutionFlags) { + /** Enables substitutions for async methods with `super` calls. */ ESNextSubstitutionFlags[ESNextSubstitutionFlags["AsyncMethodsWithSuper"] = 1] = "AsyncMethodsWithSuper"; })(ESNextSubstitutionFlags || (ESNextSubstitutionFlags = {})); function transformESNext(context) { @@ -55025,76 +64943,77 @@ var ts; return visited; } function visitor(node) { - return visitorWorker(node, false); + return visitorWorker(node, /*noDestructuringValue*/ false); } function visitorNoDestructuringValue(node) { - return visitorWorker(node, true); + return visitorWorker(node, /*noDestructuringValue*/ true); } function visitorNoAsyncModifier(node) { - if (node.kind === 120) { + if (node.kind === 120 /* AsyncKeyword */) { return undefined; } return node; } function visitorWorker(node, noDestructuringValue) { - if ((node.transformFlags & 8) === 0) { + if ((node.transformFlags & 8 /* ContainsESNext */) === 0) { return node; } switch (node.kind) { - case 197: + case 197 /* AwaitExpression */: return visitAwaitExpression(node); - case 203: + case 203 /* YieldExpression */: return visitYieldExpression(node); - case 225: + case 225 /* ReturnStatement */: return visitReturnStatement(node); - case 228: + case 228 /* LabeledStatement */: return visitLabeledStatement(node); - case 184: + case 184 /* ObjectLiteralExpression */: return visitObjectLiteralExpression(node); - case 200: + case 200 /* BinaryExpression */: return visitBinaryExpression(node, noDestructuringValue); - case 232: + case 232 /* VariableDeclaration */: return visitVariableDeclaration(node); - case 222: - return visitForOfStatement(node, undefined); - case 220: + case 222 /* ForOfStatement */: + return visitForOfStatement(node, /*outermostLabeledStatement*/ undefined); + case 220 /* ForStatement */: return visitForStatement(node); - case 196: + case 196 /* VoidExpression */: return visitVoidExpression(node); - case 155: + case 155 /* Constructor */: return visitConstructorDeclaration(node); - case 154: + case 154 /* MethodDeclaration */: return visitMethodDeclaration(node); - case 156: + case 156 /* GetAccessor */: return visitGetAccessorDeclaration(node); - case 157: + case 157 /* SetAccessor */: return visitSetAccessorDeclaration(node); - case 234: + case 234 /* FunctionDeclaration */: return visitFunctionDeclaration(node); - case 192: + case 192 /* FunctionExpression */: return visitFunctionExpression(node); - case 193: + case 193 /* ArrowFunction */: return visitArrowFunction(node); - case 149: + case 149 /* Parameter */: return visitParameter(node); - case 216: + case 216 /* ExpressionStatement */: return visitExpressionStatement(node); - case 191: + case 191 /* ParenthesizedExpression */: return visitParenthesizedExpression(node, noDestructuringValue); - case 269: + case 269 /* CatchClause */: return visitCatchClause(node); default: return ts.visitEachChild(node, visitor, context); } } function visitAwaitExpression(node) { - if (enclosingFunctionFlags & 2 && enclosingFunctionFlags & 1) { - return ts.setOriginalNode(ts.setTextRange(ts.createYield(createAwaitHelper(context, ts.visitNode(node.expression, visitor, ts.isExpression))), node), node); + if (enclosingFunctionFlags & 2 /* Async */ && enclosingFunctionFlags & 1 /* Generator */) { + return ts.setOriginalNode(ts.setTextRange(ts.createYield(createAwaitHelper(context, ts.visitNode(node.expression, visitor, ts.isExpression))), + /*location*/ node), node); } return ts.visitEachChild(node, visitor, context); } function visitYieldExpression(node) { - if (enclosingFunctionFlags & 2 && enclosingFunctionFlags & 1) { + if (enclosingFunctionFlags & 2 /* Async */ && enclosingFunctionFlags & 1 /* Generator */) { if (node.asteriskToken) { var expression = ts.visitNode(node.expression, visitor, ts.isExpression); return ts.setOriginalNode(ts.setTextRange(ts.createYield(createAwaitHelper(context, ts.updateYield(node, node.asteriskToken, createAsyncDelegatorHelper(context, createAsyncValuesHelper(context, expression, expression), expression)))), node), node); @@ -55106,15 +65025,15 @@ var ts; return ts.visitEachChild(node, visitor, context); } function visitReturnStatement(node) { - if (enclosingFunctionFlags & 2 && enclosingFunctionFlags & 1) { + if (enclosingFunctionFlags & 2 /* Async */ && enclosingFunctionFlags & 1 /* Generator */) { return ts.updateReturn(node, createDownlevelAwait(node.expression ? ts.visitNode(node.expression, visitor, ts.isExpression) : ts.createVoidZero())); } return ts.visitEachChild(node, visitor, context); } function visitLabeledStatement(node) { - if (enclosingFunctionFlags & 2) { + if (enclosingFunctionFlags & 2 /* Async */) { var statement = ts.unwrapInnermostStatementOfLabel(node); - if (statement.kind === 222 && statement.awaitModifier) { + if (statement.kind === 222 /* ForOfStatement */ && statement.awaitModifier) { return visitForOfStatement(statement, node); } return ts.restoreEnclosingLabel(ts.visitEachChild(statement, visitor, context), node); @@ -55126,7 +65045,7 @@ var ts; var objects = []; for (var _i = 0, elements_4 = elements; _i < elements_4.length; _i++) { var e = elements_4[_i]; - if (e.kind === 272) { + if (e.kind === 272 /* SpreadAssignment */) { if (chunkObject) { objects.push(ts.createObjectLiteral(chunkObject)); chunkObject = undefined; @@ -55135,7 +65054,7 @@ var ts; objects.push(ts.visitNode(target, visitor, ts.isExpression)); } else { - chunkObject = ts.append(chunkObject, e.kind === 270 + chunkObject = ts.append(chunkObject, e.kind === 270 /* PropertyAssignment */ ? ts.createPropertyAssignment(e.name, ts.visitNode(e.initializer, visitor, ts.isExpression)) : ts.visitNode(e, visitor, ts.isObjectLiteralElementLike)); } @@ -55146,9 +65065,14 @@ var ts; return objects; } function visitObjectLiteralExpression(node) { - if (node.transformFlags & 1048576) { + if (node.transformFlags & 1048576 /* ContainsObjectSpread */) { + // spread elements emit like so: + // non-spread elements are chunked together into object literals, and then all are passed to __assign: + // { a, ...o, b } => __assign({a}, o, {b}); + // If the first element is a spread element, then the first argument to __assign is {}: + // { ...o, a, b, ...o2 } => __assign({}, o, {a, b}, o2) var objects = chunkObjectLiteralElements(node.properties); - if (objects.length && objects[0].kind !== 184) { + if (objects.length && objects[0].kind !== 184 /* ObjectLiteralExpression */) { objects.unshift(ts.createObjectLiteral()); } return createAssignHelper(context, objects); @@ -55163,22 +65087,33 @@ var ts; } function visitCatchClause(node) { if (!node.variableDeclaration) { - return ts.updateCatchClause(node, ts.createVariableDeclaration(ts.createTempVariable(undefined)), ts.visitNode(node.block, visitor, ts.isBlock)); + return ts.updateCatchClause(node, ts.createVariableDeclaration(ts.createTempVariable(/*recordTempVariable*/ undefined)), ts.visitNode(node.block, visitor, ts.isBlock)); } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a BinaryExpression that contains a destructuring assignment. + * + * @param node A BinaryExpression node. + */ function visitBinaryExpression(node, noDestructuringValue) { - if (ts.isDestructuringAssignment(node) && node.left.transformFlags & 1048576) { - return ts.flattenDestructuringAssignment(node, visitor, context, 1, !noDestructuringValue); + if (ts.isDestructuringAssignment(node) && node.left.transformFlags & 1048576 /* ContainsObjectRest */) { + return ts.flattenDestructuringAssignment(node, visitor, context, 1 /* ObjectRest */, !noDestructuringValue); } - else if (node.operatorToken.kind === 26) { + else if (node.operatorToken.kind === 26 /* CommaToken */) { return ts.updateBinary(node, ts.visitNode(node.left, visitorNoDestructuringValue, ts.isExpression), ts.visitNode(node.right, noDestructuringValue ? visitorNoDestructuringValue : visitor, ts.isExpression)); } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a VariableDeclaration node with a binding pattern. + * + * @param node A VariableDeclaration node. + */ function visitVariableDeclaration(node) { - if (ts.isBindingPattern(node.name) && node.name.transformFlags & 1048576) { - return ts.flattenDestructuringBinding(node, visitor, context, 1); + // If we are here it is because the name contains a binding pattern with a rest somewhere in it. + if (ts.isBindingPattern(node.name) && node.name.transformFlags & 1048576 /* ContainsObjectRest */) { + return ts.flattenDestructuringBinding(node, visitor, context, 1 /* ObjectRest */); } return ts.visitEachChild(node, visitor, context); } @@ -55188,8 +65123,13 @@ var ts; function visitVoidExpression(node) { return ts.visitEachChild(node, visitorNoDestructuringValue, context); } + /** + * Visits a ForOfStatement and converts it into a ES2015-compatible ForOfStatement. + * + * @param node A ForOfStatement. + */ function visitForOfStatement(node, outermostLabeledStatement) { - if (node.initializer.transformFlags & 1048576) { + if (node.initializer.transformFlags & 1048576 /* ContainsObjectRest */) { node = transformForOfStatementWithObjectRest(node); } if (node.awaitModifier) { @@ -55204,7 +65144,7 @@ var ts; if (ts.isVariableDeclarationList(initializerWithoutParens) || ts.isAssignmentPattern(initializerWithoutParens)) { var bodyLocation = void 0; var statementsLocation = void 0; - var temp = ts.createTempVariable(undefined); + var temp = ts.createTempVariable(/*recordTempVariable*/ undefined); var statements = [ts.createForOfBindingStatement(initializerWithoutParens, temp)]; if (ts.isBlock(node.statement)) { ts.addRange(statements, node.statement.statements); @@ -55218,7 +65158,8 @@ var ts; } return ts.updateForOf(node, node.awaitModifier, ts.setTextRange(ts.createVariableDeclarationList([ ts.setTextRange(ts.createVariableDeclaration(temp), node.initializer) - ], 1), node.initializer), node.expression, ts.setTextRange(ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), statementsLocation), true), bodyLocation)); + ], 1 /* Let */), node.initializer), node.expression, ts.setTextRange(ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), statementsLocation), + /*multiLine*/ true), bodyLocation)); } return node; } @@ -55236,80 +65177,102 @@ var ts; else { statements.push(statement); } - return ts.setEmitFlags(ts.setTextRange(ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), statementsLocation), true), bodyLocation), 48 | 384); + return ts.setEmitFlags(ts.setTextRange(ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), statementsLocation), + /*multiLine*/ true), bodyLocation), 48 /* NoSourceMap */ | 384 /* NoTokenSourceMaps */); } function createDownlevelAwait(expression) { - return enclosingFunctionFlags & 1 - ? ts.createYield(undefined, createAwaitHelper(context, expression)) + return enclosingFunctionFlags & 1 /* Generator */ + ? ts.createYield(/*asteriskToken*/ undefined, createAwaitHelper(context, expression)) : ts.createAwait(expression); } function transformForAwaitOfStatement(node, outermostLabeledStatement) { var expression = ts.visitNode(node.expression, visitor, ts.isExpression); - var iterator = ts.isIdentifier(expression) ? ts.getGeneratedNameForNode(expression) : ts.createTempVariable(undefined); - var result = ts.isIdentifier(expression) ? ts.getGeneratedNameForNode(iterator) : ts.createTempVariable(undefined); + var iterator = ts.isIdentifier(expression) ? ts.getGeneratedNameForNode(expression) : ts.createTempVariable(/*recordTempVariable*/ undefined); + var result = ts.isIdentifier(expression) ? ts.getGeneratedNameForNode(iterator) : ts.createTempVariable(/*recordTempVariable*/ undefined); var errorRecord = ts.createUniqueName("e"); var catchVariable = ts.getGeneratedNameForNode(errorRecord); - var returnMethod = ts.createTempVariable(undefined); - var callValues = createAsyncValuesHelper(context, expression, node.expression); - var callNext = ts.createCall(ts.createPropertyAccess(iterator, "next"), undefined, []); + var returnMethod = ts.createTempVariable(/*recordTempVariable*/ undefined); + var callValues = createAsyncValuesHelper(context, expression, /*location*/ node.expression); + var callNext = ts.createCall(ts.createPropertyAccess(iterator, "next"), /*typeArguments*/ undefined, []); var getDone = ts.createPropertyAccess(result, "done"); var getValue = ts.createPropertyAccess(result, "value"); var callReturn = ts.createFunctionCall(returnMethod, iterator, []); hoistVariableDeclaration(errorRecord); hoistVariableDeclaration(returnMethod); - var forStatement = ts.setEmitFlags(ts.setTextRange(ts.createFor(ts.setEmitFlags(ts.setTextRange(ts.createVariableDeclarationList([ - ts.setTextRange(ts.createVariableDeclaration(iterator, undefined, callValues), node.expression), + var forStatement = ts.setEmitFlags(ts.setTextRange(ts.createFor( + /*initializer*/ ts.setEmitFlags(ts.setTextRange(ts.createVariableDeclarationList([ + ts.setTextRange(ts.createVariableDeclaration(iterator, /*type*/ undefined, callValues), node.expression), ts.createVariableDeclaration(result) - ]), node.expression), 2097152), ts.createComma(ts.createAssignment(result, createDownlevelAwait(callNext)), ts.createLogicalNot(getDone)), undefined, convertForOfStatementHead(node, getValue)), node), 256); + ]), node.expression), 2097152 /* NoHoisting */), + /*condition*/ ts.createComma(ts.createAssignment(result, createDownlevelAwait(callNext)), ts.createLogicalNot(getDone)), + /*incrementor*/ undefined, + /*statement*/ convertForOfStatementHead(node, getValue)), + /*location*/ node), 256 /* NoTokenTrailingSourceMaps */); return ts.createTry(ts.createBlock([ ts.restoreEnclosingLabel(forStatement, outermostLabeledStatement) ]), ts.createCatchClause(ts.createVariableDeclaration(catchVariable), ts.setEmitFlags(ts.createBlock([ ts.createStatement(ts.createAssignment(errorRecord, ts.createObjectLiteral([ ts.createPropertyAssignment("error", catchVariable) ]))) - ]), 1)), ts.createBlock([ - ts.createTry(ts.createBlock([ - ts.setEmitFlags(ts.createIf(ts.createLogicalAnd(ts.createLogicalAnd(result, ts.createLogicalNot(getDone)), ts.createAssignment(returnMethod, ts.createPropertyAccess(iterator, "return"))), ts.createStatement(createDownlevelAwait(callReturn))), 1) - ]), undefined, ts.setEmitFlags(ts.createBlock([ - ts.setEmitFlags(ts.createIf(errorRecord, ts.createThrow(ts.createPropertyAccess(errorRecord, "error"))), 1) - ]), 1)) + ]), 1 /* SingleLine */)), ts.createBlock([ + ts.createTry( + /*tryBlock*/ ts.createBlock([ + ts.setEmitFlags(ts.createIf(ts.createLogicalAnd(ts.createLogicalAnd(result, ts.createLogicalNot(getDone)), ts.createAssignment(returnMethod, ts.createPropertyAccess(iterator, "return"))), ts.createStatement(createDownlevelAwait(callReturn))), 1 /* SingleLine */) + ]), + /*catchClause*/ undefined, + /*finallyBlock*/ ts.setEmitFlags(ts.createBlock([ + ts.setEmitFlags(ts.createIf(errorRecord, ts.createThrow(ts.createPropertyAccess(errorRecord, "error"))), 1 /* SingleLine */) + ]), 1 /* SingleLine */)) ])); } function visitParameter(node) { - if (node.transformFlags & 1048576) { - return ts.updateParameter(node, undefined, undefined, node.dotDotDotToken, ts.getGeneratedNameForNode(node), undefined, undefined, ts.visitNode(node.initializer, visitor, ts.isExpression)); + if (node.transformFlags & 1048576 /* ContainsObjectRest */) { + // Binding patterns are converted into a generated name and are + // evaluated inside the function body. + return ts.updateParameter(node, + /*decorators*/ undefined, + /*modifiers*/ undefined, node.dotDotDotToken, ts.getGeneratedNameForNode(node), + /*questionToken*/ undefined, + /*type*/ undefined, ts.visitNode(node.initializer, visitor, ts.isExpression)); } return ts.visitEachChild(node, visitor, context); } function visitConstructorDeclaration(node) { var savedEnclosingFunctionFlags = enclosingFunctionFlags; - enclosingFunctionFlags = 0; - var updated = ts.updateConstructor(node, undefined, node.modifiers, ts.visitParameterList(node.parameters, visitor, context), transformFunctionBody(node)); + enclosingFunctionFlags = 0 /* Normal */; + var updated = ts.updateConstructor(node, + /*decorators*/ undefined, node.modifiers, ts.visitParameterList(node.parameters, visitor, context), transformFunctionBody(node)); enclosingFunctionFlags = savedEnclosingFunctionFlags; return updated; } function visitGetAccessorDeclaration(node) { var savedEnclosingFunctionFlags = enclosingFunctionFlags; - enclosingFunctionFlags = 0; - var updated = ts.updateGetAccessor(node, undefined, node.modifiers, ts.visitNode(node.name, visitor, ts.isPropertyName), ts.visitParameterList(node.parameters, visitor, context), undefined, transformFunctionBody(node)); + enclosingFunctionFlags = 0 /* Normal */; + var updated = ts.updateGetAccessor(node, + /*decorators*/ undefined, node.modifiers, ts.visitNode(node.name, visitor, ts.isPropertyName), ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, transformFunctionBody(node)); enclosingFunctionFlags = savedEnclosingFunctionFlags; return updated; } function visitSetAccessorDeclaration(node) { var savedEnclosingFunctionFlags = enclosingFunctionFlags; - enclosingFunctionFlags = 0; - var updated = ts.updateSetAccessor(node, undefined, node.modifiers, ts.visitNode(node.name, visitor, ts.isPropertyName), ts.visitParameterList(node.parameters, visitor, context), transformFunctionBody(node)); + enclosingFunctionFlags = 0 /* Normal */; + var updated = ts.updateSetAccessor(node, + /*decorators*/ undefined, node.modifiers, ts.visitNode(node.name, visitor, ts.isPropertyName), ts.visitParameterList(node.parameters, visitor, context), transformFunctionBody(node)); enclosingFunctionFlags = savedEnclosingFunctionFlags; return updated; } function visitMethodDeclaration(node) { var savedEnclosingFunctionFlags = enclosingFunctionFlags; enclosingFunctionFlags = ts.getFunctionFlags(node); - var updated = ts.updateMethod(node, undefined, enclosingFunctionFlags & 1 + var updated = ts.updateMethod(node, + /*decorators*/ undefined, enclosingFunctionFlags & 1 /* Generator */ ? ts.visitNodes(node.modifiers, visitorNoAsyncModifier, ts.isModifier) - : node.modifiers, enclosingFunctionFlags & 2 + : node.modifiers, enclosingFunctionFlags & 2 /* Async */ ? undefined - : node.asteriskToken, ts.visitNode(node.name, visitor, ts.isPropertyName), ts.visitNode(undefined, visitor, ts.isToken), undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, enclosingFunctionFlags & 2 && enclosingFunctionFlags & 1 + : node.asteriskToken, ts.visitNode(node.name, visitor, ts.isPropertyName), ts.visitNode(/*questionToken*/ undefined, visitor, ts.isToken), + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, enclosingFunctionFlags & 2 /* Async */ && enclosingFunctionFlags & 1 /* Generator */ ? transformAsyncGeneratorFunctionBody(node) : transformFunctionBody(node)); enclosingFunctionFlags = savedEnclosingFunctionFlags; @@ -55318,11 +65281,14 @@ var ts; function visitFunctionDeclaration(node) { var savedEnclosingFunctionFlags = enclosingFunctionFlags; enclosingFunctionFlags = ts.getFunctionFlags(node); - var updated = ts.updateFunctionDeclaration(node, undefined, enclosingFunctionFlags & 1 + var updated = ts.updateFunctionDeclaration(node, + /*decorators*/ undefined, enclosingFunctionFlags & 1 /* Generator */ ? ts.visitNodes(node.modifiers, visitorNoAsyncModifier, ts.isModifier) - : node.modifiers, enclosingFunctionFlags & 2 + : node.modifiers, enclosingFunctionFlags & 2 /* Async */ ? undefined - : node.asteriskToken, node.name, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, enclosingFunctionFlags & 2 && enclosingFunctionFlags & 1 + : node.asteriskToken, node.name, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, enclosingFunctionFlags & 2 /* Async */ && enclosingFunctionFlags & 1 /* Generator */ ? transformAsyncGeneratorFunctionBody(node) : transformFunctionBody(node)); enclosingFunctionFlags = savedEnclosingFunctionFlags; @@ -55331,18 +65297,22 @@ var ts; function visitArrowFunction(node) { var savedEnclosingFunctionFlags = enclosingFunctionFlags; enclosingFunctionFlags = ts.getFunctionFlags(node); - var updated = ts.updateArrowFunction(node, node.modifiers, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, node.equalsGreaterThanToken, transformFunctionBody(node)); + var updated = ts.updateArrowFunction(node, node.modifiers, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, node.equalsGreaterThanToken, transformFunctionBody(node)); enclosingFunctionFlags = savedEnclosingFunctionFlags; return updated; } function visitFunctionExpression(node) { var savedEnclosingFunctionFlags = enclosingFunctionFlags; enclosingFunctionFlags = ts.getFunctionFlags(node); - var updated = ts.updateFunctionExpression(node, enclosingFunctionFlags & 1 + var updated = ts.updateFunctionExpression(node, enclosingFunctionFlags & 1 /* Generator */ ? ts.visitNodes(node.modifiers, visitorNoAsyncModifier, ts.isModifier) - : node.modifiers, enclosingFunctionFlags & 2 + : node.modifiers, enclosingFunctionFlags & 2 /* Async */ ? undefined - : node.asteriskToken, node.name, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, enclosingFunctionFlags & 2 && enclosingFunctionFlags & 1 + : node.asteriskToken, node.name, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, enclosingFunctionFlags & 2 /* Async */ && enclosingFunctionFlags & 1 /* Generator */ ? transformAsyncGeneratorFunctionBody(node) : transformFunctionBody(node)); enclosingFunctionFlags = savedEnclosingFunctionFlags; @@ -55351,17 +65321,23 @@ var ts; function transformAsyncGeneratorFunctionBody(node) { resumeLexicalEnvironment(); var statements = []; - var statementOffset = ts.addPrologue(statements, node.body.statements, false, visitor); + var statementOffset = ts.addPrologue(statements, node.body.statements, /*ensureUseStrict*/ false, visitor); appendObjectRestAssignmentsIfNeeded(statements, node); - statements.push(ts.createReturn(createAsyncGeneratorHelper(context, ts.createFunctionExpression(undefined, ts.createToken(39), node.name && ts.getGeneratedNameForNode(node.name), undefined, [], undefined, ts.updateBlock(node.body, ts.visitLexicalEnvironment(node.body.statements, visitor, context, statementOffset)))))); + statements.push(ts.createReturn(createAsyncGeneratorHelper(context, ts.createFunctionExpression( + /*modifiers*/ undefined, ts.createToken(39 /* AsteriskToken */), node.name && ts.getGeneratedNameForNode(node.name), + /*typeParameters*/ undefined, + /*parameters*/ [], + /*type*/ undefined, ts.updateBlock(node.body, ts.visitLexicalEnvironment(node.body.statements, visitor, context, statementOffset)))))); ts.prependStatements(statements, endLexicalEnvironment()); var block = ts.updateBlock(node.body, statements); - if (languageVersion >= 2) { - if (resolver.getNodeCheckFlags(node) & 4096) { + // Minor optimization, emit `_super` helper to capture `super` access in an arrow. + // This step isn't needed if we eventually transform this to ES5. + if (languageVersion >= 2 /* ES2015 */) { + if (resolver.getNodeCheckFlags(node) & 4096 /* AsyncMethodWithSuperBinding */) { enableSubstitutionForAsyncMethodsWithSuper(); ts.addEmitHelper(block, ts.advancedAsyncSuperHelper); } - else if (resolver.getNodeCheckFlags(node) & 2048) { + else if (resolver.getNodeCheckFlags(node) & 2048 /* AsyncMethodWithSuper */) { enableSubstitutionForAsyncMethodsWithSuper(); ts.addEmitHelper(block, ts.asyncSuperHelper); } @@ -55374,12 +65350,12 @@ var ts; var statements = []; var body = ts.visitNode(node.body, visitor, ts.isConciseBody); if (ts.isBlock(body)) { - statementOffset = ts.addPrologue(statements, body.statements, false, visitor); + statementOffset = ts.addPrologue(statements, body.statements, /*ensureUseStrict*/ false, visitor); } - ts.addRange(statements, appendObjectRestAssignmentsIfNeeded(undefined, node)); + ts.addRange(statements, appendObjectRestAssignmentsIfNeeded(/*statements*/ undefined, node)); var leadingStatements = endLexicalEnvironment(); if (statementOffset > 0 || ts.some(statements) || ts.some(leadingStatements)) { - var block = ts.convertToFunctionBody(body, true); + var block = ts.convertToFunctionBody(body, /*multiLine*/ true); ts.prependStatements(statements, leadingStatements); ts.addRange(statements, block.statements.slice(statementOffset)); return ts.updateBlock(block, ts.setTextRange(ts.createNodeArray(statements), block.statements)); @@ -55389,12 +65365,15 @@ var ts; function appendObjectRestAssignmentsIfNeeded(statements, node) { for (var _i = 0, _a = node.parameters; _i < _a.length; _i++) { var parameter = _a[_i]; - if (parameter.transformFlags & 1048576) { + if (parameter.transformFlags & 1048576 /* ContainsObjectRest */) { var temp = ts.getGeneratedNameForNode(parameter); - var declarations = ts.flattenDestructuringBinding(parameter, visitor, context, 1, temp, false, true); + var declarations = ts.flattenDestructuringBinding(parameter, visitor, context, 1 /* ObjectRest */, temp, + /*doNotRecordTempVariablesInLine*/ false, + /*skipInitializer*/ true); if (ts.some(declarations)) { - var statement = ts.createVariableStatement(undefined, ts.createVariableDeclarationList(declarations)); - ts.setEmitFlags(statement, 1048576); + var statement = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList(declarations)); + ts.setEmitFlags(statement, 1048576 /* CustomPrologue */); statements = ts.append(statements, statement); } } @@ -55402,21 +65381,33 @@ var ts; return statements; } function enableSubstitutionForAsyncMethodsWithSuper() { - if ((enabledSubstitutions & 1) === 0) { - enabledSubstitutions |= 1; - context.enableSubstitution(187); - context.enableSubstitution(185); - context.enableSubstitution(186); - context.enableEmitNotification(235); - context.enableEmitNotification(154); - context.enableEmitNotification(156); - context.enableEmitNotification(157); - context.enableEmitNotification(155); + if ((enabledSubstitutions & 1 /* AsyncMethodsWithSuper */) === 0) { + enabledSubstitutions |= 1 /* AsyncMethodsWithSuper */; + // We need to enable substitutions for call, property access, and element access + // if we need to rewrite super calls. + context.enableSubstitution(187 /* CallExpression */); + context.enableSubstitution(185 /* PropertyAccessExpression */); + context.enableSubstitution(186 /* ElementAccessExpression */); + // We need to be notified when entering and exiting declarations that bind super. + context.enableEmitNotification(235 /* ClassDeclaration */); + context.enableEmitNotification(154 /* MethodDeclaration */); + context.enableEmitNotification(156 /* GetAccessor */); + context.enableEmitNotification(157 /* SetAccessor */); + context.enableEmitNotification(155 /* Constructor */); } } + /** + * Called by the printer just before a node is printed. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to be printed. + * @param emitCallback The callback used to emit the node. + */ function onEmitNode(hint, node, emitCallback) { - if (enabledSubstitutions & 1 && isSuperContainer(node)) { - var superContainerFlags = resolver.getNodeCheckFlags(node) & (2048 | 4096); + // If we need to support substitutions for `super` in an async method, + // we should track it here. + if (enabledSubstitutions & 1 /* AsyncMethodsWithSuper */ && isSuperContainer(node)) { + var superContainerFlags = resolver.getNodeCheckFlags(node) & (2048 /* AsyncMethodWithSuper */ | 4096 /* AsyncMethodWithSuperBinding */); if (superContainerFlags !== enclosingSuperContainerFlags) { var savedEnclosingSuperContainerFlags = enclosingSuperContainerFlags; enclosingSuperContainerFlags = superContainerFlags; @@ -55427,32 +65418,38 @@ var ts; } previousOnEmitNode(hint, node, emitCallback); } + /** + * Hooks node substitutions. + * + * @param hint The context for the emitter. + * @param node The node to substitute. + */ function onSubstituteNode(hint, node) { node = previousOnSubstituteNode(hint, node); - if (hint === 1 && enclosingSuperContainerFlags) { + if (hint === 1 /* Expression */ && enclosingSuperContainerFlags) { return substituteExpression(node); } return node; } function substituteExpression(node) { switch (node.kind) { - case 185: + case 185 /* PropertyAccessExpression */: return substitutePropertyAccessExpression(node); - case 186: + case 186 /* ElementAccessExpression */: return substituteElementAccessExpression(node); - case 187: + case 187 /* CallExpression */: return substituteCallExpression(node); } return node; } function substitutePropertyAccessExpression(node) { - if (node.expression.kind === 97) { + if (node.expression.kind === 97 /* SuperKeyword */) { return createSuperAccessInAsyncMethod(ts.createLiteral(ts.idText(node.name)), node); } return node; } function substituteElementAccessExpression(node) { - if (node.expression.kind === 97) { + if (node.expression.kind === 97 /* SuperKeyword */) { return createSuperAccessInAsyncMethod(node.argumentExpression, node); } return node; @@ -55463,7 +65460,8 @@ var ts; var argumentExpression = ts.isPropertyAccessExpression(expression) ? substitutePropertyAccessExpression(expression) : substituteElementAccessExpression(expression); - return ts.createCall(ts.createPropertyAccess(argumentExpression, "call"), undefined, [ + return ts.createCall(ts.createPropertyAccess(argumentExpression, "call"), + /*typeArguments*/ undefined, [ ts.createThis() ].concat(node.arguments)); } @@ -55471,18 +65469,20 @@ var ts; } function isSuperContainer(node) { var kind = node.kind; - return kind === 235 - || kind === 155 - || kind === 154 - || kind === 156 - || kind === 157; + return kind === 235 /* ClassDeclaration */ + || kind === 155 /* Constructor */ + || kind === 154 /* MethodDeclaration */ + || kind === 156 /* GetAccessor */ + || kind === 157 /* SetAccessor */; } function createSuperAccessInAsyncMethod(argumentExpression, location) { - if (enclosingSuperContainerFlags & 4096) { - return ts.setTextRange(ts.createPropertyAccess(ts.createCall(ts.createIdentifier("_super"), undefined, [argumentExpression]), "value"), location); + if (enclosingSuperContainerFlags & 4096 /* AsyncMethodWithSuperBinding */) { + return ts.setTextRange(ts.createPropertyAccess(ts.createCall(ts.createIdentifier("_super"), + /*typeArguments*/ undefined, [argumentExpression]), "value"), location); } else { - return ts.setTextRange(ts.createCall(ts.createIdentifier("_super"), undefined, [argumentExpression]), location); + return ts.setTextRange(ts.createCall(ts.createIdentifier("_super"), + /*typeArguments*/ undefined, [argumentExpression]), location); } } } @@ -55491,14 +65491,16 @@ var ts; name: "typescript:assign", scoped: false, priority: 1, - text: "\n var __assign = (this && this.__assign) || Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };" + text: "\n var __assign = (this && this.__assign) || function () {\n __assign = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign.apply(this, arguments);\n };" }; function createAssignHelper(context, attributesSegments) { - if (context.getCompilerOptions().target >= 2) { - return ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Object"), "assign"), undefined, attributesSegments); + if (context.getCompilerOptions().target >= 2 /* ES2015 */) { + return ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Object"), "assign"), + /*typeArguments*/ undefined, attributesSegments); } context.requestEmitHelper(assignHelper); - return ts.createCall(ts.getHelperName("__assign"), undefined, attributesSegments); + return ts.createCall(ts.getHelperName("__assign"), + /*typeArguments*/ undefined, attributesSegments); } ts.createAssignHelper = createAssignHelper; var awaitHelper = { @@ -55508,7 +65510,7 @@ var ts; }; function createAwaitHelper(context, expression) { context.requestEmitHelper(awaitHelper); - return ts.createCall(ts.getHelperName("__await"), undefined, [expression]); + return ts.createCall(ts.getHelperName("__await"), /*typeArguments*/ undefined, [expression]); } var asyncGeneratorHelper = { name: "typescript:asyncGenerator", @@ -55518,8 +65520,10 @@ var ts; function createAsyncGeneratorHelper(context, generatorFunc) { context.requestEmitHelper(awaitHelper); context.requestEmitHelper(asyncGeneratorHelper); - (generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= 262144; - return ts.createCall(ts.getHelperName("__asyncGenerator"), undefined, [ + // Mark this node as originally an async function + (generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= 262144 /* AsyncFunctionBody */; + return ts.createCall(ts.getHelperName("__asyncGenerator"), + /*typeArguments*/ undefined, [ ts.createThis(), ts.createIdentifier("arguments"), generatorFunc @@ -55533,7 +65537,8 @@ var ts; function createAsyncDelegatorHelper(context, expression, location) { context.requestEmitHelper(awaitHelper); context.requestEmitHelper(asyncDelegator); - return ts.setTextRange(ts.createCall(ts.getHelperName("__asyncDelegator"), undefined, [expression]), location); + return ts.setTextRange(ts.createCall(ts.getHelperName("__asyncDelegator"), + /*typeArguments*/ undefined, [expression]), location); } var asyncValues = { name: "typescript:asyncValues", @@ -55542,15 +65547,22 @@ var ts; }; function createAsyncValuesHelper(context, expression, location) { context.requestEmitHelper(asyncValues); - return ts.setTextRange(ts.createCall(ts.getHelperName("__asyncValues"), undefined, [expression]), location); + return ts.setTextRange(ts.createCall(ts.getHelperName("__asyncValues"), + /*typeArguments*/ undefined, [expression]), location); } })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { function transformJsx(context) { var compilerOptions = context.getCompilerOptions(); var currentSourceFile; return ts.chainBundle(transformSourceFile); + /** + * Transform JSX-specific syntax in a SourceFile. + * + * @param node A SourceFile node. + */ function transformSourceFile(node) { if (node.isDeclarationFile) { return node; @@ -55561,7 +65573,7 @@ var ts; return visited; } function visitor(node) { - if (node.transformFlags & 4) { + if (node.transformFlags & 4 /* ContainsJsx */) { return visitorWorker(node); } else { @@ -55570,13 +65582,13 @@ var ts; } function visitorWorker(node) { switch (node.kind) { - case 255: - return visitJsxElement(node, false); - case 256: - return visitJsxSelfClosingElement(node, false); - case 259: - return visitJsxFragment(node, false); - case 265: + case 255 /* JsxElement */: + return visitJsxElement(node, /*isChild*/ false); + case 256 /* JsxSelfClosingElement */: + return visitJsxSelfClosingElement(node, /*isChild*/ false); + case 259 /* JsxFragment */: + return visitJsxFragment(node, /*isChild*/ false); + case 265 /* JsxExpression */: return visitJsxExpression(node); default: return ts.visitEachChild(node, visitor, context); @@ -55584,56 +65596,65 @@ var ts; } function transformJsxChildToExpression(node) { switch (node.kind) { - case 10: + case 10 /* JsxText */: return visitJsxText(node); - case 265: + case 265 /* JsxExpression */: return visitJsxExpression(node); - case 255: - return visitJsxElement(node, true); - case 256: - return visitJsxSelfClosingElement(node, true); - case 259: - return visitJsxFragment(node, true); + case 255 /* JsxElement */: + return visitJsxElement(node, /*isChild*/ true); + case 256 /* JsxSelfClosingElement */: + return visitJsxSelfClosingElement(node, /*isChild*/ true); + case 259 /* JsxFragment */: + return visitJsxFragment(node, /*isChild*/ true); default: return ts.Debug.failBadSyntaxKind(node); } } function visitJsxElement(node, isChild) { - return visitJsxOpeningLikeElement(node.openingElement, node.children, isChild, node); + return visitJsxOpeningLikeElement(node.openingElement, node.children, isChild, /*location*/ node); } function visitJsxSelfClosingElement(node, isChild) { - return visitJsxOpeningLikeElement(node, undefined, isChild, node); + return visitJsxOpeningLikeElement(node, /*children*/ undefined, isChild, /*location*/ node); } function visitJsxFragment(node, isChild) { - return visitJsxOpeningFragment(node.openingFragment, node.children, isChild, node); + return visitJsxOpeningFragment(node.openingFragment, node.children, isChild, /*location*/ node); } function visitJsxOpeningLikeElement(node, children, isChild, location) { var tagName = getTagName(node); var objectProperties; var attrs = node.attributes.properties; if (attrs.length === 0) { + // When there are no attributes, React wants "null" objectProperties = ts.createNull(); } else { + // Map spans of JsxAttribute nodes into object literals and spans + // of JsxSpreadAttribute nodes into expressions. var segments = ts.flatten(ts.spanMap(attrs, ts.isJsxSpreadAttribute, function (attrs, isSpread) { return isSpread ? ts.map(attrs, transformJsxSpreadAttributeToExpression) : ts.createObjectLiteral(ts.map(attrs, transformJsxAttributeToObjectLiteralElement)); })); if (ts.isJsxSpreadAttribute(attrs[0])) { + // We must always emit at least one object literal before a spread + // argument. segments.unshift(ts.createObjectLiteral()); } + // Either emit one big object literal (no spread attribs), or + // a call to the __assign helper. objectProperties = ts.singleOrUndefined(segments); if (!objectProperties) { objectProperties = ts.createAssignHelper(context, segments); } } - var element = ts.createExpressionForJsxElement(context.getEmitResolver().getJsxFactoryEntity(currentSourceFile), compilerOptions.reactNamespace, tagName, objectProperties, ts.mapDefined(children, transformJsxChildToExpression), node, location); + var element = ts.createExpressionForJsxElement(context.getEmitResolver().getJsxFactoryEntity(currentSourceFile), compilerOptions.reactNamespace, // TODO: GH#18217 + tagName, objectProperties, ts.mapDefined(children, transformJsxChildToExpression), node, location); if (isChild) { ts.startOnNewLine(element); } return element; } function visitJsxOpeningFragment(node, children, isChild, location) { - var element = ts.createExpressionForJsxFragment(context.getEmitResolver().getJsxFactoryEntity(currentSourceFile), compilerOptions.reactNamespace, ts.mapDefined(children, transformJsxChildToExpression), node, location); + var element = ts.createExpressionForJsxFragment(context.getEmitResolver().getJsxFactoryEntity(currentSourceFile), compilerOptions.reactNamespace, // TODO: GH#18217 + ts.mapDefined(children, transformJsxChildToExpression), node, location); if (isChild) { ts.startOnNewLine(element); } @@ -55651,12 +65672,14 @@ var ts; if (node === undefined) { return ts.createTrue(); } - else if (node.kind === 9) { + else if (node.kind === 9 /* StringLiteral */) { + // Always recreate the literal to escape any escape sequences or newlines which may be in the original jsx string and which + // Need to be escaped to be handled correctly in a normal string var literal = ts.createLiteral(tryDecodeEntities(node.text) || node.text); literal.singleQuote = node.singleQuote !== undefined ? node.singleQuote : !ts.isStringDoubleQuoted(node, currentSourceFile); return ts.setTextRange(literal, node); } - else if (node.kind === 265) { + else if (node.kind === 265 /* JsxExpression */) { if (node.expression === undefined) { return ts.createTrue(); } @@ -55667,19 +65690,43 @@ var ts; } } function visitJsxText(node) { - var fixed = fixupWhitespaceAndDecodeEntities(ts.getTextOfNode(node, true)); + var fixed = fixupWhitespaceAndDecodeEntities(ts.getTextOfNode(node, /*includeTrivia*/ true)); return fixed === undefined ? undefined : ts.createLiteral(fixed); } + /** + * 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 + * See also https://www.w3.org/TR/html4/struct/text.html#h-9.1 and https://www.w3.org/TR/CSS2/text.html#white-space-model + * + * An equivalent algorithm would be: + * - If there is only one line, return it. + * - If there is only whitespace (but multiple lines), return `undefined`. + * - Split the text into lines. + * - 'trimRight' the first line, 'trimLeft' the last line, 'trim' middle lines. + * - Decode entities on each line (individually). + * - Remove empty lines and join the rest with " ". + */ function fixupWhitespaceAndDecodeEntities(text) { var acc; + // First non-whitespace character on this line. var firstNonWhitespace = 0; + // Last non-whitespace character on this line. var lastNonWhitespace = -1; + // These initial values are special because the first line is: + // firstNonWhitespace = 0 to indicate that we want leading whitsepace, + // but lastNonWhitespace = -1 as a special flag to indicate that we *don't* include the line if it's all whitespace. for (var i = 0; i < text.length; i++) { var c = text.charCodeAt(i); if (ts.isLineBreak(c)) { + // If we've seen any non-whitespace characters on this line, add the 'trim' of the line. + // (lastNonWhitespace === -1 is a special flag to detect whether the first line is all whitespace.) if (firstNonWhitespace !== -1 && lastNonWhitespace !== -1) { acc = addLineOfJsxText(acc, text.substr(firstNonWhitespace, lastNonWhitespace - firstNonWhitespace + 1)); } + // Reset firstNonWhitespace for the next line. + // Don't bother to reset lastNonWhitespace because we ignore it if firstNonWhitespace = -1. firstNonWhitespace = -1; } else if (!ts.isWhiteSpaceSingleLine(c)) { @@ -55690,13 +65737,21 @@ var ts; } } return firstNonWhitespace !== -1 + // Last line had a non-whitespace character. Emit the 'trimLeft', meaning keep trailing whitespace. ? addLineOfJsxText(acc, text.substr(firstNonWhitespace)) + // Last line was all whitespace, so ignore it : acc; } function addLineOfJsxText(acc, trimmedLine) { + // We do not escape the string here as that is handled by the printer + // when it emits the literal. We do, however, need to decode JSX entities. var decoded = decodeEntities(trimmedLine); return acc === undefined ? decoded : acc + " " + decoded; } + /** + * Replace entities like " ", "{", and "�" with the characters they encode. + * See https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references + */ function decodeEntities(text) { return text.replace(/&((#((\d+)|x([\da-fA-F]+)))|(\w+));/g, function (match, _all, _number, _digits, decimal, hex, word) { if (decimal) { @@ -55707,16 +65762,18 @@ var ts; } else { var ch = entities.get(word); + // If this is not a valid entity, then just use `match` (replace it with itself, i.e. don't replace) return ch ? String.fromCharCode(ch) : match; } }); } + /** Like `decodeEntities` but returns `undefined` if there were no entities to decode. */ function tryDecodeEntities(text) { var decoded = decodeEntities(text); return decoded === text ? undefined : decoded; } function getTagName(node) { - if (node.kind === 255) { + if (node.kind === 255 /* JsxElement */) { return getTagName(node.openingElement); } else { @@ -55729,6 +65786,11 @@ var ts; } } } + /** + * 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) { var name = node.name; var text = ts.idText(name); @@ -56000,6 +66062,7 @@ var ts; diams: 0x2666 }); })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { function transformES2016(context) { @@ -56012,11 +66075,11 @@ var ts; return ts.visitEachChild(node, visitor, context); } function visitor(node) { - if ((node.transformFlags & 32) === 0) { + if ((node.transformFlags & 32 /* ContainsES2016 */) === 0) { return node; } switch (node.kind) { - case 200: + case 200 /* BinaryExpression */: return visitBinaryExpression(node); default: return ts.visitEachChild(node, visitor, context); @@ -56024,9 +66087,9 @@ var ts; } function visitBinaryExpression(node) { switch (node.operatorToken.kind) { - case 62: + case 62 /* AsteriskAsteriskEqualsToken */: return visitExponentiationAssignmentExpression(node); - case 40: + case 40 /* AsteriskAsteriskToken */: return visitExponentiationExpression(node); default: return ts.visitEachChild(node, visitor, context); @@ -56038,35 +66101,42 @@ var ts; var left = ts.visitNode(node.left, visitor, ts.isExpression); var right = ts.visitNode(node.right, visitor, ts.isExpression); if (ts.isElementAccessExpression(left)) { + // Transforms `a[x] **= b` into `(_a = a)[_x = x] = Math.pow(_a[_x], b)` var expressionTemp = ts.createTempVariable(hoistVariableDeclaration); var argumentExpressionTemp = ts.createTempVariable(hoistVariableDeclaration); target = ts.setTextRange(ts.createElementAccess(ts.setTextRange(ts.createAssignment(expressionTemp, left.expression), left.expression), ts.setTextRange(ts.createAssignment(argumentExpressionTemp, left.argumentExpression), left.argumentExpression)), left); value = ts.setTextRange(ts.createElementAccess(expressionTemp, argumentExpressionTemp), left); } else if (ts.isPropertyAccessExpression(left)) { + // Transforms `a.x **= b` into `(_a = a).x = Math.pow(_a.x, b)` var expressionTemp = ts.createTempVariable(hoistVariableDeclaration); target = ts.setTextRange(ts.createPropertyAccess(ts.setTextRange(ts.createAssignment(expressionTemp, left.expression), left.expression), left.name), left); value = ts.setTextRange(ts.createPropertyAccess(expressionTemp, left.name), left); } else { + // Transforms `a **= b` into `a = Math.pow(a, b)` target = left; value = left; } - return ts.setTextRange(ts.createAssignment(target, ts.createMathPow(value, right, node)), node); + return ts.setTextRange(ts.createAssignment(target, ts.createMathPow(value, right, /*location*/ node)), node); } function visitExponentiationExpression(node) { + // Transforms `a ** b` into `Math.pow(a, b)` var left = ts.visitNode(node.left, visitor, ts.isExpression); var right = ts.visitNode(node.right, visitor, ts.isExpression); - return ts.createMathPow(left, right, node); + return ts.createMathPow(left, right, /*location*/ node); } } ts.transformES2016 = transformES2016; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { var ES2015SubstitutionFlags; (function (ES2015SubstitutionFlags) { + /** Enables substitutions for captured `this` */ ES2015SubstitutionFlags[ES2015SubstitutionFlags["CapturedThis"] = 1] = "CapturedThis"; + /** Enables substitutions for block-scoped bindings. */ ES2015SubstitutionFlags[ES2015SubstitutionFlags["BlockScopedBindings"] = 2] = "BlockScopedBindings"; })(ES2015SubstitutionFlags || (ES2015SubstitutionFlags = {})); var CopyDirection; @@ -56082,13 +66152,35 @@ var ts; })(Jump || (Jump = {})); var SuperCaptureResult; (function (SuperCaptureResult) { + /** + * A capture may have been added for calls to 'super', but + * the caller should emit subsequent statements normally. + */ SuperCaptureResult[SuperCaptureResult["NoReplacement"] = 0] = "NoReplacement"; + /** + * A call to 'super()' got replaced with a capturing statement like: + * + * var _this = _super.call(...) || this; + * + * Callers should skip the current statement. + */ SuperCaptureResult[SuperCaptureResult["ReplaceSuperCapture"] = 1] = "ReplaceSuperCapture"; + /** + * A call to 'super()' got replaced with a capturing statement like: + * + * return _super.call(...) || this; + * + * Callers should skip the current statement and avoid any returns of '_this'. + */ SuperCaptureResult[SuperCaptureResult["ReplaceWithReturn"] = 2] = "ReplaceWithReturn"; })(SuperCaptureResult || (SuperCaptureResult = {})); + // Facts we track as we traverse the tree var HierarchyFacts; (function (HierarchyFacts) { HierarchyFacts[HierarchyFacts["None"] = 0] = "None"; + // + // Ancestor facts + // HierarchyFacts[HierarchyFacts["Function"] = 1] = "Function"; HierarchyFacts[HierarchyFacts["ArrowFunction"] = 2] = "ArrowFunction"; HierarchyFacts[HierarchyFacts["AsyncFunctionBody"] = 4] = "AsyncFunctionBody"; @@ -56103,33 +66195,58 @@ var ts; HierarchyFacts[HierarchyFacts["ForInOrForOfStatement"] = 2048] = "ForInOrForOfStatement"; HierarchyFacts[HierarchyFacts["ConstructorWithCapturedSuper"] = 4096] = "ConstructorWithCapturedSuper"; HierarchyFacts[HierarchyFacts["ComputedPropertyName"] = 8192] = "ComputedPropertyName"; + // NOTE: do not add more ancestor flags without also updating AncestorFactsMask below. + // + // Ancestor masks + // HierarchyFacts[HierarchyFacts["AncestorFactsMask"] = 16383] = "AncestorFactsMask"; + // We are always in *some* kind of block scope, but only specific block-scope containers are + // top-level or Blocks. HierarchyFacts[HierarchyFacts["BlockScopeIncludes"] = 0] = "BlockScopeIncludes"; HierarchyFacts[HierarchyFacts["BlockScopeExcludes"] = 4032] = "BlockScopeExcludes"; + // A source file is a top-level block scope. HierarchyFacts[HierarchyFacts["SourceFileIncludes"] = 64] = "SourceFileIncludes"; HierarchyFacts[HierarchyFacts["SourceFileExcludes"] = 3968] = "SourceFileExcludes"; + // Functions, methods, and accessors are both new lexical scopes and new block scopes. HierarchyFacts[HierarchyFacts["FunctionIncludes"] = 65] = "FunctionIncludes"; HierarchyFacts[HierarchyFacts["FunctionExcludes"] = 16286] = "FunctionExcludes"; HierarchyFacts[HierarchyFacts["AsyncFunctionBodyIncludes"] = 69] = "AsyncFunctionBodyIncludes"; HierarchyFacts[HierarchyFacts["AsyncFunctionBodyExcludes"] = 16278] = "AsyncFunctionBodyExcludes"; + // Arrow functions are lexically scoped to their container, but are new block scopes. HierarchyFacts[HierarchyFacts["ArrowFunctionIncludes"] = 66] = "ArrowFunctionIncludes"; HierarchyFacts[HierarchyFacts["ArrowFunctionExcludes"] = 16256] = "ArrowFunctionExcludes"; + // Constructors are both new lexical scopes and new block scopes. Constructors are also + // always considered non-static members of a class. HierarchyFacts[HierarchyFacts["ConstructorIncludes"] = 73] = "ConstructorIncludes"; HierarchyFacts[HierarchyFacts["ConstructorExcludes"] = 16278] = "ConstructorExcludes"; + // 'do' and 'while' statements are not block scopes. We track that the subtree is contained + // within an IterationStatement to indicate whether the embedded statement is an + // IterationStatementBlock. HierarchyFacts[HierarchyFacts["DoOrWhileStatementIncludes"] = 256] = "DoOrWhileStatementIncludes"; HierarchyFacts[HierarchyFacts["DoOrWhileStatementExcludes"] = 0] = "DoOrWhileStatementExcludes"; + // 'for' statements are new block scopes and have special handling for 'let' declarations. HierarchyFacts[HierarchyFacts["ForStatementIncludes"] = 1280] = "ForStatementIncludes"; HierarchyFacts[HierarchyFacts["ForStatementExcludes"] = 3008] = "ForStatementExcludes"; + // 'for-in' and 'for-of' statements are new block scopes and have special handling for + // 'let' declarations. HierarchyFacts[HierarchyFacts["ForInOrForOfStatementIncludes"] = 2304] = "ForInOrForOfStatementIncludes"; HierarchyFacts[HierarchyFacts["ForInOrForOfStatementExcludes"] = 1984] = "ForInOrForOfStatementExcludes"; + // Blocks (other than function bodies) are new block scopes. HierarchyFacts[HierarchyFacts["BlockIncludes"] = 128] = "BlockIncludes"; HierarchyFacts[HierarchyFacts["BlockExcludes"] = 3904] = "BlockExcludes"; HierarchyFacts[HierarchyFacts["IterationStatementBlockIncludes"] = 512] = "IterationStatementBlockIncludes"; HierarchyFacts[HierarchyFacts["IterationStatementBlockExcludes"] = 4032] = "IterationStatementBlockExcludes"; + // Computed property names track subtree flags differently than their containing members. HierarchyFacts[HierarchyFacts["ComputedPropertyNameIncludes"] = 8192] = "ComputedPropertyNameIncludes"; HierarchyFacts[HierarchyFacts["ComputedPropertyNameExcludes"] = 0] = "ComputedPropertyNameExcludes"; + // + // Subtree facts + // HierarchyFacts[HierarchyFacts["NewTarget"] = 16384] = "NewTarget"; HierarchyFacts[HierarchyFacts["NewTargetInComputedPropertyName"] = 32768] = "NewTargetInComputedPropertyName"; + // + // Subtree masks + // HierarchyFacts[HierarchyFacts["SubtreeFactsMask"] = -16384] = "SubtreeFactsMask"; HierarchyFacts[HierarchyFacts["PropagateNewTargetMask"] = 49152] = "PropagateNewTargetMask"; })(HierarchyFacts || (HierarchyFacts = {})); @@ -56148,7 +66265,15 @@ var ts; function recordTaggedTemplateString(temp) { taggedTemplateStringDeclarations = ts.append(taggedTemplateStringDeclarations, ts.createVariableDeclaration(temp)); } + /** + * Used to track if we are emitting body of the converted loop + */ var convertedLoopState; + /** + * Keeps track of whether substitutions have been enabled for specific cases. + * They are persisted between each SourceFile transformation and should not + * be reset. + */ var enabledSubstitutions; return ts.chainBundle(transformSourceFile); function transformSourceFile(node) { @@ -56162,28 +66287,40 @@ var ts; currentSourceFile = undefined; currentText = undefined; taggedTemplateStringDeclarations = undefined; - hierarchyFacts = 0; + hierarchyFacts = 0 /* None */; return visited; } + /** + * Sets the `HierarchyFacts` for this node prior to visiting this node's subtree, returning the facts set prior to modification. + * @param excludeFacts The existing `HierarchyFacts` to reset before visiting the subtree. + * @param includeFacts The new `HierarchyFacts` to set before visiting the subtree. + */ function enterSubtree(excludeFacts, includeFacts) { var ancestorFacts = hierarchyFacts; - hierarchyFacts = (hierarchyFacts & ~excludeFacts | includeFacts) & 16383; + hierarchyFacts = (hierarchyFacts & ~excludeFacts | includeFacts) & 16383 /* AncestorFactsMask */; return ancestorFacts; } + /** + * Restores the `HierarchyFacts` for this node's ancestor after visiting this node's + * subtree, propagating specific facts from the subtree. + * @param ancestorFacts The `HierarchyFacts` of the ancestor to restore after visiting the subtree. + * @param excludeFacts The existing `HierarchyFacts` of the subtree that should not be propagated. + * @param includeFacts The new `HierarchyFacts` of the subtree that should be propagated. + */ function exitSubtree(ancestorFacts, excludeFacts, includeFacts) { - hierarchyFacts = (hierarchyFacts & ~excludeFacts | includeFacts) & -16384 | ancestorFacts; + hierarchyFacts = (hierarchyFacts & ~excludeFacts | includeFacts) & -16384 /* SubtreeFactsMask */ | ancestorFacts; } function isReturnVoidStatementInConstructorWithCapturedSuper(node) { - return (hierarchyFacts & 4096) !== 0 - && node.kind === 225 + return (hierarchyFacts & 4096 /* ConstructorWithCapturedSuper */) !== 0 + && node.kind === 225 /* ReturnStatement */ && !node.expression; } function shouldVisitNode(node) { - return (node.transformFlags & 128) !== 0 + return (node.transformFlags & 128 /* ContainsES2015 */) !== 0 || convertedLoopState !== undefined - || (hierarchyFacts & 4096 && (ts.isStatement(node) || (node.kind === 213))) - || (ts.isIterationStatement(node, false) && shouldConvertIterationStatementBody(node)) - || (ts.getEmitFlags(node) & 33554432) !== 0; + || (hierarchyFacts & 4096 /* ConstructorWithCapturedSuper */ && (ts.isStatement(node) || (node.kind === 213 /* Block */))) + || (ts.isIterationStatement(node, /*lookInLabeledStatements*/ false) && shouldConvertIterationStatementBody(node)) + || (ts.getEmitFlags(node) & 33554432 /* TypeScriptClassWrapper */) !== 0; } function visitor(node) { if (shouldVisitNode(node)) { @@ -56195,133 +66332,134 @@ var ts; } function functionBodyVisitor(node) { if (shouldVisitNode(node)) { - return visitBlock(node, true); + return visitBlock(node, /*isFunctionBody*/ true); } return node; } function callExpressionVisitor(node) { - if (node.kind === 97) { - return visitSuperKeyword(true); + if (node.kind === 97 /* SuperKeyword */) { + return visitSuperKeyword(/*isExpressionOfCall*/ true); } return visitor(node); } function visitJavaScript(node) { switch (node.kind) { - case 115: - return undefined; - case 235: + case 115 /* StaticKeyword */: + return undefined; // elide static keyword + case 235 /* ClassDeclaration */: return visitClassDeclaration(node); - case 205: + case 205 /* ClassExpression */: return visitClassExpression(node); - case 149: + case 149 /* Parameter */: return visitParameter(node); - case 234: + case 234 /* FunctionDeclaration */: return visitFunctionDeclaration(node); - case 193: + case 193 /* ArrowFunction */: return visitArrowFunction(node); - case 192: + case 192 /* FunctionExpression */: return visitFunctionExpression(node); - case 232: + case 232 /* VariableDeclaration */: return visitVariableDeclaration(node); - case 71: + case 71 /* Identifier */: return visitIdentifier(node); - case 233: + case 233 /* VariableDeclarationList */: return visitVariableDeclarationList(node); - case 227: + case 227 /* SwitchStatement */: return visitSwitchStatement(node); - case 241: + case 241 /* CaseBlock */: return visitCaseBlock(node); - case 213: - return visitBlock(node, false); - case 224: - case 223: + case 213 /* Block */: + return visitBlock(node, /*isFunctionBody*/ false); + case 224 /* BreakStatement */: + case 223 /* ContinueStatement */: return visitBreakOrContinueStatement(node); - case 228: + case 228 /* LabeledStatement */: return visitLabeledStatement(node); - case 218: - case 219: - return visitDoOrWhileStatement(node, undefined); - case 220: - return visitForStatement(node, undefined); - case 221: - return visitForInStatement(node, undefined); - case 222: - return visitForOfStatement(node, undefined); - case 216: + case 218 /* DoStatement */: + case 219 /* WhileStatement */: + return visitDoOrWhileStatement(node, /*outermostLabeledStatement*/ undefined); + case 220 /* ForStatement */: + return visitForStatement(node, /*outermostLabeledStatement*/ undefined); + case 221 /* ForInStatement */: + return visitForInStatement(node, /*outermostLabeledStatement*/ undefined); + case 222 /* ForOfStatement */: + return visitForOfStatement(node, /*outermostLabeledStatement*/ undefined); + case 216 /* ExpressionStatement */: return visitExpressionStatement(node); - case 184: + case 184 /* ObjectLiteralExpression */: return visitObjectLiteralExpression(node); - case 269: + case 269 /* CatchClause */: return visitCatchClause(node); - case 271: + case 271 /* ShorthandPropertyAssignment */: return visitShorthandPropertyAssignment(node); - case 147: + case 147 /* ComputedPropertyName */: return visitComputedPropertyName(node); - case 183: + case 183 /* ArrayLiteralExpression */: return visitArrayLiteralExpression(node); - case 187: + case 187 /* CallExpression */: return visitCallExpression(node); - case 188: + case 188 /* NewExpression */: return visitNewExpression(node); - case 191: - return visitParenthesizedExpression(node, true); - case 200: - return visitBinaryExpression(node, true); - case 13: - case 14: - case 15: - case 16: + case 191 /* ParenthesizedExpression */: + return visitParenthesizedExpression(node, /*needsDestructuringValue*/ true); + case 200 /* BinaryExpression */: + return visitBinaryExpression(node, /*needsDestructuringValue*/ true); + case 13 /* NoSubstitutionTemplateLiteral */: + case 14 /* TemplateHead */: + case 15 /* TemplateMiddle */: + case 16 /* TemplateTail */: return visitTemplateLiteral(node); - case 9: + case 9 /* StringLiteral */: return visitStringLiteral(node); - case 8: + case 8 /* NumericLiteral */: return visitNumericLiteral(node); - case 189: + case 189 /* TaggedTemplateExpression */: return visitTaggedTemplateExpression(node); - case 202: + case 202 /* TemplateExpression */: return visitTemplateExpression(node); - case 203: + case 203 /* YieldExpression */: return visitYieldExpression(node); - case 204: + case 204 /* SpreadElement */: return visitSpreadElement(node); - case 97: - return visitSuperKeyword(false); - case 99: + case 97 /* SuperKeyword */: + return visitSuperKeyword(/*isExpressionOfCall*/ false); + case 99 /* ThisKeyword */: return visitThisKeyword(node); - case 210: + case 210 /* MetaProperty */: return visitMetaProperty(node); - case 154: + case 154 /* MethodDeclaration */: return visitMethodDeclaration(node); - case 156: - case 157: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return visitAccessorDeclaration(node); - case 214: + case 214 /* VariableStatement */: return visitVariableStatement(node); - case 225: + case 225 /* ReturnStatement */: return visitReturnStatement(node); default: return ts.visitEachChild(node, visitor, context); } } function visitSourceFile(node) { - var ancestorFacts = enterSubtree(3968, 64); + var ancestorFacts = enterSubtree(3968 /* SourceFileExcludes */, 64 /* SourceFileIncludes */); var statements = []; startLexicalEnvironment(); - var statementOffset = ts.addStandardPrologue(statements, node.statements, false); + var statementOffset = ts.addStandardPrologue(statements, node.statements, /*ensureUseStrict*/ false); addCaptureThisForNodeIfNeeded(statements, node); statementOffset = ts.addCustomPrologue(statements, node.statements, statementOffset, visitor); ts.addRange(statements, ts.visitNodes(node.statements, visitor, ts.isStatement, statementOffset)); if (taggedTemplateStringDeclarations) { - statements.push(ts.createVariableStatement(undefined, ts.createVariableDeclarationList(taggedTemplateStringDeclarations))); + statements.push(ts.createVariableStatement(/*modifiers*/ undefined, ts.createVariableDeclarationList(taggedTemplateStringDeclarations))); } ts.prependStatements(statements, endLexicalEnvironment()); - exitSubtree(ancestorFacts, 0, 0); + exitSubtree(ancestorFacts, 0 /* None */, 0 /* None */); return ts.updateSourceFileNode(node, ts.setTextRange(ts.createNodeArray(statements), node.statements)); } function visitSwitchStatement(node) { if (convertedLoopState !== undefined) { var savedAllowedNonLabeledJumps = convertedLoopState.allowedNonLabeledJumps; - convertedLoopState.allowedNonLabeledJumps |= 2; + // for switch statement allow only non-labeled break + convertedLoopState.allowedNonLabeledJumps |= 2 /* Break */; var result = ts.visitEachChild(node, visitor, context); convertedLoopState.allowedNonLabeledJumps = savedAllowedNonLabeledJumps; return result; @@ -56329,9 +66467,9 @@ var ts; return ts.visitEachChild(node, visitor, context); } function visitCaseBlock(node) { - var ancestorFacts = enterSubtree(4032, 0); + var ancestorFacts = enterSubtree(4032 /* BlockScopeExcludes */, 0 /* BlockScopeIncludes */); var updated = ts.visitEachChild(node, visitor, context); - exitSubtree(ancestorFacts, 0, 0); + exitSubtree(ancestorFacts, 0 /* None */, 0 /* None */); return updated; } function returnCapturedThis(node) { @@ -56339,7 +66477,7 @@ var ts; } function visitReturnStatement(node) { if (convertedLoopState) { - convertedLoopState.nonLocalJumps |= 8; + convertedLoopState.nonLocalJumps |= 8 /* Return */; if (isReturnVoidStatementInConstructorWithCapturedSuper(node)) { node = returnCapturedThis(node); } @@ -56356,7 +66494,8 @@ var ts; } function visitThisKeyword(node) { if (convertedLoopState) { - if (hierarchyFacts & 2) { + if (hierarchyFacts & 2 /* ArrowFunction */) { + // if the enclosing function is an ArrowFunction then we use the captured 'this' keyword. convertedLoopState.containsLexicalThis = true; return node; } @@ -56378,30 +66517,35 @@ var ts; } function visitBreakOrContinueStatement(node) { if (convertedLoopState) { - var jump = node.kind === 224 ? 2 : 4; + // check if we can emit break/continue as is + // it is possible if either + // - break/continue is labeled and label is located inside the converted loop + // - break/continue is non-labeled and located in non-converted loop/switch statement + var jump = node.kind === 224 /* BreakStatement */ ? 2 /* Break */ : 4 /* Continue */; var canUseBreakOrContinue = (node.label && convertedLoopState.labels && convertedLoopState.labels.get(ts.idText(node.label))) || (!node.label && (convertedLoopState.allowedNonLabeledJumps & jump)); if (!canUseBreakOrContinue) { var labelMarker = void 0; var label = node.label; if (!label) { - if (node.kind === 224) { - convertedLoopState.nonLocalJumps |= 2; + if (node.kind === 224 /* BreakStatement */) { + convertedLoopState.nonLocalJumps |= 2 /* Break */; labelMarker = "break"; } else { - convertedLoopState.nonLocalJumps |= 4; + convertedLoopState.nonLocalJumps |= 4 /* Continue */; + // note: return value is emitted only to simplify debugging, call to converted loop body does not do any dispatching on it. labelMarker = "continue"; } } else { - if (node.kind === 224) { + if (node.kind === 224 /* BreakStatement */) { labelMarker = "break-" + label.escapedText; - setLabeledJump(convertedLoopState, true, ts.idText(label), labelMarker); + setLabeledJump(convertedLoopState, /*isBreak*/ true, ts.idText(label), labelMarker); } else { labelMarker = "continue-" + label.escapedText; - setLabeledJump(convertedLoopState, false, ts.idText(label), labelMarker); + setLabeledJump(convertedLoopState, /*isBreak*/ false, ts.idText(label), labelMarker); } } var returnExpression = ts.createLiteral(labelMarker); @@ -56409,167 +66553,305 @@ var ts; var outParams = convertedLoopState.loopOutParameters; var expr = void 0; for (var i = 0; i < outParams.length; i++) { - var copyExpr = copyOutParameter(outParams[i], 1); + var copyExpr = copyOutParameter(outParams[i], 1 /* ToOutParameter */); if (i === 0) { expr = copyExpr; } else { - expr = ts.createBinary(expr, 26, copyExpr); + expr = ts.createBinary(expr, 26 /* CommaToken */, copyExpr); } } - returnExpression = ts.createBinary(expr, 26, returnExpression); + returnExpression = ts.createBinary(expr, 26 /* CommaToken */, returnExpression); } return ts.createReturn(returnExpression); } } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a ClassDeclaration and transforms it into a variable statement. + * + * @param node A ClassDeclaration node. + */ function visitClassDeclaration(node) { - var variable = ts.createVariableDeclaration(ts.getLocalName(node, true), undefined, transformClassLikeDeclarationToExpression(node)); + // [source] + // class C { } + // + // [output] + // var C = (function () { + // function C() { + // } + // return C; + // }()); + var variable = ts.createVariableDeclaration(ts.getLocalName(node, /*allowComments*/ true), + /*type*/ undefined, transformClassLikeDeclarationToExpression(node)); ts.setOriginalNode(variable, node); var statements = []; - var statement = ts.createVariableStatement(undefined, ts.createVariableDeclarationList([variable])); + var statement = ts.createVariableStatement(/*modifiers*/ undefined, ts.createVariableDeclarationList([variable])); ts.setOriginalNode(statement, node); ts.setTextRange(statement, node); ts.startOnNewLine(statement); statements.push(statement); - if (ts.hasModifier(node, 1)) { - var exportStatement = ts.hasModifier(node, 512) + // Add an `export default` statement for default exports (for `--target es5 --module es6`) + if (ts.hasModifier(node, 1 /* Export */)) { + var exportStatement = ts.hasModifier(node, 512 /* Default */) ? ts.createExportDefault(ts.getLocalName(node)) : ts.createExternalModuleExport(ts.getLocalName(node)); ts.setOriginalNode(exportStatement, statement); statements.push(exportStatement); } var emitFlags = ts.getEmitFlags(node); - if ((emitFlags & 4194304) === 0) { + if ((emitFlags & 4194304 /* HasEndOfDeclarationMarker */) === 0) { + // Add a DeclarationMarker as a marker for the end of the declaration statements.push(ts.createEndOfDeclarationMarker(node)); - ts.setEmitFlags(statement, emitFlags | 4194304); + ts.setEmitFlags(statement, emitFlags | 4194304 /* HasEndOfDeclarationMarker */); } return ts.singleOrMany(statements); } + /** + * Visits a ClassExpression and transforms it into an expression. + * + * @param node A ClassExpression node. + */ function visitClassExpression(node) { + // [source] + // C = class { } + // + // [output] + // C = (function () { + // function class_1() { + // } + // return class_1; + // }()) return transformClassLikeDeclarationToExpression(node); } + /** + * Transforms a ClassExpression or ClassDeclaration into an expression. + * + * @param node A ClassExpression or ClassDeclaration node. + */ function transformClassLikeDeclarationToExpression(node) { + // [source] + // class C extends D { + // constructor() {} + // method() {} + // get prop() {} + // set prop(v) {} + // } + // + // [output] + // (function (_super) { + // __extends(C, _super); + // function C() { + // } + // C.prototype.method = function () {} + // Object.defineProperty(C.prototype, "prop", { + // get: function() {}, + // set: function() {}, + // enumerable: true, + // configurable: true + // }); + // return C; + // }(D)) if (node.name) { enableSubstitutionsForBlockScopedBindings(); } var extendsClauseElement = ts.getClassExtendsHeritageClauseElement(node); - var classFunction = ts.createFunctionExpression(undefined, undefined, undefined, undefined, extendsClauseElement ? [ts.createParameter(undefined, undefined, undefined, ts.createFileLevelUniqueName("_super"))] : [], undefined, transformClassBody(node, extendsClauseElement)); - ts.setEmitFlags(classFunction, (ts.getEmitFlags(node) & 65536) | 524288); + var classFunction = ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, extendsClauseElement ? [ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, ts.createFileLevelUniqueName("_super"))] : [], + /*type*/ undefined, transformClassBody(node, extendsClauseElement)); + // To preserve the behavior of the old emitter, we explicitly indent + // the body of the function here if it was requested in an earlier + // transformation. + ts.setEmitFlags(classFunction, (ts.getEmitFlags(node) & 65536 /* Indented */) | 524288 /* ReuseTempVariableScope */); + // "inner" and "outer" below are added purely to preserve source map locations from + // the old emitter var inner = ts.createPartiallyEmittedExpression(classFunction); inner.end = node.end; - ts.setEmitFlags(inner, 1536); + ts.setEmitFlags(inner, 1536 /* NoComments */); var outer = ts.createPartiallyEmittedExpression(inner); outer.end = ts.skipTrivia(currentText, node.pos); - ts.setEmitFlags(outer, 1536); - var result = ts.createParen(ts.createCall(outer, undefined, extendsClauseElement + ts.setEmitFlags(outer, 1536 /* NoComments */); + var result = ts.createParen(ts.createCall(outer, + /*typeArguments*/ undefined, extendsClauseElement ? [ts.visitNode(extendsClauseElement.expression, visitor, ts.isExpression)] : [])); - ts.addSyntheticLeadingComment(result, 3, "* @class "); + ts.addSyntheticLeadingComment(result, 3 /* MultiLineCommentTrivia */, "* @class "); return result; } + /** + * Transforms a ClassExpression or ClassDeclaration into a function body. + * + * @param node A ClassExpression or ClassDeclaration node. + * @param extendsClauseElement The expression for the class `extends` clause. + */ function transformClassBody(node, extendsClauseElement) { var statements = []; startLexicalEnvironment(); addExtendsHelperIfNeeded(statements, node, extendsClauseElement); addConstructor(statements, node, extendsClauseElement); addClassMembers(statements, node); - var closingBraceLocation = ts.createTokenRange(ts.skipTrivia(currentText, node.members.end), 18); + // Create a synthetic text range for the return statement. + var closingBraceLocation = ts.createTokenRange(ts.skipTrivia(currentText, node.members.end), 18 /* CloseBraceToken */); var localName = ts.getInternalName(node); + // The following partially-emitted expression exists purely to align our sourcemap + // emit with the original emitter. var outer = ts.createPartiallyEmittedExpression(localName); outer.end = closingBraceLocation.end; - ts.setEmitFlags(outer, 1536); + ts.setEmitFlags(outer, 1536 /* NoComments */); var statement = ts.createReturn(outer); statement.pos = closingBraceLocation.pos; - ts.setEmitFlags(statement, 1536 | 384); + ts.setEmitFlags(statement, 1536 /* NoComments */ | 384 /* NoTokenSourceMaps */); statements.push(statement); ts.prependStatements(statements, endLexicalEnvironment()); - var block = ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), node.members), true); - ts.setEmitFlags(block, 1536); + var block = ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), /*location*/ node.members), /*multiLine*/ true); + ts.setEmitFlags(block, 1536 /* NoComments */); return block; } + /** + * Adds a call to the `__extends` helper if needed for a class. + * + * @param statements The statements of the class body function. + * @param node The ClassExpression or ClassDeclaration node. + * @param extendsClauseElement The expression for the class `extends` clause. + */ function addExtendsHelperIfNeeded(statements, node, extendsClauseElement) { if (extendsClauseElement) { - statements.push(ts.setTextRange(ts.createStatement(createExtendsHelper(context, ts.getInternalName(node))), extendsClauseElement)); + statements.push(ts.setTextRange(ts.createStatement(createExtendsHelper(context, ts.getInternalName(node))), + /*location*/ extendsClauseElement)); } } + /** + * Adds the constructor of the class to a class body function. + * + * @param statements The statements of the class body function. + * @param node The ClassExpression or ClassDeclaration node. + * @param extendsClauseElement The expression for the class `extends` clause. + */ function addConstructor(statements, node, extendsClauseElement) { var savedConvertedLoopState = convertedLoopState; convertedLoopState = undefined; - var ancestorFacts = enterSubtree(16278, 73); + var ancestorFacts = enterSubtree(16278 /* ConstructorExcludes */, 73 /* ConstructorIncludes */); var constructor = ts.getFirstConstructorWithBody(node); var hasSynthesizedSuper = hasSynthesizedDefaultSuperCall(constructor, extendsClauseElement !== undefined); - var constructorFunction = ts.createFunctionDeclaration(undefined, undefined, undefined, ts.getInternalName(node), undefined, transformConstructorParameters(constructor, hasSynthesizedSuper), undefined, transformConstructorBody(constructor, node, extendsClauseElement, hasSynthesizedSuper)); + var constructorFunction = ts.createFunctionDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, ts.getInternalName(node), + /*typeParameters*/ undefined, transformConstructorParameters(constructor, hasSynthesizedSuper), + /*type*/ undefined, transformConstructorBody(constructor, node, extendsClauseElement, hasSynthesizedSuper)); ts.setTextRange(constructorFunction, constructor || node); if (extendsClauseElement) { - ts.setEmitFlags(constructorFunction, 8); + ts.setEmitFlags(constructorFunction, 8 /* CapturesThis */); } statements.push(constructorFunction); - exitSubtree(ancestorFacts, 49152, 0); + exitSubtree(ancestorFacts, 49152 /* PropagateNewTargetMask */, 0 /* None */); convertedLoopState = savedConvertedLoopState; } + /** + * Transforms the parameters of the constructor declaration of a class. + * + * @param constructor The constructor for the class. + * @param hasSynthesizedSuper A value indicating whether the constructor starts with a + * synthesized `super` call. + */ function transformConstructorParameters(constructor, hasSynthesizedSuper) { + // If the TypeScript transformer needed to synthesize a constructor for property + // initializers, it would have also added a synthetic `...args` parameter and + // `super` call. + // If this is the case, we do not include the synthetic `...args` parameter and + // will instead use the `arguments` object in ES5/3. return ts.visitParameterList(constructor && !hasSynthesizedSuper ? constructor.parameters : undefined, visitor, context) || []; } + /** + * Transforms the body of a constructor declaration of a class. + * + * @param constructor The constructor for the class. + * @param node The node which contains the constructor. + * @param extendsClauseElement The expression for the class `extends` clause. + * @param hasSynthesizedSuper A value indicating whether the constructor starts with a + * synthesized `super` call. + */ function transformConstructorBody(constructor, node, extendsClauseElement, hasSynthesizedSuper) { var statements = []; resumeLexicalEnvironment(); var statementOffset = -1; if (hasSynthesizedSuper) { + // If a super call has already been synthesized, + // we're going to assume that we should just transform everything after that. + // The assumption is that no prior step in the pipeline has added any prologue directives. statementOffset = 0; } else if (constructor) { - statementOffset = ts.addStandardPrologue(statements, constructor.body.statements, false); + statementOffset = ts.addStandardPrologue(statements, constructor.body.statements, /*ensureUseStrict*/ false); } if (constructor) { addDefaultValueAssignmentsIfNeeded(statements, constructor); addRestParameterIfNeeded(statements, constructor, hasSynthesizedSuper); if (!hasSynthesizedSuper) { + // If no super call has been synthesized, emit custom prologue directives. statementOffset = ts.addCustomPrologue(statements, constructor.body.statements, statementOffset, visitor); } ts.Debug.assert(statementOffset >= 0, "statementOffset not initialized correctly!"); } - var isDerivedClass = !!extendsClauseElement && ts.skipOuterExpressions(extendsClauseElement.expression).kind !== 95; + // determine whether the class is known syntactically to be a derived class (e.g. a + // class that extends a value that is not syntactically known to be `null`). + var isDerivedClass = !!extendsClauseElement && ts.skipOuterExpressions(extendsClauseElement.expression).kind !== 95 /* NullKeyword */; var superCaptureStatus = declareOrCaptureOrReturnThisForConstructorIfNeeded(statements, constructor, isDerivedClass, hasSynthesizedSuper, statementOffset); - if (superCaptureStatus === 1 || superCaptureStatus === 2) { + // The last statement expression was replaced. Skip it. + if (superCaptureStatus === 1 /* ReplaceSuperCapture */ || superCaptureStatus === 2 /* ReplaceWithReturn */) { statementOffset++; } if (constructor) { - if (superCaptureStatus === 1) { - hierarchyFacts |= 4096; + if (superCaptureStatus === 1 /* ReplaceSuperCapture */) { + hierarchyFacts |= 4096 /* ConstructorWithCapturedSuper */; } - ts.addRange(statements, ts.visitNodes(constructor.body.statements, visitor, ts.isStatement, statementOffset)); + ts.addRange(statements, ts.visitNodes(constructor.body.statements, visitor, ts.isStatement, /*start*/ statementOffset)); } + // Return `_this` unless we're sure enough that it would be pointless to add a return statement. + // If there's a constructor that we can tell returns in enough places, then we *do not* want to add a return. if (isDerivedClass - && superCaptureStatus !== 2 + && superCaptureStatus !== 2 /* ReplaceWithReturn */ && !(constructor && isSufficientlyCoveredByReturnStatements(constructor.body))) { statements.push(ts.createReturn(ts.createFileLevelUniqueName("_this"))); } ts.prependStatements(statements, endLexicalEnvironment()); if (constructor) { - prependCaptureNewTargetIfNeeded(statements, constructor, false); + prependCaptureNewTargetIfNeeded(statements, constructor, /*copyOnWrite*/ false); } - var block = ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), constructor ? constructor.body.statements : node.members), true); + var block = ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), + /*location*/ constructor ? constructor.body.statements : node.members), + /*multiLine*/ true); ts.setTextRange(block, constructor ? constructor.body : node); if (!constructor) { - ts.setEmitFlags(block, 1536); + ts.setEmitFlags(block, 1536 /* NoComments */); } return block; } + /** + * We want to try to avoid emitting a return statement in certain cases if a user already returned something. + * It would generate obviously dead code, so we'll try to make things a little bit prettier + * by doing a minimal check on whether some common patterns always explicitly return. + */ function isSufficientlyCoveredByReturnStatements(statement) { - if (statement.kind === 225) { + // A return statement is considered covered. + if (statement.kind === 225 /* ReturnStatement */) { return true; } - else if (statement.kind === 217) { + // An if-statement with two covered branches is covered. + else if (statement.kind === 217 /* IfStatement */) { var ifStatement = statement; if (ifStatement.elseStatement) { return isSufficientlyCoveredByReturnStatements(ifStatement.thenStatement) && isSufficientlyCoveredByReturnStatements(ifStatement.elseStatement); } } - else if (statement.kind === 213) { + // A block is covered if it has a last statement which is covered. + else if (statement.kind === 213 /* Block */) { var lastStatement = ts.lastOrUndefined(statement.statements); if (lastStatement && isSufficientlyCoveredByReturnStatements(lastStatement)) { return true; @@ -56577,72 +66859,144 @@ var ts; } return false; } + /** + * Declares a `_this` variable for derived classes and for when arrow functions capture `this`. + * + * @returns The new statement offset into the `statements` array. + */ function declareOrCaptureOrReturnThisForConstructorIfNeeded(statements, ctor, isDerivedClass, hasSynthesizedSuper, statementOffset) { + // If this isn't a derived class, just capture 'this' for arrow functions if necessary. if (!isDerivedClass) { if (ctor) { addCaptureThisForNodeIfNeeded(statements, ctor); } - return 0; + return 0 /* NoReplacement */; } + // We must be here because the user didn't write a constructor + // but we needed to call 'super(...args)' anyway as per 14.5.14 of the ES2016 spec. + // If that's the case we can just immediately return the result of a 'super()' call. if (!ctor) { statements.push(ts.createReturn(createDefaultSuperCallOrThis())); - return 2; + return 2 /* ReplaceWithReturn */; } + // The constructor exists, but it and the 'super()' call it contains were generated + // for something like property initializers. + // Create a captured '_this' variable and assume it will subsequently be used. if (hasSynthesizedSuper) { captureThisForNode(statements, ctor, createDefaultSuperCallOrThis()); enableSubstitutionsForCapturedThis(); - return 1; + return 1 /* ReplaceSuperCapture */; } + // Most of the time, a 'super' call will be the first real statement in a constructor body. + // In these cases, we'd like to transform these into a *single* statement instead of a declaration + // followed by an assignment statement for '_this'. For instance, if we emitted without an initializer, + // we'd get: + // + // var _this; + // _this = _super.call(...) || this; + // + // instead of + // + // var _this = _super.call(...) || this; + // + // Additionally, if the 'super()' call is the last statement, we should just avoid capturing + // entirely and immediately return the result like so: + // + // return _super.call(...) || this; + // var firstStatement; var superCallExpression; var ctorStatements = ctor.body.statements; if (statementOffset < ctorStatements.length) { firstStatement = ctorStatements[statementOffset]; - if (firstStatement.kind === 216 && ts.isSuperCall(firstStatement.expression)) { + if (firstStatement.kind === 216 /* ExpressionStatement */ && ts.isSuperCall(firstStatement.expression)) { superCallExpression = visitImmediateSuperCallInBody(firstStatement.expression); } } + // Return the result if we have an immediate super() call on the last statement, + // but only if the constructor itself doesn't use 'this' elsewhere. if (superCallExpression && statementOffset === ctorStatements.length - 1 - && !(ctor.transformFlags & (16384 | 32768))) { + && !(ctor.transformFlags & (16384 /* ContainsLexicalThis */ | 32768 /* ContainsCapturedLexicalThis */))) { var returnStatement = ts.createReturn(superCallExpression); - if (superCallExpression.kind !== 200 - || superCallExpression.left.kind !== 187) { + if (superCallExpression.kind !== 200 /* BinaryExpression */ + || superCallExpression.left.kind !== 187 /* CallExpression */) { ts.Debug.fail("Assumed generated super call would have form 'super.call(...) || this'."); } - ts.setCommentRange(returnStatement, ts.getCommentRange(ts.setEmitFlags(superCallExpression.left, 1536))); + // Shift comments from the original super call to the return statement. + ts.setCommentRange(returnStatement, ts.getCommentRange(ts.setEmitFlags(superCallExpression.left, 1536 /* NoComments */))); statements.push(returnStatement); - return 2; + return 2 /* ReplaceWithReturn */; } + // Perform the capture. captureThisForNode(statements, ctor, superCallExpression || createActualThis(), firstStatement); + // If we're actually replacing the original statement, we need to signal this to the caller. if (superCallExpression) { - return 1; + return 1 /* ReplaceSuperCapture */; } - return 0; + return 0 /* NoReplacement */; } function createActualThis() { - return ts.setEmitFlags(ts.createThis(), 4); + return ts.setEmitFlags(ts.createThis(), 4 /* NoSubstitution */); } function createDefaultSuperCallOrThis() { return ts.createLogicalOr(ts.createLogicalAnd(ts.createStrictInequality(ts.createFileLevelUniqueName("_super"), ts.createNull()), ts.createFunctionApply(ts.createFileLevelUniqueName("_super"), createActualThis(), ts.createIdentifier("arguments"))), createActualThis()); } + /** + * Visits a parameter declaration. + * + * @param node A ParameterDeclaration node. + */ function visitParameter(node) { if (node.dotDotDotToken) { + // rest parameters are elided return undefined; } else if (ts.isBindingPattern(node.name)) { - return ts.setOriginalNode(ts.setTextRange(ts.createParameter(undefined, undefined, undefined, ts.getGeneratedNameForNode(node), undefined, undefined, undefined), node), node); + // Binding patterns are converted into a generated name and are + // evaluated inside the function body. + return ts.setOriginalNode(ts.setTextRange(ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, ts.getGeneratedNameForNode(node), + /*questionToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined), + /*location*/ node), + /*original*/ node); } else if (node.initializer) { - return ts.setOriginalNode(ts.setTextRange(ts.createParameter(undefined, undefined, undefined, node.name, undefined, undefined, undefined), node), node); + // Initializers are elided + return ts.setOriginalNode(ts.setTextRange(ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, node.name, + /*questionToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined), + /*location*/ node), + /*original*/ node); } else { return node; } } + /** + * Gets a value indicating whether we need to add default value assignments for a + * function-like node. + * + * @param node A function-like node. + */ function shouldAddDefaultValueAssignments(node) { - return (node.transformFlags & 131072) !== 0; + return (node.transformFlags & 131072 /* ContainsDefaultValueAssignments */) !== 0; } + /** + * Adds statements to the body of a function-like node if it contains parameters with + * binding patterns or initializers. + * + * @param statements The statements for the new function body. + * @param node A function-like node. + */ function addDefaultValueAssignmentsIfNeeded(statements, node) { if (!shouldAddDefaultValueAssignments(node)) { return; @@ -56650,6 +67004,8 @@ var ts; for (var _i = 0, _a = node.parameters; _i < _a.length; _i++) { var parameter = _a[_i]; var name = parameter.name, initializer = parameter.initializer, dotDotDotToken = parameter.dotDotDotToken; + // A rest parameter cannot have a binding pattern or an initializer, + // so let's just ignore it. if (dotDotDotToken) { continue; } @@ -56661,90 +67017,153 @@ var ts; } } } + /** + * Adds statements to the body of a function-like node for parameters with binding patterns + * + * @param statements The statements for the new function body. + * @param parameter The parameter for the function. + * @param name The name of the parameter. + * @param initializer The initializer for the parameter. + */ function addDefaultValueAssignmentForBindingPattern(statements, parameter, name, initializer) { var temp = ts.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. if (name.elements.length > 0) { - statements.push(ts.setEmitFlags(ts.createVariableStatement(undefined, ts.createVariableDeclarationList(ts.flattenDestructuringBinding(parameter, visitor, context, 0, temp))), 1048576)); + statements.push(ts.setEmitFlags(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList(ts.flattenDestructuringBinding(parameter, visitor, context, 0 /* All */, temp))), 1048576 /* CustomPrologue */)); } else if (initializer) { - statements.push(ts.setEmitFlags(ts.createStatement(ts.createAssignment(temp, ts.visitNode(initializer, visitor, ts.isExpression))), 1048576)); + statements.push(ts.setEmitFlags(ts.createStatement(ts.createAssignment(temp, ts.visitNode(initializer, visitor, ts.isExpression))), 1048576 /* CustomPrologue */)); } } + /** + * Adds statements to the body of a function-like node for parameters with initializers. + * + * @param statements The statements for the new function body. + * @param parameter The parameter for the function. + * @param name The name of the parameter. + * @param initializer The initializer for the parameter. + */ function addDefaultValueAssignmentForInitializer(statements, parameter, name, initializer) { initializer = ts.visitNode(initializer, visitor, ts.isExpression); var statement = ts.createIf(ts.createTypeCheck(ts.getSynthesizedClone(name), "undefined"), ts.setEmitFlags(ts.setTextRange(ts.createBlock([ - ts.createStatement(ts.setEmitFlags(ts.setTextRange(ts.createAssignment(ts.setEmitFlags(ts.getMutableClone(name), 48), ts.setEmitFlags(initializer, 48 | ts.getEmitFlags(initializer) | 1536)), parameter), 1536)) - ]), parameter), 1 | 32 | 384 | 1536)); + ts.createStatement(ts.setEmitFlags(ts.setTextRange(ts.createAssignment(ts.setEmitFlags(ts.getMutableClone(name), 48 /* NoSourceMap */), ts.setEmitFlags(initializer, 48 /* NoSourceMap */ | ts.getEmitFlags(initializer) | 1536 /* NoComments */)), parameter), 1536 /* NoComments */)) + ]), parameter), 1 /* SingleLine */ | 32 /* NoTrailingSourceMap */ | 384 /* NoTokenSourceMaps */ | 1536 /* NoComments */)); ts.startOnNewLine(statement); ts.setTextRange(statement, parameter); - ts.setEmitFlags(statement, 384 | 32 | 1048576 | 1536); + ts.setEmitFlags(statement, 384 /* NoTokenSourceMaps */ | 32 /* NoTrailingSourceMap */ | 1048576 /* CustomPrologue */ | 1536 /* NoComments */); statements.push(statement); } + /** + * Gets a value indicating whether we need to add statements to handle a rest parameter. + * + * @param node A ParameterDeclaration node. + * @param inConstructorWithSynthesizedSuper A value indicating whether the parameter is + * part of a constructor declaration with a + * synthesized call to `super` + */ function shouldAddRestParameter(node, inConstructorWithSynthesizedSuper) { - return node && node.dotDotDotToken && node.name.kind === 71 && !inConstructorWithSynthesizedSuper; + return node && node.dotDotDotToken && node.name.kind === 71 /* Identifier */ && !inConstructorWithSynthesizedSuper; } + /** + * Adds statements to the body of a function-like node if it contains a rest parameter. + * + * @param statements The statements for the new function body. + * @param node A function-like node. + * @param inConstructorWithSynthesizedSuper A value indicating whether the parameter is + * part of a constructor declaration with a + * synthesized call to `super` + */ function addRestParameterIfNeeded(statements, node, inConstructorWithSynthesizedSuper) { var parameter = ts.lastOrUndefined(node.parameters); if (!shouldAddRestParameter(parameter, inConstructorWithSynthesizedSuper)) { return; } + // `declarationName` is the name of the local declaration for the parameter. var declarationName = ts.getMutableClone(parameter.name); - ts.setEmitFlags(declarationName, 48); + ts.setEmitFlags(declarationName, 48 /* NoSourceMap */); + // `expressionName` is the name of the parameter used in expressions. var expressionName = ts.getSynthesizedClone(parameter.name); var restIndex = node.parameters.length - 1; var temp = ts.createLoopVariable(); - statements.push(ts.setEmitFlags(ts.setTextRange(ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.createVariableDeclaration(declarationName, undefined, ts.createArrayLiteral([])) - ])), parameter), 1048576)); + // var param = []; + statements.push(ts.setEmitFlags(ts.setTextRange(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(declarationName, + /*type*/ undefined, ts.createArrayLiteral([])) + ])), + /*location*/ parameter), 1048576 /* CustomPrologue */)); + // for (var _i = restIndex; _i < arguments.length; _i++) { + // param[_i - restIndex] = arguments[_i]; + // } var forStatement = ts.createFor(ts.setTextRange(ts.createVariableDeclarationList([ - ts.createVariableDeclaration(temp, undefined, ts.createLiteral(restIndex)) + ts.createVariableDeclaration(temp, /*type*/ undefined, ts.createLiteral(restIndex)) ]), parameter), ts.setTextRange(ts.createLessThan(temp, ts.createPropertyAccess(ts.createIdentifier("arguments"), "length")), parameter), ts.setTextRange(ts.createPostfixIncrement(temp), parameter), ts.createBlock([ ts.startOnNewLine(ts.setTextRange(ts.createStatement(ts.createAssignment(ts.createElementAccess(expressionName, restIndex === 0 ? temp - : ts.createSubtract(temp, ts.createLiteral(restIndex))), ts.createElementAccess(ts.createIdentifier("arguments"), temp))), parameter)) + : ts.createSubtract(temp, ts.createLiteral(restIndex))), ts.createElementAccess(ts.createIdentifier("arguments"), temp))), + /*location*/ parameter)) ])); - ts.setEmitFlags(forStatement, 1048576); + ts.setEmitFlags(forStatement, 1048576 /* CustomPrologue */); ts.startOnNewLine(forStatement); statements.push(forStatement); } + /** + * Adds a statement to capture the `this` of a function declaration if it is needed. + * + * @param statements The statements for the new function body. + * @param node A node. + */ function addCaptureThisForNodeIfNeeded(statements, node) { - if (node.transformFlags & 32768 && node.kind !== 193) { + if (node.transformFlags & 32768 /* ContainsCapturedLexicalThis */ && node.kind !== 193 /* ArrowFunction */) { captureThisForNode(statements, node, ts.createThis()); } } function captureThisForNode(statements, node, initializer, originalStatement) { enableSubstitutionsForCapturedThis(); - var captureThisStatement = ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.createVariableDeclaration(ts.createFileLevelUniqueName("_this"), undefined, initializer) + var captureThisStatement = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(ts.createFileLevelUniqueName("_this"), + /*type*/ undefined, initializer) ])); - ts.setEmitFlags(captureThisStatement, 1536 | 1048576); + ts.setEmitFlags(captureThisStatement, 1536 /* NoComments */ | 1048576 /* CustomPrologue */); ts.setTextRange(captureThisStatement, originalStatement); ts.setSourceMapRange(captureThisStatement, node); statements.push(captureThisStatement); } function prependCaptureNewTargetIfNeeded(statements, node, copyOnWrite) { - if (hierarchyFacts & 16384) { + if (hierarchyFacts & 16384 /* NewTarget */) { var newTarget = void 0; switch (node.kind) { - case 193: + case 193 /* ArrowFunction */: return statements; - case 154: - case 156: - case 157: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + // Methods and accessors cannot be constructors, so 'new.target' will + // always return 'undefined'. newTarget = ts.createVoidZero(); break; - case 155: - newTarget = ts.createPropertyAccess(ts.setEmitFlags(ts.createThis(), 4), "constructor"); + case 155 /* Constructor */: + // Class constructors can only be called with `new`, so `this.constructor` + // should be relatively safe to use. + newTarget = ts.createPropertyAccess(ts.setEmitFlags(ts.createThis(), 4 /* NoSubstitution */), "constructor"); break; - case 234: - case 192: - newTarget = ts.createConditional(ts.createLogicalAnd(ts.setEmitFlags(ts.createThis(), 4), ts.createBinary(ts.setEmitFlags(ts.createThis(), 4), 93, ts.getLocalName(node))), ts.createPropertyAccess(ts.setEmitFlags(ts.createThis(), 4), "constructor"), ts.createVoidZero()); + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + // Functions can be called or constructed, and may have a `this` due to + // being a member or when calling an imported function via `other_1.f()`. + newTarget = ts.createConditional(ts.createLogicalAnd(ts.setEmitFlags(ts.createThis(), 4 /* NoSubstitution */), ts.createBinary(ts.setEmitFlags(ts.createThis(), 4 /* NoSubstitution */), 93 /* InstanceOfKeyword */, ts.getLocalName(node))), ts.createPropertyAccess(ts.setEmitFlags(ts.createThis(), 4 /* NoSubstitution */), "constructor"), ts.createVoidZero()); break; default: return ts.Debug.failBadSyntaxKind(node); } - var captureNewTargetStatement = ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.createVariableDeclaration(ts.createFileLevelUniqueName("_newTarget"), undefined, newTarget) + var captureNewTargetStatement = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(ts.createFileLevelUniqueName("_newTarget"), + /*type*/ undefined, newTarget) ])); if (copyOnWrite) { return [captureNewTargetStatement].concat(statements); @@ -56753,24 +67172,32 @@ var ts; } return statements; } + /** + * Adds statements to the class body function for a class to define the members of the + * class. + * + * @param statements The statements for the class body function. + * @param node The ClassExpression or ClassDeclaration node. + */ function addClassMembers(statements, node) { for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var member = _a[_i]; switch (member.kind) { - case 212: + case 212 /* SemicolonClassElement */: statements.push(transformSemicolonClassElementToStatement(member)); break; - case 154: + case 154 /* MethodDeclaration */: statements.push(transformClassMethodDeclarationToStatement(getClassMemberPrefix(node, member), member, node)); break; - case 156: - case 157: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: var accessors = ts.getAllAccessorDeclarations(node.members, member); if (member === accessors.firstAccessor) { statements.push(transformAccessorsToStatement(getClassMemberPrefix(node, member), accessors, node)); } break; - case 155: + case 155 /* Constructor */: + // Constructors are handled in visitClassExpression/visitClassDeclaration break; default: ts.Debug.failBadSyntaxKind(node); @@ -56778,133 +67205,208 @@ var ts; } } } + /** + * Transforms a SemicolonClassElement into a statement for a class body function. + * + * @param member The SemicolonClassElement node. + */ function transformSemicolonClassElementToStatement(member) { return ts.setTextRange(ts.createEmptyStatement(), member); } + /** + * Transforms a MethodDeclaration into a statement for a class body function. + * + * @param receiver The receiver for the member. + * @param member The MethodDeclaration node. + */ function transformClassMethodDeclarationToStatement(receiver, member, container) { - var ancestorFacts = enterSubtree(0, 0); + var ancestorFacts = enterSubtree(0 /* None */, 0 /* None */); var commentRange = ts.getCommentRange(member); var sourceMapRange = ts.getSourceMapRange(member); - var memberName = ts.createMemberAccessForPropertyName(receiver, ts.visitNode(member.name, visitor, ts.isPropertyName), member.name); - var memberFunction = transformFunctionLikeToExpression(member, member, undefined, container); - ts.setEmitFlags(memberFunction, 1536); + var memberName = ts.createMemberAccessForPropertyName(receiver, ts.visitNode(member.name, visitor, ts.isPropertyName), /*location*/ member.name); + var memberFunction = transformFunctionLikeToExpression(member, /*location*/ member, /*name*/ undefined, container); + ts.setEmitFlags(memberFunction, 1536 /* NoComments */); ts.setSourceMapRange(memberFunction, sourceMapRange); - var statement = ts.setTextRange(ts.createStatement(ts.createAssignment(memberName, memberFunction)), member); + var statement = ts.setTextRange(ts.createStatement(ts.createAssignment(memberName, memberFunction)), + /*location*/ member); ts.setOriginalNode(statement, member); ts.setCommentRange(statement, commentRange); - ts.setEmitFlags(statement, 48); - exitSubtree(ancestorFacts, 49152, hierarchyFacts & 49152 ? 16384 : 0); + // The location for the statement is used to emit comments only. + // No source map should be emitted for this statement to align with the + // old emitter. + ts.setEmitFlags(statement, 48 /* NoSourceMap */); + exitSubtree(ancestorFacts, 49152 /* PropagateNewTargetMask */, hierarchyFacts & 49152 /* PropagateNewTargetMask */ ? 16384 /* NewTarget */ : 0 /* None */); return statement; } + /** + * Transforms a set of related of get/set accessors into a statement for a class body function. + * + * @param receiver The receiver for the member. + * @param accessors The set of related get/set accessors. + */ function transformAccessorsToStatement(receiver, accessors, container) { - var statement = ts.createStatement(transformAccessorsToExpression(receiver, accessors, container, false)); - ts.setEmitFlags(statement, 1536); + var statement = ts.createStatement(transformAccessorsToExpression(receiver, accessors, container, /*startsOnNewLine*/ false)); + // The location for the statement is used to emit source maps only. + // No comments should be emitted for this statement to align with the + // old emitter. + ts.setEmitFlags(statement, 1536 /* NoComments */); ts.setSourceMapRange(statement, ts.getSourceMapRange(accessors.firstAccessor)); return statement; } + /** + * Transforms a set of related get/set accessors into an expression for either a class + * body function or an ObjectLiteralExpression with computed properties. + * + * @param receiver The receiver for the member. + */ function transformAccessorsToExpression(receiver, _a, container, startsOnNewLine) { var firstAccessor = _a.firstAccessor, getAccessor = _a.getAccessor, setAccessor = _a.setAccessor; - var ancestorFacts = enterSubtree(0, 0); + var ancestorFacts = enterSubtree(0 /* None */, 0 /* None */); + // To align with source maps in the old emitter, the receiver and property name + // arguments are both mapped contiguously to the accessor name. var target = ts.getMutableClone(receiver); - ts.setEmitFlags(target, 1536 | 32); - ts.setSourceMapRange(target, firstAccessor.name); + ts.setEmitFlags(target, 1536 /* NoComments */ | 32 /* NoTrailingSourceMap */); + ts.setSourceMapRange(target, firstAccessor.name); // TODO: GH#18217 var propertyName = ts.createExpressionForPropertyName(ts.visitNode(firstAccessor.name, visitor, ts.isPropertyName)); - ts.setEmitFlags(propertyName, 1536 | 16); + ts.setEmitFlags(propertyName, 1536 /* NoComments */ | 16 /* NoLeadingSourceMap */); ts.setSourceMapRange(propertyName, firstAccessor.name); var properties = []; if (getAccessor) { - var getterFunction = transformFunctionLikeToExpression(getAccessor, undefined, undefined, container); + var getterFunction = transformFunctionLikeToExpression(getAccessor, /*location*/ undefined, /*name*/ undefined, container); ts.setSourceMapRange(getterFunction, ts.getSourceMapRange(getAccessor)); - ts.setEmitFlags(getterFunction, 512); + ts.setEmitFlags(getterFunction, 512 /* NoLeadingComments */); var getter = ts.createPropertyAssignment("get", getterFunction); ts.setCommentRange(getter, ts.getCommentRange(getAccessor)); properties.push(getter); } if (setAccessor) { - var setterFunction = transformFunctionLikeToExpression(setAccessor, undefined, undefined, container); + var setterFunction = transformFunctionLikeToExpression(setAccessor, /*location*/ undefined, /*name*/ undefined, container); ts.setSourceMapRange(setterFunction, ts.getSourceMapRange(setAccessor)); - ts.setEmitFlags(setterFunction, 512); + ts.setEmitFlags(setterFunction, 512 /* NoLeadingComments */); var setter = ts.createPropertyAssignment("set", setterFunction); ts.setCommentRange(setter, ts.getCommentRange(setAccessor)); properties.push(setter); } properties.push(ts.createPropertyAssignment("enumerable", ts.createTrue()), ts.createPropertyAssignment("configurable", ts.createTrue())); - var call = ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Object"), "defineProperty"), undefined, [ + var call = ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Object"), "defineProperty"), + /*typeArguments*/ undefined, [ target, propertyName, - ts.createObjectLiteral(properties, true) + ts.createObjectLiteral(properties, /*multiLine*/ true) ]); if (startsOnNewLine) { ts.startOnNewLine(call); } - exitSubtree(ancestorFacts, 49152, hierarchyFacts & 49152 ? 16384 : 0); + exitSubtree(ancestorFacts, 49152 /* PropagateNewTargetMask */, hierarchyFacts & 49152 /* PropagateNewTargetMask */ ? 16384 /* NewTarget */ : 0 /* None */); return call; } + /** + * Visits an ArrowFunction and transforms it into a FunctionExpression. + * + * @param node An ArrowFunction node. + */ function visitArrowFunction(node) { - if (node.transformFlags & 16384) { + if (node.transformFlags & 16384 /* ContainsLexicalThis */) { enableSubstitutionsForCapturedThis(); } var savedConvertedLoopState = convertedLoopState; convertedLoopState = undefined; - var ancestorFacts = enterSubtree(16256, 66); - var func = ts.createFunctionExpression(undefined, undefined, undefined, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, transformFunctionBody(node)); + var ancestorFacts = enterSubtree(16256 /* ArrowFunctionExcludes */, 66 /* ArrowFunctionIncludes */); + var func = ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, transformFunctionBody(node)); ts.setTextRange(func, node); ts.setOriginalNode(func, node); - ts.setEmitFlags(func, 8); - exitSubtree(ancestorFacts, 0, 0); + ts.setEmitFlags(func, 8 /* CapturesThis */); + exitSubtree(ancestorFacts, 0 /* None */, 0 /* None */); convertedLoopState = savedConvertedLoopState; return func; } + /** + * Visits a FunctionExpression node. + * + * @param node a FunctionExpression node. + */ function visitFunctionExpression(node) { - var ancestorFacts = ts.getEmitFlags(node) & 262144 - ? enterSubtree(16278, 69) - : enterSubtree(16286, 65); + var ancestorFacts = ts.getEmitFlags(node) & 262144 /* AsyncFunctionBody */ + ? enterSubtree(16278 /* AsyncFunctionBodyExcludes */, 69 /* AsyncFunctionBodyIncludes */) + : enterSubtree(16286 /* FunctionExcludes */, 65 /* FunctionIncludes */); var savedConvertedLoopState = convertedLoopState; convertedLoopState = undefined; var parameters = ts.visitParameterList(node.parameters, visitor, context); - var body = node.transformFlags & 64 + var body = node.transformFlags & 64 /* ES2015 */ ? transformFunctionBody(node) : visitFunctionBodyDownLevel(node); - var name = hierarchyFacts & 16384 + var name = hierarchyFacts & 16384 /* NewTarget */ ? ts.getLocalName(node) : node.name; - exitSubtree(ancestorFacts, 49152, 0); + exitSubtree(ancestorFacts, 49152 /* PropagateNewTargetMask */, 0 /* None */); convertedLoopState = savedConvertedLoopState; - return ts.updateFunctionExpression(node, undefined, node.asteriskToken, name, undefined, parameters, undefined, body); + return ts.updateFunctionExpression(node, + /*modifiers*/ undefined, node.asteriskToken, name, + /*typeParameters*/ undefined, parameters, + /*type*/ undefined, body); } + /** + * Visits a FunctionDeclaration node. + * + * @param node a FunctionDeclaration node. + */ function visitFunctionDeclaration(node) { var savedConvertedLoopState = convertedLoopState; convertedLoopState = undefined; - var ancestorFacts = enterSubtree(16286, 65); + var ancestorFacts = enterSubtree(16286 /* FunctionExcludes */, 65 /* FunctionIncludes */); var parameters = ts.visitParameterList(node.parameters, visitor, context); - var body = node.transformFlags & 64 + var body = node.transformFlags & 64 /* ES2015 */ ? transformFunctionBody(node) : visitFunctionBodyDownLevel(node); - var name = hierarchyFacts & 16384 + var name = hierarchyFacts & 16384 /* NewTarget */ ? ts.getLocalName(node) : node.name; - exitSubtree(ancestorFacts, 49152, 0); + exitSubtree(ancestorFacts, 49152 /* PropagateNewTargetMask */, 0 /* None */); convertedLoopState = savedConvertedLoopState; - return ts.updateFunctionDeclaration(node, undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), node.asteriskToken, name, undefined, parameters, undefined, body); + return ts.updateFunctionDeclaration(node, + /*decorators*/ undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), node.asteriskToken, name, + /*typeParameters*/ undefined, parameters, + /*type*/ undefined, body); } + /** + * Transforms a function-like node into a FunctionExpression. + * + * @param node The function-like node to transform. + * @param location The source-map location for the new FunctionExpression. + * @param name The name of the new FunctionExpression. + */ function transformFunctionLikeToExpression(node, location, name, container) { var savedConvertedLoopState = convertedLoopState; convertedLoopState = undefined; - var ancestorFacts = container && ts.isClassLike(container) && !ts.hasModifier(node, 32) - ? enterSubtree(16286, 65 | 8) - : enterSubtree(16286, 65); + var ancestorFacts = container && ts.isClassLike(container) && !ts.hasModifier(node, 32 /* Static */) + ? enterSubtree(16286 /* FunctionExcludes */, 65 /* FunctionIncludes */ | 8 /* NonStaticClassElement */) + : enterSubtree(16286 /* FunctionExcludes */, 65 /* FunctionIncludes */); var parameters = ts.visitParameterList(node.parameters, visitor, context); var body = transformFunctionBody(node); - if (hierarchyFacts & 16384 && !name && (node.kind === 234 || node.kind === 192)) { + if (hierarchyFacts & 16384 /* NewTarget */ && !name && (node.kind === 234 /* FunctionDeclaration */ || node.kind === 192 /* FunctionExpression */)) { name = ts.getGeneratedNameForNode(node); } - exitSubtree(ancestorFacts, 49152, 0); + exitSubtree(ancestorFacts, 49152 /* PropagateNewTargetMask */, 0 /* None */); convertedLoopState = savedConvertedLoopState; - return ts.setOriginalNode(ts.setTextRange(ts.createFunctionExpression(undefined, node.asteriskToken, name, undefined, parameters, undefined, body), location), node); + return ts.setOriginalNode(ts.setTextRange(ts.createFunctionExpression( + /*modifiers*/ undefined, node.asteriskToken, name, + /*typeParameters*/ undefined, parameters, + /*type*/ undefined, body), location), + /*original*/ node); } + /** + * Transforms the body of a function-like node. + * + * @param node A function-like node. + */ function transformFunctionBody(node) { - var multiLine = false; - var singleLine = false; + var multiLine = false; // indicates whether the block *must* be emitted as multiple lines + var singleLine = false; // indicates whether the block *may* be emitted as a single line var statementsLocation; var closeBraceLocation; var leadingStatements = []; @@ -56913,21 +67415,29 @@ var ts; var statementOffset; resumeLexicalEnvironment(); if (ts.isBlock(body)) { - statementOffset = ts.addStandardPrologue(leadingStatements, body.statements, false); + // ensureUseStrict is false because no new prologue-directive should be added. + // addStandardPrologue will put already-existing directives at the beginning of the target statement-array + statementOffset = ts.addStandardPrologue(leadingStatements, body.statements, /*ensureUseStrict*/ false); } addCaptureThisForNodeIfNeeded(leadingStatements, node); addDefaultValueAssignmentsIfNeeded(leadingStatements, node); - addRestParameterIfNeeded(leadingStatements, node, false); + addRestParameterIfNeeded(leadingStatements, node, /*inConstructorWithSynthesizedSuper*/ false); if (ts.isBlock(body)) { + // addCustomPrologue puts already-existing directives at the beginning of the target statement-array statementOffset = ts.addCustomPrologue(leadingStatements, body.statements, statementOffset, visitor); statementsLocation = body.statements; ts.addRange(statements, ts.visitNodes(body.statements, visitor, ts.isStatement, statementOffset)); + // If the original body was a multi-line block, this must be a multi-line block. if (!multiLine && body.multiLine) { multiLine = true; } } else { - ts.Debug.assert(node.kind === 193); + ts.Debug.assert(node.kind === 193 /* ArrowFunction */); + // To align with the old emitter, we use a synthetic end position on the location + // for the statement list we synthesize when we down-level an arrow function with + // an expression function body. This prevents both comments and source maps from + // being emitted for the end position only. statementsLocation = ts.moveRangeEnd(body, -1); var equalsGreaterThanToken = node.equalsGreaterThanToken; if (!ts.nodeIsSynthesized(equalsGreaterThanToken) && !ts.nodeIsSynthesized(body)) { @@ -56942,72 +67452,103 @@ var ts; var returnStatement = ts.createReturn(expression); ts.setTextRange(returnStatement, body); ts.moveSyntheticComments(returnStatement, body); - ts.setEmitFlags(returnStatement, 384 | 32 | 1024); + ts.setEmitFlags(returnStatement, 384 /* NoTokenSourceMaps */ | 32 /* NoTrailingSourceMap */ | 1024 /* NoTrailingComments */); statements.push(returnStatement); + // To align with the source map emit for the old emitter, we set a custom + // source map location for the close brace. closeBraceLocation = body; } var lexicalEnvironment = context.endLexicalEnvironment(); ts.prependStatements(statements, lexicalEnvironment); - prependCaptureNewTargetIfNeeded(statements, node, false); + prependCaptureNewTargetIfNeeded(statements, node, /*copyOnWrite*/ false); + // If we added any final generated statements, this must be a multi-line block if (ts.some(leadingStatements) || ts.some(lexicalEnvironment)) { multiLine = true; } var block = ts.createBlock(ts.setTextRange(ts.createNodeArray(leadingStatements.concat(statements)), statementsLocation), multiLine); ts.setTextRange(block, node.body); if (!multiLine && singleLine) { - ts.setEmitFlags(block, 1); + ts.setEmitFlags(block, 1 /* SingleLine */); } if (closeBraceLocation) { - ts.setTokenSourceMapRange(block, 18, closeBraceLocation); + ts.setTokenSourceMapRange(block, 18 /* CloseBraceToken */, closeBraceLocation); } ts.setOriginalNode(block, node.body); return block; } function visitFunctionBodyDownLevel(node) { var updated = ts.visitFunctionBody(node.body, functionBodyVisitor, context); - return ts.updateBlock(updated, ts.setTextRange(ts.createNodeArray(prependCaptureNewTargetIfNeeded(updated.statements, node, true)), updated.statements)); + return ts.updateBlock(updated, ts.setTextRange(ts.createNodeArray(prependCaptureNewTargetIfNeeded(updated.statements, node, /*copyOnWrite*/ true)), + /*location*/ updated.statements)); } function visitBlock(node, isFunctionBody) { if (isFunctionBody) { + // A function body is not a block scope. return ts.visitEachChild(node, visitor, context); } - var ancestorFacts = hierarchyFacts & 256 - ? enterSubtree(4032, 512) - : enterSubtree(3904, 128); + var ancestorFacts = hierarchyFacts & 256 /* IterationStatement */ + ? enterSubtree(4032 /* IterationStatementBlockExcludes */, 512 /* IterationStatementBlockIncludes */) + : enterSubtree(3904 /* BlockExcludes */, 128 /* BlockIncludes */); var updated = ts.visitEachChild(node, visitor, context); - exitSubtree(ancestorFacts, 0, 0); + exitSubtree(ancestorFacts, 0 /* None */, 0 /* None */); return updated; } + /** + * Visits an ExpressionStatement that contains a destructuring assignment. + * + * @param node An ExpressionStatement node. + */ function visitExpressionStatement(node) { + // If we are here it is most likely because our expression is a destructuring assignment. switch (node.expression.kind) { - case 191: - return ts.updateStatement(node, visitParenthesizedExpression(node.expression, false)); - case 200: - return ts.updateStatement(node, visitBinaryExpression(node.expression, false)); + case 191 /* ParenthesizedExpression */: + return ts.updateStatement(node, visitParenthesizedExpression(node.expression, /*needsDestructuringValue*/ false)); + case 200 /* BinaryExpression */: + return ts.updateStatement(node, visitBinaryExpression(node.expression, /*needsDestructuringValue*/ false)); } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a ParenthesizedExpression that may contain a destructuring assignment. + * + * @param node A ParenthesizedExpression node. + * @param needsDestructuringValue A value indicating whether we need to hold onto the rhs + * of a destructuring assignment. + */ function visitParenthesizedExpression(node, needsDestructuringValue) { + // If we are here it is most likely because our expression is a destructuring assignment. if (!needsDestructuringValue) { + // By default we always emit the RHS at the end of a flattened destructuring + // expression. If we are in a state where we do not need the destructuring value, + // we pass that information along to the children that care about it. switch (node.expression.kind) { - case 191: - return ts.updateParen(node, visitParenthesizedExpression(node.expression, false)); - case 200: - return ts.updateParen(node, visitBinaryExpression(node.expression, false)); + case 191 /* ParenthesizedExpression */: + return ts.updateParen(node, visitParenthesizedExpression(node.expression, /*needsDestructuringValue*/ false)); + case 200 /* BinaryExpression */: + return ts.updateParen(node, visitBinaryExpression(node.expression, /*needsDestructuringValue*/ false)); } } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a BinaryExpression that contains a destructuring assignment. + * + * @param node A BinaryExpression node. + * @param needsDestructuringValue A value indicating whether we need to hold onto the rhs + * of a destructuring assignment. + */ function visitBinaryExpression(node, needsDestructuringValue) { + // If we are here it is because this is a destructuring assignment. if (ts.isDestructuringAssignment(node)) { - return ts.flattenDestructuringAssignment(node, visitor, context, 0, needsDestructuringValue); + return ts.flattenDestructuringAssignment(node, visitor, context, 0 /* All */, needsDestructuringValue); } return ts.visitEachChild(node, visitor, context); } function visitVariableStatement(node) { - var ancestorFacts = enterSubtree(0, ts.hasModifier(node, 1) ? 32 : 0); + var ancestorFacts = enterSubtree(0 /* None */, ts.hasModifier(node, 1 /* Export */) ? 32 /* ExportedVariableStatement */ : 0 /* None */); var updated; - if (convertedLoopState && (node.declarationList.flags & 3) === 0) { + if (convertedLoopState && (node.declarationList.flags & 3 /* BlockScoped */) === 0) { + // we are inside a converted loop - hoist variable declarations var assignments = void 0; for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) { var decl = _a[_i]; @@ -57015,10 +67556,10 @@ var ts; if (decl.initializer) { var assignment = void 0; if (ts.isBindingPattern(decl.name)) { - assignment = ts.flattenDestructuringAssignment(decl, visitor, context, 0); + assignment = ts.flattenDestructuringAssignment(decl, visitor, context, 0 /* All */); } else { - assignment = ts.createBinary(decl.name, 58, ts.visitNode(decl.initializer, visitor, ts.isExpression)); + assignment = ts.createBinary(decl.name, 58 /* EqualsToken */, ts.visitNode(decl.initializer, visitor, ts.isExpression)); ts.setTextRange(assignment, decl); } assignments = ts.append(assignments, assignment); @@ -57028,29 +67569,37 @@ var ts; updated = ts.setTextRange(ts.createStatement(ts.inlineExpressions(assignments)), node); } else { + // none of declarations has initializer - the entire variable statement can be deleted updated = undefined; } } else { updated = ts.visitEachChild(node, visitor, context); } - exitSubtree(ancestorFacts, 0, 0); + exitSubtree(ancestorFacts, 0 /* None */, 0 /* None */); return updated; } + /** + * Visits a VariableDeclarationList that is block scoped (e.g. `let` or `const`). + * + * @param node A VariableDeclarationList node. + */ function visitVariableDeclarationList(node) { - if (node.transformFlags & 64) { - if (node.flags & 3) { + if (node.transformFlags & 64 /* ES2015 */) { + if (node.flags & 3 /* BlockScoped */) { enableSubstitutionsForBlockScopedBindings(); } - var declarations = ts.flatMap(node.declarations, node.flags & 1 + var declarations = ts.flatMap(node.declarations, node.flags & 1 /* Let */ ? visitVariableDeclarationInLetDeclarationList : visitVariableDeclaration); var declarationList = ts.createVariableDeclarationList(declarations); ts.setOriginalNode(declarationList, node); ts.setTextRange(declarationList, node); ts.setCommentRange(declarationList, node); - if (node.transformFlags & 8388608 + if (node.transformFlags & 8388608 /* ContainsBindingPattern */ && (ts.isBindingPattern(node.declarations[0].name) || ts.isBindingPattern(ts.last(node.declarations).name))) { + // If the first or last declaration is a binding pattern, we need to modify + // the source map range for the declaration list. var firstDeclaration = ts.firstOrUndefined(declarations); if (firstDeclaration) { ts.setSourceMapRange(declarationList, ts.createRange(firstDeclaration.pos, ts.last(declarations).end)); @@ -57060,23 +67609,76 @@ var ts; } return ts.visitEachChild(node, visitor, context); } + /** + * Gets a value indicating whether we should emit an explicit initializer for a variable + * declaration in a `let` declaration list. + * + * @param node A VariableDeclaration node. + */ function shouldEmitExplicitInitializerForLetDeclaration(node) { + // Nested let bindings might need to be initialized explicitly to preserve + // ES6 semantic: + // + // { let x = 1; } + // { let x; } // x here should be undefined. not 1 + // + // Top level bindings never collide with anything and thus don't require + // explicit initialization. As for nested let bindings there are two cases: + // + // - Nested let bindings that were not renamed definitely should be + // initialized explicitly: + // + // { let x = 1; } + // { let x; if (some-condition) { x = 1}; if (x) { /*1*/ } } + // + // Without explicit initialization code in /*1*/ can be executed even if + // some-condition is evaluated to false. + // + // - Renaming introduces fresh name that should not collide with any + // existing names, however renamed bindings sometimes also should be + // explicitly initialized. One particular case: non-captured binding + // declared inside loop body (but not in loop initializer): + // + // let x; + // for (;;) { + // let x; + // } + // + // In downlevel codegen inner 'x' will be renamed so it won't collide + // with outer 'x' however it will should be reset on every iteration as + // if it was declared anew. + // + // * Why non-captured binding? + // - Because if loop contains block scoped binding captured in some + // function then loop body will be rewritten to have a fresh scope + // on every iteration so everything will just work. + // + // * Why loop initializer is excluded? + // - Since we've introduced a fresh name it already will be undefined. var flags = resolver.getNodeCheckFlags(node); - var isCapturedInFunction = flags & 131072; - var isDeclaredInLoop = flags & 262144; - var emittedAsTopLevel = (hierarchyFacts & 64) !== 0 + var isCapturedInFunction = flags & 131072 /* CapturedBlockScopedBinding */; + var isDeclaredInLoop = flags & 262144 /* BlockScopedBindingInLoop */; + var emittedAsTopLevel = (hierarchyFacts & 64 /* TopLevel */) !== 0 || (isCapturedInFunction && isDeclaredInLoop - && (hierarchyFacts & 512) !== 0); + && (hierarchyFacts & 512 /* IterationStatementBlock */) !== 0); var emitExplicitInitializer = !emittedAsTopLevel - && (hierarchyFacts & 2048) === 0 + && (hierarchyFacts & 2048 /* ForInOrForOfStatement */) === 0 && (!resolver.isDeclarationWithCollidingName(node) || (isDeclaredInLoop && !isCapturedInFunction - && (hierarchyFacts & (1024 | 2048)) === 0)); + && (hierarchyFacts & (1024 /* ForStatement */ | 2048 /* ForInOrForOfStatement */)) === 0)); return emitExplicitInitializer; } + /** + * Visits a VariableDeclaration in a `let` declaration list. + * + * @param node A VariableDeclaration node. + */ function visitVariableDeclarationInLetDeclarationList(node) { + // For binding pattern names that lack initializers there is no point to emit + // explicit initializer since downlevel codegen for destructuring will fail + // in the absence of initializer so all binding elements will say uninitialized var name = node.name; if (ts.isBindingPattern(name)) { return visitVariableDeclaration(node); @@ -57088,16 +67690,22 @@ var ts; } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a VariableDeclaration node with a binding pattern. + * + * @param node A VariableDeclaration node. + */ function visitVariableDeclaration(node) { - var ancestorFacts = enterSubtree(32, 0); + var ancestorFacts = enterSubtree(32 /* ExportedVariableStatement */, 0 /* None */); var updated; if (ts.isBindingPattern(node.name)) { - updated = ts.flattenDestructuringBinding(node, visitor, context, 0, undefined, (ancestorFacts & 32) !== 0); + updated = ts.flattenDestructuringBinding(node, visitor, context, 0 /* All */, + /*value*/ undefined, (ancestorFacts & 32 /* ExportedVariableStatement */) !== 0); } else { updated = ts.visitEachChild(node, visitor, context); } - exitSubtree(ancestorFacts, 0, 0); + exitSubtree(ancestorFacts, 0 /* None */, 0 /* None */); return updated; } function recordLabel(node) { @@ -57111,67 +67719,78 @@ var ts; convertedLoopState.labels = ts.createMap(); } var statement = ts.unwrapInnermostStatementOfLabel(node, convertedLoopState && recordLabel); - return ts.isIterationStatement(statement, false) - ? visitIterationStatement(statement, node) + return ts.isIterationStatement(statement, /*lookInLabeledStatements*/ false) + ? visitIterationStatement(statement, /*outermostLabeledStatement*/ node) : ts.restoreEnclosingLabel(ts.visitNode(statement, visitor, ts.isStatement), node, convertedLoopState && resetLabel); } function visitIterationStatement(node, outermostLabeledStatement) { switch (node.kind) { - case 218: - case 219: + case 218 /* DoStatement */: + case 219 /* WhileStatement */: return visitDoOrWhileStatement(node, outermostLabeledStatement); - case 220: + case 220 /* ForStatement */: return visitForStatement(node, outermostLabeledStatement); - case 221: + case 221 /* ForInStatement */: return visitForInStatement(node, outermostLabeledStatement); - case 222: + case 222 /* ForOfStatement */: return visitForOfStatement(node, outermostLabeledStatement); } } function visitIterationStatementWithFacts(excludeFacts, includeFacts, node, outermostLabeledStatement, convert) { var ancestorFacts = enterSubtree(excludeFacts, includeFacts); var updated = convertIterationStatementBodyIfNecessary(node, outermostLabeledStatement, convert); - exitSubtree(ancestorFacts, 0, 0); + exitSubtree(ancestorFacts, 0 /* None */, 0 /* None */); return updated; } function visitDoOrWhileStatement(node, outermostLabeledStatement) { - return visitIterationStatementWithFacts(0, 256, node, outermostLabeledStatement); + return visitIterationStatementWithFacts(0 /* DoOrWhileStatementExcludes */, 256 /* DoOrWhileStatementIncludes */, node, outermostLabeledStatement); } function visitForStatement(node, outermostLabeledStatement) { - return visitIterationStatementWithFacts(3008, 1280, node, outermostLabeledStatement); + return visitIterationStatementWithFacts(3008 /* ForStatementExcludes */, 1280 /* ForStatementIncludes */, node, outermostLabeledStatement); } function visitForInStatement(node, outermostLabeledStatement) { - return visitIterationStatementWithFacts(1984, 2304, node, outermostLabeledStatement); + return visitIterationStatementWithFacts(1984 /* ForInOrForOfStatementExcludes */, 2304 /* ForInOrForOfStatementIncludes */, node, outermostLabeledStatement); } function visitForOfStatement(node, outermostLabeledStatement) { - return visitIterationStatementWithFacts(1984, 2304, node, outermostLabeledStatement, compilerOptions.downlevelIteration ? convertForOfStatementForIterable : convertForOfStatementForArray); + return visitIterationStatementWithFacts(1984 /* ForInOrForOfStatementExcludes */, 2304 /* ForInOrForOfStatementIncludes */, node, outermostLabeledStatement, compilerOptions.downlevelIteration ? convertForOfStatementForIterable : convertForOfStatementForArray); } function convertForOfStatementHead(node, boundValue, convertedLoopBodyStatements) { var statements = []; var initializer = node.initializer; if (ts.isVariableDeclarationList(initializer)) { - if (node.initializer.flags & 3) { + if (node.initializer.flags & 3 /* BlockScoped */) { enableSubstitutionsForBlockScopedBindings(); } var firstOriginalDeclaration = ts.firstOrUndefined(initializer.declarations); if (firstOriginalDeclaration && ts.isBindingPattern(firstOriginalDeclaration.name)) { - var declarations = ts.flattenDestructuringBinding(firstOriginalDeclaration, visitor, context, 0, boundValue); + // This works whether the declaration is a var, let, or const. + // It will use rhsIterationValue _a[_i] as the initializer. + var declarations = ts.flattenDestructuringBinding(firstOriginalDeclaration, visitor, context, 0 /* All */, boundValue); var declarationList = ts.setTextRange(ts.createVariableDeclarationList(declarations), node.initializer); ts.setOriginalNode(declarationList, node.initializer); + // Adjust the source map range for the first declaration to align with the old + // emitter. ts.setSourceMapRange(declarationList, ts.createRange(declarations[0].pos, ts.last(declarations).end)); - statements.push(ts.createVariableStatement(undefined, declarationList)); + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, declarationList)); } else { - statements.push(ts.setTextRange(ts.createVariableStatement(undefined, ts.setOriginalNode(ts.setTextRange(ts.createVariableDeclarationList([ - ts.createVariableDeclaration(firstOriginalDeclaration ? firstOriginalDeclaration.name : ts.createTempVariable(undefined), undefined, boundValue) + // The following call does not include the initializer, so we have + // to emit it separately. + statements.push(ts.setTextRange(ts.createVariableStatement( + /*modifiers*/ undefined, ts.setOriginalNode(ts.setTextRange(ts.createVariableDeclarationList([ + ts.createVariableDeclaration(firstOriginalDeclaration ? firstOriginalDeclaration.name : ts.createTempVariable(/*recordTempVariable*/ undefined), + /*type*/ undefined, boundValue) ]), ts.moveRangePos(initializer, -1)), initializer)), ts.moveRangeEnd(initializer, -1))); } } else { + // Initializer is an expression. Emit the expression in the body, so that it's + // evaluated on every iteration. var assignment = ts.createAssignment(initializer, boundValue); if (ts.isDestructuringAssignment(assignment)) { ts.aggregateTransformFlags(assignment); - statements.push(ts.createStatement(visitBinaryExpression(assignment, false))); + statements.push(ts.createStatement(visitBinaryExpression(assignment, /*needsDestructuringValue*/ false))); } else { assignment.end = initializer.end; @@ -57193,62 +67812,111 @@ var ts; } } function createSyntheticBlockForConvertedStatements(statements) { - return ts.setEmitFlags(ts.createBlock(ts.createNodeArray(statements), true), 48 | 384); + return ts.setEmitFlags(ts.createBlock(ts.createNodeArray(statements), + /*multiLine*/ true), 48 /* NoSourceMap */ | 384 /* NoTokenSourceMaps */); } function convertForOfStatementForArray(node, outermostLabeledStatement, convertedLoopBodyStatements) { + // The following ES6 code: + // + // for (let v of expr) { } + // + // should be emitted as + // + // for (var _i = 0, _a = expr; _i < _a.length; _i++) { + // var 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. var expression = ts.visitNode(node.expression, visitor, ts.isExpression); + // 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. var counter = ts.createLoopVariable(); - var rhsReference = ts.isIdentifier(expression) ? ts.getGeneratedNameForNode(expression) : ts.createTempVariable(undefined); - ts.setEmitFlags(expression, 48 | ts.getEmitFlags(expression)); - var forStatement = ts.setTextRange(ts.createFor(ts.setEmitFlags(ts.setTextRange(ts.createVariableDeclarationList([ - ts.setTextRange(ts.createVariableDeclaration(counter, undefined, ts.createLiteral(0)), ts.moveRangePos(node.expression, -1)), - ts.setTextRange(ts.createVariableDeclaration(rhsReference, undefined, expression), node.expression) - ]), node.expression), 2097152), ts.setTextRange(ts.createLessThan(counter, ts.createPropertyAccess(rhsReference, "length")), node.expression), ts.setTextRange(ts.createPostfixIncrement(counter), node.expression), convertForOfStatementHead(node, ts.createElementAccess(rhsReference, counter), convertedLoopBodyStatements)), node); - ts.setEmitFlags(forStatement, 256); + var rhsReference = ts.isIdentifier(expression) ? ts.getGeneratedNameForNode(expression) : ts.createTempVariable(/*recordTempVariable*/ undefined); + // The old emitter does not emit source maps for the expression + ts.setEmitFlags(expression, 48 /* NoSourceMap */ | ts.getEmitFlags(expression)); + var forStatement = ts.setTextRange(ts.createFor( + /*initializer*/ ts.setEmitFlags(ts.setTextRange(ts.createVariableDeclarationList([ + ts.setTextRange(ts.createVariableDeclaration(counter, /*type*/ undefined, ts.createLiteral(0)), ts.moveRangePos(node.expression, -1)), + ts.setTextRange(ts.createVariableDeclaration(rhsReference, /*type*/ undefined, expression), node.expression) + ]), node.expression), 2097152 /* NoHoisting */), + /*condition*/ ts.setTextRange(ts.createLessThan(counter, ts.createPropertyAccess(rhsReference, "length")), node.expression), + /*incrementor*/ ts.setTextRange(ts.createPostfixIncrement(counter), node.expression), + /*statement*/ convertForOfStatementHead(node, ts.createElementAccess(rhsReference, counter), convertedLoopBodyStatements)), + /*location*/ node); + // Disable trailing source maps for the OpenParenToken to align source map emit with the old emitter. + ts.setEmitFlags(forStatement, 256 /* NoTokenTrailingSourceMaps */); ts.setTextRange(forStatement, node); return ts.restoreEnclosingLabel(forStatement, outermostLabeledStatement, convertedLoopState && resetLabel); } function convertForOfStatementForIterable(node, outermostLabeledStatement, convertedLoopBodyStatements) { var expression = ts.visitNode(node.expression, visitor, ts.isExpression); - var iterator = ts.isIdentifier(expression) ? ts.getGeneratedNameForNode(expression) : ts.createTempVariable(undefined); - var result = ts.isIdentifier(expression) ? ts.getGeneratedNameForNode(iterator) : ts.createTempVariable(undefined); + var iterator = ts.isIdentifier(expression) ? ts.getGeneratedNameForNode(expression) : ts.createTempVariable(/*recordTempVariable*/ undefined); + var result = ts.isIdentifier(expression) ? ts.getGeneratedNameForNode(iterator) : ts.createTempVariable(/*recordTempVariable*/ undefined); var errorRecord = ts.createUniqueName("e"); var catchVariable = ts.getGeneratedNameForNode(errorRecord); - var returnMethod = ts.createTempVariable(undefined); + var returnMethod = ts.createTempVariable(/*recordTempVariable*/ undefined); var values = ts.createValuesHelper(context, expression, node.expression); - var next = ts.createCall(ts.createPropertyAccess(iterator, "next"), undefined, []); + var next = ts.createCall(ts.createPropertyAccess(iterator, "next"), /*typeArguments*/ undefined, []); hoistVariableDeclaration(errorRecord); hoistVariableDeclaration(returnMethod); - var forStatement = ts.setEmitFlags(ts.setTextRange(ts.createFor(ts.setEmitFlags(ts.setTextRange(ts.createVariableDeclarationList([ - ts.setTextRange(ts.createVariableDeclaration(iterator, undefined, values), node.expression), - ts.createVariableDeclaration(result, undefined, next) - ]), node.expression), 2097152), ts.createLogicalNot(ts.createPropertyAccess(result, "done")), ts.createAssignment(result, next), convertForOfStatementHead(node, ts.createPropertyAccess(result, "value"), convertedLoopBodyStatements)), node), 256); + var forStatement = ts.setEmitFlags(ts.setTextRange(ts.createFor( + /*initializer*/ ts.setEmitFlags(ts.setTextRange(ts.createVariableDeclarationList([ + ts.setTextRange(ts.createVariableDeclaration(iterator, /*type*/ undefined, values), node.expression), + ts.createVariableDeclaration(result, /*type*/ undefined, next) + ]), node.expression), 2097152 /* NoHoisting */), + /*condition*/ ts.createLogicalNot(ts.createPropertyAccess(result, "done")), + /*incrementor*/ ts.createAssignment(result, next), + /*statement*/ convertForOfStatementHead(node, ts.createPropertyAccess(result, "value"), convertedLoopBodyStatements)), + /*location*/ node), 256 /* NoTokenTrailingSourceMaps */); return ts.createTry(ts.createBlock([ ts.restoreEnclosingLabel(forStatement, outermostLabeledStatement, convertedLoopState && resetLabel) ]), ts.createCatchClause(ts.createVariableDeclaration(catchVariable), ts.setEmitFlags(ts.createBlock([ ts.createStatement(ts.createAssignment(errorRecord, ts.createObjectLiteral([ ts.createPropertyAssignment("error", catchVariable) ]))) - ]), 1)), ts.createBlock([ - ts.createTry(ts.createBlock([ - ts.setEmitFlags(ts.createIf(ts.createLogicalAnd(ts.createLogicalAnd(result, ts.createLogicalNot(ts.createPropertyAccess(result, "done"))), ts.createAssignment(returnMethod, ts.createPropertyAccess(iterator, "return"))), ts.createStatement(ts.createFunctionCall(returnMethod, iterator, []))), 1), - ]), undefined, ts.setEmitFlags(ts.createBlock([ - ts.setEmitFlags(ts.createIf(errorRecord, ts.createThrow(ts.createPropertyAccess(errorRecord, "error"))), 1) - ]), 1)) + ]), 1 /* SingleLine */)), ts.createBlock([ + ts.createTry( + /*tryBlock*/ ts.createBlock([ + ts.setEmitFlags(ts.createIf(ts.createLogicalAnd(ts.createLogicalAnd(result, ts.createLogicalNot(ts.createPropertyAccess(result, "done"))), ts.createAssignment(returnMethod, ts.createPropertyAccess(iterator, "return"))), ts.createStatement(ts.createFunctionCall(returnMethod, iterator, []))), 1 /* SingleLine */), + ]), + /*catchClause*/ undefined, + /*finallyBlock*/ ts.setEmitFlags(ts.createBlock([ + ts.setEmitFlags(ts.createIf(errorRecord, ts.createThrow(ts.createPropertyAccess(errorRecord, "error"))), 1 /* SingleLine */) + ]), 1 /* SingleLine */)) ])); } + /** + * Visits an ObjectLiteralExpression with computed property names. + * + * @param node An ObjectLiteralExpression node. + */ function visitObjectLiteralExpression(node) { + // We are here because a ComputedPropertyName was used somewhere in the expression. var properties = node.properties; var numProperties = properties.length; + // Find the first computed property. + // Everything until that point can be emitted as part of the initial object literal. var numInitialProperties = numProperties; var numInitialPropertiesWithoutYield = numProperties; for (var i = 0; i < numProperties; i++) { var property = properties[i]; - if ((property.transformFlags & 16777216 && hierarchyFacts & 4) + if ((property.transformFlags & 16777216 /* ContainsYield */ && hierarchyFacts & 4 /* AsyncFunctionBody */) && i < numInitialPropertiesWithoutYield) { numInitialPropertiesWithoutYield = i; } - if (property.name.kind === 147) { + if (property.name.kind === 147 /* ComputedPropertyName */) { numInitialProperties = i; break; } @@ -57257,29 +67925,37 @@ var ts; if (numInitialPropertiesWithoutYield < numInitialProperties) { numInitialProperties = numInitialPropertiesWithoutYield; } + // 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. var temp = ts.createTempVariable(hoistVariableDeclaration); + // Write out the first non-computed properties, then emit the rest through indexing on the temp variable. var expressions = []; - var assignment = ts.createAssignment(temp, ts.setEmitFlags(ts.createObjectLiteral(ts.visitNodes(properties, visitor, ts.isObjectLiteralElementLike, 0, numInitialProperties), node.multiLine), 65536)); + var assignment = ts.createAssignment(temp, ts.setEmitFlags(ts.createObjectLiteral(ts.visitNodes(properties, visitor, ts.isObjectLiteralElementLike, 0, numInitialProperties), node.multiLine), 65536 /* Indented */)); if (node.multiLine) { ts.startOnNewLine(assignment); } expressions.push(assignment); addObjectLiteralMembers(expressions, node, temp, numInitialProperties); + // We need to clone the temporary identifier so that we can write it on a + // new line expressions.push(node.multiLine ? ts.startOnNewLine(ts.getMutableClone(temp)) : temp); return ts.inlineExpressions(expressions); } return ts.visitEachChild(node, visitor, context); } function shouldConvertIterationStatementBody(node) { - return (resolver.getNodeCheckFlags(node) & 65536) !== 0; + return (resolver.getNodeCheckFlags(node) & 65536 /* LoopWithCapturedBlockScopedBinding */) !== 0; } + /** + * Records constituents of name for the given variable to be hoisted in the outer scope. + */ function hoistVariableDeclarationDeclaredInConvertedLoop(state, node) { if (!state.hoistedLocalVariables) { state.hoistedLocalVariables = []; } visit(node.name); function visit(node) { - if (node.kind === 71) { + if (node.kind === 71 /* Identifier */) { state.hoistedLocalVariables.push(node); } else { @@ -57296,11 +67972,13 @@ var ts; if (!shouldConvertIterationStatementBody(node)) { var saveAllowedNonLabeledJumps = void 0; if (convertedLoopState) { + // we get here if we are trying to emit normal loop loop inside converted loop + // set allowedNonLabeledJumps to Break | Continue to mark that break\continue inside the loop should be emitted as is saveAllowedNonLabeledJumps = convertedLoopState.allowedNonLabeledJumps; - convertedLoopState.allowedNonLabeledJumps = 2 | 4; + convertedLoopState.allowedNonLabeledJumps = 2 /* Break */ | 4 /* Continue */; } var result = convert - ? convert(node, outermostLabeledStatement, undefined) + ? convert(node, outermostLabeledStatement, /*convertedLoopBodyStatements*/ undefined) : ts.restoreEnclosingLabel(ts.visitEachChild(node, visitor, context), outermostLabeledStatement, convertedLoopState && resetLabel); if (convertedLoopState) { convertedLoopState.allowedNonLabeledJumps = saveAllowedNonLabeledJumps; @@ -57310,18 +67988,20 @@ var ts; var functionName = ts.createUniqueName("_loop"); var loopInitializer; switch (node.kind) { - case 220: - case 221: - case 222: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: var initializer = node.initializer; - if (initializer && initializer.kind === 233) { + if (initializer && initializer.kind === 233 /* VariableDeclarationList */) { loopInitializer = initializer; } break; } + // variables that will be passed to the loop as parameters var loopParameters = []; + // variables declared in the loop initializer that will be changed inside the loop var loopOutParameters = []; - if (loopInitializer && (ts.getCombinedNodeFlags(loopInitializer) & 3)) { + if (loopInitializer && (ts.getCombinedNodeFlags(loopInitializer) & 3 /* BlockScoped */)) { for (var _i = 0, _a = loopInitializer.declarations; _i < _a.length; _i++) { var decl = _a[_i]; processLoopVariableDeclaration(decl, loopParameters, loopOutParameters); @@ -57330,13 +68010,21 @@ var ts; var outerConvertedLoopState = convertedLoopState; convertedLoopState = { loopOutParameters: loopOutParameters }; if (outerConvertedLoopState) { + // convertedOuterLoopState !== undefined means that this converted loop is nested in another converted loop. + // if outer converted loop has already accumulated some state - pass it through if (outerConvertedLoopState.argumentsName) { + // outer loop has already used 'arguments' so we've already have some name to alias it + // use the same name in all nested loops convertedLoopState.argumentsName = outerConvertedLoopState.argumentsName; } if (outerConvertedLoopState.thisName) { + // outer loop has already used 'this' so we've already have some name to alias it + // use the same name in all nested loops convertedLoopState.thisName = outerConvertedLoopState.thisName; } if (outerConvertedLoopState.hoistedLocalVariables) { + // we've already collected some non-block scoped variable declarations in enclosing loop + // use the same storage in nested loop convertedLoopState.hoistedLocalVariables = outerConvertedLoopState.hoistedLocalVariables; } } @@ -57348,61 +68036,83 @@ var ts; if (loopOutParameters.length || lexicalEnvironment) { var statements_4 = ts.isBlock(loopBody) ? loopBody.statements.slice() : [loopBody]; if (loopOutParameters.length) { - copyOutParameters(loopOutParameters, 1, statements_4); + copyOutParameters(loopOutParameters, 1 /* ToOutParameter */, statements_4); } ts.prependStatements(statements_4, lexicalEnvironment); - loopBody = ts.createBlock(statements_4, true); + loopBody = ts.createBlock(statements_4, /*multiline*/ true); } if (ts.isBlock(loopBody)) { loopBody.multiLine = true; } else { - loopBody = ts.createBlock([loopBody], true); + loopBody = ts.createBlock([loopBody], /*multiline*/ true); } - var containsYield = (node.statement.transformFlags & 16777216) !== 0; - var isAsyncBlockContainingAwait = containsYield && (hierarchyFacts & 4) !== 0; + var containsYield = (node.statement.transformFlags & 16777216 /* ContainsYield */) !== 0; + var isAsyncBlockContainingAwait = containsYield && (hierarchyFacts & 4 /* AsyncFunctionBody */) !== 0; var loopBodyFlags = 0; if (currentState.containsLexicalThis) { - loopBodyFlags |= 8; + loopBodyFlags |= 8 /* CapturesThis */; } if (isAsyncBlockContainingAwait) { - loopBodyFlags |= 262144; + loopBodyFlags |= 262144 /* AsyncFunctionBody */; } - var convertedLoopVariable = ts.createVariableStatement(undefined, ts.setEmitFlags(ts.createVariableDeclarationList([ - ts.createVariableDeclaration(functionName, undefined, ts.setEmitFlags(ts.createFunctionExpression(undefined, containsYield ? ts.createToken(39) : undefined, undefined, undefined, loopParameters, undefined, loopBody), loopBodyFlags)) - ]), 2097152)); + var convertedLoopVariable = ts.createVariableStatement( + /*modifiers*/ undefined, ts.setEmitFlags(ts.createVariableDeclarationList([ + ts.createVariableDeclaration(functionName, + /*type*/ undefined, ts.setEmitFlags(ts.createFunctionExpression( + /*modifiers*/ undefined, containsYield ? ts.createToken(39 /* AsteriskToken */) : undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, loopParameters, + /*type*/ undefined, loopBody), loopBodyFlags)) + ]), 2097152 /* NoHoisting */)); var statements = [convertedLoopVariable]; var extraVariableDeclarations; + // propagate state from the inner loop to the outer loop if necessary if (currentState.argumentsName) { + // if alias for arguments is set if (outerConvertedLoopState) { + // pass it to outer converted loop outerConvertedLoopState.argumentsName = currentState.argumentsName; } else { - (extraVariableDeclarations || (extraVariableDeclarations = [])).push(ts.createVariableDeclaration(currentState.argumentsName, undefined, ts.createIdentifier("arguments"))); + // this is top level converted loop and we need to create an alias for 'arguments' object + (extraVariableDeclarations || (extraVariableDeclarations = [])).push(ts.createVariableDeclaration(currentState.argumentsName, + /*type*/ undefined, ts.createIdentifier("arguments"))); } } if (currentState.thisName) { + // if alias for this is set if (outerConvertedLoopState) { + // pass it to outer converted loop outerConvertedLoopState.thisName = currentState.thisName; } else { - (extraVariableDeclarations || (extraVariableDeclarations = [])).push(ts.createVariableDeclaration(currentState.thisName, undefined, ts.createIdentifier("this"))); + // this is top level converted loop so we need to create an alias for 'this' here + // NOTE: + // if converted loops were all nested in arrow function then we'll always emit '_this' so convertedLoopState.thisName will not be set. + // If it is set this means that all nested loops are not nested in arrow function and it is safe to capture 'this'. + (extraVariableDeclarations || (extraVariableDeclarations = [])).push(ts.createVariableDeclaration(currentState.thisName, + /*type*/ undefined, ts.createIdentifier("this"))); } } if (currentState.hoistedLocalVariables) { + // if hoistedLocalVariables !== undefined this means that we've possibly collected some variable declarations to be hoisted later if (outerConvertedLoopState) { + // pass them to outer converted loop outerConvertedLoopState.hoistedLocalVariables = currentState.hoistedLocalVariables; } else { if (!extraVariableDeclarations) { extraVariableDeclarations = []; } + // hoist collected variable declarations for (var _b = 0, _c = currentState.hoistedLocalVariables; _b < _c.length; _b++) { var identifier = _c[_b]; extraVariableDeclarations.push(ts.createVariableDeclaration(identifier)); } } } + // add extra variables to hold out parameters if necessary if (loopOutParameters.length) { if (!extraVariableDeclarations) { extraVariableDeclarations = []; @@ -57412,8 +68122,10 @@ var ts; extraVariableDeclarations.push(ts.createVariableDeclaration(outParam.outParamName)); } } + // create variable statement to hold all introduced variable declarations if (extraVariableDeclarations) { - statements.push(ts.createVariableStatement(undefined, ts.createVariableDeclarationList(extraVariableDeclarations))); + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList(extraVariableDeclarations))); } var convertedLoopBodyStatements = generateCallToConvertedLoop(functionName, loopParameters, currentState, containsYield); var loop; @@ -57422,9 +68134,13 @@ var ts; } else { var clone_3 = ts.getMutableClone(node); + // clean statement part clone_3.statement = undefined; + // visit childnodes to transform initializer/condition/incrementor parts clone_3 = ts.visitEachChild(clone_3, visitor, context); - clone_3.statement = ts.createBlock(convertedLoopBodyStatements, true); + // set loop statement + clone_3.statement = ts.createBlock(convertedLoopBodyStatements, /*multiline*/ true); + // reset and re-aggregate the transform flags clone_3.transformFlags = 0; ts.aggregateTransformFlags(clone_3); loop = ts.restoreEnclosingLabel(clone_3, outermostLabeledStatement, convertedLoopState && resetLabel); @@ -57433,9 +68149,9 @@ var ts; return statements; } function copyOutParameter(outParam, copyDirection) { - var source = copyDirection === 0 ? outParam.outParamName : outParam.originalName; - var target = copyDirection === 0 ? outParam.originalName : outParam.outParamName; - return ts.createBinary(target, 58, source); + var source = copyDirection === 0 /* ToOriginal */ ? outParam.outParamName : outParam.originalName; + var target = copyDirection === 0 /* ToOriginal */ ? outParam.originalName : outParam.outParamName; + return ts.createBinary(target, 58 /* EqualsToken */, source); } function copyOutParameters(outParams, copyDirection, statements) { for (var _i = 0, outParams_1 = outParams; _i < outParams_1.length; _i++) { @@ -57446,40 +68162,44 @@ var ts; function generateCallToConvertedLoop(loopFunctionExpressionName, parameters, state, isAsyncBlockContainingAwait) { var outerConvertedLoopState = convertedLoopState; var statements = []; - var isSimpleLoop = !(state.nonLocalJumps & ~4) && + // loop is considered simple if it does not have any return statements or break\continue that transfer control outside of the loop + // simple loops are emitted as just 'loop()'; + // NOTE: if loop uses only 'continue' it still will be emitted as simple loop + var isSimpleLoop = !(state.nonLocalJumps & ~4 /* Continue */) && !state.labeledNonLocalBreaks && !state.labeledNonLocalContinues; - var call = ts.createCall(loopFunctionExpressionName, undefined, ts.map(parameters, function (p) { return p.name; })); + var call = ts.createCall(loopFunctionExpressionName, /*typeArguments*/ undefined, ts.map(parameters, function (p) { return p.name; })); var callResult = isAsyncBlockContainingAwait - ? ts.createYield(ts.createToken(39), ts.setEmitFlags(call, 8388608)) + ? ts.createYield(ts.createToken(39 /* AsteriskToken */), ts.setEmitFlags(call, 8388608 /* Iterator */)) : call; if (isSimpleLoop) { statements.push(ts.createStatement(callResult)); - copyOutParameters(state.loopOutParameters, 0, statements); + copyOutParameters(state.loopOutParameters, 0 /* ToOriginal */, statements); } else { var loopResultName = ts.createUniqueName("state"); - var stateVariable = ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(loopResultName, undefined, callResult)])); + var stateVariable = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(loopResultName, /*type*/ undefined, callResult)])); statements.push(stateVariable); - copyOutParameters(state.loopOutParameters, 0, statements); - if (state.nonLocalJumps & 8) { + copyOutParameters(state.loopOutParameters, 0 /* ToOriginal */, statements); + if (state.nonLocalJumps & 8 /* Return */) { var returnStatement = void 0; if (outerConvertedLoopState) { - outerConvertedLoopState.nonLocalJumps |= 8; + outerConvertedLoopState.nonLocalJumps |= 8 /* Return */; returnStatement = ts.createReturn(loopResultName); } else { returnStatement = ts.createReturn(ts.createPropertyAccess(loopResultName, "value")); } - statements.push(ts.createIf(ts.createBinary(ts.createTypeOf(loopResultName), 34, ts.createLiteral("object")), returnStatement)); + statements.push(ts.createIf(ts.createBinary(ts.createTypeOf(loopResultName), 34 /* EqualsEqualsEqualsToken */, ts.createLiteral("object")), returnStatement)); } - if (state.nonLocalJumps & 2) { - statements.push(ts.createIf(ts.createBinary(loopResultName, 34, ts.createLiteral("break")), ts.createBreak())); + if (state.nonLocalJumps & 2 /* Break */) { + statements.push(ts.createIf(ts.createBinary(loopResultName, 34 /* EqualsEqualsEqualsToken */, ts.createLiteral("break")), ts.createBreak())); } if (state.labeledNonLocalBreaks || state.labeledNonLocalContinues) { var caseClauses = []; - processLabeledJumps(state.labeledNonLocalBreaks, true, loopResultName, outerConvertedLoopState, caseClauses); - processLabeledJumps(state.labeledNonLocalContinues, false, loopResultName, outerConvertedLoopState, caseClauses); + processLabeledJumps(state.labeledNonLocalBreaks, /*isBreak*/ true, loopResultName, outerConvertedLoopState, caseClauses); + processLabeledJumps(state.labeledNonLocalContinues, /*isBreak*/ false, loopResultName, outerConvertedLoopState, caseClauses); statements.push(ts.createSwitch(loopResultName, ts.createCaseBlock(caseClauses))); } } @@ -57505,6 +68225,9 @@ var ts; } table.forEach(function (labelMarker, labelText) { var statements = []; + // if there are no outer converted loop or outer label in question is located inside outer converted loop + // then emit labeled break\continue + // otherwise propagate pair 'label -> marker' to outer converted loop and emit 'return labelMarker' so outer loop can later decide what to do if (!outerLoop || (outerLoop.labels && outerLoop.labels.get(labelText))) { var label = ts.createIdentifier(labelText); statements.push(isBreak ? ts.createBreak(label) : ts.createContinue(label)); @@ -57527,33 +68250,42 @@ var ts; } } else { - loopParameters.push(ts.createParameter(undefined, undefined, undefined, name)); - if (resolver.getNodeCheckFlags(decl) & 2097152) { + loopParameters.push(ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, name)); + if (resolver.getNodeCheckFlags(decl) & 2097152 /* NeedsLoopOutParameter */) { var outParamName = ts.createUniqueName("out_" + ts.idText(name)); loopOutParameters.push({ originalName: name, outParamName: outParamName }); } } } + /** + * Adds the members of an object literal to an array of expressions. + * + * @param expressions An array of expressions. + * @param node An ObjectLiteralExpression node. + * @param receiver The receiver for members of the ObjectLiteralExpression. + * @param numInitialNonComputedProperties The number of initial properties without + * computed property names. + */ function addObjectLiteralMembers(expressions, node, receiver, start) { var properties = node.properties; var numProperties = properties.length; for (var i = start; i < numProperties; i++) { var property = properties[i]; switch (property.kind) { - case 156: - case 157: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: var accessors = ts.getAllAccessorDeclarations(node.properties, property); if (property === accessors.firstAccessor) { expressions.push(transformAccessorsToExpression(receiver, accessors, node, !!node.multiLine)); } break; - case 154: + case 154 /* MethodDeclaration */: expressions.push(transformObjectLiteralMethodDeclarationToExpression(property, receiver, node, node.multiLine)); break; - case 270: + case 270 /* PropertyAssignment */: expressions.push(transformPropertyAssignmentToExpression(property, receiver, node.multiLine)); break; - case 271: + case 271 /* ShorthandPropertyAssignment */: expressions.push(transformShorthandPropertyAssignmentToExpression(property, receiver, node.multiLine)); break; default: @@ -57562,6 +68294,13 @@ var ts; } } } + /** + * Transforms a PropertyAssignment node into an expression. + * + * @param node The ObjectLiteralExpression that contains the PropertyAssignment. + * @param property The PropertyAssignment node. + * @param receiver The receiver for the assignment. + */ function transformPropertyAssignmentToExpression(property, receiver, startsOnNewLine) { var expression = ts.createAssignment(ts.createMemberAccessForPropertyName(receiver, ts.visitNode(property.name, visitor, ts.isPropertyName)), ts.visitNode(property.initializer, visitor, ts.isExpression)); ts.setTextRange(expression, property); @@ -57570,6 +68309,13 @@ var ts; } return expression; } + /** + * Transforms a ShorthandPropertyAssignment node into an expression. + * + * @param node The ObjectLiteralExpression that contains the ShorthandPropertyAssignment. + * @param property The ShorthandPropertyAssignment node. + * @param receiver The receiver for the assignment. + */ function transformShorthandPropertyAssignmentToExpression(property, receiver, startsOnNewLine) { var expression = ts.createAssignment(ts.createMemberAccessForPropertyName(receiver, ts.visitNode(property.name, visitor, ts.isPropertyName)), ts.getSynthesizedClone(property.name)); ts.setTextRange(expression, property); @@ -57578,103 +68324,201 @@ var ts; } return expression; } + /** + * Transforms a MethodDeclaration of an ObjectLiteralExpression into an expression. + * + * @param node The ObjectLiteralExpression that contains the MethodDeclaration. + * @param method The MethodDeclaration node. + * @param receiver The receiver for the assignment. + */ function transformObjectLiteralMethodDeclarationToExpression(method, receiver, container, startsOnNewLine) { - var ancestorFacts = enterSubtree(0, 0); - var expression = ts.createAssignment(ts.createMemberAccessForPropertyName(receiver, ts.visitNode(method.name, visitor, ts.isPropertyName)), transformFunctionLikeToExpression(method, method, undefined, container)); + var ancestorFacts = enterSubtree(0 /* None */, 0 /* None */); + var expression = ts.createAssignment(ts.createMemberAccessForPropertyName(receiver, ts.visitNode(method.name, visitor, ts.isPropertyName)), transformFunctionLikeToExpression(method, /*location*/ method, /*name*/ undefined, container)); ts.setTextRange(expression, method); if (startsOnNewLine) { ts.startOnNewLine(expression); } - exitSubtree(ancestorFacts, 49152, hierarchyFacts & 49152 ? 16384 : 0); + exitSubtree(ancestorFacts, 49152 /* PropagateNewTargetMask */, hierarchyFacts & 49152 /* PropagateNewTargetMask */ ? 16384 /* NewTarget */ : 0 /* None */); return expression; } function visitCatchClause(node) { - var ancestorFacts = enterSubtree(4032, 0); + var ancestorFacts = enterSubtree(4032 /* BlockScopeExcludes */, 0 /* BlockScopeIncludes */); var updated; ts.Debug.assert(!!node.variableDeclaration, "Catch clause variable should always be present when downleveling ES2015."); if (ts.isBindingPattern(node.variableDeclaration.name)) { - var temp = ts.createTempVariable(undefined); + var temp = ts.createTempVariable(/*recordTempVariable*/ undefined); var newVariableDeclaration = ts.createVariableDeclaration(temp); ts.setTextRange(newVariableDeclaration, node.variableDeclaration); - var vars = ts.flattenDestructuringBinding(node.variableDeclaration, visitor, context, 0, temp); + var vars = ts.flattenDestructuringBinding(node.variableDeclaration, visitor, context, 0 /* All */, temp); var list = ts.createVariableDeclarationList(vars); ts.setTextRange(list, node.variableDeclaration); - var destructure = ts.createVariableStatement(undefined, list); + var destructure = ts.createVariableStatement(/*modifiers*/ undefined, list); updated = ts.updateCatchClause(node, newVariableDeclaration, addStatementToStartOfBlock(node.block, destructure)); } else { updated = ts.visitEachChild(node, visitor, context); } - exitSubtree(ancestorFacts, 0, 0); + exitSubtree(ancestorFacts, 0 /* None */, 0 /* None */); return updated; } function addStatementToStartOfBlock(block, statement) { var transformedStatements = ts.visitNodes(block.statements, visitor, ts.isStatement); return ts.updateBlock(block, [statement].concat(transformedStatements)); } + /** + * Visits a MethodDeclaration of an ObjectLiteralExpression and transforms it into a + * PropertyAssignment. + * + * @param node A MethodDeclaration node. + */ function visitMethodDeclaration(node) { + // We should only get here for methods on an object literal with regular identifier names. + // Methods on classes are handled in visitClassDeclaration/visitClassExpression. + // Methods with computed property names are handled in visitObjectLiteralExpression. ts.Debug.assert(!ts.isComputedPropertyName(node.name)); - var functionExpression = transformFunctionLikeToExpression(node, ts.moveRangePos(node, -1), undefined, undefined); - ts.setEmitFlags(functionExpression, 512 | ts.getEmitFlags(functionExpression)); - return ts.setTextRange(ts.createPropertyAssignment(node.name, functionExpression), node); + var functionExpression = transformFunctionLikeToExpression(node, /*location*/ ts.moveRangePos(node, -1), /*name*/ undefined, /*container*/ undefined); + ts.setEmitFlags(functionExpression, 512 /* NoLeadingComments */ | ts.getEmitFlags(functionExpression)); + return ts.setTextRange(ts.createPropertyAssignment(node.name, functionExpression), + /*location*/ node); } + /** + * Visits an AccessorDeclaration of an ObjectLiteralExpression. + * + * @param node An AccessorDeclaration node. + */ function visitAccessorDeclaration(node) { ts.Debug.assert(!ts.isComputedPropertyName(node.name)); var savedConvertedLoopState = convertedLoopState; convertedLoopState = undefined; - var ancestorFacts = enterSubtree(16286, 65); + var ancestorFacts = enterSubtree(16286 /* FunctionExcludes */, 65 /* FunctionIncludes */); var updated; var parameters = ts.visitParameterList(node.parameters, visitor, context); - var body = node.transformFlags & (32768 | 128) + var body = node.transformFlags & (32768 /* ContainsCapturedLexicalThis */ | 128 /* ContainsES2015 */) ? transformFunctionBody(node) : visitFunctionBodyDownLevel(node); - if (node.kind === 156) { + if (node.kind === 156 /* GetAccessor */) { updated = ts.updateGetAccessor(node, node.decorators, node.modifiers, node.name, parameters, node.type, body); } else { updated = ts.updateSetAccessor(node, node.decorators, node.modifiers, node.name, parameters, body); } - exitSubtree(ancestorFacts, 49152, 0); + exitSubtree(ancestorFacts, 49152 /* PropagateNewTargetMask */, 0 /* None */); convertedLoopState = savedConvertedLoopState; return updated; } + /** + * Visits a ShorthandPropertyAssignment and transforms it into a PropertyAssignment. + * + * @param node A ShorthandPropertyAssignment node. + */ function visitShorthandPropertyAssignment(node) { - return ts.setTextRange(ts.createPropertyAssignment(node.name, ts.getSynthesizedClone(node.name)), node); + return ts.setTextRange(ts.createPropertyAssignment(node.name, ts.getSynthesizedClone(node.name)), + /*location*/ node); } function visitComputedPropertyName(node) { - var ancestorFacts = enterSubtree(0, 8192); + var ancestorFacts = enterSubtree(0 /* ComputedPropertyNameExcludes */, 8192 /* ComputedPropertyNameIncludes */); var updated = ts.visitEachChild(node, visitor, context); - exitSubtree(ancestorFacts, 49152, hierarchyFacts & 49152 ? 32768 : 0); + exitSubtree(ancestorFacts, 49152 /* PropagateNewTargetMask */, hierarchyFacts & 49152 /* PropagateNewTargetMask */ ? 32768 /* NewTargetInComputedPropertyName */ : 0 /* None */); return updated; } + /** + * Visits a YieldExpression node. + * + * @param node A YieldExpression node. + */ function visitYieldExpression(node) { + // `yield` expressions are transformed using the generators transformer. return ts.visitEachChild(node, visitor, context); } + /** + * Visits an ArrayLiteralExpression that contains a spread element. + * + * @param node An ArrayLiteralExpression node. + */ function visitArrayLiteralExpression(node) { - if (node.transformFlags & 64) { - return transformAndSpreadElements(node.elements, true, !!node.multiLine, !!node.elements.hasTrailingComma); + if (node.transformFlags & 64 /* ES2015 */) { + // We are here because we contain a SpreadElementExpression. + return transformAndSpreadElements(node.elements, /*needsUniqueCopy*/ true, !!node.multiLine, /*hasTrailingComma*/ !!node.elements.hasTrailingComma); } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a CallExpression that contains either a spread element or `super`. + * + * @param node a CallExpression. + */ function visitCallExpression(node) { - if (ts.getEmitFlags(node) & 33554432) { + if (ts.getEmitFlags(node) & 33554432 /* TypeScriptClassWrapper */) { return visitTypeScriptClassWrapper(node); } - if (node.transformFlags & 64) { - return visitCallExpressionWithPotentialCapturedThisAssignment(node, true); + if (node.transformFlags & 64 /* ES2015 */) { + return visitCallExpressionWithPotentialCapturedThisAssignment(node, /*assignToCapturedThis*/ true); } - return ts.updateCall(node, ts.visitNode(node.expression, callExpressionVisitor, ts.isExpression), undefined, ts.visitNodes(node.arguments, visitor, ts.isExpression)); + return ts.updateCall(node, ts.visitNode(node.expression, callExpressionVisitor, ts.isExpression), + /*typeArguments*/ undefined, ts.visitNodes(node.arguments, visitor, ts.isExpression)); } function visitTypeScriptClassWrapper(node) { + // This is a call to a class wrapper function (an IIFE) created by the 'ts' transformer. + // The wrapper has a form similar to: + // + // (function() { + // class C { // 1 + // } + // C.x = 1; // 2 + // return C; + // }()) + // + // When we transform the class, we end up with something like this: + // + // (function () { + // var C = (function () { // 3 + // function C() { + // } + // return C; // 4 + // }()); + // C.x = 1; + // return C; + // }()) + // + // We want to simplify the two nested IIFEs to end up with something like this: + // + // (function () { + // function C() { + // } + // C.x = 1; + // return C; + // }()) + // We skip any outer expressions in a number of places to get to the innermost + // expression, but we will restore them later to preserve comments and source maps. var body = ts.cast(ts.cast(ts.skipOuterExpressions(node.expression), ts.isArrowFunction).body, ts.isBlock); + // The class statements are the statements generated by visiting the first statement with initializer of the + // body (1), while all other statements are added to remainingStatements (2) var isVariableStatementWithInitializer = function (stmt) { return ts.isVariableStatement(stmt) && !!ts.first(stmt.declarationList.declarations).initializer; }; var bodyStatements = ts.visitNodes(body.statements, visitor, ts.isStatement); var classStatements = ts.filter(bodyStatements, isVariableStatementWithInitializer); var remainingStatements = ts.filter(bodyStatements, function (stmt) { return !isVariableStatementWithInitializer(stmt); }); var varStatement = ts.cast(ts.first(classStatements), ts.isVariableStatement); + // We know there is only one variable declaration here as we verified this in an + // earlier call to isTypeScriptClassWrapper var variable = varStatement.declarationList.declarations[0]; var initializer = ts.skipOuterExpressions(variable.initializer); + // Under certain conditions, the 'ts' transformer may introduce a class alias, which + // we see as an assignment, for example: + // + // (function () { + // var C_1; + // var C = C_1 = (function () { + // function C() { + // } + // C.x = function () { return C_1; } + // return C; + // }()); + // C = C_1 = __decorate([dec], C); + // return C; + // }()) + // var aliasAssignment = ts.tryCast(initializer, ts.isAssignmentExpression); + // The underlying call (3) is another IIFE that may contain a '_super' argument. var call = ts.cast(aliasAssignment ? ts.skipOuterExpressions(aliasAssignment.right) : initializer, ts.isCallExpression); var func = ts.cast(ts.skipOuterExpressions(call.expression), ts.isFunctionExpression); var funcStatements = func.body.statements; @@ -57682,47 +68526,92 @@ var ts; var classBodyEnd = -1; var statements = []; if (aliasAssignment) { + // If we have a class alias assignment, we need to move it to the down-level constructor + // function we generated for the class. var extendsCall = ts.tryCast(funcStatements[classBodyStart], ts.isExpressionStatement); if (extendsCall) { statements.push(extendsCall); classBodyStart++; } + // The next statement is the function declaration. statements.push(funcStatements[classBodyStart]); classBodyStart++; + // Add the class alias following the declaration. statements.push(ts.createStatement(ts.createAssignment(aliasAssignment.left, ts.cast(variable.name, ts.isIdentifier)))); } + // Find the trailing 'return' statement (4) while (!ts.isReturnStatement(ts.elementAt(funcStatements, classBodyEnd))) { classBodyEnd--; } + // When we extract the statements of the inner IIFE, we exclude the 'return' statement (4) + // as we already have one that has been introduced by the 'ts' transformer. ts.addRange(statements, funcStatements, classBodyStart, classBodyEnd); if (classBodyEnd < -1) { + // If there were any hoisted declarations following the return statement, we should + // append them. ts.addRange(statements, funcStatements, classBodyEnd + 1); } + // Add the remaining statements of the outer wrapper. ts.addRange(statements, remainingStatements); - ts.addRange(statements, classStatements, 1); - return ts.recreateOuterExpressions(node.expression, ts.recreateOuterExpressions(variable.initializer, ts.recreateOuterExpressions(aliasAssignment && aliasAssignment.right, ts.updateCall(call, ts.recreateOuterExpressions(call.expression, ts.updateFunctionExpression(func, undefined, undefined, undefined, undefined, func.parameters, undefined, ts.updateBlock(func.body, statements))), undefined, call.arguments)))); + // The 'es2015' class transform may add an end-of-declaration marker. If so we will add it + // after the remaining statements from the 'ts' transformer. + ts.addRange(statements, classStatements, /*start*/ 1); + // Recreate any outer parentheses or partially-emitted expressions to preserve source map + // and comment locations. + return ts.recreateOuterExpressions(node.expression, ts.recreateOuterExpressions(variable.initializer, ts.recreateOuterExpressions(aliasAssignment && aliasAssignment.right, ts.updateCall(call, ts.recreateOuterExpressions(call.expression, ts.updateFunctionExpression(func, + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, func.parameters, + /*type*/ undefined, ts.updateBlock(func.body, statements))), + /*typeArguments*/ undefined, call.arguments)))); } function visitImmediateSuperCallInBody(node) { - return visitCallExpressionWithPotentialCapturedThisAssignment(node, false); + return visitCallExpressionWithPotentialCapturedThisAssignment(node, /*assignToCapturedThis*/ false); } function visitCallExpressionWithPotentialCapturedThisAssignment(node, assignToCapturedThis) { - if (node.transformFlags & 524288 || - node.expression.kind === 97 || + // We are here either because SuperKeyword was used somewhere in the expression, or + // because we contain a SpreadElementExpression. + if (node.transformFlags & 524288 /* ContainsSpread */ || + node.expression.kind === 97 /* SuperKeyword */ || ts.isSuperProperty(ts.skipOuterExpressions(node.expression))) { var _a = ts.createCallBinding(node.expression, hoistVariableDeclaration), target = _a.target, thisArg = _a.thisArg; - if (node.expression.kind === 97) { - ts.setEmitFlags(thisArg, 4); + if (node.expression.kind === 97 /* SuperKeyword */) { + ts.setEmitFlags(thisArg, 4 /* NoSubstitution */); } var resultingCall = void 0; - if (node.transformFlags & 524288) { - resultingCall = ts.createFunctionApply(ts.visitNode(target, callExpressionVisitor, ts.isExpression), ts.visitNode(thisArg, visitor, ts.isExpression), transformAndSpreadElements(node.arguments, false, false, false)); + if (node.transformFlags & 524288 /* ContainsSpread */) { + // [source] + // f(...a, b) + // x.m(...a, b) + // super(...a, b) + // super.m(...a, b) // in static + // super.m(...a, b) // in instance + // + // [output] + // f.apply(void 0, a.concat([b])) + // (_a = x).m.apply(_a, a.concat([b])) + // _super.apply(this, a.concat([b])) + // _super.m.apply(this, a.concat([b])) + // _super.prototype.m.apply(this, a.concat([b])) + resultingCall = ts.createFunctionApply(ts.visitNode(target, callExpressionVisitor, ts.isExpression), ts.visitNode(thisArg, visitor, ts.isExpression), transformAndSpreadElements(node.arguments, /*needsUniqueCopy*/ false, /*multiLine*/ false, /*hasTrailingComma*/ false)); } else { - resultingCall = ts.createFunctionCall(ts.visitNode(target, callExpressionVisitor, ts.isExpression), ts.visitNode(thisArg, visitor, ts.isExpression), ts.visitNodes(node.arguments, visitor, ts.isExpression), node); + // [source] + // super(a) + // super.m(a) // in static + // super.m(a) // in instance + // + // [output] + // _super.call(this, a) + // _super.m.call(this, a) + // _super.prototype.m.call(this, a) + resultingCall = ts.createFunctionCall(ts.visitNode(target, callExpressionVisitor, ts.isExpression), ts.visitNode(thisArg, visitor, ts.isExpression), ts.visitNodes(node.arguments, visitor, ts.isExpression), + /*location*/ node); } - if (node.expression.kind === 97) { + if (node.expression.kind === 97 /* SuperKeyword */) { var actualThis = ts.createThis(); - ts.setEmitFlags(actualThis, 4); + ts.setEmitFlags(actualThis, 4 /* NoSubstitution */); var initializer = ts.createLogicalOr(resultingCall, actualThis); resultingCall = assignToCapturedThis ? ts.createAssignment(ts.createFileLevelUniqueName("_this"), initializer) @@ -57732,14 +68621,40 @@ var ts; } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a NewExpression that contains a spread element. + * + * @param node A NewExpression node. + */ function visitNewExpression(node) { - if (node.transformFlags & 524288) { + if (node.transformFlags & 524288 /* ContainsSpread */) { + // We are here because we contain a SpreadElementExpression. + // [source] + // new C(...a) + // + // [output] + // new ((_a = C).bind.apply(_a, [void 0].concat(a)))() var _a = ts.createCallBinding(ts.createPropertyAccess(node.expression, "bind"), hoistVariableDeclaration), target = _a.target, thisArg = _a.thisArg; - return ts.createNew(ts.createFunctionApply(ts.visitNode(target, visitor, ts.isExpression), thisArg, transformAndSpreadElements(ts.createNodeArray([ts.createVoidZero()].concat(node.arguments)), false, false, false)), undefined, []); + return ts.createNew(ts.createFunctionApply(ts.visitNode(target, visitor, ts.isExpression), thisArg, transformAndSpreadElements(ts.createNodeArray([ts.createVoidZero()].concat(node.arguments)), /*needsUniqueCopy*/ false, /*multiLine*/ false, /*hasTrailingComma*/ false)), + /*typeArguments*/ undefined, []); } return ts.visitEachChild(node, visitor, context); } + /** + * Transforms an array of Expression nodes that contains a SpreadExpression. + * + * @param elements The array of Expression nodes. + * @param needsUniqueCopy A value indicating whether to ensure that the result is a fresh array. + * @param multiLine A value indicating whether the result should be emitted on multiple lines. + */ function transformAndSpreadElements(elements, needsUniqueCopy, multiLine, hasTrailingComma) { + // [source] + // [a, ...b, c] + // + // [output] + // [a].concat(b, [c]) + // Map spans of spread expressions into their expressions and spans of other + // expressions into an array literal. var numElements = elements.length; var segments = ts.flatten(ts.spanMap(elements, partitionSpread, function (partition, visitPartition, _start, end) { return visitPartition(partition, multiLine, hasTrailingComma && end === numElements); @@ -57749,7 +68664,7 @@ var ts; var firstSegment = segments[0]; if (ts.isCallExpression(firstSegment) && ts.isIdentifier(firstSegment.expression) - && (ts.getEmitFlags(firstSegment.expression) & 4096) + && (ts.getEmitFlags(firstSegment.expression) & 4096 /* HelperName */) && firstSegment.expression.escapedText === "___spread") { return segments[0]; } @@ -57759,10 +68674,11 @@ var ts; else { if (segments.length === 1) { var firstElement = elements[0]; - return needsUniqueCopy && ts.isSpreadElement(firstElement) && firstElement.expression.kind !== 183 + return needsUniqueCopy && ts.isSpreadElement(firstElement) && firstElement.expression.kind !== 183 /* ArrayLiteralExpression */ ? ts.createArraySlice(segments[0]) : segments[0]; } + // Rewrite using the pattern .concat(, , ...) return ts.createArrayConcat(segments.shift(), segments); } } @@ -57780,26 +68696,55 @@ var ts; function visitSpreadElement(node) { return ts.visitNode(node.expression, visitor, ts.isExpression); } + /** + * Transforms the expression of a SpreadExpression node. + * + * @param node A SpreadExpression node. + */ function visitExpressionOfSpread(node) { return ts.visitNode(node.expression, visitor, ts.isExpression); } + /** + * Visits a template literal. + * + * @param node A template literal. + */ function visitTemplateLiteral(node) { return ts.setTextRange(ts.createLiteral(node.text), node); } + /** + * Visits a string literal with an extended unicode escape. + * + * @param node A string literal. + */ function visitStringLiteral(node) { if (node.hasExtendedUnicodeEscape) { return ts.setTextRange(ts.createLiteral(node.text), node); } return node; } + /** + * Visits a binary or octal (ES6) numeric literal. + * + * @param node A string literal. + */ function visitNumericLiteral(node) { - if (node.numericLiteralFlags & 384) { + if (node.numericLiteralFlags & 384 /* BinaryOrOctalSpecifier */) { return ts.setTextRange(ts.createNumericLiteral(node.text), node); } return node; } + /** + * Visits a TaggedTemplateExpression node. + * + * @param node A TaggedTemplateExpression node. + */ function visitTaggedTemplateExpression(node) { + // Visit the tag expression var tag = ts.visitNode(node.tag, visitor, ts.isExpression); + // Build up the template arguments and the raw and cooked strings for the template. + // We start out with 'undefined' for the first argument and revisit later + // to avoid walking over the template string twice and shifting all our arguments over after the fact. var templateArguments = [undefined]; var cookedStrings = []; var rawStrings = []; @@ -57819,6 +68764,9 @@ var ts; } } var helperCall = createTemplateObjectHelper(context, ts.createArrayLiteral(cookedStrings), ts.createArrayLiteral(rawStrings)); + // Create a variable to cache the template object if we're in a module. + // Do not do this in the global scope, as any variable we currently generate could conflict with + // variables from outside of the current compilation. In the future, we can revisit this behavior. if (ts.isExternalModule(currentSourceFile)) { var tempVar = ts.createUniqueName("templateObject"); recordTaggedTemplateString(tempVar); @@ -57827,19 +68775,48 @@ var ts; else { templateArguments[0] = helperCall; } - return ts.createCall(tag, undefined, templateArguments); + return ts.createCall(tag, /*typeArguments*/ undefined, templateArguments); } + /** + * Creates an ES5 compatible literal from an ES6 template literal. + * + * @param node The ES6 template literal. + */ function getRawLiteral(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". var text = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node); - var isLast = node.kind === 13 || node.kind === 16; + // 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 "${" + var isLast = node.kind === 13 /* NoSubstitutionTemplateLiteral */ || node.kind === 16 /* 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"); return ts.setTextRange(ts.createLiteral(text), node); } + /** + * Visits a TemplateExpression node. + * + * @param node A TemplateExpression node. + */ function visitTemplateExpression(node) { var expressions = []; addTemplateHead(expressions, node); addTemplateSpans(expressions, node); + // createAdd will check if each expression binds less closely than binary '+'. + // If it does, it wraps 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) + "" var expression = ts.reduceLeft(expressions, ts.createAdd); if (ts.nodeIsSynthesized(expression)) { expression.pos = node.pos; @@ -57847,76 +68824,137 @@ var ts; } return expression; } + /** + * Gets a value indicating whether we need to include the head of a TemplateExpression. + * + * @param node A TemplateExpression node. + */ function shouldAddTemplateHead(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 }` + // 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() ts.Debug.assert(node.templateSpans.length !== 0); return node.head.text.length !== 0 || node.templateSpans[0].literal.text.length === 0; } + /** + * Adds the head of a TemplateExpression to an array of expressions. + * + * @param expressions An array of expressions. + * @param node A TemplateExpression node. + */ function addTemplateHead(expressions, node) { if (!shouldAddTemplateHead(node)) { return; } expressions.push(ts.createLiteral(node.head.text)); } + /** + * Visits and adds the template spans of a TemplateExpression to an array of expressions. + * + * @param expressions An array of expressions. + * @param node A TemplateExpression node. + */ function addTemplateSpans(expressions, node) { for (var _i = 0, _a = node.templateSpans; _i < _a.length; _i++) { var span = _a[_i]; expressions.push(ts.visitNode(span.expression, visitor, ts.isExpression)); + // 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 (span.literal.text.length !== 0) { expressions.push(ts.createLiteral(span.literal.text)); } } } + /** + * Visits the `super` keyword + */ function visitSuperKeyword(isExpressionOfCall) { - return hierarchyFacts & 8 + return hierarchyFacts & 8 /* NonStaticClassElement */ && !isExpressionOfCall ? ts.createPropertyAccess(ts.createFileLevelUniqueName("_super"), "prototype") : ts.createFileLevelUniqueName("_super"); } function visitMetaProperty(node) { - if (node.keywordToken === 94 && node.name.escapedText === "target") { - if (hierarchyFacts & 8192) { - hierarchyFacts |= 32768; + if (node.keywordToken === 94 /* NewKeyword */ && node.name.escapedText === "target") { + if (hierarchyFacts & 8192 /* ComputedPropertyName */) { + hierarchyFacts |= 32768 /* NewTargetInComputedPropertyName */; } else { - hierarchyFacts |= 16384; + hierarchyFacts |= 16384 /* NewTarget */; } return ts.createFileLevelUniqueName("_newTarget"); } return node; } + /** + * Called by the printer just before a node is printed. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to be printed. + * @param emitCallback The callback used to emit the node. + */ function onEmitNode(hint, node, emitCallback) { - if (enabledSubstitutions & 1 && ts.isFunctionLike(node)) { - var ancestorFacts = enterSubtree(16286, ts.getEmitFlags(node) & 8 - ? 65 | 16 - : 65); + if (enabledSubstitutions & 1 /* CapturedThis */ && ts.isFunctionLike(node)) { + // If we are tracking a captured `this`, keep track of the enclosing function. + var ancestorFacts = enterSubtree(16286 /* FunctionExcludes */, ts.getEmitFlags(node) & 8 /* CapturesThis */ + ? 65 /* FunctionIncludes */ | 16 /* CapturesThis */ + : 65 /* FunctionIncludes */); previousOnEmitNode(hint, node, emitCallback); - exitSubtree(ancestorFacts, 0, 0); + exitSubtree(ancestorFacts, 0 /* None */, 0 /* None */); return; } previousOnEmitNode(hint, node, emitCallback); } + /** + * Enables a more costly code path for substitutions when we determine a source file + * contains block-scoped bindings (e.g. `let` or `const`). + */ function enableSubstitutionsForBlockScopedBindings() { - if ((enabledSubstitutions & 2) === 0) { - enabledSubstitutions |= 2; - context.enableSubstitution(71); + if ((enabledSubstitutions & 2 /* BlockScopedBindings */) === 0) { + enabledSubstitutions |= 2 /* BlockScopedBindings */; + context.enableSubstitution(71 /* Identifier */); } } + /** + * Enables a more costly code path for substitutions when we determine a source file + * contains a captured `this`. + */ function enableSubstitutionsForCapturedThis() { - if ((enabledSubstitutions & 1) === 0) { - enabledSubstitutions |= 1; - context.enableSubstitution(99); - context.enableEmitNotification(155); - context.enableEmitNotification(154); - context.enableEmitNotification(156); - context.enableEmitNotification(157); - context.enableEmitNotification(193); - context.enableEmitNotification(192); - context.enableEmitNotification(234); + if ((enabledSubstitutions & 1 /* CapturedThis */) === 0) { + enabledSubstitutions |= 1 /* CapturedThis */; + context.enableSubstitution(99 /* ThisKeyword */); + context.enableEmitNotification(155 /* Constructor */); + context.enableEmitNotification(154 /* MethodDeclaration */); + context.enableEmitNotification(156 /* GetAccessor */); + context.enableEmitNotification(157 /* SetAccessor */); + context.enableEmitNotification(193 /* ArrowFunction */); + context.enableEmitNotification(192 /* FunctionExpression */); + context.enableEmitNotification(234 /* FunctionDeclaration */); } } + /** + * Hooks node substitutions. + * + * @param hint The context for the emitter. + * @param node The node to substitute. + */ function onSubstituteNode(hint, node) { node = previousOnSubstituteNode(hint, node); - if (hint === 1) { + if (hint === 1 /* Expression */) { return substituteExpression(node); } if (ts.isIdentifier(node)) { @@ -57924,8 +68962,13 @@ var ts; } return node; } + /** + * Hooks substitutions for non-expression identifiers. + */ function substituteIdentifier(node) { - if (enabledSubstitutions & 2 && !ts.isInternalName(node)) { + // Only substitute the identifier if we have enabled substitutions for block-scoped + // bindings. + if (enabledSubstitutions & 2 /* BlockScopedBindings */ && !ts.isInternalName(node)) { var original = ts.getParseTreeNode(node, ts.isIdentifier); if (original && isNameOfDeclarationWithCollidingName(original)) { return ts.setTextRange(ts.getGeneratedNameForNode(original), node); @@ -57933,28 +68976,44 @@ var ts; } return node; } + /** + * Determines whether a name is the name of a declaration with a colliding name. + * NOTE: This function expects to be called with an original source tree node. + * + * @param node An original source tree node. + */ function isNameOfDeclarationWithCollidingName(node) { switch (node.parent.kind) { - case 182: - case 235: - case 238: - case 232: + case 182 /* BindingElement */: + case 235 /* ClassDeclaration */: + case 238 /* EnumDeclaration */: + case 232 /* VariableDeclaration */: return node.parent.name === node && resolver.isDeclarationWithCollidingName(node.parent); } return false; } + /** + * Substitutes an expression. + * + * @param node An Expression node. + */ function substituteExpression(node) { switch (node.kind) { - case 71: + case 71 /* Identifier */: return substituteExpressionIdentifier(node); - case 99: + case 99 /* ThisKeyword */: return substituteThisKeyword(node); } return node; } + /** + * Substitutes an expression identifier. + * + * @param node An Identifier node. + */ function substituteExpressionIdentifier(node) { - if (enabledSubstitutions & 2 && !ts.isInternalName(node)) { + if (enabledSubstitutions & 2 /* BlockScopedBindings */ && !ts.isInternalName(node)) { var declaration = resolver.getReferencedDeclarationWithCollidingName(node); if (declaration && !(ts.isClassLike(declaration) && isPartOfClassBody(declaration, node))) { return ts.setTextRange(ts.getGeneratedNameForNode(ts.getNameOfDeclaration(declaration)), node); @@ -57965,11 +69024,17 @@ var ts; function isPartOfClassBody(declaration, node) { var currentNode = ts.getParseTreeNode(node); if (!currentNode || currentNode === declaration || currentNode.end <= declaration.pos || currentNode.pos >= declaration.end) { + // if the node has no correlation to a parse tree node, its definitely not + // part of the body. + // if the node is outside of the document range of the declaration, its + // definitely not part of the body. return false; } var blockScope = ts.getEnclosingBlockScopeContainer(declaration); while (currentNode) { if (currentNode === blockScope || currentNode === declaration) { + // if we are in the enclosing block scope of the declaration, we are definitely + // not inside the class body. return false; } if (ts.isClassElement(currentNode) && currentNode.parent === declaration) { @@ -57979,15 +69044,20 @@ var ts; } return false; } + /** + * Substitutes `this` when contained within an arrow function. + * + * @param node The ThisKeyword node. + */ function substituteThisKeyword(node) { - if (enabledSubstitutions & 1 - && hierarchyFacts & 16) { + if (enabledSubstitutions & 1 /* CapturedThis */ + && hierarchyFacts & 16 /* CapturesThis */) { return ts.setTextRange(ts.createFileLevelUniqueName("_this"), node); } return node; } function getClassMemberPrefix(node, member) { - return ts.hasModifier(member, 32) + return ts.hasModifier(member, 32 /* Static */) ? ts.getInternalName(node) : ts.createPropertyAccess(ts.getInternalName(node), "prototype"); } @@ -57999,19 +69069,19 @@ var ts; return false; } var statement = ts.firstOrUndefined(constructor.body.statements); - if (!statement || !ts.nodeIsSynthesized(statement) || statement.kind !== 216) { + if (!statement || !ts.nodeIsSynthesized(statement) || statement.kind !== 216 /* ExpressionStatement */) { return false; } var statementExpression = statement.expression; - if (!ts.nodeIsSynthesized(statementExpression) || statementExpression.kind !== 187) { + if (!ts.nodeIsSynthesized(statementExpression) || statementExpression.kind !== 187 /* CallExpression */) { return false; } var callTarget = statementExpression.expression; - if (!ts.nodeIsSynthesized(callTarget) || callTarget.kind !== 97) { + if (!ts.nodeIsSynthesized(callTarget) || callTarget.kind !== 97 /* SuperKeyword */) { return false; } var callArgument = ts.singleOrUndefined(statementExpression.arguments); - if (!callArgument || !ts.nodeIsSynthesized(callArgument) || callArgument.kind !== 204) { + if (!callArgument || !ts.nodeIsSynthesized(callArgument) || callArgument.kind !== 204 /* SpreadElement */) { return false; } var expression = callArgument.expression; @@ -58021,14 +69091,16 @@ var ts; ts.transformES2015 = transformES2015; function createExtendsHelper(context, name) { context.requestEmitHelper(extendsHelper); - return ts.createCall(ts.getHelperName("__extends"), undefined, [ + return ts.createCall(ts.getHelperName("__extends"), + /*typeArguments*/ undefined, [ name, ts.createFileLevelUniqueName("_super") ]); } function createTemplateObjectHelper(context, cooked, raw) { context.requestEmitHelper(templateObjectHelper); - return ts.createCall(ts.getHelperName("__makeTemplateObject"), undefined, [ + return ts.createCall(ts.getHelperName("__makeTemplateObject"), + /*typeArguments*/ undefined, [ cooked, raw ]); @@ -58037,7 +69109,7 @@ var ts; name: "typescript:extends", scoped: false, priority: 0, - text: "\n var __extends = (this && this.__extends) || (function () {\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n })();" + text: "\n var __extends = (this && this.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n }\n\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n })();" }; var templateObjectHelper = { name: "typescript:makeTemplateObject", @@ -58046,39 +69118,64 @@ var ts; text: "\n var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\n return cooked;\n };" }; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { + /** + * Transforms ES5 syntax into ES3 syntax. + * + * @param context Context and state information for the transformation. + */ function transformES5(context) { var compilerOptions = context.getCompilerOptions(); + // enable emit notification only if using --jsx preserve or react-native var previousOnEmitNode; var noSubstitution; - if (compilerOptions.jsx === 1 || compilerOptions.jsx === 3) { + if (compilerOptions.jsx === 1 /* Preserve */ || compilerOptions.jsx === 3 /* ReactNative */) { previousOnEmitNode = context.onEmitNode; context.onEmitNode = onEmitNode; - context.enableEmitNotification(257); - context.enableEmitNotification(258); - context.enableEmitNotification(256); + context.enableEmitNotification(257 /* JsxOpeningElement */); + context.enableEmitNotification(258 /* JsxClosingElement */); + context.enableEmitNotification(256 /* JsxSelfClosingElement */); noSubstitution = []; } var previousOnSubstituteNode = context.onSubstituteNode; context.onSubstituteNode = onSubstituteNode; - context.enableSubstitution(185); - context.enableSubstitution(270); + context.enableSubstitution(185 /* PropertyAccessExpression */); + context.enableSubstitution(270 /* PropertyAssignment */); return ts.chainBundle(transformSourceFile); + /** + * Transforms an ES5 source file to ES3. + * + * @param node A SourceFile + */ function transformSourceFile(node) { return node; } + /** + * Called by the printer just before a node is printed. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emitCallback A callback used to emit the node. + */ function onEmitNode(hint, node, emitCallback) { switch (node.kind) { - case 257: - case 258: - case 256: + case 257 /* JsxOpeningElement */: + case 258 /* JsxClosingElement */: + case 256 /* JsxSelfClosingElement */: var tagName = node.tagName; noSubstitution[ts.getOriginalNodeId(tagName)] = true; break; } previousOnEmitNode(hint, node, emitCallback); } + /** + * Hooks node substitutions. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to substitute. + */ function onSubstituteNode(hint, node) { if (node.id && noSubstitution && noSubstitution[node.id]) { return previousOnSubstituteNode(hint, node); @@ -58092,6 +69189,11 @@ var ts; } return node; } + /** + * Substitutes a PropertyAccessExpression whose name is a reserved word. + * + * @param node A PropertyAccessExpression + */ function substitutePropertyAccessExpression(node) { var literalName = trySubstituteReservedName(node.name); if (literalName) { @@ -58099,6 +69201,11 @@ var ts; } return node; } + /** + * Substitutes a PropertyAssignment whose name is a reserved word. + * + * @param node A PropertyAssignment + */ function substitutePropertyAssignment(node) { var literalName = ts.isIdentifier(node.name) && trySubstituteReservedName(node.name); if (literalName) { @@ -58106,9 +69213,14 @@ var ts; } return node; } + /** + * If an identifier name is a reserved word, returns a string literal for the name. + * + * @param name An Identifier + */ function trySubstituteReservedName(name) { var token = name.originalKeywordKind || (ts.nodeIsSynthesized(name) ? ts.stringToToken(ts.idText(name)) : undefined); - if (token !== undefined && token >= 72 && token <= 107) { + if (token !== undefined && token >= 72 /* FirstReservedWord */ && token <= 107 /* LastReservedWord */) { return ts.setTextRange(ts.createLiteral(name), name); } return undefined; @@ -58116,6 +69228,125 @@ var ts; } ts.transformES5 = transformES5; })(ts || (ts = {})); +// Transforms generator functions into a compatible ES5 representation with similar runtime +// semantics. This is accomplished by first transforming the body of each generator +// function into an intermediate representation that is the compiled into a JavaScript +// switch statement. +// +// Many functions in this transformer will contain comments indicating the expected +// intermediate representation. For illustrative purposes, the following intermediate +// language is used to define this intermediate representation: +// +// .nop - Performs no operation. +// .local NAME, ... - Define local variable declarations. +// .mark LABEL - Mark the location of a label. +// .br LABEL - Jump to a label. If jumping out of a protected +// region, all .finally blocks are executed. +// .brtrue LABEL, (x) - Jump to a label IIF the expression `x` is truthy. +// If jumping out of a protected region, all .finally +// blocks are executed. +// .brfalse LABEL, (x) - Jump to a label IIF the expression `x` is falsey. +// If jumping out of a protected region, all .finally +// blocks are executed. +// .yield (x) - Yield the value of the optional expression `x`. +// Resume at the next label. +// .yieldstar (x) - Delegate yield to the value of the optional +// expression `x`. Resume at the next label. +// NOTE: `x` must be an Iterator, not an Iterable. +// .loop CONTINUE, BREAK - Marks the beginning of a loop. Any "continue" or +// "break" abrupt completions jump to the CONTINUE or +// BREAK labels, respectively. +// .endloop - Marks the end of a loop. +// .with (x) - Marks the beginning of a WithStatement block, using +// the supplied expression. +// .endwith - Marks the end of a WithStatement. +// .switch - Marks the beginning of a SwitchStatement. +// .endswitch - Marks the end of a SwitchStatement. +// .labeled NAME - Marks the beginning of a LabeledStatement with the +// supplied name. +// .endlabeled - Marks the end of a LabeledStatement. +// .try TRY, CATCH, FINALLY, END - Marks the beginning of a protected region, and the +// labels for each block. +// .catch (x) - Marks the beginning of a catch block. +// .finally - Marks the beginning of a finally block. +// .endfinally - Marks the end of a finally block. +// .endtry - Marks the end of a protected region. +// .throw (x) - Throws the value of the expression `x`. +// .return (x) - Returns the value of the expression `x`. +// +// In addition, the illustrative intermediate representation introduces some special +// variables: +// +// %sent% - Either returns the next value sent to the generator, +// returns the result of a delegated yield, or throws +// the exception sent to the generator. +// %error% - Returns the value of the current exception in a +// catch block. +// +// This intermediate representation is then compiled into JavaScript syntax. The resulting +// compilation output looks something like the following: +// +// function f() { +// var /*locals*/; +// /*functions*/ +// return __generator(function (state) { +// switch (state.label) { +// /*cases per label*/ +// } +// }); +// } +// +// Each of the above instructions corresponds to JavaScript emit similar to the following: +// +// .local NAME | var NAME; +// -------------------------------|---------------------------------------------- +// .mark LABEL | case LABEL: +// -------------------------------|---------------------------------------------- +// .br LABEL | return [3 /*break*/, LABEL]; +// -------------------------------|---------------------------------------------- +// .brtrue LABEL, (x) | if (x) return [3 /*break*/, LABEL]; +// -------------------------------|---------------------------------------------- +// .brfalse LABEL, (x) | if (!(x)) return [3, /*break*/, LABEL]; +// -------------------------------|---------------------------------------------- +// .yield (x) | return [4 /*yield*/, x]; +// .mark RESUME | case RESUME: +// a = %sent%; | a = state.sent(); +// -------------------------------|---------------------------------------------- +// .yieldstar (x) | return [5 /*yield**/, x]; +// .mark RESUME | case RESUME: +// a = %sent%; | a = state.sent(); +// -------------------------------|---------------------------------------------- +// .with (_a) | with (_a) { +// a(); | a(); +// | } +// | state.label = LABEL; +// .mark LABEL | case LABEL: +// | with (_a) { +// b(); | b(); +// | } +// .endwith | +// -------------------------------|---------------------------------------------- +// | case 0: +// | state.trys = []; +// | ... +// .try TRY, CATCH, FINALLY, END | +// .mark TRY | case TRY: +// | state.trys.push([TRY, CATCH, FINALLY, END]); +// .nop | +// a(); | a(); +// .br END | return [3 /*break*/, END]; +// .catch (e) | +// .mark CATCH | case CATCH: +// | e = state.sent(); +// b(); | b(); +// .br END | return [3 /*break*/, END]; +// .finally | +// .mark FINALLY | case FINALLY: +// c(); | c(); +// .endfinally | return [7 /*endfinally*/]; +// .endtry | +// .mark END | case END: +/*@internal*/ var ts; (function (ts) { var OpCode; @@ -58130,13 +69361,15 @@ var ts; OpCode[OpCode["YieldStar"] = 7] = "YieldStar"; OpCode[OpCode["Return"] = 8] = "Return"; OpCode[OpCode["Throw"] = 9] = "Throw"; - OpCode[OpCode["Endfinally"] = 10] = "Endfinally"; + OpCode[OpCode["Endfinally"] = 10] = "Endfinally"; // Marks the end of a `finally` block })(OpCode || (OpCode = {})); + // whether a generated code block is opening or closing at the current operation for a FunctionBuilder var BlockAction; (function (BlockAction) { BlockAction[BlockAction["Open"] = 0] = "Open"; BlockAction[BlockAction["Close"] = 1] = "Close"; })(BlockAction || (BlockAction = {})); + // the kind for a generated code block in a FunctionBuilder var CodeBlockKind; (function (CodeBlockKind) { CodeBlockKind[CodeBlockKind["Exception"] = 0] = "Exception"; @@ -58145,6 +69378,7 @@ var ts; CodeBlockKind[CodeBlockKind["Loop"] = 3] = "Loop"; CodeBlockKind[CodeBlockKind["Labeled"] = 4] = "Labeled"; })(CodeBlockKind || (CodeBlockKind = {})); + // the state for a generated code exception block var ExceptionBlockState; (function (ExceptionBlockState) { ExceptionBlockState[ExceptionBlockState["Try"] = 0] = "Try"; @@ -58152,6 +69386,7 @@ var ts; ExceptionBlockState[ExceptionBlockState["Finally"] = 2] = "Finally"; ExceptionBlockState[ExceptionBlockState["Done"] = 3] = "Done"; })(ExceptionBlockState || (ExceptionBlockState = {})); + // NOTE: changes to this enum should be reflected in the __generator helper. var Instruction; (function (Instruction) { Instruction[Instruction["Next"] = 0] = "Next"; @@ -58165,12 +69400,12 @@ var ts; })(Instruction || (Instruction = {})); function getInstructionName(instruction) { switch (instruction) { - case 2: return "return"; - case 3: return "break"; - case 4: return "yield"; - case 5: return "yield*"; - case 7: return "endfinally"; - default: return undefined; + case 2 /* Return */: return "return"; + case 3 /* Break */: return "break"; + case 4 /* Yield */: return "yield"; + case 5 /* YieldStar */: return "yield*"; + case 7 /* Endfinally */: return "endfinally"; + default: return undefined; // TODO: GH#18217 } } function transformGenerators(context) { @@ -58184,36 +69419,57 @@ var ts; var renamedCatchVariableDeclarations; var inGeneratorFunctionBody; var inStatementContainingYield; - var blocks; - var blockOffsets; - var blockActions; - var blockStack; - var labelOffsets; - var labelExpressions; - var nextLabelId = 1; - var operations; - var operationArguments; - var operationLocations; - var state; - var blockIndex = 0; - var labelNumber = 0; + // The following three arrays store information about generated code blocks. + // All three arrays are correlated by their index. This approach is used over allocating + // objects to store the same information to avoid GC overhead. + // + var blocks; // Information about the code block + var blockOffsets; // The operation offset at which a code block begins or ends + var blockActions; // Whether the code block is opened or closed + var blockStack; // A stack of currently open code blocks + // Labels are used to mark locations in the code that can be the target of a Break (jump) + // operation. These are translated into case clauses in a switch statement. + // The following two arrays are correlated by their index. This approach is used over + // allocating objects to store the same information to avoid GC overhead. + // + var labelOffsets; // The operation offset at which the label is defined. + var labelExpressions; // The NumericLiteral nodes bound to each label. + var nextLabelId = 1; // The next label id to use. + // Operations store information about generated code for the function body. This + // Includes things like statements, assignments, breaks (jumps), and yields. + // The following three arrays are correlated by their index. This approach is used over + // allocating objects to store the same information to avoid GC overhead. + // + var operations; // The operation to perform. + var operationArguments; // The arguments to the operation. + var operationLocations; // The source map location for the operation. + var state; // The name of the state object used by the generator at runtime. + // The following variables store information used by the `build` function: + // + var blockIndex = 0; // The index of the current block. + var labelNumber = 0; // The current label number. var labelNumbers; - var lastOperationWasAbrupt; - var lastOperationWasCompletion; - var clauses; - var statements; - var exceptionBlockStack; - var currentExceptionBlock; - var withBlockStack; + var lastOperationWasAbrupt; // Indicates whether the last operation was abrupt (break/continue). + var lastOperationWasCompletion; // Indicates whether the last operation was a completion (return/throw). + var clauses; // The case clauses generated for labels. + var statements; // The statements for the current label. + var exceptionBlockStack; // A stack of containing exception blocks. + var currentExceptionBlock; // The current exception block. + var withBlockStack; // A stack containing `with` blocks. return ts.chainBundle(transformSourceFile); function transformSourceFile(node) { - if (node.isDeclarationFile || (node.transformFlags & 512) === 0) { + if (node.isDeclarationFile || (node.transformFlags & 512 /* ContainsGenerator */) === 0) { return node; } var visited = ts.visitEachChild(node, visitor, context); ts.addEmitHelpers(visited, context.readEmitHelpers()); return visited; } + /** + * Visits a node. + * + * @param node The node to visit. + */ function visitor(node) { var transformFlags = node.transformFlags; if (inStatementContainingYield) { @@ -58222,56 +69478,66 @@ var ts; else if (inGeneratorFunctionBody) { return visitJavaScriptInGeneratorFunctionBody(node); } - else if (transformFlags & 256) { + else if (transformFlags & 256 /* Generator */) { return visitGenerator(node); } - else if (transformFlags & 512) { + else if (transformFlags & 512 /* ContainsGenerator */) { return ts.visitEachChild(node, visitor, context); } else { return node; } } + /** + * Visits a node that is contained within a statement that contains yield. + * + * @param node The node to visit. + */ function visitJavaScriptInStatementContainingYield(node) { switch (node.kind) { - case 218: + case 218 /* DoStatement */: return visitDoStatement(node); - case 219: + case 219 /* WhileStatement */: return visitWhileStatement(node); - case 227: + case 227 /* SwitchStatement */: return visitSwitchStatement(node); - case 228: + case 228 /* LabeledStatement */: return visitLabeledStatement(node); default: return visitJavaScriptInGeneratorFunctionBody(node); } } + /** + * Visits a node that is contained within a generator function. + * + * @param node The node to visit. + */ function visitJavaScriptInGeneratorFunctionBody(node) { switch (node.kind) { - case 234: + case 234 /* FunctionDeclaration */: return visitFunctionDeclaration(node); - case 192: + case 192 /* FunctionExpression */: return visitFunctionExpression(node); - case 156: - case 157: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return visitAccessorDeclaration(node); - case 214: + case 214 /* VariableStatement */: return visitVariableStatement(node); - case 220: + case 220 /* ForStatement */: return visitForStatement(node); - case 221: + case 221 /* ForInStatement */: return visitForInStatement(node); - case 224: + case 224 /* BreakStatement */: return visitBreakStatement(node); - case 223: + case 223 /* ContinueStatement */: return visitContinueStatement(node); - case 225: + case 225 /* ReturnStatement */: return visitReturnStatement(node); default: - if (node.transformFlags & 16777216) { + if (node.transformFlags & 16777216 /* ContainsYield */) { return visitJavaScriptContainingYield(node); } - else if (node.transformFlags & (512 | 33554432)) { + else if (node.transformFlags & (512 /* ContainsGenerator */ | 33554432 /* ContainsHoistedDeclarationOrCompletion */)) { return ts.visitEachChild(node, visitor, context); } else { @@ -58279,41 +69545,66 @@ var ts; } } } + /** + * Visits a node that contains a YieldExpression. + * + * @param node The node to visit. + */ function visitJavaScriptContainingYield(node) { switch (node.kind) { - case 200: + case 200 /* BinaryExpression */: return visitBinaryExpression(node); - case 201: + case 201 /* ConditionalExpression */: return visitConditionalExpression(node); - case 203: + case 203 /* YieldExpression */: return visitYieldExpression(node); - case 183: + case 183 /* ArrayLiteralExpression */: return visitArrayLiteralExpression(node); - case 184: + case 184 /* ObjectLiteralExpression */: return visitObjectLiteralExpression(node); - case 186: + case 186 /* ElementAccessExpression */: return visitElementAccessExpression(node); - case 187: + case 187 /* CallExpression */: return visitCallExpression(node); - case 188: + case 188 /* NewExpression */: return visitNewExpression(node); default: return ts.visitEachChild(node, visitor, context); } } + /** + * Visits a generator function. + * + * @param node The node to visit. + */ function visitGenerator(node) { switch (node.kind) { - case 234: + case 234 /* FunctionDeclaration */: return visitFunctionDeclaration(node); - case 192: + case 192 /* FunctionExpression */: return visitFunctionExpression(node); default: return ts.Debug.failBadSyntaxKind(node); } } + /** + * Visits a function declaration. + * + * This will be called when one of the following conditions are met: + * - The function declaration is a generator function. + * - The function declaration is contained within the body of a generator function. + * + * @param node The node to visit. + */ function visitFunctionDeclaration(node) { + // Currently, we only support generators that were originally async functions. if (node.asteriskToken) { - node = ts.setOriginalNode(ts.setTextRange(ts.createFunctionDeclaration(undefined, node.modifiers, undefined, node.name, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, transformGeneratorFunctionBody(node.body)), node), node); + node = ts.setOriginalNode(ts.setTextRange(ts.createFunctionDeclaration( + /*decorators*/ undefined, node.modifiers, + /*asteriskToken*/ undefined, node.name, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, transformGeneratorFunctionBody(node.body)), + /*location*/ node), node); } else { var savedInGeneratorFunctionBody = inGeneratorFunctionBody; @@ -58325,6 +69616,8 @@ var ts; inStatementContainingYield = savedInStatementContainingYield; } if (inGeneratorFunctionBody) { + // Function declarations in a generator function body are hoisted + // to the top of the lexical scope and elided from the current statement. hoistFunctionDeclaration(node); return undefined; } @@ -58332,9 +69625,24 @@ var ts; return node; } } + /** + * Visits a function expression. + * + * This will be called when one of the following conditions are met: + * - The function expression is a generator function. + * - The function expression is contained within the body of a generator function. + * + * @param node The node to visit. + */ function visitFunctionExpression(node) { + // Currently, we only support generators that were originally async functions. if (node.asteriskToken) { - node = ts.setOriginalNode(ts.setTextRange(ts.createFunctionExpression(undefined, undefined, node.name, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, transformGeneratorFunctionBody(node.body)), node), node); + node = ts.setOriginalNode(ts.setTextRange(ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, node.name, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, transformGeneratorFunctionBody(node.body)), + /*location*/ node), node); } else { var savedInGeneratorFunctionBody = inGeneratorFunctionBody; @@ -58347,6 +69655,14 @@ var ts; } return node; } + /** + * Visits a get or set accessor declaration. + * + * This will be called when one of the following conditions are met: + * - The accessor is contained within the body of a generator function. + * + * @param node The node to visit. + */ function visitAccessorDeclaration(node) { var savedInGeneratorFunctionBody = inGeneratorFunctionBody; var savedInStatementContainingYield = inStatementContainingYield; @@ -58357,7 +69673,13 @@ var ts; inStatementContainingYield = savedInStatementContainingYield; return node; } + /** + * Transforms the body of a generator function declaration. + * + * @param node The function body to transform. + */ function transformGeneratorFunctionBody(body) { + // Save existing generator state var statements = []; var savedInGeneratorFunctionBody = inGeneratorFunctionBody; var savedInStatementContainingYield = inStatementContainingYield; @@ -58372,6 +69694,7 @@ var ts; var savedOperationArguments = operationArguments; var savedOperationLocations = operationLocations; var savedState = state; + // Initialize generator state inGeneratorFunctionBody = true; inStatementContainingYield = false; blocks = undefined; @@ -58384,13 +69707,15 @@ var ts; operations = undefined; operationArguments = undefined; operationLocations = undefined; - state = ts.createTempVariable(undefined); + state = ts.createTempVariable(/*recordTempVariable*/ undefined); + // Build the generator resumeLexicalEnvironment(); - var statementOffset = ts.addPrologue(statements, body.statements, false, visitor); + var statementOffset = ts.addPrologue(statements, body.statements, /*ensureUseStrict*/ false, visitor); transformAndEmitStatements(body.statements, statementOffset); var buildResult = build(); ts.prependStatements(statements, endLexicalEnvironment()); statements.push(ts.createReturn(buildResult)); + // Restore previous generator state inGeneratorFunctionBody = savedInGeneratorFunctionBody; inStatementContainingYield = savedInStatementContainingYield; blocks = savedBlocks; @@ -58406,13 +69731,22 @@ var ts; state = savedState; return ts.setTextRange(ts.createBlock(statements, body.multiLine), body); } + /** + * Visits a variable statement. + * + * This will be called when one of the following conditions are met: + * - The variable statement is contained within the body of a generator function. + * + * @param node The node to visit. + */ function visitVariableStatement(node) { - if (node.transformFlags & 16777216) { + if (node.transformFlags & 16777216 /* ContainsYield */) { transformAndEmitVariableDeclarationList(node.declarationList); return undefined; } else { - if (ts.getEmitFlags(node) & 1048576) { + // Do not hoist custom prologues. + if (ts.getEmitFlags(node) & 1048576 /* CustomPrologue */) { return node; } for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) { @@ -58426,46 +69760,78 @@ var ts; return ts.setSourceMapRange(ts.createStatement(ts.inlineExpressions(ts.map(variables, transformInitializedVariable))), node); } } + /** + * Visits a binary expression. + * + * This will be called when one of the following conditions are met: + * - The node contains a YieldExpression. + * + * @param node The node to visit. + */ function visitBinaryExpression(node) { var assoc = ts.getExpressionAssociativity(node); switch (assoc) { - case 0: + case 0 /* Left */: return visitLeftAssociativeBinaryExpression(node); - case 1: + case 1 /* Right */: return visitRightAssociativeBinaryExpression(node); default: return ts.Debug.assertNever(assoc); } } function isCompoundAssignment(kind) { - return kind >= 59 - && kind <= 70; + return kind >= 59 /* FirstCompoundAssignment */ + && kind <= 70 /* LastCompoundAssignment */; } function getOperatorForCompoundAssignment(kind) { switch (kind) { - case 59: return 37; - case 60: return 38; - case 61: return 39; - case 62: return 40; - case 63: return 41; - case 64: return 42; - case 65: return 45; - case 66: return 46; - case 67: return 47; - case 68: return 48; - case 69: return 49; - case 70: return 50; + case 59 /* PlusEqualsToken */: return 37 /* PlusToken */; + case 60 /* MinusEqualsToken */: return 38 /* MinusToken */; + case 61 /* AsteriskEqualsToken */: return 39 /* AsteriskToken */; + case 62 /* AsteriskAsteriskEqualsToken */: return 40 /* AsteriskAsteriskToken */; + case 63 /* SlashEqualsToken */: return 41 /* SlashToken */; + case 64 /* PercentEqualsToken */: return 42 /* PercentToken */; + case 65 /* LessThanLessThanEqualsToken */: return 45 /* LessThanLessThanToken */; + case 66 /* GreaterThanGreaterThanEqualsToken */: return 46 /* GreaterThanGreaterThanToken */; + case 67 /* GreaterThanGreaterThanGreaterThanEqualsToken */: return 47 /* GreaterThanGreaterThanGreaterThanToken */; + case 68 /* AmpersandEqualsToken */: return 48 /* AmpersandToken */; + case 69 /* BarEqualsToken */: return 49 /* BarToken */; + case 70 /* CaretEqualsToken */: return 50 /* CaretToken */; } } + /** + * Visits a right-associative binary expression containing `yield`. + * + * @param node The node to visit. + */ function visitRightAssociativeBinaryExpression(node) { var left = node.left, right = node.right; if (containsYield(right)) { var target = void 0; switch (left.kind) { - case 185: + case 185 /* PropertyAccessExpression */: + // [source] + // a.b = yield; + // + // [intermediate] + // .local _a + // _a = a; + // .yield resumeLabel + // .mark resumeLabel + // _a.b = %sent%; target = ts.updatePropertyAccess(left, cacheExpression(ts.visitNode(left.expression, visitor, ts.isLeftHandSideExpression)), left.name); break; - case 186: + case 186 /* ElementAccessExpression */: + // [source] + // a[b] = yield; + // + // [intermediate] + // .local _a, _b + // _a = a; + // _b = b; + // .yield resumeLabel + // .mark resumeLabel + // _a[_b] = %sent%; target = ts.updateElementAccess(left, cacheExpression(ts.visitNode(left.expression, visitor, ts.isLeftHandSideExpression)), cacheExpression(ts.visitNode(left.argumentExpression, visitor, ts.isExpression))); break; default: @@ -58487,9 +69853,17 @@ var ts; if (ts.isLogicalOperator(node.operatorToken.kind)) { return visitLogicalBinaryExpression(node); } - else if (node.operatorToken.kind === 26) { + else if (node.operatorToken.kind === 26 /* CommaToken */) { return visitCommaExpression(node); } + // [source] + // a() + (yield) + c() + // + // [intermediate] + // .local _a + // _a = a(); + // .yield resumeLabel + // _a + %sent% + c() var clone_4 = ts.getMutableClone(node); clone_4.left = cacheExpression(ts.visitNode(node.left, visitor, ts.isExpression)); clone_4.right = ts.visitNode(node.right, visitor, ts.isExpression); @@ -58497,73 +69871,176 @@ var ts; } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a logical binary expression containing `yield`. + * + * @param node A node to visit. + */ function visitLogicalBinaryExpression(node) { + // Logical binary expressions (`&&` and `||`) are shortcutting expressions and need + // to be transformed as such: + // + // [source] + // x = a() && yield; + // + // [intermediate] + // .local _a + // _a = a(); + // .brfalse resultLabel, (_a) + // .yield resumeLabel + // .mark resumeLabel + // _a = %sent%; + // .mark resultLabel + // x = _a; + // + // [source] + // x = a() || yield; + // + // [intermediate] + // .local _a + // _a = a(); + // .brtrue resultLabel, (_a) + // .yield resumeLabel + // .mark resumeLabel + // _a = %sent%; + // .mark resultLabel + // x = _a; var resultLabel = defineLabel(); var resultLocal = declareLocal(); - emitAssignment(resultLocal, ts.visitNode(node.left, visitor, ts.isExpression), node.left); - if (node.operatorToken.kind === 53) { - emitBreakWhenFalse(resultLabel, resultLocal, node.left); + emitAssignment(resultLocal, ts.visitNode(node.left, visitor, ts.isExpression), /*location*/ node.left); + if (node.operatorToken.kind === 53 /* AmpersandAmpersandToken */) { + // Logical `&&` shortcuts when the left-hand operand is falsey. + emitBreakWhenFalse(resultLabel, resultLocal, /*location*/ node.left); } else { - emitBreakWhenTrue(resultLabel, resultLocal, node.left); + // Logical `||` shortcuts when the left-hand operand is truthy. + emitBreakWhenTrue(resultLabel, resultLocal, /*location*/ node.left); } - emitAssignment(resultLocal, ts.visitNode(node.right, visitor, ts.isExpression), node.right); + emitAssignment(resultLocal, ts.visitNode(node.right, visitor, ts.isExpression), /*location*/ node.right); markLabel(resultLabel); return resultLocal; } + /** + * Visits a comma expression containing `yield`. + * + * @param node The node to visit. + */ function visitCommaExpression(node) { + // [source] + // x = a(), yield, b(); + // + // [intermediate] + // a(); + // .yield resumeLabel + // .mark resumeLabel + // x = %sent%, b(); var pendingExpressions = []; visit(node.left); visit(node.right); return ts.inlineExpressions(pendingExpressions); function visit(node) { - if (ts.isBinaryExpression(node) && node.operatorToken.kind === 26) { + if (ts.isBinaryExpression(node) && node.operatorToken.kind === 26 /* CommaToken */) { visit(node.left); visit(node.right); } else { if (containsYield(node) && pendingExpressions.length > 0) { - emitWorker(1, [ts.createStatement(ts.inlineExpressions(pendingExpressions))]); + emitWorker(1 /* Statement */, [ts.createStatement(ts.inlineExpressions(pendingExpressions))]); pendingExpressions = []; } pendingExpressions.push(ts.visitNode(node, visitor, ts.isExpression)); } } } + /** + * Visits a conditional expression containing `yield`. + * + * @param node The node to visit. + */ function visitConditionalExpression(node) { + // [source] + // x = a() ? yield : b(); + // + // [intermediate] + // .local _a + // .brfalse whenFalseLabel, (a()) + // .yield resumeLabel + // .mark resumeLabel + // _a = %sent%; + // .br resultLabel + // .mark whenFalseLabel + // _a = b(); + // .mark resultLabel + // x = _a; + // We only need to perform a specific transformation if a `yield` expression exists + // in either the `whenTrue` or `whenFalse` branches. + // A `yield` in the condition will be handled by the normal visitor. if (containsYield(node.whenTrue) || containsYield(node.whenFalse)) { var whenFalseLabel = defineLabel(); var resultLabel = defineLabel(); var resultLocal = declareLocal(); - emitBreakWhenFalse(whenFalseLabel, ts.visitNode(node.condition, visitor, ts.isExpression), node.condition); - emitAssignment(resultLocal, ts.visitNode(node.whenTrue, visitor, ts.isExpression), node.whenTrue); + emitBreakWhenFalse(whenFalseLabel, ts.visitNode(node.condition, visitor, ts.isExpression), /*location*/ node.condition); + emitAssignment(resultLocal, ts.visitNode(node.whenTrue, visitor, ts.isExpression), /*location*/ node.whenTrue); emitBreak(resultLabel); markLabel(whenFalseLabel); - emitAssignment(resultLocal, ts.visitNode(node.whenFalse, visitor, ts.isExpression), node.whenFalse); + emitAssignment(resultLocal, ts.visitNode(node.whenFalse, visitor, ts.isExpression), /*location*/ node.whenFalse); markLabel(resultLabel); return resultLocal; } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a `yield` expression. + * + * @param node The node to visit. + */ function visitYieldExpression(node) { + // [source] + // x = yield a(); + // + // [intermediate] + // .yield resumeLabel, (a()) + // .mark resumeLabel + // x = %sent%; var resumeLabel = defineLabel(); var expression = ts.visitNode(node.expression, visitor, ts.isExpression); if (node.asteriskToken) { - var iterator = (ts.getEmitFlags(node.expression) & 8388608) === 0 - ? ts.createValuesHelper(context, expression, node) + var iterator = (ts.getEmitFlags(node.expression) & 8388608 /* Iterator */) === 0 + ? ts.createValuesHelper(context, expression, /*location*/ node) : expression; - emitYieldStar(iterator, node); + emitYieldStar(iterator, /*location*/ node); } else { - emitYield(expression, node); + emitYield(expression, /*location*/ node); } markLabel(resumeLabel); - return createGeneratorResume(node); + return createGeneratorResume(/*location*/ node); } + /** + * Visits an ArrayLiteralExpression that contains a YieldExpression. + * + * @param node The node to visit. + */ function visitArrayLiteralExpression(node) { - return visitElements(node.elements, undefined, undefined, node.multiLine); + return visitElements(node.elements, /*leadingElement*/ undefined, /*location*/ undefined, node.multiLine); } + /** + * Visits an array of expressions containing one or more YieldExpression nodes + * and returns an expression for the resulting value. + * + * @param elements The elements to visit. + * @param multiLine Whether array literals created should be emitted on multiple lines. + */ function visitElements(elements, leadingElement, location, multiLine) { + // [source] + // ar = [1, yield, 2]; + // + // [intermediate] + // .local _a + // _a = [1]; + // .yield resumeLabel + // .mark resumeLabel + // ar = _a.concat([%sent%, 2]); var numInitialElements = countInitialNodesWithoutYield(elements); var temp; if (numInitialElements > 0) { @@ -58594,6 +70071,23 @@ var ts; } } function visitObjectLiteralExpression(node) { + // [source] + // o = { + // a: 1, + // b: yield, + // c: 2 + // }; + // + // [intermediate] + // .local _a + // _a = { + // a: 1 + // }; + // .yield resumeLabel + // .mark resumeLabel + // o = (_a.b = %sent%, + // _a.c = 2, + // _a); var properties = node.properties; var multiLine = node.multiLine; var numInitialProperties = countInitialNodesWithoutYield(properties); @@ -58618,8 +70112,22 @@ var ts; return expressions; } } + /** + * Visits an ElementAccessExpression that contains a YieldExpression. + * + * @param node The node to visit. + */ function visitElementAccessExpression(node) { if (containsYield(node.argumentExpression)) { + // [source] + // a = x[yield]; + // + // [intermediate] + // .local _a + // _a = x; + // .yield resumeLabel + // .mark resumeLabel + // a = _a[%sent%] var clone_5 = ts.getMutableClone(node); clone_5.expression = cacheExpression(ts.visitNode(node.expression, visitor, ts.isLeftHandSideExpression)); clone_5.argumentExpression = ts.visitNode(node.argumentExpression, visitor, ts.isExpression); @@ -58629,15 +70137,38 @@ var ts; } function visitCallExpression(node) { if (!ts.isImportCall(node) && ts.forEach(node.arguments, containsYield)) { - var _a = ts.createCallBinding(node.expression, hoistVariableDeclaration, languageVersion, true), target = _a.target, thisArg = _a.thisArg; - return ts.setOriginalNode(ts.createFunctionApply(cacheExpression(ts.visitNode(target, visitor, ts.isLeftHandSideExpression)), thisArg, visitElements(node.arguments), node), node); + // [source] + // a.b(1, yield, 2); + // + // [intermediate] + // .local _a, _b, _c + // _b = (_a = a).b; + // _c = [1]; + // .yield resumeLabel + // .mark resumeLabel + // _b.apply(_a, _c.concat([%sent%, 2])); + var _a = ts.createCallBinding(node.expression, hoistVariableDeclaration, languageVersion, /*cacheIdentifiers*/ true), target = _a.target, thisArg = _a.thisArg; + return ts.setOriginalNode(ts.createFunctionApply(cacheExpression(ts.visitNode(target, visitor, ts.isLeftHandSideExpression)), thisArg, visitElements(node.arguments), + /*location*/ node), node); } return ts.visitEachChild(node, visitor, context); } function visitNewExpression(node) { if (ts.forEach(node.arguments, containsYield)) { + // [source] + // new a.b(1, yield, 2); + // + // [intermediate] + // .local _a, _b, _c + // _b = (_a = a.b).bind; + // _c = [1]; + // .yield resumeLabel + // .mark resumeLabel + // new (_b.apply(_a, _c.concat([%sent%, 2]))); var _a = ts.createCallBinding(ts.createPropertyAccess(node.expression, "bind"), hoistVariableDeclaration), target = _a.target, thisArg = _a.thisArg; - return ts.setOriginalNode(ts.setTextRange(ts.createNew(ts.createFunctionApply(cacheExpression(ts.visitNode(target, visitor, ts.isExpression)), thisArg, visitElements(node.arguments, ts.createVoidZero())), undefined, []), node), node); + return ts.setOriginalNode(ts.setTextRange(ts.createNew(ts.createFunctionApply(cacheExpression(ts.visitNode(target, visitor, ts.isExpression)), thisArg, visitElements(node.arguments, + /*leadingElement*/ ts.createVoidZero())), + /*typeArguments*/ undefined, []), node), node); } return ts.visitEachChild(node, visitor, context); } @@ -58666,35 +70197,35 @@ var ts; } function transformAndEmitStatementWorker(node) { switch (node.kind) { - case 213: + case 213 /* Block */: return transformAndEmitBlock(node); - case 216: + case 216 /* ExpressionStatement */: return transformAndEmitExpressionStatement(node); - case 217: + case 217 /* IfStatement */: return transformAndEmitIfStatement(node); - case 218: + case 218 /* DoStatement */: return transformAndEmitDoStatement(node); - case 219: + case 219 /* WhileStatement */: return transformAndEmitWhileStatement(node); - case 220: + case 220 /* ForStatement */: return transformAndEmitForStatement(node); - case 221: + case 221 /* ForInStatement */: return transformAndEmitForInStatement(node); - case 223: + case 223 /* ContinueStatement */: return transformAndEmitContinueStatement(node); - case 224: + case 224 /* BreakStatement */: return transformAndEmitBreakStatement(node); - case 225: + case 225 /* ReturnStatement */: return transformAndEmitReturnStatement(node); - case 226: + case 226 /* WithStatement */: return transformAndEmitWithStatement(node); - case 227: + case 227 /* SwitchStatement */: return transformAndEmitSwitchStatement(node); - case 228: + case 228 /* LabeledStatement */: return transformAndEmitLabeledStatement(node); - case 229: + case 229 /* ThrowStatement */: return transformAndEmitThrowStatement(node); - case 230: + case 230 /* TryStatement */: return transformAndEmitTryStatement(node); default: return emitStatement(ts.visitNode(node, visitor, ts.isStatement)); @@ -58743,10 +70274,23 @@ var ts; } function transformAndEmitIfStatement(node) { if (containsYield(node)) { + // [source] + // if (x) + // /*thenStatement*/ + // else + // /*elseStatement*/ + // + // [intermediate] + // .brfalse elseLabel, (x) + // /*thenStatement*/ + // .br endLabel + // .mark elseLabel + // /*elseStatement*/ + // .mark endLabel if (containsYield(node.thenStatement) || containsYield(node.elseStatement)) { var endLabel = defineLabel(); var elseLabel = node.elseStatement ? defineLabel() : undefined; - emitBreakWhenFalse(node.elseStatement ? elseLabel : endLabel, ts.visitNode(node.expression, visitor, ts.isExpression), node.expression); + emitBreakWhenFalse(node.elseStatement ? elseLabel : endLabel, ts.visitNode(node.expression, visitor, ts.isExpression), /*location*/ node.expression); transformAndEmitEmbeddedStatement(node.thenStatement); if (node.elseStatement) { emitBreak(endLabel); @@ -58765,9 +70309,23 @@ var ts; } function transformAndEmitDoStatement(node) { if (containsYield(node)) { + // [source] + // do { + // /*body*/ + // } + // while (i < 10); + // + // [intermediate] + // .loop conditionLabel, endLabel + // .mark loopLabel + // /*body*/ + // .mark conditionLabel + // .brtrue loopLabel, (i < 10) + // .endloop + // .mark endLabel var conditionLabel = defineLabel(); var loopLabel = defineLabel(); - beginLoopBlock(conditionLabel); + beginLoopBlock(/*continueLabel*/ conditionLabel); markLabel(loopLabel); transformAndEmitEmbeddedStatement(node.statement); markLabel(conditionLabel); @@ -58791,6 +70349,19 @@ var ts; } function transformAndEmitWhileStatement(node) { if (containsYield(node)) { + // [source] + // while (i < 10) { + // /*body*/ + // } + // + // [intermediate] + // .loop loopLabel, endLabel + // .mark loopLabel + // .brfalse endLabel, (i < 10) + // /*body*/ + // .br loopLabel + // .endloop + // .mark endLabel var loopLabel = defineLabel(); var endLabel = beginLoopBlock(loopLabel); markLabel(loopLabel); @@ -58816,6 +70387,23 @@ var ts; } function transformAndEmitForStatement(node) { if (containsYield(node)) { + // [source] + // for (var i = 0; i < 10; i++) { + // /*body*/ + // } + // + // [intermediate] + // .local i + // i = 0; + // .loop incrementLabel, endLoopLabel + // .mark conditionLabel + // .brfalse endLoopLabel, (i < 10) + // /*body*/ + // .mark incrementLabel + // i++; + // .br conditionLabel + // .endloop + // .mark endLoopLabel var conditionLabel = defineLabel(); var incrementLabel = defineLabel(); var endLabel = beginLoopBlock(incrementLabel); @@ -58868,14 +70456,36 @@ var ts; return node; } function transformAndEmitForInStatement(node) { + // TODO(rbuckton): Source map locations if (containsYield(node)) { - var keysArray = declareLocal(); - var key = declareLocal(); - var keysIndex = ts.createLoopVariable(); + // [source] + // for (var p in o) { + // /*body*/ + // } + // + // [intermediate] + // .local _a, _b, _i + // _a = []; + // for (_b in o) _a.push(_b); + // _i = 0; + // .loop incrementLabel, endLoopLabel + // .mark conditionLabel + // .brfalse endLoopLabel, (_i < _a.length) + // p = _a[_i]; + // /*body*/ + // .mark incrementLabel + // _b++; + // .br conditionLabel + // .endloop + // .mark endLoopLabel + var keysArray = declareLocal(); // _a + var key = declareLocal(); // _b + var keysIndex = ts.createLoopVariable(); // _i var initializer = node.initializer; hoistVariableDeclaration(keysIndex); emitAssignment(keysArray, ts.createArrayLiteral()); - emitStatement(ts.createForIn(key, ts.visitNode(node.expression, visitor, ts.isExpression), ts.createStatement(ts.createCall(ts.createPropertyAccess(keysArray, "push"), undefined, [key])))); + emitStatement(ts.createForIn(key, ts.visitNode(node.expression, visitor, ts.isExpression), ts.createStatement(ts.createCall(ts.createPropertyAccess(keysArray, "push"), + /*typeArguments*/ undefined, [key])))); emitAssignment(keysIndex, ts.createLiteral(0)); var conditionLabel = defineLabel(); var incrementLabel = defineLabel(); @@ -58906,6 +70516,18 @@ var ts; } } function visitForInStatement(node) { + // [source] + // for (var x in a) { + // /*body*/ + // } + // + // [intermediate] + // .local x + // .loop + // for (x in a) { + // /*body*/ + // } + // .endloop if (inStatementContainingYield) { beginScriptLoopBlock(); } @@ -58928,9 +70550,10 @@ var ts; function transformAndEmitContinueStatement(node) { var label = findContinueTarget(node.label ? ts.idText(node.label) : undefined); if (label > 0) { - emitBreak(label, node); + emitBreak(label, /*location*/ node); } else { + // invalid continue without a containing loop. Leave the node as is, per #17875. emitStatement(node); } } @@ -58938,7 +70561,7 @@ var ts; if (inStatementContainingYield) { var label = findContinueTarget(node.label && ts.idText(node.label)); if (label > 0) { - return createInlineBreak(label, node); + return createInlineBreak(label, /*location*/ node); } } return ts.visitEachChild(node, visitor, context); @@ -58946,9 +70569,10 @@ var ts; function transformAndEmitBreakStatement(node) { var label = findBreakTarget(node.label ? ts.idText(node.label) : undefined); if (label > 0) { - emitBreak(label, node); + emitBreak(label, /*location*/ node); } else { + // invalid break without a containing loop, switch, or labeled statement. Leave the node as is, per #17875. emitStatement(node); } } @@ -58956,19 +70580,30 @@ var ts; if (inStatementContainingYield) { var label = findBreakTarget(node.label && ts.idText(node.label)); if (label > 0) { - return createInlineBreak(label, node); + return createInlineBreak(label, /*location*/ node); } } return ts.visitEachChild(node, visitor, context); } function transformAndEmitReturnStatement(node) { - emitReturn(ts.visitNode(node.expression, visitor, ts.isExpression), node); + emitReturn(ts.visitNode(node.expression, visitor, ts.isExpression), + /*location*/ node); } function visitReturnStatement(node) { - return createInlineReturn(ts.visitNode(node.expression, visitor, ts.isExpression), node); + return createInlineReturn(ts.visitNode(node.expression, visitor, ts.isExpression), + /*location*/ node); } function transformAndEmitWithStatement(node) { if (containsYield(node)) { + // [source] + // with (x) { + // /*body*/ + // } + // + // [intermediate] + // .with (x) + // /*body*/ + // .endwith beginWithBlock(cacheExpression(ts.visitNode(node.expression, visitor, ts.isExpression))); transformAndEmitEmbeddedStatement(node.statement); endWithBlock(); @@ -58979,31 +70614,66 @@ var ts; } function transformAndEmitSwitchStatement(node) { if (containsYield(node.caseBlock)) { + // [source] + // switch (x) { + // case a: + // /*caseStatements*/ + // case b: + // /*caseStatements*/ + // default: + // /*defaultStatements*/ + // } + // + // [intermediate] + // .local _a + // .switch endLabel + // _a = x; + // switch (_a) { + // case a: + // .br clauseLabels[0] + // } + // switch (_a) { + // case b: + // .br clauseLabels[1] + // } + // .br clauseLabels[2] + // .mark clauseLabels[0] + // /*caseStatements*/ + // .mark clauseLabels[1] + // /*caseStatements*/ + // .mark clauseLabels[2] + // /*caseStatements*/ + // .endswitch + // .mark endLabel var caseBlock = node.caseBlock; var numClauses = caseBlock.clauses.length; var endLabel = beginSwitchBlock(); var expression = cacheExpression(ts.visitNode(node.expression, visitor, ts.isExpression)); + // Create labels for each clause and find the index of the first default clause. var clauseLabels = []; var defaultClauseIndex = -1; for (var i = 0; i < numClauses; i++) { var clause = caseBlock.clauses[i]; clauseLabels.push(defineLabel()); - if (clause.kind === 267 && defaultClauseIndex === -1) { + if (clause.kind === 267 /* DefaultClause */ && defaultClauseIndex === -1) { defaultClauseIndex = i; } } + // Emit switch statements for each run of case clauses either from the first case + // clause or the next case clause with a `yield` in its expression, up to the next + // case clause with a `yield` in its expression. var clausesWritten = 0; var pendingClauses = []; while (clausesWritten < numClauses) { var defaultClausesSkipped = 0; for (var i = clausesWritten; i < numClauses; i++) { var clause = caseBlock.clauses[i]; - if (clause.kind === 266) { + if (clause.kind === 266 /* CaseClause */) { if (containsYield(clause.expression) && pendingClauses.length > 0) { break; } pendingClauses.push(ts.createCaseClause(ts.visitNode(clause.expression, visitor, ts.isExpression), [ - createInlineBreak(clauseLabels[i], clause.expression) + createInlineBreak(clauseLabels[i], /*location*/ clause.expression) ])); } else { @@ -59048,6 +70718,16 @@ var ts; } function transformAndEmitLabeledStatement(node) { if (containsYield(node)) { + // [source] + // x: { + // /*body*/ + // } + // + // [intermediate] + // .labeled "x", endLabel + // /*body*/ + // .endlabeled + // .mark endLabel beginLabeledBlock(ts.idText(node.label)); transformAndEmitEmbeddedStatement(node.statement); endLabeledBlock(); @@ -59067,14 +70747,44 @@ var ts; return node; } function transformAndEmitThrowStatement(node) { - emitThrow(ts.visitNode(node.expression, visitor, ts.isExpression), node); + emitThrow(ts.visitNode(node.expression, visitor, ts.isExpression), + /*location*/ node); } function transformAndEmitTryStatement(node) { if (containsYield(node)) { + // [source] + // try { + // /*tryBlock*/ + // } + // catch (e) { + // /*catchBlock*/ + // } + // finally { + // /*finallyBlock*/ + // } + // + // [intermediate] + // .local _a + // .try tryLabel, catchLabel, finallyLabel, endLabel + // .mark tryLabel + // .nop + // /*tryBlock*/ + // .br endLabel + // .catch + // .mark catchLabel + // _a = %error%; + // /*catchBlock*/ + // .br endLabel + // .finally + // .mark finallyLabel + // /*finallyBlock*/ + // .endfinally + // .endtry + // .mark endLabel beginExceptionBlock(); transformAndEmitEmbeddedStatement(node.tryBlock); if (node.catchClause) { - beginCatchBlock(node.catchClause.variableDeclaration); + beginCatchBlock(node.catchClause.variableDeclaration); // TODO: GH#18217 transformAndEmitEmbeddedStatement(node.catchClause.block); } if (node.finallyBlock) { @@ -59088,7 +70798,7 @@ var ts; } } function containsYield(node) { - return !!node && (node.transformFlags & 16777216) !== 0; + return !!node && (node.transformFlags & 16777216 /* ContainsYield */) !== 0; } function countInitialNodesWithoutYield(nodes) { var numNodes = nodes.length; @@ -59101,7 +70811,7 @@ var ts; } function onSubstituteNode(hint, node) { node = previousOnSubstituteNode(hint, node); - if (hint === 1) { + if (hint === 1 /* Expression */) { return substituteExpression(node); } return node; @@ -59132,20 +70842,23 @@ var ts; } function cacheExpression(node) { var temp; - if (ts.isGeneratedIdentifier(node) || ts.getEmitFlags(node) & 4096) { + if (ts.isGeneratedIdentifier(node) || ts.getEmitFlags(node) & 4096 /* HelperName */) { return node; } temp = ts.createTempVariable(hoistVariableDeclaration); - emitAssignment(temp, node, node); + emitAssignment(temp, node, /*location*/ node); return temp; } function declareLocal(name) { var temp = name ? ts.createUniqueName(name) - : ts.createTempVariable(undefined); + : ts.createTempVariable(/*recordTempVariable*/ undefined); hoistVariableDeclaration(temp); return temp; } + /** + * Defines a label, uses as the target of a Break operation. + */ function defineLabel() { if (!labelOffsets) { labelOffsets = []; @@ -59155,10 +70868,18 @@ var ts; labelOffsets[label] = -1; return label; } + /** + * Marks the current operation with the specified label. + */ function markLabel(label) { ts.Debug.assert(labelOffsets !== undefined, "No labels were defined."); labelOffsets[label] = operations ? operations.length : 0; } + /** + * Begins a block operation (With, Break/Continue, Try/Catch/Finally) + * + * @param block Information about the block. + */ function beginBlock(block) { if (!blocks) { blocks = []; @@ -59167,61 +70888,87 @@ var ts; blockStack = []; } var index = blockActions.length; - blockActions[index] = 0; + blockActions[index] = 0 /* Open */; blockOffsets[index] = operations ? operations.length : 0; blocks[index] = block; blockStack.push(block); return index; } + /** + * Ends the current block operation. + */ function endBlock() { var block = peekBlock(); if (block === undefined) return ts.Debug.fail("beginBlock was never called."); var index = blockActions.length; - blockActions[index] = 1; + blockActions[index] = 1 /* Close */; blockOffsets[index] = operations ? operations.length : 0; blocks[index] = block; blockStack.pop(); return block; } + /** + * Gets the current open block. + */ function peekBlock() { return ts.lastOrUndefined(blockStack); } + /** + * Gets the kind of the current open block. + */ function peekBlockKind() { var block = peekBlock(); return block && block.kind; } + /** + * Begins a code block for a generated `with` statement. + * + * @param expression An identifier representing expression for the `with` block. + */ function beginWithBlock(expression) { var startLabel = defineLabel(); var endLabel = defineLabel(); markLabel(startLabel); beginBlock({ - kind: 1, + kind: 1 /* With */, expression: expression, startLabel: startLabel, endLabel: endLabel }); } + /** + * Ends a code block for a generated `with` statement. + */ function endWithBlock() { - ts.Debug.assert(peekBlockKind() === 1); + ts.Debug.assert(peekBlockKind() === 1 /* With */); var block = endBlock(); markLabel(block.endLabel); } + /** + * Begins a code block for a generated `try` statement. + */ function beginExceptionBlock() { var startLabel = defineLabel(); var endLabel = defineLabel(); markLabel(startLabel); beginBlock({ - kind: 0, - state: 0, + kind: 0 /* Exception */, + state: 0 /* Try */, startLabel: startLabel, endLabel: endLabel }); emitNop(); return endLabel; } + /** + * Enters the `catch` clause of a generated `try` statement. + * + * @param variable The catch variable. + */ function beginCatchBlock(variable) { - ts.Debug.assert(peekBlockKind() === 0); + ts.Debug.assert(peekBlockKind() === 0 /* Exception */); + // generated identifiers should already be unique within a file var name; if (ts.isGeneratedIdentifier(variable.name)) { name = variable.name; @@ -59233,39 +70980,45 @@ var ts; if (!renamedCatchVariables) { renamedCatchVariables = ts.createMap(); renamedCatchVariableDeclarations = []; - context.enableSubstitution(71); + context.enableSubstitution(71 /* Identifier */); } renamedCatchVariables.set(text, true); renamedCatchVariableDeclarations[ts.getOriginalNodeId(variable)] = name; } var exception = peekBlock(); - ts.Debug.assert(exception.state < 1); + ts.Debug.assert(exception.state < 1 /* Catch */); var endLabel = exception.endLabel; emitBreak(endLabel); var catchLabel = defineLabel(); markLabel(catchLabel); - exception.state = 1; + exception.state = 1 /* Catch */; exception.catchVariable = name; exception.catchLabel = catchLabel; - emitAssignment(name, ts.createCall(ts.createPropertyAccess(state, "sent"), undefined, [])); + emitAssignment(name, ts.createCall(ts.createPropertyAccess(state, "sent"), /*typeArguments*/ undefined, [])); emitNop(); } + /** + * Enters the `finally` block of a generated `try` statement. + */ function beginFinallyBlock() { - ts.Debug.assert(peekBlockKind() === 0); + ts.Debug.assert(peekBlockKind() === 0 /* Exception */); var exception = peekBlock(); - ts.Debug.assert(exception.state < 2); + ts.Debug.assert(exception.state < 2 /* Finally */); var endLabel = exception.endLabel; emitBreak(endLabel); var finallyLabel = defineLabel(); markLabel(finallyLabel); - exception.state = 2; + exception.state = 2 /* Finally */; exception.finallyLabel = finallyLabel; } + /** + * Ends the code block for a generated `try` statement. + */ function endExceptionBlock() { - ts.Debug.assert(peekBlockKind() === 0); + ts.Debug.assert(peekBlockKind() === 0 /* Exception */); var exception = endBlock(); var state = exception.state; - if (state < 2) { + if (state < 2 /* Finally */) { emitBreak(exception.endLabel); } else { @@ -59273,52 +71026,83 @@ var ts; } markLabel(exception.endLabel); emitNop(); - exception.state = 3; + exception.state = 3 /* Done */; } + /** + * Begins a code block that supports `break` or `continue` statements that are defined in + * the source tree and not from generated code. + * + * @param labelText Names from containing labeled statements. + */ function beginScriptLoopBlock() { beginBlock({ - kind: 3, + kind: 3 /* Loop */, isScript: true, breakLabel: -1, continueLabel: -1 }); } + /** + * Begins a code block that supports `break` or `continue` statements that are defined in + * generated code. Returns a label used to mark the operation to which to jump when a + * `break` statement targets this block. + * + * @param continueLabel A Label used to mark the operation to which to jump when a + * `continue` statement targets this block. + */ function beginLoopBlock(continueLabel) { var breakLabel = defineLabel(); beginBlock({ - kind: 3, + kind: 3 /* Loop */, isScript: false, breakLabel: breakLabel, continueLabel: continueLabel, }); return breakLabel; } + /** + * Ends a code block that supports `break` or `continue` statements that are defined in + * generated code or in the source tree. + */ function endLoopBlock() { - ts.Debug.assert(peekBlockKind() === 3); + ts.Debug.assert(peekBlockKind() === 3 /* Loop */); var block = endBlock(); var breakLabel = block.breakLabel; if (!block.isScript) { markLabel(breakLabel); } } + /** + * Begins a code block that supports `break` statements that are defined in the source + * tree and not from generated code. + * + */ function beginScriptSwitchBlock() { beginBlock({ - kind: 2, + kind: 2 /* Switch */, isScript: true, breakLabel: -1 }); } + /** + * Begins a code block that supports `break` statements that are defined in generated code. + * Returns a label used to mark the operation to which to jump when a `break` statement + * targets this block. + */ function beginSwitchBlock() { var breakLabel = defineLabel(); beginBlock({ - kind: 2, + kind: 2 /* Switch */, isScript: false, breakLabel: breakLabel, }); return breakLabel; } + /** + * Ends a code block that supports `break` statements that are defined in generated code. + */ function endSwitchBlock() { - ts.Debug.assert(peekBlockKind() === 2); + ts.Debug.assert(peekBlockKind() === 2 /* Switch */); var block = endBlock(); var breakLabel = block.breakLabel; if (!block.isScript) { @@ -59327,7 +71111,7 @@ var ts; } function beginScriptLabeledBlock(labelText) { beginBlock({ - kind: 4, + kind: 4 /* Labeled */, isScript: true, labelText: labelText, breakLabel: -1 @@ -59336,28 +71120,43 @@ var ts; function beginLabeledBlock(labelText) { var breakLabel = defineLabel(); beginBlock({ - kind: 4, + kind: 4 /* Labeled */, isScript: false, labelText: labelText, breakLabel: breakLabel }); } function endLabeledBlock() { - ts.Debug.assert(peekBlockKind() === 4); + ts.Debug.assert(peekBlockKind() === 4 /* Labeled */); var block = endBlock(); if (!block.isScript) { markLabel(block.breakLabel); } } + /** + * Indicates whether the provided block supports `break` statements. + * + * @param block A code block. + */ function supportsUnlabeledBreak(block) { - return block.kind === 2 - || block.kind === 3; + return block.kind === 2 /* Switch */ + || block.kind === 3 /* Loop */; } + /** + * Indicates whether the provided block supports `break` statements with labels. + * + * @param block A code block. + */ function supportsLabeledBreakOrContinue(block) { - return block.kind === 4; + return block.kind === 4 /* Labeled */; } + /** + * Indicates whether the provided block supports `continue` statements. + * + * @param block A code block. + */ function supportsUnlabeledContinue(block) { - return block.kind === 3; + return block.kind === 3 /* Loop */; } function hasImmediateContainingLabeledBlock(labelText, start) { for (var j = start; j >= 0; j--) { @@ -59373,6 +71172,11 @@ var ts; } return false; } + /** + * Finds the label that is the target for a `break` statement. + * + * @param labelText An optional name of a containing labeled statement. + */ function findBreakTarget(labelText) { if (blockStack) { if (labelText) { @@ -59397,6 +71201,11 @@ var ts; } return 0; } + /** + * Finds the label that is the target for a `continue` statement. + * + * @param labelText An optional name of a containing labeled statement. + */ function findContinueTarget(labelText) { if (blockStack) { if (labelText) { @@ -59418,6 +71227,11 @@ var ts; } return 0; } + /** + * Creates an expression that can be used to indicate the value for a label. + * + * @param label A label. + */ function createLabel(label) { if (label !== undefined && label > 0) { if (labelExpressions === undefined) { @@ -59434,64 +71248,153 @@ var ts; } return ts.createOmittedExpression(); } + /** + * Creates a numeric literal for the provided instruction. + */ function createInstruction(instruction) { var literal = ts.createLiteral(instruction); - ts.addSyntheticTrailingComment(literal, 3, getInstructionName(instruction)); + ts.addSyntheticTrailingComment(literal, 3 /* MultiLineCommentTrivia */, getInstructionName(instruction)); return literal; } + /** + * Creates a statement that can be used indicate a Break operation to the provided label. + * + * @param label A label. + * @param location An optional source map location for the statement. + */ function createInlineBreak(label, location) { ts.Debug.assertLessThan(0, label, "Invalid label"); return ts.setTextRange(ts.createReturn(ts.createArrayLiteral([ - createInstruction(3), + createInstruction(3 /* Break */), createLabel(label) ])), location); } + /** + * Creates a statement that can be used indicate a Return operation. + * + * @param expression The expression for the return statement. + * @param location An optional source map location for the statement. + */ function createInlineReturn(expression, location) { return ts.setTextRange(ts.createReturn(ts.createArrayLiteral(expression - ? [createInstruction(2), expression] - : [createInstruction(2)])), location); + ? [createInstruction(2 /* Return */), expression] + : [createInstruction(2 /* Return */)])), location); } + /** + * Creates an expression that can be used to resume from a Yield operation. + */ function createGeneratorResume(location) { - return ts.setTextRange(ts.createCall(ts.createPropertyAccess(state, "sent"), undefined, []), location); + return ts.setTextRange(ts.createCall(ts.createPropertyAccess(state, "sent"), + /*typeArguments*/ undefined, []), location); } + /** + * Emits an empty instruction. + */ function emitNop() { - emitWorker(0); + emitWorker(0 /* Nop */); } + /** + * Emits a Statement. + * + * @param node A statement. + */ function emitStatement(node) { if (node) { - emitWorker(1, [node]); + emitWorker(1 /* Statement */, [node]); } else { emitNop(); } } + /** + * Emits an Assignment operation. + * + * @param left The left-hand side of the assignment. + * @param right The right-hand side of the assignment. + * @param location An optional source map location for the assignment. + */ function emitAssignment(left, right, location) { - emitWorker(2, [left, right], location); + emitWorker(2 /* Assign */, [left, right], location); } + /** + * Emits a Break operation to the specified label. + * + * @param label A label. + * @param location An optional source map location for the assignment. + */ function emitBreak(label, location) { - emitWorker(3, [label], location); + emitWorker(3 /* Break */, [label], location); } + /** + * Emits a Break operation to the specified label when a condition evaluates to a truthy + * value at runtime. + * + * @param label A label. + * @param condition The condition. + * @param location An optional source map location for the assignment. + */ function emitBreakWhenTrue(label, condition, location) { - emitWorker(4, [label, condition], location); + emitWorker(4 /* BreakWhenTrue */, [label, condition], location); } + /** + * Emits a Break to the specified label when a condition evaluates to a falsey value at + * runtime. + * + * @param label A label. + * @param condition The condition. + * @param location An optional source map location for the assignment. + */ function emitBreakWhenFalse(label, condition, location) { - emitWorker(5, [label, condition], location); + emitWorker(5 /* BreakWhenFalse */, [label, condition], location); } + /** + * Emits a YieldStar operation for the provided expression. + * + * @param expression An optional value for the yield operation. + * @param location An optional source map location for the assignment. + */ function emitYieldStar(expression, location) { - emitWorker(7, [expression], location); + emitWorker(7 /* YieldStar */, [expression], location); } + /** + * Emits a Yield operation for the provided expression. + * + * @param expression An optional value for the yield operation. + * @param location An optional source map location for the assignment. + */ function emitYield(expression, location) { - emitWorker(6, [expression], location); + emitWorker(6 /* Yield */, [expression], location); } + /** + * Emits a Return operation for the provided expression. + * + * @param expression An optional value for the operation. + * @param location An optional source map location for the assignment. + */ function emitReturn(expression, location) { - emitWorker(8, [expression], location); + emitWorker(8 /* Return */, [expression], location); } + /** + * Emits a Throw operation for the provided expression. + * + * @param expression A value for the operation. + * @param location An optional source map location for the assignment. + */ function emitThrow(expression, location) { - emitWorker(9, [expression], location); + emitWorker(9 /* Throw */, [expression], location); } + /** + * Emits an Endfinally operation. This is used to handle `finally` block semantics. + */ function emitEndfinally() { - emitWorker(10); + emitWorker(10 /* Endfinally */); } + /** + * Emits an operation. + * + * @param code The OpCode for the operation. + * @param args The optional arguments for the operation. + */ function emitWorker(code, args, location) { if (operations === undefined) { operations = []; @@ -59499,6 +71402,7 @@ var ts; operationLocations = []; } if (labelOffsets === undefined) { + // mark entry point markLabel(defineLabel()); } var operationIndex = operations.length; @@ -59506,6 +71410,9 @@ var ts; operationArguments[operationIndex] = args; operationLocations[operationIndex] = location; } + /** + * Builds the generator function body. + */ function build() { blockIndex = 0; labelNumber = 0; @@ -59518,8 +71425,17 @@ var ts; currentExceptionBlock = undefined; withBlockStack = undefined; var buildResult = buildStatements(); - return createGeneratorHelper(context, ts.setEmitFlags(ts.createFunctionExpression(undefined, undefined, undefined, undefined, [ts.createParameter(undefined, undefined, undefined, state)], undefined, ts.createBlock(buildResult, buildResult.length > 0)), 524288)); + return createGeneratorHelper(context, ts.setEmitFlags(ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, state)], + /*type*/ undefined, ts.createBlock(buildResult, + /*multiLine*/ buildResult.length > 0)), 524288 /* ReuseTempVariableScope */)); } + /** + * Builds the statements for the generator function body. + */ function buildStatements() { if (operations) { for (var operationIndex = 0; operationIndex < operations.length; operationIndex++) { @@ -59540,33 +71456,49 @@ var ts; } return []; } + /** + * Flush the current label and advance to a new label. + */ function flushLabel() { if (!statements) { return; } - appendLabel(!lastOperationWasAbrupt); + appendLabel(/*markLabelEnd*/ !lastOperationWasAbrupt); lastOperationWasAbrupt = false; lastOperationWasCompletion = false; labelNumber++; } + /** + * Flush the final label of the generator function body. + */ function flushFinalLabel(operationIndex) { if (isFinalLabelReachable(operationIndex)) { tryEnterLabel(operationIndex); withBlockStack = undefined; - writeReturn(undefined, undefined); + writeReturn(/*expression*/ undefined, /*operationLocation*/ undefined); } if (statements && clauses) { - appendLabel(false); + appendLabel(/*markLabelEnd*/ false); } updateLabelExpressions(); } + /** + * Tests whether the final label of the generator function body + * is reachable by user code. + */ function isFinalLabelReachable(operationIndex) { + // if the last operation was *not* a completion (return/throw) then + // the final label is reachable. if (!lastOperationWasCompletion) { return true; } + // if there are no labels defined or referenced, then the final label is + // not reachable. if (!labelOffsets || !labelExpressions) { return false; } + // if the label for this offset is referenced, then the final label + // is reachable. for (var label = 0; label < labelOffsets.length; label++) { if (labelOffsets[label] === operationIndex && labelExpressions[label]) { return true; @@ -59574,20 +71506,33 @@ var ts; } return false; } + /** + * Appends a case clause for the last label and sets the new label. + * + * @param markLabelEnd Indicates that the transition between labels was a fall-through + * from a previous case clause and the change in labels should be + * reflected on the `state` object. + */ function appendLabel(markLabelEnd) { if (!clauses) { clauses = []; } if (statements) { if (withBlockStack) { + // The previous label was nested inside one or more `with` blocks, so we + // surround the statements in generated `with` blocks to create the same environment. for (var i = withBlockStack.length - 1; i >= 0; i--) { var withBlock = withBlockStack[i]; statements = [ts.createWith(withBlock.expression, ts.createBlock(statements))]; } } if (currentExceptionBlock) { + // The previous label was nested inside of an exception block, so we must + // indicate entry into a protected region by pushing the label numbers + // for each block in the protected region. var startLabel = currentExceptionBlock.startLabel, catchLabel = currentExceptionBlock.catchLabel, finallyLabel = currentExceptionBlock.finallyLabel, endLabel = currentExceptionBlock.endLabel; - statements.unshift(ts.createStatement(ts.createCall(ts.createPropertyAccess(ts.createPropertyAccess(state, "trys"), "push"), undefined, [ + statements.unshift(ts.createStatement(ts.createCall(ts.createPropertyAccess(ts.createPropertyAccess(state, "trys"), "push"), + /*typeArguments*/ undefined, [ ts.createArrayLiteral([ createLabel(startLabel), createLabel(catchLabel), @@ -59598,12 +71543,17 @@ var ts; currentExceptionBlock = undefined; } if (markLabelEnd) { + // The case clause for the last label falls through to this label, so we + // add an assignment statement to reflect the change in labels. statements.push(ts.createStatement(ts.createAssignment(ts.createPropertyAccess(state, "label"), ts.createLiteral(labelNumber + 1)))); } } clauses.push(ts.createCaseClause(ts.createLiteral(labelNumber), statements || [])); statements = undefined; } + /** + * Tries to enter into a new label at the current operation index. + */ function tryEnterLabel(operationIndex) { if (!labelOffsets) { return; @@ -59623,6 +71573,9 @@ var ts; } } } + /** + * Updates literal expressions for labels with actual label numbers. + */ function updateLabelExpressions() { if (labelExpressions !== undefined && labelNumbers !== undefined) { for (var labelNumber_1 = 0; labelNumber_1 < labelNumbers.length; labelNumber_1++) { @@ -59642,14 +71595,17 @@ var ts; } } } + /** + * Tries to enter or leave a code block. + */ function tryEnterOrLeaveBlock(operationIndex) { if (blocks) { for (; blockIndex < blockActions.length && blockOffsets[blockIndex] <= operationIndex; blockIndex++) { var block = blocks[blockIndex]; var blockAction = blockActions[blockIndex]; switch (block.kind) { - case 0: - if (blockAction === 0) { + case 0 /* Exception */: + if (blockAction === 0 /* Open */) { if (!exceptionBlockStack) { exceptionBlockStack = []; } @@ -59659,64 +71615,76 @@ var ts; exceptionBlockStack.push(currentExceptionBlock); currentExceptionBlock = block; } - else if (blockAction === 1) { + else if (blockAction === 1 /* Close */) { currentExceptionBlock = exceptionBlockStack.pop(); } break; - case 1: - if (blockAction === 0) { + case 1 /* With */: + if (blockAction === 0 /* Open */) { if (!withBlockStack) { withBlockStack = []; } withBlockStack.push(block); } - else if (blockAction === 1) { + else if (blockAction === 1 /* Close */) { withBlockStack.pop(); } break; + // default: do nothing } } } } + /** + * Writes an operation as a statement to the current label's statement list. + * + * @param operation The OpCode of the operation + */ function writeOperation(operationIndex) { tryEnterLabel(operationIndex); tryEnterOrLeaveBlock(operationIndex); + // early termination, nothing else to process in this label if (lastOperationWasAbrupt) { return; } lastOperationWasAbrupt = false; lastOperationWasCompletion = false; var opcode = operations[operationIndex]; - if (opcode === 0) { + if (opcode === 0 /* Nop */) { return; } - else if (opcode === 10) { + else if (opcode === 10 /* Endfinally */) { return writeEndfinally(); } var args = operationArguments[operationIndex]; - if (opcode === 1) { + if (opcode === 1 /* Statement */) { return writeStatement(args[0]); } var location = operationLocations[operationIndex]; switch (opcode) { - case 2: + case 2 /* Assign */: return writeAssign(args[0], args[1], location); - case 3: + case 3 /* Break */: return writeBreak(args[0], location); - case 4: + case 4 /* BreakWhenTrue */: return writeBreakWhenTrue(args[0], args[1], location); - case 5: + case 5 /* BreakWhenFalse */: return writeBreakWhenFalse(args[0], args[1], location); - case 6: + case 6 /* Yield */: return writeYield(args[0], location); - case 7: + case 7 /* YieldStar */: return writeYieldStar(args[0], location); - case 8: + case 8 /* Return */: return writeReturn(args[0], location); - case 9: + case 9 /* Throw */: return writeThrow(args[0], location); } } + /** + * Writes a statement to the current label's statement list. + * + * @param statement A statement to write. + */ function writeStatement(statement) { if (statement) { if (!statements) { @@ -59727,65 +71695,179 @@ var ts; } } } + /** + * Writes an Assign operation to the current label's statement list. + * + * @param left The left-hand side of the assignment. + * @param right The right-hand side of the assignment. + * @param operationLocation The source map location for the operation. + */ function writeAssign(left, right, operationLocation) { writeStatement(ts.setTextRange(ts.createStatement(ts.createAssignment(left, right)), operationLocation)); } + /** + * Writes a Throw operation to the current label's statement list. + * + * @param expression The value to throw. + * @param operationLocation The source map location for the operation. + */ function writeThrow(expression, operationLocation) { lastOperationWasAbrupt = true; lastOperationWasCompletion = true; writeStatement(ts.setTextRange(ts.createThrow(expression), operationLocation)); } + /** + * Writes a Return operation to the current label's statement list. + * + * @param expression The value to return. + * @param operationLocation The source map location for the operation. + */ function writeReturn(expression, operationLocation) { lastOperationWasAbrupt = true; lastOperationWasCompletion = true; writeStatement(ts.setEmitFlags(ts.setTextRange(ts.createReturn(ts.createArrayLiteral(expression - ? [createInstruction(2), expression] - : [createInstruction(2)])), operationLocation), 384)); + ? [createInstruction(2 /* Return */), expression] + : [createInstruction(2 /* Return */)])), operationLocation), 384 /* NoTokenSourceMaps */)); } + /** + * Writes a Break operation to the current label's statement list. + * + * @param label The label for the Break. + * @param operationLocation The source map location for the operation. + */ function writeBreak(label, operationLocation) { lastOperationWasAbrupt = true; writeStatement(ts.setEmitFlags(ts.setTextRange(ts.createReturn(ts.createArrayLiteral([ - createInstruction(3), + createInstruction(3 /* Break */), createLabel(label) - ])), operationLocation), 384)); + ])), operationLocation), 384 /* NoTokenSourceMaps */)); } + /** + * Writes a BreakWhenTrue operation to the current label's statement list. + * + * @param label The label for the Break. + * @param condition The condition for the Break. + * @param operationLocation The source map location for the operation. + */ function writeBreakWhenTrue(label, condition, operationLocation) { writeStatement(ts.setEmitFlags(ts.createIf(condition, ts.setEmitFlags(ts.setTextRange(ts.createReturn(ts.createArrayLiteral([ - createInstruction(3), + createInstruction(3 /* Break */), createLabel(label) - ])), operationLocation), 384)), 1)); + ])), operationLocation), 384 /* NoTokenSourceMaps */)), 1 /* SingleLine */)); } + /** + * Writes a BreakWhenFalse operation to the current label's statement list. + * + * @param label The label for the Break. + * @param condition The condition for the Break. + * @param operationLocation The source map location for the operation. + */ function writeBreakWhenFalse(label, condition, operationLocation) { writeStatement(ts.setEmitFlags(ts.createIf(ts.createLogicalNot(condition), ts.setEmitFlags(ts.setTextRange(ts.createReturn(ts.createArrayLiteral([ - createInstruction(3), + createInstruction(3 /* Break */), createLabel(label) - ])), operationLocation), 384)), 1)); + ])), operationLocation), 384 /* NoTokenSourceMaps */)), 1 /* SingleLine */)); } + /** + * Writes a Yield operation to the current label's statement list. + * + * @param expression The expression to yield. + * @param operationLocation The source map location for the operation. + */ function writeYield(expression, operationLocation) { lastOperationWasAbrupt = true; writeStatement(ts.setEmitFlags(ts.setTextRange(ts.createReturn(ts.createArrayLiteral(expression - ? [createInstruction(4), expression] - : [createInstruction(4)])), operationLocation), 384)); + ? [createInstruction(4 /* Yield */), expression] + : [createInstruction(4 /* Yield */)])), operationLocation), 384 /* NoTokenSourceMaps */)); } + /** + * Writes a YieldStar instruction to the current label's statement list. + * + * @param expression The expression to yield. + * @param operationLocation The source map location for the operation. + */ function writeYieldStar(expression, operationLocation) { lastOperationWasAbrupt = true; writeStatement(ts.setEmitFlags(ts.setTextRange(ts.createReturn(ts.createArrayLiteral([ - createInstruction(5), + createInstruction(5 /* YieldStar */), expression - ])), operationLocation), 384)); + ])), operationLocation), 384 /* NoTokenSourceMaps */)); } + /** + * Writes an Endfinally instruction to the current label's statement list. + */ function writeEndfinally() { lastOperationWasAbrupt = true; writeStatement(ts.createReturn(ts.createArrayLiteral([ - createInstruction(7) + createInstruction(7 /* Endfinally */) ]))); } } ts.transformGenerators = transformGenerators; function createGeneratorHelper(context, body) { context.requestEmitHelper(generatorHelper); - return ts.createCall(ts.getHelperName("__generator"), undefined, [ts.createThis(), body]); + return ts.createCall(ts.getHelperName("__generator"), + /*typeArguments*/ undefined, [ts.createThis(), body]); } + // The __generator helper is used by down-level transformations to emulate the runtime + // semantics of an ES2015 generator function. When called, this helper returns an + // object that implements the Iterator protocol, in that it has `next`, `return`, and + // `throw` methods that step through the generator when invoked. + // + // parameters: + // @param thisArg The value to use as the `this` binding for the transformed generator body. + // @param body A function that acts as the transformed generator body. + // + // variables: + // _ Persistent state for the generator that is shared between the helper and the + // generator body. The state object has the following members: + // sent() - A method that returns or throws the current completion value. + // label - The next point at which to resume evaluation of the generator body. + // trys - A stack of protected regions (try/catch/finally blocks). + // ops - A stack of pending instructions when inside of a finally block. + // f A value indicating whether the generator is executing. + // y An iterator to delegate for a yield*. + // t A temporary variable that holds one of the following values (note that these + // cases do not overlap): + // - The completion value when resuming from a `yield` or `yield*`. + // - The error value for a catch block. + // - The current protected region (array of try/catch/finally/end labels). + // - The verb (`next`, `throw`, or `return` method) to delegate to the expression + // of a `yield*`. + // - The result of evaluating the verb delegated to the expression of a `yield*`. + // + // functions: + // verb(n) Creates a bound callback to the `step` function for opcode `n`. + // step(op) Evaluates opcodes in a generator body until execution is suspended or + // completed. + // + // The __generator helper understands a limited set of instructions: + // 0: next(value?) - Start or resume the generator with the specified value. + // 1: throw(error) - Resume the generator with an exception. If the generator is + // suspended inside of one or more protected regions, evaluates + // any intervening finally blocks between the current label and + // the nearest catch block or function boundary. If uncaught, the + // exception is thrown to the caller. + // 2: return(value?) - Resume the generator as if with a return. If the generator is + // suspended inside of one or more protected regions, evaluates any + // intervening finally blocks. + // 3: break(label) - Jump to the specified label. If the label is outside of the + // current protected region, evaluates any intervening finally + // blocks. + // 4: yield(value?) - Yield execution to the caller with an optional value. When + // resumed, the generator will continue at the next label. + // 5: yield*(value) - Delegates evaluation to the supplied iterator. When + // delegation completes, the generator will continue at the next + // label. + // 6: catch(error) - Handles an exception thrown from within the generator body. If + // the current label is inside of one or more protected regions, + // evaluates any intervening finally blocks between the current + // label and the nearest catch block or function boundary. If + // uncaught, the exception is thrown to the caller. + // 7: endfinally - Ends a finally block, resuming the last instruction prior to + // entering a finally block. + // + // For examples of how these are used, see the comments in ./transformers/generators.ts var generatorHelper = { name: "typescript:generator", scoped: false, @@ -59793,6 +71875,7 @@ var ts; text: "\n var __generator = (this && this.__generator) || function (thisArg, body) {\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n function verb(n) { return function (v) { return step([n, v]); }; }\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n while (_) try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [op[0] & 2, t.value];\n switch (op[0]) {\n case 0: case 1: t = op; break;\n case 4: _.label++; return { value: op[1], done: false };\n case 5: _.label++; y = op[1]; op = [0]; continue;\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n if (t[2]) _.ops.pop();\n _.trys.pop(); continue;\n }\n op = body.call(thisArg, _);\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n }\n };" }; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { function transformModule(context) { @@ -59813,26 +71896,32 @@ var ts; var previousOnEmitNode = context.onEmitNode; context.onSubstituteNode = onSubstituteNode; context.onEmitNode = onEmitNode; - context.enableSubstitution(71); - context.enableSubstitution(200); - context.enableSubstitution(198); - context.enableSubstitution(199); - context.enableSubstitution(271); - context.enableEmitNotification(274); - var moduleInfoMap = []; - var deferredExports = []; - var currentSourceFile; - var currentModuleInfo; - var noSubstitution; + context.enableSubstitution(71 /* Identifier */); // Substitutes expression identifiers with imported/exported symbols. + context.enableSubstitution(200 /* BinaryExpression */); // Substitutes assignments to exported symbols. + context.enableSubstitution(198 /* PrefixUnaryExpression */); // Substitutes updates to exported symbols. + context.enableSubstitution(199 /* PostfixUnaryExpression */); // Substitutes updates to exported symbols. + context.enableSubstitution(271 /* ShorthandPropertyAssignment */); // Substitutes shorthand property assignments for imported/exported symbols. + context.enableEmitNotification(274 /* SourceFile */); // Restore state when substituting nodes in a file. + var moduleInfoMap = []; // The ExternalModuleInfo for each file. + var deferredExports = []; // Exports to defer until an EndOfDeclarationMarker is found. + var currentSourceFile; // The current file. + var currentModuleInfo; // The ExternalModuleInfo for the current file. + var noSubstitution; // Set of nodes for which substitution rules should be ignored. var needUMDDynamicImportHelper; return ts.chainBundle(transformSourceFile); + /** + * Transforms the module aspects of a SourceFile. + * + * @param node The SourceFile node. + */ function transformSourceFile(node) { - if (node.isDeclarationFile || !(ts.isEffectiveExternalModule(node, compilerOptions) || node.transformFlags & 67108864)) { + if (node.isDeclarationFile || !(ts.isEffectiveExternalModule(node, compilerOptions) || node.transformFlags & 67108864 /* ContainsDynamicImport */)) { return node; } currentSourceFile = node; currentModuleInfo = ts.collectExternalModuleInfo(node, resolver, compilerOptions); moduleInfoMap[ts.getOriginalNodeId(node)] = currentModuleInfo; + // Perform the transformation. var transformModule = getTransformModuleDelegate(moduleKind); var updated = transformModule(node); currentSourceFile = undefined; @@ -59846,6 +71935,11 @@ var ts; } return false; } + /** + * Transforms a SourceFile into a CommonJS module. + * + * @param node The SourceFile node. + */ function transformCommonJSModule(node) { startLexicalEnvironment(); var statements = []; @@ -59856,48 +71950,105 @@ var ts; } ts.append(statements, ts.visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, ts.isStatement)); ts.addRange(statements, ts.visitNodes(node.statements, sourceElementVisitor, ts.isStatement, statementOffset)); - addExportEqualsIfNeeded(statements, false); + addExportEqualsIfNeeded(statements, /*emitAsReturn*/ false); ts.prependStatements(statements, endLexicalEnvironment()); var updated = ts.updateSourceFileNode(node, ts.setTextRange(ts.createNodeArray(statements), node.statements)); if (currentModuleInfo.hasExportStarsToExportValues && !compilerOptions.importHelpers) { + // If we have any `export * from ...` declarations + // we need to inform the emitter to add the __export helper. ts.addEmitHelper(updated, exportStarHelper); } ts.addEmitHelpers(updated, context.readEmitHelpers()); return updated; } + /** + * Transforms a SourceFile into an AMD module. + * + * @param node The SourceFile node. + */ function transformAMDModule(node) { var define = ts.createIdentifier("define"); var moduleName = ts.tryGetModuleNameFromFile(node, host, compilerOptions); - var _a = collectAsynchronousDependencies(node, true), aliasedModuleNames = _a.aliasedModuleNames, unaliasedModuleNames = _a.unaliasedModuleNames, importAliasNames = _a.importAliasNames; + // An AMD define function has the following shape: + // + // define(id?, dependencies?, factory); + // + // This has the shape of the following: + // + // define(name, ["module1", "module2"], function (module1Alias) { ... } + // + // The location of the alias in the parameter list in the factory function needs to + // match the position of the module name in the dependency list. + // + // To ensure this is true in cases of modules with no aliases, e.g.: + // + // import "module" + // + // or + // + // /// + // + // we need to add modules without alias names to the end of the dependencies list + var _a = collectAsynchronousDependencies(node, /*includeNonAmdDependencies*/ true), aliasedModuleNames = _a.aliasedModuleNames, unaliasedModuleNames = _a.unaliasedModuleNames, importAliasNames = _a.importAliasNames; + // Create an updated SourceFile: + // + // define(moduleName?, ["module1", "module2"], function ... var updated = ts.updateSourceFileNode(node, ts.setTextRange(ts.createNodeArray([ - ts.createStatement(ts.createCall(define, undefined, (moduleName ? [moduleName] : []).concat([ + ts.createStatement(ts.createCall(define, + /*typeArguments*/ undefined, (moduleName ? [moduleName] : []).concat([ + // Add the dependency array argument: + // + // ["require", "exports", module1", "module2", ...] ts.createArrayLiteral([ ts.createLiteral("require"), ts.createLiteral("exports") ].concat(aliasedModuleNames, unaliasedModuleNames)), - ts.createFunctionExpression(undefined, undefined, undefined, undefined, [ - ts.createParameter(undefined, undefined, undefined, "require"), - ts.createParameter(undefined, undefined, undefined, "exports") - ].concat(importAliasNames), undefined, transformAsynchronousModuleBody(node)) + // Add the module body function argument: + // + // function (require, exports, module1, module2) ... + ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ + ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "require"), + ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "exports") + ].concat(importAliasNames), + /*type*/ undefined, transformAsynchronousModuleBody(node)) ]))) - ]), node.statements)); + ]), + /*location*/ node.statements)); ts.addEmitHelpers(updated, context.readEmitHelpers()); return updated; } + /** + * Transforms a SourceFile into a UMD module. + * + * @param node The SourceFile node. + */ function transformUMDModule(node) { - var _a = collectAsynchronousDependencies(node, false), aliasedModuleNames = _a.aliasedModuleNames, unaliasedModuleNames = _a.unaliasedModuleNames, importAliasNames = _a.importAliasNames; + var _a = collectAsynchronousDependencies(node, /*includeNonAmdDependencies*/ false), aliasedModuleNames = _a.aliasedModuleNames, unaliasedModuleNames = _a.unaliasedModuleNames, importAliasNames = _a.importAliasNames; var moduleName = ts.tryGetModuleNameFromFile(node, host, compilerOptions); - var umdHeader = ts.createFunctionExpression(undefined, undefined, undefined, undefined, [ts.createParameter(undefined, undefined, undefined, "factory")], undefined, ts.setTextRange(ts.createBlock([ + var umdHeader = ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "factory")], + /*type*/ undefined, ts.setTextRange(ts.createBlock([ ts.createIf(ts.createLogicalAnd(ts.createTypeCheck(ts.createIdentifier("module"), "object"), ts.createTypeCheck(ts.createPropertyAccess(ts.createIdentifier("module"), "exports"), "object")), ts.createBlock([ - ts.createVariableStatement(undefined, [ - ts.createVariableDeclaration("v", undefined, ts.createCall(ts.createIdentifier("factory"), undefined, [ + ts.createVariableStatement( + /*modifiers*/ undefined, [ + ts.createVariableDeclaration("v", + /*type*/ undefined, ts.createCall(ts.createIdentifier("factory"), + /*typeArguments*/ undefined, [ ts.createIdentifier("require"), ts.createIdentifier("exports") ])) ]), - ts.setEmitFlags(ts.createIf(ts.createStrictInequality(ts.createIdentifier("v"), ts.createIdentifier("undefined")), ts.createStatement(ts.createAssignment(ts.createPropertyAccess(ts.createIdentifier("module"), "exports"), ts.createIdentifier("v")))), 1) + ts.setEmitFlags(ts.createIf(ts.createStrictInequality(ts.createIdentifier("v"), ts.createIdentifier("undefined")), ts.createStatement(ts.createAssignment(ts.createPropertyAccess(ts.createIdentifier("module"), "exports"), ts.createIdentifier("v")))), 1 /* SingleLine */) ]), ts.createIf(ts.createLogicalAnd(ts.createTypeCheck(ts.createIdentifier("define"), "function"), ts.createPropertyAccess(ts.createIdentifier("define"), "amd")), ts.createBlock([ - ts.createStatement(ts.createCall(ts.createIdentifier("define"), undefined, (moduleName ? [moduleName] : []).concat([ + ts.createStatement(ts.createCall(ts.createIdentifier("define"), + /*typeArguments*/ undefined, (moduleName ? [moduleName] : []).concat([ ts.createArrayLiteral([ ts.createLiteral("require"), ts.createLiteral("exports") @@ -59905,27 +72056,62 @@ var ts; ts.createIdentifier("factory") ]))) ]))) - ], true), undefined)); + ], + /*multiLine*/ true), + /*location*/ undefined)); + // Create an updated SourceFile: + // + // (function (factory) { + // if (typeof module === "object" && typeof module.exports === "object") { + // var v = factory(require, exports); + // if (v !== undefined) module.exports = v; + // } + // else if (typeof define === 'function' && define.amd) { + // define(["require", "exports"], factory); + // } + // })(function ...) var updated = ts.updateSourceFileNode(node, ts.setTextRange(ts.createNodeArray([ - ts.createStatement(ts.createCall(umdHeader, undefined, [ - ts.createFunctionExpression(undefined, undefined, undefined, undefined, [ - ts.createParameter(undefined, undefined, undefined, "require"), - ts.createParameter(undefined, undefined, undefined, "exports") - ].concat(importAliasNames), undefined, transformAsynchronousModuleBody(node)) + ts.createStatement(ts.createCall(umdHeader, + /*typeArguments*/ undefined, [ + // Add the module body function argument: + // + // function (require, exports) ... + ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ + ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "require"), + ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "exports") + ].concat(importAliasNames), + /*type*/ undefined, transformAsynchronousModuleBody(node)) ])) - ]), node.statements)); + ]), + /*location*/ node.statements)); ts.addEmitHelpers(updated, context.readEmitHelpers()); return updated; } + /** + * Collect the additional asynchronous dependencies for the module. + * + * @param node The source file. + * @param includeNonAmdDependencies A value indicating whether to include non-AMD dependencies. + */ function collectAsynchronousDependencies(node, includeNonAmdDependencies) { + // names of modules with corresponding parameter in the factory function var aliasedModuleNames = []; + // names of modules with no corresponding parameters in factory function var unaliasedModuleNames = []; + // names of the parameters in the factory function; these + // parameters need to match the indexes of the corresponding + // module names in aliasedModuleNames. var importAliasNames = []; + // Fill in amd-dependency tags for (var _i = 0, _a = node.amdDependencies; _i < _a.length; _i++) { var amdDependency = _a[_i]; if (amdDependency.name) { aliasedModuleNames.push(ts.createLiteral(amdDependency.path)); - importAliasNames.push(ts.createParameter(undefined, undefined, undefined, amdDependency.name)); + importAliasNames.push(ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, amdDependency.name)); } else { unaliasedModuleNames.push(ts.createLiteral(amdDependency.path)); @@ -59933,13 +72119,20 @@ var ts; } for (var _b = 0, _c = currentModuleInfo.externalImports; _b < _c.length; _b++) { var importNode = _c[_b]; + // Find the name of the external module var externalModuleName = ts.getExternalModuleNameLiteral(importNode, currentSourceFile, host, resolver, compilerOptions); + // Find the name of the module alias, if there is one var importAliasName = ts.getLocalNameForExternalImport(importNode, currentSourceFile); + // It is possible that externalModuleName is undefined if it is not string literal. + // This can happen in the invalid import syntax. + // E.g : "import * from alias from 'someLib';" if (externalModuleName) { if (includeNonAmdDependencies && importAliasName) { - ts.setEmitFlags(importAliasName, 4); + // Set emitFlags on the name of the classDeclaration + // This is so that when printer will not substitute the identifier + ts.setEmitFlags(importAliasName, 4 /* NoSubstitution */); aliasedModuleNames.push(externalModuleName); - importAliasNames.push(ts.createParameter(undefined, undefined, undefined, importAliasName)); + importAliasNames.push(ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, importAliasName)); } else { unaliasedModuleNames.push(externalModuleName); @@ -59952,29 +72145,40 @@ var ts; if (ts.isImportEqualsDeclaration(node) || ts.isExportDeclaration(node) || !ts.getExternalModuleNameLiteral(node, currentSourceFile, host, resolver, compilerOptions)) { return undefined; } - var name = ts.getLocalNameForExternalImport(node, currentSourceFile); + var name = ts.getLocalNameForExternalImport(node, currentSourceFile); // TODO: GH#18217 var expr = getHelperExpressionForImport(node, name); if (expr === name) { return undefined; } return ts.createStatement(ts.createAssignment(name, expr)); } + /** + * Transforms a SourceFile into an AMD or UMD module body. + * + * @param node The SourceFile node. + */ function transformAsynchronousModuleBody(node) { startLexicalEnvironment(); var statements = []; - var statementOffset = ts.addPrologue(statements, node.statements, !compilerOptions.noImplicitUseStrict, sourceElementVisitor); + var statementOffset = ts.addPrologue(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor); if (shouldEmitUnderscoreUnderscoreESModule()) { ts.append(statements, createUnderscoreUnderscoreESModule()); } + // Visit each statement of the module body. ts.append(statements, ts.visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, ts.isStatement)); if (moduleKind === ts.ModuleKind.AMD) { ts.addRange(statements, ts.mapDefined(currentModuleInfo.externalImports, getAMDImportExpressionForImport)); } ts.addRange(statements, ts.visitNodes(node.statements, sourceElementVisitor, ts.isStatement, statementOffset)); - addExportEqualsIfNeeded(statements, true); + // Append the 'export =' statement if provided. + addExportEqualsIfNeeded(statements, /*emitAsReturn*/ true); + // End the lexical environment for the module body + // and merge any new lexical declarations. ts.prependStatements(statements, endLexicalEnvironment()); - var body = ts.createBlock(statements, true); + var body = ts.createBlock(statements, /*multiLine*/ true); if (currentModuleInfo.hasExportStarsToExportValues && !compilerOptions.importHelpers) { + // If we have any `export * from ...` declarations + // we need to inform the emitter to add the __export helper. ts.addEmitHelper(body, exportStarHelper); } if (needUMDDynamicImportHelper) { @@ -59982,6 +72186,14 @@ var ts; } return body; } + /** + * Adds the down-level representation of `export=` to the statement list if one exists + * in the source file. + * + * @param statements The Statement list to modify. + * @param emitAsReturn A value indicating whether to emit the `export=` statement as a + * return statement. + */ function addExportEqualsIfNeeded(statements, emitAsReturn) { if (currentModuleInfo.exportEquals) { var expressionResult = ts.visitNode(currentModuleInfo.exportEquals.expression, moduleExpressionElementVisitor); @@ -59989,50 +72201,60 @@ var ts; if (emitAsReturn) { var statement = ts.createReturn(expressionResult); ts.setTextRange(statement, currentModuleInfo.exportEquals); - ts.setEmitFlags(statement, 384 | 1536); + ts.setEmitFlags(statement, 384 /* NoTokenSourceMaps */ | 1536 /* NoComments */); statements.push(statement); } else { var statement = ts.createStatement(ts.createAssignment(ts.createPropertyAccess(ts.createIdentifier("module"), "exports"), expressionResult)); ts.setTextRange(statement, currentModuleInfo.exportEquals); - ts.setEmitFlags(statement, 1536); + ts.setEmitFlags(statement, 1536 /* NoComments */); statements.push(statement); } } } } + // + // Top-Level Source Element Visitors + // + /** + * Visits a node at the top level of the source file. + * + * @param node The node to visit. + */ function sourceElementVisitor(node) { switch (node.kind) { - case 244: + case 244 /* ImportDeclaration */: return visitImportDeclaration(node); - case 243: + case 243 /* ImportEqualsDeclaration */: return visitImportEqualsDeclaration(node); - case 250: + case 250 /* ExportDeclaration */: return visitExportDeclaration(node); - case 249: + case 249 /* ExportAssignment */: return visitExportAssignment(node); - case 214: + case 214 /* VariableStatement */: return visitVariableStatement(node); - case 234: + case 234 /* FunctionDeclaration */: return visitFunctionDeclaration(node); - case 235: + case 235 /* ClassDeclaration */: return visitClassDeclaration(node); - case 304: + case 304 /* MergeDeclarationMarker */: return visitMergeDeclarationMarker(node); - case 305: + case 305 /* EndOfDeclarationMarker */: return visitEndOfDeclarationMarker(node); default: return ts.visitEachChild(node, moduleExpressionElementVisitor, context); } } function moduleExpressionElementVisitor(node) { - if (!(node.transformFlags & 67108864) && !(node.transformFlags & 2048)) { + // This visitor does not need to descend into the tree if there is no dynamic import or destructuring assignment, + // as export/import statements are only transformed at the top level of a file. + if (!(node.transformFlags & 67108864 /* ContainsDynamicImport */) && !(node.transformFlags & 2048 /* ContainsDestructuringAssignment */)) { return node; } if (ts.isImportCall(node)) { return visitImportCallExpression(node); } - else if (node.transformFlags & 1024 && ts.isBinaryExpression(node)) { + else if (node.transformFlags & 1024 /* DestructuringAssignment */ && ts.isBinaryExpression(node)) { return visitDestructuringAssignment(node); } else { @@ -60044,24 +72266,24 @@ var ts; for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { var elem = _a[_i]; switch (elem.kind) { - case 270: + case 270 /* PropertyAssignment */: if (destructuringNeedsFlattening(elem.initializer)) { return true; } break; - case 271: + case 271 /* ShorthandPropertyAssignment */: if (destructuringNeedsFlattening(elem.name)) { return true; } break; - case 272: + case 272 /* SpreadAssignment */: if (destructuringNeedsFlattening(elem.expression)) { return true; } break; - case 154: - case 156: - case 157: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return false; default: ts.Debug.assertNever(elem, "Unhandled object member kind"); } @@ -60087,13 +72309,13 @@ var ts; } function visitDestructuringAssignment(node) { if (destructuringNeedsFlattening(node.left)) { - return ts.flattenDestructuringAssignment(node, moduleExpressionElementVisitor, context, 0, false, createAllExportExpressions); + return ts.flattenDestructuringAssignment(node, moduleExpressionElementVisitor, context, 0 /* All */, /*needsValue*/ false, createAllExportExpressions); } return ts.visitEachChild(node, moduleExpressionElementVisitor, context); } function visitImportCallExpression(node) { var argument = ts.visitNode(ts.firstOrUndefined(node.arguments), moduleExpressionElementVisitor); - var containsLexicalThis = !!(node.transformFlags & 16384); + var containsLexicalThis = !!(node.transformFlags & 16384 /* ContainsLexicalThis */); switch (compilerOptions.module) { case ts.ModuleKind.AMD: return createImportCallExpressionAMD(argument, containsLexicalThis); @@ -60105,103 +72327,181 @@ var ts; } } function createImportCallExpressionUMD(arg, containsLexicalThis) { + // (function (factory) { + // ... (regular UMD) + // } + // })(function (require, exports, useSyncRequire) { + // "use strict"; + // Object.defineProperty(exports, "__esModule", { value: true }); + // var __syncRequire = typeof module === "object" && typeof module.exports === "object"; + // var __resolved = new Promise(function (resolve) { resolve(); }); + // ..... + // __syncRequire + // ? __resolved.then(function () { return require(x); }) /*CommonJs Require*/ + // : new Promise(function (_a, _b) { require([x], _a, _b); }); /*Amd Require*/ + // }); needUMDDynamicImportHelper = true; if (ts.isSimpleCopiableExpression(arg)) { - var argClone = ts.isGeneratedIdentifier(arg) ? arg : ts.isStringLiteral(arg) ? ts.createLiteral(arg) : ts.setEmitFlags(ts.setTextRange(ts.getSynthesizedClone(arg), arg), 1536); - return ts.createConditional(ts.createIdentifier("__syncRequire"), createImportCallExpressionCommonJS(arg, containsLexicalThis), createImportCallExpressionAMD(argClone, containsLexicalThis)); + var argClone = ts.isGeneratedIdentifier(arg) ? arg : ts.isStringLiteral(arg) ? ts.createLiteral(arg) : ts.setEmitFlags(ts.setTextRange(ts.getSynthesizedClone(arg), arg), 1536 /* NoComments */); + return ts.createConditional( + /*condition*/ ts.createIdentifier("__syncRequire"), + /*whenTrue*/ createImportCallExpressionCommonJS(arg, containsLexicalThis), + /*whenFalse*/ createImportCallExpressionAMD(argClone, containsLexicalThis)); } else { var temp = ts.createTempVariable(hoistVariableDeclaration); - return ts.createComma(ts.createAssignment(temp, arg), ts.createConditional(ts.createIdentifier("__syncRequire"), createImportCallExpressionCommonJS(temp, containsLexicalThis), createImportCallExpressionAMD(temp, containsLexicalThis))); + return ts.createComma(ts.createAssignment(temp, arg), ts.createConditional( + /*condition*/ ts.createIdentifier("__syncRequire"), + /*whenTrue*/ createImportCallExpressionCommonJS(temp, containsLexicalThis), + /*whenFalse*/ createImportCallExpressionAMD(temp, containsLexicalThis))); } } function createImportCallExpressionAMD(arg, containsLexicalThis) { + // improt("./blah") + // emit as + // define(["require", "exports", "blah"], function (require, exports) { + // ... + // new Promise(function (_a, _b) { require([x], _a, _b); }); /*Amd Require*/ + // }); var resolve = ts.createUniqueName("resolve"); var reject = ts.createUniqueName("reject"); var parameters = [ - ts.createParameter(undefined, undefined, undefined, resolve), - ts.createParameter(undefined, undefined, undefined, reject) + ts.createParameter(/*decorator*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ resolve), + ts.createParameter(/*decorator*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ reject) ]; var body = ts.createBlock([ - ts.createStatement(ts.createCall(ts.createIdentifier("require"), undefined, [ts.createArrayLiteral([arg || ts.createOmittedExpression()]), resolve, reject])) + ts.createStatement(ts.createCall(ts.createIdentifier("require"), + /*typeArguments*/ undefined, [ts.createArrayLiteral([arg || ts.createOmittedExpression()]), resolve, reject])) ]); var func; - if (languageVersion >= 2) { - func = ts.createArrowFunction(undefined, undefined, parameters, undefined, undefined, body); + if (languageVersion >= 2 /* ES2015 */) { + func = ts.createArrowFunction( + /*modifiers*/ undefined, + /*typeParameters*/ undefined, parameters, + /*type*/ undefined, + /*equalsGreaterThanToken*/ undefined, body); } else { - func = ts.createFunctionExpression(undefined, undefined, undefined, undefined, parameters, undefined, body); + func = ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, parameters, + /*type*/ undefined, body); + // if there is a lexical 'this' in the import call arguments, ensure we indicate + // that this new function expression indicates it captures 'this' so that the + // es2015 transformer will properly substitute 'this' with '_this'. if (containsLexicalThis) { - ts.setEmitFlags(func, 8); + ts.setEmitFlags(func, 8 /* CapturesThis */); } } - var promise = ts.createNew(ts.createIdentifier("Promise"), undefined, [func]); + var promise = ts.createNew(ts.createIdentifier("Promise"), /*typeArguments*/ undefined, [func]); if (compilerOptions.esModuleInterop) { context.requestEmitHelper(importStarHelper); - return ts.createCall(ts.createPropertyAccess(promise, ts.createIdentifier("then")), undefined, [ts.getHelperName("__importStar")]); + return ts.createCall(ts.createPropertyAccess(promise, ts.createIdentifier("then")), /*typeArguments*/ undefined, [ts.getHelperName("__importStar")]); } return promise; } function createImportCallExpressionCommonJS(arg, containsLexicalThis) { - var promiseResolveCall = ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Promise"), "resolve"), undefined, []); - var requireCall = ts.createCall(ts.createIdentifier("require"), undefined, arg ? [arg] : []); + // import("./blah") + // emit as + // Promise.resolve().then(function () { return require(x); }) /*CommonJs Require*/ + // We have to wrap require in then callback so that require is done in asynchronously + // if we simply do require in resolve callback in Promise constructor. We will execute the loading immediately + var promiseResolveCall = ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Promise"), "resolve"), /*typeArguments*/ undefined, /*argumentsArray*/ []); + var requireCall = ts.createCall(ts.createIdentifier("require"), /*typeArguments*/ undefined, arg ? [arg] : []); if (compilerOptions.esModuleInterop) { context.requestEmitHelper(importStarHelper); - requireCall = ts.createCall(ts.getHelperName("__importStar"), undefined, [requireCall]); + requireCall = ts.createCall(ts.getHelperName("__importStar"), /*typeArguments*/ undefined, [requireCall]); } var func; - if (languageVersion >= 2) { - func = ts.createArrowFunction(undefined, undefined, [], undefined, undefined, requireCall); + if (languageVersion >= 2 /* ES2015 */) { + func = ts.createArrowFunction( + /*modifiers*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ [], + /*type*/ undefined, + /*equalsGreaterThanToken*/ undefined, requireCall); } else { - func = ts.createFunctionExpression(undefined, undefined, undefined, undefined, [], undefined, ts.createBlock([ts.createReturn(requireCall)])); + func = ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ [], + /*type*/ undefined, ts.createBlock([ts.createReturn(requireCall)])); + // if there is a lexical 'this' in the import call arguments, ensure we indicate + // that this new function expression indicates it captures 'this' so that the + // es2015 transformer will properly substitute 'this' with '_this'. if (containsLexicalThis) { - ts.setEmitFlags(func, 8); + ts.setEmitFlags(func, 8 /* CapturesThis */); } } - return ts.createCall(ts.createPropertyAccess(promiseResolveCall, "then"), undefined, [func]); + return ts.createCall(ts.createPropertyAccess(promiseResolveCall, "then"), /*typeArguments*/ undefined, [func]); } function getHelperExpressionForImport(node, innerExpr) { - if (!compilerOptions.esModuleInterop || ts.getEmitFlags(node) & 67108864) { + if (!compilerOptions.esModuleInterop || ts.getEmitFlags(node) & 67108864 /* NeverApplyImportHelper */) { return innerExpr; } if (ts.getImportNeedsImportStarHelper(node)) { context.requestEmitHelper(importStarHelper); - return ts.createCall(ts.getHelperName("__importStar"), undefined, [innerExpr]); + return ts.createCall(ts.getHelperName("__importStar"), /*typeArguments*/ undefined, [innerExpr]); } if (ts.getImportNeedsImportDefaultHelper(node)) { context.requestEmitHelper(importDefaultHelper); - return ts.createCall(ts.getHelperName("__importDefault"), undefined, [innerExpr]); + return ts.createCall(ts.getHelperName("__importDefault"), /*typeArguments*/ undefined, [innerExpr]); } return innerExpr; } + /** + * Visits an ImportDeclaration node. + * + * @param node The node to visit. + */ function visitImportDeclaration(node) { var statements; var namespaceDeclaration = ts.getNamespaceDeclarationNode(node); if (moduleKind !== ts.ModuleKind.AMD) { if (!node.importClause) { + // import "mod"; return ts.setTextRange(ts.createStatement(createRequireCall(node)), node); } else { var variables = []; if (namespaceDeclaration && !ts.isDefaultImport(node)) { - variables.push(ts.createVariableDeclaration(ts.getSynthesizedClone(namespaceDeclaration.name), undefined, getHelperExpressionForImport(node, createRequireCall(node)))); + // import * as n from "mod"; + variables.push(ts.createVariableDeclaration(ts.getSynthesizedClone(namespaceDeclaration.name), + /*type*/ undefined, getHelperExpressionForImport(node, createRequireCall(node)))); } else { - variables.push(ts.createVariableDeclaration(ts.getGeneratedNameForNode(node), undefined, getHelperExpressionForImport(node, createRequireCall(node)))); + // import d from "mod"; + // import { x, y } from "mod"; + // import d, { x, y } from "mod"; + // import d, * as n from "mod"; + variables.push(ts.createVariableDeclaration(ts.getGeneratedNameForNode(node), + /*type*/ undefined, getHelperExpressionForImport(node, createRequireCall(node)))); if (namespaceDeclaration && ts.isDefaultImport(node)) { - variables.push(ts.createVariableDeclaration(ts.getSynthesizedClone(namespaceDeclaration.name), undefined, ts.getGeneratedNameForNode(node))); + variables.push(ts.createVariableDeclaration(ts.getSynthesizedClone(namespaceDeclaration.name), + /*type*/ undefined, ts.getGeneratedNameForNode(node))); } } - statements = ts.append(statements, ts.setTextRange(ts.createVariableStatement(undefined, ts.createVariableDeclarationList(variables, languageVersion >= 2 ? 2 : 0)), node)); + statements = ts.append(statements, ts.setTextRange(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList(variables, languageVersion >= 2 /* ES2015 */ ? 2 /* Const */ : 0 /* None */)), + /*location*/ node)); } } else if (namespaceDeclaration && ts.isDefaultImport(node)) { - statements = ts.append(statements, ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.setTextRange(ts.createVariableDeclaration(ts.getSynthesizedClone(namespaceDeclaration.name), undefined, ts.getGeneratedNameForNode(node)), node) - ], languageVersion >= 2 ? 2 : 0))); + // import d, * as n from "mod"; + statements = ts.append(statements, ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.setTextRange(ts.createVariableDeclaration(ts.getSynthesizedClone(namespaceDeclaration.name), + /*type*/ undefined, ts.getGeneratedNameForNode(node)), + /*location*/ node) + ], languageVersion >= 2 /* ES2015 */ ? 2 /* Const */ : 0 /* None */))); } if (hasAssociatedEndOfDeclarationMarker(node)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfImportDeclaration(deferredExports[id], node); } @@ -60210,33 +72510,47 @@ var ts; } return ts.singleOrMany(statements); } + /** + * Creates a `require()` call to import an external module. + * + * @param importNode The declararation to import. + */ function createRequireCall(importNode) { var moduleName = ts.getExternalModuleNameLiteral(importNode, currentSourceFile, host, resolver, compilerOptions); var args = []; if (moduleName) { args.push(moduleName); } - return ts.createCall(ts.createIdentifier("require"), undefined, args); + return ts.createCall(ts.createIdentifier("require"), /*typeArguments*/ undefined, args); } + /** + * Visits an ImportEqualsDeclaration node. + * + * @param node The node to visit. + */ function visitImportEqualsDeclaration(node) { ts.Debug.assert(ts.isExternalModuleImportEqualsDeclaration(node), "import= for internal module references should be handled in an earlier transformer."); var statements; if (moduleKind !== ts.ModuleKind.AMD) { - if (ts.hasModifier(node, 1)) { + if (ts.hasModifier(node, 1 /* Export */)) { statements = ts.append(statements, ts.setTextRange(ts.createStatement(createExportExpression(node.name, createRequireCall(node))), node)); } else { - statements = ts.append(statements, ts.setTextRange(ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.createVariableDeclaration(ts.getSynthesizedClone(node.name), undefined, createRequireCall(node)) - ], languageVersion >= 2 ? 2 : 0)), node)); + statements = ts.append(statements, ts.setTextRange(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(ts.getSynthesizedClone(node.name), + /*type*/ undefined, createRequireCall(node)) + ], + /*flags*/ languageVersion >= 2 /* ES2015 */ ? 2 /* Const */ : 0 /* None */)), node)); } } else { - if (ts.hasModifier(node, 1)) { + if (ts.hasModifier(node, 1 /* Export */)) { statements = ts.append(statements, ts.setTextRange(ts.createStatement(createExportExpression(ts.getExportName(node), ts.getLocalName(node))), node)); } } if (hasAssociatedEndOfDeclarationMarker(node)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfImportEqualsDeclaration(deferredExports[id], node); } @@ -60245,17 +72559,28 @@ var ts; } return ts.singleOrMany(statements); } + /** + * Visits an ExportDeclaration node. + * + * @param The node to visit. + */ function visitExportDeclaration(node) { if (!node.moduleSpecifier) { + // Elide export declarations with no module specifier as they are handled + // elsewhere. return undefined; } var generatedName = ts.getGeneratedNameForNode(node); if (node.exportClause) { var statements = []; + // export { x, y } from "mod"; if (moduleKind !== ts.ModuleKind.AMD) { - statements.push(ts.setTextRange(ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.createVariableDeclaration(generatedName, undefined, createRequireCall(node)) - ])), node)); + statements.push(ts.setTextRange(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(generatedName, + /*type*/ undefined, createRequireCall(node)) + ])), + /*location*/ node)); } for (var _i = 0, _a = node.exportClause.elements; _i < _a.length; _i++) { var specifier = _a[_i]; @@ -60265,9 +72590,15 @@ var ts; return ts.singleOrMany(statements); } else { + // export * from "mod"; return ts.setTextRange(ts.createStatement(createExportStarHelper(context, moduleKind !== ts.ModuleKind.AMD ? createRequireCall(node) : generatedName)), node); } } + /** + * Visits an ExportAssignment node. + * + * @param node The node to visit. + */ function visitExportAssignment(node) { if (node.isExportEquals) { return undefined; @@ -60275,23 +72606,35 @@ var ts; var statements; var original = node.original; if (original && hasAssociatedEndOfDeclarationMarker(original)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); - deferredExports[id] = appendExportStatement(deferredExports[id], ts.createIdentifier("default"), ts.visitNode(node.expression, moduleExpressionElementVisitor), node, true); + deferredExports[id] = appendExportStatement(deferredExports[id], ts.createIdentifier("default"), ts.visitNode(node.expression, moduleExpressionElementVisitor), /*location*/ node, /*allowComments*/ true); } else { - statements = appendExportStatement(statements, ts.createIdentifier("default"), ts.visitNode(node.expression, moduleExpressionElementVisitor), node, true); + statements = appendExportStatement(statements, ts.createIdentifier("default"), ts.visitNode(node.expression, moduleExpressionElementVisitor), /*location*/ node, /*allowComments*/ true); } return ts.singleOrMany(statements); } + /** + * Visits a FunctionDeclaration node. + * + * @param node The node to visit. + */ function visitFunctionDeclaration(node) { var statements; - if (ts.hasModifier(node, 1)) { - statements = ts.append(statements, ts.setOriginalNode(ts.setTextRange(ts.createFunctionDeclaration(undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), node.asteriskToken, ts.getDeclarationName(node, true, true), undefined, ts.visitNodes(node.parameters, moduleExpressionElementVisitor), undefined, ts.visitEachChild(node.body, moduleExpressionElementVisitor, context)), node), node)); + if (ts.hasModifier(node, 1 /* Export */)) { + statements = ts.append(statements, ts.setOriginalNode(ts.setTextRange(ts.createFunctionDeclaration( + /*decorators*/ undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), node.asteriskToken, ts.getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true), + /*typeParameters*/ undefined, ts.visitNodes(node.parameters, moduleExpressionElementVisitor), + /*type*/ undefined, ts.visitEachChild(node.body, moduleExpressionElementVisitor, context)), + /*location*/ node), + /*original*/ node)); } else { statements = ts.append(statements, ts.visitEachChild(node, moduleExpressionElementVisitor, context)); } if (hasAssociatedEndOfDeclarationMarker(node)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfHoistedDeclaration(deferredExports[id], node); } @@ -60300,15 +72643,23 @@ var ts; } return ts.singleOrMany(statements); } + /** + * Visits a ClassDeclaration node. + * + * @param node The node to visit. + */ function visitClassDeclaration(node) { var statements; - if (ts.hasModifier(node, 1)) { - statements = ts.append(statements, ts.setOriginalNode(ts.setTextRange(ts.createClassDeclaration(undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), ts.getDeclarationName(node, true, true), undefined, ts.visitNodes(node.heritageClauses, moduleExpressionElementVisitor), ts.visitNodes(node.members, moduleExpressionElementVisitor)), node), node)); + if (ts.hasModifier(node, 1 /* Export */)) { + statements = ts.append(statements, ts.setOriginalNode(ts.setTextRange(ts.createClassDeclaration( + /*decorators*/ undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), ts.getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true), + /*typeParameters*/ undefined, ts.visitNodes(node.heritageClauses, moduleExpressionElementVisitor), ts.visitNodes(node.members, moduleExpressionElementVisitor)), node), node)); } else { statements = ts.append(statements, ts.visitEachChild(node, moduleExpressionElementVisitor, context)); } if (hasAssociatedEndOfDeclarationMarker(node)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfHoistedDeclaration(deferredExports[id], node); } @@ -60317,12 +72668,19 @@ var ts; } return ts.singleOrMany(statements); } + /** + * Visits a VariableStatement node. + * + * @param node The node to visit. + */ function visitVariableStatement(node) { var statements; var variables; var expressions; - if (ts.hasModifier(node, 1)) { + if (ts.hasModifier(node, 1 /* Export */)) { var modifiers = void 0; + // If we're exporting these variables, then these just become assignments to 'exports.x'. + // We only want to emit assignments for variables with initializers. for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) { var variable = _a[_i]; if (ts.isIdentifier(variable.name) && ts.isLocalName(variable.name)) { @@ -60346,6 +72704,7 @@ var ts; statements = ts.append(statements, ts.visitEachChild(node, moduleExpressionElementVisitor, context)); } if (hasAssociatedEndOfDeclarationMarker(node)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfVariableStatement(deferredExports[id], node); } @@ -60357,35 +72716,72 @@ var ts; function createAllExportExpressions(name, value, location) { var exportedNames = getExports(name); if (exportedNames) { + // For each additional export of the declaration, apply an export assignment. var expression = ts.isExportName(name) ? value : ts.createAssignment(name, value); for (var _i = 0, exportedNames_1 = exportedNames; _i < exportedNames_1.length; _i++) { var exportName = exportedNames_1[_i]; - ts.setEmitFlags(expression, 4); - expression = createExportExpression(exportName, expression, location); + // Mark the node to prevent triggering substitution. + ts.setEmitFlags(expression, 4 /* NoSubstitution */); + expression = createExportExpression(exportName, expression, /*location*/ location); } return expression; } return ts.createAssignment(name, value); } + /** + * Transforms an exported variable with an initializer into an expression. + * + * @param node The node to transform. + */ function transformInitializedVariable(node) { if (ts.isBindingPattern(node.name)) { - return ts.flattenDestructuringAssignment(ts.visitNode(node, moduleExpressionElementVisitor), undefined, context, 0, false, createAllExportExpressions); + return ts.flattenDestructuringAssignment(ts.visitNode(node, moduleExpressionElementVisitor), + /*visitor*/ undefined, context, 0 /* All */, + /*needsValue*/ false, createAllExportExpressions); } else { - return ts.createAssignment(ts.setTextRange(ts.createPropertyAccess(ts.createIdentifier("exports"), node.name), node.name), ts.visitNode(node.initializer, moduleExpressionElementVisitor)); + return ts.createAssignment(ts.setTextRange(ts.createPropertyAccess(ts.createIdentifier("exports"), node.name), + /*location*/ node.name), ts.visitNode(node.initializer, moduleExpressionElementVisitor)); } } + /** + * Visits a MergeDeclarationMarker used as a placeholder for the beginning of a merged + * and transformed declaration. + * + * @param node The node to visit. + */ function visitMergeDeclarationMarker(node) { - if (hasAssociatedEndOfDeclarationMarker(node) && node.original.kind === 214) { + // For an EnumDeclaration or ModuleDeclaration that merges with a preceeding + // declaration we do not emit a leading variable declaration. To preserve the + // begin/end semantics of the declararation and to properly handle exports + // we wrapped the leading variable declaration in a `MergeDeclarationMarker`. + // + // To balance the declaration, add the exports of the elided variable + // statement. + if (hasAssociatedEndOfDeclarationMarker(node) && node.original.kind === 214 /* VariableStatement */) { var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfVariableStatement(deferredExports[id], node.original); } return node; } + /** + * Determines whether a node has an associated EndOfDeclarationMarker. + * + * @param node The node to test. + */ function hasAssociatedEndOfDeclarationMarker(node) { - return (ts.getEmitFlags(node) & 4194304) !== 0; + return (ts.getEmitFlags(node) & 4194304 /* HasEndOfDeclarationMarker */) !== 0; } + /** + * Visits a DeclarationMarker used as a placeholder for the end of a transformed + * declaration. + * + * @param node The node to visit. + */ function visitEndOfDeclarationMarker(node) { + // For some transformations we emit an `EndOfDeclarationMarker` to mark the actual + // end of the transformed declaration. We use this marker to emit any deferred exports + // of the declaration. var id = ts.getOriginalNodeId(node); var statements = deferredExports[id]; if (statements) { @@ -60394,6 +72790,15 @@ var ts; } return node; } + /** + * Appends the exports of an ImportDeclaration to a statement list, returning the + * statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param decl The declaration whose exports are to be recorded. + */ function appendExportsOfImportDeclaration(statements, decl) { if (currentModuleInfo.exportEquals) { return statements; @@ -60408,10 +72813,10 @@ var ts; var namedBindings = importClause.namedBindings; if (namedBindings) { switch (namedBindings.kind) { - case 246: + case 246 /* NamespaceImport */: statements = appendExportsOfDeclaration(statements, namedBindings); break; - case 247: + case 247 /* NamedImports */: for (var _i = 0, _a = namedBindings.elements; _i < _a.length; _i++) { var importBinding = _a[_i]; statements = appendExportsOfDeclaration(statements, importBinding); @@ -60421,12 +72826,30 @@ var ts; } return statements; } + /** + * Appends the exports of an ImportEqualsDeclaration to a statement list, returning the + * statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param decl The declaration whose exports are to be recorded. + */ function appendExportsOfImportEqualsDeclaration(statements, decl) { if (currentModuleInfo.exportEquals) { return statements; } return appendExportsOfDeclaration(statements, decl); } + /** + * Appends the exports of a VariableStatement to a statement list, returning the statement + * list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param node The VariableStatement whose exports are to be recorded. + */ function appendExportsOfVariableStatement(statements, node) { if (currentModuleInfo.exportEquals) { return statements; @@ -60437,6 +72860,15 @@ var ts; } return statements; } + /** + * Appends the exports of a VariableDeclaration or BindingElement to a statement list, + * returning the statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param decl The declaration whose exports are to be recorded. + */ function appendExportsOfBindingElement(statements, decl) { if (currentModuleInfo.exportEquals) { return statements; @@ -60454,72 +72886,136 @@ var ts; } return statements; } + /** + * Appends the exports of a ClassDeclaration or FunctionDeclaration to a statement list, + * returning the statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param decl The declaration whose exports are to be recorded. + */ function appendExportsOfHoistedDeclaration(statements, decl) { if (currentModuleInfo.exportEquals) { return statements; } - if (ts.hasModifier(decl, 1)) { - var exportName = ts.hasModifier(decl, 512) ? ts.createIdentifier("default") : ts.getDeclarationName(decl); - statements = appendExportStatement(statements, exportName, ts.getLocalName(decl), decl); + if (ts.hasModifier(decl, 1 /* Export */)) { + var exportName = ts.hasModifier(decl, 512 /* Default */) ? ts.createIdentifier("default") : ts.getDeclarationName(decl); + statements = appendExportStatement(statements, exportName, ts.getLocalName(decl), /*location*/ decl); } if (decl.name) { statements = appendExportsOfDeclaration(statements, decl); } return statements; } + /** + * Appends the exports of a declaration to a statement list, returning the statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param decl The declaration to export. + */ function appendExportsOfDeclaration(statements, decl) { var name = ts.getDeclarationName(decl); var exportSpecifiers = currentModuleInfo.exportSpecifiers.get(ts.idText(name)); if (exportSpecifiers) { for (var _i = 0, exportSpecifiers_1 = exportSpecifiers; _i < exportSpecifiers_1.length; _i++) { var exportSpecifier = exportSpecifiers_1[_i]; - statements = appendExportStatement(statements, exportSpecifier.name, name, exportSpecifier.name); + statements = appendExportStatement(statements, exportSpecifier.name, name, /*location*/ exportSpecifier.name); } } return statements; } + /** + * Appends the down-level representation of an export to a statement list, returning the + * statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param exportName The name of the export. + * @param expression The expression to export. + * @param location The location to use for source maps and comments for the export. + * @param allowComments Whether to allow comments on the export. + */ function appendExportStatement(statements, exportName, expression, location, allowComments) { statements = ts.append(statements, createExportStatement(exportName, expression, location, allowComments)); return statements; } function createUnderscoreUnderscoreESModule() { var statement; - if (languageVersion === 0) { - statement = ts.createStatement(createExportExpression(ts.createIdentifier("__esModule"), ts.createLiteral(true))); + if (languageVersion === 0 /* ES3 */) { + statement = ts.createStatement(createExportExpression(ts.createIdentifier("__esModule"), ts.createLiteral(/*value*/ true))); } else { - statement = ts.createStatement(ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Object"), "defineProperty"), undefined, [ + statement = ts.createStatement(ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Object"), "defineProperty"), + /*typeArguments*/ undefined, [ ts.createIdentifier("exports"), ts.createLiteral("__esModule"), ts.createObjectLiteral([ - ts.createPropertyAssignment("value", ts.createLiteral(true)) + ts.createPropertyAssignment("value", ts.createLiteral(/*value*/ true)) ]) ])); } - ts.setEmitFlags(statement, 1048576); + ts.setEmitFlags(statement, 1048576 /* CustomPrologue */); return statement; } + /** + * Creates a call to the current file's export function to export a value. + * + * @param name The bound name of the export. + * @param value The exported value. + * @param location The location to use for source maps and comments for the export. + * @param allowComments An optional value indicating whether to emit comments for the statement. + */ function createExportStatement(name, value, location, allowComments) { var statement = ts.setTextRange(ts.createStatement(createExportExpression(name, value)), location); ts.startOnNewLine(statement); if (!allowComments) { - ts.setEmitFlags(statement, 1536); + ts.setEmitFlags(statement, 1536 /* NoComments */); } return statement; } + /** + * Creates a call to the current file's export function to export a value. + * + * @param name The bound name of the export. + * @param value The exported value. + * @param location The location to use for source maps and comments for the export. + */ function createExportExpression(name, value, location) { return ts.setTextRange(ts.createAssignment(ts.createPropertyAccess(ts.createIdentifier("exports"), ts.getSynthesizedClone(name)), value), location); } + // + // Modifier Visitors + // + /** + * Visit nodes to elide module-specific modifiers. + * + * @param node The node to visit. + */ function modifierVisitor(node) { + // Elide module-specific modifiers. switch (node.kind) { - case 84: - case 79: + case 84 /* ExportKeyword */: + case 79 /* DefaultKeyword */: return undefined; } return node; } + // + // Emit Notification + // + /** + * Hook for node emit notifications. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emit A callback used to emit the node in the printer. + */ function onEmitNode(hint, node, emitCallback) { - if (node.kind === 274) { + if (node.kind === 274 /* SourceFile */) { currentSourceFile = node; currentModuleInfo = moduleInfoMap[ts.getOriginalNodeId(currentSourceFile)]; noSubstitution = []; @@ -60532,12 +73028,21 @@ var ts; previousOnEmitNode(hint, node, emitCallback); } } + // + // Substitutions + // + /** + * Hooks node substitutions. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to substitute. + */ function onSubstituteNode(hint, node) { node = previousOnSubstituteNode(hint, node); if (node.id && noSubstitution[node.id]) { return node; } - if (hint === 1) { + if (hint === 1 /* Expression */) { return substituteExpression(node); } else if (ts.isShorthandPropertyAssignment(node)) { @@ -60545,10 +73050,18 @@ var ts; } return node; } + /** + * Substitution for a ShorthandPropertyAssignment whose declaration name is an imported + * or exported symbol. + * + * @param node The node to substitute. + */ function substituteShorthandPropertyAssignment(node) { var name = node.name; var exportedOrImportedName = substituteExpressionIdentifier(name); if (exportedOrImportedName !== name) { + // A shorthand property with an assignment initializer is probably part of a + // destructuring assignment if (node.objectAssignmentInitializer) { var initializer = ts.createAssignment(exportedOrImportedName, node.objectAssignmentInitializer); return ts.setTextRange(ts.createPropertyAssignment(name, initializer), node); @@ -60557,20 +73070,31 @@ var ts; } return node; } + /** + * Substitution for an Expression that may contain an imported or exported symbol. + * + * @param node The node to substitute. + */ function substituteExpression(node) { switch (node.kind) { - case 71: + case 71 /* Identifier */: return substituteExpressionIdentifier(node); - case 200: + case 200 /* BinaryExpression */: return substituteBinaryExpression(node); - case 199: - case 198: + case 199 /* PostfixUnaryExpression */: + case 198 /* PrefixUnaryExpression */: return substituteUnaryExpression(node); } return node; } + /** + * Substitution for an Identifier expression that may contain an imported or exported + * symbol. + * + * @param node The node to substitute. + */ function substituteExpressionIdentifier(node) { - if (ts.getEmitFlags(node) & 4096) { + if (ts.getEmitFlags(node) & 4096 /* HelperName */) { var externalHelpersModuleName = ts.getExternalHelpersModuleName(currentSourceFile); if (externalHelpersModuleName) { return ts.createPropertyAccess(externalHelpersModuleName, node); @@ -60579,23 +73103,39 @@ var ts; } if (!ts.isGeneratedIdentifier(node) && !ts.isLocalName(node)) { var exportContainer = resolver.getReferencedExportContainer(node, ts.isExportName(node)); - if (exportContainer && exportContainer.kind === 274) { - return ts.setTextRange(ts.createPropertyAccess(ts.createIdentifier("exports"), ts.getSynthesizedClone(node)), node); + if (exportContainer && exportContainer.kind === 274 /* SourceFile */) { + return ts.setTextRange(ts.createPropertyAccess(ts.createIdentifier("exports"), ts.getSynthesizedClone(node)), + /*location*/ node); } var importDeclaration = resolver.getReferencedImportDeclaration(node); if (importDeclaration) { if (ts.isImportClause(importDeclaration)) { - return ts.setTextRange(ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent), ts.createIdentifier("default")), node); + return ts.setTextRange(ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent), ts.createIdentifier("default")), + /*location*/ node); } else if (ts.isImportSpecifier(importDeclaration)) { var name = importDeclaration.propertyName || importDeclaration.name; - return ts.setTextRange(ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent.parent.parent), ts.getSynthesizedClone(name)), node); + return ts.setTextRange(ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent.parent.parent), ts.getSynthesizedClone(name)), + /*location*/ node); } } } return node; } + /** + * Substitution for a BinaryExpression that may contain an imported or exported symbol. + * + * @param node The node to substitute. + */ function substituteBinaryExpression(node) { + // When we see an assignment expression whose left-hand side is an exported symbol, + // we should ensure all exports of that symbol are updated with the correct value. + // + // - We do not substitute generated identifiers for any reason. + // - We do not substitute identifiers tagged with the LocalName flag. + // - We do not substitute identifiers that were originally the name of an enum or + // namespace due to how they are transformed in TypeScript. + // - We only substitute identifiers that are exported at the top level. if (ts.isAssignmentOperator(node.operatorToken.kind) && ts.isIdentifier(node.left) && !ts.isGeneratedIdentifier(node.left) @@ -60603,30 +73143,48 @@ var ts; && !ts.isDeclarationNameOfEnumOrNamespace(node.left)) { var exportedNames = getExports(node.left); if (exportedNames) { + // For each additional export of the declaration, apply an export assignment. var expression = node; for (var _i = 0, exportedNames_2 = exportedNames; _i < exportedNames_2.length; _i++) { var exportName = exportedNames_2[_i]; + // Mark the node to prevent triggering this rule again. noSubstitution[ts.getNodeId(expression)] = true; - expression = createExportExpression(exportName, expression, node); + expression = createExportExpression(exportName, expression, /*location*/ node); } return expression; } } return node; } + /** + * Substitution for a UnaryExpression that may contain an imported or exported symbol. + * + * @param node The node to substitute. + */ function substituteUnaryExpression(node) { - if ((node.operator === 43 || node.operator === 44) + // When we see a prefix or postfix increment expression whose operand is an exported + // symbol, we should ensure all exports of that symbol are updated with the correct + // value. + // + // - We do not substitute generated identifiers for any reason. + // - We do not substitute identifiers tagged with the LocalName flag. + // - We do not substitute identifiers that were originally the name of an enum or + // namespace due to how they are transformed in TypeScript. + // - We only substitute identifiers that are exported at the top level. + if ((node.operator === 43 /* PlusPlusToken */ || node.operator === 44 /* MinusMinusToken */) && ts.isIdentifier(node.operand) && !ts.isGeneratedIdentifier(node.operand) && !ts.isLocalName(node.operand) && !ts.isDeclarationNameOfEnumOrNamespace(node.operand)) { var exportedNames = getExports(node.operand); if (exportedNames) { - var expression = node.kind === 199 - ? ts.setTextRange(ts.createBinary(node.operand, ts.createToken(node.operator === 43 ? 59 : 60), ts.createLiteral(1)), node) + var expression = node.kind === 199 /* PostfixUnaryExpression */ + ? ts.setTextRange(ts.createBinary(node.operand, ts.createToken(node.operator === 43 /* PlusPlusToken */ ? 59 /* PlusEqualsToken */ : 60 /* MinusEqualsToken */), ts.createLiteral(1)), + /*location*/ node) : node; for (var _i = 0, exportedNames_3 = exportedNames; _i < exportedNames_3.length; _i++) { var exportName = exportedNames_3[_i]; + // Mark the node to prevent triggering this rule again. noSubstitution[ts.getNodeId(expression)] = true; expression = createExportExpression(exportName, expression); } @@ -60635,6 +73193,11 @@ var ts; } return node; } + /** + * Gets the additional exports of a name. + * + * @param name The name. + */ function getExports(name) { if (!ts.isGeneratedIdentifier(name)) { var valueDeclaration = resolver.getReferencedImportDeclaration(name) @@ -60647,6 +73210,7 @@ var ts; } } ts.transformModule = transformModule; + // emit output for the __export helper function var exportStarHelper = { name: "typescript:export-star", scoped: true, @@ -60655,25 +73219,29 @@ var ts; function createExportStarHelper(context, module) { var compilerOptions = context.getCompilerOptions(); return compilerOptions.importHelpers - ? ts.createCall(ts.getHelperName("__exportStar"), undefined, [module, ts.createIdentifier("exports")]) - : ts.createCall(ts.createIdentifier("__export"), undefined, [module]); + ? ts.createCall(ts.getHelperName("__exportStar"), /*typeArguments*/ undefined, [module, ts.createIdentifier("exports")]) + : ts.createCall(ts.createIdentifier("__export"), /*typeArguments*/ undefined, [module]); } + // emit helper for dynamic import var dynamicImportUMDHelper = { name: "typescript:dynamicimport-sync-require", scoped: true, text: "\n var __syncRequire = typeof module === \"object\" && typeof module.exports === \"object\";" }; + // emit helper for `import * as Name from "foo"` var importStarHelper = { name: "typescript:commonjsimportstar", scoped: false, text: "\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];\n result[\"default\"] = mod;\n return result;\n};" }; + // emit helper for `import Name from "foo"` var importDefaultHelper = { name: "typescript:commonjsimportdefault", scoped: false, text: "\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};" }; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { function transformSystemModule(context) { @@ -60685,48 +73253,78 @@ var ts; var previousOnEmitNode = context.onEmitNode; context.onSubstituteNode = onSubstituteNode; context.onEmitNode = onEmitNode; - context.enableSubstitution(71); - context.enableSubstitution(271); - context.enableSubstitution(200); - context.enableSubstitution(198); - context.enableSubstitution(199); - context.enableEmitNotification(274); - var moduleInfoMap = []; - var deferredExports = []; - var exportFunctionsMap = []; - var noSubstitutionMap = []; - var currentSourceFile; - var moduleInfo; - var exportFunction; - var contextObject; + context.enableSubstitution(71 /* Identifier */); // Substitutes expression identifiers for imported symbols. + context.enableSubstitution(271 /* ShorthandPropertyAssignment */); // Substitutes expression identifiers for imported symbols + context.enableSubstitution(200 /* BinaryExpression */); // Substitutes assignments to exported symbols. + context.enableSubstitution(198 /* PrefixUnaryExpression */); // Substitutes updates to exported symbols. + context.enableSubstitution(199 /* PostfixUnaryExpression */); // Substitutes updates to exported symbols. + context.enableEmitNotification(274 /* SourceFile */); // Restore state when substituting nodes in a file. + var moduleInfoMap = []; // The ExternalModuleInfo for each file. + var deferredExports = []; // Exports to defer until an EndOfDeclarationMarker is found. + var exportFunctionsMap = []; // The export function associated with a source file. + var noSubstitutionMap = []; // Set of nodes for which substitution rules should be ignored for each file. + var currentSourceFile; // The current file. + var moduleInfo; // ExternalModuleInfo for the current file. + var exportFunction; // The export function for the current file. + var contextObject; // The context object for the current file. var hoistedStatements; var enclosingBlockScopedContainer; - var noSubstitution; + var noSubstitution; // Set of nodes for which substitution rules should be ignored. return ts.chainBundle(transformSourceFile); + /** + * Transforms the module aspects of a SourceFile. + * + * @param node The SourceFile node. + */ function transformSourceFile(node) { - if (node.isDeclarationFile || !(ts.isEffectiveExternalModule(node, compilerOptions) || node.transformFlags & 67108864)) { + if (node.isDeclarationFile || !(ts.isEffectiveExternalModule(node, compilerOptions) || node.transformFlags & 67108864 /* ContainsDynamicImport */)) { return node; } var id = ts.getOriginalNodeId(node); currentSourceFile = node; enclosingBlockScopedContainer = node; + // System modules have the following shape: + // + // System.register(['dep-1', ... 'dep-n'], function(exports) {/* module body function */}) + // + // The parameter 'exports' here is a callback '(name: string, value: T) => T' that + // is used to publish exported values. 'exports' returns its 'value' argument so in + // most cases expressions that mutate exported values can be rewritten as: + // + // expr -> exports('name', expr) + // + // The only exception in this rule is postfix unary operators, + // see comment to 'substitutePostfixUnaryExpression' for more details + // Collect information about the external module and dependency groups. moduleInfo = moduleInfoMap[id] = ts.collectExternalModuleInfo(node, resolver, compilerOptions); + // Make sure that the name of the 'exports' function does not conflict with + // existing identifiers. exportFunction = ts.createUniqueName("exports"); exportFunctionsMap[id] = exportFunction; contextObject = ts.createUniqueName("context"); + // Add the body of the module. var dependencyGroups = collectDependencyGroups(moduleInfo.externalImports); var moduleBodyBlock = createSystemModuleBody(node, dependencyGroups); - var moduleBodyFunction = ts.createFunctionExpression(undefined, undefined, undefined, undefined, [ - ts.createParameter(undefined, undefined, undefined, exportFunction), - ts.createParameter(undefined, undefined, undefined, contextObject) - ], undefined, moduleBodyBlock); + var moduleBodyFunction = ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ + ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, exportFunction), + ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, contextObject) + ], + /*type*/ undefined, moduleBodyBlock); + // Write the call to `System.register` + // Clear the emit-helpers flag for later passes since we'll have already used it in the module body + // So the helper will be emit at the correct position instead of at the top of the source-file var moduleName = ts.tryGetModuleNameFromFile(node, host, compilerOptions); var dependencies = ts.createArrayLiteral(ts.map(dependencyGroups, function (dependencyGroup) { return dependencyGroup.name; })); var updated = ts.setEmitFlags(ts.updateSourceFileNode(node, ts.setTextRange(ts.createNodeArray([ - ts.createStatement(ts.createCall(ts.createPropertyAccess(ts.createIdentifier("System"), "register"), undefined, moduleName + ts.createStatement(ts.createCall(ts.createPropertyAccess(ts.createIdentifier("System"), "register"), + /*typeArguments*/ undefined, moduleName ? [moduleName, dependencies, moduleBodyFunction] : [dependencies, moduleBodyFunction])) - ]), node.statements)), 1024); + ]), node.statements)), 1024 /* NoTrailingComments */); if (!(compilerOptions.outFile || compilerOptions.out)) { ts.moveEmitHelpers(updated, moduleBodyBlock, function (helper) { return !helper.scoped; }); } @@ -60742,6 +73340,11 @@ var ts; enclosingBlockScopedContainer = undefined; return ts.aggregateTransformFlags(updated); } + /** + * Collects the dependency groups for this files imports. + * + * @param externalImports The imports for the file. + */ function collectDependencyGroups(externalImports) { var groupIndices = ts.createMap(); var dependencyGroups = []; @@ -60752,6 +73355,7 @@ var ts; var text = externalModuleName.text; var groupIndex = groupIndices.get(text); if (groupIndex !== undefined) { + // deduplicate/group entries in dependency list by the dependency name dependencyGroups[groupIndex].externalImports.push(externalImport); } else { @@ -60765,42 +73369,124 @@ var ts; } return dependencyGroups; } + /** + * Adds the statements for the module body function for the source file. + * + * @param node The source file for the module. + * @param dependencyGroups The grouped dependencies of the module. + */ function createSystemModuleBody(node, dependencyGroups) { + // Shape of the body in system modules: + // + // function (exports) { + // + // + // + // return { + // setters: [ + // + // ], + // execute: function() { + // + // } + // } + // + // } + // + // i.e: + // + // import {x} from 'file1' + // var y = 1; + // export function foo() { return y + x(); } + // console.log(y); + // + // Will be transformed to: + // + // function(exports) { + // function foo() { return y + file_1.x(); } + // exports("foo", foo); + // var file_1, y; + // return { + // setters: [ + // function(v) { file_1 = v } + // ], + // execute(): function() { + // y = 1; + // console.log(y); + // } + // }; + // } var statements = []; + // We start a new lexical environment in this function body, but *not* in the + // body of the execute function. This allows us to emit temporary declarations + // only in the outer module body and not in the inner one. startLexicalEnvironment(); + // Add any prologue directives. var ensureUseStrict = ts.getStrictOptionValue(compilerOptions, "alwaysStrict") || (!compilerOptions.noImplicitUseStrict && ts.isExternalModule(currentSourceFile)); var statementOffset = ts.addPrologue(statements, node.statements, ensureUseStrict, sourceElementVisitor); - statements.push(ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.createVariableDeclaration("__moduleName", undefined, ts.createLogicalAnd(contextObject, ts.createPropertyAccess(contextObject, "id"))) + // var __moduleName = context_1 && context_1.id; + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration("__moduleName", + /*type*/ undefined, ts.createLogicalAnd(contextObject, ts.createPropertyAccess(contextObject, "id"))) ]))); + // Visit the synthetic external helpers import declaration if present ts.visitNode(moduleInfo.externalHelpersImportDeclaration, sourceElementVisitor, ts.isStatement); + // Visit the statements of the source file, emitting any transformations into + // the `executeStatements` array. We do this *before* we fill the `setters` array + // as we both emit transformations as well as aggregate some data used when creating + // setters. This allows us to reduce the number of times we need to loop through the + // statements of the source file. var executeStatements = ts.visitNodes(node.statements, sourceElementVisitor, ts.isStatement, statementOffset); + // Emit early exports for function declarations. ts.addRange(statements, hoistedStatements); + // We emit hoisted variables early to align roughly with our previous emit output. + // Two key differences in this approach are: + // - Temporary variables will appear at the top rather than at the bottom of the file ts.prependStatements(statements, endLexicalEnvironment()); - var exportStarFunction = addExportStarIfNeeded(statements); + var exportStarFunction = addExportStarIfNeeded(statements); // TODO: GH#18217 var moduleObject = ts.createObjectLiteral([ ts.createPropertyAssignment("setters", createSettersArray(exportStarFunction, dependencyGroups)), - ts.createPropertyAssignment("execute", ts.createFunctionExpression(undefined, undefined, undefined, undefined, [], undefined, ts.createBlock(executeStatements, true))) + ts.createPropertyAssignment("execute", ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ [], + /*type*/ undefined, ts.createBlock(executeStatements, /*multiLine*/ true))) ]); moduleObject.multiLine = true; statements.push(ts.createReturn(moduleObject)); - return ts.createBlock(statements, true); + return ts.createBlock(statements, /*multiLine*/ true); } + /** + * Adds an exportStar function to a statement list if it is needed for the file. + * + * @param statements A statement list. + */ function addExportStarIfNeeded(statements) { if (!moduleInfo.hasExportStarsToExportValues) { return; } + // 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. + // this set is used to filter names brought by star expors. + // local names set should only be added if we have anything exported if (!moduleInfo.exportedNames && moduleInfo.exportSpecifiers.size === 0) { + // no exported declarations (export var ...) or export specifiers (export {x}) + // check if we have any non star export declarations. var hasExportDeclarationWithExportClause = false; for (var _i = 0, _a = moduleInfo.externalImports; _i < _a.length; _i++) { var externalImport = _a[_i]; - if (externalImport.kind === 250 && externalImport.exportClause) { + if (externalImport.kind === 250 /* ExportDeclaration */ && externalImport.exportClause) { hasExportDeclarationWithExportClause = true; break; } } if (!hasExportDeclarationWithExportClause) { - var exportStarFunction_1 = createExportStarFunction(undefined); + // we still need to emit exportStar helper + var exportStarFunction_1 = createExportStarFunction(/*localNames*/ undefined); statements.push(exportStarFunction_1); return exportStarFunction_1.name; } @@ -60812,30 +73498,42 @@ var ts; if (exportedLocalName.escapedText === "default") { continue; } + // write name of exported declaration, i.e 'export var x...' exportedNames.push(ts.createPropertyAssignment(ts.createLiteral(exportedLocalName), ts.createTrue())); } } for (var _d = 0, _e = moduleInfo.externalImports; _d < _e.length; _d++) { var externalImport = _e[_d]; - if (externalImport.kind !== 250) { + if (externalImport.kind !== 250 /* ExportDeclaration */) { continue; } if (!externalImport.exportClause) { + // export * from ... continue; } for (var _f = 0, _g = externalImport.exportClause.elements; _f < _g.length; _f++) { var element = _g[_f]; + // write name of indirectly exported entry, i.e. 'export {x} from ...' exportedNames.push(ts.createPropertyAssignment(ts.createLiteral(ts.idText(element.name || element.propertyName)), ts.createTrue())); } } var exportedNamesStorageRef = ts.createUniqueName("exportedNames"); - statements.push(ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.createVariableDeclaration(exportedNamesStorageRef, undefined, ts.createObjectLiteral(exportedNames, true)) + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(exportedNamesStorageRef, + /*type*/ undefined, ts.createObjectLiteral(exportedNames, /*multiline*/ true)) ]))); var exportStarFunction = createExportStarFunction(exportedNamesStorageRef); statements.push(exportStarFunction); return exportStarFunction.name; } + /** + * Creates an exportStar function for the file, with an optional set of excluded local + * names. + * + * @param localNames An optional reference to an object containing a set of excluded local + * names. + */ function createExportStarFunction(localNames) { var exportStarFunction = ts.createUniqueName("exportStar"); var m = ts.createIdentifier("m"); @@ -60843,79 +73541,135 @@ var ts; var exports = ts.createIdentifier("exports"); var condition = ts.createStrictInequality(n, ts.createLiteral("default")); if (localNames) { - condition = ts.createLogicalAnd(condition, ts.createLogicalNot(ts.createCall(ts.createPropertyAccess(localNames, "hasOwnProperty"), undefined, [n]))); + condition = ts.createLogicalAnd(condition, ts.createLogicalNot(ts.createCall(ts.createPropertyAccess(localNames, "hasOwnProperty"), + /*typeArguments*/ undefined, [n]))); } - return ts.createFunctionDeclaration(undefined, undefined, undefined, exportStarFunction, undefined, [ts.createParameter(undefined, undefined, undefined, m)], undefined, ts.createBlock([ - ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.createVariableDeclaration(exports, undefined, ts.createObjectLiteral([])) + return ts.createFunctionDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, exportStarFunction, + /*typeParameters*/ undefined, [ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, m)], + /*type*/ undefined, ts.createBlock([ + ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(exports, + /*type*/ undefined, ts.createObjectLiteral([])) ])), ts.createForIn(ts.createVariableDeclarationList([ - ts.createVariableDeclaration(n, undefined) + ts.createVariableDeclaration(n, /*type*/ undefined) ]), m, ts.createBlock([ - ts.setEmitFlags(ts.createIf(condition, ts.createStatement(ts.createAssignment(ts.createElementAccess(exports, n), ts.createElementAccess(m, n)))), 1) + ts.setEmitFlags(ts.createIf(condition, ts.createStatement(ts.createAssignment(ts.createElementAccess(exports, n), ts.createElementAccess(m, n)))), 1 /* SingleLine */) ])), - ts.createStatement(ts.createCall(exportFunction, undefined, [exports])) - ], true)); + ts.createStatement(ts.createCall(exportFunction, + /*typeArguments*/ undefined, [exports])) + ], /*multiline*/ true)); } + /** + * Creates an array setter callbacks for each dependency group. + * + * @param exportStarFunction A reference to an exportStarFunction for the file. + * @param dependencyGroups An array of grouped dependencies. + */ function createSettersArray(exportStarFunction, dependencyGroups) { var setters = []; for (var _i = 0, dependencyGroups_1 = dependencyGroups; _i < dependencyGroups_1.length; _i++) { var group_1 = dependencyGroups_1[_i]; + // derive a unique name for parameter from the first named entry in the group var localName = ts.forEach(group_1.externalImports, function (i) { return ts.getLocalNameForExternalImport(i, currentSourceFile); }); var parameterName = localName ? ts.getGeneratedNameForNode(localName) : ts.createUniqueName(""); var statements = []; for (var _a = 0, _b = group_1.externalImports; _a < _b.length; _a++) { var entry = _b[_a]; - var importVariableName = ts.getLocalNameForExternalImport(entry, currentSourceFile); + var importVariableName = ts.getLocalNameForExternalImport(entry, currentSourceFile); // TODO: GH#18217 switch (entry.kind) { - case 244: + case 244 /* ImportDeclaration */: if (!entry.importClause) { + // 'import "..."' case + // module is imported only for side-effects, no emit required break; } - case 243: + // falls through + case 243 /* ImportEqualsDeclaration */: ts.Debug.assert(importVariableName !== undefined); + // save import into the local statements.push(ts.createStatement(ts.createAssignment(importVariableName, parameterName))); break; - case 250: + case 250 /* ExportDeclaration */: ts.Debug.assert(importVariableName !== undefined); if (entry.exportClause) { + // export {a, b as c} from 'foo' + // + // emit as: + // + // exports_({ + // "a": _["a"], + // "c": _["b"] + // }); var properties = []; for (var _c = 0, _d = entry.exportClause.elements; _c < _d.length; _c++) { var e = _d[_c]; properties.push(ts.createPropertyAssignment(ts.createLiteral(ts.idText(e.name)), ts.createElementAccess(parameterName, ts.createLiteral(ts.idText(e.propertyName || e.name))))); } - statements.push(ts.createStatement(ts.createCall(exportFunction, undefined, [ts.createObjectLiteral(properties, true)]))); + statements.push(ts.createStatement(ts.createCall(exportFunction, + /*typeArguments*/ undefined, [ts.createObjectLiteral(properties, /*multiline*/ true)]))); } else { - statements.push(ts.createStatement(ts.createCall(exportStarFunction, undefined, [parameterName]))); + // export * from 'foo' + // + // emit as: + // + // exportStar(foo_1_1); + statements.push(ts.createStatement(ts.createCall(exportStarFunction, + /*typeArguments*/ undefined, [parameterName]))); } break; } } - setters.push(ts.createFunctionExpression(undefined, undefined, undefined, undefined, [ts.createParameter(undefined, undefined, undefined, parameterName)], undefined, ts.createBlock(statements, true))); + setters.push(ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)], + /*type*/ undefined, ts.createBlock(statements, /*multiLine*/ true))); } - return ts.createArrayLiteral(setters, true); + return ts.createArrayLiteral(setters, /*multiLine*/ true); } + // + // Top-level Source Element Visitors + // + /** + * Visit source elements at the top-level of a module. + * + * @param node The node to visit. + */ function sourceElementVisitor(node) { switch (node.kind) { - case 244: + case 244 /* ImportDeclaration */: return visitImportDeclaration(node); - case 243: + case 243 /* ImportEqualsDeclaration */: return visitImportEqualsDeclaration(node); - case 250: + case 250 /* ExportDeclaration */: + // ExportDeclarations are elided as they are handled via + // `appendExportsOfDeclaration`. return undefined; - case 249: + case 249 /* ExportAssignment */: return visitExportAssignment(node); default: return nestedElementVisitor(node); } } + /** + * Visits an ImportDeclaration node. + * + * @param node The node to visit. + */ function visitImportDeclaration(node) { var statements; if (node.importClause) { - hoistVariableDeclaration(ts.getLocalNameForExternalImport(node, currentSourceFile)); + hoistVariableDeclaration(ts.getLocalNameForExternalImport(node, currentSourceFile)); // TODO: GH#18217 } if (hasAssociatedEndOfDeclarationMarker(node)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfImportDeclaration(deferredExports[id], node); } @@ -60924,11 +73678,17 @@ var ts; } return ts.singleOrMany(statements); } + /** + * Visits an ImportEqualsDeclaration node. + * + * @param node The node to visit. + */ function visitImportEqualsDeclaration(node) { ts.Debug.assert(ts.isExternalModuleImportEqualsDeclaration(node), "import= for internal module references should be handled in an earlier transformer."); var statements; - hoistVariableDeclaration(ts.getLocalNameForExternalImport(node, currentSourceFile)); + hoistVariableDeclaration(ts.getLocalNameForExternalImport(node, currentSourceFile)); // TODO: GH#18217 if (hasAssociatedEndOfDeclarationMarker(node)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfImportEqualsDeclaration(deferredExports[id], node); } @@ -60937,28 +73697,43 @@ var ts; } return ts.singleOrMany(statements); } + /** + * Visits an ExportAssignment node. + * + * @param node The node to visit. + */ function visitExportAssignment(node) { if (node.isExportEquals) { + // Elide `export=` as it is illegal in a SystemJS module. return undefined; } var expression = ts.visitNode(node.expression, destructuringAndImportCallVisitor, ts.isExpression); var original = node.original; if (original && hasAssociatedEndOfDeclarationMarker(original)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); - deferredExports[id] = appendExportStatement(deferredExports[id], ts.createIdentifier("default"), expression, true); + deferredExports[id] = appendExportStatement(deferredExports[id], ts.createIdentifier("default"), expression, /*allowComments*/ true); } else { - return createExportStatement(ts.createIdentifier("default"), expression, true); + return createExportStatement(ts.createIdentifier("default"), expression, /*allowComments*/ true); } } + /** + * Visits a FunctionDeclaration, hoisting it to the outer module body function. + * + * @param node The node to visit. + */ function visitFunctionDeclaration(node) { - if (ts.hasModifier(node, 1)) { - hoistedStatements = ts.append(hoistedStatements, ts.updateFunctionDeclaration(node, node.decorators, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), node.asteriskToken, ts.getDeclarationName(node, true, true), undefined, ts.visitNodes(node.parameters, destructuringAndImportCallVisitor, ts.isParameterDeclaration), undefined, ts.visitNode(node.body, destructuringAndImportCallVisitor, ts.isBlock))); + if (ts.hasModifier(node, 1 /* Export */)) { + hoistedStatements = ts.append(hoistedStatements, ts.updateFunctionDeclaration(node, node.decorators, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), node.asteriskToken, ts.getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true), + /*typeParameters*/ undefined, ts.visitNodes(node.parameters, destructuringAndImportCallVisitor, ts.isParameterDeclaration), + /*type*/ undefined, ts.visitNode(node.body, destructuringAndImportCallVisitor, ts.isBlock))); } else { hoistedStatements = ts.append(hoistedStatements, ts.visitEachChild(node, destructuringAndImportCallVisitor, context)); } if (hasAssociatedEndOfDeclarationMarker(node)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfHoistedDeclaration(deferredExports[id], node); } @@ -60967,12 +73742,22 @@ var ts; } return undefined; } + /** + * Visits a ClassDeclaration, hoisting its name to the outer module body function. + * + * @param node The node to visit. + */ function visitClassDeclaration(node) { var statements; + // Hoist the name of the class declaration to the outer module body function. var name = ts.getLocalName(node); hoistVariableDeclaration(name); - statements = ts.append(statements, ts.setTextRange(ts.createStatement(ts.createAssignment(name, ts.setTextRange(ts.createClassExpression(undefined, node.name, undefined, ts.visitNodes(node.heritageClauses, destructuringAndImportCallVisitor, ts.isHeritageClause), ts.visitNodes(node.members, destructuringAndImportCallVisitor, ts.isClassElement)), node))), node)); + // Rewrite the class declaration into an assignment of a class expression. + statements = ts.append(statements, ts.setTextRange(ts.createStatement(ts.createAssignment(name, ts.setTextRange(ts.createClassExpression( + /*modifiers*/ undefined, node.name, + /*typeParameters*/ undefined, ts.visitNodes(node.heritageClauses, destructuringAndImportCallVisitor, ts.isHeritageClause), ts.visitNodes(node.members, destructuringAndImportCallVisitor, ts.isClassElement)), node))), node)); if (hasAssociatedEndOfDeclarationMarker(node)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfHoistedDeclaration(deferredExports[id], node); } @@ -60981,12 +73766,18 @@ var ts; } return ts.singleOrMany(statements); } + /** + * Visits a variable statement, hoisting declared names to the top-level module body. + * Each declaration is rewritten into an assignment expression. + * + * @param node The node to visit. + */ function visitVariableStatement(node) { if (!shouldHoistVariableDeclarationList(node.declarationList)) { return ts.visitNode(node, destructuringAndImportCallVisitor, ts.isStatement); } var expressions; - var isExportedDeclaration = ts.hasModifier(node, 1); + var isExportedDeclaration = ts.hasModifier(node, 1 /* Export */); var isMarkedDeclaration = hasAssociatedEndOfDeclarationMarker(node); for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) { var variable = _a[_i]; @@ -61002,14 +73793,20 @@ var ts; statements = ts.append(statements, ts.setTextRange(ts.createStatement(ts.inlineExpressions(expressions)), node)); } if (isMarkedDeclaration) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfVariableStatement(deferredExports[id], node, isExportedDeclaration); } else { - statements = appendExportsOfVariableStatement(statements, node, false); + statements = appendExportsOfVariableStatement(statements, node, /*exportSelf*/ false); } return ts.singleOrMany(statements); } + /** + * Hoists the declared names of a VariableDeclaration or BindingElement. + * + * @param node The declaration to hoist. + */ function hoistBindingElement(node) { if (ts.isBindingPattern(node.name)) { for (var _i = 0, _a = node.name.elements; _i < _a.length; _i++) { @@ -61023,41 +73820,103 @@ var ts; hoistVariableDeclaration(ts.getSynthesizedClone(node.name)); } } + /** + * Determines whether a VariableDeclarationList should be hoisted. + * + * @param node The node to test. + */ function shouldHoistVariableDeclarationList(node) { - return (ts.getEmitFlags(node) & 2097152) === 0 - && (enclosingBlockScopedContainer.kind === 274 - || (ts.getOriginalNode(node).flags & 3) === 0); + // hoist only non-block scoped declarations or block scoped declarations parented by source file + return (ts.getEmitFlags(node) & 2097152 /* NoHoisting */) === 0 + && (enclosingBlockScopedContainer.kind === 274 /* SourceFile */ + || (ts.getOriginalNode(node).flags & 3 /* BlockScoped */) === 0); } + /** + * Transform an initialized variable declaration into an expression. + * + * @param node The node to transform. + * @param isExportedDeclaration A value indicating whether the variable is exported. + */ function transformInitializedVariable(node, isExportedDeclaration) { var createAssignment = isExportedDeclaration ? createExportedVariableAssignment : createNonExportedVariableAssignment; return ts.isBindingPattern(node.name) - ? ts.flattenDestructuringAssignment(node, destructuringAndImportCallVisitor, context, 0, false, createAssignment) + ? ts.flattenDestructuringAssignment(node, destructuringAndImportCallVisitor, context, 0 /* All */, + /*needsValue*/ false, createAssignment) : node.initializer ? createAssignment(node.name, ts.visitNode(node.initializer, destructuringAndImportCallVisitor, ts.isExpression)) : node.name; } + /** + * Creates an assignment expression for an exported variable declaration. + * + * @param name The name of the variable. + * @param value The value of the variable's initializer. + * @param location The source map location for the assignment. + */ function createExportedVariableAssignment(name, value, location) { - return createVariableAssignment(name, value, location, true); + return createVariableAssignment(name, value, location, /*isExportedDeclaration*/ true); } + /** + * Creates an assignment expression for a non-exported variable declaration. + * + * @param name The name of the variable. + * @param value The value of the variable's initializer. + * @param location The source map location for the assignment. + */ function createNonExportedVariableAssignment(name, value, location) { - return createVariableAssignment(name, value, location, false); + return createVariableAssignment(name, value, location, /*isExportedDeclaration*/ false); } + /** + * Creates an assignment expression for a variable declaration. + * + * @param name The name of the variable. + * @param value The value of the variable's initializer. + * @param location The source map location for the assignment. + * @param isExportedDeclaration A value indicating whether the variable is exported. + */ function createVariableAssignment(name, value, location, isExportedDeclaration) { hoistVariableDeclaration(ts.getSynthesizedClone(name)); return isExportedDeclaration ? createExportExpression(name, preventSubstitution(ts.setTextRange(ts.createAssignment(name, value), location))) : preventSubstitution(ts.setTextRange(ts.createAssignment(name, value), location)); } + /** + * Visits a MergeDeclarationMarker used as a placeholder for the beginning of a merged + * and transformed declaration. + * + * @param node The node to visit. + */ function visitMergeDeclarationMarker(node) { - if (hasAssociatedEndOfDeclarationMarker(node) && node.original.kind === 214) { + // For an EnumDeclaration or ModuleDeclaration that merges with a preceeding + // declaration we do not emit a leading variable declaration. To preserve the + // begin/end semantics of the declararation and to properly handle exports + // we wrapped the leading variable declaration in a `MergeDeclarationMarker`. + // + // To balance the declaration, we defer the exports of the elided variable + // statement until we visit this declaration's `EndOfDeclarationMarker`. + if (hasAssociatedEndOfDeclarationMarker(node) && node.original.kind === 214 /* VariableStatement */) { var id = ts.getOriginalNodeId(node); - var isExportedDeclaration = ts.hasModifier(node.original, 1); + var isExportedDeclaration = ts.hasModifier(node.original, 1 /* Export */); deferredExports[id] = appendExportsOfVariableStatement(deferredExports[id], node.original, isExportedDeclaration); } return node; } + /** + * Determines whether a node has an associated EndOfDeclarationMarker. + * + * @param node The node to test. + */ function hasAssociatedEndOfDeclarationMarker(node) { - return (ts.getEmitFlags(node) & 4194304) !== 0; + return (ts.getEmitFlags(node) & 4194304 /* HasEndOfDeclarationMarker */) !== 0; } + /** + * Visits a DeclarationMarker used as a placeholder for the end of a transformed + * declaration. + * + * @param node The node to visit. + */ function visitEndOfDeclarationMarker(node) { + // For some transformations we emit an `EndOfDeclarationMarker` to mark the actual + // end of the transformed declaration. We use this marker to emit any deferred exports + // of the declaration. var id = ts.getOriginalNodeId(node); var statements = deferredExports[id]; if (statements) { @@ -61072,6 +73931,15 @@ var ts; } return node; } + /** + * Appends the exports of an ImportDeclaration to a statement list, returning the + * statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param decl The declaration whose exports are to be recorded. + */ function appendExportsOfImportDeclaration(statements, decl) { if (moduleInfo.exportEquals) { return statements; @@ -61086,10 +73954,10 @@ var ts; var namedBindings = importClause.namedBindings; if (namedBindings) { switch (namedBindings.kind) { - case 246: + case 246 /* NamespaceImport */: statements = appendExportsOfDeclaration(statements, namedBindings); break; - case 247: + case 247 /* NamedImports */: for (var _i = 0, _a = namedBindings.elements; _i < _a.length; _i++) { var importBinding = _a[_i]; statements = appendExportsOfDeclaration(statements, importBinding); @@ -61099,12 +73967,32 @@ var ts; } return statements; } + /** + * Appends the export of an ImportEqualsDeclaration to a statement list, returning the + * statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param decl The declaration whose exports are to be recorded. + */ function appendExportsOfImportEqualsDeclaration(statements, decl) { if (moduleInfo.exportEquals) { return statements; } return appendExportsOfDeclaration(statements, decl); } + /** + * Appends the exports of a VariableStatement to a statement list, returning the statement + * list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param node The VariableStatement whose exports are to be recorded. + * @param exportSelf A value indicating whether to also export each VariableDeclaration of + * `nodes` declaration list. + */ function appendExportsOfVariableStatement(statements, node, exportSelf) { if (moduleInfo.exportEquals) { return statements; @@ -61117,6 +74005,16 @@ var ts; } return statements; } + /** + * Appends the exports of a VariableDeclaration or BindingElement to a statement list, + * returning the statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param decl The declaration whose exports are to be recorded. + * @param exportSelf A value indicating whether to also export the declaration itself. + */ function appendExportsOfBindingElement(statements, decl, exportSelf) { if (moduleInfo.exportEquals) { return statements; @@ -61139,13 +74037,22 @@ var ts; } return statements; } + /** + * Appends the exports of a ClassDeclaration or FunctionDeclaration to a statement list, + * returning the statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param decl The declaration whose exports are to be recorded. + */ function appendExportsOfHoistedDeclaration(statements, decl) { if (moduleInfo.exportEquals) { return statements; } var excludeName; - if (ts.hasModifier(decl, 1)) { - var exportName = ts.hasModifier(decl, 512) ? ts.createLiteral("default") : decl.name; + if (ts.hasModifier(decl, 1 /* Export */)) { + var exportName = ts.hasModifier(decl, 512 /* Default */) ? ts.createLiteral("default") : decl.name; statements = appendExportStatement(statements, exportName, ts.getLocalName(decl)); excludeName = ts.getTextOfIdentifierOrLiteral(exportName); } @@ -61154,6 +74061,15 @@ var ts; } return statements; } + /** + * Appends the exports of a declaration to a statement list, returning the statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param decl The declaration to export. + * @param excludeName An optional name to exclude from exports. + */ function appendExportsOfDeclaration(statements, decl, excludeName) { if (moduleInfo.exportEquals) { return statements; @@ -61170,67 +74086,104 @@ var ts; } return statements; } + /** + * Appends the down-level representation of an export to a statement list, returning the + * statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param exportName The name of the export. + * @param expression The expression to export. + * @param allowComments Whether to allow comments on the export. + */ function appendExportStatement(statements, exportName, expression, allowComments) { statements = ts.append(statements, createExportStatement(exportName, expression, allowComments)); return statements; } + /** + * Creates a call to the current file's export function to export a value. + * + * @param name The bound name of the export. + * @param value The exported value. + * @param allowComments An optional value indicating whether to emit comments for the statement. + */ function createExportStatement(name, value, allowComments) { var statement = ts.createStatement(createExportExpression(name, value)); ts.startOnNewLine(statement); if (!allowComments) { - ts.setEmitFlags(statement, 1536); + ts.setEmitFlags(statement, 1536 /* NoComments */); } return statement; } + /** + * Creates a call to the current file's export function to export a value. + * + * @param name The bound name of the export. + * @param value The exported value. + */ function createExportExpression(name, value) { var exportName = ts.isIdentifier(name) ? ts.createLiteral(name) : name; - ts.setEmitFlags(value, ts.getEmitFlags(value) | 1536); - return ts.setCommentRange(ts.createCall(exportFunction, undefined, [exportName, value]), value); + ts.setEmitFlags(value, ts.getEmitFlags(value) | 1536 /* NoComments */); + return ts.setCommentRange(ts.createCall(exportFunction, /*typeArguments*/ undefined, [exportName, value]), value); } + // + // Top-Level or Nested Source Element Visitors + // + /** + * Visit nested elements at the top-level of a module. + * + * @param node The node to visit. + */ function nestedElementVisitor(node) { switch (node.kind) { - case 214: + case 214 /* VariableStatement */: return visitVariableStatement(node); - case 234: + case 234 /* FunctionDeclaration */: return visitFunctionDeclaration(node); - case 235: + case 235 /* ClassDeclaration */: return visitClassDeclaration(node); - case 220: + case 220 /* ForStatement */: return visitForStatement(node); - case 221: + case 221 /* ForInStatement */: return visitForInStatement(node); - case 222: + case 222 /* ForOfStatement */: return visitForOfStatement(node); - case 218: + case 218 /* DoStatement */: return visitDoStatement(node); - case 219: + case 219 /* WhileStatement */: return visitWhileStatement(node); - case 228: + case 228 /* LabeledStatement */: return visitLabeledStatement(node); - case 226: + case 226 /* WithStatement */: return visitWithStatement(node); - case 227: + case 227 /* SwitchStatement */: return visitSwitchStatement(node); - case 241: + case 241 /* CaseBlock */: return visitCaseBlock(node); - case 266: + case 266 /* CaseClause */: return visitCaseClause(node); - case 267: + case 267 /* DefaultClause */: return visitDefaultClause(node); - case 230: + case 230 /* TryStatement */: return visitTryStatement(node); - case 269: + case 269 /* CatchClause */: return visitCatchClause(node); - case 213: + case 213 /* Block */: return visitBlock(node); - case 304: + case 304 /* MergeDeclarationMarker */: return visitMergeDeclarationMarker(node); - case 305: + case 305 /* EndOfDeclarationMarker */: return visitEndOfDeclarationMarker(node); default: return destructuringAndImportCallVisitor(node); } } + /** + * Visits the body of a ForStatement to hoist declarations. + * + * @param node The node to visit. + */ function visitForStatement(node) { var savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer; enclosingBlockScopedContainer = node; @@ -61238,6 +74191,11 @@ var ts; enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer; return node; } + /** + * Visits the body of a ForInStatement to hoist declarations. + * + * @param node The node to visit. + */ function visitForInStatement(node) { var savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer; enclosingBlockScopedContainer = node; @@ -61245,6 +74203,11 @@ var ts; enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer; return node; } + /** + * Visits the body of a ForOfStatement to hoist declarations. + * + * @param node The node to visit. + */ function visitForOfStatement(node) { var savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer; enclosingBlockScopedContainer = node; @@ -61252,16 +74215,27 @@ var ts; enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer; return node; } + /** + * Determines whether to hoist the initializer of a ForStatement, ForInStatement, or + * ForOfStatement. + * + * @param node The node to test. + */ function shouldHoistForInitializer(node) { return ts.isVariableDeclarationList(node) && shouldHoistVariableDeclarationList(node); } + /** + * Visits the initializer of a ForStatement, ForInStatement, or ForOfStatement + * + * @param node The node to visit. + */ function visitForInitializer(node) { if (shouldHoistForInitializer(node)) { var expressions = void 0; for (var _i = 0, _a = node.declarations; _i < _a.length; _i++) { var variable = _a[_i]; - expressions = ts.append(expressions, transformInitializedVariable(variable, false)); + expressions = ts.append(expressions, transformInitializedVariable(variable, /*isExportedDeclaration*/ false)); if (!variable.initializer) { hoistBindingElement(variable); } @@ -61272,21 +74246,51 @@ var ts; return ts.visitEachChild(node, nestedElementVisitor, context); } } + /** + * Visits the body of a DoStatement to hoist declarations. + * + * @param node The node to visit. + */ function visitDoStatement(node) { return ts.updateDo(node, ts.visitNode(node.statement, nestedElementVisitor, ts.isStatement, ts.liftToBlock), ts.visitNode(node.expression, destructuringAndImportCallVisitor, ts.isExpression)); } + /** + * Visits the body of a WhileStatement to hoist declarations. + * + * @param node The node to visit. + */ function visitWhileStatement(node) { return ts.updateWhile(node, ts.visitNode(node.expression, destructuringAndImportCallVisitor, ts.isExpression), ts.visitNode(node.statement, nestedElementVisitor, ts.isStatement, ts.liftToBlock)); } + /** + * Visits the body of a LabeledStatement to hoist declarations. + * + * @param node The node to visit. + */ function visitLabeledStatement(node) { return ts.updateLabel(node, node.label, ts.visitNode(node.statement, nestedElementVisitor, ts.isStatement, ts.liftToBlock)); } + /** + * Visits the body of a WithStatement to hoist declarations. + * + * @param node The node to visit. + */ function visitWithStatement(node) { return ts.updateWith(node, ts.visitNode(node.expression, destructuringAndImportCallVisitor, ts.isExpression), ts.visitNode(node.statement, nestedElementVisitor, ts.isStatement, ts.liftToBlock)); } + /** + * Visits the body of a SwitchStatement to hoist declarations. + * + * @param node The node to visit. + */ function visitSwitchStatement(node) { return ts.updateSwitch(node, ts.visitNode(node.expression, destructuringAndImportCallVisitor, ts.isExpression), ts.visitNode(node.caseBlock, nestedElementVisitor, ts.isCaseBlock)); } + /** + * Visits the body of a CaseBlock to hoist declarations. + * + * @param node The node to visit. + */ function visitCaseBlock(node) { var savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer; enclosingBlockScopedContainer = node; @@ -61294,15 +74298,35 @@ var ts; enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer; return node; } + /** + * Visits the body of a CaseClause to hoist declarations. + * + * @param node The node to visit. + */ function visitCaseClause(node) { return ts.updateCaseClause(node, ts.visitNode(node.expression, destructuringAndImportCallVisitor, ts.isExpression), ts.visitNodes(node.statements, nestedElementVisitor, ts.isStatement)); } + /** + * Visits the body of a DefaultClause to hoist declarations. + * + * @param node The node to visit. + */ function visitDefaultClause(node) { return ts.visitEachChild(node, nestedElementVisitor, context); } + /** + * Visits the body of a TryStatement to hoist declarations. + * + * @param node The node to visit. + */ function visitTryStatement(node) { return ts.visitEachChild(node, nestedElementVisitor, context); } + /** + * Visits the body of a CatchClause to hoist declarations. + * + * @param node The node to visit. + */ function visitCatchClause(node) { var savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer; enclosingBlockScopedContainer = node; @@ -61310,6 +74334,11 @@ var ts; enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer; return node; } + /** + * Visits the body of a Block to hoist declarations. + * + * @param node The node to visit. + */ function visitBlock(node) { var savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer; enclosingBlockScopedContainer = node; @@ -61317,15 +74346,23 @@ var ts; enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer; return node; } + // + // Destructuring Assignment Visitors + // + /** + * Visit nodes to flatten destructuring assignments to exported symbols. + * + * @param node The node to visit. + */ function destructuringAndImportCallVisitor(node) { - if (node.transformFlags & 1024 - && node.kind === 200) { + if (node.transformFlags & 1024 /* DestructuringAssignment */ + && node.kind === 200 /* BinaryExpression */) { return visitDestructuringAssignment(node); } else if (ts.isImportCall(node)) { return visitImportCallExpression(node); } - else if ((node.transformFlags & 2048) || (node.transformFlags & 67108864)) { + else if ((node.transformFlags & 2048 /* ContainsDestructuringAssignment */) || (node.transformFlags & 67108864 /* ContainsDynamicImport */)) { return ts.visitEachChild(node, destructuringAndImportCallVisitor, context); } else { @@ -61333,16 +74370,38 @@ var ts; } } function visitImportCallExpression(node) { - return ts.createCall(ts.createPropertyAccess(contextObject, ts.createIdentifier("import")), undefined, ts.some(node.arguments) ? [ts.visitNode(node.arguments[0], destructuringAndImportCallVisitor)] : []); + // import("./blah") + // emit as + // System.register([], function (_export, _context) { + // return { + // setters: [], + // execute: () => { + // _context.import('./blah'); + // } + // }; + // }); + return ts.createCall(ts.createPropertyAccess(contextObject, ts.createIdentifier("import")), + /*typeArguments*/ undefined, ts.some(node.arguments) ? [ts.visitNode(node.arguments[0], destructuringAndImportCallVisitor)] : []); } + /** + * Visits a DestructuringAssignment to flatten destructuring to exported symbols. + * + * @param node The node to visit. + */ function visitDestructuringAssignment(node) { if (hasExportedReferenceInDestructuringTarget(node.left)) { - return ts.flattenDestructuringAssignment(node, destructuringAndImportCallVisitor, context, 0, true); + return ts.flattenDestructuringAssignment(node, destructuringAndImportCallVisitor, context, 0 /* All */, + /*needsValue*/ true); } return ts.visitEachChild(node, destructuringAndImportCallVisitor, context); } + /** + * Determines whether the target of a destructuring assigment refers to an exported symbol. + * + * @param node The destructuring target. + */ function hasExportedReferenceInDestructuringTarget(node) { - if (ts.isAssignmentExpression(node, true)) { + if (ts.isAssignmentExpression(node, /*excludeCompoundAssignment*/ true)) { return hasExportedReferenceInDestructuringTarget(node.left); } else if (ts.isSpreadElement(node)) { @@ -61362,22 +74421,40 @@ var ts; } else if (ts.isIdentifier(node)) { var container = resolver.getReferencedExportContainer(node); - return container !== undefined && container.kind === 274; + return container !== undefined && container.kind === 274 /* SourceFile */; } else { return false; } } + // + // Modifier Visitors + // + /** + * Visit nodes to elide module-specific modifiers. + * + * @param node The node to visit. + */ function modifierVisitor(node) { switch (node.kind) { - case 84: - case 79: + case 84 /* ExportKeyword */: + case 79 /* DefaultKeyword */: return undefined; } return node; } + // + // Emit Notification + // + /** + * Hook for node emit notifications. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emitCallback A callback used to emit the node in the printer. + */ function onEmitNode(hint, node, emitCallback) { - if (node.kind === 274) { + if (node.kind === 274 /* SourceFile */) { var id = ts.getOriginalNodeId(node); currentSourceFile = node; moduleInfo = moduleInfoMap[id]; @@ -61396,75 +74473,127 @@ var ts; previousOnEmitNode(hint, node, emitCallback); } } + // + // Substitutions + // + /** + * Hooks node substitutions. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to substitute. + */ function onSubstituteNode(hint, node) { node = previousOnSubstituteNode(hint, node); if (isSubstitutionPrevented(node)) { return node; } - if (hint === 1) { + if (hint === 1 /* Expression */) { return substituteExpression(node); } - else if (hint === 4) { + else if (hint === 4 /* Unspecified */) { return substituteUnspecified(node); } return node; } + /** + * Substitute the node, if necessary. + * + * @param node The node to substitute. + */ function substituteUnspecified(node) { switch (node.kind) { - case 271: + case 271 /* ShorthandPropertyAssignment */: return substituteShorthandPropertyAssignment(node); } return node; } + /** + * Substitution for a ShorthandPropertyAssignment whose name that may contain an imported or exported symbol. + * + * @param node The node to substitute. + */ function substituteShorthandPropertyAssignment(node) { var name = node.name; if (!ts.isGeneratedIdentifier(name) && !ts.isLocalName(name)) { var importDeclaration = resolver.getReferencedImportDeclaration(name); if (importDeclaration) { if (ts.isImportClause(importDeclaration)) { - return ts.setTextRange(ts.createPropertyAssignment(ts.getSynthesizedClone(name), ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent), ts.createIdentifier("default"))), node); + return ts.setTextRange(ts.createPropertyAssignment(ts.getSynthesizedClone(name), ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent), ts.createIdentifier("default"))), + /*location*/ node); } else if (ts.isImportSpecifier(importDeclaration)) { - return ts.setTextRange(ts.createPropertyAssignment(ts.getSynthesizedClone(name), ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent.parent.parent), ts.getSynthesizedClone(importDeclaration.propertyName || importDeclaration.name))), node); + return ts.setTextRange(ts.createPropertyAssignment(ts.getSynthesizedClone(name), ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent.parent.parent), ts.getSynthesizedClone(importDeclaration.propertyName || importDeclaration.name))), + /*location*/ node); } } } return node; } + /** + * Substitute the expression, if necessary. + * + * @param node The node to substitute. + */ function substituteExpression(node) { switch (node.kind) { - case 71: + case 71 /* Identifier */: return substituteExpressionIdentifier(node); - case 200: + case 200 /* BinaryExpression */: return substituteBinaryExpression(node); - case 198: - case 199: + case 198 /* PrefixUnaryExpression */: + case 199 /* PostfixUnaryExpression */: return substituteUnaryExpression(node); } return node; } + /** + * Substitution for an Identifier expression that may contain an imported or exported symbol. + * + * @param node The node to substitute. + */ function substituteExpressionIdentifier(node) { - if (ts.getEmitFlags(node) & 4096) { + if (ts.getEmitFlags(node) & 4096 /* HelperName */) { var externalHelpersModuleName = ts.getExternalHelpersModuleName(currentSourceFile); if (externalHelpersModuleName) { return ts.createPropertyAccess(externalHelpersModuleName, node); } return node; } + // When we see an identifier in an expression position that + // points to an imported symbol, we should substitute a qualified + // reference to the imported symbol if one is needed. + // + // - We do not substitute generated identifiers for any reason. + // - We do not substitute identifiers tagged with the LocalName flag. if (!ts.isGeneratedIdentifier(node) && !ts.isLocalName(node)) { var importDeclaration = resolver.getReferencedImportDeclaration(node); if (importDeclaration) { if (ts.isImportClause(importDeclaration)) { - return ts.setTextRange(ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent), ts.createIdentifier("default")), node); + return ts.setTextRange(ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent), ts.createIdentifier("default")), + /*location*/ node); } else if (ts.isImportSpecifier(importDeclaration)) { - return ts.setTextRange(ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent.parent.parent), ts.getSynthesizedClone(importDeclaration.propertyName || importDeclaration.name)), node); + return ts.setTextRange(ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent.parent.parent), ts.getSynthesizedClone(importDeclaration.propertyName || importDeclaration.name)), + /*location*/ node); } } } return node; } + /** + * Substitution for a BinaryExpression that may contain an imported or exported symbol. + * + * @param node The node to substitute. + */ function substituteBinaryExpression(node) { + // When we see an assignment expression whose left-hand side is an exported symbol, + // we should ensure all exports of that symbol are updated with the correct value. + // + // - We do not substitute generated identifiers for any reason. + // - We do not substitute identifiers tagged with the LocalName flag. + // - We do not substitute identifiers that were originally the name of an enum or + // namespace due to how they are transformed in TypeScript. + // - We only substitute identifiers that are exported at the top level. if (ts.isAssignmentOperator(node.operatorToken.kind) && ts.isIdentifier(node.left) && !ts.isGeneratedIdentifier(node.left) @@ -61472,6 +74601,7 @@ var ts; && !ts.isDeclarationNameOfEnumOrNamespace(node.left)) { var exportedNames = getExports(node.left); if (exportedNames) { + // For each additional export of the declaration, apply an export assignment. var expression = node; for (var _i = 0, exportedNames_4 = exportedNames; _i < exportedNames_4.length; _i++) { var exportName = exportedNames_4[_i]; @@ -61482,23 +74612,37 @@ var ts; } return node; } + /** + * Substitution for a UnaryExpression that may contain an imported or exported symbol. + * + * @param node The node to substitute. + */ function substituteUnaryExpression(node) { - if ((node.operator === 43 || node.operator === 44) + // When we see a prefix or postfix increment expression whose operand is an exported + // symbol, we should ensure all exports of that symbol are updated with the correct + // value. + // + // - We do not substitute generated identifiers for any reason. + // - We do not substitute identifiers tagged with the LocalName flag. + // - We do not substitute identifiers that were originally the name of an enum or + // namespace due to how they are transformed in TypeScript. + // - We only substitute identifiers that are exported at the top level. + if ((node.operator === 43 /* PlusPlusToken */ || node.operator === 44 /* MinusMinusToken */) && ts.isIdentifier(node.operand) && !ts.isGeneratedIdentifier(node.operand) && !ts.isLocalName(node.operand) && !ts.isDeclarationNameOfEnumOrNamespace(node.operand)) { var exportedNames = getExports(node.operand); if (exportedNames) { - var expression = node.kind === 199 + var expression = node.kind === 199 /* PostfixUnaryExpression */ ? ts.setTextRange(ts.createPrefix(node.operator, node.operand), node) : node; for (var _i = 0, exportedNames_5 = exportedNames; _i < exportedNames_5.length; _i++) { var exportName = exportedNames_5[_i]; expression = createExportExpression(exportName, preventSubstitution(expression)); } - if (node.kind === 199) { - expression = node.operator === 43 + if (node.kind === 199 /* PostfixUnaryExpression */) { + expression = node.operator === 43 /* PlusPlusToken */ ? ts.createSubtract(preventSubstitution(expression), ts.createLiteral(1)) : ts.createAdd(preventSubstitution(expression), ts.createLiteral(1)); } @@ -61507,14 +74651,19 @@ var ts; } return node; } + /** + * Gets the exports of a name. + * + * @param name The name. + */ function getExports(name) { var exportedNames; if (!ts.isGeneratedIdentifier(name)) { var valueDeclaration = resolver.getReferencedImportDeclaration(name) || resolver.getReferencedValueDeclaration(name); if (valueDeclaration) { - var exportContainer = resolver.getReferencedExportContainer(name, false); - if (exportContainer && exportContainer.kind === 274) { + var exportContainer = resolver.getReferencedExportContainer(name, /*prefixLocals*/ false); + if (exportContainer && exportContainer.kind === 274 /* SourceFile */) { exportedNames = ts.append(exportedNames, ts.getDeclarationName(valueDeclaration)); } exportedNames = ts.addRange(exportedNames, moduleInfo && moduleInfo.exportedBindings[ts.getOriginalNodeId(valueDeclaration)]); @@ -61522,18 +74671,29 @@ var ts; } return exportedNames; } + /** + * Prevent substitution of a node for this transformer. + * + * @param node The node which should not be substituted. + */ function preventSubstitution(node) { if (noSubstitution === undefined) noSubstitution = []; noSubstitution[ts.getNodeId(node)] = true; return node; } + /** + * Determines whether a node should not be substituted. + * + * @param node The node to test. + */ function isSubstitutionPrevented(node) { return noSubstitution && node.id && noSubstitution[node.id]; } } ts.transformSystemModule = transformSystemModule; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { function transformES2015Module(context) { @@ -61542,8 +74702,8 @@ var ts; var previousOnSubstituteNode = context.onSubstituteNode; context.onEmitNode = onEmitNode; context.onSubstituteNode = onSubstituteNode; - context.enableEmitNotification(274); - context.enableSubstitution(71); + context.enableEmitNotification(274 /* SourceFile */); + context.enableSubstitution(71 /* Identifier */); var currentSourceFile; return ts.chainBundle(transformSourceFile); function transformSourceFile(node) { @@ -61555,8 +74715,10 @@ var ts; if (externalHelpersModuleName) { var statements = []; var statementOffset = ts.addPrologue(statements, node.statements); - var tslibImport = ts.createImportDeclaration(undefined, undefined, ts.createImportClause(undefined, ts.createNamespaceImport(externalHelpersModuleName)), ts.createLiteral(ts.externalHelpersModuleNameText)); - ts.addEmitFlags(tslibImport, 67108864); + var tslibImport = ts.createImportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, ts.createImportClause(/*name*/ undefined, ts.createNamespaceImport(externalHelpersModuleName)), ts.createLiteral(ts.externalHelpersModuleNameText)); + ts.addEmitFlags(tslibImport, 67108864 /* NeverApplyImportHelper */); ts.append(statements, tslibImport); ts.addRange(statements, ts.visitNodes(node.statements, visitor, ts.isStatement, statementOffset)); return ts.updateSourceFileNode(node, ts.setTextRange(ts.createNodeArray(statements), node.statements)); @@ -61569,16 +74731,28 @@ var ts; } function visitor(node) { switch (node.kind) { - case 243: + case 243 /* ImportEqualsDeclaration */: + // Elide `import=` as it is not legal with --module ES6 return undefined; - case 249: + case 249 /* ExportAssignment */: return visitExportAssignment(node); } return node; } function visitExportAssignment(node) { + // Elide `export=` as it is not legal with --module ES6 return node.isExportEquals ? undefined : node; } + // + // Emit Notification + // + /** + * Hook for node emit. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emit A callback used to emit the node in the printer. + */ function onEmitNode(hint, node, emitCallback) { if (ts.isSourceFile(node)) { currentSourceFile = node; @@ -61589,15 +74763,24 @@ var ts; previousOnEmitNode(hint, node, emitCallback); } } + // + // Substitutions + // + /** + * Hooks node substitutions. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to substitute. + */ function onSubstituteNode(hint, node) { node = previousOnSubstituteNode(hint, node); - if (ts.isIdentifier(node) && hint === 1) { + if (ts.isIdentifier(node) && hint === 1 /* Expression */) { return substituteExpressionIdentifier(node); } return node; } function substituteExpressionIdentifier(node) { - if (ts.getEmitFlags(node) & 4096) { + if (ts.getEmitFlags(node) & 4096 /* HelperName */) { var externalHelpersModuleName = ts.getExternalHelpersModuleName(currentSourceFile); if (externalHelpersModuleName) { return ts.createPropertyAccess(externalHelpersModuleName, node); @@ -61608,6 +74791,7 @@ var ts; } ts.transformES2015Module = transformES2015Module; })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { function canProduceDiagnostics(node) { @@ -61650,16 +74834,16 @@ var ts; } : undefined; } function getAccessorNameVisibilityDiagnosticMessage(symbolAccessibilityResult) { - if (ts.hasModifier(node, 32)) { + if (ts.hasModifier(node, 32 /* Static */)) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1; } - else if (node.parent.kind === 235) { + else if (node.parent.kind === 235 /* ClassDeclaration */) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1; @@ -61679,16 +74863,16 @@ var ts; } : undefined; } function getMethodNameVisibilityDiagnosticMessage(symbolAccessibilityResult) { - if (ts.hasModifier(node, 32)) { + if (ts.hasModifier(node, 32 /* Static */)) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Public_static_method_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Public_static_method_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Public_static_method_0_of_exported_class_has_or_is_using_private_name_1; } - else if (node.parent.kind === 235) { + else if (node.parent.kind === 235 /* ClassDeclaration */) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Public_method_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Public_method_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Public_method_0_of_exported_class_has_or_is_using_private_name_1; @@ -61712,7 +74896,7 @@ var ts; return getReturnTypeVisibilityError; } else if (ts.isParameter(node)) { - if (ts.isParameterPropertyDeclaration(node) && ts.hasModifier(node.parent, 8)) { + if (ts.isParameterPropertyDeclaration(node) && ts.hasModifier(node.parent, 8 /* Private */)) { return getVariableDeclarationTypeVisibilityError; } return getParameterDeclarationTypeVisibilityError; @@ -61733,30 +74917,34 @@ var ts; return ts.Debug.assertNever(node, "Attempted to set a declaration diagnostic context for unhandled node kind: " + ts.SyntaxKind[node.kind]); } function getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult) { - if (node.kind === 232 || node.kind === 182) { + if (node.kind === 232 /* VariableDeclaration */ || node.kind === 182 /* BindingElement */) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Exported_variable_0_has_or_is_using_private_name_1; } - else if (node.kind === 152 || node.kind === 151 || - (node.kind === 149 && ts.hasModifier(node.parent, 8))) { - if (ts.hasModifier(node, 32)) { + // This check is to ensure we don't report error on constructor parameter property as that error would be reported during parameter emit + // The only exception here is if the constructor was marked as private. we are not emitting the constructor parameters at all. + else if (node.kind === 152 /* PropertyDeclaration */ || node.kind === 151 /* PropertySignature */ || + (node.kind === 149 /* Parameter */ && ts.hasModifier(node.parent, 8 /* Private */))) { + // TODO(jfreeman): Deal with computed properties in error reporting. + if (ts.hasModifier(node, 32 /* Static */)) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1; } - else if (node.parent.kind === 235 || node.kind === 149) { + else if (node.parent.kind === 235 /* ClassDeclaration */ || node.kind === 149 /* Parameter */) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1; } else { + // Interfaces cannot have types that cannot be named return symbolAccessibilityResult.errorModuleName ? ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_private_name_1; @@ -61773,8 +74961,10 @@ var ts; } function getAccessorDeclarationTypeVisibilityError(symbolAccessibilityResult) { var diagnosticMessage; - if (node.kind === 157) { - if (ts.hasModifier(node, 32)) { + if (node.kind === 157 /* SetAccessor */) { + // Getters can infer the return type from the returned expression, but setters cannot, so the + // "_from_external_module_1_but_cannot_be_named" case cannot occur. + if (ts.hasModifier(node, 32 /* Static */)) { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? ts.Diagnostics.Parameter_type_of_public_static_setter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_type_of_public_static_setter_0_from_exported_class_has_or_is_using_private_name_1; @@ -61786,16 +74976,16 @@ var ts; } } else { - if (ts.hasModifier(node, 32)) { + if (ts.hasModifier(node, 32 /* Static */)) { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_private_name_1; } else { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_private_name_1; @@ -61810,46 +75000,50 @@ var ts; function getReturnTypeVisibilityError(symbolAccessibilityResult) { var diagnosticMessage; switch (node.kind) { - case 159: + case 159 /* ConstructSignature */: + // Interfaces cannot have return types that cannot be named diagnosticMessage = symbolAccessibilityResult.errorModuleName ? ts.Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_0; break; - case 158: + case 158 /* CallSignature */: + // Interfaces cannot have return types that cannot be named diagnosticMessage = symbolAccessibilityResult.errorModuleName ? ts.Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_name_0; break; - case 160: + case 160 /* IndexSignature */: + // Interfaces cannot have return types that cannot be named diagnosticMessage = symbolAccessibilityResult.errorModuleName ? ts.Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_name_0; break; - case 154: - case 153: - if (ts.hasModifier(node, 32)) { + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + if (ts.hasModifier(node, 32 /* Static */)) { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_name_0; } - else if (node.parent.kind === 235) { + else if (node.parent.kind === 235 /* ClassDeclaration */) { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_private_name_0; } else { + // Interfaces cannot have return types that cannot be named diagnosticMessage = symbolAccessibilityResult.errorModuleName ? ts.Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_private_name_0; } break; - case 234: + case 234 /* FunctionDeclaration */: diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_private_name_0; @@ -61872,50 +75066,54 @@ var ts; } function getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult) { switch (node.parent.kind) { - case 155: + case 155 /* Constructor */: return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1; - case 159: - case 164: + case 159 /* ConstructSignature */: + case 164 /* ConstructorType */: + // Interfaces cannot have parameter types that cannot be named return symbolAccessibilityResult.errorModuleName ? ts.Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; - case 158: + case 158 /* CallSignature */: + // Interfaces cannot have parameter types that cannot be named return symbolAccessibilityResult.errorModuleName ? ts.Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1; - case 160: + case 160 /* IndexSignature */: + // Interfaces cannot have parameter types that cannot be named return symbolAccessibilityResult.errorModuleName ? ts.Diagnostics.Parameter_0_of_index_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_index_signature_from_exported_interface_has_or_is_using_private_name_1; - case 154: - case 153: - if (ts.hasModifier(node.parent, 32)) { + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + if (ts.hasModifier(node.parent, 32 /* Static */)) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; } - else if (node.parent.parent.kind === 235) { + else if (node.parent.parent.kind === 235 /* ClassDeclaration */) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; } else { + // Interfaces cannot have parameter types that cannot be named return symbolAccessibilityResult.errorModuleName ? ts.Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1; } - case 234: - case 163: + case 234 /* FunctionDeclaration */: + case 163 /* FunctionType */: return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_private_name_1; @@ -61924,36 +75122,37 @@ var ts; } } function getTypeParameterConstraintVisibilityError() { + // Type parameter constraints are named by user so we should always be able to name it var diagnosticMessage; switch (node.parent.kind) { - case 235: + case 235 /* ClassDeclaration */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_class_has_or_is_using_private_name_1; break; - case 236: + case 236 /* InterfaceDeclaration */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1; break; - case 159: + case 159 /* ConstructSignature */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; break; - case 158: + case 158 /* CallSignature */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1; break; - case 154: - case 153: - if (ts.hasModifier(node.parent, 32)) { + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + if (ts.hasModifier(node.parent, 32 /* Static */)) { diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; } - else if (node.parent.parent.kind === 235) { + else if (node.parent.parent.kind === 235 /* ClassDeclaration */) { diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; } else { diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1; } break; - case 234: + case 234 /* FunctionDeclaration */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_function_has_or_is_using_private_name_1; break; - case 237: + case 237 /* TypeAliasDeclaration */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_type_alias_has_or_is_using_private_name_1; break; default: @@ -61967,12 +75166,15 @@ var ts; } function getHeritageClauseVisibilityError() { var diagnosticMessage; - if (node.parent.parent.kind === 235) { - diagnosticMessage = node.parent.token === 108 ? + // Heritage clause is written by user so it can always be named + if (node.parent.parent.kind === 235 /* ClassDeclaration */) { + // Class or Interface implemented/extended is inaccessible + diagnosticMessage = node.parent.token === 108 /* ImplementsKeyword */ ? ts.Diagnostics.Implements_clause_of_exported_class_0_has_or_is_using_private_name_1 : ts.Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1; } else { + // interface is inaccessible diagnosticMessage = ts.Diagnostics.extends_clause_of_exported_interface_0_has_or_is_using_private_name_1; } return { @@ -61998,23 +75200,30 @@ var ts; } ts.createGetSymbolAccessibilityDiagnosticForNode = createGetSymbolAccessibilityDiagnosticForNode; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { function getDeclarationDiagnostics(host, resolver, file) { if (file && ts.isSourceFileJavaScript(file)) { - return []; + return []; // No declaration diagnostics for js for now } var compilerOptions = host.getCompilerOptions(); - var result = ts.transformNodes(resolver, host, compilerOptions, file ? [file] : ts.filter(host.getSourceFiles(), ts.isSourceFileNotJavaScript), [transformDeclarations], false); + var result = ts.transformNodes(resolver, host, compilerOptions, file ? [file] : ts.filter(host.getSourceFiles(), ts.isSourceFileNotJavaScript), [transformDeclarations], /*allowDtsFiles*/ false); return result.diagnostics; } ts.getDeclarationDiagnostics = getDeclarationDiagnostics; - var declarationEmitNodeBuilderFlags = 1024 | - 2048 | - 4096 | - 8 | - 524288 | - 4; + var declarationEmitNodeBuilderFlags = 1024 /* MultilineObjectLiterals */ | + 2048 /* WriteClassExpressionAsTypeLiteral */ | + 4096 /* UseTypeOfFunction */ | + 8 /* UseStructuralFallback */ | + 524288 /* AllowEmptyTuple */ | + 4 /* GenerateNamesForShadowedTypeParams */; + /** + * Transforms a ts file into a .d.ts file + * This process requires type information, which is retrieved through the emit resolver. Because of this, + * in many places this transformer assumes it will be operating on parse tree nodes directly. + * This means that _no transforms should be allowed to occur before this one_. + */ function transformDeclarations(context) { var throwDiagnostic = function () { return ts.Debug.fail("Diagnostic emitted without context"); }; var getSymbolAccessibilityDiagnostic = throwDiagnostic; @@ -62060,7 +75269,8 @@ var ts; refs.set("" + ts.getOriginalNodeId(container), container); } function handleSymbolAccessibilityError(symbolAccessibilityResult) { - if (symbolAccessibilityResult.accessibility === 0) { + if (symbolAccessibilityResult.accessibility === 0 /* Accessible */) { + // Add aliases back onto the possible imports list if they're not there so we can try them again with updated visibility info if (symbolAccessibilityResult && symbolAccessibilityResult.aliasesToMakeVisible) { if (!lateMarkedStatements) { lateMarkedStatements = symbolAccessibilityResult.aliasesToMakeVisible; @@ -62072,8 +75282,10 @@ var ts; } } } + // TODO: Do all these accessibility checks inside/after the first pass in the checker when declarations are enabled, if possible } else { + // Report error var errorInfo = getSymbolAccessibilityDiagnostic(symbolAccessibilityResult); if (errorInfo) { if (errorInfo.typeName) { @@ -62086,9 +75298,9 @@ var ts; } } function trackSymbol(symbol, enclosingDeclaration, meaning) { - if (symbol.flags & 262144) + if (symbol.flags & 262144 /* TypeParameter */) return; - handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning, true)); + handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning, /*shouldComputeAliasesToMakeVisible*/ true)); recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForSymbol(symbol, meaning)); } function reportPrivateInBaseOfClassExpression(propertyName) { @@ -62107,16 +75319,16 @@ var ts; } } function transformRoot(node) { - if (node.kind === 274 && (node.isDeclarationFile || ts.isSourceFileJavaScript(node))) { + if (node.kind === 274 /* SourceFile */ && (node.isDeclarationFile || ts.isSourceFileJavaScript(node))) { return node; } - if (node.kind === 275) { + if (node.kind === 275 /* Bundle */) { isBundledEmit = true; var refs_1 = ts.createMap(); var hasNoDefaultLib_1 = false; var bundle = ts.createBundle(ts.map(node.sourceFiles, function (sourceFile) { if (sourceFile.isDeclarationFile || ts.isSourceFileJavaScript(sourceFile)) - return undefined; + return undefined; // Omit declaration files from bundle results, too // TODO: GH#18217 hasNoDefaultLib_1 = hasNoDefaultLib_1 || sourceFile.hasNoDefaultLib; currentSourceFile = sourceFile; enclosingDeclaration = sourceFile; @@ -62128,28 +75340,29 @@ var ts; resultHasScopeMarker = false; collectReferences(sourceFile, refs_1); if (ts.isExternalModule(sourceFile)) { - resultHasExternalModuleIndicator = false; + resultHasExternalModuleIndicator = false; // unused in external module bundle emit (all external modules are within module blocks, therefore are known to be modules) needsDeclare = false; var statements_5 = ts.visitNodes(sourceFile.statements, visitDeclarationStatements); - var newFile = ts.updateSourceFileNode(sourceFile, [ts.createModuleDeclaration([], [ts.createModifier(124)], ts.createLiteral(ts.getResolvedExternalModuleName(context.getEmitHost(), sourceFile)), ts.createModuleBlock(ts.setTextRange(ts.createNodeArray(transformAndReplaceLatePaintedStatements(statements_5)), sourceFile.statements)))], true, [], [], false, []); + var newFile = ts.updateSourceFileNode(sourceFile, [ts.createModuleDeclaration([], [ts.createModifier(124 /* DeclareKeyword */)], ts.createLiteral(ts.getResolvedExternalModuleName(context.getEmitHost(), sourceFile)), ts.createModuleBlock(ts.setTextRange(ts.createNodeArray(transformAndReplaceLatePaintedStatements(statements_5)), sourceFile.statements)))], /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false, /*libReferences*/ []); return newFile; } needsDeclare = true; var updated = ts.visitNodes(sourceFile.statements, visitDeclarationStatements); - return ts.updateSourceFileNode(sourceFile, transformAndReplaceLatePaintedStatements(updated), true, [], [], false, []); + return ts.updateSourceFileNode(sourceFile, transformAndReplaceLatePaintedStatements(updated), /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false, /*libReferences*/ []); }), ts.mapDefined(node.prepends, function (prepend) { - if (prepend.kind === 277) { + if (prepend.kind === 277 /* InputFiles */) { return ts.createUnparsedSourceFile(prepend.declarationText, prepend.declarationMapPath, prepend.declarationMapText); } })); bundle.syntheticFileReferences = []; bundle.syntheticTypeReferences = getFileReferencesForUsedTypeReferences(); bundle.hasNoDefaultLib = hasNoDefaultLib_1; - var outputFilePath_1 = ts.getDirectoryPath(ts.normalizeSlashes(ts.getOutputPathsFor(node, host, true).declarationFilePath)); + var outputFilePath_1 = ts.getDirectoryPath(ts.normalizeSlashes(ts.getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath)); var referenceVisitor_1 = mapReferencesIntoArray(bundle.syntheticFileReferences, outputFilePath_1); refs_1.forEach(referenceVisitor_1); return bundle; } + // Single source file needsDeclare = true; needsScopeFixMarker = false; resultHasScopeMarker = false; @@ -62164,21 +75377,22 @@ var ts; necessaryTypeRefernces = undefined; refs = collectReferences(currentSourceFile, ts.createMap()); var references = []; - var outputFilePath = ts.getDirectoryPath(ts.normalizeSlashes(ts.getOutputPathsFor(node, host, true).declarationFilePath)); + var outputFilePath = ts.getDirectoryPath(ts.normalizeSlashes(ts.getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath)); var referenceVisitor = mapReferencesIntoArray(references, outputFilePath); var statements = ts.visitNodes(node.statements, visitDeclarationStatements); var combinedStatements = ts.setTextRange(ts.createNodeArray(transformAndReplaceLatePaintedStatements(statements)), node.statements); refs.forEach(referenceVisitor); var emittedImports = ts.filter(combinedStatements, ts.isAnyImportSyntax); if (ts.isExternalModule(node) && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker))) { - combinedStatements = ts.setTextRange(ts.createNodeArray(combinedStatements.concat([ts.createExportDeclaration(undefined, undefined, ts.createNamedExports([]), undefined)])), combinedStatements); + combinedStatements = ts.setTextRange(ts.createNodeArray(combinedStatements.concat([ts.createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, ts.createNamedExports([]), /*moduleSpecifier*/ undefined)])), combinedStatements); } - var updated = ts.updateSourceFileNode(node, combinedStatements, true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib); + var updated = ts.updateSourceFileNode(node, combinedStatements, /*isDeclarationFile*/ true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib); return updated; function getFileReferencesForUsedTypeReferences() { return necessaryTypeRefernces ? ts.mapDefined(ts.arrayFrom(necessaryTypeRefernces.keys()), getFileReferenceForTypeName) : []; } function getFileReferenceForTypeName(typeName) { + // Elide type references for which we have imports if (emittedImports) { for (var _i = 0, emittedImports_1 = emittedImports; _i < emittedImports_1.length; _i++) { var importStatement = emittedImports_1[_i]; @@ -62198,17 +75412,18 @@ var ts; function mapReferencesIntoArray(references, outputFilePath) { return function (file) { var declFileName; - if (file.isDeclarationFile) { + if (file.isDeclarationFile) { // Neither decl files or js should have their refs changed declFileName = file.fileName; } else { if (isBundledEmit && ts.contains(node.sourceFiles, file)) - return; - var paths = ts.getOutputPathsFor(file, host, true); + return; // Omit references to files which are being merged + var paths = ts.getOutputPathsFor(file, host, /*forceDtsPaths*/ true); declFileName = paths.declarationFilePath || paths.jsFilePath; } if (declFileName) { - var fileName = ts.getRelativePathToDirectoryOrUrl(outputFilePath, declFileName, host.getCurrentDirectory(), host.getCanonicalFileName, false); + var fileName = ts.getRelativePathToDirectoryOrUrl(outputFilePath, declFileName, host.getCurrentDirectory(), host.getCanonicalFileName, + /*isAbsolutePathAnUrl*/ false); if (ts.startsWith(fileName, "./") && ts.hasExtension(fileName)) { fileName = fileName.substring(2); } @@ -62229,11 +75444,11 @@ var ts; return ret; } function filterBindingPatternInitializers(name) { - if (name.kind === 71) { + if (name.kind === 71 /* Identifier */) { return name; } else { - if (name.kind === 181) { + if (name.kind === 181 /* ArrayBindingPattern */) { return ts.updateArrayBindingPattern(name, ts.visitNodes(name.elements, visitBindingElement)); } else { @@ -62241,7 +75456,7 @@ var ts; } } function visitBindingElement(elem) { - if (elem.kind === 206) { + if (elem.kind === 206 /* OmittedExpression */) { return elem; } return ts.updateBindingElement(elem, elem.dotDotDotToken, elem.propertyName, filterBindingPatternInitializers(elem.name), shouldPrintWithInitializer(elem) ? elem.initializer : undefined); @@ -62253,39 +75468,45 @@ var ts; oldDiag = getSymbolAccessibilityDiagnostic; getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNode(p); } - var newParam = ts.updateParameter(p, undefined, maskModifiers(p, modifierMask), p.dotDotDotToken, filterBindingPatternInitializers(p.name), resolver.isOptionalParameter(p) ? (p.questionToken || ts.createToken(55)) : undefined, ensureType(p, p.type, true), ensureNoInitializer(p)); + var newParam = ts.updateParameter(p, + /*decorators*/ undefined, maskModifiers(p, modifierMask), p.dotDotDotToken, filterBindingPatternInitializers(p.name), resolver.isOptionalParameter(p) ? (p.questionToken || ts.createToken(55 /* QuestionToken */)) : undefined, ensureType(p, p.type, /*ignorePrivate*/ true), // Ignore private param props, since this type is going straight back into a param + ensureNoInitializer(p)); if (!suppressNewDiagnosticContexts) { getSymbolAccessibilityDiagnostic = oldDiag; } return newParam; } function shouldPrintWithInitializer(node) { - return canHaveLiteralInitializer(node) && resolver.isLiteralConstDeclaration(ts.getParseTreeNode(node)); + return canHaveLiteralInitializer(node) && resolver.isLiteralConstDeclaration(ts.getParseTreeNode(node)); // TODO: Make safe } function ensureNoInitializer(node) { if (shouldPrintWithInitializer(node)) { - return resolver.createLiteralConstValue(ts.getParseTreeNode(node)); + return resolver.createLiteralConstValue(ts.getParseTreeNode(node)); // TODO: Make safe } return undefined; } function ensureType(node, type, ignorePrivate) { - if (!ignorePrivate && ts.hasModifier(node, 8)) { + if (!ignorePrivate && ts.hasModifier(node, 8 /* Private */)) { + // Private nodes emit no types (except private parameter properties, whose parameter types are actually visible) return; } if (shouldPrintWithInitializer(node)) { + // Literal const declarations will have an initializer ensured rather than a type return; } - var shouldUseResolverType = node.kind === 149 && + var shouldUseResolverType = node.kind === 149 /* Parameter */ && (resolver.isRequiredInitializedParameter(node) || resolver.isOptionalUninitializedParameterProperty(node)); if (type && !shouldUseResolverType) { return ts.visitNode(type, visitDeclarationSubtree); } if (!ts.getParseTreeNode(node)) { - return type ? ts.visitNode(type, visitDeclarationSubtree) : ts.createKeywordTypeNode(119); + return type ? ts.visitNode(type, visitDeclarationSubtree) : ts.createKeywordTypeNode(119 /* AnyKeyword */); } - if (node.kind === 157) { - return ts.createKeywordTypeNode(119); + if (node.kind === 157 /* SetAccessor */) { + // Set accessors with no associated type node (from it's param or get accessor return) are `any` since they are never contextually typed right now + // (The inferred type here will be void, but the old declaration emitter printed `any`, so this replicates that) + return ts.createKeywordTypeNode(119 /* AnyKeyword */); } errorNameNode = node.name; var oldDiag; @@ -62293,12 +75514,12 @@ var ts; oldDiag = getSymbolAccessibilityDiagnostic; getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNode(node); } - if (node.kind === 232 || node.kind === 182) { + if (node.kind === 232 /* VariableDeclaration */ || node.kind === 182 /* BindingElement */) { return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker)); } - if (node.kind === 149 - || node.kind === 152 - || node.kind === 151) { + if (node.kind === 149 /* Parameter */ + || node.kind === 152 /* PropertyDeclaration */ + || node.kind === 151 /* PropertySignature */) { if (!node.initializer) return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker, shouldUseResolverType)); return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker, shouldUseResolverType) || resolver.createTypeOfExpression(node.initializer, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker)); @@ -62309,25 +75530,26 @@ var ts; if (!suppressNewDiagnosticContexts) { getSymbolAccessibilityDiagnostic = oldDiag; } - return returnValue || ts.createKeywordTypeNode(119); + return returnValue || ts.createKeywordTypeNode(119 /* AnyKeyword */); } } function isDeclarationAndNotVisible(node) { node = ts.getParseTreeNode(node); switch (node.kind) { - case 234: - case 239: - case 236: - case 235: - case 237: - case 238: + case 234 /* FunctionDeclaration */: + case 239 /* ModuleDeclaration */: + case 236 /* InterfaceDeclaration */: + case 235 /* ClassDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 238 /* EnumDeclaration */: return !resolver.isDeclarationVisible(node); - case 232: + // The following should be doing their own visibility checks based on filtering their members + case 232 /* VariableDeclaration */: return !getBindingNameVisible(node); - case 243: - case 244: - case 250: - case 249: + case 243 /* ImportEqualsDeclaration */: + case 244 /* ImportDeclaration */: + case 250 /* ExportDeclaration */: + case 249 /* ExportAssignment */: return false; } return false; @@ -62337,6 +75559,7 @@ var ts; return false; } if (ts.isBindingPattern(elem.name)) { + // If any child binding pattern element has been marked visible (usually by collect linked aliases), then this is visible return ts.some(elem.name.elements, getBindingNameVisible); } else { @@ -62344,17 +75567,17 @@ var ts; } } function updateParamsList(node, params, modifierMask) { - if (ts.hasModifier(node, 8)) { - return undefined; + if (ts.hasModifier(node, 8 /* Private */)) { + return undefined; // TODO: GH#18217 } var newParams = ts.map(params, function (p) { return ensureParameter(p, modifierMask); }); if (!newParams) { - return undefined; + return undefined; // TODO: GH#18217 } return ts.createNodeArray(newParams, params.hasTrailingComma); } function ensureTypeParams(node, params) { - return ts.hasModifier(node, 8) ? undefined : ts.visitNodes(params, visitDeclarationSubtree); + return ts.hasModifier(node, 8 /* Private */) ? undefined : ts.visitNodes(params, visitDeclarationSubtree); } function isEnclosingDeclaration(node) { return ts.isSourceFile(node) @@ -62379,9 +75602,9 @@ var ts; } function rewriteModuleSpecifier(parent, input) { if (!input) - return undefined; - resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || (parent.kind !== 239 && parent.kind !== 179); - if (input.kind === 9 && isBundledEmit) { + return undefined; // TODO: GH#18217 + resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || (parent.kind !== 239 /* ModuleDeclaration */ && parent.kind !== 179 /* ImportType */); + if (input.kind === 9 /* StringLiteral */ && isBundledEmit) { var newName = ts.getExternalModuleNameFromDeclaration(context.getEmitHost(), resolver, parent); if (newName) { return ts.createLiteral(newName); @@ -62392,9 +75615,11 @@ var ts; function transformImportEqualsDeclaration(decl) { if (!resolver.isDeclarationVisible(decl)) return; - if (decl.moduleReference.kind === 254) { + if (decl.moduleReference.kind === 254 /* ExternalModuleReference */) { + // Rewrite external module names if necessary var specifier = ts.getExternalModuleImportEqualsDeclarationExpression(decl); - return ts.updateImportEqualsDeclaration(decl, undefined, decl.modifiers, decl.name, ts.updateExternalModuleReference(decl.moduleReference, rewriteModuleSpecifier(decl, specifier))); + return ts.updateImportEqualsDeclaration(decl, + /*decorators*/ undefined, decl.modifiers, decl.name, ts.updateExternalModuleReference(decl.moduleReference, rewriteModuleSpecifier(decl, specifier))); } else { var oldDiag = getSymbolAccessibilityDiagnostic; @@ -62406,30 +75631,55 @@ var ts; } function transformImportDeclaration(decl) { if (!decl.importClause) { - return ts.updateImportDeclaration(decl, undefined, decl.modifiers, decl.importClause, rewriteModuleSpecifier(decl, decl.moduleSpecifier)); + // import "mod" - possibly needed for side effects? (global interface patches, module augmentations, etc) + return ts.updateImportDeclaration(decl, + /*decorators*/ undefined, decl.modifiers, decl.importClause, rewriteModuleSpecifier(decl, decl.moduleSpecifier)); } + // The `importClause` visibility corresponds to the default's visibility. var visibleDefaultBinding = decl.importClause && decl.importClause.name && resolver.isDeclarationVisible(decl.importClause) ? decl.importClause.name : undefined; if (!decl.importClause.namedBindings) { - return visibleDefaultBinding && ts.updateImportDeclaration(decl, undefined, decl.modifiers, ts.updateImportClause(decl.importClause, visibleDefaultBinding, undefined), rewriteModuleSpecifier(decl, decl.moduleSpecifier)); + // No named bindings (either namespace or list), meaning the import is just default or should be elided + return visibleDefaultBinding && ts.updateImportDeclaration(decl, /*decorators*/ undefined, decl.modifiers, ts.updateImportClause(decl.importClause, visibleDefaultBinding, + /*namedBindings*/ undefined), rewriteModuleSpecifier(decl, decl.moduleSpecifier)); } - if (decl.importClause.namedBindings.kind === 246) { - var namedBindings = resolver.isDeclarationVisible(decl.importClause.namedBindings) ? decl.importClause.namedBindings : undefined; - return visibleDefaultBinding || namedBindings ? ts.updateImportDeclaration(decl, undefined, decl.modifiers, ts.updateImportClause(decl.importClause, visibleDefaultBinding, namedBindings), rewriteModuleSpecifier(decl, decl.moduleSpecifier)) : undefined; + if (decl.importClause.namedBindings.kind === 246 /* NamespaceImport */) { + // Namespace import (optionally with visible default) + var namedBindings = resolver.isDeclarationVisible(decl.importClause.namedBindings) ? decl.importClause.namedBindings : /*namedBindings*/ undefined; + return visibleDefaultBinding || namedBindings ? ts.updateImportDeclaration(decl, /*decorators*/ undefined, decl.modifiers, ts.updateImportClause(decl.importClause, visibleDefaultBinding, namedBindings), rewriteModuleSpecifier(decl, decl.moduleSpecifier)) : undefined; } + // Named imports (optionally with visible default) var bindingList = ts.mapDefined(decl.importClause.namedBindings.elements, function (b) { return resolver.isDeclarationVisible(b) ? b : undefined; }); if ((bindingList && bindingList.length) || visibleDefaultBinding) { - return ts.updateImportDeclaration(decl, undefined, decl.modifiers, ts.updateImportClause(decl.importClause, visibleDefaultBinding, bindingList && bindingList.length ? ts.updateNamedImports(decl.importClause.namedBindings, bindingList) : undefined), rewriteModuleSpecifier(decl, decl.moduleSpecifier)); + return ts.updateImportDeclaration(decl, + /*decorators*/ undefined, decl.modifiers, ts.updateImportClause(decl.importClause, visibleDefaultBinding, bindingList && bindingList.length ? ts.updateNamedImports(decl.importClause.namedBindings, bindingList) : undefined), rewriteModuleSpecifier(decl, decl.moduleSpecifier)); } + // Nothing visible } function transformAndReplaceLatePaintedStatements(statements) { + // This is a `while` loop because `handleSymbolAccessibilityError` can see additional import aliases marked as visible during + // error handling which must now be included in the output and themselves checked for errors. + // For example: + // ``` + // module A { + // export module Q {} + // import B = Q; + // import C = B; + // export import D = C; + // } + // ``` + // In such a scenario, only Q and D are initially visible, but we don't consider imports as private names - instead we say they if they are referenced they must + // be recorded. So while checking D's visibility we mark C as visible, then we must check C which in turn marks B, completing the chain of + // dependent imports and allowing a valid declaration file output. Today, this dependent alias marking only happens for internal import aliases. while (ts.length(lateMarkedStatements)) { var i = lateMarkedStatements.shift(); if (!ts.isLateVisibilityPaintedStatement(i)) { return ts.Debug.fail("Late replaced statement was found which is not handled by the declaration transformer!: " + (ts.SyntaxKind ? ts.SyntaxKind[i.kind] : i.kind)); } - var result = transformTopLevelDeclaration(i, true); + var result = transformTopLevelDeclaration(i, /*privateDeclaration*/ true); lateStatementReplacementMap.set("" + ts.getOriginalNodeId(i), result); } + // And lastly, we need to get the final form of all those indetermine import declarations from before and add them to the output list + // (and remove them from the set to examine for outter declarations) return ts.visitNodes(statements, visitLateVisibilityMarkedStatements); function visitLateVisibilityMarkedStatements(statement) { if (ts.isLateVisibilityPaintedStatement(statement)) { @@ -62439,6 +75689,7 @@ var ts; lateStatementReplacementMap.delete(key); if (result && ts.isSourceFile(statement.parent)) { if (ts.isArray(result) ? ts.some(result, needsScopeMarker) : needsScopeMarker(result)) { + // Top-level declarations in .d.ts files are always considered exported even without a modifier unless there's an export assignment or specifier needsScopeFixMarker = true; } if (ts.isArray(result) ? ts.some(result, isExternalModuleIndicator) : isExternalModuleIndicator(result)) { @@ -62452,10 +75703,11 @@ var ts; } } function isExternalModuleIndicator(result) { - return ts.isAnyImportOrReExport(result) || ts.isExportAssignment(result) || ts.hasModifier(result, 1); + // Exported top-level member indicates moduleness + return ts.isAnyImportOrReExport(result) || ts.isExportAssignment(result) || ts.hasModifier(result, 1 /* Export */); } function needsScopeMarker(result) { - return !ts.isAnyImportOrReExport(result) && !ts.isExportAssignment(result) && !ts.hasModifier(result, 1) && !ts.isAmbientModule(result); + return !ts.isAnyImportOrReExport(result) && !ts.isExportAssignment(result) && !ts.hasModifier(result, 1 /* Export */) && !ts.isAmbientModule(result); } function visitDeclarationSubtree(input) { if (shouldStripInternal(input)) @@ -62467,8 +75719,10 @@ var ts; return; } } + // Elide implementation signatures from overload sets if (ts.isFunctionLike(input) && resolver.isImplementationOfOverload(input)) return; + // Elide semicolon class statements if (ts.isSemicolonClassElement(input)) return; var previousEnclosingDeclaration; @@ -62477,11 +75731,12 @@ var ts; enclosingDeclaration = input; } var oldDiag = getSymbolAccessibilityDiagnostic; + // Emit methods which are private as properties with no type information if (ts.isMethodDeclaration(input) || ts.isMethodSignature(input)) { - if (ts.hasModifier(input, 8)) { + if (ts.hasModifier(input, 8 /* Private */)) { if (input.symbol && input.symbol.declarations && input.symbol.declarations[0] !== input) - return; - return cleanup(ts.createProperty(undefined, ensureModifiers(input), input.name, undefined, undefined, undefined)); + return; // Elide all but the first overload + return cleanup(ts.createProperty(/*decorators*/ undefined, ensureModifiers(input), input.name, /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined)); } } var canProdiceDiagnostic = ts.canProduceDiagnostics(input); @@ -62492,75 +75747,84 @@ var ts; checkEntityNameVisibility(input.exprName, enclosingDeclaration); } var oldWithinObjectLiteralType = suppressNewDiagnosticContexts; - var shouldEnterSuppressNewDiagnosticsContextContext = ((input.kind === 166 || input.kind === 177) && input.parent.kind !== 237); + var shouldEnterSuppressNewDiagnosticsContextContext = ((input.kind === 166 /* TypeLiteral */ || input.kind === 177 /* MappedType */) && input.parent.kind !== 237 /* TypeAliasDeclaration */); if (shouldEnterSuppressNewDiagnosticsContextContext) { + // We stop making new diagnostic contexts within object literal types. Unless it's an object type on the RHS of a type alias declaration. Then we do. suppressNewDiagnosticContexts = true; } if (isProcessedComponent(input)) { switch (input.kind) { - case 207: { + case 207 /* ExpressionWithTypeArguments */: { if ((ts.isEntityName(input.expression) || ts.isEntityNameExpression(input.expression))) { checkEntityNameVisibility(input.expression, enclosingDeclaration); } var node = ts.visitEachChild(input, visitDeclarationSubtree, context); return cleanup(ts.updateExpressionWithTypeArguments(node, ts.parenthesizeTypeParameters(node.typeArguments), node.expression)); } - case 162: { + case 162 /* TypeReference */: { checkEntityNameVisibility(input.typeName, enclosingDeclaration); var node = ts.visitEachChild(input, visitDeclarationSubtree, context); return cleanup(ts.updateTypeReferenceNode(node, node.typeName, ts.parenthesizeTypeParameters(node.typeArguments))); } - case 159: + case 159 /* ConstructSignature */: return cleanup(ts.updateConstructSignature(input, ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type))); - case 155: { - var isPrivate = ts.hasModifier(input, 8); - var ctor = ts.createSignatureDeclaration(155, isPrivate ? undefined : ensureTypeParams(input, input.typeParameters), isPrivate ? undefined : updateParamsList(input, input.parameters, 0), undefined); + case 155 /* Constructor */: { + var isPrivate = ts.hasModifier(input, 8 /* Private */); + // A constructor declaration may not have a type annotation + var ctor = ts.createSignatureDeclaration(155 /* Constructor */, isPrivate ? undefined : ensureTypeParams(input, input.typeParameters), + // TODO: GH#18217 + isPrivate ? undefined : updateParamsList(input, input.parameters, 0 /* None */), + /*type*/ undefined); ctor.modifiers = ts.createNodeArray(ensureModifiers(input)); return cleanup(ctor); } - case 154: { - var sig = ts.createSignatureDeclaration(153, ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type)); + case 154 /* MethodDeclaration */: { + var sig = ts.createSignatureDeclaration(153 /* MethodSignature */, ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type)); sig.name = input.name; sig.modifiers = ts.createNodeArray(ensureModifiers(input)); sig.questionToken = input.questionToken; return cleanup(sig); } - case 156: { + case 156 /* GetAccessor */: { var newNode = ensureAccessor(input); return cleanup(newNode); } - case 157: { + case 157 /* SetAccessor */: { var newNode = ensureAccessor(input); return cleanup(newNode); } - case 152: - return cleanup(ts.updateProperty(input, undefined, ensureModifiers(input), input.name, input.questionToken, !ts.hasModifier(input, 8) ? ensureType(input, input.type) : undefined, ensureNoInitializer(input))); - case 151: - return cleanup(ts.updatePropertySignature(input, ensureModifiers(input), input.name, input.questionToken, !ts.hasModifier(input, 8) ? ensureType(input, input.type) : undefined, ensureNoInitializer(input))); - case 153: { + case 152 /* PropertyDeclaration */: + return cleanup(ts.updateProperty(input, + /*decorators*/ undefined, ensureModifiers(input), input.name, input.questionToken, !ts.hasModifier(input, 8 /* Private */) ? ensureType(input, input.type) : undefined, ensureNoInitializer(input))); + case 151 /* PropertySignature */: + return cleanup(ts.updatePropertySignature(input, ensureModifiers(input), input.name, input.questionToken, !ts.hasModifier(input, 8 /* Private */) ? ensureType(input, input.type) : undefined, ensureNoInitializer(input))); + case 153 /* MethodSignature */: { return cleanup(ts.updateMethodSignature(input, ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type), input.name, input.questionToken)); } - case 158: { + case 158 /* CallSignature */: { return cleanup(ts.updateCallSignature(input, ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type))); } - case 160: { - return cleanup(ts.updateIndexSignature(input, undefined, ensureModifiers(input), updateParamsList(input, input.parameters), ts.visitNode(input.type, visitDeclarationSubtree) || ts.createKeywordTypeNode(119))); + case 160 /* IndexSignature */: { + return cleanup(ts.updateIndexSignature(input, + /*decorators*/ undefined, ensureModifiers(input), updateParamsList(input, input.parameters), ts.visitNode(input.type, visitDeclarationSubtree) || ts.createKeywordTypeNode(119 /* AnyKeyword */))); } - case 232: { + case 232 /* VariableDeclaration */: { if (ts.isBindingPattern(input.name)) { return recreateBindingPattern(input.name); } shouldEnterSuppressNewDiagnosticsContextContext = true; - suppressNewDiagnosticContexts = true; + suppressNewDiagnosticContexts = true; // Variable declaration types also suppress new diagnostic contexts, provided the contexts wouldn't be made for binding pattern types return cleanup(ts.updateVariableDeclaration(input, input.name, ensureType(input, input.type), ensureNoInitializer(input))); } - case 148: { + case 148 /* TypeParameter */: { if (isPrivateMethodTypeParameter(input) && (input.default || input.constraint)) { - return cleanup(ts.updateTypeParameterDeclaration(input, input.name, undefined, undefined)); + return cleanup(ts.updateTypeParameterDeclaration(input, input.name, /*constraint*/ undefined, /*defaultType*/ undefined)); } return cleanup(ts.visitEachChild(input, visitDeclarationSubtree, context)); } - case 171: { + case 171 /* ConditionalType */: { + // We have to process conditional types in a special way because for visibility purposes we need to push a new enclosingDeclaration + // just for the `infer` types in the true branch. It's an implicit declaration scope that only applies to _part_ of the type. var checkType = ts.visitNode(input.checkType, visitDeclarationSubtree); var extendsType = ts.visitNode(input.extendsType, visitDeclarationSubtree); var oldEnclosingDecl = enclosingDeclaration; @@ -62570,13 +75834,13 @@ var ts; var falseType = ts.visitNode(input.falseType, visitDeclarationSubtree); return cleanup(ts.updateConditionalTypeNode(input, checkType, extendsType, trueType, falseType)); } - case 163: { + case 163 /* FunctionType */: { return cleanup(ts.updateFunctionTypeNode(input, ts.visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), ts.visitNode(input.type, visitDeclarationSubtree))); } - case 164: { + case 164 /* ConstructorType */: { return cleanup(ts.updateConstructorTypeNode(input, ts.visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), ts.visitNode(input.type, visitDeclarationSubtree))); } - case 179: { + case 179 /* ImportType */: { if (!ts.isLiteralImportTypeNode(input)) return cleanup(input); return cleanup(ts.updateImportTypeNode(input, ts.updateLiteralTypeNode(input.argument, rewriteModuleSpecifier(input, input.argument.literal)), input.qualifier, ts.visitNodes(input.typeArguments, visitDeclarationSubtree, ts.isTypeNode), input.isTypeOf)); @@ -62605,28 +75869,32 @@ var ts; } } function isPrivateMethodTypeParameter(node) { - return node.parent.kind === 154 && ts.hasModifier(node.parent, 8); + return node.parent.kind === 154 /* MethodDeclaration */ && ts.hasModifier(node.parent, 8 /* Private */); } function visitDeclarationStatements(input) { if (!isPreservedDeclarationStatement(input)) { + // return undefined for unmatched kinds to omit them from the tree return; } if (shouldStripInternal(input)) return; switch (input.kind) { - case 250: { + case 250 /* ExportDeclaration */: { if (ts.isSourceFile(input.parent)) { resultHasExternalModuleIndicator = true; resultHasScopeMarker = true; } - return ts.updateExportDeclaration(input, undefined, input.modifiers, input.exportClause, rewriteModuleSpecifier(input, input.moduleSpecifier)); + // Always visible if the parent node isn't dropped for being not visible + // Rewrite external module names if necessary + return ts.updateExportDeclaration(input, /*decorators*/ undefined, input.modifiers, input.exportClause, rewriteModuleSpecifier(input, input.moduleSpecifier)); } - case 249: { + case 249 /* ExportAssignment */: { + // Always visible if the parent node isn't dropped for being not visible if (ts.isSourceFile(input.parent)) { resultHasExternalModuleIndicator = true; resultHasScopeMarker = true; } - if (input.expression.kind === 71) { + if (input.expression.kind === 71 /* Identifier */) { return input; } else { @@ -62635,13 +75903,14 @@ var ts; diagnosticMessage: ts.Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0, errorNode: input }); }; - var varDecl = ts.createVariableDeclaration(newId, resolver.createTypeOfExpression(input.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), undefined); - var statement = ts.createVariableStatement(needsDeclare ? [ts.createModifier(124)] : [], ts.createVariableDeclarationList([varDecl], 2)); + var varDecl = ts.createVariableDeclaration(newId, resolver.createTypeOfExpression(input.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined); + var statement = ts.createVariableStatement(needsDeclare ? [ts.createModifier(124 /* DeclareKeyword */)] : [], ts.createVariableDeclarationList([varDecl], 2 /* Const */)); return [statement, ts.updateExportAssignment(input, input.decorators, input.modifiers, newId)]; } } } var result = transformTopLevelDeclaration(input); + // Don't actually transform yet; just leave as original node - will be elided/swapped by late pass lateStatementReplacementMap.set("" + ts.getOriginalNodeId(input), result); return input; } @@ -62649,15 +75918,16 @@ var ts; if (shouldStripInternal(input)) return; switch (input.kind) { - case 243: { + case 243 /* ImportEqualsDeclaration */: { return transformImportEqualsDeclaration(input); } - case 244: { + case 244 /* ImportDeclaration */: { return transformImportDeclaration(input); } } if (ts.isDeclaration(input) && isDeclarationAndNotVisible(input)) return; + // Elide implementation signatures from overload sets if (ts.isFunctionLike(input) && resolver.isImplementationOfOverload(input)) return; var previousEnclosingDeclaration; @@ -62672,36 +75942,45 @@ var ts; } var previousNeedsDeclare = needsDeclare; switch (input.kind) { - case 237: - return cleanup(ts.updateTypeAliasDeclaration(input, undefined, ensureModifiers(input, isPrivate), input.name, ts.visitNodes(input.typeParameters, visitDeclarationSubtree, ts.isTypeParameterDeclaration), ts.visitNode(input.type, visitDeclarationSubtree, ts.isTypeNode))); - case 236: { - return cleanup(ts.updateInterfaceDeclaration(input, undefined, ensureModifiers(input, isPrivate), input.name, ensureTypeParams(input, input.typeParameters), transformHeritageClauses(input.heritageClauses), ts.visitNodes(input.members, visitDeclarationSubtree))); + case 237 /* TypeAliasDeclaration */: // Type aliases get `declare`d if need be (for legacy support), but that's all + return cleanup(ts.updateTypeAliasDeclaration(input, + /*decorators*/ undefined, ensureModifiers(input, isPrivate), input.name, ts.visitNodes(input.typeParameters, visitDeclarationSubtree, ts.isTypeParameterDeclaration), ts.visitNode(input.type, visitDeclarationSubtree, ts.isTypeNode))); + case 236 /* InterfaceDeclaration */: { + return cleanup(ts.updateInterfaceDeclaration(input, + /*decorators*/ undefined, ensureModifiers(input, isPrivate), input.name, ensureTypeParams(input, input.typeParameters), transformHeritageClauses(input.heritageClauses), ts.visitNodes(input.members, visitDeclarationSubtree))); } - case 234: { - return cleanup(ts.updateFunctionDeclaration(input, undefined, ensureModifiers(input, isPrivate), undefined, input.name, ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type), undefined)); + case 234 /* FunctionDeclaration */: { + // Generators lose their generator-ness, excepting their return type + return cleanup(ts.updateFunctionDeclaration(input, + /*decorators*/ undefined, ensureModifiers(input, isPrivate), + /*asteriskToken*/ undefined, input.name, ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type), + /*body*/ undefined)); } - case 239: { + case 239 /* ModuleDeclaration */: { needsDeclare = false; var inner = input.body; - if (inner && inner.kind === 240) { + if (inner && inner.kind === 240 /* ModuleBlock */) { var statements = ts.visitNodes(inner.statements, visitDeclarationStatements); var body = ts.updateModuleBlock(inner, transformAndReplaceLatePaintedStatements(statements)); needsDeclare = previousNeedsDeclare; var mods = ensureModifiers(input, isPrivate); - return cleanup(ts.updateModuleDeclaration(input, undefined, mods, ts.isExternalModuleAugmentation(input) ? rewriteModuleSpecifier(input, input.name) : input.name, body)); + return cleanup(ts.updateModuleDeclaration(input, + /*decorators*/ undefined, mods, ts.isExternalModuleAugmentation(input) ? rewriteModuleSpecifier(input, input.name) : input.name, body)); } else { needsDeclare = previousNeedsDeclare; var mods = ensureModifiers(input, isPrivate); needsDeclare = false; ts.visitNode(inner, visitDeclarationStatements); - var id = "" + ts.getOriginalNodeId(inner); + // eagerly transform nested namespaces (the nesting doesn't need any elision or painting done) + var id = "" + ts.getOriginalNodeId(inner); // TODO: GH#18217 var body = lateStatementReplacementMap.get(id); lateStatementReplacementMap.delete(id); - return cleanup(ts.updateModuleDeclaration(input, undefined, mods, input.name, body)); + return cleanup(ts.updateModuleDeclaration(input, + /*decorators*/ undefined, mods, input.name, body)); } } - case 235: { + case 235 /* ClassDeclaration */: { var modifiers = ts.createNodeArray(ensureModifiers(input, isPrivate)); var typeParameters = ensureTypeParams(input, input.typeParameters); var ctor = ts.getFirstConstructorWithBody(input); @@ -62709,13 +75988,15 @@ var ts; if (ctor) { var oldDiag_1 = getSymbolAccessibilityDiagnostic; parameterProperties = ts.compact(ts.flatMap(ctor.parameters, function (param) { - if (!ts.hasModifier(param, 92)) + if (!ts.hasModifier(param, 92 /* ParameterPropertyModifier */)) return; getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNode(param); - if (param.name.kind === 71) { - return preserveJsDoc(ts.createProperty(undefined, ensureModifiers(param), param.name, param.questionToken, ensureType(param, param.type), ensureNoInitializer(param)), param); + if (param.name.kind === 71 /* Identifier */) { + return preserveJsDoc(ts.createProperty( + /*decorators*/ undefined, ensureModifiers(param), param.name, param.questionToken, ensureType(param, param.type), ensureNoInitializer(param)), param); } else { + // Pattern - this is currently an error, but we emit declarations for it somewhat correctly return walkBindingPattern(param.name); } function walkBindingPattern(pattern) { @@ -62728,7 +76009,10 @@ var ts; elems = ts.concatenate(elems, walkBindingPattern(elem.name)); } elems = elems || []; - elems.push(ts.createProperty(undefined, ensureModifiers(param), elem.name, undefined, ensureType(elem, undefined), undefined)); + elems.push(ts.createProperty( + /*decorators*/ undefined, ensureModifiers(param), elem.name, + /*questionToken*/ undefined, ensureType(elem, /*type*/ undefined), + /*initializer*/ undefined)); } return elems; } @@ -62737,44 +76021,49 @@ var ts; } var members = ts.createNodeArray(ts.concatenate(parameterProperties, ts.visitNodes(input.members, visitDeclarationSubtree))); var extendsClause_1 = ts.getClassExtendsHeritageClauseElement(input); - if (extendsClause_1 && !ts.isEntityNameExpression(extendsClause_1.expression) && extendsClause_1.expression.kind !== 95) { - var newId_1 = ts.createOptimisticUniqueName(ts.unescapeLeadingUnderscores(input.name.escapedText) + "_base"); + if (extendsClause_1 && !ts.isEntityNameExpression(extendsClause_1.expression) && extendsClause_1.expression.kind !== 95 /* NullKeyword */) { + // We must add a temporary declaration for the extends clause expression + var newId_1 = ts.createOptimisticUniqueName(ts.unescapeLeadingUnderscores(input.name.escapedText) + "_base"); // TODO: GH#18217 getSymbolAccessibilityDiagnostic = function () { return ({ diagnosticMessage: ts.Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1, errorNode: extendsClause_1, typeName: input.name }); }; - var varDecl = ts.createVariableDeclaration(newId_1, resolver.createTypeOfExpression(extendsClause_1.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), undefined); - var statement = ts.createVariableStatement(needsDeclare ? [ts.createModifier(124)] : [], ts.createVariableDeclarationList([varDecl], 2)); + var varDecl = ts.createVariableDeclaration(newId_1, resolver.createTypeOfExpression(extendsClause_1.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined); + var statement = ts.createVariableStatement(needsDeclare ? [ts.createModifier(124 /* DeclareKeyword */)] : [], ts.createVariableDeclarationList([varDecl], 2 /* Const */)); var heritageClauses = ts.createNodeArray(ts.map(input.heritageClauses, function (clause) { - if (clause.token === 85) { + if (clause.token === 85 /* ExtendsKeyword */) { var oldDiag_2 = getSymbolAccessibilityDiagnostic; getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNode(clause.types[0]); var newClause = ts.updateHeritageClause(clause, ts.map(clause.types, function (t) { return ts.updateExpressionWithTypeArguments(t, ts.visitNodes(t.typeArguments, visitDeclarationSubtree), newId_1); })); getSymbolAccessibilityDiagnostic = oldDiag_2; return newClause; } - return ts.updateHeritageClause(clause, ts.visitNodes(ts.createNodeArray(ts.filter(clause.types, function (t) { return ts.isEntityNameExpression(t.expression) || t.expression.kind === 95; })), visitDeclarationSubtree)); + return ts.updateHeritageClause(clause, ts.visitNodes(ts.createNodeArray(ts.filter(clause.types, function (t) { return ts.isEntityNameExpression(t.expression) || t.expression.kind === 95 /* NullKeyword */; })), visitDeclarationSubtree)); })); - return [statement, cleanup(ts.updateClassDeclaration(input, undefined, modifiers, input.name, typeParameters, heritageClauses, members))]; + return [statement, cleanup(ts.updateClassDeclaration(input, + /*decorators*/ undefined, modifiers, input.name, typeParameters, heritageClauses, members))]; // TODO: GH#18217 } else { var heritageClauses = transformHeritageClauses(input.heritageClauses); - return cleanup(ts.updateClassDeclaration(input, undefined, modifiers, input.name, typeParameters, heritageClauses, members)); + return cleanup(ts.updateClassDeclaration(input, + /*decorators*/ undefined, modifiers, input.name, typeParameters, heritageClauses, members)); } } - case 214: { + case 214 /* VariableStatement */: { return cleanup(transformVariableStatement(input, isPrivate)); } - case 238: { - return cleanup(ts.updateEnumDeclaration(input, undefined, ts.createNodeArray(ensureModifiers(input, isPrivate)), input.name, ts.createNodeArray(ts.mapDefined(input.members, function (m) { + case 238 /* EnumDeclaration */: { + return cleanup(ts.updateEnumDeclaration(input, /*decorators*/ undefined, ts.createNodeArray(ensureModifiers(input, isPrivate)), input.name, ts.createNodeArray(ts.mapDefined(input.members, function (m) { if (shouldStripInternal(m)) return; + // Rewrite enum values to their constants, if available var constValue = resolver.getConstantValue(m); return preserveJsDoc(ts.updateEnumMember(m, m.name, constValue !== undefined ? ts.createLiteral(constValue) : undefined), m); })))); } } + // Anything left unhandled is an error, so this should be unreachable return ts.Debug.assertNever(input, "Unhandled top-level node in declaration emit: " + ts.SyntaxKind[input.kind]); function cleanup(node) { if (isEnclosingDeclaration(input)) { @@ -62783,7 +76072,7 @@ var ts; if (canProdiceDiagnostic) { getSymbolAccessibilityDiagnostic = oldDiag; } - if (input.kind === 239) { + if (input.kind === 239 /* ModuleDeclaration */) { needsDeclare = previousNeedsDeclare; } if (node === input) { @@ -62804,7 +76093,7 @@ var ts; return ts.flatten(ts.mapDefined(d.elements, function (e) { return recreateBindingElement(e); })); } function recreateBindingElement(e) { - if (e.kind === 206) { + if (e.kind === 206 /* OmittedExpression */) { return; } if (e.name) { @@ -62814,7 +76103,7 @@ var ts; return recreateBindingPattern(e.name); } else { - return ts.createVariableDeclaration(e.name, ensureType(e, undefined), undefined); + return ts.createVariableDeclaration(e.name, ensureType(e, /*type*/ undefined), /*initializer*/ undefined); } } } @@ -62825,7 +76114,7 @@ var ts; getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNodeName(node); } errorNameNode = node.name; - ts.Debug.assert(resolver.isLateBound(ts.getParseTreeNode(node))); + ts.Debug.assert(resolver.isLateBound(ts.getParseTreeNode(node))); // Should only be called with dynamic names var decl = node; var entityName = decl.name.expression; checkEntityNameVisibility(entityName, enclosingDeclaration); @@ -62856,12 +76145,12 @@ var ts; return ts.createModifiersFromModifierFlags(newFlags); } function ensureModifierFlags(node, privateDeclaration) { - var mask = 3071 ^ (4 | 256); - var additions = (needsDeclare && !isAlwaysType(node)) ? 2 : 0; - var parentIsFile = node.parent.kind === 274; + var mask = 3071 /* All */ ^ (4 /* Public */ | 256 /* Async */); // No async modifiers in declaration files + var additions = (needsDeclare && !isAlwaysType(node)) ? 2 /* Ambient */ : 0 /* None */; + var parentIsFile = node.parent.kind === 274 /* SourceFile */; if (!parentIsFile || (isBundledEmit && parentIsFile && ts.isExternalModule(node.parent))) { - mask ^= ((privateDeclaration || (isBundledEmit && parentIsFile) ? 0 : 1) | 512 | 2); - additions = 0; + mask ^= ((privateDeclaration || (isBundledEmit && parentIsFile) ? 0 : 1 /* Export */) | 512 /* Default */ | 2 /* Ambient */); + additions = 0 /* None */; } return maskModifierFlags(node, mask, additions); } @@ -62873,13 +76162,14 @@ var ts; var accessorType = getTypeAnnotationFromAccessor(node); if (!accessorType && accessors.secondAccessor) { accessorType = getTypeAnnotationFromAccessor(accessors.secondAccessor); + // If we end up pulling the type from the second accessor, we also need to change the diagnostic context to get the expected error message getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNode(accessors.secondAccessor); } - var prop = ts.createProperty(undefined, maskModifiers(node, undefined, (!accessors.setAccessor) ? 64 : 0), node.name, node.questionToken, ensureType(node, accessorType), undefined); + var prop = ts.createProperty(/*decorators*/ undefined, maskModifiers(node, /*mask*/ undefined, (!accessors.setAccessor) ? 64 /* Readonly */ : 0 /* None */), node.name, node.questionToken, ensureType(node, accessorType), /*initializer*/ undefined); var leadingsSyntheticCommentRanges = accessors.secondAccessor && ts.getLeadingCommentRangesOfNode(accessors.secondAccessor, currentSourceFile); if (leadingsSyntheticCommentRanges) { var _loop_10 = function (range) { - if (range.kind === 3) { + if (range.kind === 3 /* MultiLineCommentTrivia */) { var text = currentSourceFile.text.slice(range.pos + 2, range.end - 2); var lines = text.split(/\r\n?|\n/g); if (lines.length > 1) { @@ -62899,90 +76189,92 @@ var ts; } function transformHeritageClauses(nodes) { return ts.createNodeArray(ts.filter(ts.map(nodes, function (clause) { return ts.updateHeritageClause(clause, ts.visitNodes(ts.createNodeArray(ts.filter(clause.types, function (t) { - return ts.isEntityNameExpression(t.expression) || (clause.token === 85 && t.expression.kind === 95); + return ts.isEntityNameExpression(t.expression) || (clause.token === 85 /* ExtendsKeyword */ && t.expression.kind === 95 /* NullKeyword */); })), visitDeclarationSubtree)); }), function (clause) { return clause.types && !!clause.types.length; })); } } ts.transformDeclarations = transformDeclarations; function isAlwaysType(node) { - if (node.kind === 236) { + if (node.kind === 236 /* InterfaceDeclaration */) { return true; } return false; } + // Elide "public" modifier, as it is the default function maskModifiers(node, modifierMask, modifierAdditions) { return ts.createModifiersFromModifierFlags(maskModifierFlags(node, modifierMask, modifierAdditions)); } function maskModifierFlags(node, modifierMask, modifierAdditions) { - if (modifierMask === void 0) { modifierMask = 3071 ^ 4; } - if (modifierAdditions === void 0) { modifierAdditions = 0; } + if (modifierMask === void 0) { modifierMask = 3071 /* All */ ^ 4 /* Public */; } + if (modifierAdditions === void 0) { modifierAdditions = 0 /* None */; } var flags = (ts.getModifierFlags(node) & modifierMask) | modifierAdditions; - if (flags & 512 && flags & 2) { - flags ^= 2; + if (flags & 512 /* Default */ && flags & 2 /* Ambient */) { + flags ^= 2 /* Ambient */; // `declare` is never required alongside `default` (and would be an error if printed) } return flags; } function getTypeAnnotationFromAccessor(accessor) { if (accessor) { - return accessor.kind === 156 - ? accessor.type + return accessor.kind === 156 /* GetAccessor */ + ? accessor.type // Getter - return type : accessor.parameters.length > 0 - ? accessor.parameters[0].type + ? accessor.parameters[0].type // Setter parameter type : undefined; } } function canHaveLiteralInitializer(node) { switch (node.kind) { - case 232: - case 152: - case 151: - case 149: + case 232 /* VariableDeclaration */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 149 /* Parameter */: return true; } return false; } function isPreservedDeclarationStatement(node) { switch (node.kind) { - case 234: - case 239: - case 243: - case 236: - case 235: - case 237: - case 238: - case 214: - case 244: - case 250: - case 249: + case 234 /* FunctionDeclaration */: + case 239 /* ModuleDeclaration */: + case 243 /* ImportEqualsDeclaration */: + case 236 /* InterfaceDeclaration */: + case 235 /* ClassDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 238 /* EnumDeclaration */: + case 214 /* VariableStatement */: + case 244 /* ImportDeclaration */: + case 250 /* ExportDeclaration */: + case 249 /* ExportAssignment */: return true; } return false; } function isProcessedComponent(node) { switch (node.kind) { - case 159: - case 155: - case 154: - case 156: - case 157: - case 152: - case 151: - case 153: - case 158: - case 160: - case 232: - case 148: - case 207: - case 162: - case 171: - case 163: - case 164: - case 179: + case 159 /* ConstructSignature */: + case 155 /* Constructor */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 153 /* MethodSignature */: + case 158 /* CallSignature */: + case 160 /* IndexSignature */: + case 232 /* VariableDeclaration */: + case 148 /* TypeParameter */: + case 207 /* ExpressionWithTypeArguments */: + case 162 /* TypeReference */: + case 171 /* ConditionalType */: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 179 /* ImportType */: return true; } return false; } })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { function getModuleTransformer(moduleKind) { @@ -63015,32 +76307,44 @@ var ts; var transformers = []; ts.addRange(transformers, customTransformers && customTransformers.before); transformers.push(ts.transformTypeScript); - if (jsx === 2) { + if (jsx === 2 /* React */) { transformers.push(ts.transformJsx); } - if (languageVersion < 6) { + if (languageVersion < 6 /* ESNext */) { transformers.push(ts.transformESNext); } - if (languageVersion < 4) { + if (languageVersion < 4 /* ES2017 */) { transformers.push(ts.transformES2017); } - if (languageVersion < 3) { + if (languageVersion < 3 /* ES2016 */) { transformers.push(ts.transformES2016); } - if (languageVersion < 2) { + if (languageVersion < 2 /* ES2015 */) { transformers.push(ts.transformES2015); transformers.push(ts.transformGenerators); } transformers.push(getModuleTransformer(moduleKind)); - if (languageVersion < 1) { + // The ES5 transformer is last so that it can substitute expressions like `exports.default` + // for ES3. + if (languageVersion < 1 /* ES5 */) { transformers.push(ts.transformES5); } ts.addRange(transformers, customTransformers && customTransformers.after); return transformers; } ts.getTransformers = getTransformers; + /** + * Transforms an array of SourceFiles by passing them through each transformer. + * + * @param resolver The emit resolver provided by the checker. + * @param host The emit host object used to interact with the file system. + * @param options Compiler options to surface in the `TransformationContext`. + * @param nodes An array of nodes to transform. + * @param transforms An array of `TransformerFactory` callbacks. + * @param allowDtsFiles A value indicating whether to allow the transformation of .d.ts files. + */ function transformNodes(resolver, host, options, nodes, transformers, allowDtsFiles) { - var enabledSyntaxKindFeatures = new Array(306); + var enabledSyntaxKindFeatures = new Array(306 /* Count */); var lexicalEnvironmentVariableDeclarations; var lexicalEnvironmentFunctionDeclarations; var lexicalEnvironmentVariableDeclarationsStack = []; @@ -63050,8 +76354,10 @@ var ts; var emitHelpers; var onSubstituteNode = function (_, node) { return node; }; var onEmitNode = function (hint, node, callback) { return callback(hint, node); }; - var state = 0; + var state = 0 /* Uninitialized */; var diagnostics = []; + // The transformation context is provided to each transformer as part of transformer + // initialization. var context = { getCompilerOptions: function () { return options; }, getEmitResolver: function () { return resolver; }, @@ -63070,13 +76376,13 @@ var ts; isEmitNotificationEnabled: isEmitNotificationEnabled, get onSubstituteNode() { return onSubstituteNode; }, set onSubstituteNode(value) { - ts.Debug.assert(state < 1, "Cannot modify transformation hooks after initialization has completed."); + ts.Debug.assert(state < 1 /* Initialized */, "Cannot modify transformation hooks after initialization has completed."); ts.Debug.assert(value !== undefined, "Value must not be 'undefined'"); onSubstituteNode = value; }, get onEmitNode() { return onEmitNode; }, set onEmitNode(value) { - ts.Debug.assert(state < 1, "Cannot modify transformation hooks after initialization has completed."); + ts.Debug.assert(state < 1 /* Initialized */, "Cannot modify transformation hooks after initialization has completed."); ts.Debug.assert(value !== undefined, "Value must not be 'undefined'"); onEmitNode = value; }, @@ -63084,15 +76390,20 @@ var ts; diagnostics.push(diag); } }; + // Ensure the parse tree is clean before applying transformations for (var _i = 0, nodes_4 = nodes; _i < nodes_4.length; _i++) { var node = nodes_4[_i]; ts.disposeEmitNodes(ts.getSourceFileOfNode(ts.getParseTreeNode(node))); } ts.performance.mark("beforeTransform"); + // Chain together and initialize each transformer. var transformation = ts.chain.apply(void 0, transformers)(context); - state = 1; + // prevent modification of transformation hooks. + state = 1 /* Initialized */; + // Transform each node. var transformed = ts.map(nodes, allowDtsFiles ? transformation : transformRoot); - state = 2; + // prevent modification of the lexical environment. + state = 2 /* Completed */; ts.performance.mark("afterTransform"); ts.performance.measure("transformTime", "beforeTransform", "afterTransform"); return { @@ -63105,28 +76416,55 @@ var ts; function transformRoot(node) { return node && (!ts.isSourceFile(node) || !node.isDeclarationFile) ? transformation(node) : node; } + /** + * Enables expression substitutions in the pretty printer for the provided SyntaxKind. + */ function enableSubstitution(kind) { - ts.Debug.assert(state < 2, "Cannot modify the transformation context after transformation has completed."); - enabledSyntaxKindFeatures[kind] |= 1; + ts.Debug.assert(state < 2 /* Completed */, "Cannot modify the transformation context after transformation has completed."); + enabledSyntaxKindFeatures[kind] |= 1 /* Substitution */; } + /** + * Determines whether expression substitutions are enabled for the provided node. + */ function isSubstitutionEnabled(node) { - return (enabledSyntaxKindFeatures[node.kind] & 1) !== 0 - && (ts.getEmitFlags(node) & 4) === 0; + return (enabledSyntaxKindFeatures[node.kind] & 1 /* Substitution */) !== 0 + && (ts.getEmitFlags(node) & 4 /* NoSubstitution */) === 0; } + /** + * Emits a node with possible substitution. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emitCallback The callback used to emit the node or its substitute. + */ function substituteNode(hint, node) { - ts.Debug.assert(state < 3, "Cannot substitute a node after the result is disposed."); + ts.Debug.assert(state < 3 /* Disposed */, "Cannot substitute a node after the result is disposed."); return node && isSubstitutionEnabled(node) && onSubstituteNode(hint, node) || node; } + /** + * Enables before/after emit notifications in the pretty printer for the provided SyntaxKind. + */ function enableEmitNotification(kind) { - ts.Debug.assert(state < 2, "Cannot modify the transformation context after transformation has completed."); - enabledSyntaxKindFeatures[kind] |= 2; + ts.Debug.assert(state < 2 /* Completed */, "Cannot modify the transformation context after transformation has completed."); + enabledSyntaxKindFeatures[kind] |= 2 /* EmitNotifications */; } + /** + * Determines whether before/after emit notifications should be raised in the pretty + * printer when it emits a node. + */ function isEmitNotificationEnabled(node) { - return (enabledSyntaxKindFeatures[node.kind] & 2) !== 0 - || (ts.getEmitFlags(node) & 2) !== 0; + return (enabledSyntaxKindFeatures[node.kind] & 2 /* EmitNotifications */) !== 0 + || (ts.getEmitFlags(node) & 2 /* AdviseOnEmitNode */) !== 0; } + /** + * Emits a node with possible emit notification. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emitCallback The callback used to emit the node. + */ function emitNodeWithNotification(hint, node, emitCallback) { - ts.Debug.assert(state < 3, "Cannot invoke TransformationResult callbacks after the result is disposed."); + ts.Debug.assert(state < 3 /* Disposed */, "Cannot invoke TransformationResult callbacks after the result is disposed."); if (node) { if (isEmitNotificationEnabled(node)) { onEmitNode(hint, node, emitCallback); @@ -63136,10 +76474,13 @@ var ts; } } } + /** + * Records a hoisted variable declaration for the provided name within a lexical environment. + */ function hoistVariableDeclaration(name) { - ts.Debug.assert(state > 0, "Cannot modify the lexical environment during initialization."); - ts.Debug.assert(state < 2, "Cannot modify the lexical environment after transformation has completed."); - var decl = ts.setEmitFlags(ts.createVariableDeclaration(name), 64); + ts.Debug.assert(state > 0 /* Uninitialized */, "Cannot modify the lexical environment during initialization."); + ts.Debug.assert(state < 2 /* Completed */, "Cannot modify the lexical environment after transformation has completed."); + var decl = ts.setEmitFlags(ts.createVariableDeclaration(name), 64 /* NoNestedSourceMaps */); if (!lexicalEnvironmentVariableDeclarations) { lexicalEnvironmentVariableDeclarations = [decl]; } @@ -63147,9 +76488,12 @@ var ts; lexicalEnvironmentVariableDeclarations.push(decl); } } + /** + * Records a hoisted function declaration within a lexical environment. + */ function hoistFunctionDeclaration(func) { - ts.Debug.assert(state > 0, "Cannot modify the lexical environment during initialization."); - ts.Debug.assert(state < 2, "Cannot modify the lexical environment after transformation has completed."); + ts.Debug.assert(state > 0 /* Uninitialized */, "Cannot modify the lexical environment during initialization."); + ts.Debug.assert(state < 2 /* Completed */, "Cannot modify the lexical environment after transformation has completed."); if (!lexicalEnvironmentFunctionDeclarations) { lexicalEnvironmentFunctionDeclarations = [func]; } @@ -63157,31 +76501,45 @@ var ts; lexicalEnvironmentFunctionDeclarations.push(func); } } + /** + * Starts a new lexical environment. Any existing hoisted variable or function declarations + * are pushed onto a stack, and the related storage variables are reset. + */ function startLexicalEnvironment() { - ts.Debug.assert(state > 0, "Cannot modify the lexical environment during initialization."); - ts.Debug.assert(state < 2, "Cannot modify the lexical environment after transformation has completed."); + ts.Debug.assert(state > 0 /* Uninitialized */, "Cannot modify the lexical environment during initialization."); + ts.Debug.assert(state < 2 /* Completed */, "Cannot modify the lexical environment after transformation has completed."); ts.Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended."); + // Save the current lexical environment. Rather than resizing the array we adjust the + // stack size variable. This allows us to reuse existing array slots we've + // already allocated between transformations to avoid allocation and GC overhead during + // transformation. lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentVariableDeclarations; lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentFunctionDeclarations; lexicalEnvironmentStackOffset++; lexicalEnvironmentVariableDeclarations = undefined; lexicalEnvironmentFunctionDeclarations = undefined; } + /** Suspends the current lexical environment, usually after visiting a parameter list. */ function suspendLexicalEnvironment() { - ts.Debug.assert(state > 0, "Cannot modify the lexical environment during initialization."); - ts.Debug.assert(state < 2, "Cannot modify the lexical environment after transformation has completed."); + ts.Debug.assert(state > 0 /* Uninitialized */, "Cannot modify the lexical environment during initialization."); + ts.Debug.assert(state < 2 /* Completed */, "Cannot modify the lexical environment after transformation has completed."); ts.Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is already suspended."); lexicalEnvironmentSuspended = true; } + /** Resumes a suspended lexical environment, usually before visiting a function body. */ function resumeLexicalEnvironment() { - ts.Debug.assert(state > 0, "Cannot modify the lexical environment during initialization."); - ts.Debug.assert(state < 2, "Cannot modify the lexical environment after transformation has completed."); + ts.Debug.assert(state > 0 /* Uninitialized */, "Cannot modify the lexical environment during initialization."); + ts.Debug.assert(state < 2 /* Completed */, "Cannot modify the lexical environment after transformation has completed."); ts.Debug.assert(lexicalEnvironmentSuspended, "Lexical environment is not suspended."); lexicalEnvironmentSuspended = false; } + /** + * Ends a lexical environment. The previous set of hoisted declarations are restored and + * any hoisted declarations added in this environment are returned. + */ function endLexicalEnvironment() { - ts.Debug.assert(state > 0, "Cannot modify the lexical environment during initialization."); - ts.Debug.assert(state < 2, "Cannot modify the lexical environment after transformation has completed."); + ts.Debug.assert(state > 0 /* Uninitialized */, "Cannot modify the lexical environment during initialization."); + ts.Debug.assert(state < 2 /* Completed */, "Cannot modify the lexical environment after transformation has completed."); ts.Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended."); var statements; if (lexicalEnvironmentVariableDeclarations || lexicalEnvironmentFunctionDeclarations) { @@ -63189,7 +76547,8 @@ var ts; statements = lexicalEnvironmentFunctionDeclarations.slice(); } if (lexicalEnvironmentVariableDeclarations) { - var statement = ts.createVariableStatement(undefined, ts.createVariableDeclarationList(lexicalEnvironmentVariableDeclarations)); + var statement = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList(lexicalEnvironmentVariableDeclarations)); if (!statements) { statements = [statement]; } @@ -63198,6 +76557,7 @@ var ts; } } } + // Restore the previous lexical environment. lexicalEnvironmentStackOffset--; lexicalEnvironmentVariableDeclarations = lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset]; lexicalEnvironmentFunctionDeclarations = lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset]; @@ -63208,24 +76568,26 @@ var ts; return statements; } function requestEmitHelper(helper) { - ts.Debug.assert(state > 0, "Cannot modify the transformation context during initialization."); - ts.Debug.assert(state < 2, "Cannot modify the transformation context after transformation has completed."); + ts.Debug.assert(state > 0 /* Uninitialized */, "Cannot modify the transformation context during initialization."); + ts.Debug.assert(state < 2 /* Completed */, "Cannot modify the transformation context after transformation has completed."); ts.Debug.assert(!helper.scoped, "Cannot request a scoped emit helper."); emitHelpers = ts.append(emitHelpers, helper); } function readEmitHelpers() { - ts.Debug.assert(state > 0, "Cannot modify the transformation context during initialization."); - ts.Debug.assert(state < 2, "Cannot modify the transformation context after transformation has completed."); + ts.Debug.assert(state > 0 /* Uninitialized */, "Cannot modify the transformation context during initialization."); + ts.Debug.assert(state < 2 /* Completed */, "Cannot modify the transformation context after transformation has completed."); var helpers = emitHelpers; emitHelpers = undefined; return helpers; } function dispose() { - if (state < 3) { + if (state < 3 /* Disposed */) { + // Clean up emit nodes on parse tree for (var _i = 0, nodes_5 = nodes; _i < nodes_5.length; _i++) { var node = nodes_5[_i]; ts.disposeEmitNodes(ts.getSourceFileOfNode(ts.getParseTreeNode(node))); } + // Release references to external entries for GC purposes. lexicalEnvironmentVariableDeclarations = undefined; lexicalEnvironmentVariableDeclarationsStack = undefined; lexicalEnvironmentFunctionDeclarations = undefined; @@ -63233,14 +76595,17 @@ var ts; onSubstituteNode = undefined; onEmitNode = undefined; emitHelpers = undefined; - state = 3; + // Prevent further use of the transformation result. + state = 3 /* Disposed */; } } } ts.transformNodes = transformNodes; })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { + // Used for initialize lastEncodedSourceMapSpan and reset lastEncodedSourceMapSpan when updateLastEncodedAndRecordedSpans var defaultLastEncodedSourceMapSpan = { emittedLine: 0, emittedColumn: 0, @@ -63253,11 +76618,14 @@ var ts; var extendedDiagnostics = compilerOptions.extendedDiagnostics; var currentSource; var currentSourceText; - var sourceMapDir; + var sourceMapDir; // The directory in which sourcemap will be + // Current source map file and its index in the sources list var sourceMapSourceIndex; + // Last recorded and encoded spans var lastRecordedSourceMapSpan; var lastEncodedSourceMapSpan; var lastEncodedNameIndex; + // Source map data var sourceMapData; var sourceMapDataList; var disabled = !(compilerOptions.sourceMap || compilerOptions.inlineSourceMap); @@ -63271,11 +76639,21 @@ var ts; getText: getText, getSourceMappingURL: getSourceMappingURL, }; + /** + * Skips trivia such as comments and white-space that can optionally overriden by the source map source + */ function skipSourceTrivia(pos) { return currentSource.skipTrivia ? currentSource.skipTrivia(pos) : ts.skipTrivia(currentSourceText, pos); } + /** + * Initialize the SourceMapWriter for a new output file. + * + * @param filePath The path to the generated output file. + * @param sourceMapFilePath The path to the output source map file. + * @param sourceFileOrBundle The input source file or bundle for the program. + */ function initialize(filePath, sourceMapFilePath, sourceFileOrBundle, outputSourceMapDataList) { - if (disabled || ts.fileExtensionIs(filePath, ".json")) { + if (disabled || ts.fileExtensionIs(filePath, ".json" /* Json */)) { return; } if (sourceMapData) { @@ -63284,10 +76662,13 @@ var ts; sourceMapDataList = outputSourceMapDataList; currentSource = undefined; currentSourceText = undefined; + // Current source map file and its index in the sources list sourceMapSourceIndex = -1; + // Last recorded and encoded spans lastRecordedSourceMapSpan = undefined; lastEncodedSourceMapSpan = defaultLastEncodedSourceMapSpan; lastEncodedNameIndex = 0; + // Initialize source map data sourceMapData = { sourceMapFilePath: sourceMapFilePath, jsSourceMappingURL: !compilerOptions.inlineSourceMap ? ts.getBaseFileName(ts.normalizeSlashes(sourceMapFilePath)) : undefined, @@ -63300,18 +76681,26 @@ var ts; sourceMapSourcesContent: compilerOptions.inlineSources ? [] : undefined, sourceMapDecodedMappings: [] }; + // Normalize source root and make sure it has trailing "/" so that it can be used to combine paths with the + // relative paths of the sources list in the sourcemap sourceMapData.sourceMapSourceRoot = ts.normalizeSlashes(sourceMapData.sourceMapSourceRoot); - if (sourceMapData.sourceMapSourceRoot.length && sourceMapData.sourceMapSourceRoot.charCodeAt(sourceMapData.sourceMapSourceRoot.length - 1) !== 47) { + if (sourceMapData.sourceMapSourceRoot.length && sourceMapData.sourceMapSourceRoot.charCodeAt(sourceMapData.sourceMapSourceRoot.length - 1) !== 47 /* slash */) { sourceMapData.sourceMapSourceRoot += ts.directorySeparator; } if (compilerOptions.mapRoot) { sourceMapDir = ts.normalizeSlashes(compilerOptions.mapRoot); - if (sourceFileOrBundle.kind === 274) { + if (sourceFileOrBundle.kind === 274 /* SourceFile */) { // emitting single module file + // For modules or multiple emit files the mapRoot will have directory structure like the sources + // So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map sourceMapDir = ts.getDirectoryPath(ts.getSourceFilePathInNewDir(sourceFileOrBundle, host, sourceMapDir)); } if (!ts.isRootedDiskPath(sourceMapDir) && !ts.isUrl(sourceMapDir)) { + // The relative paths are relative to the common directory sourceMapDir = ts.combinePaths(host.getCommonSourceDirectory(), sourceMapDir); - sourceMapData.jsSourceMappingURL = ts.getRelativePathToDirectoryOrUrl(ts.getDirectoryPath(ts.normalizePath(filePath)), ts.combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), host.getCurrentDirectory(), host.getCanonicalFileName, true); + sourceMapData.jsSourceMappingURL = ts.getRelativePathToDirectoryOrUrl(ts.getDirectoryPath(ts.normalizePath(filePath)), // get the relative sourceMapDir path based on jsFilePath + ts.combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), // this is where user expects to see sourceMap + host.getCurrentDirectory(), host.getCanonicalFileName, + /*isAbsolutePathAnUrl*/ true); } else { sourceMapData.jsSourceMappingURL = ts.combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL); @@ -63321,10 +76710,14 @@ var ts; sourceMapDir = ts.getDirectoryPath(ts.normalizePath(filePath)); } } + /** + * Reset the SourceMapWriter to an empty state. + */ function reset() { if (disabled) { return; } + // Record source map data for the test harness. if (sourceMapDataList) { sourceMapDataList.push(sourceMapData); } @@ -63348,6 +76741,7 @@ var ts; sourcesContent: sourceMapData.sourceMapSourcesContent, }; } + // Encoding for sourcemap span function encodeLastRecordedSourceMapSpan() { if (!lastRecordedSourceMapSpan || lastRecordedSourceMapSpan === lastEncodedSourceMapSpan) { return; @@ -63357,21 +76751,29 @@ var ts; ts.Debug.assert(lastRecordedSourceMapSpan.sourceLine >= 0, "lastEncodedSourceMapSpan.sourceLine was negative"); ts.Debug.assert(lastRecordedSourceMapSpan.sourceColumn >= 0, "lastEncodedSourceMapSpan.sourceColumn was negative"); var prevEncodedEmittedColumn = lastEncodedSourceMapSpan.emittedColumn; + // Line/Comma delimiters if (lastEncodedSourceMapSpan.emittedLine === lastRecordedSourceMapSpan.emittedLine) { + // Emit comma to separate the entry if (sourceMapData.sourceMapMappings) { sourceMapData.sourceMapMappings += ","; } } else { + // Emit line delimiters for (var encodedLine = lastEncodedSourceMapSpan.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) { sourceMapData.sourceMapMappings += ";"; } prevEncodedEmittedColumn = 0; } + // 1. Relative Column 0 based sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.emittedColumn - prevEncodedEmittedColumn); + // 2. Relative sourceIndex sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceIndex - lastEncodedSourceMapSpan.sourceIndex); + // 3. Relative sourceLine 0 based sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceLine - lastEncodedSourceMapSpan.sourceLine); + // 4. Relative sourceColumn 0 based sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceColumn - lastEncodedSourceMapSpan.sourceColumn); + // 5. Relative namePosition 0 based if (lastRecordedSourceMapSpan.nameIndex >= 0) { ts.Debug.assert(false, "We do not support name index right now, Make sure to update updateLastEncodedAndRecordedSpans when we start using this"); sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.nameIndex - lastEncodedNameIndex); @@ -63380,6 +76782,14 @@ var ts; lastEncodedSourceMapSpan = lastRecordedSourceMapSpan; sourceMapData.sourceMapDecodedMappings.push(lastEncodedSourceMapSpan); } + /** + * Emits a mapping. + * + * If the position is synthetic (undefined or a negative value), no mapping will be + * created. + * + * @param pos The position. + */ function emitPos(pos) { if (disabled || ts.positionIsSynthesized(pos) || isJsonSourceMapSource(currentSource)) { return; @@ -63390,13 +76800,16 @@ var ts; var sourceLinePos = ts.getLineAndCharacterOfPosition(currentSource, pos); var emittedLine = writer.getLine(); var emittedColumn = writer.getColumn(); + // If this location wasn't recorded or the location in source is going backwards, record the span if (!lastRecordedSourceMapSpan || lastRecordedSourceMapSpan.emittedLine !== emittedLine || lastRecordedSourceMapSpan.emittedColumn !== emittedColumn || (lastRecordedSourceMapSpan.sourceIndex === sourceMapSourceIndex && (lastRecordedSourceMapSpan.sourceLine > sourceLinePos.line || (lastRecordedSourceMapSpan.sourceLine === sourceLinePos.line && lastRecordedSourceMapSpan.sourceColumn > sourceLinePos.character)))) { + // Encode the last recordedSpan before assigning new encodeLastRecordedSourceMapSpan(); + // New span lastRecordedSourceMapSpan = { emittedLine: emittedLine, emittedColumn: emittedColumn, @@ -63406,6 +76819,7 @@ var ts; }; } else { + // Take the new pos instead since there is no change in emittedLine and column since last location lastRecordedSourceMapSpan.sourceLine = sourceLinePos.line; lastRecordedSourceMapSpan.sourceColumn = sourceLinePos.character; lastRecordedSourceMapSpan.sourceIndex = sourceMapSourceIndex; @@ -63418,6 +76832,13 @@ var ts; function isPossiblySourceMap(x) { return typeof x === "object" && !!x.mappings && typeof x.mappings === "string" && !!x.sources; } + /** + * Emits a node with possible leading and trailing source maps. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emitCallback The callback used to emit the node. + */ function emitNodeWithSourceMap(hint, node, emitCallback) { if (disabled || ts.isInJsonFile(node)) { return emitCallback(hint, node); @@ -63430,29 +76851,40 @@ var ts; parsed = JSON.parse(text); } catch (_a) { + // empty } if (!parsed || !isPossiblySourceMap(parsed)) { return emitCallback(hint, node); } var offsetLine_1 = writer.getLine(); var firstLineColumnOffset_1 = writer.getColumn(); + // First, decode the old component sourcemap var originalMap_1 = parsed; + var sourcesDirectoryPath_1 = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir; + var resolvedPathCache_1 = ts.createMap(); ts.sourcemaps.calculateDecodedMappings(originalMap_1, function (raw) { + // Apply offsets to each position and fixup source entries var rawPath = originalMap_1.sources[raw.sourceIndex]; var relativePath = originalMap_1.sourceRoot ? ts.combinePaths(originalMap_1.sourceRoot, rawPath) : rawPath; var combinedPath = ts.combinePaths(ts.getDirectoryPath(node.sourceMapPath), relativePath); - var sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir; - var resolvedPath = ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, combinedPath, host.getCurrentDirectory(), host.getCanonicalFileName, true); - var absolutePath = ts.getNormalizedAbsolutePath(resolvedPath, sourcesDirectoryPath); - setupSourceEntry(absolutePath, originalMap_1.sourcesContent ? originalMap_1.sourcesContent[raw.sourceIndex] : null); + if (!resolvedPathCache_1.has(combinedPath)) { + resolvedPathCache_1.set(combinedPath, ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath_1, combinedPath, host.getCurrentDirectory(), host.getCanonicalFileName, + /*isAbsolutePathAnUrl*/ true)); + } + var resolvedPath = resolvedPathCache_1.get(combinedPath); + var absolutePath = ts.getNormalizedAbsolutePath(resolvedPath, sourcesDirectoryPath_1); + // tslint:disable-next-line:no-null-keyword + setupSourceEntry(absolutePath, originalMap_1.sourcesContent ? originalMap_1.sourcesContent[raw.sourceIndex] : null); // TODO: Lookup content for inlining? var newIndex = sourceMapData.sourceMapSources.indexOf(resolvedPath); + // Then reencode all the updated spans into the overall map encodeLastRecordedSourceMapSpan(); lastRecordedSourceMapSpan = __assign({}, raw, { emittedLine: raw.emittedLine + offsetLine_1, emittedColumn: raw.emittedLine === 0 ? (raw.emittedColumn + firstLineColumnOffset_1) : raw.emittedColumn, sourceIndex: newIndex }); }); + // And actually emit the text these sourcemaps are for return emitCallback(hint, node); } var emitNode = node.emitNode; - var emitFlags = emitNode && emitNode.flags || 0; + var emitFlags = emitNode && emitNode.flags || 0 /* None */; var range = emitNode && emitNode.sourceMapRange; var _b = range || node, pos = _b.pos, end = _b.end; var source = range && range.source; @@ -63461,14 +76893,14 @@ var ts; source = undefined; if (source) setSourceFile(source); - if (node.kind !== 301 - && (emitFlags & 16) === 0 + if (node.kind !== 301 /* NotEmittedStatement */ + && (emitFlags & 16 /* NoLeadingSourceMap */) === 0 && pos >= 0) { emitPos(skipSourceTrivia(pos)); } if (source) setSourceFile(oldSource); - if (emitFlags & 64) { + if (emitFlags & 64 /* NoNestedSourceMaps */) { disabled = true; emitCallback(hint, node); disabled = false; @@ -63478,8 +76910,8 @@ var ts; } if (source) setSourceFile(source); - if (node.kind !== 301 - && (emitFlags & 32) === 0 + if (node.kind !== 301 /* NotEmittedStatement */ + && (emitFlags & 32 /* NoTrailingSourceMap */) === 0 && end >= 0) { emitPos(end); } @@ -63487,28 +76919,41 @@ var ts; setSourceFile(oldSource); } } + /** + * Emits a token of a node with possible leading and trailing source maps. + * + * @param node The node containing the token. + * @param token The token to emit. + * @param tokenStartPos The start pos of the token. + * @param emitCallback The callback used to emit the token. + */ function emitTokenWithSourceMap(node, token, writer, tokenPos, emitCallback) { if (disabled || ts.isInJsonFile(node)) { return emitCallback(token, writer, tokenPos); } var emitNode = node && node.emitNode; - var emitFlags = emitNode && emitNode.flags || 0; + var emitFlags = emitNode && emitNode.flags || 0 /* None */; var range = emitNode && emitNode.tokenSourceMapRanges && emitNode.tokenSourceMapRanges[token]; tokenPos = skipSourceTrivia(range ? range.pos : tokenPos); - if ((emitFlags & 128) === 0 && tokenPos >= 0) { + if ((emitFlags & 128 /* NoTokenLeadingSourceMaps */) === 0 && tokenPos >= 0) { emitPos(tokenPos); } tokenPos = emitCallback(token, writer, tokenPos); if (range) tokenPos = range.end; - if ((emitFlags & 256) === 0 && tokenPos >= 0) { + if ((emitFlags & 256 /* NoTokenTrailingSourceMaps */) === 0 && tokenPos >= 0) { emitPos(tokenPos); } return tokenPos; } function isJsonSourceMapSource(sourceFile) { - return ts.fileExtensionIs(sourceFile.fileName, ".json"); + return ts.fileExtensionIs(sourceFile.fileName, ".json" /* Json */); } + /** + * Set the current source file. + * + * @param sourceFile The source file. + */ function setSourceFile(sourceFile) { if (disabled) { return; @@ -63521,30 +76966,42 @@ var ts; setupSourceEntry(sourceFile.fileName, sourceFile.text); } function setupSourceEntry(fileName, content) { + // Add the file to tsFilePaths + // If sourceroot option: Use the relative path corresponding to the common directory path + // otherwise source locations relative to map file location var sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir; - var source = ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, fileName, host.getCurrentDirectory(), host.getCanonicalFileName, true); + var source = ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, fileName, host.getCurrentDirectory(), host.getCanonicalFileName, + /*isAbsolutePathAnUrl*/ true); sourceMapSourceIndex = sourceMapData.sourceMapSources.indexOf(source); if (sourceMapSourceIndex === -1) { sourceMapSourceIndex = sourceMapData.sourceMapSources.length; sourceMapData.sourceMapSources.push(source); + // The one that can be used from program to get the actual source file sourceMapData.inputSourceFileNames.push(fileName); if (compilerOptions.inlineSources) { sourceMapData.sourceMapSourcesContent.push(content); } } } + /** + * Gets the text for the source map. + */ function getText() { if (disabled || isJsonSourceMapSource(currentSource)) { - return undefined; + return undefined; // TODO: GH#18217 } encodeLastRecordedSourceMapSpan(); return JSON.stringify(captureSection()); } + /** + * Gets the SourceMappingURL for the source map. + */ function getSourceMappingURL() { if (disabled || isJsonSourceMapSource(currentSource)) { - return undefined; + return undefined; // TODO: GH#18217 } if (compilerOptions.inlineSourceMap) { + // Encode the sourceMap into the sourceMap url var base64SourceMapText = ts.base64encode(ts.sys, getText()); return sourceMapData.jsSourceMappingURL = "data:application/json;base64," + base64SourceMapText; } @@ -63562,17 +77019,24 @@ var ts; throw TypeError(inValue + ": not a 64 based value"); } function base64VLQFormatEncode(inValue) { + // Add a new least significant bit that has the sign of the value. + // if negative number the least significant bit that gets added to the number has value 1 + // else least significant bit value that gets added is 0 + // eg. -1 changes to binary : 01 [1] => 3 + // +1 changes to binary : 01 [0] => 2 if (inValue < 0) { inValue = ((-inValue) << 1) + 1; } else { inValue = inValue << 1; } + // Encode 5 bits at a time starting from least significant bits var encodedStr = ""; do { - var currentDigit = inValue & 31; + var currentDigit = inValue & 31; // 11111 inValue = inValue >> 5; if (inValue > 0) { + // There are still more digits to decode, set the msb (6th bit) currentDigit = currentDigit | 32; } encodedStr = encodedStr + base64FormatEncode(currentDigit); @@ -63580,6 +77044,7 @@ var ts; return encodedStr; } })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { function createCommentWriter(printerOptions, emitPos) { @@ -63615,18 +77080,24 @@ var ts; var emitFlags = emitNode && emitNode.flags || 0; var _a = emitNode && emitNode.commentRange || node, pos = _a.pos, end = _a.end; if ((pos < 0 && end < 0) || (pos === end)) { + // Both pos and end are synthesized, so just emit the node without comments. emitNodeWithSynthesizedComments(hint, node, emitNode, emitFlags, emitCallback); } else { if (extendedDiagnostics) { ts.performance.mark("preEmitNodeWithComment"); } - var isEmittedNode = node.kind !== 301; - var skipLeadingComments = pos < 0 || (emitFlags & 512) !== 0 || node.kind === 10; - var skipTrailingComments = end < 0 || (emitFlags & 1024) !== 0 || node.kind === 10; + var isEmittedNode = node.kind !== 301 /* NotEmittedStatement */; + // We have to explicitly check that the node is JsxText because if the compilerOptions.jsx is "preserve" we will not do any transformation. + // It is expensive to walk entire tree just to set one kind of node to have no comments. + var skipLeadingComments = pos < 0 || (emitFlags & 512 /* NoLeadingComments */) !== 0 || node.kind === 10 /* JsxText */; + var skipTrailingComments = end < 0 || (emitFlags & 1024 /* NoTrailingComments */) !== 0 || node.kind === 10 /* JsxText */; + // Emit leading comments if the position is not synthesized and the node + // has not opted out from emitting leading comments. if (!skipLeadingComments) { emitLeadingComments(pos, isEmittedNode); } + // Save current container state on the stack. var savedContainerPos = containerPos; var savedContainerEnd = containerEnd; var savedDeclarationListContainerEnd = declarationListContainerEnd; @@ -63635,7 +77106,9 @@ var ts; } if (!skipTrailingComments) { containerEnd = end; - if (node.kind === 233) { + // To avoid invalid comment emit in a down-level binding pattern, we + // keep track of the last declaration list container's end + if (node.kind === 233 /* VariableDeclarationList */) { declarationListContainerEnd = end; } } @@ -63646,9 +77119,12 @@ var ts; if (extendedDiagnostics) { ts.performance.mark("postEmitNodeWithComment"); } + // Restore previous container state. containerPos = savedContainerPos; containerEnd = savedContainerEnd; declarationListContainerEnd = savedDeclarationListContainerEnd; + // Emit trailing comments if the position is not synthesized and the node + // has not opted out from emitting leading comments and is an emitted node. if (!skipTrailingComments && isEmittedNode) { emitTrailingComments(end); } @@ -63682,11 +77158,11 @@ var ts; } } function emitLeadingSynthesizedComment(comment) { - if (comment.kind === 2) { + if (comment.kind === 2 /* SingleLineCommentTrivia */) { writer.writeLine(); } writeSynthesizedComment(comment); - if (comment.hasTrailingNewLine || comment.kind === 2) { + if (comment.hasTrailingNewLine || comment.kind === 2 /* SingleLineCommentTrivia */) { writer.writeLine(); } else { @@ -63704,16 +77180,16 @@ var ts; } function writeSynthesizedComment(comment) { var text = formatSynthesizedComment(comment); - var lineMap = comment.kind === 3 ? ts.computeLineStarts(text) : undefined; + var lineMap = comment.kind === 3 /* MultiLineCommentTrivia */ ? ts.computeLineStarts(text) : undefined; ts.writeCommentRange(text, lineMap, writer, 0, text.length, newLine); } function formatSynthesizedComment(comment) { - return comment.kind === 3 + return comment.kind === 3 /* MultiLineCommentTrivia */ ? "/*" + comment.text + "*/" : "//" + comment.text; } function emitNodeWithNestedComments(hint, node, emitFlags, emitCallback) { - if (emitFlags & 2048) { + if (emitFlags & 2048 /* NoNestedComments */) { disabled = true; emitCallback(hint, node); disabled = false; @@ -63728,15 +77204,15 @@ var ts; } var pos = detachedRange.pos, end = detachedRange.end; var emitFlags = ts.getEmitFlags(node); - var skipLeadingComments = pos < 0 || (emitFlags & 512) !== 0; - var skipTrailingComments = disabled || end < 0 || (emitFlags & 1024) !== 0; + var skipLeadingComments = pos < 0 || (emitFlags & 512 /* NoLeadingComments */) !== 0; + var skipTrailingComments = disabled || end < 0 || (emitFlags & 1024 /* NoTrailingComments */) !== 0; if (!skipLeadingComments) { emitDetachedCommentsAndUpdateCommentsInfo(detachedRange); } if (extendedDiagnostics) { ts.performance.measure("commentTime", "preEmitBodyWithDetachedComments"); } - if (emitFlags & 2048 && !disabled) { + if (emitFlags & 2048 /* NoNestedComments */ && !disabled) { disabled = true; emitCallback(node); disabled = false; @@ -63748,7 +77224,7 @@ var ts; ts.performance.mark("beginEmitBodyWithDetachedCommetns"); } if (!skipTrailingComments) { - emitLeadingComments(detachedRange.end, true); + emitLeadingComments(detachedRange.end, /*isEmittedNode*/ true); if (hasWrittenComment && !writer.isAtStartOfLine()) { writer.writeLine(); } @@ -63763,6 +77239,14 @@ var ts; forEachLeadingCommentToEmit(pos, emitLeadingComment); } else if (pos === 0) { + // If the node will not be emitted in JS, remove all the comments(normal, pinned and ///) associated with the node, + // unless it is a triple slash comment at the top of the file. + // For Example: + // /// + // declare var x; + // /// + // interface F {} + // The first /// will NOT be removed while the second one will be removed even though both node will not be emitted forEachLeadingCommentToEmit(pos, emitTripleSlashLeadingComment); } } @@ -63784,6 +77268,7 @@ var ts; ts.emitNewLineBeforeLeadingCommentOfPosition(currentLineMap, writer, rangePos, commentPos); hasWrittenComment = true; } + // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space if (emitPos) emitPos(commentPos); ts.writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine); @@ -63792,7 +77277,7 @@ var ts; if (hasTrailingNewLine) { writer.writeLine(); } - else if (kind === 3) { + else if (kind === 3 /* MultiLineCommentTrivia */) { writer.write(" "); } } @@ -63800,7 +77285,7 @@ var ts; if (disabled || pos === -1) { return; } - emitLeadingComments(pos, true); + emitLeadingComments(pos, /*isEmittedNode*/ true); } function emitTrailingComments(pos) { forEachTrailingCommentToEmit(pos, emitTrailingComment); @@ -63808,6 +77293,7 @@ var ts; function emitTrailingComment(commentPos, commentEnd, _kind, hasTrailingNewLine) { if (!shouldWriteComment(currentText, commentPos)) return; + // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment2*/ if (!writer.isAtStartOfLine()) { writer.write(" "); } @@ -63833,6 +77319,7 @@ var ts; } } function emitTrailingCommentOfPosition(commentPos, commentEnd, _kind, hasTrailingNewLine) { + // trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space if (emitPos) emitPos(commentPos); ts.writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine); @@ -63846,16 +77333,18 @@ var ts; } } function forEachLeadingCommentToEmit(pos, cb) { + // Emit the leading comments only if the container's pos doesn't match because the container should take care of emitting these comments if (containerPos === -1 || pos !== containerPos) { if (hasDetachedComments(pos)) { forEachLeadingCommentWithoutDetachedComments(cb); } else { - ts.forEachLeadingCommentRange(currentText, pos, cb, pos); + ts.forEachLeadingCommentRange(currentText, pos, cb, /*state*/ pos); } } } function forEachTrailingCommentToEmit(end, cb) { + // Emit the trailing comments only if the container's end doesn't match because the container should take care of emitting these comments if (containerEnd === -1 || (end !== containerEnd && end !== declarationListContainerEnd)) { ts.forEachTrailingCommentRange(currentText, end, cb); } @@ -63879,6 +77368,7 @@ var ts; return detachedCommentsInfo !== undefined && ts.last(detachedCommentsInfo).nodePos === pos; } function forEachLeadingCommentWithoutDetachedComments(cb) { + // get the leading comments from detachedPos var pos = ts.last(detachedCommentsInfo).detachedCommentEndPos; if (detachedCommentsInfo.length - 1) { detachedCommentsInfo.pop(); @@ -63886,7 +77376,7 @@ var ts; else { detachedCommentsInfo = undefined; } - ts.forEachLeadingCommentRange(currentText, pos, cb, pos); + ts.forEachLeadingCommentRange(currentText, pos, cb, /*state*/ pos); } function emitDetachedCommentsAndUpdateCommentsInfo(range) { var currentDetachedCommentInfo = ts.emitDetachedComments(currentText, currentLineMap, writer, writeComment, range, newLine, disabled); @@ -63908,6 +77398,11 @@ var ts; if (emitPos) emitPos(commentEnd); } + /** + * Determine if the given comment is a triple-slash + * + * @return true if the comment is a triple-slash comment else false + */ function isTripleSlashComment(commentPos, commentEnd) { return ts.isRecognizedTripleSlashComment(currentText, commentPos, commentEnd); } @@ -63918,6 +77413,16 @@ var ts; (function (ts) { var infoExtension = ".tsbundleinfo"; var brackets = createBracketsMap(); + /*@internal*/ + /** + * Iterates over the source files that are expected to have an emit output. + * + * @param host An EmitHost. + * @param action The action to execute. + * @param sourceFilesOrTargetSourceFile + * If an array, the full list of source files to emit. + * Else, calls `getSourceFilesToEmit` with the (optional) target source file to determine the list of source files to emit. + */ function forEachEmittedFile(host, action, sourceFilesOrTargetSourceFile, emitOnlyDtsFiles) { if (emitOnlyDtsFiles === void 0) { emitOnlyDtsFiles = false; } var sourceFiles = ts.isArray(sourceFilesOrTargetSourceFile) ? sourceFilesOrTargetSourceFile : ts.getSourceFilesToEmit(host, sourceFilesOrTargetSourceFile); @@ -63942,12 +77447,13 @@ var ts; } } ts.forEachEmittedFile = forEachEmittedFile; + /*@internal*/ function getOutputPathsFor(sourceFile, host, forceDtsPaths) { var options = host.getCompilerOptions(); - if (sourceFile.kind === 275) { + if (sourceFile.kind === 275 /* Bundle */) { var jsFilePath = options.outFile || options.out; var sourceMapFilePath = getSourceMapFilePath(jsFilePath, options); - var declarationFilePath = (forceDtsPaths || options.declaration) ? ts.removeFileExtension(jsFilePath) + ".d.ts" : undefined; + var declarationFilePath = (forceDtsPaths || options.declaration) ? ts.removeFileExtension(jsFilePath) + ".d.ts" /* Dts */ : undefined; var declarationMapPath = ts.getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined; var bundleInfoPath = options.references && jsFilePath ? (ts.removeFileExtension(jsFilePath) + infoExtension) : undefined; return { jsFilePath: jsFilePath, sourceMapFilePath: sourceMapFilePath, declarationFilePath: declarationFilePath, declarationMapPath: declarationMapPath, bundleInfoPath: bundleInfoPath }; @@ -63955,6 +77461,7 @@ var ts; else { var jsFilePath = ts.getOwnEmitOutputFilePath(sourceFile, host, getOutputExtension(sourceFile, options)); var sourceMapFilePath = ts.isJsonSourceFile(sourceFile) ? undefined : getSourceMapFilePath(jsFilePath, options); + // For legacy reasons (ie, we have baselines capturing the behavior), js files don't report a .d.ts output path - this would only matter if `declaration` and `allowJs` were both on, which is currently an error var isJs = ts.isSourceFileJavaScript(sourceFile); var declarationFilePath = ((forceDtsPaths || options.declaration) && !isJs) ? ts.getDeclarationEmitOutputFilePath(sourceFile, host) : undefined; var declarationMapPath = ts.getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined; @@ -63971,23 +77478,30 @@ var ts; totalLength: -1 }; } + // JavaScript files are always LanguageVariant.JSX, as JSX syntax is allowed in .js files also. + // So for JavaScript files, '.jsx' is only emitted if the input was '.jsx', and JsxEmit.Preserve. + // For TypeScript, the only time to emit with a '.jsx' extension, is on JSX input, and JsxEmit.Preserve + /* @internal */ function getOutputExtension(sourceFile, options) { if (ts.isJsonSourceFile(sourceFile)) { - return ".json"; + return ".json" /* Json */; } - if (options.jsx === 1) { + if (options.jsx === 1 /* Preserve */) { if (ts.isSourceFileJavaScript(sourceFile)) { - if (ts.fileExtensionIs(sourceFile.fileName, ".jsx")) { - return ".jsx"; + if (ts.fileExtensionIs(sourceFile.fileName, ".jsx" /* Jsx */)) { + return ".jsx" /* Jsx */; } } - else if (sourceFile.languageVariant === 1) { - return ".jsx"; + else if (sourceFile.languageVariant === 1 /* JSX */) { + // TypeScript source file preserving JSX syntax + return ".jsx" /* Jsx */; } } - return ".js"; + return ".js" /* Js */; } ts.getOutputExtension = getOutputExtension; + /*@internal*/ + // targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature function emitFiles(resolver, host, targetSourceFile, emitOnlyDtsFiles, transformers, declarationTransformers) { var compilerOptions = host.getCompilerOptions(); var sourceMapDataList = (compilerOptions.sourceMap || compilerOptions.inlineSourceMap || ts.getAreDeclarationMapsEnabled(compilerOptions)) ? [] : undefined; @@ -64004,6 +77518,7 @@ var ts; }); var bundleInfo = createDefaultBundleInfo(); var emitSkipped = false; + // Emit each output file ts.performance.mark("beforePrint"); forEachEmittedFile(host, emitSourceFileOrBundle, ts.getSourceFilesToEmit(host, targetSourceFile), emitOnlyDtsFiles); ts.performance.measure("printTime", "beforePrint"); @@ -64033,6 +77548,7 @@ var ts; } } function emitJsFileOrBundle(sourceFileOrBundle, jsFilePath, sourceMapFilePath, bundleInfoPath) { + // Make sure not to write js file and source map file if any of them cannot be written if (host.isEmitBlocked(jsFilePath) || compilerOptions.noEmit || compilerOptions.emitDeclarationOnly) { emitSkipped = true; return; @@ -64040,18 +77556,25 @@ var ts; if (emitOnlyDtsFiles) { return; } - var transform = ts.transformNodes(resolver, host, compilerOptions, [sourceFileOrBundle], transformers, false); + // Transform the source files + var transform = ts.transformNodes(resolver, host, compilerOptions, [sourceFileOrBundle], transformers, /*allowDtsFiles*/ false); + // Create a printer to print the nodes var printer = createPrinter(__assign({}, compilerOptions, { noEmitHelpers: compilerOptions.noEmitHelpers }), { + // resolver hooks hasGlobalName: resolver.hasGlobalName, + // transform hooks onEmitNode: transform.emitNodeWithNotification, substituteNode: transform.substituteNode, + // sourcemap hooks onEmitSourceMapOfNode: sourceMap.emitNodeWithSourceMap, onEmitSourceMapOfToken: sourceMap.emitTokenWithSourceMap, onEmitSourceMapOfPosition: sourceMap.emitPos, + // emitter hooks onSetSourceFile: setSourceFile, }); ts.Debug.assert(transform.transformed.length === 1, "Should only see one output from the transform"); printSourceFileOrBundle(jsFilePath, sourceMapFilePath, transform.transformed[0], bundleInfoPath, printer, sourceMap); + // Clean up emit nodes on parse tree transform.dispose(); } function emitDeclarationFileOrBundle(sourceFileOrBundle, declarationFilePath, declarationMapPath) { @@ -64059,9 +77582,10 @@ var ts; return; } var sourceFiles = ts.isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : sourceFileOrBundle.sourceFiles; + // Setup and perform the transformation to retrieve declarations from the input files var nonJsFiles = ts.filter(sourceFiles, ts.isSourceFileNotJavaScript); var inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [ts.createBundle(nonJsFiles, !ts.isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : nonJsFiles; - var declarationTransform = ts.transformNodes(resolver, host, compilerOptions, inputListOrBundle, ts.concatenate([ts.transformDeclarations], declarationTransformers), false); + var declarationTransform = ts.transformNodes(resolver, host, compilerOptions, inputListOrBundle, ts.concatenate([ts.transformDeclarations], declarationTransformers), /*allowDtsFiles*/ false); if (ts.length(declarationTransform.diagnostics)) { for (var _a = 0, _b = declarationTransform.diagnostics; _a < _b.length; _a++) { var diagnostic = _b[_a]; @@ -64069,11 +77593,14 @@ var ts; } } var declarationPrinter = createPrinter(__assign({}, compilerOptions, { onlyPrintJsDocStyle: true, noEmitHelpers: true }), { + // resolver hooks hasGlobalName: resolver.hasGlobalName, + // sourcemap hooks onEmitSourceMapOfNode: declarationSourceMap.emitNodeWithSourceMap, onEmitSourceMapOfToken: declarationSourceMap.emitTokenWithSourceMap, onEmitSourceMapOfPosition: declarationSourceMap.emitPos, onSetSourceFile: setSourceFileForDeclarationSourceMaps, + // transform hooks onEmitNode: declarationTransform.emitNodeWithNotification, substituteNode: declarationTransform.substituteNode, }); @@ -64081,13 +77608,13 @@ var ts; emitSkipped = emitSkipped || declBlocked; if (!declBlocked || emitOnlyDtsFiles) { ts.Debug.assert(declarationTransform.transformed.length === 1, "Should only see one output from the decl transform"); - printSourceFileOrBundle(declarationFilePath, declarationMapPath, declarationTransform.transformed[0], undefined, declarationPrinter, declarationSourceMap); + printSourceFileOrBundle(declarationFilePath, declarationMapPath, declarationTransform.transformed[0], /* bundleInfopath*/ undefined, declarationPrinter, declarationSourceMap); } declarationTransform.dispose(); } function printSourceFileOrBundle(jsFilePath, sourceMapFilePath, sourceFileOrBundle, bundleInfoPath, printer, mapRecorder) { - var bundle = sourceFileOrBundle.kind === 275 ? sourceFileOrBundle : undefined; - var sourceFile = sourceFileOrBundle.kind === 274 ? sourceFileOrBundle : undefined; + var bundle = sourceFileOrBundle.kind === 275 /* Bundle */ ? sourceFileOrBundle : undefined; + var sourceFile = sourceFileOrBundle.kind === 274 /* SourceFile */ ? sourceFileOrBundle : undefined; var sourceFiles = bundle ? bundle.sourceFiles : [sourceFile]; mapRecorder.initialize(jsFilePath, sourceMapFilePath || "", sourceFileOrBundle, sourceMapDataList); if (bundle) { @@ -64099,16 +77626,20 @@ var ts; writer.writeLine(); var sourceMappingURL = mapRecorder.getSourceMappingURL(); if (sourceMappingURL) { - writer.write("//# " + "sourceMappingURL" + "=" + sourceMappingURL); + writer.write("//# " + "sourceMappingURL" + "=" + sourceMappingURL); // Sometimes tools can sometimes see this line as a source mapping url comment } + // Write the source map if (sourceMapFilePath) { - ts.writeFile(host, emitterDiagnostics, sourceMapFilePath, mapRecorder.getText(), false, sourceFiles); + ts.writeFile(host, emitterDiagnostics, sourceMapFilePath, mapRecorder.getText(), /*writeByteOrderMark*/ false, sourceFiles); } + // Write the output file ts.writeFile(host, emitterDiagnostics, jsFilePath, writer.getText(), !!compilerOptions.emitBOM, sourceFiles); + // Write bundled offset information if applicable if (bundleInfoPath) { bundleInfo.totalLength = writer.getTextPos(); - ts.writeFile(host, emitterDiagnostics, bundleInfoPath, JSON.stringify(bundleInfo, undefined, 2), false); + ts.writeFile(host, emitterDiagnostics, bundleInfoPath, JSON.stringify(bundleInfo, undefined, 2), /*writeByteOrderMark*/ false); } + // Reset state mapRecorder.reset(); writer.clear(); bundleInfo = createDefaultBundleInfo(); @@ -64136,13 +77667,13 @@ var ts; var comments = ts.createCommentWriter(printerOptions, onEmitSourceMapOfPosition); var emitNodeWithComments = comments.emitNodeWithComments, emitBodyWithDetachedComments = comments.emitBodyWithDetachedComments, emitTrailingCommentsOfPosition = comments.emitTrailingCommentsOfPosition, emitLeadingCommentsOfPosition = comments.emitLeadingCommentsOfPosition; var currentSourceFile; - var nodeIdToGeneratedName; - var autoGeneratedIdToGeneratedName; - var generatedNames; - var tempFlagsStack; - var tempFlags; - var reservedNamesStack; - var reservedNames; + var nodeIdToGeneratedName; // Map of generated names for specific nodes. + var autoGeneratedIdToGeneratedName; // Map of generated names for temp and loop variables. + var generatedNames; // Set of names generated by the NameGenerator. + var tempFlagsStack; // Stack of enclosing name generation scopes. + var tempFlags; // TempFlags for the current name generation scope. + var reservedNamesStack; // Stack of TempFlags reserved in enclosing name generation scopes. + var reservedNames; // TempFlags to reserve in nested name generation scopes. var writer; var ownWriter; var write = writeBase; @@ -64159,10 +77690,12 @@ var ts; var isOwnFileEmit; reset(); return { + // public API printNode: printNode, printList: printList, printFile: printFile, printBundle: printBundle, + // internal API writeNode: writeNode, writeList: writeList, writeFile: writeFile, @@ -64170,20 +77703,20 @@ var ts; }; function printNode(hint, node, sourceFile) { switch (hint) { - case 0: + case 0 /* SourceFile */: ts.Debug.assert(ts.isSourceFile(node), "Expected a SourceFile node."); break; - case 2: + case 2 /* IdentifierName */: ts.Debug.assert(ts.isIdentifier(node), "Expected an Identifier node."); break; - case 1: + case 1 /* Expression */: ts.Debug.assert(ts.isExpression(node), "Expected an Expression node."); break; } switch (node.kind) { - case 274: return printFile(node); - case 275: return printBundle(node); - case 276: return printUnparsedSource(node); + case 274 /* SourceFile */: return printFile(node); + case 275 /* Bundle */: return printBundle(node); + case 276 /* UnparsedSource */: return printUnparsedSource(node); } writeNode(hint, node, sourceFile, beginPrint()); return endPrint(); @@ -64231,7 +77764,7 @@ var ts; emitSyntheticTripleSlashReferencesIfNeeded(bundle); for (var _a = 0, _b = bundle.prepends; _a < _b.length; _a++) { var prepend = _b[_a]; - print(4, prepend, undefined); + print(4 /* Unspecified */, prepend, /*sourceFile*/ undefined); writeLine(); } if (bundleInfo) { @@ -64239,7 +77772,7 @@ var ts; } for (var _c = 0, _d = bundle.sourceFiles; _c < _d.length; _c++) { var sourceFile = _d[_c]; - print(0, sourceFile, sourceFile); + print(0 /* SourceFile */, sourceFile, sourceFile); } reset(); writer = previousWriter; @@ -64247,7 +77780,7 @@ var ts; function writeUnparsedSource(unparsed, output) { var previousWriter = writer; setWriter(output); - print(4, unparsed, undefined); + print(4 /* Unspecified */, unparsed, /*sourceFile*/ undefined); reset(); writer = previousWriter; } @@ -64257,7 +77790,7 @@ var ts; setWriter(output); emitShebangIfNeeded(sourceFile); emitPrologueDirectivesIfNeeded(sourceFile); - print(0, sourceFile, sourceFile); + print(0 /* SourceFile */, sourceFile, sourceFile); reset(); writer = previousWriter; } @@ -64273,7 +77806,7 @@ var ts; if (sourceFile) { setSourceFile(sourceFile); } - var pipelinePhase = getPipelinePhase(0, hint); + var pipelinePhase = getPipelinePhase(0 /* Notification */, hint); pipelinePhase(hint, node); } function setSourceFile(sourceFile) { @@ -64284,7 +77817,7 @@ var ts; } } function setWriter(output) { - writer = output; + writer = output; // TODO: GH#18217 comments.setWriter(output); } function reset() { @@ -64292,45 +77825,47 @@ var ts; autoGeneratedIdToGeneratedName = []; generatedNames = ts.createMap(); tempFlagsStack = []; - tempFlags = 0; + tempFlags = 0 /* Auto */; reservedNamesStack = []; comments.reset(); - setWriter(undefined); + setWriter(/*output*/ undefined); } function emit(node) { if (!node) return; - var pipelinePhase = getPipelinePhase(0, 4); - pipelinePhase(4, node); + var pipelinePhase = getPipelinePhase(0 /* Notification */, 4 /* Unspecified */); + pipelinePhase(4 /* Unspecified */, node); } function emitIdentifierName(node) { if (!node) return; - var pipelinePhase = getPipelinePhase(0, 2); - pipelinePhase(2, node); + var pipelinePhase = getPipelinePhase(0 /* Notification */, 2 /* IdentifierName */); + pipelinePhase(2 /* IdentifierName */, node); } function emitExpression(node) { if (!node) return; - var pipelinePhase = getPipelinePhase(0, 1); - pipelinePhase(1, node); + var pipelinePhase = getPipelinePhase(0 /* Notification */, 1 /* Expression */); + pipelinePhase(1 /* Expression */, node); } function getPipelinePhase(phase, hint) { switch (phase) { - case 0: + case 0 /* Notification */: if (onEmitNode) { return pipelineEmitWithNotification; } - case 1: - if (emitNodeWithComments && hint !== 0) { + // falls through + case 1 /* Comments */: + if (emitNodeWithComments && hint !== 0 /* SourceFile */) { return pipelineEmitWithComments; } return pipelineEmitWithoutComments; - case 2: - if (onEmitSourceMapOfNode && hint !== 0 && hint !== 2) { + case 2 /* SourceMaps */: + if (onEmitSourceMapOfNode && hint !== 0 /* SourceFile */ && hint !== 2 /* IdentifierName */) { return pipelineEmitWithSourceMap; } - case 3: + // falls through + case 3 /* Emit */: return pipelineEmitWithHint; default: return ts.Debug.assertNever(phase, "Unexpected value for PipelinePhase: " + phase); @@ -64340,341 +77875,365 @@ var ts; return getPipelinePhase(currentPhase + 1, hint); } function pipelineEmitWithNotification(hint, node) { - ts.Debug.assertDefined(onEmitNode)(hint, node, getNextPipelinePhase(0, hint)); + ts.Debug.assertDefined(onEmitNode)(hint, node, getNextPipelinePhase(0 /* Notification */, hint)); } function pipelineEmitWithComments(hint, node) { ts.Debug.assertDefined(emitNodeWithComments); - ts.Debug.assert(hint !== 0); - emitNodeWithComments(hint, trySubstituteNode(hint, node), getNextPipelinePhase(1, hint)); + ts.Debug.assert(hint !== 0 /* SourceFile */); + emitNodeWithComments(hint, trySubstituteNode(hint, node), getNextPipelinePhase(1 /* Comments */, hint)); } function pipelineEmitWithoutComments(hint, node) { - var pipelinePhase = getNextPipelinePhase(1, hint); + var pipelinePhase = getNextPipelinePhase(1 /* Comments */, hint); pipelinePhase(hint, trySubstituteNode(hint, node)); } function pipelineEmitWithSourceMap(hint, node) { - ts.Debug.assert(hint !== 0 && hint !== 2); + ts.Debug.assert(hint !== 0 /* SourceFile */ && hint !== 2 /* IdentifierName */); ts.Debug.assertDefined(onEmitSourceMapOfNode)(hint, node, pipelineEmitWithHint); } function pipelineEmitWithHint(hint, node) { - if (hint === 0) + if (hint === 0 /* SourceFile */) return emitSourceFile(ts.cast(node, ts.isSourceFile)); - if (hint === 2) + if (hint === 2 /* IdentifierName */) return emitIdentifier(ts.cast(node, ts.isIdentifier)); - if (hint === 3) + if (hint === 3 /* MappedTypeParameter */) return emitMappedTypeParameter(ts.cast(node, ts.isTypeParameterDeclaration)); - if (hint === 4) { + if (hint === 4 /* Unspecified */) { if (ts.isKeyword(node.kind)) return writeTokenNode(node, writeKeyword); switch (node.kind) { - case 14: - case 15: - case 16: + // Pseudo-literals + case 14 /* TemplateHead */: + case 15 /* TemplateMiddle */: + case 16 /* TemplateTail */: return emitLiteral(node); - case 276: + case 276 /* UnparsedSource */: return emitUnparsedSource(node); - case 71: + // Identifiers + case 71 /* Identifier */: return emitIdentifier(node); - case 146: + // Parse tree nodes + // Names + case 146 /* QualifiedName */: return emitQualifiedName(node); - case 147: + case 147 /* ComputedPropertyName */: return emitComputedPropertyName(node); - case 148: + // Signature elements + case 148 /* TypeParameter */: return emitTypeParameter(node); - case 149: + case 149 /* Parameter */: return emitParameter(node); - case 150: + case 150 /* Decorator */: return emitDecorator(node); - case 151: + // Type members + case 151 /* PropertySignature */: return emitPropertySignature(node); - case 152: + case 152 /* PropertyDeclaration */: return emitPropertyDeclaration(node); - case 153: + case 153 /* MethodSignature */: return emitMethodSignature(node); - case 154: + case 154 /* MethodDeclaration */: return emitMethodDeclaration(node); - case 155: + case 155 /* Constructor */: return emitConstructor(node); - case 156: - case 157: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return emitAccessorDeclaration(node); - case 158: + case 158 /* CallSignature */: return emitCallSignature(node); - case 159: + case 159 /* ConstructSignature */: return emitConstructSignature(node); - case 160: + case 160 /* IndexSignature */: return emitIndexSignature(node); - case 161: + // Types + case 161 /* TypePredicate */: return emitTypePredicate(node); - case 162: + case 162 /* TypeReference */: return emitTypeReference(node); - case 163: + case 163 /* FunctionType */: return emitFunctionType(node); - case 284: + case 284 /* JSDocFunctionType */: return emitJSDocFunctionType(node); - case 164: + case 164 /* ConstructorType */: return emitConstructorType(node); - case 165: + case 165 /* TypeQuery */: return emitTypeQuery(node); - case 166: + case 166 /* TypeLiteral */: return emitTypeLiteral(node); - case 167: + case 167 /* ArrayType */: return emitArrayType(node); - case 168: + case 168 /* TupleType */: return emitTupleType(node); - case 169: + case 169 /* UnionType */: return emitUnionType(node); - case 170: + case 170 /* IntersectionType */: return emitIntersectionType(node); - case 171: + case 171 /* ConditionalType */: return emitConditionalType(node); - case 172: + case 172 /* InferType */: return emitInferType(node); - case 173: + case 173 /* ParenthesizedType */: return emitParenthesizedType(node); - case 207: + case 207 /* ExpressionWithTypeArguments */: return emitExpressionWithTypeArguments(node); - case 174: + case 174 /* ThisType */: return emitThisType(); - case 175: + case 175 /* TypeOperator */: return emitTypeOperator(node); - case 176: + case 176 /* IndexedAccessType */: return emitIndexedAccessType(node); - case 177: + case 177 /* MappedType */: return emitMappedType(node); - case 178: + case 178 /* LiteralType */: return emitLiteralType(node); - case 179: + case 179 /* ImportType */: return emitImportTypeNode(node); - case 279: + case 279 /* JSDocAllType */: write("*"); return; - case 280: + case 280 /* JSDocUnknownType */: write("?"); return; - case 281: + case 281 /* JSDocNullableType */: return emitJSDocNullableType(node); - case 282: + case 282 /* JSDocNonNullableType */: return emitJSDocNonNullableType(node); - case 283: + case 283 /* JSDocOptionalType */: return emitJSDocOptionalType(node); - case 285: + case 285 /* JSDocVariadicType */: return emitJSDocVariadicType(node); - case 180: + // Binding patterns + case 180 /* ObjectBindingPattern */: return emitObjectBindingPattern(node); - case 181: + case 181 /* ArrayBindingPattern */: return emitArrayBindingPattern(node); - case 182: + case 182 /* BindingElement */: return emitBindingElement(node); - case 211: + // Misc + case 211 /* TemplateSpan */: return emitTemplateSpan(node); - case 212: + case 212 /* SemicolonClassElement */: return emitSemicolonClassElement(); - case 213: + // Statements + case 213 /* Block */: return emitBlock(node); - case 214: + case 214 /* VariableStatement */: return emitVariableStatement(node); - case 215: + case 215 /* EmptyStatement */: return emitEmptyStatement(); - case 216: + case 216 /* ExpressionStatement */: return emitExpressionStatement(node); - case 217: + case 217 /* IfStatement */: return emitIfStatement(node); - case 218: + case 218 /* DoStatement */: return emitDoStatement(node); - case 219: + case 219 /* WhileStatement */: return emitWhileStatement(node); - case 220: + case 220 /* ForStatement */: return emitForStatement(node); - case 221: + case 221 /* ForInStatement */: return emitForInStatement(node); - case 222: + case 222 /* ForOfStatement */: return emitForOfStatement(node); - case 223: + case 223 /* ContinueStatement */: return emitContinueStatement(node); - case 224: + case 224 /* BreakStatement */: return emitBreakStatement(node); - case 225: + case 225 /* ReturnStatement */: return emitReturnStatement(node); - case 226: + case 226 /* WithStatement */: return emitWithStatement(node); - case 227: + case 227 /* SwitchStatement */: return emitSwitchStatement(node); - case 228: + case 228 /* LabeledStatement */: return emitLabeledStatement(node); - case 229: + case 229 /* ThrowStatement */: return emitThrowStatement(node); - case 230: + case 230 /* TryStatement */: return emitTryStatement(node); - case 231: + case 231 /* DebuggerStatement */: return emitDebuggerStatement(node); - case 232: + // Declarations + case 232 /* VariableDeclaration */: return emitVariableDeclaration(node); - case 233: + case 233 /* VariableDeclarationList */: return emitVariableDeclarationList(node); - case 234: + case 234 /* FunctionDeclaration */: return emitFunctionDeclaration(node); - case 235: + case 235 /* ClassDeclaration */: return emitClassDeclaration(node); - case 236: + case 236 /* InterfaceDeclaration */: return emitInterfaceDeclaration(node); - case 237: + case 237 /* TypeAliasDeclaration */: return emitTypeAliasDeclaration(node); - case 238: + case 238 /* EnumDeclaration */: return emitEnumDeclaration(node); - case 239: + case 239 /* ModuleDeclaration */: return emitModuleDeclaration(node); - case 240: + case 240 /* ModuleBlock */: return emitModuleBlock(node); - case 241: + case 241 /* CaseBlock */: return emitCaseBlock(node); - case 242: + case 242 /* NamespaceExportDeclaration */: return emitNamespaceExportDeclaration(node); - case 243: + case 243 /* ImportEqualsDeclaration */: return emitImportEqualsDeclaration(node); - case 244: + case 244 /* ImportDeclaration */: return emitImportDeclaration(node); - case 245: + case 245 /* ImportClause */: return emitImportClause(node); - case 246: + case 246 /* NamespaceImport */: return emitNamespaceImport(node); - case 247: + case 247 /* NamedImports */: return emitNamedImports(node); - case 248: + case 248 /* ImportSpecifier */: return emitImportSpecifier(node); - case 249: + case 249 /* ExportAssignment */: return emitExportAssignment(node); - case 250: + case 250 /* ExportDeclaration */: return emitExportDeclaration(node); - case 251: + case 251 /* NamedExports */: return emitNamedExports(node); - case 252: + case 252 /* ExportSpecifier */: return emitExportSpecifier(node); - case 253: + case 253 /* MissingDeclaration */: return; - case 254: + // Module references + case 254 /* ExternalModuleReference */: return emitExternalModuleReference(node); - case 10: + // JSX (non-expression) + case 10 /* JsxText */: return emitJsxText(node); - case 257: - case 260: + case 257 /* JsxOpeningElement */: + case 260 /* JsxOpeningFragment */: return emitJsxOpeningElementOrFragment(node); - case 258: - case 261: + case 258 /* JsxClosingElement */: + case 261 /* JsxClosingFragment */: return emitJsxClosingElementOrFragment(node); - case 262: + case 262 /* JsxAttribute */: return emitJsxAttribute(node); - case 263: + case 263 /* JsxAttributes */: return emitJsxAttributes(node); - case 264: + case 264 /* JsxSpreadAttribute */: return emitJsxSpreadAttribute(node); - case 265: + case 265 /* JsxExpression */: return emitJsxExpression(node); - case 266: + // Clauses + case 266 /* CaseClause */: return emitCaseClause(node); - case 267: + case 267 /* DefaultClause */: return emitDefaultClause(node); - case 268: + case 268 /* HeritageClause */: return emitHeritageClause(node); - case 269: + case 269 /* CatchClause */: return emitCatchClause(node); - case 270: + // Property assignments + case 270 /* PropertyAssignment */: return emitPropertyAssignment(node); - case 271: + case 271 /* ShorthandPropertyAssignment */: return emitShorthandPropertyAssignment(node); - case 272: + case 272 /* SpreadAssignment */: return emitSpreadAssignment(node); - case 273: + // Enum + case 273 /* EnumMember */: return emitEnumMember(node); + // JSDoc nodes (ignored) + // Transformation nodes (ignored) } if (ts.isExpression(node)) { - hint = 1; - node = trySubstituteNode(1, node); + hint = 1 /* Expression */; + node = trySubstituteNode(1 /* Expression */, node); } else if (ts.isToken(node)) { return writeTokenNode(node, writePunctuation); } } - if (hint === 1) { + if (hint === 1 /* Expression */) { switch (node.kind) { - case 8: + // Literals + case 8 /* NumericLiteral */: return emitNumericLiteral(node); - case 9: - case 12: - case 13: + case 9 /* StringLiteral */: + case 12 /* RegularExpressionLiteral */: + case 13 /* NoSubstitutionTemplateLiteral */: return emitLiteral(node); - case 71: + // Identifiers + case 71 /* Identifier */: return emitIdentifier(node); - case 86: - case 95: - case 97: - case 101: - case 99: - case 91: + // Reserved words + case 86 /* FalseKeyword */: + case 95 /* NullKeyword */: + case 97 /* SuperKeyword */: + case 101 /* TrueKeyword */: + case 99 /* ThisKeyword */: + case 91 /* ImportKeyword */: writeTokenNode(node, writeKeyword); return; - case 183: + // Expressions + case 183 /* ArrayLiteralExpression */: return emitArrayLiteralExpression(node); - case 184: + case 184 /* ObjectLiteralExpression */: return emitObjectLiteralExpression(node); - case 185: + case 185 /* PropertyAccessExpression */: return emitPropertyAccessExpression(node); - case 186: + case 186 /* ElementAccessExpression */: return emitElementAccessExpression(node); - case 187: + case 187 /* CallExpression */: return emitCallExpression(node); - case 188: + case 188 /* NewExpression */: return emitNewExpression(node); - case 189: + case 189 /* TaggedTemplateExpression */: return emitTaggedTemplateExpression(node); - case 190: + case 190 /* TypeAssertionExpression */: return emitTypeAssertionExpression(node); - case 191: + case 191 /* ParenthesizedExpression */: return emitParenthesizedExpression(node); - case 192: + case 192 /* FunctionExpression */: return emitFunctionExpression(node); - case 193: + case 193 /* ArrowFunction */: return emitArrowFunction(node); - case 194: + case 194 /* DeleteExpression */: return emitDeleteExpression(node); - case 195: + case 195 /* TypeOfExpression */: return emitTypeOfExpression(node); - case 196: + case 196 /* VoidExpression */: return emitVoidExpression(node); - case 197: + case 197 /* AwaitExpression */: return emitAwaitExpression(node); - case 198: + case 198 /* PrefixUnaryExpression */: return emitPrefixUnaryExpression(node); - case 199: + case 199 /* PostfixUnaryExpression */: return emitPostfixUnaryExpression(node); - case 200: + case 200 /* BinaryExpression */: return emitBinaryExpression(node); - case 201: + case 201 /* ConditionalExpression */: return emitConditionalExpression(node); - case 202: + case 202 /* TemplateExpression */: return emitTemplateExpression(node); - case 203: + case 203 /* YieldExpression */: return emitYieldExpression(node); - case 204: + case 204 /* SpreadElement */: return emitSpreadExpression(node); - case 205: + case 205 /* ClassExpression */: return emitClassExpression(node); - case 206: + case 206 /* OmittedExpression */: return; - case 208: + case 208 /* AsExpression */: return emitAsExpression(node); - case 209: + case 209 /* NonNullExpression */: return emitNonNullExpression(node); - case 210: + case 210 /* MetaProperty */: return emitMetaProperty(node); - case 255: + // JSX + case 255 /* JsxElement */: return emitJsxElement(node); - case 256: + case 256 /* JsxSelfClosingElement */: return emitJsxSelfClosingElement(node); - case 259: + case 259 /* JsxFragment */: return emitJsxFragment(node); - case 302: + // Transformation nodes + case 302 /* PartiallyEmittedExpression */: return emitPartiallyEmittedExpression(node); - case 303: + case 303 /* CommaListExpression */: return emitCommaList(node); } } @@ -64691,7 +78250,7 @@ var ts; } function emitHelpers(node) { var helpersEmitted = false; - var bundle = node.kind === 275 ? node : undefined; + var bundle = node.kind === 275 /* Bundle */ ? node : undefined; if (bundle && moduleKind === ts.ModuleKind.None) { return; } @@ -64706,8 +78265,13 @@ var ts; for (var _a = 0, _b = ts.stableSort(helpers, ts.compareEmitHelpers); _a < _b.length; _a++) { var helper = _b[_a]; if (!helper.scoped) { + // Skip the helper if it can be skipped and the noEmitHelpers compiler + // option is set, or if it can be imported and the importHelpers compiler + // option is set. if (shouldSkip) continue; + // Skip the helper if it can be bundled but hasn't already been emitted and we + // are emitting a bundled module. if (shouldBundle) { if (bundledHelpers.get(helper.name)) { continue; @@ -64716,6 +78280,7 @@ var ts; } } else if (bundle) { + // Skip the helper if it is scoped and we are emitting bundled helpers continue; } if (typeof helper.text === "string") { @@ -64730,34 +78295,52 @@ var ts; } return helpersEmitted; } + // + // Literals/Pseudo-literals + // + // SyntaxKind.NumericLiteral function emitNumericLiteral(node) { emitLiteral(node); } + // SyntaxKind.StringLiteral + // SyntaxKind.RegularExpressionLiteral + // SyntaxKind.NoSubstitutionTemplateLiteral + // SyntaxKind.TemplateHead + // SyntaxKind.TemplateMiddle + // SyntaxKind.TemplateTail function emitLiteral(node) { var text = getLiteralTextOfNode(node); if ((printerOptions.sourceMap || printerOptions.inlineSourceMap) - && (node.kind === 9 || ts.isTemplateLiteralKind(node.kind))) { + && (node.kind === 9 /* StringLiteral */ || ts.isTemplateLiteralKind(node.kind))) { writeLiteral(text); } else { + // Quick info expects all literals to be called with writeStringLiteral, as there's no specific type for numberLiterals writeStringLiteral(text); } } + // SyntaxKind.UnparsedSource function emitUnparsedSource(unparsed) { writer.rawWrite(unparsed.text); } + // + // Identifiers + // function emitIdentifier(node) { var writeText = node.symbol ? writeSymbol : write; - writeText(getTextOfNode(node, false), node.symbol); - emitList(node, node.typeArguments, 26896); + writeText(getTextOfNode(node, /*includeTrivia*/ false), node.symbol); + emitList(node, node.typeArguments, 26896 /* TypeParameters */); // Call emitList directly since it could be an array of TypeParameterDeclarations _or_ type arguments } + // + // Names + // function emitQualifiedName(node) { emitEntityName(node.left); writePunctuation("."); emit(node.right); } function emitEntityName(node) { - if (node.kind === 71) { + if (node.kind === 71 /* Identifier */) { emitExpression(node); } else { @@ -64769,6 +78352,9 @@ var ts; emitExpression(node.expression); writePunctuation("]"); } + // + // Signature elements + // function emitTypeParameter(node) { emit(node.name); if (node.constraint) { @@ -64790,18 +78376,22 @@ var ts; emit(node.dotDotDotToken); emitNodeWithWriter(node.name, writeParameter); emit(node.questionToken); - if (node.parent && node.parent.kind === 284 && !node.name) { + if (node.parent && node.parent.kind === 284 /* JSDocFunctionType */ && !node.name) { emit(node.type); } else { emitTypeAnnotation(node.type); } + // The comment position has to fallback to any present node within the parameterdeclaration because as it turns out, the parser can make parameter declarations with _just_ an initializer. emitInitializer(node.initializer, node.type ? node.type.end : node.questionToken ? node.questionToken.end : node.name ? node.name.end : node.modifiers ? node.modifiers.end : node.decorators ? node.decorators.end : node.pos, node); } function emitDecorator(decorator) { writePunctuation("@"); emitExpression(decorator.expression); } + // + // Type members + // function emitPropertySignature(node) { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); @@ -64848,7 +78438,7 @@ var ts; function emitAccessorDeclaration(node) { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); - writeKeyword(node.kind === 156 ? "get" : "set"); + writeKeyword(node.kind === 156 /* GetAccessor */ ? "get" : "set"); writeSpace(); emit(node.name); emitSignatureAndBody(node, emitSignatureHead); @@ -64885,6 +78475,9 @@ var ts; function emitSemicolonClassElement() { writeSemicolon(); } + // + // Types + // function emitTypePredicate(node) { emit(node.parameterName); writeSpace(); @@ -64943,8 +78536,8 @@ var ts; } function emitTypeLiteral(node) { writePunctuation("{"); - var flags = ts.getEmitFlags(node) & 1 ? 384 : 16449; - emitList(node, node.members, flags | 262144); + var flags = ts.getEmitFlags(node) & 1 /* SingleLine */ ? 384 /* SingleLineTypeLiteralMembers */ : 16449 /* MultiLineTypeLiteralMembers */; + emitList(node, node.members, flags | 262144 /* NoSpaceIfEmpty */); writePunctuation("}"); } function emitArrayType(node) { @@ -64958,14 +78551,14 @@ var ts; } function emitTupleType(node) { writePunctuation("["); - emitList(node, node.elementTypes, 272); + emitList(node, node.elementTypes, 272 /* TupleTypeElements */); writePunctuation("]"); } function emitUnionType(node) { - emitList(node, node.types, 260); + emitList(node, node.types, 260 /* UnionTypeConstituents */); } function emitIntersectionType(node) { - emitList(node, node.types, 264); + emitList(node, node.types, 264 /* IntersectionTypeConstituents */); } function emitConditionalType(node) { emit(node.checkType); @@ -65009,7 +78602,7 @@ var ts; function emitMappedType(node) { var emitFlags = ts.getEmitFlags(node); writePunctuation("{"); - if (emitFlags & 1) { + if (emitFlags & 1 /* SingleLine */) { writeSpace(); } else { @@ -65018,18 +78611,18 @@ var ts; } if (node.readonlyToken) { emit(node.readonlyToken); - if (node.readonlyToken.kind !== 132) { + if (node.readonlyToken.kind !== 132 /* ReadonlyKeyword */) { writeKeyword("readonly"); } writeSpace(); } writePunctuation("["); - var pipelinePhase = getPipelinePhase(0, 3); - pipelinePhase(3, node.typeParameter); + var pipelinePhase = getPipelinePhase(0 /* Notification */, 3 /* MappedTypeParameter */); + pipelinePhase(3 /* MappedTypeParameter */, node.typeParameter); writePunctuation("]"); if (node.questionToken) { emit(node.questionToken); - if (node.questionToken.kind !== 55) { + if (node.questionToken.kind !== 55 /* QuestionToken */) { writePunctuation("?"); } } @@ -65037,7 +78630,7 @@ var ts; writeSpace(); emit(node.type); writeSemicolon(); - if (emitFlags & 1) { + if (emitFlags & 1 /* SingleLine */) { writeSpace(); } else { @@ -65064,14 +78657,17 @@ var ts; } emitTypeArguments(node, node.typeArguments); } + // + // Binding patterns + // function emitObjectBindingPattern(node) { writePunctuation("{"); - emitList(node, node.elements, 262576); + emitList(node, node.elements, 262576 /* ObjectBindingPatternElements */); writePunctuation("}"); } function emitArrayBindingPattern(node) { writePunctuation("["); - emitList(node, node.elements, 262448); + emitList(node, node.elements, 262448 /* ArrayBindingPatternElements */); writePunctuation("]"); } function emitBindingElement(node) { @@ -65084,20 +78680,23 @@ var ts; emit(node.name); emitInitializer(node.initializer, node.name.end, node); } + // + // Expressions + // function emitArrayLiteralExpression(node) { var elements = node.elements; - var preferNewLine = node.multiLine ? 32768 : 0; - emitExpressionList(node, elements, 4466 | preferNewLine); + var preferNewLine = node.multiLine ? 32768 /* PreferNewLine */ : 0 /* None */; + emitExpressionList(node, elements, 4466 /* ArrayLiteralExpressionElements */ | preferNewLine); } function emitObjectLiteralExpression(node) { ts.forEach(node.properties, generateMemberNames); - var indentedFlag = ts.getEmitFlags(node) & 65536; + var indentedFlag = ts.getEmitFlags(node) & 65536 /* Indented */; if (indentedFlag) { increaseIndent(); } - var preferNewLine = node.multiLine ? 32768 : 0; - var allowTrailingComma = currentSourceFile.languageVersion >= 1 && !ts.isJsonSourceFile(currentSourceFile) ? 32 : 0; - emitList(node, node.properties, 263122 | allowTrailingComma | preferNewLine); + var preferNewLine = node.multiLine ? 32768 /* PreferNewLine */ : 0 /* None */; + var allowTrailingComma = currentSourceFile.languageVersion >= 1 /* ES5 */ && !ts.isJsonSourceFile(currentSourceFile) ? 32 /* AllowTrailingComma */ : 0 /* None */; + emitList(node, node.properties, 263122 /* ObjectLiteralExpressionProperties */ | allowTrailingComma | preferNewLine); if (indentedFlag) { decreaseIndent(); } @@ -65105,10 +78704,10 @@ var ts; function emitPropertyAccessExpression(node) { var indentBeforeDot = false; var indentAfterDot = false; - if (!(ts.getEmitFlags(node) & 131072)) { + if (!(ts.getEmitFlags(node) & 131072 /* NoIndentation */)) { var dotRangeStart = node.expression.end; var dotRangeEnd = ts.skipTrivia(currentSourceFile.text, node.expression.end) + 1; - var dotToken = ts.createToken(23); + var dotToken = ts.createToken(23 /* DotToken */); dotToken.pos = dotRangeStart; dotToken.end = dotRangeEnd; indentBeforeDot = needsIndentation(node, node.expression, dotToken); @@ -65120,20 +78719,25 @@ var ts; if (shouldEmitDotDot) { writePunctuation("."); } - emitTokenWithComment(23, node.expression.end, writePunctuation, node); + emitTokenWithComment(23 /* DotToken */, node.expression.end, writePunctuation, node); increaseIndentIf(indentAfterDot); emit(node.name); decreaseIndentIf(indentBeforeDot, indentAfterDot); } + // 1..toString is a valid property access, emit a dot after the literal + // Also emit a dot if expression is a integer const enum value - it will appear in generated code as numeric literal function needsDotDotForPropertyAccess(expression) { expression = ts.skipPartiallyEmittedExpressions(expression); if (ts.isNumericLiteral(expression)) { + // check if numeric literal is a decimal literal that was originally written with a dot var text = getLiteralTextOfNode(expression); return !expression.numericLiteralFlags - && !ts.stringContains(text, ts.tokenToString(23)); + && !ts.stringContains(text, ts.tokenToString(23 /* DotToken */)); } else if (ts.isPropertyAccessExpression(expression) || ts.isElementAccessExpression(expression)) { + // check if constant enum value is integer var constantValue = ts.getConstantValue(expression); + // isFinite handles cases when constantValue is undefined return typeof constantValue === "number" && isFinite(constantValue) && Math.floor(constantValue) === constantValue && printerOptions.removeComments; @@ -65141,21 +78745,21 @@ var ts; } function emitElementAccessExpression(node) { emitExpression(node.expression); - emitTokenWithComment(21, node.expression.end, writePunctuation, node); + emitTokenWithComment(21 /* OpenBracketToken */, node.expression.end, writePunctuation, node); emitExpression(node.argumentExpression); - emitTokenWithComment(22, node.argumentExpression.end, writePunctuation, node); + emitTokenWithComment(22 /* CloseBracketToken */, node.argumentExpression.end, writePunctuation, node); } function emitCallExpression(node) { emitExpression(node.expression); emitTypeArguments(node, node.typeArguments); - emitExpressionList(node, node.arguments, 1296); + emitExpressionList(node, node.arguments, 1296 /* CallExpressionArguments */); } function emitNewExpression(node) { - emitTokenWithComment(94, node.pos, writeKeyword, node); + emitTokenWithComment(94 /* NewKeyword */, node.pos, writeKeyword, node); writeSpace(); emitExpression(node.expression); emitTypeArguments(node, node.typeArguments); - emitExpressionList(node, node.arguments, 9488); + emitExpressionList(node, node.arguments, 9488 /* NewExpressionArguments */); } function emitTaggedTemplateExpression(node) { emitExpression(node.tag); @@ -65170,9 +78774,9 @@ var ts; emitExpression(node.expression); } function emitParenthesizedExpression(node) { - var openParenPos = emitTokenWithComment(19, node.pos, writePunctuation, node); + var openParenPos = emitTokenWithComment(19 /* OpenParenToken */, node.pos, writePunctuation, node); emitExpression(node.expression); - emitTokenWithComment(20, node.expression ? node.expression.end : openParenPos, writePunctuation, node); + emitTokenWithComment(20 /* CloseParenToken */, node.expression ? node.expression.end : openParenPos, writePunctuation, node); } function emitFunctionExpression(node) { generateNameIfNeeded(node.name); @@ -65191,22 +78795,22 @@ var ts; emit(node.equalsGreaterThanToken); } function emitDeleteExpression(node) { - emitTokenWithComment(80, node.pos, writeKeyword, node); + emitTokenWithComment(80 /* DeleteKeyword */, node.pos, writeKeyword, node); writeSpace(); emitExpression(node.expression); } function emitTypeOfExpression(node) { - emitTokenWithComment(103, node.pos, writeKeyword, node); + emitTokenWithComment(103 /* TypeOfKeyword */, node.pos, writeKeyword, node); writeSpace(); emitExpression(node.expression); } function emitVoidExpression(node) { - emitTokenWithComment(105, node.pos, writeKeyword, node); + emitTokenWithComment(105 /* VoidKeyword */, node.pos, writeKeyword, node); writeSpace(); emitExpression(node.expression); } function emitAwaitExpression(node) { - emitTokenWithComment(121, node.pos, writeKeyword, node); + emitTokenWithComment(121 /* AwaitKeyword */, node.pos, writeKeyword, node); writeSpace(); emitExpression(node.expression); } @@ -65218,24 +78822,36 @@ var ts; emitExpression(node.operand); } function shouldEmitWhitespaceBeforeOperand(node) { + // In some cases, we need to emit a space between the operator and the operand. One obvious case + // is when the operator is an identifier, like delete or typeof. We also need to do this for plus + // and minus expressions in certain cases. Specifically, consider the following two cases (parens + // are just for clarity of exposition, and not part of the source code): + // + // (+(+1)) + // (+(++1)) + // + // We need to emit a space in both cases. In the first case, the absence of a space will make + // the resulting expression a prefix increment operation. And in the second, it will make the resulting + // expression a prefix increment whose operand is a plus expression - (++(+x)) + // The same is true of minus of course. var operand = node.operand; - return operand.kind === 198 - && ((node.operator === 37 && (operand.operator === 37 || operand.operator === 43)) - || (node.operator === 38 && (operand.operator === 38 || operand.operator === 44))); + return operand.kind === 198 /* PrefixUnaryExpression */ + && ((node.operator === 37 /* PlusToken */ && (operand.operator === 37 /* PlusToken */ || operand.operator === 43 /* PlusPlusToken */)) + || (node.operator === 38 /* MinusToken */ && (operand.operator === 38 /* MinusToken */ || operand.operator === 44 /* MinusMinusToken */))); } function emitPostfixUnaryExpression(node) { emitExpression(node.operand); writeTokenText(node.operator, writeOperator); } function emitBinaryExpression(node) { - var isCommaOperator = node.operatorToken.kind !== 26; + var isCommaOperator = node.operatorToken.kind !== 26 /* CommaToken */; var indentBeforeOperator = needsIndentation(node, node.left, node.operatorToken); var indentAfterOperator = needsIndentation(node, node.operatorToken, node.right); emitExpression(node.left); increaseIndentIf(indentBeforeOperator, isCommaOperator ? " " : undefined); emitLeadingCommentsOfPosition(node.operatorToken.pos); writeTokenNode(node.operatorToken, writeOperator); - emitTrailingCommentsOfPosition(node.operatorToken.end, true); + emitTrailingCommentsOfPosition(node.operatorToken.end, /*prefixSpace*/ true); // Binary operators should have a space before the comment starts increaseIndentIf(indentAfterOperator, " "); emitExpression(node.right); decreaseIndentIf(indentBeforeOperator, indentAfterOperator); @@ -65259,10 +78875,10 @@ var ts; } function emitTemplateExpression(node) { emit(node.head); - emitList(node, node.templateSpans, 131072); + emitList(node, node.templateSpans, 131072 /* TemplateExpressionSpans */); } function emitYieldExpression(node) { - emitTokenWithComment(116, node.pos, writeKeyword, node); + emitTokenWithComment(116 /* YieldKeyword */, node.pos, writeKeyword, node); emit(node.asteriskToken); emitExpressionWithLeadingSpace(node.expression); } @@ -65296,18 +78912,24 @@ var ts; writePunctuation("."); emit(node.name); } + // + // Misc + // function emitTemplateSpan(node) { emitExpression(node.expression); emit(node.literal); } + // + // Statements + // function emitBlock(node) { - emitBlockStatements(node, !node.multiLine && isEmptyBlock(node)); + emitBlockStatements(node, /*forceSingleLine*/ !node.multiLine && isEmptyBlock(node)); } function emitBlockStatements(node, forceSingleLine) { - emitTokenWithComment(17, node.pos, writePunctuation, node); - var format = forceSingleLine || ts.getEmitFlags(node) & 1 ? 384 : 65; + emitTokenWithComment(17 /* OpenBraceToken */, node.pos, writePunctuation, /*contextNode*/ node); + var format = forceSingleLine || ts.getEmitFlags(node) & 1 /* SingleLine */ ? 384 /* SingleLineBlockStatements */ : 65 /* MultiLineBlockStatements */; emitList(node, node.statements, format); - emitTokenWithComment(18, node.statements.end, writePunctuation, node, !!(format & 1)); + emitTokenWithComment(18 /* CloseBraceToken */, node.statements.end, writePunctuation, /*contextNode*/ node, /*indentLeading*/ !!(format & 1 /* MultiLine */)); } function emitVariableStatement(node) { emitModifiers(node, node.modifiers); @@ -65324,16 +78946,16 @@ var ts; } } function emitIfStatement(node) { - var openParenPos = emitTokenWithComment(90, node.pos, writeKeyword, node); + var openParenPos = emitTokenWithComment(90 /* IfKeyword */, node.pos, writeKeyword, node); writeSpace(); - emitTokenWithComment(19, openParenPos, writePunctuation, node); + emitTokenWithComment(19 /* OpenParenToken */, openParenPos, writePunctuation, node); emitExpression(node.expression); - emitTokenWithComment(20, node.expression.end, writePunctuation, node); + emitTokenWithComment(20 /* CloseParenToken */, node.expression.end, writePunctuation, node); emitEmbeddedStatement(node, node.thenStatement); if (node.elseStatement) { writeLineOrSpace(node); - emitTokenWithComment(82, node.thenStatement.end, writeKeyword, node); - if (node.elseStatement.kind === 217) { + emitTokenWithComment(82 /* ElseKeyword */, node.thenStatement.end, writeKeyword, node); + if (node.elseStatement.kind === 217 /* IfStatement */) { writeSpace(); emit(node.elseStatement); } @@ -65343,14 +78965,14 @@ var ts; } } function emitWhileClause(node, startPos) { - var openParenPos = emitTokenWithComment(106, startPos, writeKeyword, node); + var openParenPos = emitTokenWithComment(106 /* WhileKeyword */, startPos, writeKeyword, node); writeSpace(); - emitTokenWithComment(19, openParenPos, writePunctuation, node); + emitTokenWithComment(19 /* OpenParenToken */, openParenPos, writePunctuation, node); emitExpression(node.expression); - emitTokenWithComment(20, node.expression.end, writePunctuation, node); + emitTokenWithComment(20 /* CloseParenToken */, node.expression.end, writePunctuation, node); } function emitDoStatement(node) { - emitTokenWithComment(81, node.pos, writeKeyword, node); + emitTokenWithComment(81 /* DoKeyword */, node.pos, writeKeyword, node); emitEmbeddedStatement(node, node.statement); if (ts.isBlock(node.statement)) { writeSpace(); @@ -65366,45 +78988,45 @@ var ts; emitEmbeddedStatement(node, node.statement); } function emitForStatement(node) { - var openParenPos = emitTokenWithComment(88, node.pos, writeKeyword, node); + var openParenPos = emitTokenWithComment(88 /* ForKeyword */, node.pos, writeKeyword, node); writeSpace(); - var pos = emitTokenWithComment(19, openParenPos, writePunctuation, node); + var pos = emitTokenWithComment(19 /* OpenParenToken */, openParenPos, writePunctuation, /*contextNode*/ node); emitForBinding(node.initializer); - pos = emitTokenWithComment(25, node.initializer ? node.initializer.end : pos, writeSemicolon, node); + pos = emitTokenWithComment(25 /* SemicolonToken */, node.initializer ? node.initializer.end : pos, writeSemicolon, node); emitExpressionWithLeadingSpace(node.condition); - pos = emitTokenWithComment(25, node.condition ? node.condition.end : pos, writeSemicolon, node); + pos = emitTokenWithComment(25 /* SemicolonToken */, node.condition ? node.condition.end : pos, writeSemicolon, node); emitExpressionWithLeadingSpace(node.incrementor); - emitTokenWithComment(20, node.incrementor ? node.incrementor.end : pos, writePunctuation, node); + emitTokenWithComment(20 /* CloseParenToken */, node.incrementor ? node.incrementor.end : pos, writePunctuation, node); emitEmbeddedStatement(node, node.statement); } function emitForInStatement(node) { - var openParenPos = emitTokenWithComment(88, node.pos, writeKeyword, node); + var openParenPos = emitTokenWithComment(88 /* ForKeyword */, node.pos, writeKeyword, node); writeSpace(); - emitTokenWithComment(19, openParenPos, writePunctuation, node); + emitTokenWithComment(19 /* OpenParenToken */, openParenPos, writePunctuation, node); emitForBinding(node.initializer); writeSpace(); - emitTokenWithComment(92, node.initializer.end, writeKeyword, node); + emitTokenWithComment(92 /* InKeyword */, node.initializer.end, writeKeyword, node); writeSpace(); emitExpression(node.expression); - emitTokenWithComment(20, node.expression.end, writePunctuation, node); + emitTokenWithComment(20 /* CloseParenToken */, node.expression.end, writePunctuation, node); emitEmbeddedStatement(node, node.statement); } function emitForOfStatement(node) { - var openParenPos = emitTokenWithComment(88, node.pos, writeKeyword, node); + var openParenPos = emitTokenWithComment(88 /* ForKeyword */, node.pos, writeKeyword, node); writeSpace(); emitWithTrailingSpace(node.awaitModifier); - emitTokenWithComment(19, openParenPos, writePunctuation, node); + emitTokenWithComment(19 /* OpenParenToken */, openParenPos, writePunctuation, node); emitForBinding(node.initializer); writeSpace(); - emitTokenWithComment(145, node.initializer.end, writeKeyword, node); + emitTokenWithComment(145 /* OfKeyword */, node.initializer.end, writeKeyword, node); writeSpace(); emitExpression(node.expression); - emitTokenWithComment(20, node.expression.end, writePunctuation, node); + emitTokenWithComment(20 /* CloseParenToken */, node.expression.end, writePunctuation, node); emitEmbeddedStatement(node, node.statement); } function emitForBinding(node) { if (node !== undefined) { - if (node.kind === 233) { + if (node.kind === 233 /* VariableDeclarationList */) { emit(node); } else { @@ -65413,12 +79035,12 @@ var ts; } } function emitContinueStatement(node) { - emitTokenWithComment(77, node.pos, writeKeyword, node); + emitTokenWithComment(77 /* ContinueKeyword */, node.pos, writeKeyword, node); emitWithLeadingSpace(node.label); writeSemicolon(); } function emitBreakStatement(node) { - emitTokenWithComment(72, node.pos, writeKeyword, node); + emitTokenWithComment(72 /* BreakKeyword */, node.pos, writeKeyword, node); emitWithLeadingSpace(node.label); writeSemicolon(); } @@ -65441,45 +79063,45 @@ var ts; } pos = writeTokenText(token, writer, pos); if (emitTrailingCommentsOfPosition && isSimilarNode && contextNode.end !== pos) { - emitTrailingCommentsOfPosition(pos, true); + emitTrailingCommentsOfPosition(pos, /*prefixSpace*/ true); } return pos; } function emitReturnStatement(node) { - emitTokenWithComment(96, node.pos, writeKeyword, node); + emitTokenWithComment(96 /* ReturnKeyword */, node.pos, writeKeyword, /*contextNode*/ node); emitExpressionWithLeadingSpace(node.expression); writeSemicolon(); } function emitWithStatement(node) { - var openParenPos = emitTokenWithComment(107, node.pos, writeKeyword, node); + var openParenPos = emitTokenWithComment(107 /* WithKeyword */, node.pos, writeKeyword, node); writeSpace(); - emitTokenWithComment(19, openParenPos, writePunctuation, node); + emitTokenWithComment(19 /* OpenParenToken */, openParenPos, writePunctuation, node); emitExpression(node.expression); - emitTokenWithComment(20, node.expression.end, writePunctuation, node); + emitTokenWithComment(20 /* CloseParenToken */, node.expression.end, writePunctuation, node); emitEmbeddedStatement(node, node.statement); } function emitSwitchStatement(node) { - var openParenPos = emitTokenWithComment(98, node.pos, writeKeyword, node); + var openParenPos = emitTokenWithComment(98 /* SwitchKeyword */, node.pos, writeKeyword, node); writeSpace(); - emitTokenWithComment(19, openParenPos, writePunctuation, node); + emitTokenWithComment(19 /* OpenParenToken */, openParenPos, writePunctuation, node); emitExpression(node.expression); - emitTokenWithComment(20, node.expression.end, writePunctuation, node); + emitTokenWithComment(20 /* CloseParenToken */, node.expression.end, writePunctuation, node); writeSpace(); emit(node.caseBlock); } function emitLabeledStatement(node) { emit(node.label); - emitTokenWithComment(56, node.label.end, writePunctuation, node); + emitTokenWithComment(56 /* ColonToken */, node.label.end, writePunctuation, node); writeSpace(); emit(node.statement); } function emitThrowStatement(node) { - emitTokenWithComment(100, node.pos, writeKeyword, node); + emitTokenWithComment(100 /* ThrowKeyword */, node.pos, writeKeyword, node); emitExpressionWithLeadingSpace(node.expression); writeSemicolon(); } function emitTryStatement(node) { - emitTokenWithComment(102, node.pos, writeKeyword, node); + emitTokenWithComment(102 /* TryKeyword */, node.pos, writeKeyword, node); writeSpace(); emit(node.tryBlock); if (node.catchClause) { @@ -65488,15 +79110,18 @@ var ts; } if (node.finallyBlock) { writeLineOrSpace(node); - emitTokenWithComment(87, (node.catchClause || node.tryBlock).end, writeKeyword, node); + emitTokenWithComment(87 /* FinallyKeyword */, (node.catchClause || node.tryBlock).end, writeKeyword, node); writeSpace(); emit(node.finallyBlock); } } function emitDebuggerStatement(node) { - writeToken(78, node.pos, writeKeyword); + writeToken(78 /* DebuggerKeyword */, node.pos, writeKeyword); writeSemicolon(); } + // + // Declarations + // function emitVariableDeclaration(node) { emit(node.name); emitTypeAnnotation(node.type); @@ -65505,7 +79130,7 @@ var ts; function emitVariableDeclarationList(node) { writeKeyword(ts.isLet(node) ? "let" : ts.isConst(node) ? "const" : "var"); writeSpace(); - emitList(node, node.declarations, 272); + emitList(node, node.declarations, 272 /* VariableDeclarationList */); } function emitFunctionDeclaration(node) { emitFunctionDeclarationOrExpression(node); @@ -65516,7 +79141,7 @@ var ts; writeKeyword("function"); emit(node.asteriskToken); writeSpace(); - emitIdentifierName(node.name); + emitIdentifierName(node.name); // TODO: GH#18217 emitSignatureAndBody(node, emitSignatureHead); } function emitBlockCallback(_hint, body) { @@ -65526,7 +79151,7 @@ var ts; var body = node.body; if (body) { if (ts.isBlock(body)) { - var indentedFlag = ts.getEmitFlags(node) & 65536; + var indentedFlag = ts.getEmitFlags(node) & 65536 /* Indented */; if (indentedFlag) { increaseIndent(); } @@ -65535,7 +79160,7 @@ var ts; generateNames(node.body); emitSignatureHead(node); if (onEmitNode) { - onEmitNode(4, body, emitBlockCallback); + onEmitNode(4 /* Unspecified */, body, emitBlockCallback); } else { emitBlockFunctionBody(body); @@ -65562,7 +79187,13 @@ var ts; emitTypeAnnotation(node.type); } function shouldEmitBlockFunctionBodyOnSingleLine(body) { - if (ts.getEmitFlags(body) & 1) { + // We must emit a function body as a single-line body in the following case: + // * The body has NodeEmitFlags.SingleLine specified. + // We must emit a function body as a multi-line body in the following cases: + // * The body is explicitly marked as multi-line. + // * A non-synthesized body's start and end position are on different lines. + // * Any statement in the body starts on a new line. + if (ts.getEmitFlags(body) & 1 /* SingleLine */) { return true; } if (body.multiLine) { @@ -65571,14 +79202,14 @@ var ts; if (!ts.nodeIsSynthesized(body) && !ts.rangeIsOnSingleLine(body, currentSourceFile)) { return false; } - if (shouldWriteLeadingLineTerminator(body, body.statements, 2) - || shouldWriteClosingLineTerminator(body, body.statements, 2)) { + if (shouldWriteLeadingLineTerminator(body, body.statements, 2 /* PreserveLines */) + || shouldWriteClosingLineTerminator(body, body.statements, 2 /* PreserveLines */)) { return false; } var previousStatement; for (var _a = 0, _b = body.statements; _a < _b.length; _a++) { var statement = _b[_a]; - if (shouldWriteSeparatingLineTerminator(previousStatement, statement, 2)) { + if (shouldWriteSeparatingLineTerminator(previousStatement, statement, 2 /* PreserveLines */)) { return false; } previousStatement = statement; @@ -65599,22 +79230,23 @@ var ts; emitBlockFunctionBody(body); } decreaseIndent(); - writeToken(18, body.statements.end, writePunctuation, body); + writeToken(18 /* CloseBraceToken */, body.statements.end, writePunctuation, body); } function emitBlockFunctionBodyOnSingleLine(body) { - emitBlockFunctionBodyWorker(body, true); + emitBlockFunctionBodyWorker(body, /*emitBlockFunctionBodyOnSingleLine*/ true); } function emitBlockFunctionBodyWorker(body, emitBlockFunctionBodyOnSingleLine) { - var statementOffset = emitPrologueDirectives(body.statements, true); + // Emit all the prologue directives (like "use strict"). + var statementOffset = emitPrologueDirectives(body.statements, /*startWithNewLine*/ true); var pos = writer.getTextPos(); emitHelpers(body); if (statementOffset === 0 && pos === writer.getTextPos() && emitBlockFunctionBodyOnSingleLine) { decreaseIndent(); - emitList(body, body.statements, 384); + emitList(body, body.statements, 384 /* SingleLineFunctionBodyStatements */); increaseIndent(); } else { - emitList(body, body.statements, 1, statementOffset); + emitList(body, body.statements, 1 /* MultiLineFunctionBodyStatements */, statementOffset); } } function emitClassDeclaration(node) { @@ -65629,15 +79261,15 @@ var ts; writeSpace(); emitIdentifierName(node.name); } - var indentedFlag = ts.getEmitFlags(node) & 65536; + var indentedFlag = ts.getEmitFlags(node) & 65536 /* Indented */; if (indentedFlag) { increaseIndent(); } emitTypeParameters(node, node.typeParameters); - emitList(node, node.heritageClauses, 0); + emitList(node, node.heritageClauses, 0 /* ClassHeritageClauses */); writeSpace(); writePunctuation("{"); - emitList(node, node.members, 65); + emitList(node, node.members, 65 /* ClassMembers */); writePunctuation("}"); if (indentedFlag) { decreaseIndent(); @@ -65650,10 +79282,10 @@ var ts; writeSpace(); emit(node.name); emitTypeParameters(node, node.typeParameters); - emitList(node, node.heritageClauses, 256); + emitList(node, node.heritageClauses, 256 /* HeritageClauses */); writeSpace(); writePunctuation("{"); - emitList(node, node.members, 65); + emitList(node, node.members, 65 /* InterfaceMembers */); writePunctuation("}"); } function emitTypeAliasDeclaration(node) { @@ -65676,20 +79308,20 @@ var ts; emit(node.name); writeSpace(); writePunctuation("{"); - emitList(node, node.members, 81); + emitList(node, node.members, 81 /* EnumMembers */); writePunctuation("}"); } function emitModuleDeclaration(node) { emitModifiers(node, node.modifiers); - if (~node.flags & 512) { - writeKeyword(node.flags & 16 ? "namespace" : "module"); + if (~node.flags & 512 /* GlobalAugmentation */) { + writeKeyword(node.flags & 16 /* Namespace */ ? "namespace" : "module"); writeSpace(); } emit(node.name); var body = node.body; if (!body) return writeSemicolon(); - while (body.kind === 239) { + while (body.kind === 239 /* ModuleDeclaration */) { writePunctuation("."); emit(body.name); body = body.body; @@ -65700,27 +79332,27 @@ var ts; function emitModuleBlock(node) { pushNameGenerationScope(node); ts.forEach(node.statements, generateNames); - emitBlockStatements(node, isEmptyBlock(node)); + emitBlockStatements(node, /*forceSingleLine*/ isEmptyBlock(node)); popNameGenerationScope(node); } function emitCaseBlock(node) { - emitTokenWithComment(17, node.pos, writePunctuation, node); - emitList(node, node.clauses, 65); - emitTokenWithComment(18, node.clauses.end, writePunctuation, node, true); + emitTokenWithComment(17 /* OpenBraceToken */, node.pos, writePunctuation, node); + emitList(node, node.clauses, 65 /* CaseBlockClauses */); + emitTokenWithComment(18 /* CloseBraceToken */, node.clauses.end, writePunctuation, node, /*indentLeading*/ true); } function emitImportEqualsDeclaration(node) { emitModifiers(node, node.modifiers); - emitTokenWithComment(91, node.modifiers ? node.modifiers.end : node.pos, writeKeyword, node); + emitTokenWithComment(91 /* ImportKeyword */, node.modifiers ? node.modifiers.end : node.pos, writeKeyword, node); writeSpace(); emit(node.name); writeSpace(); - emitTokenWithComment(58, node.name.end, writePunctuation, node); + emitTokenWithComment(58 /* EqualsToken */, node.name.end, writePunctuation, node); writeSpace(); emitModuleReference(node.moduleReference); writeSemicolon(); } function emitModuleReference(node) { - if (node.kind === 71) { + if (node.kind === 71 /* Identifier */) { emitExpression(node); } else { @@ -65729,12 +79361,12 @@ var ts; } function emitImportDeclaration(node) { emitModifiers(node, node.modifiers); - emitTokenWithComment(91, node.modifiers ? node.modifiers.end : node.pos, writeKeyword, node); + emitTokenWithComment(91 /* ImportKeyword */, node.modifiers ? node.modifiers.end : node.pos, writeKeyword, node); writeSpace(); if (node.importClause) { emit(node.importClause); writeSpace(); - emitTokenWithComment(143, node.importClause.end, writeKeyword, node); + emitTokenWithComment(143 /* FromKeyword */, node.importClause.end, writeKeyword, node); writeSpace(); } emitExpression(node.moduleSpecifier); @@ -65743,15 +79375,15 @@ var ts; function emitImportClause(node) { emit(node.name); if (node.name && node.namedBindings) { - emitTokenWithComment(26, node.name.end, writePunctuation, node); + emitTokenWithComment(26 /* CommaToken */, node.name.end, writePunctuation, node); writeSpace(); } emit(node.namedBindings); } function emitNamespaceImport(node) { - var asPos = emitTokenWithComment(39, node.pos, writePunctuation, node); + var asPos = emitTokenWithComment(39 /* AsteriskToken */, node.pos, writePunctuation, node); writeSpace(); - emitTokenWithComment(118, asPos, writeKeyword, node); + emitTokenWithComment(118 /* AsKeyword */, asPos, writeKeyword, node); writeSpace(); emit(node.name); } @@ -65762,42 +79394,42 @@ var ts; emitImportOrExportSpecifier(node); } function emitExportAssignment(node) { - var nextPos = emitTokenWithComment(84, node.pos, writeKeyword, node); + var nextPos = emitTokenWithComment(84 /* ExportKeyword */, node.pos, writeKeyword, node); writeSpace(); if (node.isExportEquals) { - emitTokenWithComment(58, nextPos, writeOperator, node); + emitTokenWithComment(58 /* EqualsToken */, nextPos, writeOperator, node); } else { - emitTokenWithComment(79, nextPos, writeKeyword, node); + emitTokenWithComment(79 /* DefaultKeyword */, nextPos, writeKeyword, node); } writeSpace(); emitExpression(node.expression); writeSemicolon(); } function emitExportDeclaration(node) { - var nextPos = emitTokenWithComment(84, node.pos, writeKeyword, node); + var nextPos = emitTokenWithComment(84 /* ExportKeyword */, node.pos, writeKeyword, node); writeSpace(); if (node.exportClause) { emit(node.exportClause); } else { - nextPos = emitTokenWithComment(39, nextPos, writePunctuation, node); + nextPos = emitTokenWithComment(39 /* AsteriskToken */, nextPos, writePunctuation, node); } if (node.moduleSpecifier) { writeSpace(); var fromPos = node.exportClause ? node.exportClause.end : nextPos; - emitTokenWithComment(143, fromPos, writeKeyword, node); + emitTokenWithComment(143 /* FromKeyword */, fromPos, writeKeyword, node); writeSpace(); emitExpression(node.moduleSpecifier); } writeSemicolon(); } function emitNamespaceExportDeclaration(node) { - var nextPos = emitTokenWithComment(84, node.pos, writeKeyword, node); + var nextPos = emitTokenWithComment(84 /* ExportKeyword */, node.pos, writeKeyword, node); writeSpace(); - nextPos = emitTokenWithComment(118, nextPos, writeKeyword, node); + nextPos = emitTokenWithComment(118 /* AsKeyword */, nextPos, writeKeyword, node); writeSpace(); - nextPos = emitTokenWithComment(130, nextPos, writeKeyword, node); + nextPos = emitTokenWithComment(130 /* NamespaceKeyword */, nextPos, writeKeyword, node); writeSpace(); emit(node.name); writeSemicolon(); @@ -65810,27 +79442,33 @@ var ts; } function emitNamedImportsOrExports(node) { writePunctuation("{"); - emitList(node, node.elements, 262576); + emitList(node, node.elements, 262576 /* NamedImportsOrExportsElements */); writePunctuation("}"); } function emitImportOrExportSpecifier(node) { if (node.propertyName) { emit(node.propertyName); writeSpace(); - emitTokenWithComment(118, node.propertyName.end, writeKeyword, node); + emitTokenWithComment(118 /* AsKeyword */, node.propertyName.end, writeKeyword, node); writeSpace(); } emit(node.name); } + // + // Module references + // function emitExternalModuleReference(node) { writeKeyword("require"); writePunctuation("("); emitExpression(node.expression); writePunctuation(")"); } + // + // JSX + // function emitJsxElement(node) { emit(node.openingElement); - emitList(node, node.children, 131072); + emitList(node, node.children, 131072 /* JsxElementOrFragmentChildren */); emit(node.closingElement); } function emitJsxSelfClosingElement(node) { @@ -65842,7 +79480,7 @@ var ts; } function emitJsxFragment(node) { emit(node.openingFragment); - emitList(node, node.children, 131072); + emitList(node, node.children, 131072 /* JsxElementOrFragmentChildren */); emit(node.closingFragment); } function emitJsxOpeningElementOrFragment(node) { @@ -65858,7 +79496,7 @@ var ts; } function emitJsxText(node) { commitPendingSemicolon(); - writer.writeLiteral(getTextOfNode(node, true)); + writer.writeLiteral(getTextOfNode(node, /*includeTrivia*/ true)); } function emitJsxClosingElementOrFragment(node) { writePunctuation(""); } function emitJsxAttributes(node) { - emitList(node, node.properties, 131328); + emitList(node, node.properties, 131328 /* JsxElementAttributes */); } function emitJsxAttribute(node) { emit(node.name); - emitNodeWithPrefix("=", writePunctuation, node.initializer, emit); + emitNodeWithPrefix("=", writePunctuation, node.initializer, emit); // TODO: GH#18217 } function emitJsxSpreadAttribute(node) { writePunctuation("{..."); @@ -65888,36 +79526,41 @@ var ts; } } function emitJsxTagName(node) { - if (node.kind === 71) { + if (node.kind === 71 /* Identifier */) { emitExpression(node); } else { emit(node); } } + // + // Clauses + // function emitCaseClause(node) { - emitTokenWithComment(73, node.pos, writeKeyword, node); + emitTokenWithComment(73 /* CaseKeyword */, node.pos, writeKeyword, node); writeSpace(); emitExpression(node.expression); emitCaseOrDefaultClauseRest(node, node.statements, node.expression.end); } function emitDefaultClause(node) { - var pos = emitTokenWithComment(79, node.pos, writeKeyword, node); + var pos = emitTokenWithComment(79 /* DefaultKeyword */, node.pos, writeKeyword, node); emitCaseOrDefaultClauseRest(node, node.statements, pos); } function emitCaseOrDefaultClauseRest(parentNode, statements, colonPos) { var emitAsSingleStatement = statements.length === 1 && - (ts.nodeIsSynthesized(parentNode) || + ( + // treat synthesized nodes as located on the same line for emit purposes + ts.nodeIsSynthesized(parentNode) || ts.nodeIsSynthesized(statements[0]) || ts.rangeStartPositionsAreOnSameLine(parentNode, statements[0], currentSourceFile)); - var format = 81985; + var format = 81985 /* CaseOrDefaultClauseStatements */; if (emitAsSingleStatement) { - writeToken(56, colonPos, writePunctuation, parentNode); + writeToken(56 /* ColonToken */, colonPos, writePunctuation, parentNode); writeSpace(); - format &= ~(1 | 64); + format &= ~(1 /* MultiLine */ | 64 /* Indented */); } else { - emitTokenWithComment(56, colonPos, writePunctuation, parentNode); + emitTokenWithComment(56 /* ColonToken */, colonPos, writePunctuation, parentNode); } emitList(parentNode, statements, format); } @@ -65925,25 +79568,35 @@ var ts; writeSpace(); writeTokenText(node.token, writeKeyword); writeSpace(); - emitList(node, node.types, 272); + emitList(node, node.types, 272 /* HeritageClauseTypes */); } function emitCatchClause(node) { - var openParenPos = emitTokenWithComment(74, node.pos, writeKeyword, node); + var openParenPos = emitTokenWithComment(74 /* CatchKeyword */, node.pos, writeKeyword, node); writeSpace(); if (node.variableDeclaration) { - emitTokenWithComment(19, openParenPos, writePunctuation, node); + emitTokenWithComment(19 /* OpenParenToken */, openParenPos, writePunctuation, node); emit(node.variableDeclaration); - emitTokenWithComment(20, node.variableDeclaration.end, writePunctuation, node); + emitTokenWithComment(20 /* CloseParenToken */, node.variableDeclaration.end, writePunctuation, node); writeSpace(); } emit(node.block); } + // + // Property assignments + // function emitPropertyAssignment(node) { emit(node.name); writePunctuation(":"); writeSpace(); + // This is to ensure that we emit comment in the following case: + // For example: + // obj = { + // id: /*comment1*/ ()=>void + // } + // "comment1" is not considered to be leading comment for node.initializer + // but rather a trailing comment on the previous node. var initializer = node.initializer; - if (emitTrailingCommentsOfPosition && (ts.getEmitFlags(initializer) & 512) === 0) { + if (emitTrailingCommentsOfPosition && (ts.getEmitFlags(initializer) & 512 /* NoLeadingComments */) === 0) { var commentRange = ts.getCommentRange(initializer); emitTrailingCommentsOfPosition(commentRange.pos); } @@ -65964,14 +79617,22 @@ var ts; emitExpression(node.expression); } } + // + // Enum + // function emitEnumMember(node) { emit(node.name); emitInitializer(node.initializer, node.name.end, node); } + // + // Top-level nodes + // function emitSourceFile(node) { writeLine(); var statements = node.statements; if (emitBodyWithDetachedComments) { + // Emit detached comment if there are no prologue directives or if the first node is synthesized. + // The synthesized node will have no leading comment so some comments may be missed. var shouldEmitDetachedComment = statements.length === 0 || !ts.isPrologueDirective(statements[0]) || ts.nodeIsSynthesized(statements[0]); @@ -66028,15 +79689,20 @@ var ts; emitHelpers(node); var index = ts.findIndex(statements, function (statement) { return !ts.isPrologueDirective(statement); }); emitTripleSlashDirectivesIfNeeded(node); - emitList(node, statements, 1, index === -1 ? statements.length : index); + emitList(node, statements, 1 /* MultiLine */, index === -1 ? statements.length : index); popNameGenerationScope(node); } + // Transformation nodes function emitPartiallyEmittedExpression(node) { emitExpression(node.expression); } function emitCommaList(node) { - emitExpressionList(node, node.elements, 272); + emitExpressionList(node, node.elements, 272 /* CommaListElements */); } + /** + * Emits any prologue directives at the start of a Statement list, returning the + * number of prologue directives written to the output. + */ function emitPrologueDirectives(statements, startWithNewLine, seenPrologueDirectives) { for (var i = 0; i < statements.length; i++) { var statement = statements[i]; @@ -66053,6 +79719,7 @@ var ts; } } else { + // return index of the first non prologue directive return i; } } @@ -66068,7 +79735,7 @@ var ts; for (var _a = 0, _b = sourceFileOrBundle.sourceFiles; _a < _b.length; _a++) { var sourceFile = _b[_a]; setSourceFile(sourceFile); - emitPrologueDirectives(sourceFile.statements, true, seenPrologueDirectives); + emitPrologueDirectives(sourceFile.statements, /*startWithNewLine*/ true, seenPrologueDirectives); } } } @@ -66084,12 +79751,16 @@ var ts; else { for (var _a = 0, _b = sourceFileOrBundle.sourceFiles; _a < _b.length; _a++) { var sourceFile = _b[_a]; + // Emit only the first encountered shebang if (emitShebangIfNeeded(sourceFile)) { break; } } } } + // + // Helpers + // function emitNodeWithWriter(node, writer) { if (!node) return; @@ -66100,7 +79771,7 @@ var ts; } function emitModifiers(node, modifiers) { if (modifiers && modifiers.length) { - emitList(node, modifiers, 131328); + emitList(node, modifiers, 131328 /* Modifiers */); writeSpace(); } } @@ -66114,7 +79785,7 @@ var ts; function emitInitializer(node, equalCommentStartPos, container) { if (node) { writeSpace(); - emitTokenWithComment(58, equalCommentStartPos, writeOperator, container); + emitTokenWithComment(58 /* EqualsToken */, equalCommentStartPos, writeOperator, container); writeSpace(); emitExpression(node); } @@ -66144,7 +79815,7 @@ var ts; } } function emitEmbeddedStatement(parent, node) { - if (ts.isBlock(node) || ts.getEmitFlags(parent) & 1) { + if (ts.isBlock(node) || ts.getEmitFlags(parent) & 1 /* SingleLine */) { writeSpace(); emit(node); } @@ -66156,65 +79827,65 @@ var ts; } } function emitDecorators(parentNode, decorators) { - emitList(parentNode, decorators, 24577); + emitList(parentNode, decorators, 24577 /* Decorators */); } function emitTypeArguments(parentNode, typeArguments) { - emitList(parentNode, typeArguments, 26896); + emitList(parentNode, typeArguments, 26896 /* TypeArguments */); } function emitTypeParameters(parentNode, typeParameters) { - if (ts.isFunctionLike(parentNode) && parentNode.typeArguments) { + if (ts.isFunctionLike(parentNode) && parentNode.typeArguments) { // Quick info uses type arguments in place of type parameters on instantiated signatures return emitTypeArguments(parentNode, parentNode.typeArguments); } - emitList(parentNode, typeParameters, 26896); + emitList(parentNode, typeParameters, 26896 /* TypeParameters */); } function emitParameters(parentNode, parameters) { - emitList(parentNode, parameters, 1296); + emitList(parentNode, parameters, 1296 /* Parameters */); } function canEmitSimpleArrowHead(parentNode, parameters) { var parameter = ts.singleOrUndefined(parameters); return parameter - && parameter.pos === parentNode.pos - && !(ts.isArrowFunction(parentNode) && parentNode.type) - && !ts.some(parentNode.decorators) - && !ts.some(parentNode.modifiers) - && !ts.some(parentNode.typeParameters) - && !ts.some(parameter.decorators) - && !ts.some(parameter.modifiers) - && !parameter.dotDotDotToken - && !parameter.questionToken - && !parameter.type - && !parameter.initializer - && ts.isIdentifier(parameter.name); + && parameter.pos === parentNode.pos // may not have parsed tokens between parent and parameter + && !(ts.isArrowFunction(parentNode) && parentNode.type) // arrow function may not have return type annotation + && !ts.some(parentNode.decorators) // parent may not have decorators + && !ts.some(parentNode.modifiers) // parent may not have modifiers + && !ts.some(parentNode.typeParameters) // parent may not have type parameters + && !ts.some(parameter.decorators) // parameter may not have decorators + && !ts.some(parameter.modifiers) // parameter may not have modifiers + && !parameter.dotDotDotToken // parameter may not be rest + && !parameter.questionToken // parameter may not be optional + && !parameter.type // parameter may not have a type annotation + && !parameter.initializer // parameter may not have an initializer + && ts.isIdentifier(parameter.name); // parameter name must be identifier } function emitParametersForArrow(parentNode, parameters) { if (canEmitSimpleArrowHead(parentNode, parameters)) { - emitList(parentNode, parameters, 1296 & ~1024); + emitList(parentNode, parameters, 1296 /* Parameters */ & ~1024 /* Parenthesis */); } else { emitParameters(parentNode, parameters); } } function emitParametersForIndexSignature(parentNode, parameters) { - emitList(parentNode, parameters, 4432); + emitList(parentNode, parameters, 4432 /* IndexSignatureParameters */); } function emitList(parentNode, children, format, start, count) { emitNodeList(emit, parentNode, children, format, start, count); } function emitExpressionList(parentNode, children, format, start, count) { - emitNodeList(emitExpression, parentNode, children, format, start, count); + emitNodeList(emitExpression, parentNode, children, format, start, count); // TODO: GH#18217 } function writeDelimiter(format) { - switch (format & 28) { - case 0: + switch (format & 28 /* DelimitersMask */) { + case 0 /* None */: break; - case 16: + case 16 /* CommaDelimited */: writePunctuation(","); break; - case 4: + case 4 /* BarDelimited */: writeSpace(); writePunctuation("|"); break; - case 8: + case 8 /* AmpersandDelimited */: writeSpace(); writePunctuation("&"); break; @@ -66224,11 +79895,11 @@ var ts; if (start === void 0) { start = 0; } if (count === void 0) { count = children ? children.length - start : 0; } var isUndefined = children === undefined; - if (isUndefined && format & 8192) { + if (isUndefined && format & 8192 /* OptionalIfUndefined */) { return; } var isEmpty = children === undefined || start >= children.length || count === 0; - if (isEmpty && format & 16384) { + if (isEmpty && format & 16384 /* OptionalIfEmpty */) { if (onBeforeEmitNodeArray) { onBeforeEmitNodeArray(children); } @@ -66237,57 +79908,73 @@ var ts; } return; } - if (format & 7680) { + if (format & 7680 /* BracketsMask */) { writePunctuation(getOpeningBracket(format)); if (isEmpty && !isUndefined) { - emitTrailingCommentsOfPosition(children.pos, true); + // TODO: GH#18217 + emitTrailingCommentsOfPosition(children.pos, /*prefixSpace*/ true); // Emit comments within empty bracketed lists } } if (onBeforeEmitNodeArray) { onBeforeEmitNodeArray(children); } if (isEmpty) { - if (format & 1) { + // Write a line terminator if the parent node was multi-line + if (format & 1 /* MultiLine */) { writeLine(); } - else if (format & 128 && !(format & 262144)) { + else if (format & 128 /* SpaceBetweenBraces */ && !(format & 262144 /* NoSpaceIfEmpty */)) { writeSpace(); } } else { - var mayEmitInterveningComments = (format & 131072) === 0; + // Write the opening line terminator or leading whitespace. + var mayEmitInterveningComments = (format & 131072 /* NoInterveningComments */) === 0; var shouldEmitInterveningComments = mayEmitInterveningComments; - if (shouldWriteLeadingLineTerminator(parentNode, children, format)) { + if (shouldWriteLeadingLineTerminator(parentNode, children, format)) { // TODO: GH#18217 writeLine(); shouldEmitInterveningComments = false; } - else if (format & 128) { + else if (format & 128 /* SpaceBetweenBraces */) { writeSpace(); } - if (format & 64) { + // Increase the indent, if requested. + if (format & 64 /* Indented */) { increaseIndent(); } + // Emit each child. var previousSibling = void 0; var shouldDecreaseIndentAfterEmit = false; for (var i = 0; i < count; i++) { var child = children[start + i]; + // Write the delimiter if this is not the first node. if (previousSibling) { - if (format & 28 && previousSibling.end !== parentNode.end) { + // i.e + // function commentedParameters( + // /* Parameter a */ + // a + // /* End of parameter a */ -> this comment isn't considered to be trailing comment of parameter "a" due to newline + // , + if (format & 28 /* DelimitersMask */ && previousSibling.end !== parentNode.end) { emitLeadingCommentsOfPosition(previousSibling.end); } writeDelimiter(format); + // Write either a line terminator or whitespace to separate the elements. if (shouldWriteSeparatingLineTerminator(previousSibling, child, format)) { - if ((format & (3 | 64)) === 0) { + // If a synthesized node in a single-line list starts on a new + // line, we should increase the indent. + if ((format & (3 /* LinesMask */ | 64 /* Indented */)) === 0 /* SingleLine */) { increaseIndent(); shouldDecreaseIndentAfterEmit = true; } writeLine(); shouldEmitInterveningComments = false; } - else if (previousSibling && format & 256) { + else if (previousSibling && format & 256 /* SpaceBetweenSiblings */) { writeSpace(); } } + // Emit this child. if (shouldEmitInterveningComments) { if (emitTrailingCommentsOfPosition) { var commentRange = ts.getCommentRange(child); @@ -66304,29 +79991,39 @@ var ts; } previousSibling = child; } - var hasTrailingComma = (format & 32) && children.hasTrailingComma; - if (format & 16 && hasTrailingComma) { + // Write a trailing comma, if requested. + var hasTrailingComma = (format & 32 /* AllowTrailingComma */) && children.hasTrailingComma; + if (format & 16 /* CommaDelimited */ && hasTrailingComma) { writePunctuation(","); } - if (previousSibling && format & 28 && previousSibling.end !== parentNode.end && !(ts.getEmitFlags(previousSibling) & 1024)) { + // Emit any trailing comment of the last element in the list + // i.e + // var array = [... + // 2 + // /* end of element 2 */ + // ]; + if (previousSibling && format & 28 /* DelimitersMask */ && previousSibling.end !== parentNode.end && !(ts.getEmitFlags(previousSibling) & 1024 /* NoTrailingComments */)) { emitLeadingCommentsOfPosition(previousSibling.end); } - if (format & 64) { + // Decrease the indent, if requested. + if (format & 64 /* Indented */) { decreaseIndent(); } + // Write the closing line terminator or closing whitespace. if (shouldWriteClosingLineTerminator(parentNode, children, format)) { writeLine(); } - else if (format & 128) { + else if (format & 128 /* SpaceBetweenBraces */) { writeSpace(); } } if (onAfterEmitNodeArray) { onAfterEmitNodeArray(children); } - if (format & 7680) { + if (format & 7680 /* BracketsMask */) { if (isEmpty && !isUndefined) { - emitLeadingCommentsOfPosition(children.end); + // TODO: GH#18217 + emitLeadingCommentsOfPosition(children.end); // Emit leading comments within empty lists } writePunctuation(getClosingBracket(format)); } @@ -66415,7 +80112,7 @@ var ts; return pos < 0 ? pos : pos + tokenString.length; } function writeLineOrSpace(node) { - if (ts.getEmitFlags(node) & 1) { + if (ts.getEmitFlags(node) & 1 /* SingleLine */) { writeSpace(); } else { @@ -66444,6 +80141,10 @@ var ts; write(valueToWriteWhenNotIndenting); } } + // Helper function to decrease the indent if we previously indented. Allows multiple + // previous indent values to be considered at a time. This also allows caller to just + // call this once, passing in all their appropriate indent values, instead of needing + // to call this helper function multiple times. function decreaseIndentIf(value1, value2) { if (value1) { decreaseIndent(); @@ -66453,11 +80154,11 @@ var ts; } } function shouldWriteLeadingLineTerminator(parentNode, children, format) { - if (format & 1) { + if (format & 1 /* MultiLine */) { return true; } - if (format & 2) { - if (format & 32768) { + if (format & 2 /* PreserveLines */) { + if (format & 32768 /* PreferNewLine */) { return true; } var firstChild = children[0]; @@ -66476,10 +80177,10 @@ var ts; } } function shouldWriteSeparatingLineTerminator(previousNode, nextNode, format) { - if (format & 1) { + if (format & 1 /* MultiLine */) { return true; } - else if (format & 2) { + else if (format & 2 /* PreserveLines */) { if (previousNode === undefined || nextNode === undefined) { return false; } @@ -66495,11 +80196,11 @@ var ts; } } function shouldWriteClosingLineTerminator(parentNode, children, format) { - if (format & 1) { - return (format & 65536) === 0; + if (format & 1 /* MultiLine */) { + return (format & 65536 /* NoTrailingNewLine */) === 0; } - else if (format & 2) { - if (format & 32768) { + else if (format & 2 /* PreserveLines */) { + if (format & 32768 /* PreferNewLine */) { return true; } var lastChild = ts.lastOrUndefined(children); @@ -66521,16 +80222,17 @@ var ts; if (ts.nodeIsSynthesized(node)) { var startsOnNewLine = ts.getStartsOnNewLine(node); if (startsOnNewLine === undefined) { - return (format & 32768) !== 0; + return (format & 32768 /* PreferNewLine */) !== 0; } return startsOnNewLine; } - return (format & 32768) !== 0; + return (format & 32768 /* PreferNewLine */) !== 0; } function needsIndentation(parent, node1, node2) { parent = skipSynthesizedParentheses(parent); node1 = skipSynthesizedParentheses(node1); node2 = skipSynthesizedParentheses(node2); + // Always use a newline for synthesized code if the synthesizer desires it. if (ts.getStartsOnNewLine(node2)) { return true; } @@ -66544,7 +80246,7 @@ var ts; && ts.rangeEndIsOnSameLineAsRangeStart(block, block, currentSourceFile); } function skipSynthesizedParentheses(node) { - while (node.kind === 191 && ts.nodeIsSynthesized(node)) { + while (node.kind === 191 /* ParenthesizedExpression */ && ts.nodeIsSynthesized(node)) { node = node.expression; } return node; @@ -66556,7 +80258,7 @@ var ts; else if (ts.isIdentifier(node) && (ts.nodeIsSynthesized(node) || !node.parent || !currentSourceFile || (node.parent && currentSourceFile && ts.getSourceFileOfNode(node) !== ts.getOriginalNode(currentSourceFile)))) { return ts.idText(node); } - else if (node.kind === 9 && node.textSourceNode) { + else if (node.kind === 9 /* StringLiteral */ && node.textSourceNode) { return getTextOfNode(node.textSourceNode, includeTrivia); } else if (ts.isLiteralExpression(node) && (ts.nodeIsSynthesized(node) || !node.parent)) { @@ -66565,10 +80267,10 @@ var ts; return ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node, includeTrivia); } function getLiteralTextOfNode(node) { - if (node.kind === 9 && node.textSourceNode) { + if (node.kind === 9 /* StringLiteral */ && node.textSourceNode) { var textSourceNode = node.textSourceNode; if (ts.isIdentifier(textSourceNode)) { - return ts.getEmitFlags(node) & 16777216 ? + return ts.getEmitFlags(node) & 16777216 /* NoAsciiEscaping */ ? "\"" + ts.escapeString(getTextOfNode(textSourceNode)) + "\"" : "\"" + ts.escapeNonAsciiString(getTextOfNode(textSourceNode)) + "\""; } @@ -66578,16 +80280,22 @@ var ts; } return ts.getLiteralText(node, currentSourceFile); } + /** + * Push a new name generation scope. + */ function pushNameGenerationScope(node) { - if (node && ts.getEmitFlags(node) & 524288) { + if (node && ts.getEmitFlags(node) & 524288 /* ReuseTempVariableScope */) { return; } tempFlagsStack.push(tempFlags); tempFlags = 0; reservedNamesStack.push(reservedNames); } + /** + * Pop the current name generation scope. + */ function popNameGenerationScope(node) { - if (node && ts.getEmitFlags(node) & 524288) { + if (node && ts.getEmitFlags(node) & 524288 /* ReuseTempVariableScope */) { return; } tempFlags = tempFlagsStack.pop(); @@ -66603,81 +80311,81 @@ var ts; if (!node) return; switch (node.kind) { - case 213: + case 213 /* Block */: ts.forEach(node.statements, generateNames); break; - case 228: - case 226: - case 218: - case 219: + case 228 /* LabeledStatement */: + case 226 /* WithStatement */: + case 218 /* DoStatement */: + case 219 /* WhileStatement */: generateNames(node.statement); break; - case 217: + case 217 /* IfStatement */: generateNames(node.thenStatement); generateNames(node.elseStatement); break; - case 220: - case 222: - case 221: + case 220 /* ForStatement */: + case 222 /* ForOfStatement */: + case 221 /* ForInStatement */: generateNames(node.initializer); generateNames(node.statement); break; - case 227: + case 227 /* SwitchStatement */: generateNames(node.caseBlock); break; - case 241: + case 241 /* CaseBlock */: ts.forEach(node.clauses, generateNames); break; - case 266: - case 267: + case 266 /* CaseClause */: + case 267 /* DefaultClause */: ts.forEach(node.statements, generateNames); break; - case 230: + case 230 /* TryStatement */: generateNames(node.tryBlock); generateNames(node.catchClause); generateNames(node.finallyBlock); break; - case 269: + case 269 /* CatchClause */: generateNames(node.variableDeclaration); generateNames(node.block); break; - case 214: + case 214 /* VariableStatement */: generateNames(node.declarationList); break; - case 233: + case 233 /* VariableDeclarationList */: ts.forEach(node.declarations, generateNames); break; - case 232: - case 149: - case 182: - case 235: + case 232 /* VariableDeclaration */: + case 149 /* Parameter */: + case 182 /* BindingElement */: + case 235 /* ClassDeclaration */: generateNameIfNeeded(node.name); break; - case 234: + case 234 /* FunctionDeclaration */: generateNameIfNeeded(node.name); - if (ts.getEmitFlags(node) & 524288) { + if (ts.getEmitFlags(node) & 524288 /* ReuseTempVariableScope */) { ts.forEach(node.parameters, generateNames); generateNames(node.body); } break; - case 180: - case 181: + case 180 /* ObjectBindingPattern */: + case 181 /* ArrayBindingPattern */: ts.forEach(node.elements, generateNames); break; - case 244: + case 244 /* ImportDeclaration */: generateNames(node.importClause); break; - case 245: + case 245 /* ImportClause */: generateNameIfNeeded(node.name); generateNames(node.namedBindings); break; - case 246: + case 246 /* NamespaceImport */: generateNameIfNeeded(node.name); break; - case 247: + case 247 /* NamedImports */: ts.forEach(node.elements, generateNames); break; - case 248: + case 248 /* ImportSpecifier */: generateNameIfNeeded(node.propertyName || node.name); break; } @@ -66686,12 +80394,12 @@ var ts; if (!node) return; switch (node.kind) { - case 270: - case 271: - case 152: - case 154: - case 156: - case 157: + case 270 /* PropertyAssignment */: + case 271 /* ShorthandPropertyAssignment */: + case 152 /* PropertyDeclaration */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: generateNameIfNeeded(node.name); break; } @@ -66706,11 +80414,18 @@ var ts; } } } + /** + * Generate the text for a generated identifier. + */ function generateName(name) { - if ((name.autoGenerateFlags & 7) === 4) { + if ((name.autoGenerateFlags & 7 /* KindMask */) === 4 /* Node */) { + // Node names generate unique names based on their original node + // and are cached based on that node's id. return generateNameCached(getNodeForGeneratedName(name), name.autoGenerateFlags); } else { + // Auto, Loop, and Unique names are cached based on their unique + // autoGenerateId. var autoGenerateId = name.autoGenerateId; return autoGeneratedIdToGeneratedName[autoGenerateId] || (autoGeneratedIdToGeneratedName[autoGenerateId] = makeName(name)); } @@ -66719,28 +80434,44 @@ var ts; var nodeId = ts.getNodeId(node); return nodeIdToGeneratedName[nodeId] || (nodeIdToGeneratedName[nodeId] = generateNameForNode(node, flags)); } + /** + * Returns a value indicating whether a name is unique globally, within the current file, + * or within the NameGenerator. + */ function isUniqueName(name) { return isFileLevelUniqueName(name) && !generatedNames.has(name) && !(reservedNames && reservedNames.has(name)); } + /** + * Returns a value indicating whether a name is unique globally or within the current file. + */ function isFileLevelUniqueName(name) { return currentSourceFile ? ts.isFileLevelUniqueName(currentSourceFile, name, hasGlobalName) : true; } + /** + * Returns a value indicating whether a name is unique within a container. + */ function isUniqueLocalName(name, container) { for (var node = container; ts.isNodeDescendantOf(node, container); node = node.nextContainer) { if (node.locals) { var local = node.locals.get(ts.escapeLeadingUnderscores(name)); - if (local && local.flags & (67216319 | 1048576 | 2097152)) { + // We conservatively include alias symbols to cover cases where they're emitted as locals + if (local && local.flags & (67216319 /* Value */ | 1048576 /* ExportValue */ | 2097152 /* Alias */)) { return false; } } } return true; } + /** + * Return the next available name in the pattern _a ... _z, _0, _1, ... + * TempFlags._i or TempFlags._n may be used to express a preference for that dedicated name. + * Note that names generated by makeTempVariableName and makeUniqueName will never conflict. + */ function makeTempVariableName(flags, reservedInNestedScopes) { if (flags && !(tempFlags & flags)) { - var name = flags === 268435456 ? "_i" : "_n"; + var name = flags === 268435456 /* _i */ ? "_i" : "_n"; if (isUniqueName(name)) { tempFlags |= flags; if (reservedInNestedScopes) { @@ -66750,11 +80481,12 @@ var ts; } } while (true) { - var count = tempFlags & 268435455; + var count = tempFlags & 268435455 /* CountMask */; tempFlags++; + // Skip over 'i' and 'n' if (count !== 8 && count !== 13) { var name = count < 26 - ? "_" + String.fromCharCode(97 + count) + ? "_" + String.fromCharCode(97 /* a */ + count) : "_" + (count - 26); if (isUniqueName(name)) { if (reservedInNestedScopes) { @@ -66765,6 +80497,13 @@ var ts; } } } + /** + * Generate a name that is unique within the current file and doesn't conflict with any names + * in global scope. The name is formed by adding an '_n' suffix to the specified base name, + * where n is a positive integer. Note that names generated by makeTempVariableName and + * makeUniqueName are guaranteed to never conflict. + * If `optimistic` is set, the first instance will use 'baseName' verbatim instead of 'baseName_1' + */ function makeUniqueName(baseName, checkFn, optimistic, scoped) { if (checkFn === void 0) { checkFn = isUniqueName; } if (optimistic) { @@ -66778,7 +80517,8 @@ var ts; return baseName; } } - if (baseName.charCodeAt(baseName.length - 1) !== 95) { + // Find the first unique 'name_n', where n is a positive number + if (baseName.charCodeAt(baseName.length - 1) !== 95 /* _ */) { baseName += "_"; } var i = 1; @@ -66797,21 +80537,34 @@ var ts; } } function makeFileLevelOptmiisticUniqueName(name) { - return makeUniqueName(name, isFileLevelUniqueName, true); + return makeUniqueName(name, isFileLevelUniqueName, /*optimistic*/ true); } + /** + * Generates a unique name for a ModuleDeclaration or EnumDeclaration. + */ function generateNameForModuleOrEnum(node) { var name = getTextOfNode(node.name); + // Use module/enum name itself if it is unique, otherwise make a unique variation return isUniqueLocalName(name, node) ? name : makeUniqueName(name); } + /** + * Generates a unique name for an ImportDeclaration or ExportDeclaration. + */ function generateNameForImportOrExportDeclaration(node) { - var expr = ts.getExternalModuleName(node); + var expr = ts.getExternalModuleName(node); // TODO: GH#18217 var baseName = ts.isStringLiteral(expr) ? ts.makeIdentifierFromModuleName(expr.text) : "module"; return makeUniqueName(baseName); } + /** + * Generates a unique name for a default export. + */ function generateNameForExportDefault() { return makeUniqueName("default"); } + /** + * Generates a unique name for a class expression. + */ function generateNameForClassExpression() { return makeUniqueName("class"); } @@ -66819,74 +80572,87 @@ var ts; if (ts.isIdentifier(node.name)) { return generateNameCached(node.name); } - return makeTempVariableName(0); + return makeTempVariableName(0 /* Auto */); } + /** + * Generates a unique name from a node. + */ function generateNameForNode(node, flags) { switch (node.kind) { - case 71: - return makeUniqueName(getTextOfNode(node), isUniqueName, !!(flags & 16), !!(flags & 8)); - case 239: - case 238: + case 71 /* Identifier */: + return makeUniqueName(getTextOfNode(node), isUniqueName, !!(flags & 16 /* Optimistic */), !!(flags & 8 /* ReservedInNestedScopes */)); + case 239 /* ModuleDeclaration */: + case 238 /* EnumDeclaration */: return generateNameForModuleOrEnum(node); - case 244: - case 250: + case 244 /* ImportDeclaration */: + case 250 /* ExportDeclaration */: return generateNameForImportOrExportDeclaration(node); - case 234: - case 235: - case 249: + case 234 /* FunctionDeclaration */: + case 235 /* ClassDeclaration */: + case 249 /* ExportAssignment */: return generateNameForExportDefault(); - case 205: + case 205 /* ClassExpression */: return generateNameForClassExpression(); - case 154: - case 156: - case 157: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return generateNameForMethodOrAccessor(node); default: - return makeTempVariableName(0); + return makeTempVariableName(0 /* Auto */); } } + /** + * Generates a unique identifier for a node. + */ function makeName(name) { - switch (name.autoGenerateFlags & 7) { - case 1: - return makeTempVariableName(0, !!(name.autoGenerateFlags & 8)); - case 2: - return makeTempVariableName(268435456, !!(name.autoGenerateFlags & 8)); - case 3: - return makeUniqueName(ts.idText(name), (name.autoGenerateFlags & 32) ? isFileLevelUniqueName : isUniqueName, !!(name.autoGenerateFlags & 16), !!(name.autoGenerateFlags & 8)); + switch (name.autoGenerateFlags & 7 /* KindMask */) { + case 1 /* Auto */: + return makeTempVariableName(0 /* Auto */, !!(name.autoGenerateFlags & 8 /* ReservedInNestedScopes */)); + case 2 /* Loop */: + return makeTempVariableName(268435456 /* _i */, !!(name.autoGenerateFlags & 8 /* ReservedInNestedScopes */)); + case 3 /* Unique */: + return makeUniqueName(ts.idText(name), (name.autoGenerateFlags & 32 /* FileLevel */) ? isFileLevelUniqueName : isUniqueName, !!(name.autoGenerateFlags & 16 /* Optimistic */), !!(name.autoGenerateFlags & 8 /* ReservedInNestedScopes */)); } return ts.Debug.fail("Unsupported GeneratedIdentifierKind."); } + /** + * Gets the node from which a name should be generated. + */ function getNodeForGeneratedName(name) { var autoGenerateId = name.autoGenerateId; var node = name; var original = node.original; while (original) { node = original; + // if "node" is a different generated name (having a different + // "autoGenerateId"), use it and stop traversing. if (ts.isIdentifier(node) - && !!(node.autoGenerateFlags & 4) + && !!(node.autoGenerateFlags & 4 /* Node */) && node.autoGenerateId !== autoGenerateId) { break; } original = node.original; } + // otherwise, return the original node for the source; return node; } } ts.createPrinter = createPrinter; function createBracketsMap() { var brackets = []; - brackets[512] = ["{", "}"]; - brackets[1024] = ["(", ")"]; - brackets[2048] = ["<", ">"]; - brackets[4096] = ["[", "]"]; + brackets[512 /* Braces */] = ["{", "}"]; + brackets[1024 /* Parenthesis */] = ["(", ")"]; + brackets[2048 /* AngleBrackets */] = ["<", ">"]; + brackets[4096 /* SquareBrackets */] = ["[", "]"]; return brackets; } function getOpeningBracket(format) { - return brackets[format & 7680][0]; + return brackets[format & 7680 /* BracketsMask */][0]; } function getClosingBracket(format) { - return brackets[format & 7680][1]; + return brackets[format & 7680 /* BracketsMask */][1]; } + // Flags enum to track count of temp variables and a few dedicated names var TempFlags; (function (TempFlags) { TempFlags[TempFlags["Auto"] = 0] = "Auto"; @@ -66894,6 +80660,7 @@ var ts; TempFlags[TempFlags["_i"] = 268435456] = "_i"; })(TempFlags || (TempFlags = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { function createCachedDirectoryStructureHost(host, currentDirectory, useCaseSensitiveFileNames) { @@ -66929,12 +80696,17 @@ var ts; } function createCachedFileSystemEntries(rootDir, rootDirPath) { var resultFromHost = { - files: ts.map(host.readDirectory(rootDir, undefined, undefined, ["*.*"]), getBaseNameOfFileName) || [], + files: ts.map(host.readDirectory(rootDir, /*extensions*/ undefined, /*exclude*/ undefined, /*include*/ ["*.*"]), getBaseNameOfFileName) || [], directories: host.getDirectories(rootDir) || [] }; cachedReadDirectoryResult.set(ts.ensureTrailingDirectorySeparator(rootDirPath), resultFromHost); return resultFromHost; } + /** + * If the readDirectory result was already cached, it returns that + * Otherwise gets result from host and caches it. + * The host request is done under try catch block to avoid caching incorrect result + */ function tryReadDirectory(rootDir, rootDirPath) { rootDirPath = ts.ensureTrailingDirectorySeparator(rootDirPath); var cachedResult = getCachedFileSystemEntries(rootDirPath); @@ -66945,6 +80717,7 @@ var ts; return createCachedFileSystemEntries(rootDir, rootDirPath); } catch (_e) { + // If there is exception to read directories, dont cache the result and direct the calls to host ts.Debug.assert(!cachedReadDirectoryResult.has(ts.ensureTrailingDirectorySeparator(rootDirPath))); return undefined; } @@ -66969,7 +80742,7 @@ var ts; var path = toPath(fileName); var result = getCachedFileSystemEntriesForBaseDir(path); if (result) { - updateFilesOfFileSystemEntry(result, getBaseNameOfFileName(fileName), true); + updateFilesOfFileSystemEntry(result, getBaseNameOfFileName(fileName), /*fileExists*/ true); } return host.writeFile(fileName, data, writeByteOrderMark); } @@ -66988,7 +80761,7 @@ var ts; var result = getCachedFileSystemEntriesForBaseDir(path); var baseFileName = getBaseNameOfFileName(dirPath); if (result) { - updateFileSystemEntry(result.directories, baseFileName, true); + updateFileSystemEntry(result.directories, baseFileName, /*isValid*/ true); } host.createDirectory(dirPath); } @@ -67018,6 +80791,8 @@ var ts; function addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath) { var existingResult = getCachedFileSystemEntries(fileOrDirectoryPath); if (existingResult) { + // Just clear the cache for now + // For now just clear the cache, since this could mean that multiple level entries might need to be re-evaluated clearCache(); return undefined; } @@ -67025,7 +80800,10 @@ var ts; if (!parentResult) { return undefined; } + // This was earlier a file (hence not in cached directory contents) + // or we never cached the directory containing it if (!host.directoryExists) { + // Since host doesnt support directory exists, clear the cache as otherwise it might not be same clearCache(); return undefined; } @@ -67035,9 +80813,11 @@ var ts; directoryExists: host.directoryExists(fileOrDirectoryPath) }; if (fsQueryResult.directoryExists || hasEntry(parentResult.directories, baseName)) { + // Folder added or removed, clear the cache instead of updating the folder and its structure clearCache(); } else { + // No need to update the directory structure, just files updateFilesOfFileSystemEntry(parentResult, baseName, fsQueryResult.fileExists); } return fsQueryResult; @@ -67062,31 +80842,51 @@ var ts; var ConfigFileProgramReloadLevel; (function (ConfigFileProgramReloadLevel) { ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["None"] = 0] = "None"; + /** Update the file name list from the disk */ ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Partial"] = 1] = "Partial"; + /** Reload completely by re-reading contents of config file from disk and updating program */ ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Full"] = 2] = "Full"; })(ConfigFileProgramReloadLevel = ts.ConfigFileProgramReloadLevel || (ts.ConfigFileProgramReloadLevel = {})); + /** + * Updates the existing missing file watches with the new set of missing files after new program is created + */ function updateMissingFilePathsWatch(program, missingFileWatches, createMissingFileWatch) { var missingFilePaths = program.getMissingFilePaths(); var newMissingFilePathMap = ts.arrayToSet(missingFilePaths); + // Update the missing file paths watcher ts.mutateMap(missingFileWatches, newMissingFilePathMap, { + // Watch the missing files createNewValue: createMissingFileWatch, + // Files that are no longer missing (e.g. because they are no longer required) + // should no longer be watched. onDeleteValue: ts.closeFileWatcher }); } ts.updateMissingFilePathsWatch = updateMissingFilePathsWatch; + /** + * Updates the existing wild card directory watches with the new set of wild card directories from the config file + * after new program is created because the config file was reloaded or program was created first time from the config file + * Note that there is no need to call this function when the program is updated with additional files without reloading config files, + * as wildcard directories wont change unless reloading config file + */ function updateWatchingWildcardDirectories(existingWatchedForWildcards, wildcardDirectories, watchDirectory) { ts.mutateMap(existingWatchedForWildcards, wildcardDirectories, { + // Create new watch and recursive info createNewValue: createWildcardDirectoryWatcher, + // Close existing watch thats not needed any more onDeleteValue: closeFileWatcherOf, + // Close existing watch that doesnt match in the flags onExistingValue: updateWildcardDirectoryWatcher }); function createWildcardDirectoryWatcher(directory, flags) { + // Create new watch and recursive info return { watcher: watchDirectory(directory, flags), flags: flags }; } function updateWildcardDirectoryWatcher(existingWatcher, flags, directory) { + // Watcher needs to be updated if the recursive flags dont match if (existingWatcher.flags === flags) { return; } @@ -67118,13 +80918,13 @@ var ts; var createDirectoryWatcher = getCreateFileWatcher(watchLogLevel, watchDirectory); return { watchFile: function (host, file, callback, pollingInterval, detailInfo1, detailInfo2) { - return createFileWatcher(host, file, callback, pollingInterval, undefined, detailInfo1, detailInfo2, watchFile, log, "FileWatcher", getDetailWatchInfo); + return createFileWatcher(host, file, callback, pollingInterval, /*passThrough*/ undefined, detailInfo1, detailInfo2, watchFile, log, "FileWatcher", getDetailWatchInfo); }, watchFilePath: function (host, file, callback, pollingInterval, path, detailInfo1, detailInfo2) { return createFilePathWatcher(host, file, callback, pollingInterval, path, detailInfo1, detailInfo2, watchFile, log, "FileWatcher", getDetailWatchInfo); }, watchDirectory: function (host, directory, callback, flags, detailInfo1, detailInfo2) { - return createDirectoryWatcher(host, directory, callback, flags, undefined, detailInfo1, detailInfo2, watchDirectory, log, "DirectoryWatcher", getDetailWatchInfo); + return createDirectoryWatcher(host, directory, callback, flags, /*passThrough*/ undefined, detailInfo1, detailInfo2, watchDirectory, log, "DirectoryWatcher", getDetailWatchInfo); } }; function watchFilePath(host, file, callback, pollingInterval, path) { @@ -67135,7 +80935,7 @@ var ts; return host.watchFile(file, callback, pollingInterval); } function watchDirectory(host, directory, callback, flags) { - return host.watchDirectory(directory, callback, (flags & 1) !== 0); + return host.watchDirectory(directory, callback, (flags & 1 /* Recursive */) !== 0); } function getCreateFileWatcher(watchLogLevel, addWatch) { switch (watchLogLevel) { @@ -67192,12 +80992,15 @@ var ts; return ts.normalizePath(referencedFileName); } ts.resolveTripleslashReference = resolveTripleslashReference; + /* @internal */ function computeCommonSourceDirectoryOfFilenames(fileNames, currentDirectory, getCanonicalFileName) { var commonPathComponents; var failed = ts.forEach(fileNames, function (sourceFile) { + // Each file contributes into common source file path var sourcePathComponents = ts.getNormalizedPathComponents(sourceFile, currentDirectory); - sourcePathComponents.pop(); + sourcePathComponents.pop(); // The base file name is not part of the common directory path if (!commonPathComponents) { + // first file commonPathComponents = sourcePathComponents; return; } @@ -67205,20 +81008,24 @@ var ts; for (var i = 0; i < n; i++) { if (getCanonicalFileName(commonPathComponents[i]) !== getCanonicalFileName(sourcePathComponents[i])) { if (i === 0) { + // Failed to find any common path component return true; } + // New common path found that is 0 -> i-1 commonPathComponents.length = i; break; } } + // If the sourcePathComponents was shorter than the commonPathComponents, truncate to the sourcePathComponents if (sourcePathComponents.length < commonPathComponents.length) { commonPathComponents.length = sourcePathComponents.length; } }); + // A common path can not be found when paths span multiple drives on windows, for example if (failed) { return ""; } - if (!commonPathComponents) { + if (!commonPathComponents) { // Can happen when all input files are .d.ts files return currentDirectory; } return ts.getPathFromPathComponents(commonPathComponents); @@ -67227,6 +81034,8 @@ var ts; function createCompilerHost(options, setParentNodes) { var existingDirectories = ts.createMap(); function getCanonicalFileName(fileName) { + // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form. + // otherwise use toLowerCase as a canonical form. return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); } function getSourceFile(fileName, languageVersion, onError) { @@ -67267,10 +81076,11 @@ var ts; if (!outputFingerprints) { outputFingerprints = ts.createMap(); } - var hash = ts.sys.createHash(data); - var mtimeBefore = ts.sys.getModifiedTime(fileName); + var hash = ts.sys.createHash(data); // TODO: GH#18217 + var mtimeBefore = ts.sys.getModifiedTime(fileName); // TODO: GH#18217 if (mtimeBefore) { var fingerprint = outputFingerprints.get(fileName); + // If output has not been changed, and the file has no external modification if (fingerprint && fingerprint.byteOrderMark === writeByteOrderMark && fingerprint.hash === hash && @@ -67279,7 +81089,7 @@ var ts; } } ts.sys.writeFile(fileName, data, writeByteOrderMark); - var mtimeAfter = ts.sys.getModifiedTime(fileName); + var mtimeAfter = ts.sys.getModifiedTime(fileName); // TODO: GH#18217 outputFingerprints.set(fileName, { hash: hash, byteOrderMark: writeByteOrderMark, @@ -67353,7 +81163,7 @@ var ts; function formatDiagnostic(diagnostic, host) { var errorMessage = ts.diagnosticCategoryName(diagnostic) + " TS" + diagnostic.code + ": " + flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine()) + host.getNewLine(); if (diagnostic.file) { - var _a = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start), line = _a.line, character = _a.character; + var _a = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start), line = _a.line, character = _a.character; // TODO: GH#18217 var fileName = diagnostic.file.fileName; var relativeFileName = ts.convertToRelativePath(fileName, host.getCurrentDirectory(), function (fileName) { return host.getCanonicalFileName(fileName); }); return relativeFileName + "(" + (line + 1) + "," + (character + 1) + "): " + errorMessage; @@ -67361,6 +81171,7 @@ var ts; return errorMessage; } ts.formatDiagnostic = formatDiagnostic; + /** @internal */ var ForegroundColorEscapeSequences; (function (ForegroundColorEscapeSequences) { ForegroundColorEscapeSequences["Grey"] = "\u001B[90m"; @@ -67383,6 +81194,7 @@ var ts; case ts.DiagnosticCategory.Message: return ForegroundColorEscapeSequences.Blue; } } + /** @internal */ function formatColorAndReset(text, formatStyle) { return formatStyle + text + resetEscapeSequence; } @@ -67405,6 +81217,8 @@ var ts; var context = ""; for (var i = firstLine; i <= lastLine; i++) { context += host.getNewLine(); + // If the error spans over 5 lines, we'll only show the first 2 and last 2 lines, + // so we'll skip ahead to the second-to-last line. if (hasMoreThanFiveLines && firstLine + 1 < i && i < lastLine - 1) { context += indent + formatColorAndReset(padLeft(ellipsis, gutterWidth), gutterStyleSequence) + gutterSeparator + host.getNewLine(); i = lastLine - 1; @@ -67412,13 +81226,17 @@ var ts; var lineStart = ts.getPositionOfLineAndCharacter(file, i, 0); var lineEnd = i < lastLineInFile ? ts.getPositionOfLineAndCharacter(file, i + 1, 0) : file.text.length; var lineContent = file.text.slice(lineStart, lineEnd); - lineContent = lineContent.replace(/\s+$/g, ""); - lineContent = lineContent.replace("\t", " "); + lineContent = lineContent.replace(/\s+$/g, ""); // trim from end + lineContent = lineContent.replace("\t", " "); // convert tabs to single spaces + // Output the gutter and the actual contents of the line. context += indent + formatColorAndReset(padLeft(i + 1 + "", gutterWidth), gutterStyleSequence) + gutterSeparator; context += lineContent + host.getNewLine(); + // Output the gutter and the error span for the line using tildes. context += indent + formatColorAndReset(padLeft("", gutterWidth), gutterStyleSequence) + gutterSeparator; context += squiggleColor; if (i === firstLine) { + // If we're on the last line, then limit it to the last character of the last line. + // Otherwise, we'll just squiggle the rest of the line, giving 'slice' no end position. var lastCharForLine = i === lastLine ? lastLineChar : undefined; context += lineContent.slice(0, firstLineChar).replace(/\S/g, " "); context += lineContent.slice(firstLineChar, lastCharForLine).replace(/./g, "~"); @@ -67427,6 +81245,7 @@ var ts; context += lineContent.slice(0, lastLineChar).replace(/./g, "~"); } else { + // Squiggle the entire line. context += lineContent.replace(/./g, "~"); } context += resetEscapeSequence; @@ -67434,7 +81253,7 @@ var ts; return context; } function formatLocation(file, start, host) { - var _a = ts.getLineAndCharacterOfPosition(file, start), firstLine = _a.line, firstLineChar = _a.character; + var _a = ts.getLineAndCharacterOfPosition(file, start), firstLine = _a.line, firstLineChar = _a.character; // TODO: GH#18217 var relativeFileName = host ? ts.convertToRelativePath(file.fileName, host.getCurrentDirectory(), function (fileName) { return host.getCanonicalFileName(fileName); }) : file.fileName; var output = ""; output += formatColorAndReset(relativeFileName, ForegroundColorEscapeSequences.Cyan); @@ -67450,7 +81269,7 @@ var ts; var diagnostic = diagnostics_2[_i]; if (diagnostic.file) { var file = diagnostic.file, start = diagnostic.start; - output += formatLocation(file, start, host); + output += formatLocation(file, start, host); // TODO: GH#18217 output += " - "; } output += formatColorAndReset(ts.diagnosticCategoryName(diagnostic), getCategoryFormat(diagnostic.category)); @@ -67458,15 +81277,15 @@ var ts; output += flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine()); if (diagnostic.file) { output += host.getNewLine(); - output += formatCodeSpan(diagnostic.file, diagnostic.start, diagnostic.length, "", getCategoryFormat(diagnostic.category), host); + output += formatCodeSpan(diagnostic.file, diagnostic.start, diagnostic.length, "", getCategoryFormat(diagnostic.category), host); // TODO: GH#18217 if (diagnostic.relatedInformation) { output += host.getNewLine(); for (var _a = 0, _b = diagnostic.relatedInformation; _a < _b.length; _a++) { var _c = _b[_a], file = _c.file, start = _c.start, length_4 = _c.length, messageText = _c.messageText; if (file) { output += host.getNewLine(); - output += halfIndent + formatLocation(file, start, host); - output += formatCodeSpan(file, start, length_4, indent, ForegroundColorEscapeSequences.Cyan, host); + output += halfIndent + formatLocation(file, start, host); // TODO: GH#18217 + output += formatCodeSpan(file, start, length_4, indent, ForegroundColorEscapeSequences.Cyan, host); // TODO: GH#18217 } output += host.getNewLine(); output += indent + flattenDiagnosticMessageText(messageText, host.getNewLine()); @@ -67520,23 +81339,34 @@ var ts; } return resolutions; } + /** + * Determines if program structure is upto date or needs to be recreated + */ + /* @internal */ function isProgramUptoDate(program, rootFileNames, newOptions, getSourceVersion, fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames) { + // If we haven't created a program yet or have changed automatic type directives, then it is not up-to-date if (!program || hasChangedAutomaticTypeDirectiveNames) { return false; } + // If number of files in the program do not match, it is not up-to-date if (program.getRootFileNames().length !== rootFileNames.length) { return false; } + // If any file is not up-to-date, then the whole program is not up-to-date if (program.getSourceFiles().some(sourceFileNotUptoDate)) { return false; } + // If any of the missing file paths are now created if (program.getMissingFilePaths().some(fileExists)) { return false; } var currentOptions = program.getCompilerOptions(); + // If the compilation settings do no match, then the program is not up-to-date if (!ts.compareDataObjects(currentOptions, newOptions)) { return false; } + // If everything matches but the text of config file is changed, + // error locations can change for program options, so update the program if (currentOptions.configFile && newOptions.configFile) { return currentOptions.configFile.text === newOptions.configFile.text; } @@ -67552,7 +81382,12 @@ var ts; configFileParseResult.errors; } ts.getConfigFileParsingDiagnostics = getConfigFileParsingDiagnostics; + /** + * Determined if source file needs to be re-created even if its text hasn't changed + */ function shouldProgramCreateNewSourceFiles(program, newOptions) { + // If any of these options change, we can't reuse old source file even if version match + // The change in options like these could result in change in syntax tree change var oldOptions = program && program.getCompilerOptions(); return oldOptions && (oldOptions.target !== newOptions.target || oldOptions.module !== newOptions.module || @@ -67574,7 +81409,7 @@ var ts; }; } function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _configFileParsingDiagnostics) { - var createProgramOptions = ts.isArray(rootNamesOrOptions) ? createCreateProgramOptions(rootNamesOrOptions, _options, _host, _oldProgram, _configFileParsingDiagnostics) : rootNamesOrOptions; + var createProgramOptions = ts.isArray(rootNamesOrOptions) ? createCreateProgramOptions(rootNamesOrOptions, _options, _host, _oldProgram, _configFileParsingDiagnostics) : rootNamesOrOptions; // TODO: GH#18217 var rootNames = createProgramOptions.rootNames, options = createProgramOptions.options, configFileParsingDiagnostics = createProgramOptions.configFileParsingDiagnostics, projectReferences = createProgramOptions.projectReferences; var oldProgram = createProgramOptions.oldProgram; var program; @@ -67590,9 +81425,19 @@ var ts; var cachedDeclarationDiagnosticsForFile = {}; var resolvedTypeReferenceDirectives = ts.createMap(); var fileProcessingDiagnostics = ts.createDiagnosticCollection(); + // The below settings are to track if a .js file should be add to the program if loaded via searching under node_modules. + // This works as imported modules are discovered recursively in a depth first manner, specifically: + // - For each root file, findSourceFile is called. + // - This calls processImportedModules for each module imported in the source file. + // - This calls resolveModuleNames, and then calls findSourceFile for each resolved module. + // As all these operations happen - and are nested - within the createProgram call, they close over the below variables. + // The current resolution depth is tracked by incrementing/decrementing as the depth first search progresses. var maxNodeModuleJsDepth = typeof options.maxNodeModuleJsDepth === "number" ? options.maxNodeModuleJsDepth : 0; var currentNodeModulesDepth = 0; + // If a module has some of its imports skipped due to being at the depth limit under node_modules, then track + // this, as it may be imported at a shallower depth later, and then it will need its skipped imports processed. var modulesWithElidedImports = ts.createMap(); + // Track source files that are source files found by searching under node_modules, as these shouldn't be compiled. var sourceFilesFoundSearchingNodeModules = ts.createMap(); ts.performance.mark("beforeProgram"); var host = createProgramOptions.host || createCompilerHost(options); @@ -67603,6 +81448,7 @@ var ts; var programDiagnostics = ts.createDiagnosticCollection(); var currentDirectory = host.getCurrentDirectory(); var supportedExtensions = ts.getSupportedExtensions(options); + // Map storing if there is emit blocking diagnostics for given input var hasEmitBlockingDiagnostics = ts.createMap(); var _compilerOptionsObjectLiteralSyntax; var _referencesArrayLiteralSyntax; @@ -67611,6 +81457,7 @@ var ts; var hasInvalidatedResolution = host.hasInvalidatedResolution || ts.returnFalse; if (host.resolveModuleNames) { resolveModuleNamesWorker = function (moduleNames, containingFile, reusedNames) { return host.resolveModuleNames(ts.Debug.assertEachDefined(moduleNames), containingFile, reusedNames).map(function (resolved) { + // An older host may have omitted extension, in which case we should infer it from the file extension of resolvedFileName. if (!resolved || resolved.extension !== undefined) { return resolved; } @@ -67621,7 +81468,7 @@ var ts; } else { moduleResolutionCache = ts.createModuleResolutionCache(currentDirectory, function (x) { return host.getCanonicalFileName(x); }); - var loader_1 = function (moduleName, containingFile) { return ts.resolveModuleName(moduleName, containingFile, options, host, moduleResolutionCache).resolvedModule; }; + var loader_1 = function (moduleName, containingFile) { return ts.resolveModuleName(moduleName, containingFile, options, host, moduleResolutionCache).resolvedModule; }; // TODO: GH#18217 resolveModuleNamesWorker = function (moduleNames, containingFile) { return loadWithLocalCache(ts.Debug.assertEachDefined(moduleNames), containingFile, loader_1); }; } var resolveTypeReferenceDirectiveNamesWorker; @@ -67629,20 +81476,27 @@ var ts; resolveTypeReferenceDirectiveNamesWorker = function (typeDirectiveNames, containingFile) { return host.resolveTypeReferenceDirectives(ts.Debug.assertEachDefined(typeDirectiveNames), containingFile); }; } else { - var loader_2 = function (typesRef, containingFile) { return ts.resolveTypeReferenceDirective(typesRef, containingFile, options, host).resolvedTypeReferenceDirective; }; + var loader_2 = function (typesRef, containingFile) { return ts.resolveTypeReferenceDirective(typesRef, containingFile, options, host).resolvedTypeReferenceDirective; }; // TODO: GH#18217 resolveTypeReferenceDirectiveNamesWorker = function (typeReferenceDirectiveNames, containingFile) { return loadWithLocalCache(ts.Debug.assertEachDefined(typeReferenceDirectiveNames), containingFile, loader_2); }; } + // Map from a stringified PackageId to the source file with that id. + // Only one source file may have a given packageId. Others become redirects (see createRedirectSourceFile). + // `packageIdToSourceFile` is only used while building the program, while `sourceFileToPackageName` and `isSourceFileTargetOfRedirect` are kept around. var packageIdToSourceFile = ts.createMap(); + // Maps from a SourceFile's `.path` to the name of the package it was imported with. var sourceFileToPackageName = ts.createMap(); var redirectTargetsSet = ts.createMap(); var filesByName = ts.createMap(); var missingFilePaths; + // stores 'filename -> file association' ignoring case + // used to track cases when two file names differ only in casing var filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? ts.createMap() : undefined; + // A parallel array to projectReferences storing the results of reading in the referenced tsconfig files var resolvedProjectReferences = projectReferences ? [] : undefined; var projectReferenceRedirects = ts.createMap(); var shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options); var structuralIsReused = tryReuseStructureFromOldProgram(); - if (structuralIsReused !== 2) { + if (structuralIsReused !== 2 /* Completely */) { processingDefaultLibFiles = []; processingOtherFiles = []; if (projectReferences) { @@ -67653,15 +81507,17 @@ var ts; if (parsedRef) { if (parsedRef.commandLine.options.outFile) { var dtsOutfile = ts.changeExtension(parsedRef.commandLine.options.outFile, ".d.ts"); - processSourceFile(dtsOutfile, false, false, undefined); + processSourceFile(dtsOutfile, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined); } addProjectReferenceRedirects(parsedRef.commandLine, projectReferenceRedirects); } } } - ts.forEach(rootNames, function (name) { return processRootFile(name, false, false); }); + ts.forEach(rootNames, function (name) { return processRootFile(name, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false); }); + // load type declarations specified via 'types' argument or implicitly from types/ and node_modules/@types folders var typeReferences = ts.getAutomaticTypeDirectiveNames(options, host); if (typeReferences.length) { + // This containingFilename needs to match with the one used in managed-side var containingDirectory = options.configFilePath ? ts.getDirectoryPath(options.configFilePath) : host.getCurrentDirectory(); var containingFilename = ts.combinePaths(containingDirectory, "__inferred type names__.ts"); var resolutions = resolveTypeReferenceDirectiveNamesWorker(typeReferences, containingFilename); @@ -67669,14 +81525,20 @@ var ts; processTypeReferenceDirective(typeReferences[i], resolutions[i]); } } + // Do not process the default library if: + // - The '--noLib' flag is used. + // - A 'no-default-lib' reference comment is encountered in + // processing the root files. if (!skipDefaultLib) { + // If '--lib' is not specified, include default library file according to '--target' + // otherwise, using options specified in '--lib' instead of '--target' default library file var defaultLibraryFileName = getDefaultLibraryFileName(); if (!options.lib && defaultLibraryFileName) { - processRootFile(defaultLibraryFileName, true, false); + processRootFile(defaultLibraryFileName, /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ false); } else { ts.forEach(options.lib, function (libFileName) { - processRootFile(ts.combinePaths(defaultLibraryPath, libFileName), true, false); + processRootFile(ts.combinePaths(defaultLibraryPath, libFileName), /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ false); }); } } @@ -67686,6 +81548,8 @@ var ts; processingOtherFiles = undefined; } ts.Debug.assert(!!missingFilePaths); + // Release any files we have acquired in the old program but are + // not part of the new program. if (oldProgram && host.onReleaseOldSourceFile) { var oldSourceFiles = oldProgram.getSourceFiles(); for (var _a = 0, oldSourceFiles_1 = oldSourceFiles; _a < oldSourceFiles_1.length; _a++) { @@ -67695,6 +81559,7 @@ var ts; } } } + // unconditionally set oldProgram to undefined to prevent it from being captured in closure oldProgram = undefined; program = { getRootFileNames: function () { return rootNames; }, @@ -67741,7 +81606,7 @@ var ts; return ts.compareValues(getDefaultLibFilePriority(a), getDefaultLibFilePriority(b)); } function getDefaultLibFilePriority(a) { - if (ts.containsPath(defaultLibraryPath, a.fileName, false)) { + if (ts.containsPath(defaultLibraryPath, a.fileName, /*ignoreCase*/ false)) { var basename = ts.getBaseFileName(a.fileName); if (basename === "lib.d.ts" || basename === "lib.es6.d.ts") return 0; @@ -67762,16 +81627,21 @@ var ts; if (commonSourceDirectory === undefined) { var emittedFiles = ts.filter(files, function (file) { return ts.sourceFileMayBeEmitted(file, options, isSourceFileFromExternalLibrary); }); if (options.rootDir && checkSourceFilesBelongToPath(emittedFiles, options.rootDir)) { + // If a rootDir is specified use it as the commonSourceDirectory commonSourceDirectory = ts.getNormalizedAbsolutePath(options.rootDir, currentDirectory); } else if (options.composite) { - commonSourceDirectory = ts.getDirectoryPath(ts.normalizeSlashes(options.configFilePath)); + // Project compilations never infer their root from the input source paths + commonSourceDirectory = ts.getDirectoryPath(ts.normalizeSlashes(options.configFilePath)); // TODO: GH#18217 checkSourceFilesBelongToPath(emittedFiles, commonSourceDirectory); } else { commonSourceDirectory = computeCommonSourceDirectory(emittedFiles); } if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== ts.directorySeparator) { + // Make sure directory path ends with directory separator so this string can directly + // used to replace with "" to get the relative path of the source file and the relative path doesn't + // start with / making it rooted path commonSourceDirectory += ts.directorySeparator; } } @@ -67779,6 +81649,7 @@ var ts; } function getClassifiableNames() { if (!classifiableNames) { + // Initialize a checker so that all our files are bound. getTypeChecker(); classifiableNames = ts.createUnderscoreEscapedMap(); for (var _i = 0, files_2 = files; _i < files_2.length; _i++) { @@ -67789,11 +81660,21 @@ var ts; return classifiableNames; } function resolveModuleNamesReusingOldState(moduleNames, containingFile, file, oldProgramState) { - if (structuralIsReused === 0 && !file.ambientModuleNames.length) { + if (structuralIsReused === 0 /* Not */ && !file.ambientModuleNames.length) { + // If the old program state does not permit reusing resolutions and `file` does not contain locally defined ambient modules, + // the best we can do is fallback to the default logic. return resolveModuleNamesWorker(moduleNames, containingFile); } var oldSourceFile = oldProgramState.program && oldProgramState.program.getSourceFile(containingFile); if (oldSourceFile !== file && file.resolvedModules) { + // `file` was created for the new program. + // + // We only set `file.resolvedModules` via work from the current function, + // so it is defined iff we already called the current function on `file`. + // That call happened no later than the creation of the `file` object, + // which per above occurred during the current program creation. + // Since we assume the filesystem does not change during program creation, + // it is safe to reuse resolutions from the earlier call. var result_4 = []; for (var _i = 0, moduleNames_1 = moduleNames; _i < moduleNames_1.length; _i++) { var moduleName = moduleNames_1[_i]; @@ -67802,12 +81683,28 @@ var ts; } return result_4; } + // At this point, we know at least one of the following hold: + // - file has local declarations for ambient modules + // - old program state is available + // With this information, we can infer some module resolutions without performing resolution. + /** An ordered list of module names for which we cannot recover the resolution. */ var unknownModuleNames; + /** + * The indexing of elements in this list matches that of `moduleNames`. + * + * Before combining results, result[i] is in one of the following states: + * * undefined: needs to be recomputed, + * * predictedToResolveToAmbientModuleMarker: known to be an ambient module. + * Needs to be reset to undefined before returning, + * * ResolvedModuleFull instance: can be reused. + */ var result; var reusedNames; + /** A transient placeholder used to mark predicted resolution in the result list. */ var predictedToResolveToAmbientModuleMarker = {}; for (var i = 0; i < moduleNames.length; i++) { var moduleName = moduleNames[i]; + // If the source file is unchanged and doesnt have invalidated resolution, reuse the module resolutions if (file === oldSourceFile && !hasInvalidatedResolution(oldSourceFile.path)) { var oldResolvedModule = oldSourceFile && oldSourceFile.resolvedModules.get(moduleName); if (oldResolvedModule) { @@ -67819,6 +81716,10 @@ var ts; continue; } } + // We know moduleName resolves to an ambient module provided that moduleName: + // - is in the list of ambient modules locally declared in the current source file. + // - resolved to an ambient module in the old program whose declaration is in an unmodified file + // (so the same module declaration will land in the new program) var resolvesToAmbientModuleInNonModifiedFile = false; if (ts.contains(file.ambientModuleNames, moduleName)) { resolvesToAmbientModuleInNonModifiedFile = true; @@ -67833,21 +81734,26 @@ var ts; (result || (result = new Array(moduleNames.length)))[i] = predictedToResolveToAmbientModuleMarker; } else { + // Resolution failed in the old program, or resolved to an ambient module for which we can't reuse the result. (unknownModuleNames || (unknownModuleNames = [])).push(moduleName); } } var resolutions = unknownModuleNames && unknownModuleNames.length ? resolveModuleNamesWorker(unknownModuleNames, containingFile, reusedNames) : ts.emptyArray; + // Combine results of resolutions and predicted results if (!result) { + // There were no unresolved/ambient resolutions. ts.Debug.assert(resolutions.length === moduleNames.length); return resolutions; } var j = 0; for (var i = 0; i < result.length; i++) { if (result[i]) { + // `result[i]` is either a `ResolvedModuleFull` or a marker. + // If it is the former, we can leave it as is. if (result[i] === predictedToResolveToAmbientModuleMarker) { - result[i] = undefined; + result[i] = undefined; // TODO: GH#18217 } } else { @@ -67857,16 +81763,23 @@ var ts; } ts.Debug.assert(j === resolutions.length); return result; + // If we change our policy of rechecking failed lookups on each program create, + // we should adjust the value returned here. function moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName, oldProgramState) { - var resolutionToFile = ts.getResolvedModule(oldProgramState.oldSourceFile, moduleName); + var resolutionToFile = ts.getResolvedModule(oldProgramState.oldSourceFile, moduleName); // TODO: GH#18217 var resolvedFile = resolutionToFile && oldProgramState.program && oldProgramState.program.getSourceFile(resolutionToFile.resolvedFileName); if (resolutionToFile && resolvedFile && !resolvedFile.externalModuleIndicator) { + // In the old program, we resolved to an ambient module that was in the same + // place as we expected to find an actual module file. + // We actually need to return 'false' here even though this seems like a 'true' case + // because the normal module resolution algorithm will find this anyway. return false; } var ambientModule = oldProgramState.program && oldProgramState.program.getTypeChecker().tryFindAmbientModuleWithoutAugmentations(moduleName); if (!(ambientModule && ambientModule.declarations)) { return false; } + // at least one of declarations should come from non-modified source file var firstUnmodifiedFile = ts.forEach(ambientModule.declarations, function (d) { var f = ts.getSourceFileOfNode(d); return !ts.contains(oldProgramState.modifiedFilePaths, f.path) && f; @@ -67882,51 +81795,61 @@ var ts; } function tryReuseStructureFromOldProgram() { if (!oldProgram) { - return 0; + return 0 /* Not */; } + // check properties that can affect structure of the program or module resolution strategy + // if any of these properties has changed - structure cannot be reused var oldOptions = oldProgram.getCompilerOptions(); if (ts.changesAffectModuleResolution(oldOptions, options)) { - return oldProgram.structureIsReused = 0; + return oldProgram.structureIsReused = 0 /* Not */; } - ts.Debug.assert(!(oldProgram.structureIsReused & (2 | 1))); + ts.Debug.assert(!(oldProgram.structureIsReused & (2 /* Completely */ | 1 /* SafeModules */))); + // there is an old program, check if we can reuse its structure var oldRootNames = oldProgram.getRootFileNames(); if (!ts.arrayIsEqualTo(oldRootNames, rootNames)) { - return oldProgram.structureIsReused = 0; + return oldProgram.structureIsReused = 0 /* Not */; } if (!ts.arrayIsEqualTo(options.types, oldOptions.types)) { - return oldProgram.structureIsReused = 0; + return oldProgram.structureIsReused = 0 /* Not */; } + // Check if any referenced project tsconfig files are different var oldRefs = oldProgram.getProjectReferences(); if (projectReferences) { if (!oldRefs) { - return oldProgram.structureIsReused = 0; + return oldProgram.structureIsReused = 0 /* Not */; } for (var i = 0; i < projectReferences.length; i++) { var oldRef = oldRefs[i]; if (oldRef) { var newRef = parseProjectReferenceConfigFile(projectReferences[i]); if (!newRef || newRef.sourceFile !== oldRef.sourceFile) { - return oldProgram.structureIsReused = 0; + // Resolved project reference has gone missing or changed + return oldProgram.structureIsReused = 0 /* Not */; } } else { + // A previously-unresolved reference may be resolved now if (parseProjectReferenceConfigFile(projectReferences[i]) !== undefined) { - return oldProgram.structureIsReused = 0; + return oldProgram.structureIsReused = 0 /* Not */; } } } } else { if (oldRefs) { - return oldProgram.structureIsReused = 0; + return oldProgram.structureIsReused = 0 /* Not */; } } + // check if program source files has changed in the way that can affect structure of the program var newSourceFiles = []; var filePaths = []; var modifiedSourceFiles = []; - oldProgram.structureIsReused = 2; + oldProgram.structureIsReused = 2 /* Completely */; + // If the missing file paths are now present, it can change the progam structure, + // and hence cant reuse the structure. + // This is same as how we dont reuse the structure if one of the file from old program is now missing if (oldProgram.getMissingFilePaths().some(function (missingFilePath) { return host.fileExists(missingFilePath); })) { - return oldProgram.structureIsReused = 0; + return oldProgram.structureIsReused = 0 /* Not */; } var oldSourceFiles = oldProgram.getSourceFiles(); var SeenPackageName; @@ -67938,23 +81861,27 @@ var ts; for (var _i = 0, oldSourceFiles_2 = oldSourceFiles; _i < oldSourceFiles_2.length; _i++) { var oldSourceFile = oldSourceFiles_2[_i]; var newSourceFile = host.getSourceFileByPath - ? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.resolvedPath || oldSourceFile.path, options.target, undefined, shouldCreateNewSourceFile) - : host.getSourceFile(oldSourceFile.fileName, options.target, undefined, shouldCreateNewSourceFile); + ? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.resolvedPath || oldSourceFile.path, options.target, /*onError*/ undefined, shouldCreateNewSourceFile) + : host.getSourceFile(oldSourceFile.fileName, options.target, /*onError*/ undefined, shouldCreateNewSourceFile); // TODO: GH#18217 if (!newSourceFile) { - return oldProgram.structureIsReused = 0; + return oldProgram.structureIsReused = 0 /* Not */; } ts.Debug.assert(!newSourceFile.redirectInfo, "Host should not return a redirect source file from `getSourceFile`"); var fileChanged = void 0; if (oldSourceFile.redirectInfo) { + // We got `newSourceFile` by path, so it is actually for the unredirected file. + // This lets us know if the unredirected file has changed. If it has we should break the redirect. if (newSourceFile !== oldSourceFile.redirectInfo.unredirected) { - return oldProgram.structureIsReused = 0; + // Underlying file has changed. Might not redirect anymore. Must rebuild program. + return oldProgram.structureIsReused = 0 /* Not */; } fileChanged = false; - newSourceFile = oldSourceFile; + newSourceFile = oldSourceFile; // Use the redirect. } else if (oldProgram.redirectTargetsSet.has(oldSourceFile.path)) { + // If a redirected-to source file changes, the redirect may be broken. if (newSourceFile !== oldSourceFile) { - return oldProgram.structureIsReused = 0; + return oldProgram.structureIsReused = 0 /* Not */; } fileChanged = false; } @@ -67965,48 +81892,66 @@ var ts; filePaths.push(newSourceFile.path); var packageName = oldProgram.sourceFileToPackageName.get(oldSourceFile.path); if (packageName !== undefined) { + // If there are 2 different source files for the same package name and at least one of them changes, + // they might become redirects. So we must rebuild the program. var prevKind = seenPackageNames.get(packageName); - var newKind = fileChanged ? 1 : 0; - if ((prevKind !== undefined && newKind === 1) || prevKind === 1) { - return oldProgram.structureIsReused = 0; + var newKind = fileChanged ? 1 /* Modified */ : 0 /* Exists */; + if ((prevKind !== undefined && newKind === 1 /* Modified */) || prevKind === 1 /* Modified */) { + return oldProgram.structureIsReused = 0 /* Not */; } seenPackageNames.set(packageName, newKind); } if (fileChanged) { + // The `newSourceFile` object was created for the new program. if (!ts.arrayIsEqualTo(oldSourceFile.libReferenceDirectives, newSourceFile.libReferenceDirectives, fileReferenceIsEqualTo)) { - return oldProgram.structureIsReused = 0; + // 'lib' references has changed. Matches behavior in changesAffectModuleResolution + return oldProgram.structureIsReused = 0 /* Not */; } if (oldSourceFile.hasNoDefaultLib !== newSourceFile.hasNoDefaultLib) { - oldProgram.structureIsReused = 1; + // value of no-default-lib has changed + // this will affect if default library is injected into the list of files + oldProgram.structureIsReused = 1 /* SafeModules */; } + // check tripleslash references if (!ts.arrayIsEqualTo(oldSourceFile.referencedFiles, newSourceFile.referencedFiles, fileReferenceIsEqualTo)) { - oldProgram.structureIsReused = 1; + // tripleslash references has changed + oldProgram.structureIsReused = 1 /* SafeModules */; } + // check imports and module augmentations collectExternalModuleReferences(newSourceFile); if (!ts.arrayIsEqualTo(oldSourceFile.imports, newSourceFile.imports, moduleNameIsEqualTo)) { - oldProgram.structureIsReused = 1; + // imports has changed + oldProgram.structureIsReused = 1 /* SafeModules */; } if (!ts.arrayIsEqualTo(oldSourceFile.moduleAugmentations, newSourceFile.moduleAugmentations, moduleNameIsEqualTo)) { - oldProgram.structureIsReused = 1; + // moduleAugmentations has changed + oldProgram.structureIsReused = 1 /* SafeModules */; } - if ((oldSourceFile.flags & 1572864) !== (newSourceFile.flags & 1572864)) { - oldProgram.structureIsReused = 1; + if ((oldSourceFile.flags & 1572864 /* PermanentlySetIncrementalFlags */) !== (newSourceFile.flags & 1572864 /* PermanentlySetIncrementalFlags */)) { + // dynamicImport has changed + oldProgram.structureIsReused = 1 /* SafeModules */; } if (!ts.arrayIsEqualTo(oldSourceFile.typeReferenceDirectives, newSourceFile.typeReferenceDirectives, fileReferenceIsEqualTo)) { - oldProgram.structureIsReused = 1; + // 'types' references has changed + oldProgram.structureIsReused = 1 /* SafeModules */; } + // tentatively approve the file modifiedSourceFiles.push({ oldFile: oldSourceFile, newFile: newSourceFile }); } else if (hasInvalidatedResolution(oldSourceFile.path)) { - oldProgram.structureIsReused = 1; + // 'module/types' references could have changed + oldProgram.structureIsReused = 1 /* SafeModules */; + // add file to the modified list so that we will resolve it later modifiedSourceFiles.push({ oldFile: oldSourceFile, newFile: newSourceFile }); } + // if file has passed all checks it should be safe to reuse it newSourceFiles.push(newSourceFile); } - if (oldProgram.structureIsReused !== 2) { + if (oldProgram.structureIsReused !== 2 /* Completely */) { return oldProgram.structureIsReused; } modifiedFilePaths = modifiedSourceFiles.map(function (f) { return f.newFile.path; }); + // try to verify results of module resolution for (var _a = 0, modifiedSourceFiles_1 = modifiedSourceFiles; _a < modifiedSourceFiles_1.length; _a++) { var _b = modifiedSourceFiles_1[_a], oldSourceFile = _b.oldFile, newSourceFile = _b.newFile; var newSourceFilePath = ts.getNormalizedAbsolutePath(newSourceFile.fileName, currentDirectory); @@ -68014,9 +81959,10 @@ var ts; var moduleNames = getModuleNames(newSourceFile); var oldProgramState = { program: oldProgram, oldSourceFile: oldSourceFile, modifiedFilePaths: modifiedFilePaths }; var resolutions = resolveModuleNamesReusingOldState(moduleNames, newSourceFilePath, newSourceFile, oldProgramState); + // ensure that module resolution results are still correct var resolutionsChanged = ts.hasChangesInResolutions(moduleNames, resolutions, oldSourceFile.resolvedModules, ts.moduleResolutionIsEqualTo); if (resolutionsChanged) { - oldProgram.structureIsReused = 1; + oldProgram.structureIsReused = 1 /* SafeModules */; newSourceFile.resolvedModules = ts.zipToMap(moduleNames, resolutions); } else { @@ -68026,9 +81972,10 @@ var ts; if (resolveTypeReferenceDirectiveNamesWorker) { var typesReferenceDirectives = ts.map(newSourceFile.typeReferenceDirectives, function (x) { return x.fileName; }); var resolutions = resolveTypeReferenceDirectiveNamesWorker(typesReferenceDirectives, newSourceFilePath); + // ensure that types resolutions are still correct var resolutionsChanged = ts.hasChangesInResolutions(typesReferenceDirectives, resolutions, oldSourceFile.resolvedTypeReferenceDirectiveNames, ts.typeDirectiveIsEqualTo); if (resolutionsChanged) { - oldProgram.structureIsReused = 1; + oldProgram.structureIsReused = 1 /* SafeModules */; newSourceFile.resolvedTypeReferenceDirectiveNames = ts.zipToMap(typesReferenceDirectives, resolutions); } else { @@ -68036,15 +81983,17 @@ var ts; } } } - if (oldProgram.structureIsReused !== 2) { + if (oldProgram.structureIsReused !== 2 /* Completely */) { return oldProgram.structureIsReused; } if (host.hasChangedAutomaticTypeDirectiveNames) { - return oldProgram.structureIsReused = 1; + return oldProgram.structureIsReused = 1 /* SafeModules */; } missingFilePaths = oldProgram.getMissingFilePaths(); + // update fileName -> file mapping for (var i = 0; i < newSourceFiles.length; i++) { filesByName.set(filePaths[i], newSourceFiles[i]); + // Set the file as found during node modules search if it was found that way in old progra, if (oldProgram.isSourceFileFromExternalLibrary(oldProgram.getSourceFileByPath(filePaths[i]))) { sourceFilesFoundSearchingNodeModules.set(filePaths[i], true); } @@ -68059,7 +82008,7 @@ var ts; resolvedProjectReferences = oldProgram.getProjectReferences(); sourceFileToPackageName = oldProgram.sourceFileToPackageName; redirectTargetsSet = oldProgram.redirectTargetsSet; - return oldProgram.structureIsReused = 2; + return oldProgram.structureIsReused = 2 /* Completely */; } function getEmitHost(writeFileCallback) { return __assign({ getPrependNodes: getPrependNodes, @@ -68079,11 +82028,12 @@ var ts; var ref = projectReferences[i]; var resolvedRefOpts = resolvedProjectReferences[i].commandLine; if (ref.prepend && resolvedRefOpts && resolvedRefOpts.options) { + // Upstream project didn't have outFile set -- skip (error will have been issued earlier) if (!resolvedRefOpts.options.outFile) continue; var dtsFilename = ts.changeExtension(resolvedRefOpts.options.outFile, ".d.ts"); var js = host.readFile(resolvedRefOpts.options.outFile) || "/* Input file " + resolvedRefOpts.options.outFile + " was missing */\r\n"; - var jsMapPath = resolvedRefOpts.options.outFile + ".map"; + var jsMapPath = resolvedRefOpts.options.outFile + ".map"; // TODO: try to read sourceMappingUrl comment from the file var jsMap = host.readFile(jsMapPath); var dts = host.readFile(dtsFilename) || "/* Input file " + dtsFilename + " was missing */\r\n"; var dtsMapPath = dtsFilename + ".map"; @@ -68104,6 +82054,8 @@ var ts; if (!options.noLib) { return false; } + // If '--lib' is not specified, include default library file according to '--target' + // otherwise, using options specified in '--lib' instead of '--target' default library file var equalityComparer = host.useCaseSensitiveFileNames() ? ts.equateStringsCaseSensitive : ts.equateStringsCaseInsensitive; if (!options.lib) { return equalityComparer(file.fileName, getDefaultLibraryFileName()); @@ -68113,13 +82065,13 @@ var ts; } } function getDiagnosticsProducingTypeChecker() { - return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = ts.createTypeChecker(program, true)); + return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = ts.createTypeChecker(program, /*produceDiagnostics:*/ true)); } function dropDiagnosticsProducingTypeChecker() { diagnosticsProducingTypeChecker = undefined; } function getTypeChecker() { - return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = ts.createTypeChecker(program, false)); + return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = ts.createTypeChecker(program, /*produceDiagnostics:*/ false)); } function emit(sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles, transformers) { return runWithCancellationToken(function () { return emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles, transformers); }); @@ -68133,10 +82085,13 @@ var ts; if (options.noEmit) { return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true }; } + // If the noEmitOnError flag is set, then check if we have any errors so far. If so, + // immediately bail out. Note that we pass 'undefined' for 'sourceFile' so that we + // get any preEmit diagnostics, not just the ones if (options.noEmitOnError) { var diagnostics = program.getOptionsDiagnostics(cancellationToken).concat(program.getSyntacticDiagnostics(sourceFile, cancellationToken), program.getGlobalDiagnostics(cancellationToken), program.getSemanticDiagnostics(sourceFile, cancellationToken)); if (diagnostics.length === 0 && program.getCompilerOptions().declaration) { - declarationDiagnostics = program.getDeclarationDiagnostics(undefined, cancellationToken); + declarationDiagnostics = program.getDeclarationDiagnostics(/*sourceFile*/ undefined, cancellationToken); } if (diagnostics.length > 0 || declarationDiagnostics.length > 0) { return { @@ -68148,10 +82103,19 @@ var ts; } } } + // Create the emit resolver outside of the "emitTime" tracking code below. That way + // any cost associated with it (like type checking) are appropriate associated with + // the type-checking counter. + // + // If the -out option is specified, we should not pass the source file to getEmitResolver. + // This is because in the -out scenario all files need to be emitted, and therefore all + // files need to be type checked. And the way to specify that all files need to be type + // checked is to not pass the file to getEmitResolver. var emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver((options.outFile || options.out) ? undefined : sourceFile, cancellationToken); ts.performance.mark("beforeEmit"); var transformers = emitOnlyDtsFiles ? [] : ts.getTransformers(options, customTransformers); - var emitResult = ts.emitFiles(emitResolver, getEmitHost(writeFileCallback), sourceFile, emitOnlyDtsFiles, transformers, customTransformers && customTransformers.afterDeclarations); + var emitResult = ts.emitFiles(emitResolver, getEmitHost(writeFileCallback), sourceFile, // TODO: GH#18217 + emitOnlyDtsFiles, transformers, customTransformers && customTransformers.afterDeclarations); ts.performance.mark("afterEmit"); ts.performance.measure("Emit", "beforeEmit", "afterEmit"); return emitResult; @@ -68181,6 +82145,7 @@ var ts; } function getDeclarationDiagnostics(sourceFile, cancellationToken) { var options = program.getCompilerOptions(); + // collect diagnostics from the program only once if either no source file was specified or out/outFile is set (bundled emit) if (!sourceFile || options.out || options.outFile) { return getDeclarationDiagnosticsWorker(sourceFile, cancellationToken); } @@ -68189,6 +82154,8 @@ var ts; } } function getSyntacticDiagnosticsForFile(sourceFile) { + // For JavaScript files, we report semantic errors for using TypeScript-only + // constructs from within a JavaScript file as syntactic errors. if (ts.isSourceFileJavaScript(sourceFile)) { if (!sourceFile.additionalSyntacticDiagnostics) { sourceFile.additionalSyntacticDiagnostics = getJavaScriptSyntacticDiagnosticsForFile(sourceFile); @@ -68203,6 +82170,15 @@ var ts; } catch (e) { if (e instanceof ts.OperationCanceledException) { + // We were canceled while performing the operation. Because our type checker + // might be a bad state, we need to throw it away. + // + // Note: we are overly aggressive here. We do not actually *have* to throw away + // the "noDiagnosticsTypeChecker". However, for simplicity, i'd like to keep + // the lifetimes of these two TypeCheckers the same. Also, we generally only + // cancel when the user has made a change anyways. And, in that case, we (the + // program instance) will get thrown away anyways. So trying to keep one of + // these type checkers alive doesn't serve much purpose. noDiagnosticsTypeChecker = undefined; diagnosticsProducingTypeChecker = undefined; } @@ -68214,14 +82190,18 @@ var ts; } function getSemanticDiagnosticsForFileNoCache(sourceFile, cancellationToken) { return runWithCancellationToken(function () { + // If skipLibCheck is enabled, skip reporting errors if file is a declaration file. + // If skipDefaultLibCheck is enabled, skip reporting errors if file contains a + // '/// ' directive. if (options.skipLibCheck && sourceFile.isDeclarationFile || options.skipDefaultLibCheck && sourceFile.hasNoDefaultLib) { return ts.emptyArray; } var typeChecker = getDiagnosticsProducingTypeChecker(); ts.Debug.assert(!!sourceFile.bindDiagnostics); var isCheckJs = ts.isCheckJsEnabledForFile(sourceFile, options); - var includeBindAndCheckDiagnostics = sourceFile.scriptKind === 3 || sourceFile.scriptKind === 4 || - sourceFile.scriptKind === 5 || isCheckJs || sourceFile.scriptKind === 7; + // By default, only type-check .ts, .tsx, 'Deferred' and 'External' files (external files are added by plugins) + var includeBindAndCheckDiagnostics = sourceFile.scriptKind === 3 /* TS */ || sourceFile.scriptKind === 4 /* TSX */ || + sourceFile.scriptKind === 5 /* External */ || isCheckJs || sourceFile.scriptKind === 7 /* Deferred */; var bindDiagnostics = includeBindAndCheckDiagnostics ? sourceFile.bindDiagnostics : ts.emptyArray; var checkDiagnostics = includeBindAndCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : ts.emptyArray; var fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName); @@ -68246,18 +82226,23 @@ var ts; return getDiagnosticsProducingTypeChecker().getSuggestionDiagnostics(sourceFile, cancellationToken); }); } + /** + * Skip errors if previous line start with '// @ts-ignore' comment, not counting non-empty non-comment lines + */ function shouldReportDiagnostic(diagnostic) { var file = diagnostic.file, start = diagnostic.start; if (file) { var lineStarts = ts.getLineStarts(file); - var line = ts.computeLineAndCharacterOfPosition(lineStarts, start).line; + var line = ts.computeLineAndCharacterOfPosition(lineStarts, start).line; // TODO: GH#18217 while (line > 0) { var previousLineText = file.text.slice(lineStarts[line - 1], lineStarts[line]); var result = ignoreDiagnosticCommentRegEx.exec(previousLineText); if (!result) { + // non-empty line return true; } if (result[3]) { + // @ts-ignore return false; } line--; @@ -68272,64 +82257,68 @@ var ts; walk(sourceFile); return diagnostics; function walk(node) { + // Return directly from the case if the given node doesnt want to visit each child + // Otherwise break to visit each child switch (parent.kind) { - case 149: - case 152: + case 149 /* Parameter */: + case 152 /* PropertyDeclaration */: if (parent.questionToken === node) { diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics._0_can_only_be_used_in_a_ts_file, "?")); return; } - case 154: - case 153: - case 155: - case 156: - case 157: - case 192: - case 234: - case 193: - case 232: + // falls through + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 192 /* FunctionExpression */: + case 234 /* FunctionDeclaration */: + case 193 /* ArrowFunction */: + case 232 /* VariableDeclaration */: + // type annotation if (parent.type === node) { diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.types_can_only_be_used_in_a_ts_file)); return; } } switch (node.kind) { - case 243: + case 243 /* ImportEqualsDeclaration */: diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.import_can_only_be_used_in_a_ts_file)); return; - case 249: + case 249 /* ExportAssignment */: if (node.isExportEquals) { diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.export_can_only_be_used_in_a_ts_file)); return; } break; - case 268: + case 268 /* HeritageClause */: var heritageClause = node; - if (heritageClause.token === 108) { + if (heritageClause.token === 108 /* ImplementsKeyword */) { diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.implements_clauses_can_only_be_used_in_a_ts_file)); return; } break; - case 236: + case 236 /* InterfaceDeclaration */: diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.interface_declarations_can_only_be_used_in_a_ts_file)); return; - case 239: + case 239 /* ModuleDeclaration */: diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.module_declarations_can_only_be_used_in_a_ts_file)); return; - case 237: + case 237 /* TypeAliasDeclaration */: diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.type_aliases_can_only_be_used_in_a_ts_file)); return; - case 238: + case 238 /* EnumDeclaration */: diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.enum_declarations_can_only_be_used_in_a_ts_file)); return; - case 209: + case 209 /* NonNullExpression */: diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.non_null_assertions_can_only_be_used_in_a_ts_file)); return; - case 208: + case 208 /* AsExpression */: diagnostics.push(createDiagnosticForNode(node.type, ts.Diagnostics.type_assertion_expressions_can_only_be_used_in_a_ts_file)); return; - case 190: - ts.Debug.fail(); + case 190 /* TypeAssertionExpression */: + ts.Debug.fail(); // Won't parse these in a JS file anyway, as they are interpreted as JSX. } var prevParent = parent; parent = node; @@ -68341,46 +82330,52 @@ var ts; diagnostics.push(createDiagnosticForNode(parent, ts.Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_to_remove_this_warning)); } switch (parent.kind) { - case 235: - case 154: - case 153: - case 155: - case 156: - case 157: - case 192: - case 234: - case 193: + case 235 /* ClassDeclaration */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 192 /* FunctionExpression */: + case 234 /* FunctionDeclaration */: + case 193 /* ArrowFunction */: + // Check type parameters if (nodes === parent.typeParameters) { diagnostics.push(createDiagnosticForNodeArray(nodes, ts.Diagnostics.type_parameter_declarations_can_only_be_used_in_a_ts_file)); return; } - case 214: + // falls through + case 214 /* VariableStatement */: + // Check modifiers if (nodes === parent.modifiers) { - return checkModifiers(nodes, parent.kind === 214); + return checkModifiers(nodes, parent.kind === 214 /* VariableStatement */); } break; - case 152: + case 152 /* PropertyDeclaration */: + // Check modifiers of property declaration if (nodes === parent.modifiers) { for (var _i = 0, _a = nodes; _i < _a.length; _i++) { var modifier = _a[_i]; - if (modifier.kind !== 115) { + if (modifier.kind !== 115 /* StaticKeyword */) { diagnostics.push(createDiagnosticForNode(modifier, ts.Diagnostics._0_can_only_be_used_in_a_ts_file, ts.tokenToString(modifier.kind))); } } return; } break; - case 149: + case 149 /* Parameter */: + // Check modifiers of parameter declaration if (nodes === parent.modifiers) { diagnostics.push(createDiagnosticForNodeArray(nodes, ts.Diagnostics.parameter_modifiers_can_only_be_used_in_a_ts_file)); return; } break; - case 187: - case 188: - case 207: - case 256: - case 257: + case 187 /* CallExpression */: + case 188 /* NewExpression */: + case 207 /* ExpressionWithTypeArguments */: + case 256 /* JsxSelfClosingElement */: + case 257 /* JsxOpeningElement */: + // Check type arguments if (nodes === parent.typeArguments) { diagnostics.push(createDiagnosticForNodeArray(nodes, ts.Diagnostics.type_arguments_can_only_be_used_in_a_ts_file)); return; @@ -68396,21 +82391,24 @@ var ts; for (var _i = 0, modifiers_1 = modifiers; _i < modifiers_1.length; _i++) { var modifier = modifiers_1[_i]; switch (modifier.kind) { - case 76: + case 76 /* ConstKeyword */: if (isConstValid) { continue; } - case 114: - case 112: - case 113: - case 132: - case 124: - case 117: + // to report error, + // falls through + case 114 /* PublicKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: + case 132 /* ReadonlyKeyword */: + case 124 /* DeclareKeyword */: + case 117 /* AbstractKeyword */: diagnostics.push(createDiagnosticForNode(modifier, ts.Diagnostics._0_can_only_be_used_in_a_ts_file, ts.tokenToString(modifier.kind))); break; - case 115: - case 84: - case 79: + // These are all legal modifiers. + case 115 /* StaticKeyword */: + case 84 /* ExportKeyword */: + case 79 /* DefaultKeyword */: } } } @@ -68418,6 +82416,8 @@ var ts; var start = nodes.pos; return ts.createFileDiagnostic(sourceFile, start, nodes.end - start, message, arg0, arg1, arg2); } + // Since these are syntactic diagnostics, parent might not have been set + // this means the sourceFile cannot be infered from the node function createDiagnosticForNode(node, message, arg0, arg1, arg2) { return ts.createDiagnosticForNodeInSourceFile(sourceFile, node, message, arg0, arg1, arg2); } @@ -68429,6 +82429,7 @@ var ts; function getDeclarationDiagnosticsForFileNoCache(sourceFile, cancellationToken) { return runWithCancellationToken(function () { var resolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile, cancellationToken); + // Don't actually write any files since we're just getting diagnostics. return ts.getDeclarationDiagnostics(getEmitHost(ts.noop), resolver, sourceFile); }); } @@ -68439,7 +82440,7 @@ var ts; if (cachedResult) { return cachedResult; } - var result = getDiagnostics(sourceFile, cancellationToken) || ts.emptyArray; + var result = getDiagnostics(sourceFile, cancellationToken) || ts.emptyArray; // TODO: GH#18217 if (sourceFile) { if (!cache.perFile) { cache.perFile = ts.createMap(); @@ -68464,15 +82465,15 @@ var ts; return configFileParsingDiagnostics || ts.emptyArray; } function processRootFile(fileName, isDefaultLib, ignoreNoDefaultLib) { - processSourceFile(ts.normalizePath(fileName), isDefaultLib, ignoreNoDefaultLib, undefined); + processSourceFile(ts.normalizePath(fileName), isDefaultLib, ignoreNoDefaultLib, /*packageId*/ undefined); } function fileReferenceIsEqualTo(a, b) { return a.fileName === b.fileName; } function moduleNameIsEqualTo(a, b) { - return a.kind === 71 - ? b.kind === 71 && a.escapedText === b.escapedText - : b.kind === 9 && a.text === b.text; + return a.kind === 71 /* Identifier */ + ? b.kind === 71 /* Identifier */ && a.escapedText === b.escapedText + : b.kind === 9 /* StringLiteral */ && a.text === b.text; } function collectExternalModuleReferences(file) { if (file.imports) { @@ -68480,27 +82481,31 @@ var ts; } var isJavaScriptFile = ts.isSourceFileJavaScript(file); var isExternalModuleFile = ts.isExternalModule(file); + // file.imports may not be undefined if there exists dynamic import var imports; var moduleAugmentations; var ambientModules; + // If we are importing helpers, we need to add a synthetic reference to resolve the + // helpers library. if (options.importHelpers && (options.isolatedModules || isExternalModuleFile) && !file.isDeclarationFile) { + // synthesize 'import "tslib"' declaration var externalHelpersModuleReference = ts.createLiteral(ts.externalHelpersModuleNameText); - var importDecl = ts.createImportDeclaration(undefined, undefined, undefined, externalHelpersModuleReference); - ts.addEmitFlags(importDecl, 67108864); + var importDecl = ts.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*importClause*/ undefined, externalHelpersModuleReference); + ts.addEmitFlags(importDecl, 67108864 /* NeverApplyImportHelper */); externalHelpersModuleReference.parent = importDecl; importDecl.parent = file; imports = [externalHelpersModuleReference]; } for (var _i = 0, _a = file.statements; _i < _a.length; _i++) { var node = _a[_i]; - collectModuleReferences(node, false); - if ((file.flags & 524288) || isJavaScriptFile) { + collectModuleReferences(node, /*inAmbientModule*/ false); + if ((file.flags & 524288 /* PossiblyContainsDynamicImport */) || isJavaScriptFile) { collectDynamicImportOrRequireCalls(node); } } - if ((file.flags & 524288) || isJavaScriptFile) { + if ((file.flags & 524288 /* PossiblyContainsDynamicImport */) || isJavaScriptFile) { collectDynamicImportOrRequireCalls(file.endOfFileToken); } file.imports = imports || ts.emptyArray; @@ -68510,25 +82515,39 @@ var ts; function collectModuleReferences(node, inAmbientModule) { if (ts.isAnyImportOrReExport(node)) { var moduleNameExpr = ts.getExternalModuleName(node); + // TypeScript 1.0 spec (April 2014): 12.1.6 + // An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference other external modules + // only through top - level external module names. Relative external module names are not permitted. if (moduleNameExpr && ts.isStringLiteral(moduleNameExpr) && moduleNameExpr.text && (!inAmbientModule || !ts.isExternalModuleNameRelative(moduleNameExpr.text))) { imports = ts.append(imports, moduleNameExpr); } } else if (ts.isModuleDeclaration(node)) { - if (ts.isAmbientModule(node) && (inAmbientModule || ts.hasModifier(node, 2) || file.isDeclarationFile)) { + if (ts.isAmbientModule(node) && (inAmbientModule || ts.hasModifier(node, 2 /* Ambient */) || file.isDeclarationFile)) { var nameText = ts.getTextOfIdentifierOrLiteral(node.name); + // Ambient module declarations can be interpreted as augmentations for some existing external modules. + // This will happen in two cases: + // - if current file is external module then module augmentation is a ambient module declaration defined in the top level scope + // - if current file is not external module then module augmentation is an ambient module declaration with non-relative module name + // immediately nested in top level ambient module declaration . if (isExternalModuleFile || (inAmbientModule && !ts.isExternalModuleNameRelative(nameText))) { (moduleAugmentations || (moduleAugmentations = [])).push(node.name); } else if (!inAmbientModule) { if (file.isDeclarationFile) { + // for global .d.ts files record name of ambient module (ambientModules || (ambientModules = [])).push(nameText); } + // An AmbientExternalModuleDeclaration declares an external module. + // This type of declaration is permitted only in the global module. + // The StringLiteral must specify a top - level external module name. + // Relative external module names are not permitted + // NOTE: body of ambient module is always a module block, if it exists var body = node.body; if (body) { for (var _i = 0, _a = body.statements; _i < _a.length; _i++) { var statement = _a[_i]; - collectModuleReferences(statement, true); + collectModuleReferences(statement, /*inAmbientModule*/ true); } } } @@ -68536,9 +82555,10 @@ var ts; } } function collectDynamicImportOrRequireCalls(node) { - if (ts.isRequireCall(node, true)) { + if (ts.isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true)) { imports = ts.append(imports, node.arguments[0]); } + // we have to check the argument list has length of 1. We will still have to process these even though we have parsing error. else if (ts.isImportCall(node) && node.arguments.length === 1 && ts.isStringLiteralLike(node.arguments[0])) { imports = ts.append(imports, node.arguments[0]); } @@ -68561,6 +82581,7 @@ var ts; return getSourceFile(ts.combinePaths(defaultLibraryPath, libFileName)); } } + /** This should have similar behavior to 'processSourceFile' without diagnostics or mutation. */ function getSourceFileFromReference(referencingFile, ref) { return getSourceFileFromReferenceWorker(resolveTripleslashReference(ref.fileName, referencingFile.fileName), function (fileName) { return filesByName.get(toPath(fileName)); }); } @@ -68598,12 +82619,14 @@ var ts; } var sourceFileWithAddedExtension = ts.forEach(supportedExtensions, function (extension) { return getSourceFile(fileName + extension); }); if (fail && !sourceFileWithAddedExtension) - fail(ts.Diagnostics.File_0_not_found, fileName + ".ts"); + fail(ts.Diagnostics.File_0_not_found, fileName + ".ts" /* Ts */); return sourceFileWithAddedExtension; } } + /** This has side effects through `findSourceFile`. */ function processSourceFile(fileName, isDefaultLib, ignoreNoDefaultLib, packageId, refFile, refPos, refEnd) { - getSourceFileFromReferenceWorker(fileName, function (fileName) { return findSourceFile(fileName, toPath(fileName), isDefaultLib, ignoreNoDefaultLib, refFile, refPos, refEnd, packageId); }, function (diagnostic) { + getSourceFileFromReferenceWorker(fileName, function (fileName) { return findSourceFile(fileName, toPath(fileName), isDefaultLib, ignoreNoDefaultLib, refFile, refPos, refEnd, packageId); }, // TODO: GH#18217 + function (diagnostic) { var args = []; for (var _i = 1; _i < arguments.length; _i++) { args[_i - 1] = arguments[_i]; @@ -68637,12 +82660,17 @@ var ts; }); return redirect; } + // Get source file from normalized fileName function findSourceFile(fileName, path, isDefaultLib, ignoreNoDefaultLib, refFile, refPos, refEnd, packageId) { if (filesByName.has(path)) { var file_1 = filesByName.get(path); + // try to check if we've already seen this file but with a different casing in path + // NOTE: this only makes sense for case-insensitive file systems if (file_1 && options.forceConsistentCasingInFileNames && ts.getNormalizedAbsolutePath(file_1.fileName, currentDirectory) !== ts.getNormalizedAbsolutePath(fileName, currentDirectory)) { reportFileNamesDifferOnlyInCasingError(fileName, file_1.fileName, refFile, refPos, refEnd); } + // If the file was previously found via a node_modules search, but is now being processed as a root file, + // then everything it sucks in may also be marked incorrectly, and needs to be checked again. if (file_1 && sourceFilesFoundSearchingNodeModules.get(file_1.path) && currentNodeModulesDepth === 0) { sourceFilesFoundSearchingNodeModules.set(file_1.path, false); if (!options.noResolve) { @@ -68653,6 +82681,7 @@ var ts; modulesWithElidedImports.set(file_1.path, false); processImportedModules(file_1); } + // See if we need to reprocess the imports due to prior skipped imports else if (file_1 && modulesWithElidedImports.get(file_1.path)) { if (currentNodeModulesDepth < maxNodeModuleJsDepth) { modulesWithElidedImports.set(file_1.path, false); @@ -68667,9 +82696,15 @@ var ts; if (redirect) { (refFile.redirectedReferences || (refFile.redirectedReferences = [])).push(fileName); fileName = redirect; + // Once we start redirecting to a file, we can potentially come back to it + // via a back-reference from another file in the .d.ts folder. If that happens we'll + // end up trying to add it to the program *again* because we were tracking it via its + // original (un-redirected) name. So we have to map both the original path and the redirected path + // to the source file we're about to find/create redirectedPath = toPath(redirect); } } + // We haven't looked for this file, do so now and cache result var file = host.getSourceFile(fileName, options.target, function (hostErrorMessage) { if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) { fileProcessingDiagnostics.add(ts.createFileDiagnostic(refFile, refPos, refEnd - refPos, ts.Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage)); @@ -68682,7 +82717,9 @@ var ts; var packageIdKey = ts.packageIdToString(packageId); var fileFromPackageId = packageIdToSourceFile.get(packageIdKey); if (fileFromPackageId) { - var dupFile = createRedirectSourceFile(fileFromPackageId, file, fileName, path); + // Some other SourceFile already exists with this package name and version. + // Instead of creating a duplicate, just redirect to the existing one. + var dupFile = createRedirectSourceFile(fileFromPackageId, file, fileName, path); // TODO: GH#18217 redirectTargetsSet.set(fileFromPackageId.path, true); filesByName.set(path, dupFile); sourceFileToPackageName.set(path, packageId.name); @@ -68690,6 +82727,7 @@ var ts; return dupFile; } else if (file) { + // This is the first source file to have this packageId. packageIdToSourceFile.set(packageIdKey, file); sourceFileToPackageName.set(path, packageId.name); } @@ -68704,6 +82742,7 @@ var ts; file.resolvedPath = toPath(fileName); if (host.useCaseSensitiveFileNames()) { var pathLowerCase = path.toLowerCase(); + // for case-sensitive file systems check if we've already seen some file with similar filename ignoring case var existingFile = filesByNameIgnoreCase.get(pathLowerCase); if (existingFile) { reportFileNamesDifferOnlyInCasingError(fileName, existingFile.fileName, refFile, refPos, refEnd); @@ -68718,6 +82757,7 @@ var ts; processTypeReferenceDirectives(file); } processLibReferenceDirectives(file); + // always process imported modules to record module name resolutions processImportedModules(file); if (isDefaultLib) { processingDefaultLibFiles.push(file); @@ -68730,6 +82770,8 @@ var ts; } function getProjectReferenceRedirect(fileName) { var path = toPath(fileName); + // If this file is produced by a referenced project, we need to rewrite it to + // look in the output folder of the referenced project rather than the input var normalized = ts.getNormalizedAbsolutePath(fileName, path); var result; projectReferenceRedirects.forEach(function (v, k) { @@ -68745,10 +82787,11 @@ var ts; function processReferencedFiles(file, isDefaultLib) { ts.forEach(file.referencedFiles, function (ref) { var referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName); - processSourceFile(referencedFileName, isDefaultLib, false, undefined, file, ref.pos, ref.end); + processSourceFile(referencedFileName, isDefaultLib, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined, file, ref.pos, ref.end); }); } function processTypeReferenceDirectives(file) { + // We lower-case all type references because npm automatically lowercases all packages. See GH#9824. var typeDirectives = ts.map(file.typeReferenceDirectives, function (ref) { return ref.fileName.toLocaleLowerCase(); }); if (!typeDirectives) { return; @@ -68757,12 +82800,14 @@ var ts; for (var i = 0; i < typeDirectives.length; i++) { var ref = file.typeReferenceDirectives[i]; var resolvedTypeReferenceDirective = resolutions[i]; + // store resolved type directive on the file var fileName = ref.fileName.toLocaleLowerCase(); ts.setResolvedTypeReferenceDirective(file, fileName, resolvedTypeReferenceDirective); processTypeReferenceDirective(fileName, resolvedTypeReferenceDirective, file, ref.pos, ref.end); } } function processTypeReferenceDirective(typeReferenceDirective, resolvedTypeReferenceDirective, refFile, refPos, refEnd) { + // If we already found this library as a primary reference - nothing to do var previousResolution = resolvedTypeReferenceDirectives.get(typeReferenceDirective); if (previousResolution && previousResolution.primary) { return; @@ -68770,25 +82815,32 @@ var ts; var saveResolution = true; if (resolvedTypeReferenceDirective) { if (resolvedTypeReferenceDirective.primary) { - processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, false, false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd); + // resolved from the primary path + processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd); // TODO: GH#18217 } else { + // If we already resolved to this file, it must have been a secondary reference. Check file contents + // for sameness and possibly issue an error if (previousResolution) { + // Don't bother reading the file again if it's the same file. if (resolvedTypeReferenceDirective.resolvedFileName !== previousResolution.resolvedFileName) { var otherFileText = host.readFile(resolvedTypeReferenceDirective.resolvedFileName); if (otherFileText !== getSourceFile(previousResolution.resolvedFileName).text) { - fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd, ts.Diagnostics.Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict, typeReferenceDirective, resolvedTypeReferenceDirective.resolvedFileName, previousResolution.resolvedFileName)); + fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd, // TODO: GH#18217 + ts.Diagnostics.Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict, typeReferenceDirective, resolvedTypeReferenceDirective.resolvedFileName, previousResolution.resolvedFileName)); } } + // don't overwrite previous resolution result saveResolution = false; } else { - processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, false, false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd); + // First resolution of this library + processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd); } } } else { - fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd, ts.Diagnostics.Cannot_find_type_definition_file_for_0, typeReferenceDirective)); + fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd, ts.Diagnostics.Cannot_find_type_definition_file_for_0, typeReferenceDirective)); // TODO: GH#18217 } if (saveResolution) { resolvedTypeReferenceDirectives.set(typeReferenceDirective, resolvedTypeReferenceDirective); @@ -68799,7 +82851,8 @@ var ts; var libName = libReference.fileName.toLocaleLowerCase(); var libFileName = ts.libMap.get(libName); if (libFileName) { - processRootFile(ts.combinePaths(defaultLibraryPath, libFileName), true, true); + // we ignore any 'no-default-lib' reference set on this file. + processRootFile(ts.combinePaths(defaultLibraryPath, libFileName), /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ true); } else { var unqualifiedLibName = ts.removeSuffix(ts.removePrefix(libName, "lib."), ".d.ts"); @@ -68827,6 +82880,7 @@ var ts; function processImportedModules(file) { collectExternalModuleReferences(file); if (file.imports.length || file.moduleAugmentations.length) { + // Because global augmentation doesn't have string literal name, we can check for global augmentation as such. var moduleNames = getModuleNames(file); var oldProgramState = { program: oldProgram, oldSourceFile: oldProgram && oldProgram.getSourceFile(file.fileName), modifiedFilePaths: modifiedFilePaths }; var resolutions = resolveModuleNamesReusingOldState(moduleNames, ts.getNormalizedAbsolutePath(file.fileName, currentDirectory), file, oldProgramState); @@ -68844,21 +82898,28 @@ var ts; if (isFromNodeModulesSearch) { currentNodeModulesDepth++; } + // add file to program only if: + // - resolution was successful + // - noResolve is falsy + // - module name comes from the list of imports + // - it's not a top level JavaScript module that exceeded the search max var elideImport = isJsFileFromNodeModules && currentNodeModulesDepth > maxNodeModuleJsDepth; + // Don't add the file if it has a bad extension (e.g. 'tsx' if we don't have '--allowJs') + // This may still end up being an untyped module -- the file won't be included but imports will be allowed. var shouldAddFile = resolvedFileName && !getResolutionDiagnostic(options, resolution) && !options.noResolve && i < file.imports.length && !elideImport && !(isJsFile && !options.allowJs) - && (ts.isInJavaScriptFile(file.imports[i]) || !(file.imports[i].flags & 2097152)); + && (ts.isInJavaScriptFile(file.imports[i]) || !(file.imports[i].flags & 2097152 /* JSDoc */)); if (elideImport) { modulesWithElidedImports.set(file.path, true); } else if (shouldAddFile) { var path = toPath(resolvedFileName); var pos = ts.skipTrivia(file.text, file.imports[i].pos); - findSourceFile(resolvedFileName, path, false, false, file, pos, file.imports[i].end, resolution.packageId); + findSourceFile(resolvedFileName, path, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, file, pos, file.imports[i].end, resolution.packageId); } if (isFromNodeModulesSearch) { currentNodeModulesDepth--; @@ -68866,6 +82927,7 @@ var ts; } } else { + // no imports - drop cached module resolutions file.resolvedModules = undefined; } } @@ -68897,23 +82959,25 @@ var ts; return allFilesBelongToPath; } function parseProjectReferenceConfigFile(ref) { + // The actual filename (i.e. add "/tsconfig.json" if necessary) var refPath = resolveProjectReferencePath(host, ref); + // An absolute path pointing to the containing directory of the config file var basePath = ts.getNormalizedAbsolutePath(ts.getDirectoryPath(refPath), host.getCurrentDirectory()); - var sourceFile = host.getSourceFile(refPath, 100); + var sourceFile = host.getSourceFile(refPath, 100 /* JSON */); if (sourceFile === undefined) { return undefined; } - var commandLine = ts.parseJsonSourceFileConfigFileContent(sourceFile, configParsingHost, basePath, undefined, refPath); + var commandLine = ts.parseJsonSourceFileConfigFileContent(sourceFile, configParsingHost, basePath, /*existingOptions*/ undefined, refPath); return { commandLine: commandLine, sourceFile: sourceFile }; } function addProjectReferenceRedirects(referencedProject, target) { - var rootDir = ts.normalizePath(referencedProject.options.rootDir || ts.getDirectoryPath(referencedProject.options.configFilePath)); + var rootDir = ts.normalizePath(referencedProject.options.rootDir || ts.getDirectoryPath(referencedProject.options.configFilePath)); // TODO: GH#18217 target.set(rootDir, getDeclarationOutputDirectory(referencedProject)); } function getDeclarationOutputDirectory(proj) { return proj.options.declarationDir || proj.options.outDir || - ts.getDirectoryPath(proj.options.configFilePath); + ts.getDirectoryPath(proj.options.configFilePath); // TODO: GH#18217 } function verifyCompilerOptions() { if (options.strictPropertyInitialization && !options.strictNullChecks) { @@ -68972,6 +83036,7 @@ var ts; } } } + // List of collected files is complete; validate exhautiveness if this is a project with a file list if (options.composite && rootNames.length < files.length) { var normalizedRootNames = rootNames.map(function (r) { return ts.normalizePath(r).toLowerCase(); }); var sourceFiles = files.filter(function (f) { return !f.isDeclarationFile; }).map(function (f) { return ts.normalizePath(f.path).toLowerCase(); }); @@ -68991,12 +83056,12 @@ var ts; continue; } if (!ts.hasZeroOrOneAsteriskCharacter(key)) { - createDiagnosticForOptionPaths(true, key, ts.Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, key); + createDiagnosticForOptionPaths(/*onKey*/ true, key, ts.Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, key); } if (ts.isArray(options.paths[key])) { var len = options.paths[key].length; if (len === 0) { - createDiagnosticForOptionPaths(false, key, ts.Diagnostics.Substitutions_for_pattern_0_shouldn_t_be_an_empty_array, key); + createDiagnosticForOptionPaths(/*onKey*/ false, key, ts.Diagnostics.Substitutions_for_pattern_0_shouldn_t_be_an_empty_array, key); } for (var i = 0; i < len; i++) { var subst = options.paths[key][i]; @@ -69012,7 +83077,7 @@ var ts; } } else { - createDiagnosticForOptionPaths(false, key, ts.Diagnostics.Substitutions_for_pattern_0_should_be_an_array, key); + createDiagnosticForOptionPaths(/*onKey*/ false, key, ts.Diagnostics.Substitutions_for_pattern_0_should_be_an_array, key); } } } @@ -69028,6 +83093,7 @@ var ts; createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "outFile"); } if (options.mapRoot && !(options.sourceMap || options.declarationMap)) { + // Error to specify --mapRoot without --sourcemap createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "mapRoot", "sourceMap", "declarationMap"); } if (options.declarationDir) { @@ -69047,11 +83113,11 @@ var ts; if (options.noImplicitUseStrict && ts.getStrictOptionValue(options, "alwaysStrict")) { createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "noImplicitUseStrict", "alwaysStrict"); } - var languageVersion = options.target || 0; + var languageVersion = options.target || 0 /* ES3 */; var outFile = options.outFile || options.out; var firstNonAmbientExternalModuleSourceFile = ts.forEach(files, function (f) { return ts.isExternalModule(f) && !f.isDeclarationFile ? f : undefined; }); if (options.isolatedModules) { - if (options.module === ts.ModuleKind.None && languageVersion < 2) { + if (options.module === ts.ModuleKind.None && languageVersion < 2 /* ES2015 */) { createDiagnosticForOptionName(ts.Diagnostics.Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES2015_or_higher, "isolatedModules", "target"); } var firstNonExternalModuleSourceFile = ts.forEach(files, function (f) { return !ts.isExternalModule(f) && !f.isDeclarationFile ? f : undefined; }); @@ -69060,10 +83126,12 @@ var ts; programDiagnostics.add(ts.createFileDiagnostic(firstNonExternalModuleSourceFile, span.start, span.length, ts.Diagnostics.Cannot_compile_namespaces_when_the_isolatedModules_flag_is_provided)); } } - else if (firstNonAmbientExternalModuleSourceFile && languageVersion < 2 && options.module === ts.ModuleKind.None) { + else if (firstNonAmbientExternalModuleSourceFile && languageVersion < 2 /* ES2015 */ && options.module === ts.ModuleKind.None) { + // We cannot use createDiagnosticFromNode because nodes do not have parents yet var span = ts.getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator); programDiagnostics.add(ts.createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span.start, span.length, ts.Diagnostics.Cannot_use_imports_exports_or_module_augmentations_when_module_is_none)); } + // Cannot specify module gen that isn't amd or system with --out if (outFile) { if (options.module && !(options.module === ts.ModuleKind.AMD || options.module === ts.ModuleKind.System)) { createDiagnosticForOptionName(ts.Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, options.out ? "out" : "outFile", "module"); @@ -69078,10 +83146,14 @@ var ts; createDiagnosticForOptionName(ts.Diagnostics.Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy, "resolveJsonModule"); } } - if (options.outDir || - options.sourceRoot || - options.mapRoot) { + // there has to be common source directory if user specified --outdir || --sourceRoot + // if user specified --mapRoot, there needs to be common source directory if there would be multiple files being emitted + if (options.outDir || // there is --outDir specified + options.sourceRoot || // there is --sourceRoot specified + options.mapRoot) { // there is --mapRoot specified + // Precalculate and cache the common source directory var dir = getCommonSourceDirectory(); + // If we failed to find a good common directory, but outDir is specified and at least one of our files is on a windows drive/URL/other resource, add a failure if (options.outDir && dir === "" && ts.forEach(files, function (file) { return ts.getRootLength(file.fileName) > 1; })) { createDiagnosticForOptionName(ts.Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files, "outDir"); } @@ -69115,6 +83187,7 @@ var ts; else if (options.reactNamespace && !ts.isIdentifierText(options.reactNamespace, languageVersion)) { createOptionValueDiagnostic("reactNamespace", ts.Diagnostics.Invalid_value_for_reactNamespace_0_is_not_a_valid_identifier, options.reactNamespace); } + // If the emit is enabled make sure that every output file is unique and not overwriting any of the input files if (!options.noEmit && !options.suppressOutputPathCheck) { var emitHost = getEmitHost(); var emitFilesSeen_1 = ts.createMap(); @@ -69125,19 +83198,24 @@ var ts; verifyEmitFilePath(emitFileNames.declarationFilePath, emitFilesSeen_1); }); } + // Verify that all the emit files are unique and don't overwrite input files function verifyEmitFilePath(emitFileName, emitFilesSeen) { if (emitFileName) { var emitFilePath = toPath(emitFileName); + // Report error if the output overwrites input file if (filesByName.has(emitFilePath)) { var chain_2; if (!options.configFilePath) { - chain_2 = ts.chainDiagnosticMessages(undefined, ts.Diagnostics.Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript_files_Learn_more_at_https_Colon_Slash_Slashaka_ms_Slashtsconfig); + // The program is from either an inferred project or an external project + chain_2 = ts.chainDiagnosticMessages(/*details*/ undefined, ts.Diagnostics.Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript_files_Learn_more_at_https_Colon_Slash_Slashaka_ms_Slashtsconfig); } chain_2 = ts.chainDiagnosticMessages(chain_2, ts.Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file, emitFileName); blockEmittingOfFile(emitFileName, ts.createCompilerDiagnosticFromMessageChain(chain_2)); } var emitFileKey = !host.useCaseSensitiveFileNames() ? emitFilePath.toLocaleLowerCase() : emitFilePath; + // Report error if multiple files write into same file if (emitFilesSeen.has(emitFileKey)) { + // Already seen the same emit file - report error blockEmittingOfFile(emitFileName, ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_write_file_0_because_it_would_be_overwritten_by_multiple_input_files, emitFileName)); } else { @@ -69172,7 +83250,7 @@ var ts; for (var _i = 0, pathsSyntax_2 = pathsSyntax; _i < pathsSyntax_2.length; _i++) { var pathProp = pathsSyntax_2[_i]; if (ts.isObjectLiteralExpression(pathProp.initializer) && - createOptionDiagnosticInObjectLiteralSyntax(pathProp.initializer, onKey, key, undefined, message, arg0)) { + createOptionDiagnosticInObjectLiteralSyntax(pathProp.initializer, onKey, key, /*key2*/ undefined, message, arg0)) { needCompilerDiagnostic = false; } } @@ -69191,10 +83269,10 @@ var ts; return getOptionsSyntaxByName("paths") || ts.emptyArray; } function createDiagnosticForOptionName(message, option1, option2, option3) { - createDiagnosticForOption(true, option1, option2, message, option1, option2, option3); + createDiagnosticForOption(/*onKey*/ true, option1, option2, message, option1, option2, option3); } function createOptionValueDiagnostic(option1, message, arg0) { - createDiagnosticForOption(false, option1, undefined, message, arg0); + createDiagnosticForOption(/*onKey*/ false, option1, /*option2*/ undefined, message, arg0); } function createDiagnosticForReference(index, message, arg0, arg1) { var referencesSyntax = getProjectReferencesSyntax(); @@ -69215,9 +83293,9 @@ var ts; } function getProjectReferencesSyntax() { if (_referencesArrayLiteralSyntax === undefined) { - _referencesArrayLiteralSyntax = null; + _referencesArrayLiteralSyntax = null; // tslint:disable-line:no-null-keyword if (options.configFile) { - var jsonObjectLiteral = ts.getTsConfigObjectLiteralExpression(options.configFile); + var jsonObjectLiteral = ts.getTsConfigObjectLiteralExpression(options.configFile); // TODO: GH#18217 for (var _i = 0, _a = ts.getPropertyAssignment(jsonObjectLiteral, "references"); _i < _a.length; _i++) { var prop = _a[_i]; if (ts.isArrayLiteralExpression(prop.initializer)) { @@ -69231,7 +83309,7 @@ var ts; } function getCompilerOptionsObjectLiteralSyntax() { if (_compilerOptionsObjectLiteralSyntax === undefined) { - _compilerOptionsObjectLiteralSyntax = null; + _compilerOptionsObjectLiteralSyntax = null; // tslint:disable-line:no-null-keyword var jsonObjectLiteral = ts.getTsConfigObjectLiteralExpression(options.configFile); if (jsonObjectLiteral) { for (var _i = 0, _a = ts.getPropertyAssignment(jsonObjectLiteral, "compilerOptions"); _i < _a.length; _i++) { @@ -69255,10 +83333,11 @@ var ts; } function createOptionDiagnosticInArrayLiteralSyntax(arrayLiteral, index, message, arg0, arg1, arg2) { if (arrayLiteral.elements.length <= index) { + // Out-of-bounds return false; } programDiagnostics.add(ts.createDiagnosticForNodeInSourceFile(options.configFile, arrayLiteral.elements[index], message, arg0, arg1, arg2)); - return false; + return false; // TODO: GH#18217 This function always returns `false`!` } function blockEmittingOfFile(emitFileName, diag) { hasEmitBlockingDiagnostics.set(toPath(emitFileName), true); @@ -69268,32 +83347,38 @@ var ts; if (options.noEmit) { return false; } + // If this is source file, its not emitted file var filePath = toPath(file); if (getSourceFileByPath(filePath)) { return false; } + // If options have --outFile or --out just check that var out = options.outFile || options.out; if (out) { - return isSameFile(filePath, out) || isSameFile(filePath, ts.removeFileExtension(out) + ".d.ts"); + return isSameFile(filePath, out) || isSameFile(filePath, ts.removeFileExtension(out) + ".d.ts" /* Dts */); } + // If declarationDir is specified, return if its a file in that directory if (options.declarationDir && ts.containsPath(options.declarationDir, filePath, currentDirectory, !host.useCaseSensitiveFileNames())) { return true; } + // If --outDir, check if file is in that directory if (options.outDir) { return ts.containsPath(options.outDir, filePath, currentDirectory, !host.useCaseSensitiveFileNames()); } - if (ts.fileExtensionIsOneOf(filePath, ts.supportedJavascriptExtensions) || ts.fileExtensionIs(filePath, ".d.ts")) { + if (ts.fileExtensionIsOneOf(filePath, ts.supportedJavascriptExtensions) || ts.fileExtensionIs(filePath, ".d.ts" /* Dts */)) { + // Otherwise just check if sourceFile with the name exists var filePathWithoutExtension = ts.removeFileExtension(filePath); - return !!getSourceFileByPath((filePathWithoutExtension + ".ts")) || - !!getSourceFileByPath((filePathWithoutExtension + ".tsx")); + return !!getSourceFileByPath((filePathWithoutExtension + ".ts" /* Ts */)) || + !!getSourceFileByPath((filePathWithoutExtension + ".tsx" /* Tsx */)); } return false; } function isSameFile(file1, file2) { - return ts.comparePaths(file1, file2, currentDirectory, !host.useCaseSensitiveFileNames()) === 0; + return ts.comparePaths(file1, file2, currentDirectory, !host.useCaseSensitiveFileNames()) === 0 /* EqualTo */; } } ts.createProgram = createProgram; + /* @internal */ function parseConfigHostFromCompilerHost(host) { return { fileExists: function (f) { return host.fileExists(f); }, @@ -69305,6 +83390,9 @@ var ts; }; } ts.parseConfigHostFromCompilerHost = parseConfigHostFromCompilerHost; + /** + * Returns the target config filename of a project reference + */ function resolveProjectReferencePath(host, ref) { if (!host.fileExists(ref.path)) { return ts.combinePaths(ref.path, "tsconfig.json"); @@ -69312,18 +83400,25 @@ var ts; return ref.path; } ts.resolveProjectReferencePath = resolveProjectReferencePath; + /* @internal */ + /** + * Returns a DiagnosticMessage if we won't include a resolved module due to its extension. + * The DiagnosticMessage's parameters are the imported module name, and the filename it resolved to. + * This returns a diagnostic even if the module will be an untyped module. + */ function getResolutionDiagnostic(options, _a) { var extension = _a.extension; switch (extension) { - case ".ts": - case ".d.ts": - case ".json": + case ".ts" /* Ts */: + case ".d.ts" /* Dts */: + case ".json" /* Json */: // Since module is resolved to json file only when --resolveJsonModule, we dont need further check + // These are always allowed. return undefined; - case ".tsx": + case ".tsx" /* Tsx */: return needJsx(); - case ".jsx": + case ".jsx" /* Jsx */: return needJsx() || needAllowJs(); - case ".js": + case ".js" /* Js */: return needAllowJs(); } function needJsx() { @@ -69339,13 +83434,15 @@ var ts; var res = imports.map(function (i) { return i.text; }); for (var _i = 0, moduleAugmentations_1 = moduleAugmentations; _i < moduleAugmentations_1.length; _i++) { var aug = moduleAugmentations_1[_i]; - if (aug.kind === 9) { + if (aug.kind === 9 /* StringLiteral */) { res.push(aug.text); } + // Do nothing if it's an Identifier; we don't need to do module resolution for `declare global`. } return res; } })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { function getFileEmitOutput(program, sourceFile, emitOnlyDtsFiles, cancellationToken, customTransformers) { @@ -69358,11 +83455,18 @@ var ts; } ts.getFileEmitOutput = getFileEmitOutput; })(ts || (ts = {})); +/*@internal*/ (function (ts) { var BuilderState; (function (BuilderState) { + /** + * Gets the referenced files for a file from the program with values for the keys as referenced file's path to be true + */ function getReferencedFiles(program, sourceFile, getCanonicalFileName) { var referencedFiles; + // We need to use a set here since the code can contain the same import twice, + // but that will only be one dependency. + // To avoid invernal conversion, the key of the referencedFiles map must be of type Path if (sourceFile.imports && sourceFile.imports.length > 0) { var checker = program.getTypeChecker(); for (var _i = 0, _a = sourceFile.imports; _i < _a.length; _i++) { @@ -69377,6 +83481,7 @@ var ts; } } var sourceFileDirectory = ts.getDirectoryPath(sourceFile.path); + // Handle triple slash references if (sourceFile.referencedFiles && sourceFile.referencedFiles.length > 0) { for (var _b = 0, _c = sourceFile.referencedFiles; _b < _c.length; _b++) { var referencedFile = _c[_b]; @@ -69384,12 +83489,13 @@ var ts; addReferencedFile(referencedPath); } } + // Handle type reference directives if (sourceFile.resolvedTypeReferenceDirectiveNames) { sourceFile.resolvedTypeReferenceDirectiveNames.forEach(function (resolvedTypeReferenceDirective) { if (!resolvedTypeReferenceDirective) { return; } - var fileName = resolvedTypeReferenceDirective.resolvedFileName; + var fileName = resolvedTypeReferenceDirective.resolvedFileName; // TODO: GH#18217 var typeFilePath = ts.toPath(fileName, sourceFileDirectory, getCanonicalFileName); addReferencedFile(typeFilePath); }); @@ -69402,15 +83508,22 @@ var ts; referencedFiles.set(referencedPath, true); } } + /** + * Returns true if oldState is reusable, that is the emitKind = module/non module has not changed + */ function canReuseOldState(newReferencedMap, oldState) { return oldState && !oldState.referencedMap === !newReferencedMap; } BuilderState.canReuseOldState = canReuseOldState; + /** + * Creates the state of file references and signature for the new program from oldState if it is safe + */ function create(newProgram, getCanonicalFileName, oldState) { var fileInfos = ts.createMap(); var referencedMap = newProgram.getCompilerOptions().module !== ts.ModuleKind.None ? ts.createMap() : undefined; var hasCalledUpdateShapeSignature = ts.createMap(); var useOldState = canReuseOldState(referencedMap, oldState); + // Create the reference map, and set the file infos for (var _i = 0, _a = newProgram.getSourceFiles(); _i < _a.length; _i++) { var sourceFile = _a[_i]; var version_1 = sourceFile.version; @@ -69432,7 +83545,14 @@ var ts; }; } BuilderState.create = create; + /** + * Gets the files affected by the path from the program + */ function getFilesAffectedBy(state, programOfThisState, path, cancellationToken, computeHash, cacheToUpdateSignature) { + // Since the operation could be cancelled, the signatures are always stored in the cache + // They will be commited once it is safe to use them + // eg when calling this api from tsserver, if there is no cancellation of the operation + // In the other cases the affected files signatures are commited only after the iteration through the result is complete var signatureCache = cacheToUpdateSignature || ts.createMap(); var sourceFile = programOfThisState.getSourceFileByPath(path); if (!sourceFile) { @@ -69443,11 +83563,16 @@ var ts; } var result = (state.referencedMap ? getFilesAffectedByUpdatedShapeWhenModuleEmit : getFilesAffectedByUpdatedShapeWhenNonModuleEmit)(state, programOfThisState, sourceFile, signatureCache, cancellationToken, computeHash); if (!cacheToUpdateSignature) { + // Commit all the signatures in the signature cache updateSignaturesFromCache(state, signatureCache); } return result; } BuilderState.getFilesAffectedBy = getFilesAffectedBy; + /** + * Updates the signatures from the cache into state's fileinfo signatures + * This should be called whenever it is safe to commit the state of the builder + */ function updateSignaturesFromCache(state, signatureCache) { signatureCache.forEach(function (signature, path) { state.fileInfos.get(path).signature = signature; @@ -69455,8 +83580,12 @@ var ts; }); } BuilderState.updateSignaturesFromCache = updateSignaturesFromCache; + /** + * Returns if the shape of the signature has changed since last emit + */ function updateShapeSignature(state, programOfThisState, sourceFile, cacheToUpdateSignature, cancellationToken, computeHash) { ts.Debug.assert(!!sourceFile); + // If we have cached the result for this file, that means hence forth we should assume file shape is uptodate if (state.hasCalledUpdateShapeSignature.has(sourceFile.path) || cacheToUpdateSignature.has(sourceFile.path)) { return false; } @@ -69469,26 +83598,32 @@ var ts; latestSignature = sourceFile.version; } else { - var emitOutput = ts.getFileEmitOutput(programOfThisState, sourceFile, true, cancellationToken); + var emitOutput = ts.getFileEmitOutput(programOfThisState, sourceFile, /*emitOnlyDtsFiles*/ true, cancellationToken); if (emitOutput.outputFiles && emitOutput.outputFiles.length > 0) { latestSignature = computeHash(emitOutput.outputFiles[0].text); } else { - latestSignature = prevSignature; + latestSignature = prevSignature; // TODO: GH#18217 } } cacheToUpdateSignature.set(sourceFile.path, latestSignature); return !prevSignature || latestSignature !== prevSignature; } + /** + * Get all the dependencies of the sourceFile + */ function getAllDependencies(state, programOfThisState, sourceFile) { var _a; var compilerOptions = programOfThisState.getCompilerOptions(); + // With --out or --outFile all outputs go into single file, all files depend on each other if (compilerOptions.outFile || compilerOptions.out) { return getAllFileNames(state, programOfThisState); } + // If this is non module emit, or its a global file, it depends on all the source files if (!state.referencedMap || (!ts.isExternalModule(sourceFile) && !containsOnlyAmbientModules(sourceFile))) { return getAllFileNames(state, programOfThisState); } + // Get the references, traversing deep from the referenceMap var seenMap = ts.createMap(); var queue = [sourceFile.path]; while (queue.length) { @@ -69510,6 +83645,9 @@ var ts; })); } BuilderState.getAllDependencies = getAllDependencies; + /** + * Gets the names of all files from the program + */ function getAllFileNames(state, programOfThisState) { if (!state.allFileNames) { var sourceFiles = programOfThisState.getSourceFiles(); @@ -69517,12 +83655,21 @@ var ts; } return state.allFileNames; } + /** + * Gets the files referenced by the the file path + */ function getReferencedByPaths(state, referencedFilePath) { return ts.arrayFrom(ts.mapDefinedIterator(state.referencedMap.entries(), function (_a) { var filePath = _a[0], referencesInFile = _a[1]; return referencesInFile.has(referencedFilePath) ? filePath : undefined; })); } + /** + * For script files that contains only ambient external modules, although they are not actually external module files, + * they can only be consumed via importing elements from them. Regular script files cannot consume them. Therefore, + * there are no point to rebuild all script files if these special files have changed. However, if any statement + * in the file is not ambient external module, we treat it as a regular script file. + */ function containsOnlyAmbientModules(sourceFile) { for (var _i = 0, _a = sourceFile.statements; _i < _a.length; _i++) { var statement = _a[_i]; @@ -69532,7 +83679,11 @@ var ts; } return true; } + /** + * Gets all files of the program excluding the default library file + */ function getAllFilesExcludingDefaultLibraryFile(state, programOfThisState, firstSourceFile) { + // Use cached result if (state.allFilesExcludingDefaultLibraryFile) { return state.allFilesExcludingDefaultLibraryFile; } @@ -69552,13 +83703,21 @@ var ts; } } } + /** + * When program emits non modular code, gets the files affected by the sourceFile whose shape has changed + */ function getFilesAffectedByUpdatedShapeWhenNonModuleEmit(state, programOfThisState, sourceFileWithUpdatedShape) { var compilerOptions = programOfThisState.getCompilerOptions(); + // If `--out` or `--outFile` is specified, any new emit will result in re-emitting the entire project, + // so returning the file itself is good enough. if (compilerOptions && (compilerOptions.out || compilerOptions.outFile)) { return [sourceFileWithUpdatedShape]; } return getAllFilesExcludingDefaultLibraryFile(state, programOfThisState, sourceFileWithUpdatedShape); } + /** + * When program emits modular code, gets the files affected by the sourceFile whose shape has changed + */ function getFilesAffectedByUpdatedShapeWhenModuleEmit(state, programOfThisState, sourceFileWithUpdatedShape, cacheToUpdateSignature, cancellationToken, computeHash) { if (!ts.isExternalModule(sourceFileWithUpdatedShape) && !containsOnlyAmbientModules(sourceFileWithUpdatedShape)) { return getAllFilesExcludingDefaultLibraryFile(state, programOfThisState, sourceFileWithUpdatedShape); @@ -69567,7 +83726,11 @@ var ts; if (compilerOptions && (compilerOptions.isolatedModules || compilerOptions.out || compilerOptions.outFile)) { return [sourceFileWithUpdatedShape]; } + // Now we need to if each file in the referencedBy list has a shape change as well. + // Because if so, its own referencedBy files need to be saved as well to make the + // emitting result consistent with files on disk. var seenFileNamesMap = ts.createMap(); + // Start with the paths this file was referenced by seenFileNamesMap.set(sourceFileWithUpdatedShape.path, sourceFileWithUpdatedShape); var queue = getReferencedByPaths(state, sourceFileWithUpdatedShape.path); while (queue.length > 0) { @@ -69575,20 +83738,28 @@ var ts; if (!seenFileNamesMap.has(currentPath)) { var currentSourceFile = programOfThisState.getSourceFileByPath(currentPath); seenFileNamesMap.set(currentPath, currentSourceFile); - if (currentSourceFile && updateShapeSignature(state, programOfThisState, currentSourceFile, cacheToUpdateSignature, cancellationToken, computeHash)) { - queue.push.apply(queue, getReferencedByPaths(state, currentPath)); + if (currentSourceFile && updateShapeSignature(state, programOfThisState, currentSourceFile, cacheToUpdateSignature, cancellationToken, computeHash)) { // TODO: GH#18217 + queue.push.apply(// TODO: GH#18217 + queue, getReferencedByPaths(state, currentPath)); } } } + // Return array of values that needs emit + // Return array of values that needs emit return ts.arrayFrom(ts.mapDefinedIterator(seenFileNamesMap.values(), function (value) { return value; })); } })(BuilderState = ts.BuilderState || (ts.BuilderState = {})); })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { function hasSameKeys(map1, map2) { + // Has same size and every key is present in both maps return map1 === map2 || map1 !== undefined && map2 !== undefined && map1.size === map2.size && !ts.forEachKey(map1, function (key) { return !map2.has(key); }); } + /** + * Create the state so that we can iterate on changedFiles/affected files + */ function createBuilderProgramState(newProgram, getCanonicalFileName, oldState) { var state = ts.BuilderState.create(newProgram, getCanonicalFileName, oldState); state.program = newProgram; @@ -69600,27 +83771,37 @@ var ts; var useOldState = ts.BuilderState.canReuseOldState(state.referencedMap, oldState); var canCopySemanticDiagnostics = useOldState && oldState.semanticDiagnosticsPerFile && !!state.semanticDiagnosticsPerFile; if (useOldState) { + // Verify the sanity of old state if (!oldState.currentChangedFilePath) { ts.Debug.assert(!oldState.affectedFiles && (!oldState.currentAffectedFilesSignatures || !oldState.currentAffectedFilesSignatures.size), "Cannot reuse if only few affected files of currentChangedFile were iterated"); } if (canCopySemanticDiagnostics) { ts.Debug.assert(!ts.forEachKey(oldState.changedFilesSet, function (path) { return oldState.semanticDiagnosticsPerFile.has(path); }), "Semantic diagnostics shouldnt be available for changed files"); } + // Copy old state's changed files set ts.copyEntries(oldState.changedFilesSet, state.changedFilesSet); } + // Update changed files and copy semantic diagnostics if we can var referencedMap = state.referencedMap; var oldReferencedMap = useOldState ? oldState.referencedMap : undefined; state.fileInfos.forEach(function (info, sourceFilePath) { var oldInfo; var newReferences; + // if not using old state, every file is changed if (!useOldState || + // File wasnt present in old state !(oldInfo = oldState.fileInfos.get(sourceFilePath)) || + // versions dont match oldInfo.version !== info.version || + // Referenced files changed !hasSameKeys(newReferences = referencedMap && referencedMap.get(sourceFilePath), oldReferencedMap && oldReferencedMap.get(sourceFilePath)) || + // Referenced file was deleted in the new program newReferences && ts.forEachKey(newReferences, function (path) { return !state.fileInfos.has(path) && oldState.fileInfos.has(path); })) { + // Register file as changed file and do not copy semantic diagnostics, since all changed files need to be re-evaluated state.changedFilesSet.set(sourceFilePath, true); } else if (canCopySemanticDiagnostics) { + // Unchanged file copy diagnostics var diagnostics = oldState.semanticDiagnosticsPerFile.get(sourceFilePath); if (diagnostics) { state.semanticDiagnosticsPerFile.set(sourceFilePath, diagnostics); @@ -69629,18 +83810,28 @@ var ts; }); return state; } + /** + * Verifies that source file is ok to be used in calls that arent handled by next + */ function assertSourceFileOkWithoutNextAffectedCall(state, sourceFile) { ts.Debug.assert(!sourceFile || !state.affectedFiles || state.affectedFiles[state.affectedFilesIndex - 1] !== sourceFile || !state.semanticDiagnosticsPerFile.has(sourceFile.path)); } + /** + * This function returns the next affected file to be processed. + * Note that until doneAffected is called it would keep reporting same result + * This is to allow the callers to be able to actually remove affected file only when the operation is complete + * eg. if during diagnostics check cancellation token ends up cancelling the request, the affected file should be retained + */ function getNextAffectedFile(state, cancellationToken, computeHash) { while (true) { var affectedFiles = state.affectedFiles; if (affectedFiles) { var seenAffectedFiles = state.seenAffectedFiles, semanticDiagnosticsPerFile = state.semanticDiagnosticsPerFile; - var affectedFilesIndex = state.affectedFilesIndex; + var affectedFilesIndex = state.affectedFilesIndex; // TODO: GH#18217 while (affectedFilesIndex < affectedFiles.length) { var affectedFile = affectedFiles[affectedFilesIndex]; if (!seenAffectedFiles.has(affectedFile.path)) { + // Set the next affected file as seen and remove the cached semantic diagnostics state.affectedFilesIndex = affectedFilesIndex; semanticDiagnosticsPerFile.delete(affectedFile.path); return affectedFile; @@ -69648,21 +83839,28 @@ var ts; seenAffectedFiles.set(affectedFile.path, true); affectedFilesIndex++; } + // Remove the changed file from the change set state.changedFilesSet.delete(state.currentChangedFilePath); state.currentChangedFilePath = undefined; + // Commit the changes in file signature ts.BuilderState.updateSignaturesFromCache(state, state.currentAffectedFilesSignatures); state.currentAffectedFilesSignatures.clear(); state.affectedFiles = undefined; } + // Get next changed file var nextKey = state.changedFilesSet.keys().next(); if (nextKey.done) { + // Done return undefined; } + // With --out or --outFile all outputs go into single file + // so operations are performed directly on program, return program var compilerOptions = state.program.getCompilerOptions(); if (compilerOptions.outFile || compilerOptions.out) { ts.Debug.assert(!state.semanticDiagnosticsPerFile); return state.program; } + // Get next batch of affected files state.currentAffectedFilesSignatures = state.currentAffectedFilesSignatures || ts.createMap(); state.affectedFiles = ts.BuilderState.getFilesAffectedBy(state, state.program, nextKey.value, cancellationToken, computeHash, state.currentAffectedFilesSignatures); state.currentChangedFilePath = nextKey.value; @@ -69671,6 +83869,10 @@ var ts; state.seenAffectedFiles = state.seenAffectedFiles || ts.createMap(); } } + /** + * This is called after completing operation on the next affected file. + * The operations here are postponed to ensure that cancellation during the iteration is handled correctly + */ function doneWithAffectedFile(state, affected) { if (affected === state.program) { state.changedFilesSet.clear(); @@ -69680,16 +83882,25 @@ var ts; state.affectedFilesIndex++; } } + /** + * Returns the result with affected file + */ function toAffectedFileResult(state, result, affected) { doneWithAffectedFile(state, affected); return { result: result, affected: affected }; } + /** + * Gets the semantic diagnostics either from cache if present, or otherwise from program and caches it + * Note that it is assumed that the when asked about semantic diagnostics, the file has been taken out of affected files/changed file set + */ function getSemanticDiagnosticsOfFile(state, sourceFile, cancellationToken) { var path = sourceFile.path; var cachedDiagnostics = state.semanticDiagnosticsPerFile.get(path); + // Report the semantic diagnostics from the cache if we already have those diagnostics present if (cachedDiagnostics) { return cachedDiagnostics; } + // Diagnostics werent cached, get them from program, and cache the result var diagnostics = state.program.getSemanticDiagnostics(sourceFile, cancellationToken); state.semanticDiagnosticsPerFile.set(path, diagnostics); return diagnostics; @@ -69726,16 +83937,24 @@ var ts; ts.getBuilderCreationParameters = getBuilderCreationParameters; function createBuilderProgram(kind, _a) { var newProgram = _a.newProgram, host = _a.host, oldProgram = _a.oldProgram, configFileParsingDiagnostics = _a.configFileParsingDiagnostics; + // Return same program if underlying program doesnt change var oldState = oldProgram && oldProgram.getState(); if (oldState && newProgram === oldState.program && configFileParsingDiagnostics === newProgram.getConfigFileParsingDiagnostics()) { - newProgram = undefined; + newProgram = undefined; // TODO: GH#18217 oldState = undefined; return oldProgram; } + /** + * Create the canonical file name for identity + */ var getCanonicalFileName = ts.createGetCanonicalFileName(host.useCaseSensitiveFileNames()); + /** + * Computing hash to for signature verification + */ var computeHash = host.createHash || ts.identity; var state = createBuilderProgramState(newProgram, getCanonicalFileName, oldState); - newProgram = undefined; + // To ensure that we arent storing any references to old program or new program without state + newProgram = undefined; // TODO: GH#18217 oldProgram = undefined; oldState = undefined; var result = { @@ -69763,17 +83982,38 @@ var ts; ts.notImplemented(); } return result; + /** + * Emits the next affected file's emit result (EmitResult and sourceFiles emitted) or returns undefined if iteration is complete + * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host + * in that order would be used to write the files + */ function emitNextAffectedFile(writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers) { var affected = getNextAffectedFile(state, cancellationToken, computeHash); if (!affected) { + // Done return undefined; } - return toAffectedFileResult(state, state.program.emit(affected === state.program ? undefined : affected, writeFile || host.writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers), affected); + return toAffectedFileResult(state, + // When whole program is affected, do emit only once (eg when --out or --outFile is specified) + // Otherwise just affected file + state.program.emit(affected === state.program ? undefined : affected, writeFile || host.writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers), affected); } + /** + * Emits the JavaScript and declaration files. + * When targetSource file is specified, emits the files corresponding to that source file, + * otherwise for the whole program. + * In case of EmitAndSemanticDiagnosticsBuilderProgram, when targetSourceFile is specified, + * it is assumed that that file is handled from affected file list. If targetSourceFile is not specified, + * it will only emit all the affected files instead of whole program + * + * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host + * in that order would be used to write the files + */ function emit(targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers) { if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { assertSourceFileOkWithoutNextAffectedCall(state, targetSourceFile); if (!targetSourceFile) { + // Emit and report any errors we ran into. var sourceMaps = []; var emitSkipped = false; var diagnostics = void 0; @@ -69795,33 +84035,52 @@ var ts; } return state.program.emit(targetSourceFile, writeFile || host.writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers); } + /** + * Return the semantic diagnostics for the next affected file or undefined if iteration is complete + * If provided ignoreSourceFile would be called before getting the diagnostics and would ignore the sourceFile if the returned value was true + */ function getSemanticDiagnosticsOfNextAffectedFile(cancellationToken, ignoreSourceFile) { while (true) { var affected = getNextAffectedFile(state, cancellationToken, computeHash); if (!affected) { + // Done return undefined; } else if (affected === state.program) { - return toAffectedFileResult(state, state.program.getSemanticDiagnostics(undefined, cancellationToken), affected); + // When whole program is affected, get all semantic diagnostics (eg when --out or --outFile is specified) + return toAffectedFileResult(state, state.program.getSemanticDiagnostics(/*targetSourceFile*/ undefined, cancellationToken), affected); } + // Get diagnostics for the affected file if its not ignored if (ignoreSourceFile && ignoreSourceFile(affected)) { + // Get next affected file doneWithAffectedFile(state, affected); continue; } return toAffectedFileResult(state, getSemanticDiagnosticsOfFile(state, affected, cancellationToken), affected); } } + /** + * Gets the semantic diagnostics from the program corresponding to this state of file (if provided) or whole program + * The semantic diagnostics are cached and managed here + * Note that it is assumed that when asked about semantic diagnostics through this API, + * the file has been taken out of affected files so it is safe to use cache or get from program and cache the diagnostics + * In case of SemanticDiagnosticsBuilderProgram if the source file is not provided, + * it will iterate through all the affected files, to ensure that cache stays valid and yet provide a way to get all semantic diagnostics + */ function getSemanticDiagnostics(sourceFile, cancellationToken) { assertSourceFileOkWithoutNextAffectedCall(state, sourceFile); var compilerOptions = state.program.getCompilerOptions(); if (compilerOptions.outFile || compilerOptions.out) { ts.Debug.assert(!state.semanticDiagnosticsPerFile); + // We dont need to cache the diagnostics just return them from program return state.program.getSemanticDiagnostics(sourceFile, cancellationToken); } if (sourceFile) { return getSemanticDiagnosticsOfFile(state, sourceFile, cancellationToken); } if (kind === BuilderProgramKind.SemanticDiagnosticsBuilderProgram) { + // When semantic builder asks for diagnostics of the whole program, + // ensure that all the affected files are handled var affected = void 0; while (affected = getNextAffectedFile(state, cancellationToken, computeHash)) { doneWithAffectedFile(state, affected); @@ -69849,6 +84108,7 @@ var ts; function createAbstractBuilder(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics) { var program = ts.getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics).newProgram; return { + // Only return program, all other methods are not implemented getProgram: function () { return program; }, getState: ts.notImplemented, getCompilerOptions: ts.notImplemented, @@ -69866,6 +84126,7 @@ var ts; } ts.createAbstractBuilder = createAbstractBuilder; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { ts.maxNumberOfFilesToIterateForInvalidation = 256; @@ -69874,23 +84135,35 @@ var ts; var filesWithInvalidatedResolutions; var filesWithInvalidatedNonRelativeUnresolvedImports; var allFilesHaveInvalidatedResolution = false; - var getCurrentDirectory = ts.memoize(function () { return resolutionHost.getCurrentDirectory(); }); + var getCurrentDirectory = ts.memoize(function () { return resolutionHost.getCurrentDirectory(); }); // TODO: GH#18217 var cachedDirectoryStructureHost = resolutionHost.getCachedDirectoryStructureHost(); + // The resolvedModuleNames and resolvedTypeReferenceDirectives are the cache of resolutions per file. + // The key in the map is source file's path. + // The values are Map of resolutions with key being name lookedup. var resolvedModuleNames = ts.createMap(); var perDirectoryResolvedModuleNames = ts.createMap(); var nonRelaticeModuleNameCache = ts.createMap(); var moduleResolutionCache = ts.createModuleResolutionCacheWithMaps(perDirectoryResolvedModuleNames, nonRelaticeModuleNameCache, getCurrentDirectory(), resolutionHost.getCanonicalFileName); var resolvedTypeReferenceDirectives = ts.createMap(); var perDirectoryResolvedTypeReferenceDirectives = ts.createMap(); - var failedLookupDefaultExtensions = [".ts", ".tsx", ".js", ".jsx", ".json"]; + /** + * These are the extensions that failed lookup files will have by default, + * any other extension of failed lookup will be store that path in custom failed lookup path + * This helps in not having to comb through all resolutions when files are added/removed + * Note that .d.ts file also has .d.ts extension hence will be part of default extensions + */ + var failedLookupDefaultExtensions = [".ts" /* Ts */, ".tsx" /* Tsx */, ".js" /* Js */, ".jsx" /* Jsx */, ".json" /* Json */]; var customFailedLookupPaths = ts.createMap(); var directoryWatchesOfFailedLookups = ts.createMap(); var rootDir = rootDirForResolution && ts.removeTrailingDirectorySeparator(ts.getNormalizedAbsolutePath(rootDirForResolution, getCurrentDirectory())); - var rootPath = (rootDir && resolutionHost.toPath(rootDir)); + var rootPath = (rootDir && resolutionHost.toPath(rootDir)); // TODO: GH#18217 + // TypeRoot watches for the types that get added as part of getAutomaticTypeDirectiveNames var typeRootsWatches = ts.createMap(); return { startRecordingFilesWithChangedResolutions: startRecordingFilesWithChangedResolutions, finishRecordingFilesWithChangedResolutions: finishRecordingFilesWithChangedResolutions, + // perDirectoryResolvedModuleNames and perDirectoryResolvedTypeReferenceDirectives could be non empty if there was exception during program update + // (between startCachingPerDirectoryResolution and finishCachingPerDirectoryResolution) startCachingPerDirectoryResolution: clearPerDirectoryResolutions, finishCachingPerDirectoryResolution: finishCachingPerDirectoryResolution, resolveModuleNames: resolveModuleNames, @@ -69923,6 +84196,8 @@ var ts; resolvedModuleNames.clear(); resolvedTypeReferenceDirectives.clear(); allFilesHaveInvalidatedResolution = false; + // perDirectoryResolvedModuleNames and perDirectoryResolvedTypeReferenceDirectives could be non empty if there was exception during program update + // (between startCachingPerDirectoryResolution and finishCachingPerDirectoryResolution) clearPerDirectoryResolutions(); } function startRecordingFilesWithChangedResolutions() { @@ -69937,11 +84212,13 @@ var ts; if (!filesWithInvalidatedNonRelativeUnresolvedImports) { return false; } + // Invalidated if file has unresolved imports var value = filesWithInvalidatedNonRelativeUnresolvedImports.get(path); return !!value && !!value.length; } function createHasInvalidatedResolution(forceAllFilesAsInvalidated) { if (allFilesHaveInvalidatedResolution || forceAllFilesAsInvalidated) { + // Any file asked would have invalidated resolution filesWithInvalidatedResolutions = undefined; return ts.returnTrue; } @@ -69968,16 +84245,21 @@ var ts; } function resolveModuleName(moduleName, containingFile, compilerOptions, host) { var primaryResult = ts.resolveModuleName(moduleName, containingFile, compilerOptions, host, moduleResolutionCache); + // return result immediately only if global cache support is not enabled or if it is .ts, .tsx or .d.ts if (!resolutionHost.getGlobalCache) { return primaryResult; } + // otherwise try to load typings from @types var globalCache = resolutionHost.getGlobalCache(); if (globalCache !== undefined && !ts.isExternalModuleNameRelative(moduleName) && !(primaryResult.resolvedModule && ts.extensionIsTypeScript(primaryResult.resolvedModule.extension))) { + // create different collection of failed lookup locations for second pass + // if it will fail and we've already found something during the first pass - we don't want to pollute its results var _a = ts.loadModuleFromGlobalCache(moduleName, resolutionHost.projectName, compilerOptions, host, globalCache), resolvedModule = _a.resolvedModule, failedLookupLocations = _a.failedLookupLocations; if (resolvedModule) { return { resolvedModule: resolvedModule, failedLookupLocations: ts.addRange(primaryResult.failedLookupLocations, failedLookupLocations) }; } } + // Default return the result from the first pass return primaryResult; } function resolveNamesWithLocalCache(names, containingFile, cache, perDirectoryCache, loader, getResolutionWithResolvedFileName, reusedNames, logChanges) { @@ -69996,8 +84278,10 @@ var ts; for (var _i = 0, names_2 = names; _i < names_2.length; _i++) { var name = names_2[_i]; var resolution = resolutionsInFile.get(name); + // Resolution is valid if it is present and not invalidated if (!seenNamesInFile.has(name) && allFilesHaveInvalidatedResolution || !resolution || resolution.isInvalidated || + // If the name is unresolved import that was invalidated, recalculate (hasInvalidatedNonRelativeUnresolvedImport && !ts.isExternalModuleNameRelative(name) && !getResolutionWithResolvedFileName(resolution))) { var existingResolution = resolution; var resolutionInDirectory = perDirectoryResolution.get(name); @@ -70015,13 +84299,15 @@ var ts; } if (logChanges && filesWithChangedSetOfUnresolvedImports && !resolutionIsEqualTo(existingResolution, resolution)) { filesWithChangedSetOfUnresolvedImports.push(path); + // reset log changes to avoid recording the same file multiple times logChanges = false; } } ts.Debug.assert(resolution !== undefined && !resolution.isInvalidated); seenNamesInFile.set(name, true); - resolvedModules.push(getResolutionWithResolvedFileName(resolution)); + resolvedModules.push(getResolutionWithResolvedFileName(resolution)); // TODO: GH#18217 } + // Stop watching and remove the unused name resolutionsInFile.forEach(function (resolution, name) { if (!seenNamesInFile.has(name) && !ts.contains(reusedNames, name)) { stopWatchFailedLookupLocationOfResolution(resolution); @@ -70048,7 +84334,8 @@ var ts; } } function resolveTypeReferenceDirectives(typeDirectiveNames, containingFile) { - return resolveNamesWithLocalCache(typeDirectiveNames, containingFile, resolvedTypeReferenceDirectives, perDirectoryResolvedTypeReferenceDirectives, ts.resolveTypeReferenceDirective, getResolvedTypeReferenceDirective, undefined, false); + return resolveNamesWithLocalCache(typeDirectiveNames, containingFile, resolvedTypeReferenceDirectives, perDirectoryResolvedTypeReferenceDirectives, ts.resolveTypeReferenceDirective, getResolvedTypeReferenceDirective, + /*reusedNames*/ undefined, /*logChanges*/ false); } function resolveModuleNames(moduleNames, containingFile, reusedNames) { return resolveNamesWithLocalCache(moduleNames, containingFile, resolvedModuleNames, perDirectoryResolvedModuleNames, resolveModuleName, getResolvedModule, reusedNames, logChangesWhenResolvingModule); @@ -70063,22 +84350,32 @@ var ts; function isNodeModulesAtTypesDirectory(dirPath) { return ts.endsWith(dirPath, "/node_modules/@types"); } + /** + * Filter out paths like + * "/", "/user", "/user/username", "/user/username/folderAtRoot", + * "c:/", "c:/users", "c:/users/username", "c:/users/username/folderAtRoot", "c:/folderAtRoot" + * @param dirPath + */ function canWatchDirectory(dirPath) { var rootLength = ts.getRootLength(dirPath); if (dirPath.length === rootLength) { + // Ignore "/", "c:/" return false; } var nextDirectorySeparator = dirPath.indexOf(ts.directorySeparator, rootLength); if (nextDirectorySeparator === -1) { + // ignore "/user", "c:/users" or "c:/folderAtRoot" return false; } - if (dirPath.charCodeAt(0) !== 47 && + if (dirPath.charCodeAt(0) !== 47 /* slash */ && dirPath.substr(rootLength, nextDirectorySeparator).search(/users/i) === -1) { + // Paths like c:/folderAtRoot/subFolder are allowed return true; } for (var searchIndex = nextDirectorySeparator + 1, searchLevels = 2; searchLevels > 0; searchLevels--) { searchIndex = dirPath.indexOf(ts.directorySeparator, searchIndex) + 1; if (searchIndex === 0) { + // Folder isnt at expected minimun levels return false; } } @@ -70092,19 +84389,23 @@ var ts; } function getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath) { if (isInDirectoryPath(rootPath, failedLookupLocationPath)) { - return { dir: rootDir, dirPath: rootPath }; + // Always watch root directory recursively + return { dir: rootDir, dirPath: rootPath }; // TODO: GH#18217 } return getDirectoryToWatchFromFailedLookupLocationDirectory(ts.getDirectoryPath(ts.getNormalizedAbsolutePath(failedLookupLocation, getCurrentDirectory())), ts.getDirectoryPath(failedLookupLocationPath)); } function getDirectoryToWatchFromFailedLookupLocationDirectory(dir, dirPath) { + // If directory path contains node module, get the most parent node_modules directory for watching while (ts.stringContains(dirPath, "/node_modules/")) { dir = ts.getDirectoryPath(dir); dirPath = ts.getDirectoryPath(dirPath); } + // If the directory is node_modules use it to watch, always watch it recursively if (isNodeModulesDirectory(dirPath)) { return filterFSRootDirectoriesToWatch({ dir: dir, dirPath: dirPath }, ts.getDirectoryPath(dirPath)); } var nonRecursive = true; + // Use some ancestor of the root directory var subDirectoryPath, subDirectory; if (rootPath !== undefined) { while (!isInDirectoryPath(dirPath, rootPath)) { @@ -70125,6 +84426,7 @@ var ts; return ts.fileExtensionIsOneOf(path, failedLookupDefaultExtensions); } function watchFailedLookupLocationOfResolution(resolution) { + // No need to set the resolution refCount if (!resolution.failedLookupLocations || !resolution.failedLookupLocations.length) { return; } @@ -70140,6 +84442,8 @@ var ts; var failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation); var _a = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath), dir = _a.dir, dirPath = _a.dirPath, nonRecursive = _a.nonRecursive, ignore = _a.ignore; if (!ignore) { + // If the failed lookup location path is not one of the supported extensions, + // store it in the custom path if (!isPathWithDefaultFailedLookupExtension(failedLookupLocationPath)) { var refCount = customFailedLookupPaths.get(failedLookupLocationPath) || 0; customFailedLookupPaths.set(failedLookupLocationPath, refCount + 1); @@ -70153,7 +84457,8 @@ var ts; } } if (setAtRoot) { - setDirectoryWatcher(rootDir, rootPath); + // This is always recursive + setDirectoryWatcher(rootDir, rootPath); // TODO: GH#18217 } } function setDirectoryWatcher(dir, dirPath, nonRecursive) { @@ -70205,20 +84510,23 @@ var ts; } function removeDirectoryWatcher(dirPath) { var dirWatcher = directoryWatchesOfFailedLookups.get(dirPath); + // Do not close the watcher yet since it might be needed by other failed lookup locations. dirWatcher.refCount--; } function createDirectoryWatcher(directory, dirPath, nonRecursive) { return resolutionHost.watchDirectoryOfFailedLookupLocation(directory, function (fileOrDirectory) { var fileOrDirectoryPath = resolutionHost.toPath(fileOrDirectory); if (cachedDirectoryStructureHost) { + // Since the file existence changed, update the sourceFiles cache cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); } if (!allFilesHaveInvalidatedResolution && invalidateResolutionOfFailedLookupLocation(fileOrDirectoryPath, dirPath === fileOrDirectoryPath)) { resolutionHost.onInvalidatedResolution(); } - }, nonRecursive ? 0 : 1); + }, nonRecursive ? 0 /* None */ : 1 /* Recursive */); } function removeResolutionsOfFileFromCache(cache, filePath) { + // Deleted file, stop watching failed lookups for all the resolutions in the file var resolutions = cache.get(filePath); if (resolutions) { resolutions.forEach(stopWatchFailedLookupLocationOfResolution); @@ -70244,6 +84552,7 @@ var ts; } seenInDir.set(name, true); if (!resolution.isInvalidated && isInvalidatedResolution(resolution, getResolutionWithResolvedFileName)) { + // Mark the file as needing re-evaluation of module resolution instead of using it blindly. resolution.isInvalidated = true; (filesWithInvalidatedResolutions || (filesWithInvalidatedResolutions = ts.createMap())).set(containingFilePath, true); } @@ -70255,6 +84564,8 @@ var ts; return resolvedModuleNames.size > maxSize || resolvedTypeReferenceDirectives.size > maxSize; } function invalidateResolutions(isInvalidatedResolution) { + // If more than maxNumberOfFilesToIterateForInvalidation present, + // just invalidated all files and recalculate the resolutions for files instead if (hasReachedResolutionIterationLimit()) { allFilesHaveInvalidatedResolution = true; return; @@ -70264,9 +84575,11 @@ var ts; } function invalidateResolutionOfFile(filePath) { removeResolutionsOfFile(filePath); - invalidateResolutions(function (resolution, getResolutionWithResolvedFileName) { + invalidateResolutions( + // Resolution is invalidated if the resulting file name is same as the deleted file path + function (resolution, getResolutionWithResolvedFileName) { var result = getResolutionWithResolvedFileName(resolution); - return !!result && resolutionHost.toPath(result.resolvedFileName) === filePath; + return !!result && resolutionHost.toPath(result.resolvedFileName) === filePath; // TODO: GH#18217 }); } function setFilesWithInvalidatedNonRelativeUnresolvedImports(filesMap) { @@ -70276,12 +84589,17 @@ var ts; function invalidateResolutionOfFailedLookupLocation(fileOrDirectoryPath, isCreatingWatchedDirectory) { var isChangedFailedLookupLocation; if (isCreatingWatchedDirectory) { + // Watching directory is created + // Invalidate any resolution has failed lookup in this directory isChangedFailedLookupLocation = function (location) { return isInDirectoryPath(fileOrDirectoryPath, resolutionHost.toPath(location)); }; } else { + // Some file or directory in the watching directory is created + // Return early if it does not have any of the watching extension or not the custom failed lookup path var dirOfFileOrDirectory = ts.getDirectoryPath(fileOrDirectoryPath); if (isNodeModulesAtTypesDirectory(fileOrDirectoryPath) || isNodeModulesDirectory(fileOrDirectoryPath) || isNodeModulesAtTypesDirectory(dirOfFileOrDirectory) || isNodeModulesDirectory(dirOfFileOrDirectory)) { + // Invalidate any resolution from this directory isChangedFailedLookupLocation = function (location) { var locationPath = resolutionHost.toPath(location); return locationPath === fileOrDirectoryPath || ts.startsWith(resolutionHost.toPath(location), fileOrDirectoryPath); @@ -70291,15 +84609,19 @@ var ts; if (!isPathWithDefaultFailedLookupExtension(fileOrDirectoryPath) && !customFailedLookupPaths.has(fileOrDirectoryPath)) { return false; } + // Ignore emits from the program if (ts.isEmittedFileOfProgram(resolutionHost.getCurrentProgram(), fileOrDirectoryPath)) { return false; } + // Resolution need to be invalidated if failed lookup location is same as the file or directory getting created isChangedFailedLookupLocation = function (location) { return resolutionHost.toPath(location) === fileOrDirectoryPath; }; } } var hasChangedFailedLookupLocation = function (resolution) { return ts.some(resolution.failedLookupLocations, isChangedFailedLookupLocation); }; var invalidatedFilesCount = filesWithInvalidatedResolutions && filesWithInvalidatedResolutions.size; - invalidateResolutions(hasChangedFailedLookupLocation); + invalidateResolutions( + // Resolution is invalidated if the resulting file name is same as the deleted file path + hasChangedFailedLookupLocation); return allFilesHaveInvalidatedResolution || filesWithInvalidatedResolutions && filesWithInvalidatedResolutions.size !== invalidatedFilesCount; } function closeTypeRootsWatch() { @@ -70316,24 +84638,39 @@ var ts; return !ignore && directoryWatchesOfFailedLookups.has(dirPath) ? dirPath : undefined; } function createTypeRootsWatch(typeRootPath, typeRoot) { + // Create new watch and recursive info return resolutionHost.watchTypeRootsDirectory(typeRoot, function (fileOrDirectory) { var fileOrDirectoryPath = resolutionHost.toPath(fileOrDirectory); if (cachedDirectoryStructureHost) { + // Since the file existence changed, update the sourceFiles cache cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); } + // For now just recompile + // We could potentially store more data here about whether it was/would be really be used or not + // and with that determine to trigger compilation but for now this is enough resolutionHost.onChangedAutomaticTypeDirectiveNames(); + // Since directory watchers invoked are flaky, the failed lookup location events might not be triggered + // So handle to failed lookup locations here as well to ensure we are invalidating resolutions var dirPath = getDirectoryToWatchFailedLookupLocationFromTypeRoot(typeRoot, typeRootPath); if (dirPath && invalidateResolutionOfFailedLookupLocation(fileOrDirectoryPath, dirPath === fileOrDirectoryPath)) { resolutionHost.onInvalidatedResolution(); } - }, 1); + }, 1 /* Recursive */); } + /** + * Watches the types that would get added as part of getAutomaticTypeDirectiveNames + * To be called when compiler options change + */ function updateTypeRootsWatch() { var options = resolutionHost.getCompilationSettings(); if (options.types) { + // No need to do any watch since resolution cache is going to handle the failed lookups + // for the types added by this closeTypeRootsWatch(); return; } + // we need to assume the directories exist to ensure that we can get all the type root directories that get included + // But filter directories that are at root level to say directory doesnt exist, so that we arent watching them var typeRoots = ts.getEffectiveTypeRoots(options, { directoryExists: directoryExistsForTypeRootWatch, getCurrentDirectory: getCurrentDirectory }); if (typeRoots) { ts.mutateMap(typeRootsWatches, ts.arrayToMap(typeRoots, function (tr) { return resolutionHost.toPath(tr); }), { @@ -70345,6 +84682,11 @@ var ts; closeTypeRootsWatch(); } } + /** + * Use this function to return if directory exists to get type roots to watch + * If we return directory exists then only the paths will be added to type roots + * Hence return true for all directories except root directories which are filtered from watching + */ function directoryExistsForTypeRootWatch(nodeTypesDirectory) { var dir = ts.getDirectoryPath(ts.getDirectoryPath(nodeTypesDirectory)); var dirPath = resolutionHost.toPath(dir); @@ -70353,10 +84695,13 @@ var ts; } ts.createResolutionCache = createResolutionCache; })(ts || (ts = {})); +// Used by importFixes to synthesize import module specifiers. +/* @internal */ var ts; (function (ts) { var moduleSpecifiers; (function (moduleSpecifiers) { + // Note: fromSourceFile is just for usesJsExtensionOnImports function getModuleSpecifier(compilerOptions, fromSourceFile, fromSourceFileName, toFileName, host, preferences) { if (preferences === void 0) { preferences = {}; } var info = getInfo(compilerOptions, fromSourceFile, fromSourceFileName, host); @@ -70364,6 +84709,7 @@ var ts; ts.first(getLocalModuleSpecifiers(toFileName, info, compilerOptions, preferences)); } moduleSpecifiers.getModuleSpecifier = getModuleSpecifier; + // For each symlink/original for a module, returns a list of ways to import that file. function getModuleSpecifiers(moduleSymbol, compilerOptions, importingSourceFile, host, files, preferences) { var ambient = tryGetModuleNameFromAmbientModule(moduleSymbol); if (ambient) @@ -70379,6 +84725,7 @@ var ts; }); } moduleSpecifiers.getModuleSpecifiers = getModuleSpecifiers; + // importingSourceFileName is separate because getEditsForFileRename may need to specify an updated path function getInfo(compilerOptions, importingSourceFile, importingSourceFileName, host) { var moduleResolutionKind = ts.getEmitModuleResolutionKind(compilerOptions); var addJsExtension = usesJsExtensionOnImports(importingSourceFile); @@ -70418,6 +84765,33 @@ var ts; if (isPathRelativeToParent(relativeToBaseUrl)) { return [relativePath]; } + /* + Prefer a relative import over a baseUrl import if it doesn't traverse up to baseUrl. + + Suppose we have: + baseUrl = /base + sourceDirectory = /base/a/b + moduleFileName = /base/foo/bar + Then: + relativePath = ../../foo/bar + getRelativePathNParents(relativePath) = 2 + pathFromSourceToBaseUrl = ../../ + getRelativePathNParents(pathFromSourceToBaseUrl) = 2 + 2 < 2 = false + In this case we should prefer using the baseUrl path "/a/b" instead of the relative path "../../foo/bar". + + Suppose we have: + baseUrl = /base + sourceDirectory = /base/foo/a + moduleFileName = /base/foo/bar + Then: + relativePath = ../a + getRelativePathNParents(relativePath) = 1 + pathFromSourceToBaseUrl = ../../ + getRelativePathNParents(pathFromSourceToBaseUrl) = 2 + 1 < 2 = true + In this case we should prefer using the relative path "../a" instead of the baseUrl path "foo/a". + */ var pathFromSourceToBaseUrl = ts.ensurePathIsNonModuleName(ts.getRelativePathFromDirectory(sourceDirectory, baseUrl, getCanonicalFileName)); var relativeFirst = getRelativePathNParents(relativePath) < getRelativePathNParents(pathFromSourceToBaseUrl); return relativeFirst ? [relativePath, importRelativeToBaseUrl] : [importRelativeToBaseUrl, relativePath]; @@ -70426,7 +84800,7 @@ var ts; var imports = _a.imports; return ts.firstDefined(imports, function (_a) { var text = _a.text; - return ts.pathIsRelative(text) ? ts.fileExtensionIs(text, ".js") : undefined; + return ts.pathIsRelative(text) ? ts.fileExtensionIs(text, ".js" /* Js */) : undefined; }) || false; } function discoverProbableSymlinks(files, getCanonicalFileName, host) { @@ -70459,7 +84833,7 @@ var ts; for (var _i = 0, paths_2 = paths; _i < paths_2.length; _i++) { var path = paths_2[_i]; var resolved = links.get(path); - if (compareStrings(target.slice(0, resolved.length + 1), resolved + "/") === 0) { + if (compareStrings(target.slice(0, resolved.length + 1), resolved + "/") === 0 /* EqualTo */) { var relative = ts.getRelativePathFromDirectory(resolved, target, getCanonicalFileName); var option = ts.resolvePath(path, relative); if (!host.fileExists || host.fileExists(option)) { @@ -70470,11 +84844,15 @@ var ts; } } if (options) { - options.push(target); + options.push(target); // Since these are speculative, we also include the original resolved name as a possibility return options; } return [target]; } + /** + * Looks for a existing imports that use symlinks to this module. + * Only if no symlink is available, the real path will be used. + */ function getAllModulePaths(files, _a, getCanonicalFileName, host) { var fileName = _a.fileName; var symlinks = ts.mapDefined(files, function (sf) { @@ -70537,28 +84915,36 @@ var ts; function tryGetModuleNameFromTypeRoots(options, host, getCanonicalFileName, moduleFileName, addJsExtension) { var roots = ts.getEffectiveTypeRoots(options, host); return ts.firstDefined(roots, function (unNormalizedTypeRoot) { - var typeRoot = ts.toPath(unNormalizedTypeRoot, undefined, getCanonicalFileName); + var typeRoot = ts.toPath(unNormalizedTypeRoot, /*basePath*/ undefined, getCanonicalFileName); if (ts.startsWith(moduleFileName, typeRoot)) { + // For a type definition, we can strip `/index` even with classic resolution. return removeExtensionAndIndexPostFix(moduleFileName.substring(typeRoot.length + 1), ts.ModuleResolutionKind.NodeJs, addJsExtension); } }); } function tryGetModuleNameAsNodeModule(options, moduleFileName, host, getCanonicalFileName, sourceDirectory) { if (ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.NodeJs) { + // nothing to do here return undefined; } var parts = getNodeModulePathParts(moduleFileName); if (!parts) { return undefined; } + // Simplify the full file path to something that can be resolved by Node. + // If the module could be imported by a directory name, use that directory's name var moduleSpecifier = getDirectoryOrExtensionlessFileName(moduleFileName); + // Get a path that's relative to node_modules or the importing file's path + // if node_modules folder is in this folder or any of its parent folders, no need to keep it. if (!ts.startsWith(sourceDirectory, moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex))) return undefined; + // If the module was found in @types, get the actual Node package name return ts.getPackageNameFromAtTypesDirectory(moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1)); function getDirectoryOrExtensionlessFileName(path) { + // If the file is the main module, it can be imported by the package name var packageRootPath = path.substring(0, parts.packageRootIndex); var packageJsonPath = ts.combinePaths(packageRootPath, "package.json"); - if (host.fileExists(packageJsonPath)) { + if (host.fileExists(packageJsonPath)) { // TODO: GH#18217 var packageJsonContent = JSON.parse(host.readFile(packageJsonPath)); if (packageJsonContent) { var mainFileRelative = packageJsonContent.typings || packageJsonContent.types || packageJsonContent.main; @@ -70570,7 +84956,10 @@ var ts; } } } + // We still have a file name - remove the extension var fullModulePathWithoutExtension = ts.removeFileExtension(path); + // If the file is /index, it can be imported by its directory name + // IFF there is not _also_ a file by the same name if (getCanonicalFileName(fullModulePathWithoutExtension.substring(parts.fileNameIndex)) === "/index" && !tryGetAnyFileFromPath(host, fullModulePathWithoutExtension.substring(0, parts.fileNameIndex))) { return fullModulePathWithoutExtension.substring(0, parts.fileNameIndex); } @@ -70578,16 +84967,20 @@ var ts; } } function tryGetAnyFileFromPath(host, path) { - var extensions = ts.getSupportedExtensions({ allowJs: true }, [{ extension: "node", isMixedContent: false }, { extension: "json", isMixedContent: false, scriptKind: 6 }]); + // We check all js, `node` and `json` extensions in addition to TS, since node module resolution would also choose those over the directory + var extensions = ts.getSupportedExtensions({ allowJs: true }, [{ extension: "node", isMixedContent: false }, { extension: "json", isMixedContent: false, scriptKind: 6 /* JSON */ }]); for (var _i = 0, extensions_3 = extensions; _i < extensions_3.length; _i++) { var e = extensions_3[_i]; var fullPath = path + e; - if (host.fileExists(fullPath)) { + if (host.fileExists(fullPath)) { // TODO: GH#18217 return fullPath; } } } function getNodeModulePathParts(fullPath) { + // If fullPath can't be valid module file within node_modules, returns undefined. + // Example of expected pattern: /base/path/node_modules/[@scope/otherpackage/@otherscope/node_modules/]package/[subdirectory/]file.js + // Returns indices: ^ ^ ^ ^ var topLevelNodeModulesIndex = 0; var topLevelPackageNameIndex = 0; var packageRootIndex = 0; @@ -70601,44 +84994,44 @@ var ts; })(States || (States = {})); var partStart = 0; var partEnd = 0; - var state = 0; + var state = 0 /* BeforeNodeModules */; while (partEnd >= 0) { partStart = partEnd; partEnd = fullPath.indexOf("/", partStart + 1); switch (state) { - case 0: + case 0 /* BeforeNodeModules */: if (fullPath.indexOf("/node_modules/", partStart) === partStart) { topLevelNodeModulesIndex = partStart; topLevelPackageNameIndex = partEnd; - state = 1; + state = 1 /* NodeModules */; } break; - case 1: - case 2: - if (state === 1 && fullPath.charAt(partStart + 1) === "@") { - state = 2; + case 1 /* NodeModules */: + case 2 /* Scope */: + if (state === 1 /* NodeModules */ && fullPath.charAt(partStart + 1) === "@") { + state = 2 /* Scope */; } else { packageRootIndex = partEnd; - state = 3; + state = 3 /* PackageContent */; } break; - case 3: + case 3 /* PackageContent */: if (fullPath.indexOf("/node_modules/", partStart) === partStart) { - state = 1; + state = 1 /* NodeModules */; } else { - state = 3; + state = 3 /* PackageContent */; } break; } } fileNameIndex = partStart; - return state > 1 ? { topLevelNodeModulesIndex: topLevelNodeModulesIndex, topLevelPackageNameIndex: topLevelPackageNameIndex, packageRootIndex: packageRootIndex, fileNameIndex: fileNameIndex } : undefined; + return state > 1 /* NodeModules */ ? { topLevelNodeModulesIndex: topLevelNodeModulesIndex, topLevelPackageNameIndex: topLevelPackageNameIndex, packageRootIndex: packageRootIndex, fileNameIndex: fileNameIndex } : undefined; } function getPathRelativeToRootDirs(path, rootDirs, getCanonicalFileName) { return ts.firstDefined(rootDirs, function (rootDir) { - var relativePath = getRelativePathIfInDirectory(path, rootDir, getCanonicalFileName); + var relativePath = getRelativePathIfInDirectory(path, rootDir, getCanonicalFileName); // TODO: GH#18217 return isPathRelativeToParent(relativePath) ? undefined : relativePath; }); } @@ -70651,7 +85044,7 @@ var ts; : noExtension; } function getRelativePathIfInDirectory(path, directoryPath, getCanonicalFileName) { - var relativePath = ts.getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, false); + var relativePath = ts.getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); return ts.isRootedDiskPath(relativePath) ? undefined : relativePath; } function isPathRelativeToParent(path) { @@ -70659,13 +85052,17 @@ var ts; } })(moduleSpecifiers = ts.moduleSpecifiers || (ts.moduleSpecifiers = {})); })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { var sysFormatDiagnosticsHost = ts.sys ? { getCurrentDirectory: function () { return ts.sys.getCurrentDirectory(); }, getNewLine: function () { return ts.sys.newLine; }, getCanonicalFileName: ts.createGetCanonicalFileName(ts.sys.useCaseSensitiveFileNames) - } : undefined; + } : undefined; // TODO: GH#18217 + /** + * Create a function that reports error by writing to the system and handles the formating of the diagnostic + */ function createDiagnosticReporter(system, pretty) { var host = system === ts.sys ? sysFormatDiagnosticsHost : { getCurrentDirectory: function () { return system.getCurrentDirectory(); }, @@ -70679,14 +85076,18 @@ var ts; return function (diagnostic) { diagnostics[0] = diagnostic; system.write(ts.formatDiagnosticsWithColorAndContext(diagnostics, host) + host.getNewLine()); - diagnostics[0] = undefined; + diagnostics[0] = undefined; // TODO: GH#18217 }; } ts.createDiagnosticReporter = createDiagnosticReporter; + /** @internal */ ts.nonClearingMessageCodes = [ ts.Diagnostics.Found_1_error_Watching_for_file_changes.code, ts.Diagnostics.Found_0_errors_Watching_for_file_changes.code ]; + /** + * @returns Whether the screen was cleared. + */ function clearScreenIfNotWatchingForFileChanges(system, diagnostic, options) { if (system.clearScreen && !options.preserveWatchOutput && @@ -70698,6 +85099,7 @@ var ts; } return false; } + /** @internal */ ts.screenStartingMessageCodes = [ ts.Diagnostics.Starting_compilation_in_watch_mode.code, ts.Diagnostics.File_change_detected_Starting_incremental_compilation.code, @@ -70707,6 +85109,9 @@ var ts; ? newLine + newLine : newLine; } + /** + * Create a function that reports watch status by writing to the system and handles the formating of the diagnostic + */ function createWatchStatusReporter(system, pretty) { return pretty ? function (diagnostic, newLine, options) { @@ -70726,19 +85131,26 @@ var ts; }; } ts.createWatchStatusReporter = createWatchStatusReporter; + /** Parses config file using System interface */ function parseConfigFileWithSystem(configFileName, optionsToExtend, system, reportDiagnostic) { var host = system; host.onUnRecoverableConfigFileDiagnostic = function (diagnostic) { return reportUnrecoverableDiagnostic(ts.sys, reportDiagnostic, diagnostic); }; var result = ts.getParsedCommandLineOfConfigFile(configFileName, optionsToExtend, host); - host.onUnRecoverableConfigFileDiagnostic = undefined; + host.onUnRecoverableConfigFileDiagnostic = undefined; // TODO: GH#18217 return result; } ts.parseConfigFileWithSystem = parseConfigFileWithSystem; + /** + * Helper that emit files, report diagnostics and lists emitted and/or source files depending on compiler options + */ function emitFilesAndReportErrors(program, reportDiagnostic, writeFileName, reportSummary) { + // First get and report any syntactic errors. var diagnostics = program.getConfigFileParsingDiagnostics().slice(); var configFileParsingDiagnosticsLength = diagnostics.length; ts.addRange(diagnostics, program.getSyntacticDiagnostics()); var reportSemanticDiagnostics = false; + // If we didn't have any syntactic errors, then also try getting the global and + // semantic errors. if (diagnostics.length === configFileParsingDiagnosticsLength) { ts.addRange(diagnostics, program.getOptionsDiagnostics()); ts.addRange(diagnostics, program.getGlobalDiagnostics()); @@ -70746,6 +85158,7 @@ var ts; reportSemanticDiagnostics = true; } } + // Emit and report any errors we ran into. var _a = program.emit(), emittedFiles = _a.emittedFiles, emitSkipped = _a.emitSkipped, emitDiagnostics = _a.diagnostics; ts.addRange(diagnostics, emitDiagnostics); if (reportSemanticDiagnostics) { @@ -70768,15 +85181,21 @@ var ts; reportSummary(diagnostics.filter(function (diagnostic) { return diagnostic.category === ts.DiagnosticCategory.Error; }).length); } if (emitSkipped && diagnostics.length > 0) { + // If the emitter didn't emit anything, then pass that value along. return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped; } else if (diagnostics.length > 0) { + // The emitter emitted something, inform the caller if that happened in the presence + // of diagnostics or not. return ts.ExitStatus.DiagnosticsPresent_OutputsGenerated; } return ts.ExitStatus.Success; } ts.emitFilesAndReportErrors = emitFilesAndReportErrors; var noopFileWatcher = { close: ts.noop }; + /** + * Creates the watch compiler host that can be extended with config file or root file names and options host + */ function createWatchCompilerHost(system, createProgram, reportDiagnostic, reportWatchStatus) { if (system === void 0) { system = ts.sys; } if (!createProgram) { @@ -70836,10 +85255,16 @@ var ts; emitFilesAndReportErrors(builderProgram, reportDiagnostic, writeFileName, reportSummary); } } + /** + * Report error and exit + */ function reportUnrecoverableDiagnostic(system, reportDiagnostic, diagnostic) { reportDiagnostic(diagnostic); system.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); } + /** + * Creates the watch compiler host from system for config file in watch mode + */ function createWatchCompilerHostOfConfigFile(configFileName, optionsToExtend, system, createProgram, reportDiagnostic, reportWatchStatus) { var diagnosticReporter = reportDiagnostic || createDiagnosticReporter(system); var host = createWatchCompilerHost(system, createProgram, diagnosticReporter, reportWatchStatus); @@ -70849,6 +85274,9 @@ var ts; return host; } ts.createWatchCompilerHostOfConfigFile = createWatchCompilerHostOfConfigFile; + /** + * Creates the watch compiler host from system for compiling root files and options in watch mode + */ function createWatchCompilerHostOfFilesAndCompilerOptions(rootFiles, options, system, createProgram, reportDiagnostic, reportWatchStatus) { var host = createWatchCompilerHost(system, createProgram, reportDiagnostic || createDiagnosticReporter(system), reportWatchStatus); host.rootFiles = rootFiles; @@ -70860,7 +85288,7 @@ var ts; (function (ts) { function createWatchCompilerHost(rootFilesOrConfigFileName, options, system, createProgram, reportDiagnostic, reportWatchStatus) { if (ts.isArray(rootFilesOrConfigFileName)) { - return ts.createWatchCompilerHostOfFilesAndCompilerOptions(rootFilesOrConfigFileName, options, system, createProgram, reportDiagnostic, reportWatchStatus); + return ts.createWatchCompilerHostOfFilesAndCompilerOptions(rootFilesOrConfigFileName, options, system, createProgram, reportDiagnostic, reportWatchStatus); // TODO: GH#18217 } else { return ts.createWatchCompilerHostOfConfigFile(rootFilesOrConfigFileName, options, system, createProgram, reportDiagnostic, reportWatchStatus); @@ -70870,14 +85298,14 @@ var ts; var initialVersion = 1; function createWatchProgram(host) { var builderProgram; - var reloadLevel; - var missingFilesMap; - var watchedWildcardDirectories; - var timerToUpdateProgram; - var sourceFilesCache = ts.createMap(); - var missingFilePathsRequestedForRelease; - var hasChangedCompilerOptions = false; - var hasChangedAutomaticTypeDirectiveNames = false; + var reloadLevel; // level to indicate if the program needs to be reloaded from config file/just filenames etc + var missingFilesMap; // Map of file watchers for the missing files + var watchedWildcardDirectories; // map of watchers for the wild card directories in the config file + var timerToUpdateProgram; // timer callback to recompile the program + var sourceFilesCache = ts.createMap(); // Cache that stores the source file and version info + var missingFilePathsRequestedForRelease; // These paths are held temparirly so that we can remove the entry from source file cache if the file is not tracked by missing files + var hasChangedCompilerOptions = false; // True if the compiler options have changed between compilations + var hasChangedAutomaticTypeDirectiveNames = false; // True if the automatic type directives have changed var useCaseSensitiveFileNames = host.useCaseSensitiveFileNames(); var currentDirectory = host.getCurrentDirectory(); var getCurrentDirectory = function () { return currentDirectory; }; @@ -70900,6 +85328,7 @@ var ts; getCurrentDirectory: getCurrentDirectory, onUnRecoverableConfigFileDiagnostic: host.onUnRecoverableConfigFileDiagnostic }; + // From tsc we want to get already parsed result and hence check for rootFileNames var newLine = updateNewLine(); reportWatchDiagnostic(ts.Diagnostics.Starting_compilation_in_watch_mode); if (configFileName) { @@ -70916,7 +85345,7 @@ var ts; var trace = host.trace && (function (s) { host.trace(s + newLine); }); var watchLogLevel = trace ? compilerOptions.extendedDiagnostics ? ts.WatchLogLevel.Verbose : compilerOptions.diagnostis ? ts.WatchLogLevel.TriggerOnly : ts.WatchLogLevel.None : ts.WatchLogLevel.None; - var writeLog = watchLogLevel !== ts.WatchLogLevel.None ? trace : ts.noop; + var writeLog = watchLogLevel !== ts.WatchLogLevel.None ? trace : ts.noop; // TODO: GH#18217 var _b = ts.getWatchFactory(watchLogLevel, writeLog), watchFile = _b.watchFile, watchFilePath = _b.watchFilePath, watchDirectory = _b.watchDirectory; var getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); writeLog("Current directory: " + currentDirectory + " CaseSensitiveFileNames: " + useCaseSensitiveFileNames); @@ -70924,6 +85353,7 @@ var ts; watchFile(host, configFileName, scheduleProgramReload, ts.PollingInterval.High, "Config file"); } var compilerHost = { + // Members for CompilerHost getSourceFile: function (fileName, languageVersion, onError, shouldCreateNewSourceFile) { return getVersionedSourceFileByPath(fileName, toPath(fileName), languageVersion, onError, shouldCreateNewSourceFile); }, getSourceFileByPath: getVersionedSourceFileByPath, getDefaultLibLocation: host.getDefaultLibLocation && (function () { return host.getDefaultLibLocation(); }), @@ -70942,6 +85372,7 @@ var ts; getEnvironmentVariable: host.getEnvironmentVariable ? (function (name) { return host.getEnvironmentVariable(name); }) : (function () { return ""; }), onReleaseOldSourceFile: onReleaseOldSourceFile, createHash: host.createHash && (function (data) { return host.createHash(data); }), + // Members for ResolutionCacheHost toPath: toPath, getCompilationSettings: function () { return compilerOptions; }, watchDirectoryOfFailedLookupLocation: function (dir, cb, flags) { return watchDirectory(host, dir, cb, flags, "Failed Lookup Locations"); }, @@ -70956,9 +85387,12 @@ var ts; getCurrentProgram: getCurrentProgram, writeLog: writeLog }; + // Cache for the module resolution var resolutionCache = ts.createResolutionCache(compilerHost, configFileName ? ts.getDirectoryPath(ts.getNormalizedAbsolutePath(configFileName, currentDirectory)) : - currentDirectory, false); + currentDirectory, + /*logChangesWhenResolvingModule*/ false); + // Resolve module using host module resolution strategy if provided otherwise use resolution cache to resolve module names compilerHost.resolveModuleNames = host.resolveModuleNames ? (function (moduleNames, containingFile, reusedNames) { return host.resolveModuleNames(moduleNames, containingFile, reusedNames); }) : (function (moduleNames, containingFile, reusedNames) { return resolutionCache.resolveModuleNames(moduleNames, containingFile, reusedNames); }); @@ -70967,6 +85401,7 @@ var ts; (function (typeDirectiveNames, containingFile) { return resolutionCache.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile); }); var userProvidedResolution = !!host.resolveModuleNames || !!host.resolveTypeReferenceDirectives; synchronizeProgram(); + // Update the wild card directory watch watchConfigFileWildCardDirectories(); return configFileName ? { getCurrentProgram: getCurrentBuilderProgram, getProgram: synchronizeProgram } : @@ -70986,10 +85421,11 @@ var ts; resolutionCache.clear(); } } + // All resolutions are invalid if user provided resolutions var hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(userProvidedResolution); if (ts.isProgramUptoDate(getCurrentProgram(), rootFileNames, compilerOptions, getSourceVersion, fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames)) { if (hasChangedConfigFileParsingErrors) { - builderProgram = createProgram(undefined, undefined, compilerHost, builderProgram, configFileParsingDiagnostics); + builderProgram = createProgram(/*rootNames*/ undefined, /*options*/ undefined, compilerHost, builderProgram, configFileParsingDiagnostics); hasChangedConfigFileParsingErrors = false; } } @@ -71002,6 +85438,7 @@ var ts; return builderProgram; } function createNewProgram(program, hasInvalidatedResolution) { + // Compile the program if (watchLogLevel !== ts.WatchLogLevel.None) { writeLog("CreatingProgramWith::"); writeLog(" roots: " + JSON.stringify(rootFileNames)); @@ -71015,11 +85452,17 @@ var ts; compilerHost.hasChangedAutomaticTypeDirectiveNames = hasChangedAutomaticTypeDirectiveNames; builderProgram = createProgram(rootFileNames, compilerOptions, compilerHost, builderProgram, configFileParsingDiagnostics); resolutionCache.finishCachingPerDirectoryResolution(); + // Update watches ts.updateMissingFilePathsWatch(builderProgram.getProgram(), missingFilesMap || (missingFilesMap = ts.createMap()), watchMissingFilePath); if (needsUpdateInTypeRootWatch) { resolutionCache.updateTypeRootsWatch(); } if (missingFilePathsRequestedForRelease) { + // These are the paths that program creater told us as not in use any more but were missing on the disk. + // We didnt remove the entry for them from sourceFiles cache so that we dont have to do File IO, + // if there is already watcher for it (for missing files) + // At this point our watches were updated, hence now we know that these paths are not tracked and need to be removed + // so that at later time we have correct result of their presence for (var _i = 0, missingFilePathsRequestedForRelease_1 = missingFilePathsRequestedForRelease; _i < missingFilePathsRequestedForRelease_1.length; _i++) { var missingFilePath = missingFilePathsRequestedForRelease_1[_i]; if (!missingFilesMap.has(missingFilePath)) { @@ -71048,6 +85491,8 @@ var ts; } function fileExists(fileName) { var path = toPath(fileName); + // If file is missing on host from cache, we can definitely say file doesnt exist + // otherwise we need to ensure from the disk if (isFileMissingOnHost(sourceFilesCache.get(path))) { return true; } @@ -71055,9 +85500,11 @@ var ts; } function getVersionedSourceFileByPath(fileName, path, languageVersion, onError, shouldCreateNewSourceFile) { var hostSourceFile = sourceFilesCache.get(path); + // No source file on the host if (isFileMissingOnHost(hostSourceFile)) { return undefined; } + // Create new source file if requested or the versions dont match if (!hostSourceFile || shouldCreateNewSourceFile || !isFilePresentOnHost(hostSourceFile) || hostSourceFile.version.toString() !== hostSourceFile.sourceFile.version) { var sourceFile = getNewSourceFile(); if (hostSourceFile) { @@ -71065,6 +85512,7 @@ var ts; hostSourceFile.version++; } if (sourceFile) { + // Set the source file and create file watcher now that file was present on the disk hostSourceFile.sourceFile = sourceFile; sourceFile.version = hostSourceFile.version.toString(); if (!hostSourceFile.fileWatcher) { @@ -71072,6 +85520,7 @@ var ts; } } else { + // There is no source file on host any more, close the watch, missing file paths will track it if (isFilePresentOnHost(hostSourceFile)) { hostSourceFile.fileWatcher.close(); } @@ -71111,6 +85560,7 @@ var ts; var hostSourceFile = sourceFilesCache.get(path); if (hostSourceFile !== undefined) { if (isFileMissingOnHost(hostSourceFile)) { + // The next version, lets set it as presence unknown file sourceFilesCache.set(path, { version: Number(hostSourceFile) + 1 }); } else { @@ -71124,7 +85574,12 @@ var ts; } function onReleaseOldSourceFile(oldSourceFile, _oldOptions) { var hostSourceFileInfo = sourceFilesCache.get(oldSourceFile.path); + // If this is the source file thats in the cache and new program doesnt need it, + // remove the cached entry. + // Note we arent deleting entry if file became missing in new program or + // there was version update and new source file was created. if (hostSourceFileInfo) { + // record the missing file paths so they can be removed later if watchers arent tracking them if (isFileMissingOnHost(hostSourceFileInfo)) { (missingFilePathsRequestedForRelease || (missingFilePathsRequestedForRelease = [])).push(oldSourceFile.path); } @@ -71142,6 +85597,9 @@ var ts; host.onWatchStatusChange(ts.createCompilerDiagnostic(message), newLine, compilerOptions || optionsToExtendForConfigFile); } } + // Upon detecting a file change, wait for 250ms and then perform a recompilation. This gives batch + // operations (such as saving all modified files in an editor) a chance to complete before we kick + // off a new compilation. function scheduleProgramUpdate() { if (!host.setTimeout || !host.clearTimeout) { return; @@ -71182,6 +85640,7 @@ var ts; hasChangedConfigFileParsingErrors = true; } rootFileNames = result.fileNames; + // Update the program synchronizeProgram(); } function reloadConfigFile() { @@ -71193,24 +85652,27 @@ var ts; parseConfigFile(); hasChangedCompilerOptions = true; synchronizeProgram(); + // Update the wild card directory watch watchConfigFileWildCardDirectories(); } function parseConfigFile() { - setConfigFileParsingResult(ts.getParsedCommandLineOfConfigFile(configFileName, optionsToExtendForConfigFile, parseConfigFileHost)); + setConfigFileParsingResult(ts.getParsedCommandLineOfConfigFile(configFileName, optionsToExtendForConfigFile, parseConfigFileHost)); // TODO: GH#18217 } function setConfigFileParsingResult(configFileParseResult) { rootFileNames = configFileParseResult.fileNames; compilerOptions = configFileParseResult.options; - configFileSpecs = configFileParseResult.configFileSpecs; + configFileSpecs = configFileParseResult.configFileSpecs; // TODO: GH#18217 configFileParsingDiagnostics = ts.getConfigFileParsingDiagnostics(configFileParseResult); hasChangedConfigFileParsingErrors = true; } function onSourceFileChange(fileName, eventKind, path) { updateCachedSystemWithFile(fileName, path, eventKind); + // Update the source file cache if (eventKind === ts.FileWatcherEventKind.Deleted && sourceFilesCache.get(path)) { resolutionCache.invalidateResolutionOfFile(path); } nextSourceFileVersion(path); + // Update the program scheduleProgramUpdate(); } function updateCachedSystemWithFile(fileName, path, eventKind) { @@ -71226,7 +85688,9 @@ var ts; if (eventKind === ts.FileWatcherEventKind.Created && missingFilesMap.has(missingFilePath)) { missingFilesMap.get(missingFilePath).close(); missingFilesMap.delete(missingFilePath); + // Delete the entry in the source files cache so that new source file is created nextSourceFileVersion(missingFilePath); + // When a missing file is created, we should update the graph. scheduleProgramUpdate(); } } @@ -71242,16 +85706,21 @@ var ts; return watchDirectory(host, directory, function (fileOrDirectory) { ts.Debug.assert(!!configFileName); var fileOrDirectoryPath = toPath(fileOrDirectory); + // Since the file existance changed, update the sourceFiles cache if (cachedDirectoryStructureHost) { cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); } nextSourceFileVersion(fileOrDirectoryPath); + // If the the added or created file or directory is not supported file name, ignore the file + // But when watched directory is added/removed, we need to reload the file list if (fileOrDirectoryPath !== directory && ts.hasExtension(fileOrDirectoryPath) && !ts.isSupportedSourceFileName(fileOrDirectory, compilerOptions)) { writeLog("Project: " + configFileName + " Detected file add/remove of non supported extension: " + fileOrDirectory); return; } + // Reload is pending, do the reload if (reloadLevel !== ts.ConfigFileProgramReloadLevel.Full) { reloadLevel = ts.ConfigFileProgramReloadLevel.Partial; + // Schedule Update the program scheduleProgramUpdate(); } }, flags, "Wild card directories"); @@ -71287,7 +85756,14 @@ var ts; var BuildResultFlags; (function (BuildResultFlags) { BuildResultFlags[BuildResultFlags["None"] = 0] = "None"; + /** + * No errors of any kind occurred during build + */ BuildResultFlags[BuildResultFlags["Success"] = 1] = "Success"; + /** + * None of the .d.ts files emitted by this build were + * different from the existing files on disk + */ BuildResultFlags[BuildResultFlags["DeclarationOutputUnchanged"] = 2] = "DeclarationOutputUnchanged"; BuildResultFlags[BuildResultFlags["ConfigFileErrors"] = 4] = "ConfigFileErrors"; BuildResultFlags[BuildResultFlags["SyntaxErrors"] = 8] = "SyntaxErrors"; @@ -71299,15 +85775,27 @@ var ts; (function (UpToDateStatusType) { UpToDateStatusType[UpToDateStatusType["Unbuildable"] = 0] = "Unbuildable"; UpToDateStatusType[UpToDateStatusType["UpToDate"] = 1] = "UpToDate"; + /** + * The project appears out of date because its upstream inputs are newer than its outputs, + * but all of its outputs are actually newer than the previous identical outputs of its (.d.ts) inputs. + * This means we can Pseudo-build (just touch timestamps), as if we had actually built this project. + */ UpToDateStatusType[UpToDateStatusType["UpToDateWithUpstreamTypes"] = 2] = "UpToDateWithUpstreamTypes"; UpToDateStatusType[UpToDateStatusType["OutputMissing"] = 3] = "OutputMissing"; UpToDateStatusType[UpToDateStatusType["OutOfDateWithSelf"] = 4] = "OutOfDateWithSelf"; UpToDateStatusType[UpToDateStatusType["OutOfDateWithUpstream"] = 5] = "OutOfDateWithUpstream"; UpToDateStatusType[UpToDateStatusType["UpstreamOutOfDate"] = 6] = "UpstreamOutOfDate"; UpToDateStatusType[UpToDateStatusType["UpstreamBlocked"] = 7] = "UpstreamBlocked"; + /** + * Projects with no outputs (i.e. "solution" files) + */ UpToDateStatusType[UpToDateStatusType["ContainerOnly"] = 8] = "ContainerOnly"; })(UpToDateStatusType = ts.UpToDateStatusType || (ts.UpToDateStatusType = {})); + /** + * A FileMap maintains a normalized-key to value relationship + */ function createFileMap() { + // tslint:disable-next-line:no-null-keyword var lookup = ts.createMap(); return { setValue: setValue, @@ -71381,14 +85869,14 @@ var ts; }; } function getOutputDeclarationFileName(inputFileName, configFile) { - var relativePath = ts.getRelativePathFromDirectory(rootDirOfOptions(configFile.options, configFile.options.configFilePath), inputFileName, true); + var relativePath = ts.getRelativePathFromDirectory(rootDirOfOptions(configFile.options, configFile.options.configFilePath), inputFileName, /*ignoreCase*/ true); var outputPath = ts.resolvePath(configFile.options.declarationDir || configFile.options.outDir || ts.getDirectoryPath(configFile.options.configFilePath), relativePath); - return ts.changeExtension(outputPath, ".d.ts"); + return ts.changeExtension(outputPath, ".d.ts" /* Dts */); } function getOutputJavaScriptFileName(inputFileName, configFile) { - var relativePath = ts.getRelativePathFromDirectory(rootDirOfOptions(configFile.options, configFile.options.configFilePath), inputFileName, true); + var relativePath = ts.getRelativePathFromDirectory(rootDirOfOptions(configFile.options, configFile.options.configFilePath), inputFileName, /*ignoreCase*/ true); var outputPath = ts.resolvePath(configFile.options.outDir || ts.getDirectoryPath(configFile.options.configFilePath), relativePath); - return ts.changeExtension(outputPath, (ts.fileExtensionIs(inputFileName, ".tsx") && configFile.options.jsx === 1) ? ".jsx" : ".js"); + return ts.changeExtension(outputPath, (ts.fileExtensionIs(inputFileName, ".tsx" /* Tsx */) && configFile.options.jsx === 1 /* Preserve */) ? ".jsx" /* Jsx */ : ".js" /* Js */); } function getOutputFileNames(inputFileName, configFile) { if (configFile.options.outFile) { @@ -71411,7 +85899,7 @@ var ts; var outputs = []; outputs.push(project.options.outFile); if (project.options.declaration) { - var dts = ts.changeExtension(project.options.outFile, ".d.ts"); + var dts = ts.changeExtension(project.options.outFile, ".d.ts" /* Dts */); outputs.push(dts); if (project.options.declarationMap) { outputs.push(dts + ".map"); @@ -71426,7 +85914,7 @@ var ts; var cache = createFileMap(); var configParseHost = ts.parseConfigHostFromCompilerHost(host); function parseConfigFile(configFilePath) { - var sourceFile = host.getSourceFile(configFilePath, 100); + var sourceFile = host.getSourceFile(configFilePath, 100 /* JSON */); if (sourceFile === undefined) { return undefined; } @@ -71447,7 +85935,7 @@ var ts; return date2 > date1 ? date2 : date1; } function isDeclarationFile(fileName) { - return ts.fileExtensionIs(fileName, ".d.ts"); + return ts.fileExtensionIs(fileName, ".d.ts" /* Dts */); } function createBuildContext(options) { var invalidatedProjects = createFileMap(); @@ -71533,8 +86021,10 @@ var ts; ts.printHelp(buildOpts, "--build "); return ts.ExitStatus.Success; } + // Not a flag, parse as filename addProject(arg); } + // Nonsensical combinations if (clean && force) { buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force"); return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped; @@ -71552,6 +86042,7 @@ var ts; return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped; } if (projects.length === 0) { + // tsc -b invoked with no extra arguments; act as if invoked with "tsc -b ." addProject("."); } var builder = createSolutionBuilder(compilerHost, buildHost, projects, { dry: dry, force: force, verbose: verbose }, system); @@ -71576,6 +86067,10 @@ var ts; } } ts.performBuild = performBuild; + /** + * A SolutionBuilder has an immutable set of rootNames that are the "entry point" projects, but + * can dynamically add/remove other projects based on changes on the rootNames' references + */ function createSolutionBuilder(compilerHost, buildHost, rootNames, defaultOptions, system) { if (!compilerHost.getModifiedTime || !compilerHost.setModifiedTime) { throw new Error("Host must support timestamp APIs"); @@ -71611,22 +86106,26 @@ var ts; throw new Error("System host must support watchFile / watchDirectory / setTimeout if using --watch"); var graph = getGlobalDependencyGraph(); if (!graph.buildQueue) { + // Everything is broken - we don't even know what to watch. Give up. return; } var _loop_12 = function (resolved) { var cfg = configFileCache.parseConfigFile(resolved); if (cfg) { + // Watch this file system.watchFile(resolved, function () { configFileCache.removeKey(resolved); invalidateProjectAndScheduleBuilds(resolved); }); + // Update watchers for wildcard directories if (cfg.configFileSpecs) { ts.updateWatchingWildcardDirectories(existingWatchersForWildcards, ts.createMapFromTemplate(cfg.configFileSpecs.wildcardDirectories), function (dir, flags) { return system.watchDirectory(dir, function () { invalidateProjectAndScheduleBuilds(resolved); - }, !!(flags & 1)); + }, !!(flags & 1 /* Recursive */)); }); } + // Watch input files for (var _i = 0, _a = cfg.fileNames; _i < _a.length; _i++) { var input = _a[_i]; system.watchFile(input, function () { @@ -71667,6 +86166,10 @@ var ts; function invalidateProject(configFileName) { var resolved = resolveProjectName(configFileName); if (resolved === undefined) { + // If this was a rootName, we need to track it as missing. + // Otherwise we can just ignore it and have it possibly surface as an error in any downstream projects, + // if they exist + // TODO: do those things return; } configFileCache.removeKey(resolved); @@ -71676,10 +86179,12 @@ var ts; if (graph) { queueBuildForDownstreamReferences(resolved); } + // Mark all downstream projects of this one needing to be built "later" function queueBuildForDownstreamReferences(root) { var deps = graph.dependencyMap.getReferencesTo(root); for (var _i = 0, deps_1 = deps; _i < deps_1.length; _i++) { var ref = deps_1[_i]; + // Can skip circular references if (!context.queuedProjects.hasKey(ref)) { context.queuedProjects.setValue(ref, true); queueBuildForDownstreamReferences(ref); @@ -71704,10 +86209,10 @@ var ts; continue; var resolved = resolveProjectName(next); if (!resolved) - continue; + continue; // ?? var proj = configFileCache.parseConfigFile(resolved); if (!proj) - continue; + continue; // ? var status = getUpToDateStatus(proj); verboseReportProjectStatus(next, status); if (status.type === UpToDateStatusType.UpstreamBlocked) { @@ -71738,8 +86243,10 @@ var ts; }; function visit(projPath, inCircularContext) { if (inCircularContext === void 0) { inCircularContext = false; } + // Already visited if (permanentMarks[projPath]) return; + // Circular if (temporaryMarks[projPath]) { if (!inCircularContext) { hadError = true; @@ -71782,11 +86289,13 @@ var ts; resultFlags |= BuildResultFlags.DeclarationOutputUnchanged; var configFile = configFileCache.parseConfigFile(proj); if (!configFile) { + // Failed to read the config file resultFlags |= BuildResultFlags.ConfigFileErrors; context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Config file errors" }); return resultFlags; } if (configFile.fileNames.length === 0) { + // Nothing to build - must be a solution file, basically return BuildResultFlags.None; } var programOptions = { @@ -71796,6 +86305,7 @@ var ts; options: configFile.options }; var program = ts.createProgram(programOptions); + // Don't emit anything in the presence of syntactic errors or options diagnostics var syntaxDiagnostics = program.getOptionsDiagnostics().concat(program.getSyntacticDiagnostics()); if (syntaxDiagnostics.length) { resultFlags |= BuildResultFlags.SyntaxErrors; @@ -71806,6 +86316,7 @@ var ts; context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Syntactic errors" }); return resultFlags; } + // Don't emit .d.ts if there are decl file errors if (program.getCompilerOptions().declaration) { var declDiagnostics = program.getDeclarationDiagnostics(); if (declDiagnostics.length) { @@ -71818,6 +86329,7 @@ var ts; return resultFlags; } } + // Same as above but now for semantic diagnostics var semanticDiagnostics = program.getSemanticDiagnostics(); if (semanticDiagnostics.length) { resultFlags |= BuildResultFlags.TypeErrors; @@ -71829,10 +86341,11 @@ var ts; return resultFlags; } var newestDeclarationFileContentChangedTime = minimumDate; - program.emit(undefined, function (fileName, content, writeBom, onError) { + program.emit(/*targetSourceFile*/ undefined, function (fileName, content, writeBom, onError) { var priorChangeTime; if (isDeclarationFile(fileName) && compilerHost.fileExists(fileName)) { if (compilerHost.readFile(fileName) === content) { + // Check for unchanged .d.ts files resultFlags &= ~BuildResultFlags.DeclarationOutputUnchanged; priorChangeTime = compilerHost.getModifiedTime && compilerHost.getModifiedTime(fileName); } @@ -71868,6 +86381,7 @@ var ts; var resolvedNames = resolveProjectNames(configFileNames); if (resolvedNames === undefined) return undefined; + // Get the same graph for cleaning we'd use for building var graph = createDependencyGraph(resolvedNames); if (graph === undefined) return undefined; @@ -71876,6 +86390,7 @@ var ts; var proj = _a[_i]; var parsed = configFileCache.parseConfigFile(proj); if (parsed === undefined) { + // File has gone missing; fine to ignore here continue; } var outputs = getAllProjectOutputs(parsed); @@ -71912,6 +86427,7 @@ var ts; buildHost.message(ts.Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, filesToDelete.map(function (f) { return "\r\n * " + f; }).join("")); return ts.ExitStatus.Success; } + // Do this check later to allow --clean --dry to function even if the host can't delete files if (!compilerHost.deleteFile) { throw new Error("Host does not support deleting files"); } @@ -71963,12 +86479,15 @@ var ts; verboseReportProjectStatus(next, status); var projName = proj.options.configFilePath; if (status.type === UpToDateStatusType.UpToDate && !context.options.force) { + // Up to date, skip if (defaultOptions.dry) { + // In a dry build, inform the user of this fact buildHost.message(ts.Diagnostics.Project_0_is_up_to_date, projName); } continue; } if (status.type === UpToDateStatusType.UpToDateWithUpstreamTypes && !context.options.force) { + // Fake build updateOutputTimestamps(proj); continue; } @@ -71978,6 +86497,7 @@ var ts; continue; } if (status.type === UpToDateStatusType.ContainerOnly) { + // Do nothing continue; } var buildResult = buildSingleProject(next); @@ -71985,6 +86505,9 @@ var ts; } return anyFailed ? ts.ExitStatus.DiagnosticsPresent_OutputsSkipped : ts.ExitStatus.Success; } + /** + * Report the build ordering inferred from the current project graph if we're in verbose mode + */ function reportBuildQueue(graph) { if (!context.options.verbose) return; @@ -72006,6 +86529,9 @@ var ts; } buildHost.verbose.apply(buildHost, [message].concat(args)); } + /** + * Report the up-to-date status of a project if we're in verbose mode + */ function verboseReportProjectStatus(configFileName, status) { if (!context.options.verbose) return; @@ -72013,12 +86539,10 @@ var ts; } } ts.createSolutionBuilder = createSolutionBuilder; + /** + * Gets the UpToDateStatus for a project + */ function getUpToDateStatus(host, project) { - if (project === undefined) { - return { - type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" - }; - } if (project === undefined) { return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" }; } @@ -72036,6 +86560,7 @@ var ts; function getUpToDateStatusWorker(host, project) { var newestInputFileName = undefined; var newestInputFileTime = minimumDate; + // Get timestamps of input files for (var _i = 0, _a = project.fileNames; _i < _a.length; _i++) { var inputFile = _a[_i]; if (!host.fileExists(inputFile)) { @@ -72050,12 +86575,14 @@ var ts; newestInputFileTime = inputTime; } } + // Collect the expected outputs of this project var outputs = getAllProjectOutputs(project); if (outputs.length === 0) { return { type: UpToDateStatusType.ContainerOnly }; } + // Now see if all outputs are newer than the newest input var oldestOutputFileName = "(none)"; var oldestOutputFileTime = maximumDate; var newestOutputFileName = "(none)"; @@ -72065,6 +86592,8 @@ var ts; var isOutOfDateWithInputs = false; for (var _b = 0, outputs_3 = outputs; _b < outputs_3.length; _b++) { var output = outputs_3[_b]; + // Output is missing; can stop checking + // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status if (!host.fileExists(output)) { missingOutputFileName = output; break; @@ -72074,6 +86603,8 @@ var ts; oldestOutputFileTime = outputTime; oldestOutputFileName = output; } + // If an output is older than the newest input, we can stop checking + // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status if (outputTime < newestInputFileTime) { isOutOfDateWithInputs = true; break; @@ -72082,6 +86613,10 @@ var ts; newestOutputFileTime = outputTime; newestOutputFileName = output; } + // Keep track of when the most recent time a .d.ts file was changed. + // In addition to file timestamps, we also keep track of when a .d.ts file + // had its file touched but not had its contents changed - this allows us + // to skip a downstream typecheck if (isDeclarationFile(output)) { var unchangedTime = host.getUnchangedTime ? host.getUnchangedTime(output) : undefined; if (unchangedTime !== undefined) { @@ -72094,31 +86629,40 @@ var ts; } var pseudoUpToDate = false; var usesPrepend = false; + var upstreamChangedProject; if (project.projectReferences && host.parseConfigFile) { for (var _c = 0, _d = project.projectReferences; _c < _d.length; _c++) { var ref = _d[_c]; usesPrepend = usesPrepend || !!(ref.prepend); var resolvedRef = ts.resolveProjectReferencePath(host, ref); var refStatus = getUpToDateStatus(host, host.parseConfigFile(resolvedRef)); + // An upstream project is blocked if (refStatus.type === UpToDateStatusType.Unbuildable) { return { type: UpToDateStatusType.UpstreamBlocked, upstreamProjectName: ref.path }; } + // If the upstream project is out of date, then so are we (someone shouldn't have asked, though?) if (refStatus.type !== UpToDateStatusType.UpToDate) { return { type: UpToDateStatusType.UpstreamOutOfDate, upstreamProjectName: ref.path }; } + // If the upstream project's newest file is older than our oldest output, we + // can't be out of date because of it if (refStatus.newestInputFileTime <= oldestOutputFileTime) { continue; } + // If the upstream project has only change .d.ts files, and we've built + // *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild if (refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) { pseudoUpToDate = true; + upstreamChangedProject = ref.path; continue; } + // We have an output older than an upstream output - we are out of date ts.Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here"); return { type: UpToDateStatusType.OutOfDateWithUpstream, @@ -72140,9 +86684,14 @@ var ts; newerInputFileName: newestInputFileName }; } - if (usesPrepend) { - pseudoUpToDate = false; + if (usesPrepend && pseudoUpToDate) { + return { + type: UpToDateStatusType.OutOfDateWithUpstream, + outOfDateOutputFileName: oldestOutputFileName, + newerProjectName: upstreamChangedProject + }; } + // Up to date return { type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate, newestDeclarationFileContentChangedTime: newestDeclarationFileContentChangedTime, @@ -72179,6 +86728,7 @@ var ts; if (status.newestInputFileTime !== undefined) { return formatMessage(ts.Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, relName(configFileName), relName(status.newestInputFileName), relName(status.oldestOutputFileName)); } + // Don't report anything for "up to date because it was already built" -- too verbose break; case UpToDateStatusType.UpToDateWithUpstreamTypes: return formatMessage(ts.Diagnostics.Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies, relName(configFileName)); @@ -72189,6 +86739,7 @@ var ts; case UpToDateStatusType.Unbuildable: return formatMessage(ts.Diagnostics.Failed_to_parse_file_0_Colon_1, relName(configFileName), status.reason); case UpToDateStatusType.ContainerOnly: + // Don't report status on "solution" projects break; default: ts.assertTypeIsNever(status); @@ -72196,10 +86747,12 @@ var ts; } ts.formatUpToDateStatus = formatUpToDateStatus; })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var server; (function (server) { + // tslint:disable variable-name server.ActionSet = "action::set"; server.ActionInvalidate = "action::invalidate"; server.ActionPackageInstalled = "action::packageInstalled"; @@ -72214,6 +86767,10 @@ var ts; Arguments.EnableTelemetry = "--enableTelemetry"; Arguments.TypingSafeListLocation = "--typingSafeListLocation"; Arguments.TypesMapLocation = "--typesMapLocation"; + /** + * This argument specifies the location of the NPM executable. + * typingsInstaller will run the command with `${npmLocation} install ...`. + */ Arguments.NpmLocation = "--npmLocation"; })(Arguments = server.Arguments || (server.Arguments = {})); function hasArgument(argumentName) { @@ -72227,22 +86784,27 @@ var ts; : undefined; } server.findArgument = findArgument; + /*@internal*/ function nowString() { + // E.g. "12:34:56.789" var d = new Date(); return d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds() + "." + d.getMilliseconds(); } server.nowString = nowString; })(server = ts.server || (ts.server = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var JsTyping; (function (JsTyping) { + /* @internal */ function isTypingUpToDate(cachedTyping, availableTypingVersions) { var availableVersion = ts.Semver.parse(ts.getProperty(availableTypingVersions, "ts" + ts.versionMajorMinor) || ts.getProperty(availableTypingVersions, "latest")); return !availableVersion.greaterThan(cachedTyping.version); } JsTyping.isTypingUpToDate = isTypingUpToDate; + /* @internal */ JsTyping.nodeCoreModuleList = [ "assert", "async_hooks", @@ -72281,6 +86843,7 @@ var ts; "vm", "zlib" ]; + /* @internal */ JsTyping.nodeCoreModules = ts.arrayToSet(JsTyping.nodeCoreModuleList); function loadSafeList(host, safeListPath) { var result = ts.readConfigFile(safeListPath, function (path) { return host.readFile(path); }); @@ -72295,11 +86858,22 @@ var ts; return undefined; } JsTyping.loadTypesMap = loadTypesMap; + /** + * @param host is the object providing I/O related operations. + * @param fileNames are the file names that belong to the same project + * @param projectRootPath is the path to the project root directory + * @param safeListPath is the path used to retrieve the safe list + * @param packageNameToTypingLocation is the map of package names to their cached typing locations and installed versions + * @param typeAcquisition is used to customize the typing acquisition process + * @param compilerOptions are used as a source for typing inference + */ function discoverTypings(host, log, fileNames, projectRootPath, safeList, packageNameToTypingLocation, typeAcquisition, unresolvedImports, typesRegistry) { if (!typeAcquisition || !typeAcquisition.enable) { return { cachedTypingPaths: [], newTypingNames: [], filesToWatch: [] }; } + // A typing name to typing file path mapping var inferredTypings = ts.createMap(); + // Only infer typings for .js and .jsx files fileNames = ts.mapDefined(fileNames, function (fileName) { var path = ts.normalizePath(fileName); if (ts.hasJavaScriptFileExtension(path)) { @@ -72310,6 +86884,7 @@ var ts; if (typeAcquisition.include) addInferredTypings(typeAcquisition.include, "Explicitly included types"); var exclude = typeAcquisition.exclude || []; + // Directories to search for package.json, bower.json and other typing information var possibleSearchDirs = ts.arrayToSet(fileNames, ts.getDirectoryPath); possibleSearchDirs.set(projectRootPath, true); possibleSearchDirs.forEach(function (_true, searchDir) { @@ -72323,16 +86898,19 @@ var ts; getTypingNamesFromPackagesFolder(nodeModulesPath, filesToWatch); }); getTypingNamesFromSourceFileNames(fileNames); + // add typings for unresolved imports if (unresolvedImports) { var module_1 = ts.deduplicate(unresolvedImports.map(function (moduleId) { return JsTyping.nodeCoreModules.has(moduleId) ? "node" : moduleId; }), ts.equateStringsCaseSensitive, ts.compareStringsCaseSensitive); addInferredTypings(module_1, "Inferred typings from unresolved imports"); } + // Add the cached typing locations for inferred typings that are already installed packageNameToTypingLocation.forEach(function (typing, name) { var registryEntry = typesRegistry.get(name); if (inferredTypings.has(name) && inferredTypings.get(name) === undefined && registryEntry !== undefined && isTypingUpToDate(typing, registryEntry)) { inferredTypings.set(name, typing.typingLocation); } }); + // Remove typings that the user has added to the exclude list for (var _i = 0, exclude_1 = exclude; _i < exclude_1.length; _i++) { var excludeTypingName = exclude_1[_i]; var didDelete = inferredTypings.delete(excludeTypingName); @@ -72355,7 +86933,7 @@ var ts; return result; function addInferredTyping(typingName) { if (!inferredTypings.has(typingName)) { - inferredTypings.set(typingName, undefined); + inferredTypings.set(typingName, undefined); // TODO: GH#18217 } } function addInferredTypings(typingNames, message) { @@ -72363,6 +86941,9 @@ var ts; log(message + ": " + JSON.stringify(typingNames)); ts.forEach(typingNames, addInferredTyping); } + /** + * Get the typing info from common package manager json files like package.json or bower.json + */ function getTypingNamesFromJson(jsonPath, filesToWatch) { if (!host.fileExists(jsonPath)) { return; @@ -72372,6 +86953,12 @@ var ts; var jsonTypingNames = ts.flatMap([jsonConfig.dependencies, jsonConfig.devDependencies, jsonConfig.optionalDependencies, jsonConfig.peerDependencies], ts.getOwnKeys); addInferredTypings(jsonTypingNames, "Typing names in '" + jsonPath + "' dependencies"); } + /** + * Infer typing names from given file names. For example, the file name "jquery-min.2.3.4.js" + * should be inferred to the 'jquery' typing name; and "angular-route.1.2.3.js" should be inferred + * to the 'angular-route' typing name. + * @param fileNames are the names for source files in the project + */ function getTypingNamesFromSourceFileNames(fileNames) { var fromFileNames = ts.mapDefined(fileNames, function (j) { if (!ts.hasJavaScriptFileExtension(j)) @@ -72383,19 +86970,25 @@ var ts; if (fromFileNames.length) { addInferredTypings(fromFileNames, "Inferred typings from file names"); } - var hasJsxFile = ts.some(fileNames, function (f) { return ts.fileExtensionIs(f, ".jsx"); }); + var hasJsxFile = ts.some(fileNames, function (f) { return ts.fileExtensionIs(f, ".jsx" /* Jsx */); }); if (hasJsxFile) { if (log) log("Inferred 'react' typings due to presence of '.jsx' extension"); addInferredTyping("react"); } } + /** + * Infer typing names from packages folder (ex: node_module, bower_components) + * @param packagesFolderPath is the path to the packages folder + */ function getTypingNamesFromPackagesFolder(packagesFolderPath, filesToWatch) { filesToWatch.push(packagesFolderPath); + // Todo: add support for ModuleResolutionHost too if (!host.directoryExists(packagesFolderPath)) { return; } - var fileNames = host.readDirectory(packagesFolderPath, [".json"], undefined, undefined, 2); + // depth of 2, so we access `node_modules/foo` but not `node_modules/foo/bar` + var fileNames = host.readDirectory(packagesFolderPath, [".json" /* Json */], /*excludes*/ undefined, /*includes*/ undefined, /*depth*/ 2); if (log) log("Searching for typing names in " + packagesFolderPath + "; all files: " + JSON.stringify(fileNames)); var packageNames = []; @@ -72408,10 +87001,15 @@ var ts; } var result_5 = ts.readConfigFile(normalizedFileName, function (path) { return host.readFile(path); }); var packageJson = result_5.config; + // npm 3's package.json contains a "_requiredBy" field + // we should include all the top level module names for npm 2, and only module names whose + // "_requiredBy" field starts with "#" or equals "/" for npm 3. if (baseFileName === "package.json" && packageJson._requiredBy && ts.filter(packageJson._requiredBy, function (r) { return r[0] === "#" || r === "/"; }).length === 0) { continue; } + // If the package has its own d.ts typings, those will take precedence. Otherwise the package name will be used + // to download d.ts files from DefinitelyTyped if (!packageJson.name) { continue; } @@ -72441,44 +87039,50 @@ var ts; PackageNameValidationResult[PackageNameValidationResult["NameContainsNonURISafeCharacters"] = 6] = "NameContainsNonURISafeCharacters"; })(PackageNameValidationResult = JsTyping.PackageNameValidationResult || (JsTyping.PackageNameValidationResult = {})); var maxPackageNameLength = 214; + /** + * Validates package name using rules defined at https://docs.npmjs.com/files/package.json + */ function validatePackageName(packageName) { if (!packageName) { - return 2; + return 2 /* EmptyName */; } if (packageName.length > maxPackageNameLength) { - return 3; + return 3 /* NameTooLong */; } - if (packageName.charCodeAt(0) === 46) { - return 4; + if (packageName.charCodeAt(0) === 46 /* dot */) { + return 4 /* NameStartsWithDot */; } - if (packageName.charCodeAt(0) === 95) { - return 5; + if (packageName.charCodeAt(0) === 95 /* _ */) { + return 5 /* NameStartsWithUnderscore */; } + // check if name is scope package like: starts with @ and has one '/' in the middle + // scoped packages are not currently supported + // TODO: when support will be added we'll need to split and check both scope and package name if (/^@[^/]+\/[^/]+$/.test(packageName)) { - return 1; + return 1 /* ScopedPackagesNotSupported */; } if (encodeURIComponent(packageName) !== packageName) { - return 6; + return 6 /* NameContainsNonURISafeCharacters */; } - return 0; + return 0 /* Ok */; } JsTyping.validatePackageName = validatePackageName; function renderPackageNameValidationFailure(result, typing) { switch (result) { - case 2: + case 2 /* EmptyName */: return "Package name '" + typing + "' cannot be empty"; - case 3: + case 3 /* NameTooLong */: return "Package name '" + typing + "' should be less than " + maxPackageNameLength + " characters"; - case 4: + case 4 /* NameStartsWithDot */: return "Package name '" + typing + "' cannot start with '.'"; - case 5: + case 5 /* NameStartsWithUnderscore */: return "Package name '" + typing + "' cannot start with '_'"; - case 1: + case 1 /* ScopedPackagesNotSupported */: return "Package '" + typing + "' is scoped and currently is not supported"; - case 6: + case 6 /* NameContainsNonURISafeCharacters */: return "Package name '" + typing + "' contains non URI safe characters"; - case 0: - return ts.Debug.fail(); + case 0 /* Ok */: + return ts.Debug.fail(); // Shouldn't have called this. default: throw ts.Debug.assertNever(result); } @@ -72486,6 +87090,7 @@ var ts; JsTyping.renderPackageNameValidationFailure = renderPackageNameValidationFailure; })(JsTyping = ts.JsTyping || (ts.JsTyping = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { function stringToInt(str) { @@ -72498,8 +87103,13 @@ var ts; var isPrereleaseRegex = /^(.*)-next.\d+/; var prereleaseSemverRegex = /^(\d+)\.(\d+)\.0-next.(\d+)$/; var semverRegex = /^(\d+)\.(\d+)\.(\d+)$/; - var Semver = (function () { - function Semver(major, minor, patch, isPrerelease) { + var Semver = /** @class */ (function () { + function Semver(major, minor, patch, + /** + * If true, this is `major.minor.0-next.patch`. + * If false, this is `major.minor.patch`. + */ + isPrerelease) { this.major = major; this.minor = minor; this.patch = patch; @@ -72517,7 +87127,10 @@ var ts; var major = _a.major, minor = _a.minor, patch = _a.patch, isPrerelease = _a.isPrerelease; return new Semver(major, minor, patch, isPrerelease); }; + // This must parse the output of `versionString`. Semver.tryParse = function (semver, isPrerelease) { + // Per the semver spec : + // "A normal version number MUST take the form X.Y.Z where X, Y, and Z are non-negative integers, and MUST NOT contain leading zeroes." var rgx = isPrerelease ? prereleaseSemverRegex : semverRegex; var match = rgx.exec(semver); return match ? new Semver(stringToInt(match[1]), stringToInt(match[2]), stringToInt(match[3]), isPrerelease) : undefined; @@ -72546,7 +87159,7 @@ var ts; (function (ts) { var ScriptSnapshot; (function (ScriptSnapshot) { - var StringScriptSnapshot = (function () { + var StringScriptSnapshot = /** @class */ (function () { function StringScriptSnapshot(text) { this.text = text; } @@ -72559,6 +87172,8 @@ var ts; return this.text.length; }; StringScriptSnapshot.prototype.getChangeRange = function () { + // Text-based snapshots do not support incremental parsing. Return undefined + // to signal that to the caller. return undefined; }; return StringScriptSnapshot; @@ -72568,8 +87183,9 @@ var ts; } ScriptSnapshot.fromString = fromString; })(ScriptSnapshot = ts.ScriptSnapshot || (ts.ScriptSnapshot = {})); + /* @internal */ ts.defaultPreferences = {}; - var TextChange = (function () { + var TextChange = /** @class */ (function () { function TextChange() { } return TextChange; @@ -72615,9 +87231,13 @@ var ts; })(SymbolDisplayPartKind = ts.SymbolDisplayPartKind || (ts.SymbolDisplayPartKind = {})); var OutliningSpanKind; (function (OutliningSpanKind) { + /** Single or multi-line comments */ OutliningSpanKind["Comment"] = "comment"; + /** Sections marked by '// #region' and '// #endregion' comments */ OutliningSpanKind["Region"] = "region"; + /** Declarations and expressions */ OutliningSpanKind["Code"] = "code"; + /** Contiguous blocks of import declarations */ OutliningSpanKind["Imports"] = "imports"; })(OutliningSpanKind = ts.OutliningSpanKind || (ts.OutliningSpanKind = {})); var OutputFileType; @@ -72652,27 +87272,56 @@ var ts; (function (ScriptElementKind) { ScriptElementKind["unknown"] = ""; ScriptElementKind["warning"] = "warning"; + /** predefined type (void) or keyword (class) */ ScriptElementKind["keyword"] = "keyword"; + /** top level script node */ ScriptElementKind["scriptElement"] = "script"; + /** module foo {} */ ScriptElementKind["moduleElement"] = "module"; + /** class X {} */ ScriptElementKind["classElement"] = "class"; + /** var x = class X {} */ ScriptElementKind["localClassElement"] = "local class"; + /** interface Y {} */ ScriptElementKind["interfaceElement"] = "interface"; + /** type T = ... */ ScriptElementKind["typeElement"] = "type"; + /** enum E */ ScriptElementKind["enumElement"] = "enum"; ScriptElementKind["enumMemberElement"] = "enum member"; + /** + * Inside module and script only + * const v = .. + */ ScriptElementKind["variableElement"] = "var"; + /** Inside function */ ScriptElementKind["localVariableElement"] = "local var"; + /** + * Inside module and script only + * function f() { } + */ ScriptElementKind["functionElement"] = "function"; + /** Inside function */ ScriptElementKind["localFunctionElement"] = "local function"; + /** class X { [public|private]* foo() {} } */ ScriptElementKind["memberFunctionElement"] = "method"; + /** class X { [public|private]* [get|set] foo:number; } */ ScriptElementKind["memberGetAccessorElement"] = "getter"; ScriptElementKind["memberSetAccessorElement"] = "setter"; + /** + * class X { [public|private]* foo:number; } + * interface Y { foo:number; } + */ ScriptElementKind["memberVariableElement"] = "property"; + /** class X { constructor() { } } */ ScriptElementKind["constructorImplementationElement"] = "constructor"; + /** interface Y { ():number; } */ ScriptElementKind["callSignatureElement"] = "call"; + /** interface Y { []:number; } */ ScriptElementKind["indexSignatureElement"] = "index"; + /** interface Y { new():Y; } */ ScriptElementKind["constructSignatureElement"] = "construct"; + /** function foo(*Y*: string) */ ScriptElementKind["parameterElement"] = "parameter"; ScriptElementKind["typeParameterElement"] = "type parameter"; ScriptElementKind["primitiveType"] = "primitive type"; @@ -72682,7 +87331,11 @@ var ts; ScriptElementKind["letElement"] = "let"; ScriptElementKind["directory"] = "directory"; ScriptElementKind["externalModuleName"] = "external module name"; + /** + * + */ ScriptElementKind["jsxAttribute"] = "JSX attribute"; + /** String literal */ ScriptElementKind["string"] = "string"; })(ScriptElementKind = ts.ScriptElementKind || (ts.ScriptElementKind = {})); var ScriptElementKindModifier; @@ -72751,9 +87404,11 @@ var ts; ClassificationType[ClassificationType["jsxAttributeStringLiteralValue"] = 24] = "jsxAttributeStringLiteralValue"; })(ClassificationType = ts.ClassificationType || (ts.ClassificationType = {})); })(ts || (ts = {})); +// These utilities are common to multiple language service features. +/* @internal */ var ts; (function (ts) { - ts.scanner = ts.createScanner(6, true); + ts.scanner = ts.createScanner(6 /* Latest */, /*skipTrivia*/ true); var SemanticMeaning; (function (SemanticMeaning) { SemanticMeaning[SemanticMeaning["None"] = 0] = "None"; @@ -72764,64 +87419,66 @@ var ts; })(SemanticMeaning = ts.SemanticMeaning || (ts.SemanticMeaning = {})); function getMeaningFromDeclaration(node) { switch (node.kind) { - case 149: - case 232: - case 182: - case 152: - case 151: - case 270: - case 271: - case 154: - case 153: - case 155: - case 156: - case 157: - case 234: - case 192: - case 193: - case 269: - case 262: - return 1; - case 148: - case 236: - case 237: - case 166: - return 2; - case 298: - return node.name === undefined ? 1 | 2 : 2; - case 273: - case 235: - return 1 | 2; - case 239: + case 149 /* Parameter */: + case 232 /* VariableDeclaration */: + case 182 /* BindingElement */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 270 /* PropertyAssignment */: + case 271 /* ShorthandPropertyAssignment */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 269 /* CatchClause */: + case 262 /* JsxAttribute */: + return 1 /* Value */; + case 148 /* TypeParameter */: + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 166 /* TypeLiteral */: + return 2 /* Type */; + case 298 /* JSDocTypedefTag */: + // If it has no name node, it shares the name with the value declaration below it. + return node.name === undefined ? 1 /* Value */ | 2 /* Type */ : 2 /* Type */; + case 273 /* EnumMember */: + case 235 /* ClassDeclaration */: + return 1 /* Value */ | 2 /* Type */; + case 239 /* ModuleDeclaration */: if (ts.isAmbientModule(node)) { - return 4 | 1; + return 4 /* Namespace */ | 1 /* Value */; } - else if (ts.getModuleInstanceState(node) === 1) { - return 4 | 1; + else if (ts.getModuleInstanceState(node) === 1 /* Instantiated */) { + return 4 /* Namespace */ | 1 /* Value */; } else { - return 4; + return 4 /* Namespace */; } - case 238: - case 247: - case 248: - case 243: - case 244: - case 249: - case 250: - return 7; - case 274: - return 4 | 1; + case 238 /* EnumDeclaration */: + case 247 /* NamedImports */: + case 248 /* ImportSpecifier */: + case 243 /* ImportEqualsDeclaration */: + case 244 /* ImportDeclaration */: + case 249 /* ExportAssignment */: + case 250 /* ExportDeclaration */: + return 7 /* All */; + // An external module can be a Value + case 274 /* SourceFile */: + return 4 /* Namespace */ | 1 /* Value */; } - return 7; + return 7 /* All */; } ts.getMeaningFromDeclaration = getMeaningFromDeclaration; function getMeaningFromLocation(node) { - if (node.kind === 274) { - return 1; + if (node.kind === 274 /* SourceFile */) { + return 1 /* Value */; } - else if (node.parent.kind === 249) { - return 7; + else if (node.parent.kind === 249 /* ExportAssignment */) { + return 7 /* All */; } else if (isInRightSideOfInternalImportEqualsDeclaration(node)) { return getMeaningFromRightHandSideOfImportEquals(node); @@ -72830,29 +87487,33 @@ var ts; return getMeaningFromDeclaration(node.parent); } else if (isTypeReference(node)) { - return 2; + return 2 /* Type */; } else if (isNamespaceReference(node)) { - return 4; + return 4 /* Namespace */; } else if (ts.isTypeParameterDeclaration(node.parent)) { - ts.Debug.assert(ts.isJSDocTemplateTag(node.parent.parent)); - return 2; + ts.Debug.assert(ts.isJSDocTemplateTag(node.parent.parent)); // Else would be handled by isDeclarationName + return 2 /* Type */; } else if (ts.isLiteralTypeNode(node.parent)) { - return 2 | 1; + // This might be T["name"], which is actually referencing a property and not a type. So allow both meanings. + return 2 /* Type */ | 1 /* Value */; } else { - return 1; + return 1 /* Value */; } } ts.getMeaningFromLocation = getMeaningFromLocation; function getMeaningFromRightHandSideOfImportEquals(node) { - var name = node.kind === 146 ? node : ts.isQualifiedName(node.parent) && node.parent.right === node ? node.parent : undefined; - return name && name.parent.kind === 243 ? 7 : 4; + // import a = |b|; // Namespace + // import a = |b.c|; // Value, type, namespace + // import a = |b.c|.d; // Namespace + var name = node.kind === 146 /* QualifiedName */ ? node : ts.isQualifiedName(node.parent) && node.parent.right === node ? node.parent : undefined; + return name && name.parent.kind === 243 /* ImportEqualsDeclaration */ ? 7 /* All */ : 4 /* Namespace */; } function isInRightSideOfInternalImportEqualsDeclaration(node) { - while (node.parent.kind === 146) { + while (node.parent.kind === 146 /* QualifiedName */) { node = node.parent; } return ts.isInternalModuleImportEqualsDeclaration(node.parent) && node.parent.moduleReference === node; @@ -72864,27 +87525,27 @@ var ts; function isQualifiedNameNamespaceReference(node) { var root = node; var isLastClause = true; - if (root.parent.kind === 146) { - while (root.parent && root.parent.kind === 146) { + if (root.parent.kind === 146 /* QualifiedName */) { + while (root.parent && root.parent.kind === 146 /* QualifiedName */) { root = root.parent; } isLastClause = root.right === node; } - return root.parent.kind === 162 && !isLastClause; + return root.parent.kind === 162 /* TypeReference */ && !isLastClause; } function isPropertyAccessNamespaceReference(node) { var root = node; var isLastClause = true; - if (root.parent.kind === 185) { - while (root.parent && root.parent.kind === 185) { + if (root.parent.kind === 185 /* PropertyAccessExpression */) { + while (root.parent && root.parent.kind === 185 /* PropertyAccessExpression */) { root = root.parent; } isLastClause = root.name === node; } - if (!isLastClause && root.parent.kind === 207 && root.parent.parent.kind === 268) { + if (!isLastClause && root.parent.kind === 207 /* ExpressionWithTypeArguments */ && root.parent.parent.kind === 268 /* HeritageClause */) { var decl = root.parent.parent.parent; - return (decl.kind === 235 && root.parent.parent.token === 108) || - (decl.kind === 236 && root.parent.parent.token === 85); + return (decl.kind === 235 /* ClassDeclaration */ && root.parent.parent.token === 108 /* ImplementsKeyword */) || + (decl.kind === 236 /* InterfaceDeclaration */ && root.parent.parent.token === 85 /* ExtendsKeyword */); } return false; } @@ -72893,27 +87554,27 @@ var ts; node = node.parent; } switch (node.kind) { - case 99: + case 99 /* ThisKeyword */: return !ts.isExpressionNode(node); - case 174: + case 174 /* ThisType */: return true; } switch (node.parent.kind) { - case 162: + case 162 /* TypeReference */: return true; - case 179: + case 179 /* ImportType */: return !node.parent.isTypeOf; - case 207: + case 207 /* ExpressionWithTypeArguments */: return !ts.isExpressionWithTypeArgumentsInClassExtendsClause(node.parent); } return false; } function isCallExpressionTarget(node) { - return isCallOrNewExpressionTarget(node, 187); + return isCallOrNewExpressionTarget(node, 187 /* CallExpression */); } ts.isCallExpressionTarget = isCallExpressionTarget; function isNewExpressionTarget(node) { - return isCallOrNewExpressionTarget(node, 188); + return isCallOrNewExpressionTarget(node, 188 /* NewExpression */); } ts.isNewExpressionTarget = isNewExpressionTarget; function isCallOrNewExpressionTarget(node, kind) { @@ -72926,7 +87587,7 @@ var ts; ts.climbPastPropertyAccess = climbPastPropertyAccess; function getTargetLabel(referenceNode, labelName) { while (referenceNode) { - if (referenceNode.kind === 228 && referenceNode.label.escapedText === labelName) { + if (referenceNode.kind === 228 /* LabeledStatement */ && referenceNode.label.escapedText === labelName) { return referenceNode.label; } referenceNode = referenceNode.parent; @@ -72935,11 +87596,11 @@ var ts; } ts.getTargetLabel = getTargetLabel; function isJumpStatementTarget(node) { - return node.kind === 71 && ts.isBreakOrContinueStatement(node.parent) && node.parent.label === node; + return node.kind === 71 /* Identifier */ && ts.isBreakOrContinueStatement(node.parent) && node.parent.label === node; } ts.isJumpStatementTarget = isJumpStatementTarget; function isLabelOfLabeledStatement(node) { - return node.kind === 71 && ts.isLabeledStatement(node.parent) && node.parent.label === node; + return node.kind === 71 /* Identifier */ && ts.isLabeledStatement(node.parent) && node.parent.label === node; } ts.isLabelOfLabeledStatement = isLabelOfLabeledStatement; function isLabelName(node) { @@ -72947,40 +87608,40 @@ var ts; } ts.isLabelName = isLabelName; function isRightSideOfQualifiedName(node) { - return node.parent.kind === 146 && node.parent.right === node; + return node.parent.kind === 146 /* QualifiedName */ && node.parent.right === node; } ts.isRightSideOfQualifiedName = isRightSideOfQualifiedName; function isRightSideOfPropertyAccess(node) { - return node && node.parent && node.parent.kind === 185 && node.parent.name === node; + return node && node.parent && node.parent.kind === 185 /* PropertyAccessExpression */ && node.parent.name === node; } ts.isRightSideOfPropertyAccess = isRightSideOfPropertyAccess; function isNameOfModuleDeclaration(node) { - return node.parent.kind === 239 && node.parent.name === node; + return node.parent.kind === 239 /* ModuleDeclaration */ && node.parent.name === node; } ts.isNameOfModuleDeclaration = isNameOfModuleDeclaration; function isNameOfFunctionDeclaration(node) { - return node.kind === 71 && + return node.kind === 71 /* Identifier */ && ts.isFunctionLike(node.parent) && node.parent.name === node; } ts.isNameOfFunctionDeclaration = isNameOfFunctionDeclaration; function isLiteralNameOfPropertyDeclarationOrIndexAccess(node) { switch (node.parent.kind) { - case 152: - case 151: - case 270: - case 273: - case 154: - case 153: - case 156: - case 157: - case 239: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 270 /* PropertyAssignment */: + case 273 /* EnumMember */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 239 /* ModuleDeclaration */: return ts.getNameOfDeclaration(node.parent) === node; - case 186: + case 186 /* ElementAccessExpression */: return node.parent.argumentExpression === node; - case 147: + case 147 /* ComputedPropertyName */: return true; - case 178: - return node.parent.parent.kind === 176; + case 178 /* LiteralType */: + return node.parent.parent.kind === 176 /* IndexedAccessType */; default: return false; } @@ -72993,6 +87654,9 @@ var ts; ts.isExpressionOfExternalModuleImportEqualsDeclaration = isExpressionOfExternalModuleImportEqualsDeclaration; function getContainerNode(node) { if (ts.isJSDocTypeAlias(node)) { + // This doesn't just apply to the node immediately under the comment, but to everything in its parent's scope. + // node.parent = the JSDoc comment, node.parent.parent = the node having the comment. + // Then we get parent again in the loop. node = node.parent.parent; } while (true) { @@ -73001,17 +87665,17 @@ var ts; return undefined; } switch (node.kind) { - case 274: - case 154: - case 153: - case 234: - case 192: - case 156: - case 157: - case 235: - case 236: - case 238: - case 239: + case 274 /* SourceFile */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + case 238 /* EnumDeclaration */: + case 239 /* ModuleDeclaration */: return node; } } @@ -73019,94 +87683,98 @@ var ts; ts.getContainerNode = getContainerNode; function getNodeKind(node) { switch (node.kind) { - case 274: - return ts.isExternalModule(node) ? "module" : "script"; - case 239: - return "module"; - case 235: - case 205: - return "class"; - case 236: return "interface"; - case 237: - case 292: - case 298: - return "type"; - case 238: return "enum"; - case 232: + case 274 /* SourceFile */: + return ts.isExternalModule(node) ? "module" /* moduleElement */ : "script" /* scriptElement */; + case 239 /* ModuleDeclaration */: + return "module" /* moduleElement */; + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + return "class" /* classElement */; + case 236 /* InterfaceDeclaration */: return "interface" /* interfaceElement */; + case 237 /* TypeAliasDeclaration */: + case 292 /* JSDocCallbackTag */: + case 298 /* JSDocTypedefTag */: + return "type" /* typeElement */; + case 238 /* EnumDeclaration */: return "enum" /* enumElement */; + case 232 /* VariableDeclaration */: return getKindOfVariableDeclaration(node); - case 182: + case 182 /* BindingElement */: return getKindOfVariableDeclaration(ts.getRootDeclaration(node)); - case 193: - case 234: - case 192: - return "function"; - case 156: return "getter"; - case 157: return "setter"; - case 154: - case 153: - return "method"; - case 152: - case 151: - return "property"; - case 160: return "index"; - case 159: return "construct"; - case 158: return "call"; - case 155: return "constructor"; - case 148: return "type parameter"; - case 273: return "enum member"; - case 149: return ts.hasModifier(node, 92) ? "property" : "parameter"; - case 243: - case 248: - case 245: - case 252: - case 246: - return "alias"; - case 200: + case 193 /* ArrowFunction */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + return "function" /* functionElement */; + case 156 /* GetAccessor */: return "getter" /* memberGetAccessorElement */; + case 157 /* SetAccessor */: return "setter" /* memberSetAccessorElement */; + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + return "method" /* memberFunctionElement */; + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + return "property" /* memberVariableElement */; + case 160 /* IndexSignature */: return "index" /* indexSignatureElement */; + case 159 /* ConstructSignature */: return "construct" /* constructSignatureElement */; + case 158 /* CallSignature */: return "call" /* callSignatureElement */; + case 155 /* Constructor */: return "constructor" /* constructorImplementationElement */; + case 148 /* TypeParameter */: return "type parameter" /* typeParameterElement */; + case 273 /* EnumMember */: return "enum member" /* enumMemberElement */; + case 149 /* Parameter */: return ts.hasModifier(node, 92 /* ParameterPropertyModifier */) ? "property" /* memberVariableElement */ : "parameter" /* parameterElement */; + case 243 /* ImportEqualsDeclaration */: + case 248 /* ImportSpecifier */: + case 245 /* ImportClause */: + case 252 /* ExportSpecifier */: + case 246 /* NamespaceImport */: + return "alias" /* alias */; + case 200 /* BinaryExpression */: var kind = ts.getSpecialPropertyAssignmentKind(node); var right = node.right; switch (kind) { - case 0: - return ""; - case 1: - case 2: + case 0 /* None */: + return "" /* unknown */; + case 1 /* ExportsProperty */: + case 2 /* ModuleExports */: var rightKind = getNodeKind(right); - return rightKind === "" ? "const" : rightKind; - case 3: - return ts.isFunctionExpression(right) ? "method" : "property"; - case 4: - return "property"; - case 5: - return ts.isFunctionExpression(right) ? "method" : "property"; - case 6: - return "local class"; + return rightKind === "" /* unknown */ ? "const" /* constElement */ : rightKind; + case 3 /* PrototypeProperty */: + return ts.isFunctionExpression(right) ? "method" /* memberFunctionElement */ : "property" /* memberVariableElement */; + case 4 /* ThisProperty */: + return "property" /* memberVariableElement */; // property + case 5 /* Property */: + // static method / property + return ts.isFunctionExpression(right) ? "method" /* memberFunctionElement */ : "property" /* memberVariableElement */; + case 6 /* Prototype */: + return "local class" /* localClassElement */; default: { ts.assertTypeIsNever(kind); - return ""; + return "" /* unknown */; } } default: - return ""; + return "" /* unknown */; } function getKindOfVariableDeclaration(v) { return ts.isConst(v) - ? "const" + ? "const" /* constElement */ : ts.isLet(v) - ? "let" - : "var"; + ? "let" /* letElement */ + : "var" /* variableElement */; } } ts.getNodeKind = getNodeKind; function isThis(node) { switch (node.kind) { - case 99: + case 99 /* ThisKeyword */: + // case SyntaxKind.ThisType: TODO: GH#9267 return true; - case 71: - return ts.identifierIsThisKeyword(node) && node.parent.kind === 149; + case 71 /* Identifier */: + // 'this' as a parameter + return ts.identifierIsThisKeyword(node) && node.parent.kind === 149 /* Parameter */; default: return false; } } ts.isThis = isThis; + // Matches the beginning of a triple slash directive var tripleSlashDirectivePrefixRegex = /^\/\/\/\s*= start and (position < end or (position === end && token is literal or keyword or identifier)) + */ function getTouchingPropertyName(sourceFile, position) { - return getTouchingToken(sourceFile, position, true, function (n) { return ts.isPropertyNameLiteral(n) || ts.isKeyword(n.kind); }); + return getTouchingToken(sourceFile, position, /*includeJsDocComment*/ true, function (n) { return ts.isPropertyNameLiteral(n) || ts.isKeyword(n.kind); }); } ts.getTouchingPropertyName = getTouchingPropertyName; + /** + * Returns the token if position is in [start, end). + * If position === end, returns the preceding token if includeItemAtEndPosition(previousToken) === true + */ function getTouchingToken(sourceFile, position, includeJsDocComment, includePrecedingTokenAtEndPosition) { - return getTokenAtPositionWorker(sourceFile, position, false, includePrecedingTokenAtEndPosition, false, includeJsDocComment); + return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, includePrecedingTokenAtEndPosition, /*includeEndPosition*/ false, includeJsDocComment); } ts.getTouchingToken = getTouchingToken; + /** Returns a token if position is in [start-of-leading-trivia, end) */ function getTokenAtPosition(sourceFile, position, includeJsDocComment, includeEndPosition) { if (includeEndPosition === void 0) { includeEndPosition = false; } - return getTokenAtPositionWorker(sourceFile, position, true, undefined, includeEndPosition, includeJsDocComment); + return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includePrecedingTokenAtEndPosition*/ undefined, includeEndPosition, includeJsDocComment); } ts.getTokenAtPosition = getTokenAtPosition; + /** Get the token whose text contains the position */ function getTokenAtPositionWorker(sourceFile, position, allowPositionInLeadingTrivia, includePrecedingTokenAtEndPosition, includeEndPosition, includeJsDocComment) { var current = sourceFile; outer: while (true) { if (ts.isToken(current)) { + // exit early return current; } + // find the child that contains 'position' for (var _i = 0, _a = current.getChildren(); _i < _a.length; _i++) { var child = _a[_i]; if (!includeJsDocComment && ts.isJSDocNode(child)) { @@ -73324,10 +88025,11 @@ var ts; } var start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile, includeJsDocComment); if (start > position) { + // If this child begins after position, then all subsequent children will as well. break; } var end = child.getEnd(); - if (position < end || (position === end && (child.kind === 1 || includeEndPosition))) { + if (position < end || (position === end && (child.kind === 1 /* EndOfFileToken */ || includeEndPosition))) { current = child; continue outer; } @@ -73341,8 +88043,18 @@ var ts; return current; } } + /** + * The token on the left of the position is the token that strictly includes the position + * or sits to the left of the cursor if it is on a boundary. For example + * + * fo|o -> will return foo + * foo |bar -> will return foo + * + */ function findTokenOnLeftOfPosition(file, position) { - var tokenAtPosition = getTokenAtPosition(file, position, false); + // Ideally, getTokenAtPosition should return a token. However, it is currently + // broken, so we do a check to make sure the result was indeed a token. + var tokenAtPosition = getTokenAtPosition(file, position, /*includeJsDocComment*/ false); if (ts.isToken(tokenAtPosition) && position > tokenAtPosition.getStart(file) && position < tokenAtPosition.getEnd()) { return tokenAtPosition; } @@ -73353,12 +88065,16 @@ var ts; return find(parent); function find(n) { if (ts.isToken(n) && n.pos === previousToken.end) { + // this is token that starts at the end of previous token - return it return n; } var children = n.getChildren(); for (var _i = 0, children_3 = children; _i < children_3.length; _i++) { var child = children_3[_i]; - var shouldDiveInChildNode = (child.pos <= previousToken.pos && child.end > previousToken.end) || + var shouldDiveInChildNode = + // previous token is enclosed somewhere in the child + (child.pos <= previousToken.pos && child.end > previousToken.end) || + // previous token ends exactly at the beginning of child (child.pos === previousToken.end); if (shouldDiveInChildNode && nodeHasTokens(child, sourceFile)) { return find(child); @@ -73368,6 +88084,10 @@ var ts; } } ts.findNextToken = findNextToken; + /** + * Finds the rightmost token satisfying `token.end <= position`, + * excluding `JsxText` tokens containing only whitespace. + */ function findPrecedingToken(position, sourceFile, startNode, includeJsDoc) { var result = find(startNode || sourceFile); ts.Debug.assert(!(result && isWhiteSpaceOnlyJsxText(result))); @@ -73379,23 +88099,34 @@ var ts; var children = n.getChildren(sourceFile); for (var i = 0; i < children.length; i++) { var child = children[i]; + // Note that the span of a node's tokens is [node.getStart(...), node.end). + // Given that `position < child.end` and child has constituent tokens, we distinguish these cases: + // 1) `position` precedes `child`'s tokens or `child` has no tokens (ie: in a comment or whitespace preceding `child`): + // we need to find the last token in a previous child. + // 2) `position` is within the same span: we recurse on `child`. if (position < child.end) { var start = child.getStart(sourceFile, includeJsDoc); - var lookInPreviousChild = (start >= position) || + var lookInPreviousChild = (start >= position) || // cursor in the leading trivia !nodeHasTokens(child, sourceFile) || isWhiteSpaceOnlyJsxText(child); if (lookInPreviousChild) { - var candidate = findRightmostChildNodeWithTokens(children, i, sourceFile); + // actual start of the node is past the position - previous token should be at the end of previous child + var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i, sourceFile); return candidate && findRightmostToken(candidate, sourceFile); } else { + // candidate should be in this node return find(child); } } } - ts.Debug.assert(startNode !== undefined || n.kind === 274 || ts.isJSDocCommentContainingNode(n)); + ts.Debug.assert(startNode !== undefined || n.kind === 274 /* SourceFile */ || ts.isJSDocCommentContainingNode(n)); + // Here we know that none of child token nodes embrace the position, + // the only known case is when position is at the end of the file. + // Try to find the rightmost token in the file without filtering. + // Namely we are skipping the check: 'position < node.end' if (children.length) { - var candidate = findRightmostChildNodeWithTokens(children, children.length, sourceFile); + var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length, sourceFile); return candidate && findRightmostToken(candidate, sourceFile); } } @@ -73409,9 +88140,12 @@ var ts; return n; } var children = n.getChildren(sourceFile); - var candidate = findRightmostChildNodeWithTokens(children, children.length, sourceFile); + var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length, sourceFile); return candidate && findRightmostToken(candidate, sourceFile); } + /** + * Finds the rightmost child to the left of `children[exclusiveStartPosition]` which is a non-all-whitespace token or has constituent tokens. + */ function findRightmostChildNodeWithTokens(children, exclusiveStartPosition, sourceFile) { for (var i = exclusiveStartPosition - 1; i >= 0; i--) { var child = children[i]; @@ -73428,6 +88162,10 @@ var ts; if (previousToken && ts.isStringTextContainingNode(previousToken)) { var start = previousToken.getStart(sourceFile); var end = previousToken.getEnd(); + // To be "in" one of these literals, the position has to be: + // 1. entirely within the token text. + // 2. at the end position of an unterminated token. + // 3. at the end of a regular expression (due to trailing flags like '/foo/g'). if (start < position && position < end) { return true; } @@ -73438,24 +88176,33 @@ var ts; return false; } ts.isInString = isInString; + /** + * returns true if the position is in between the open and close elements of an JSX expression. + */ function isInsideJsxElementOrAttribute(sourceFile, position) { - var token = getTokenAtPosition(sourceFile, position, false); + var token = getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); if (!token) { return false; } - if (token.kind === 10) { + if (token.kind === 10 /* JsxText */) { return true; } - if (token.kind === 27 && token.parent.kind === 10) { + //
Hello |
+ if (token.kind === 27 /* LessThanToken */ && token.parent.kind === 10 /* JsxText */) { return true; } - if (token.kind === 27 && token.parent.kind === 265) { + //
{ |
or
+ if (token.kind === 27 /* LessThanToken */ && token.parent.kind === 265 /* JsxExpression */) { return true; } - if (token && token.kind === 18 && token.parent.kind === 265) { + //
{ + // | + // } < /div> + if (token && token.kind === 18 /* CloseBraceToken */ && token.parent.kind === 265 /* JsxExpression */) { return true; } - if (token.kind === 27 && token.parent.kind === 258) { + //
|
+ if (token.kind === 27 /* LessThanToken */ && token.parent.kind === 258 /* JsxClosingElement */) { return true; } return false; @@ -73465,7 +88212,7 @@ var ts; return ts.isJsxText(node) && node.containsOnlyWhiteSpaces; } function isInTemplateString(sourceFile, position) { - var token = getTokenAtPosition(sourceFile, position, false); + var token = getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); return ts.isTemplateLiteralKind(token.kind) && position > token.getStart(sourceFile); } ts.isInTemplateString = isInTemplateString; @@ -73492,11 +88239,17 @@ var ts; ts.findPrecedingMatchingToken = findPrecedingMatchingToken; function isPossiblyTypeArgumentPosition(tokenIn, sourceFile) { var token = tokenIn; + // This function determines if the node could be type argument position + // Since during editing, when type argument list is not complete, + // the tree could be of any shape depending on the tokens parsed before current node, + // scanning of the previous identifier followed by "<" before current node would give us better result + // Note that we also balance out the already provided type arguments, arrays, object literals while doing so var remainingLessThanTokens = 0; var nTypeArguments = 0; while (token) { switch (token.kind) { - case 27: + case 27 /* LessThanToken */: + // Found the beginning of the generic argument expression token = findPrecedingToken(token.getFullStart(), sourceFile); if (!token || !ts.isIdentifier(token)) return undefined; @@ -73505,51 +88258,59 @@ var ts; } remainingLessThanTokens--; break; - case 47: + case 47 /* GreaterThanGreaterThanGreaterThanToken */: remainingLessThanTokens = +3; break; - case 46: + case 46 /* GreaterThanGreaterThanToken */: remainingLessThanTokens = +2; break; - case 29: + case 29 /* GreaterThanToken */: remainingLessThanTokens++; break; - case 18: - token = findPrecedingMatchingToken(token, 17, sourceFile); + case 18 /* CloseBraceToken */: + // This can be object type, skip until we find the matching open brace token + // Skip until the matching open brace token + token = findPrecedingMatchingToken(token, 17 /* OpenBraceToken */, sourceFile); if (!token) return undefined; break; - case 20: - token = findPrecedingMatchingToken(token, 19, sourceFile); + case 20 /* CloseParenToken */: + // This can be object type, skip until we find the matching open brace token + // Skip until the matching open brace token + token = findPrecedingMatchingToken(token, 19 /* OpenParenToken */, sourceFile); if (!token) return undefined; break; - case 22: - token = findPrecedingMatchingToken(token, 21, sourceFile); + case 22 /* CloseBracketToken */: + // This can be object type, skip until we find the matching open brace token + // Skip until the matching open brace token + token = findPrecedingMatchingToken(token, 21 /* OpenBracketToken */, sourceFile); if (!token) return undefined; break; - case 26: + // Valid tokens in a type name. Skip. + case 26 /* CommaToken */: nTypeArguments++; break; - case 36: - case 71: - case 9: - case 8: - case 101: - case 86: - case 103: - case 85: - case 128: - case 23: - case 49: - case 55: - case 56: + case 36 /* EqualsGreaterThanToken */: + case 71 /* Identifier */: + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: + case 103 /* TypeOfKeyword */: + case 85 /* ExtendsKeyword */: + case 128 /* KeyOfKeyword */: + case 23 /* DotToken */: + case 49 /* BarToken */: + case 55 /* QuestionToken */: + case 56 /* ColonToken */: break; default: if (ts.isTypeNode(token)) { break; } + // Invalid token in type return undefined; } token = findPrecedingToken(token.getFullStart(), sourceFile); @@ -73557,12 +88318,19 @@ var ts; return undefined; } ts.isPossiblyTypeArgumentPosition = isPossiblyTypeArgumentPosition; + /** + * Returns true if the cursor at position in sourceFile is within a comment. + * + * @param tokenAtPosition Must equal `getTokenAtPosition(sourceFile, position) + * @param predicate Additional predicate to test on the comment range. + */ function isInComment(sourceFile, position, tokenAtPosition, predicate) { - return !!ts.formatting.getRangeOfEnclosingComment(sourceFile, position, false, undefined, tokenAtPosition, predicate); + return !!ts.formatting.getRangeOfEnclosingComment(sourceFile, position, /*onlyMultiLine*/ false, /*precedingToken*/ undefined, tokenAtPosition, predicate); } ts.isInComment = isInComment; function hasDocComment(sourceFile, position) { - var token = getTokenAtPosition(sourceFile, position, false); + var token = getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); + // First, we have to see if this position actually landed in a comment. var commentRanges = ts.getLeadingCommentRanges(sourceFile.text, token.pos); return ts.forEach(commentRanges, jsDocPrefix); function jsDocPrefix(c) { @@ -73572,45 +88340,47 @@ var ts; } ts.hasDocComment = hasDocComment; function nodeHasTokens(n, sourceFile) { + // If we have a token or node that has a non-zero width, it must have tokens. + // Note: getWidth() does not take trivia into account. return n.getWidth(sourceFile) !== 0; } function getNodeModifiers(node) { var flags = ts.getCombinedModifierFlags(node); var result = []; - if (flags & 8) - result.push("private"); - if (flags & 16) - result.push("protected"); - if (flags & 4) - result.push("public"); - if (flags & 32) - result.push("static"); - if (flags & 128) - result.push("abstract"); - if (flags & 1) - result.push("export"); - if (node.flags & 4194304) - result.push("declare"); - return result.length > 0 ? result.join(",") : ""; + if (flags & 8 /* Private */) + result.push("private" /* privateMemberModifier */); + if (flags & 16 /* Protected */) + result.push("protected" /* protectedMemberModifier */); + if (flags & 4 /* Public */) + result.push("public" /* publicMemberModifier */); + if (flags & 32 /* Static */) + result.push("static" /* staticModifier */); + if (flags & 128 /* Abstract */) + result.push("abstract" /* abstractModifier */); + if (flags & 1 /* Export */) + result.push("export" /* exportedModifier */); + if (node.flags & 4194304 /* Ambient */) + result.push("declare" /* ambientModifier */); + return result.length > 0 ? result.join(",") : "" /* none */; } ts.getNodeModifiers = getNodeModifiers; function getTypeArgumentOrTypeParameterList(node) { - if (node.kind === 162 || node.kind === 187) { + if (node.kind === 162 /* TypeReference */ || node.kind === 187 /* CallExpression */) { return node.typeArguments; } - if (ts.isFunctionLike(node) || node.kind === 235 || node.kind === 236) { + if (ts.isFunctionLike(node) || node.kind === 235 /* ClassDeclaration */ || node.kind === 236 /* InterfaceDeclaration */) { return node.typeParameters; } return undefined; } ts.getTypeArgumentOrTypeParameterList = getTypeArgumentOrTypeParameterList; function isComment(kind) { - return kind === 2 || kind === 3; + return kind === 2 /* SingleLineCommentTrivia */ || kind === 3 /* MultiLineCommentTrivia */; } ts.isComment = isComment; function isStringOrRegularExpressionOrTemplateLiteral(kind) { - if (kind === 9 - || kind === 12 + if (kind === 9 /* StringLiteral */ + || kind === 12 /* RegularExpressionLiteral */ || ts.isTemplateLiteralKind(kind)) { return true; } @@ -73618,7 +88388,7 @@ var ts; } ts.isStringOrRegularExpressionOrTemplateLiteral = isStringOrRegularExpressionOrTemplateLiteral; function isPunctuation(kind) { - return 17 <= kind && kind <= 70; + return 17 /* FirstPunctuation */ <= kind && kind <= 70 /* LastPunctuation */; } ts.isPunctuation = isPunctuation; function isInsideTemplateLiteral(node, position, sourceFile) { @@ -73628,9 +88398,9 @@ var ts; ts.isInsideTemplateLiteral = isInsideTemplateLiteral; function isAccessibilityModifier(kind) { switch (kind) { - case 114: - case 112: - case 113: + case 114 /* PublicKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: return true; } return false; @@ -73643,18 +88413,26 @@ var ts; } ts.cloneCompilerOptions = cloneCompilerOptions; function isArrayLiteralOrObjectLiteralDestructuringPattern(node) { - if (node.kind === 183 || - node.kind === 184) { - if (node.parent.kind === 200 && + if (node.kind === 183 /* ArrayLiteralExpression */ || + node.kind === 184 /* ObjectLiteralExpression */) { + // [a,b,c] from: + // [a, b, c] = someExpression; + if (node.parent.kind === 200 /* BinaryExpression */ && node.parent.left === node && - node.parent.operatorToken.kind === 58) { + node.parent.operatorToken.kind === 58 /* EqualsToken */) { return true; } - if (node.parent.kind === 222 && + // [a, b, c] from: + // for([a, b, c] of expression) + if (node.parent.kind === 222 /* ForOfStatement */ && node.parent.initializer === node) { return true; } - if (isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.kind === 270 ? node.parent.parent : node.parent)) { + // [a, b, c] of + // [x, [a, b, c] ] = someExpression + // or + // {x, a: {a, b, c} } = someExpression + if (isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.kind === 270 /* PropertyAssignment */ ? node.parent.parent : node.parent)) { return true; } } @@ -73662,14 +88440,14 @@ var ts; } ts.isArrayLiteralOrObjectLiteralDestructuringPattern = isArrayLiteralOrObjectLiteralDestructuringPattern; function isInReferenceComment(sourceFile, position) { - return isInComment(sourceFile, position, undefined, function (c) { + return isInComment(sourceFile, position, /*tokenAtPosition*/ undefined, function (c) { var commentText = sourceFile.text.substring(c.pos, c.end); return tripleSlashDirectivePrefixRegex.test(commentText); }); } ts.isInReferenceComment = isInReferenceComment; function isInNonReferenceComment(sourceFile, position) { - return isInComment(sourceFile, position, undefined, function (c) { + return isInComment(sourceFile, position, /*tokenAtPosition*/ undefined, function (c) { var commentText = sourceFile.text.substring(c.pos, c.end); return !tripleSlashDirectivePrefixRegex.test(commentText); }); @@ -73696,27 +88474,28 @@ var ts; } ts.createTextChange = createTextChange; ts.typeKeywords = [ - 119, - 122, - 128, - 131, - 95, - 134, - 135, - 137, - 138, - 105, - 140, - 141, - 142, + 119 /* AnyKeyword */, + 122 /* BooleanKeyword */, + 128 /* KeyOfKeyword */, + 131 /* NeverKeyword */, + 95 /* NullKeyword */, + 134 /* NumberKeyword */, + 135 /* ObjectKeyword */, + 137 /* StringKeyword */, + 138 /* SymbolKeyword */, + 105 /* VoidKeyword */, + 140 /* UndefinedKeyword */, + 141 /* UniqueKeyword */, + 142 /* UnknownKeyword */, ]; function isTypeKeyword(kind) { return ts.contains(ts.typeKeywords, kind); } ts.isTypeKeyword = isTypeKeyword; + /** True if the symbol is for an external module, as opposed to a namespace. */ function isExternalModuleSymbol(moduleSymbol) { - ts.Debug.assert(!!(moduleSymbol.flags & 1536)); - return moduleSymbol.name.charCodeAt(0) === 34; + ts.Debug.assert(!!(moduleSymbol.flags & 1536 /* Module */)); + return moduleSymbol.name.charCodeAt(0) === 34 /* doubleQuote */; } ts.isExternalModuleSymbol = isExternalModuleSymbol; function nodeSeenTracker() { @@ -73740,11 +88519,12 @@ var ts; } ts.repeatString = repeatString; function skipConstraint(type) { - return type.isTypeParameter() ? type.getConstraint() : type; + return type.isTypeParameter() ? type.getConstraint() : type; // TODO: GH#18217 } ts.skipConstraint = skipConstraint; function getNameFromPropertyName(name) { - return name.kind === 147 + return name.kind === 147 /* ComputedPropertyName */ + // treat computed property names where expression is string/numeric literal as just string/numeric literal ? ts.isStringOrNumericLiteral(name.expression) ? name.expression.text : undefined : ts.getTextOfIdentifierOrLiteral(name); } @@ -73754,7 +88534,7 @@ var ts; } ts.programContainsEs6Modules = programContainsEs6Modules; function compilerOptionsIndicateEs6Modules(compilerOptions) { - return !!compilerOptions.module || compilerOptions.target >= 2 || !!compilerOptions.noEmit; + return !!compilerOptions.module || compilerOptions.target >= 2 /* ES2015 */ || !!compilerOptions.noEmit; } ts.compilerOptionsIndicateEs6Modules = compilerOptionsIndicateEs6Modules; function hostUsesCaseSensitiveFileNames(host) { @@ -73770,13 +88550,15 @@ var ts; } ts.makeImportIfNecessary = makeImportIfNecessary; function makeImport(defaultImport, namedImports, moduleSpecifier, quotePreference) { - return ts.createImportDeclaration(undefined, undefined, defaultImport || namedImports + return ts.createImportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, defaultImport || namedImports ? ts.createImportClause(defaultImport, namedImports && namedImports.length ? ts.createNamedImports(namedImports) : undefined) : undefined, typeof moduleSpecifier === "string" ? makeStringLiteral(moduleSpecifier, quotePreference) : moduleSpecifier); } ts.makeImport = makeImport; function makeStringLiteral(text, quotePreference) { - return ts.createLiteral(text, quotePreference === 0); + return ts.createLiteral(text, quotePreference === 0 /* Single */); } ts.makeStringLiteral = makeStringLiteral; var QuotePreference; @@ -73786,11 +88568,11 @@ var ts; })(QuotePreference = ts.QuotePreference || (ts.QuotePreference = {})); function getQuotePreference(sourceFile, preferences) { if (preferences.quotePreference) { - return preferences.quotePreference === "single" ? 0 : 1; + return preferences.quotePreference === "single" ? 0 /* Single */ : 1 /* Double */; } else { var firstModuleSpecifier = ts.firstOrUndefined(sourceFile.imports); - return !!firstModuleSpecifier && !ts.isStringDoubleQuoted(firstModuleSpecifier, sourceFile) ? 0 : 1; + return !!firstModuleSpecifier && !ts.isStringDoubleQuoted(firstModuleSpecifier, sourceFile) ? 0 /* Single */ : 1 /* Double */; } } ts.getQuotePreference = getQuotePreference; @@ -73800,34 +88582,48 @@ var ts; } ts.symbolNameNoDefault = symbolNameNoDefault; function symbolEscapedNameNoDefault(symbol) { - if (symbol.escapedName !== "default") { + if (symbol.escapedName !== "default" /* Default */) { return symbol.escapedName; } return ts.firstDefined(symbol.declarations, function (decl) { var name = ts.getNameOfDeclaration(decl); - return name && name.kind === 71 ? name.escapedText : undefined; + return name && name.kind === 71 /* Identifier */ ? name.escapedText : undefined; }); } ts.symbolEscapedNameNoDefault = symbolEscapedNameNoDefault; function getPropertySymbolFromBindingElement(checker, bindingElement) { var typeOfPattern = checker.getTypeAtLocation(bindingElement.parent); var propSymbol = typeOfPattern && checker.getPropertyOfType(typeOfPattern, bindingElement.name.text); - if (propSymbol && propSymbol.flags & 98304) { - ts.Debug.assert(!!(propSymbol.flags & 33554432)); + if (propSymbol && propSymbol.flags & 98304 /* Accessor */) { + // See GH#16922 + ts.Debug.assert(!!(propSymbol.flags & 33554432 /* Transient */)); return propSymbol.target; } return propSymbol; } ts.getPropertySymbolFromBindingElement = getPropertySymbolFromBindingElement; + /** + * Find symbol of the given property-name and add the symbol to the given result array + * @param symbol a symbol to start searching for the given propertyName + * @param propertyName a name of property to search for + * @param result an array of symbol of found property symbols + * @param previousIterationSymbolsCache a cache of symbol from previous iterations of calling this function to prevent infinite revisiting of the same symbol. + * The value of previousIterationSymbol is undefined when the function is first called. + */ function getPropertySymbolsFromBaseTypes(symbol, propertyName, checker, cb) { var seen = ts.createMap(); return recur(symbol); function recur(symbol) { - if (!(symbol.flags & (32 | 64)) || !ts.addToSeen(seen, ts.getSymbolId(symbol))) + // Use `addToSeen` to ensure we don't infinitely recurse in this situation: + // interface C extends C { + // /*findRef*/propName: string; + // } + if (!(symbol.flags & (32 /* Class */ | 64 /* Interface */)) || !ts.addToSeen(seen, ts.getSymbolId(symbol))) return; return ts.firstDefined(symbol.declarations, function (declaration) { return ts.firstDefined(ts.getAllSuperTypeNodes(declaration), function (typeReference) { var type = checker.getTypeAtLocation(typeReference); var propertySymbol = type && type.symbol && checker.getPropertyOfType(type, propertyName); + // Visit the typeReference as well to see if it directly or indirectly uses that property return type && propertySymbol && (ts.firstDefined(checker.getRootSymbols(propertySymbol), cb) || recur(type.symbol)); }); }); } @@ -73837,7 +88633,7 @@ var ts; return getPropertySymbolsFromBaseTypes(memberSymbol.parent, memberSymbol.name, checker, function (_) { return true; }) || false; } ts.isMemberSymbolInBaseType = isMemberSymbolInBaseType; - var NodeSet = (function () { + var NodeSet = /** @class */ (function () { function NodeSet() { this.map = ts.createMap(); } @@ -73871,20 +88667,23 @@ var ts; return ts.textSpanContainsPosition(span, node.getStart(file)) && node.getEnd() <= ts.textSpanEnd(span); } + /* @internal */ function insertImport(changes, sourceFile, importDecl) { var lastImportDeclaration = ts.findLast(sourceFile.statements, ts.isAnyImportSyntax); if (lastImportDeclaration) { changes.insertNodeAfter(sourceFile, lastImportDeclaration, importDecl); } else { - changes.insertNodeAtTopOfFile(sourceFile, importDecl, true); + changes.insertNodeAtTopOfFile(sourceFile, importDecl, /*blankLineBetween*/ true); } } ts.insertImport = insertImport; })(ts || (ts = {})); +// Display-part writer helpers +/* @internal */ (function (ts) { function isFirstDeclarationOfSymbolParameter(symbol) { - return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === 149; + return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === 149 /* Parameter */; } ts.isFirstDeclarationOfSymbolParameter = isFirstDeclarationOfSymbolParameter; var displayPartWriter = getDisplayPartWriter(); @@ -73954,46 +88753,46 @@ var ts; return displayPart(text, displayPartKind(symbol)); function displayPartKind(symbol) { var flags = symbol.flags; - if (flags & 3) { + if (flags & 3 /* Variable */) { return isFirstDeclarationOfSymbolParameter(symbol) ? ts.SymbolDisplayPartKind.parameterName : ts.SymbolDisplayPartKind.localName; } - else if (flags & 4) { + else if (flags & 4 /* Property */) { return ts.SymbolDisplayPartKind.propertyName; } - else if (flags & 32768) { + else if (flags & 32768 /* GetAccessor */) { return ts.SymbolDisplayPartKind.propertyName; } - else if (flags & 65536) { + else if (flags & 65536 /* SetAccessor */) { return ts.SymbolDisplayPartKind.propertyName; } - else if (flags & 8) { + else if (flags & 8 /* EnumMember */) { return ts.SymbolDisplayPartKind.enumMemberName; } - else if (flags & 16) { + else if (flags & 16 /* Function */) { return ts.SymbolDisplayPartKind.functionName; } - else if (flags & 32) { + else if (flags & 32 /* Class */) { return ts.SymbolDisplayPartKind.className; } - else if (flags & 64) { + else if (flags & 64 /* Interface */) { return ts.SymbolDisplayPartKind.interfaceName; } - else if (flags & 384) { + else if (flags & 384 /* Enum */) { return ts.SymbolDisplayPartKind.enumName; } - else if (flags & 1536) { + else if (flags & 1536 /* Module */) { return ts.SymbolDisplayPartKind.moduleName; } - else if (flags & 8192) { + else if (flags & 8192 /* Method */) { return ts.SymbolDisplayPartKind.methodName; } - else if (flags & 262144) { + else if (flags & 262144 /* TypeParameter */) { return ts.SymbolDisplayPartKind.typeParameterName; } - else if (flags & 524288) { + else if (flags & 524288 /* TypeAlias */) { return ts.SymbolDisplayPartKind.aliasName; } - else if (flags & 2097152) { + else if (flags & 2097152 /* Alias */) { return ts.SymbolDisplayPartKind.aliasName; } return ts.SymbolDisplayPartKind.text; @@ -74032,6 +88831,9 @@ var ts; } ts.textPart = textPart; var carriageReturnLineFeed = "\r\n"; + /** + * The default is CRLF. + */ function getNewLineOrDefaultFromHost(host, formatSettings) { return (formatSettings && formatSettings.newLineCharacter) || (host.getNewLine && host.getNewLine()) || @@ -74042,6 +88844,7 @@ var ts; return displayPart("\n", ts.SymbolDisplayPartKind.lineBreak); } ts.lineBreakPart = lineBreakPart; + /* @internal */ function mapToDisplayParts(writeDisplayParts) { try { writeDisplayParts(displayPartWriter); @@ -74053,33 +88856,38 @@ var ts; } ts.mapToDisplayParts = mapToDisplayParts; function typeToDisplayParts(typechecker, type, enclosingDeclaration, flags) { - if (flags === void 0) { flags = 0; } + if (flags === void 0) { flags = 0 /* None */; } return mapToDisplayParts(function (writer) { - typechecker.writeType(type, enclosingDeclaration, flags | 1024 | 16384, writer); + typechecker.writeType(type, enclosingDeclaration, flags | 1024 /* MultilineObjectLiterals */ | 16384 /* UseAliasDefinedOutsideCurrentScope */, writer); }); } ts.typeToDisplayParts = typeToDisplayParts; function symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration, meaning, flags) { - if (flags === void 0) { flags = 0; } + if (flags === void 0) { flags = 0 /* None */; } return mapToDisplayParts(function (writer) { - typeChecker.writeSymbol(symbol, enclosingDeclaration, meaning, flags | 8, writer); + typeChecker.writeSymbol(symbol, enclosingDeclaration, meaning, flags | 8 /* UseAliasDefinedOutsideCurrentScope */, writer); }); } ts.symbolToDisplayParts = symbolToDisplayParts; function signatureToDisplayParts(typechecker, signature, enclosingDeclaration, flags) { - if (flags === void 0) { flags = 0; } - flags |= 16384 | 1024 | 32 | 8192; + if (flags === void 0) { flags = 0 /* None */; } + flags |= 16384 /* UseAliasDefinedOutsideCurrentScope */ | 1024 /* MultilineObjectLiterals */ | 32 /* WriteTypeArgumentsOfSignature */ | 8192 /* OmitParameterModifiers */; return mapToDisplayParts(function (writer) { - typechecker.writeSignature(signature, enclosingDeclaration, flags, undefined, writer); + typechecker.writeSignature(signature, enclosingDeclaration, flags, /*signatureKind*/ undefined, writer); }); } ts.signatureToDisplayParts = signatureToDisplayParts; function isImportOrExportSpecifierName(location) { return !!location.parent && - (location.parent.kind === 248 || location.parent.kind === 252) && + (location.parent.kind === 248 /* ImportSpecifier */ || location.parent.kind === 252 /* ExportSpecifier */) && location.parent.propertyName === location; } ts.isImportOrExportSpecifierName = isImportOrExportSpecifierName; + /** + * Strip off existed single quotes or double quotes from a given string + * + * @return non-quoted string + */ function stripQuotes(name) { var length = name.length; if (length >= 2 && name.charCodeAt(0) === name.charCodeAt(length - 1) && startsWithQuote(name)) { @@ -74102,6 +88910,8 @@ var ts; } ts.scriptKindIs = scriptKindIs; function getScriptKind(fileName, host) { + // First check to see if the script kind was specified by the host. Chances are the host + // may override the default script kind for the file extension. return ts.ensureScriptKind(fileName, host && host.getScriptKind && host.getScriptKind(fileName)); } ts.getScriptKind = getScriptKind; @@ -74116,6 +88926,12 @@ var ts; return position; } ts.getFirstNonSpaceCharacterPosition = getFirstNonSpaceCharacterPosition; + /** + * Creates a deep, memberwise clone of a node with no source map location. + * + * WARNING: This is an expensive operation and is only intended to be used in refactorings + * and code fixes (because those are triggered by explicit user actions). + */ function getSynthesizedDeepClone(node, includeTrivia) { if (includeTrivia === void 0) { includeTrivia = true; } var clone = node && getSynthesizedDeepCloneWorker(node); @@ -74127,6 +88943,7 @@ var ts; function getSynthesizedDeepCloneWorker(node) { var visited = ts.visitEachChild(node, getSynthesizedDeepClone, ts.nullTransformationContext); if (visited === node) { + // This only happens for leaf nodes - internal nodes always see their children change. var clone_7 = ts.getSynthesizedClone(node); if (ts.isStringLiteral(clone_7)) { clone_7.textSourceNode = node; @@ -74136,6 +88953,9 @@ var ts; } return ts.setTextRange(clone_7, node); } + // PERF: As an optimization, rather than calling getSynthesizedClone, we'll update + // the new node created by visitEachChild with the extra changes getSynthesizedClone + // would have made. visited.parent = undefined; return visited; } @@ -74144,17 +88964,29 @@ var ts; return nodes && ts.createNodeArray(nodes.map(function (n) { return getSynthesizedDeepClone(n, includeTrivia); }), nodes.hasTrailingComma); } ts.getSynthesizedDeepClones = getSynthesizedDeepClones; + /** + * Sets EmitFlags to suppress leading and trailing trivia on the node. + */ + /* @internal */ function suppressLeadingAndTrailingTrivia(node) { suppressLeadingTrivia(node); suppressTrailingTrivia(node); } ts.suppressLeadingAndTrailingTrivia = suppressLeadingAndTrailingTrivia; + /** + * Sets EmitFlags to suppress leading trivia on the node. + */ + /* @internal */ function suppressLeadingTrivia(node) { - addEmitFlagsRecursively(node, 512, getFirstChild); + addEmitFlagsRecursively(node, 512 /* NoLeadingComments */, getFirstChild); } ts.suppressLeadingTrivia = suppressLeadingTrivia; + /** + * Sets EmitFlags to suppress trailing trivia on the node. + */ + /* @internal */ function suppressTrailingTrivia(node) { - addEmitFlagsRecursively(node, 1024, ts.getLastChild); + addEmitFlagsRecursively(node, 1024 /* NoTrailingComments */, ts.getLastChild); } ts.suppressTrailingTrivia = suppressTrailingTrivia; function addEmitFlagsRecursively(node, flag, getChild) { @@ -74166,6 +88998,7 @@ var ts; function getFirstChild(node) { return node.forEachChild(function (child) { return child; }); } + /* @internal */ function getUniqueName(baseName, sourceFile) { var nameText = baseName; for (var i = 1; !ts.isFileLevelUniqueName(sourceFile, nameText); i++) { @@ -74174,6 +89007,12 @@ var ts; return nameText; } ts.getUniqueName = getUniqueName; + /** + * @return The index of the (only) reference to the extracted symbol. We want the cursor + * to be on the reference, rather than the declaration, because it's closer to where the + * user was before extracting it. + */ + /* @internal */ function getRenameLocation(edits, renameFilename, name, preferLastLocation) { var delta = 0; var lastPos = -1; @@ -74186,6 +89025,7 @@ var ts; var index = indexInTextChange(newText, name); if (index !== -1) { lastPos = span.start + delta + index; + // If the reference comes first, return immediately. if (!preferLastLocation) { return lastPos; } @@ -74193,6 +89033,7 @@ var ts; delta += newText.length - span.length; } } + // If the declaration comes first, return the position of the last occurrence. ts.Debug.assert(preferLastLocation); ts.Debug.assert(lastPos >= 0); return lastPos; @@ -74200,11 +89041,14 @@ var ts; ts.getRenameLocation = getRenameLocation; function copyComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) { ts.forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, function (pos, end, kind, htnl) { - if (kind === 3) { + if (kind === 3 /* MultiLineCommentTrivia */) { + // Remove leading /* pos += 2; + // Remove trailing */ end -= 2; } else { + // Remove leading // pos += 2; } ts.addSyntheticLeadingComment(targetNode, commentKind || kind, sourceFile.text.slice(pos, end), hasTrailingNewLine !== undefined ? hasTrailingNewLine : htnl); @@ -74214,6 +89058,7 @@ var ts; function indexInTextChange(change, name) { if (ts.startsWith(change, name)) return 0; + // Add a " " to avoid references inside words var idx = change.indexOf(" " + name); if (idx === -1) idx = change.indexOf("." + name); @@ -74225,23 +89070,64 @@ var ts; var ts; (function (ts) { function createClassifier() { - var scanner = ts.createScanner(6, false); + var scanner = ts.createScanner(6 /* Latest */, /*skipTrivia*/ false); function getClassificationsForLine(text, lexState, syntacticClassifierAbsent) { return convertClassificationsToResult(getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent), text); } + // If there is a syntactic classifier ('syntacticClassifierAbsent' is false), + // we will be more conservative in order to avoid conflicting with the syntactic classifier. function getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent) { - var token = 0; - var lastNonTriviaToken = 0; + var token = 0 /* Unknown */; + var lastNonTriviaToken = 0 /* Unknown */; + // Just a stack of TemplateHeads and OpenCurlyBraces, used to perform rudimentary (inexact) + // classification on template strings. Because of the context free nature of templates, + // the only precise way to classify a template portion would be by propagating the stack across + // lines, just as we do with the end-of-line state. However, this is a burden for implementers, + // and the behavior is entirely subsumed by the syntactic classifier anyway, so we instead + // flatten any nesting when the template stack is non-empty and encode it in the end-of-line state. + // Situations in which this fails are + // 1) When template strings are nested across different lines: + // `hello ${ `world + // ` }` + // + // Where on the second line, you will get the closing of a template, + // a closing curly, and a new template. + // + // 2) When substitution expressions have curly braces and the curly brace falls on the next line: + // `hello ${ () => { + // return "world" } } ` + // + // Where on the second line, you will get the 'return' keyword, + // a string literal, and a template end consisting of '} } `'. var templateStack = []; var _a = getPrefixFromLexState(lexState), prefix = _a.prefix, pushTemplate = _a.pushTemplate; text = prefix + text; var offset = prefix.length; if (pushTemplate) { - templateStack.push(14); + templateStack.push(14 /* TemplateHead */); } scanner.setText(text); - var endOfLineState = 0; + var endOfLineState = 0 /* None */; var spans = []; + // We can run into an unfortunate interaction between the lexical and syntactic classifier + // when the user is typing something generic. Consider the case where the user types: + // + // Foo tokens. It's a weak heuristic, but should + // work well enough in practice. var angleBracketStack = 0; do { token = scanner.scan(); @@ -74257,56 +89143,68 @@ var ts; endOfLineState = end_1; } } - } while (token !== 1); + } while (token !== 1 /* EndOfFileToken */); function handleToken() { switch (token) { - case 41: - case 63: - if (!noRegexTable[lastNonTriviaToken] && scanner.reScanSlashToken() === 12) { - token = 12; + case 41 /* SlashToken */: + case 63 /* SlashEqualsToken */: + if (!noRegexTable[lastNonTriviaToken] && scanner.reScanSlashToken() === 12 /* RegularExpressionLiteral */) { + token = 12 /* RegularExpressionLiteral */; } break; - case 27: - if (lastNonTriviaToken === 71) { + case 27 /* LessThanToken */: + if (lastNonTriviaToken === 71 /* Identifier */) { + // Could be the start of something generic. Keep track of that by bumping + // up the current count of generic contexts we may be in. angleBracketStack++; } break; - case 29: + case 29 /* GreaterThanToken */: if (angleBracketStack > 0) { + // If we think we're currently in something generic, then mark that that + // generic entity is complete. angleBracketStack--; } break; - case 119: - case 137: - case 134: - case 122: - case 138: + case 119 /* AnyKeyword */: + case 137 /* StringKeyword */: + case 134 /* NumberKeyword */: + case 122 /* BooleanKeyword */: + case 138 /* SymbolKeyword */: if (angleBracketStack > 0 && !syntacticClassifierAbsent) { - token = 71; + // If it looks like we're could be in something generic, don't classify this + // as a keyword. We may just get overwritten by the syntactic classifier, + // causing a noisy experience for the user. + token = 71 /* Identifier */; } break; - case 14: + case 14 /* TemplateHead */: templateStack.push(token); break; - case 17: + case 17 /* OpenBraceToken */: + // If we don't have anything on the template stack, + // then we aren't trying to keep track of a previously scanned template head. if (templateStack.length > 0) { templateStack.push(token); } break; - case 18: + case 18 /* CloseBraceToken */: + // If we don't have anything on the template stack, + // then we aren't trying to keep track of a previously scanned template head. if (templateStack.length > 0) { var lastTemplateStackToken = ts.lastOrUndefined(templateStack); - if (lastTemplateStackToken === 14) { + if (lastTemplateStackToken === 14 /* TemplateHead */) { token = scanner.reScanTemplateToken(); - if (token === 16) { + // Only pop on a TemplateTail; a TemplateMiddle indicates there is more for us. + if (token === 16 /* TemplateTail */) { templateStack.pop(); } else { - ts.Debug.assertEqual(token, 15, "Should have been a template middle."); + ts.Debug.assertEqual(token, 15 /* TemplateMiddle */, "Should have been a template middle."); } } else { - ts.Debug.assertEqual(lastTemplateStackToken, 17, "Should have been an open brace"); + ts.Debug.assertEqual(lastTemplateStackToken, 17 /* OpenBraceToken */, "Should have been an open brace"); templateStack.pop(); } } @@ -74315,11 +89213,15 @@ var ts; if (!ts.isKeyword(token)) { break; } - if (lastNonTriviaToken === 23) { - token = 71; + if (lastNonTriviaToken === 23 /* DotToken */) { + token = 71 /* Identifier */; } else if (ts.isKeyword(lastNonTriviaToken) && ts.isKeyword(token) && !canFollow(lastNonTriviaToken, token)) { - token = 71; + // We have two keywords in a row. Only treat the second as a keyword if + // it's a sequence that could legally occur in the language. Otherwise + // treat it as an identifier. This way, if someone writes "private var" + // we recognize that 'var' is actually an identifier here. + token = 71 /* Identifier */; } } } @@ -74328,63 +89230,75 @@ var ts; return { getClassificationsForLine: getClassificationsForLine, getEncodedLexicalClassifications: getEncodedLexicalClassifications }; } ts.createClassifier = createClassifier; + /// We do not have a full parser support to know when we should parse a regex or not + /// If we consider every slash token to be a regex, we could be missing cases like "1/2/3", where + /// we have a series of divide operator. this list allows us to be more accurate by ruling out + /// locations where a regexp cannot exist. var noRegexTable = ts.arrayToNumericMap([ - 71, - 9, - 8, - 12, - 99, - 43, - 44, - 20, - 22, - 18, - 101, - 86, + 71 /* Identifier */, + 9 /* StringLiteral */, + 8 /* NumericLiteral */, + 12 /* RegularExpressionLiteral */, + 99 /* ThisKeyword */, + 43 /* PlusPlusToken */, + 44 /* MinusMinusToken */, + 20 /* CloseParenToken */, + 22 /* CloseBracketToken */, + 18 /* CloseBraceToken */, + 101 /* TrueKeyword */, + 86 /* FalseKeyword */, ], function (token) { return token; }, function () { return true; }); function getNewEndOfLineState(scanner, token, lastOnTemplateStack) { switch (token) { - case 9: { + case 9 /* StringLiteral */: { + // Check to see if we finished up on a multiline string literal. if (!scanner.isUnterminated()) return undefined; var tokenText = scanner.getTokenText(); var lastCharIndex = tokenText.length - 1; var numBackslashes = 0; - while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === 92) { + while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === 92 /* backslash */) { numBackslashes++; } + // If we have an odd number of backslashes, then the multiline string is unclosed if ((numBackslashes & 1) === 0) return undefined; - return tokenText.charCodeAt(0) === 34 ? 3 : 2; + return tokenText.charCodeAt(0) === 34 /* doubleQuote */ ? 3 /* InDoubleQuoteStringLiteral */ : 2 /* InSingleQuoteStringLiteral */; } - case 3: - return scanner.isUnterminated() ? 1 : undefined; + case 3 /* MultiLineCommentTrivia */: + // Check to see if the multiline comment was unclosed. + return scanner.isUnterminated() ? 1 /* InMultiLineCommentTrivia */ : undefined; default: if (ts.isTemplateLiteralKind(token)) { if (!scanner.isUnterminated()) { return undefined; } switch (token) { - case 16: - return 5; - case 13: - return 4; + case 16 /* TemplateTail */: + return 5 /* InTemplateMiddleOrTail */; + case 13 /* NoSubstitutionTemplateLiteral */: + return 4 /* InTemplateHeadOrNoSubstitutionTemplate */; default: return ts.Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token); } } - return lastOnTemplateStack === 14 ? 6 : undefined; + return lastOnTemplateStack === 14 /* TemplateHead */ ? 6 /* InTemplateSubstitutionPosition */ : undefined; } } function pushEncodedClassification(start, end, offset, classification, result) { - if (classification === 8) { + if (classification === 8 /* whiteSpace */) { + // Don't bother with whitespace classifications. They're not needed. return; } if (start === 0 && offset > 0) { + // We're classifying the first token, and this was a case where we prepended text. + // We should consider the start of this token to be at the start of the original text. start += offset; } var length = end - start; if (length > 0) { + // All our tokens are in relation to the augmented text. Move them back to be + // relative to the original text. result.push(start - offset, length, classification); } } @@ -74396,6 +89310,7 @@ var ts; var start = dense[i]; var length_5 = dense[i + 1]; var type = dense[i + 2]; + // Make a whitespace entry between the last item and this one. if (lastEnd >= 0) { var whitespaceLength_1 = start - lastEnd; if (whitespaceLength_1 > 0) { @@ -74413,56 +89328,64 @@ var ts; } function convertClassification(type) { switch (type) { - case 1: return ts.TokenClass.Comment; - case 3: return ts.TokenClass.Keyword; - case 4: return ts.TokenClass.NumberLiteral; - case 5: return ts.TokenClass.Operator; - case 6: return ts.TokenClass.StringLiteral; - case 8: return ts.TokenClass.Whitespace; - case 10: return ts.TokenClass.Punctuation; - case 2: - case 11: - case 12: - case 13: - case 14: - case 15: - case 16: - case 9: - case 17: + case 1 /* comment */: return ts.TokenClass.Comment; + case 3 /* keyword */: return ts.TokenClass.Keyword; + case 4 /* numericLiteral */: return ts.TokenClass.NumberLiteral; + case 5 /* operator */: return ts.TokenClass.Operator; + case 6 /* stringLiteral */: return ts.TokenClass.StringLiteral; + case 8 /* whiteSpace */: return ts.TokenClass.Whitespace; + case 10 /* punctuation */: return ts.TokenClass.Punctuation; + case 2 /* identifier */: + case 11 /* className */: + case 12 /* enumName */: + case 13 /* interfaceName */: + case 14 /* moduleName */: + case 15 /* typeParameterName */: + case 16 /* typeAliasName */: + case 9 /* text */: + case 17 /* parameterName */: return ts.TokenClass.Identifier; default: - return undefined; + return undefined; // TODO: GH#18217 Debug.assertNever(type); } } + /** Returns true if 'keyword2' can legally follow 'keyword1' in any language construct. */ function canFollow(keyword1, keyword2) { if (!ts.isAccessibilityModifier(keyword1)) { + // Assume any other keyword combination is legal. + // This can be refined in the future if there are more cases we want the classifier to be better at. return true; } switch (keyword2) { - case 125: - case 136: - case 123: - case 115: - return true; + case 125 /* GetKeyword */: + case 136 /* SetKeyword */: + case 123 /* ConstructorKeyword */: + case 115 /* StaticKeyword */: + return true; // Allow things like "public get", "public constructor" and "public static". default: - return false; + return false; // Any other keyword following "public" is actually an identifier, not a real keyword. } } function getPrefixFromLexState(lexState) { + // If we're in a string literal, then prepend: "\ + // (and a newline). That way when we lex we'll think we're still in a string literal. + // + // If we're in a multiline comment, then prepend: /* + // (and a newline). That way when we lex we'll think we're still in a multiline comment. switch (lexState) { - case 3: + case 3 /* InDoubleQuoteStringLiteral */: return { prefix: "\"\\\n" }; - case 2: + case 2 /* InSingleQuoteStringLiteral */: return { prefix: "'\\\n" }; - case 1: + case 1 /* InMultiLineCommentTrivia */: return { prefix: "/*\n" }; - case 4: + case 4 /* InTemplateHeadOrNoSubstitutionTemplate */: return { prefix: "`\n" }; - case 5: + case 5 /* InTemplateMiddleOrTail */: return { prefix: "}\n", pushTemplate: true }; - case 6: + case 6 /* InTemplateSubstitutionPosition */: return { prefix: "", pushTemplate: true }; - case 0: + case 0 /* None */: return { prefix: "" }; default: return ts.Debug.assertNever(lexState); @@ -74470,43 +89393,43 @@ var ts; } function isBinaryExpressionOperatorToken(token) { switch (token) { - case 39: - case 41: - case 42: - case 37: - case 38: - case 45: - case 46: - case 47: - case 27: - case 29: - case 30: - case 31: - case 93: - case 92: - case 118: - case 32: - case 33: - case 34: - case 35: - case 48: - case 50: - case 49: - case 53: - case 54: - case 69: - case 68: - case 70: - case 65: - case 66: - case 67: - case 59: - case 60: - case 61: - case 63: - case 64: - case 58: - case 26: + case 39 /* AsteriskToken */: + case 41 /* SlashToken */: + case 42 /* PercentToken */: + case 37 /* PlusToken */: + case 38 /* MinusToken */: + case 45 /* LessThanLessThanToken */: + case 46 /* GreaterThanGreaterThanToken */: + case 47 /* GreaterThanGreaterThanGreaterThanToken */: + case 27 /* LessThanToken */: + case 29 /* GreaterThanToken */: + case 30 /* LessThanEqualsToken */: + case 31 /* GreaterThanEqualsToken */: + case 93 /* InstanceOfKeyword */: + case 92 /* InKeyword */: + case 118 /* AsKeyword */: + case 32 /* EqualsEqualsToken */: + case 33 /* ExclamationEqualsToken */: + case 34 /* EqualsEqualsEqualsToken */: + case 35 /* ExclamationEqualsEqualsToken */: + case 48 /* AmpersandToken */: + case 50 /* CaretToken */: + case 49 /* BarToken */: + case 53 /* AmpersandAmpersandToken */: + case 54 /* BarBarToken */: + case 69 /* BarEqualsToken */: + case 68 /* AmpersandEqualsToken */: + case 70 /* CaretEqualsToken */: + case 65 /* LessThanLessThanEqualsToken */: + case 66 /* GreaterThanGreaterThanEqualsToken */: + case 67 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + case 59 /* PlusEqualsToken */: + case 60 /* MinusEqualsToken */: + case 61 /* AsteriskEqualsToken */: + case 63 /* SlashEqualsToken */: + case 64 /* PercentEqualsToken */: + case 58 /* EqualsToken */: + case 26 /* CommaToken */: return true; default: return false; @@ -74514,12 +89437,12 @@ var ts; } function isPrefixUnaryExpressionOperatorToken(token) { switch (token) { - case 37: - case 38: - case 52: - case 51: - case 43: - case 44: + case 37 /* PlusToken */: + case 38 /* MinusToken */: + case 52 /* TildeToken */: + case 51 /* ExclamationToken */: + case 43 /* PlusPlusToken */: + case 44 /* MinusMinusToken */: return true; default: return false; @@ -74527,56 +89450,72 @@ var ts; } function classFromKind(token) { if (ts.isKeyword(token)) { - return 3; + return 3 /* keyword */; } else if (isBinaryExpressionOperatorToken(token) || isPrefixUnaryExpressionOperatorToken(token)) { - return 5; + return 5 /* operator */; } - else if (token >= 17 && token <= 70) { - return 10; + else if (token >= 17 /* FirstPunctuation */ && token <= 70 /* LastPunctuation */) { + return 10 /* punctuation */; } switch (token) { - case 8: - return 4; - case 9: - return 6; - case 12: - return 7; - case 7: - case 3: - case 2: - return 1; - case 5: - case 4: - return 8; - case 71: + case 8 /* NumericLiteral */: + return 4 /* numericLiteral */; + case 9 /* StringLiteral */: + return 6 /* stringLiteral */; + case 12 /* RegularExpressionLiteral */: + return 7 /* regularExpressionLiteral */; + case 7 /* ConflictMarkerTrivia */: + case 3 /* MultiLineCommentTrivia */: + case 2 /* SingleLineCommentTrivia */: + return 1 /* comment */; + case 5 /* WhitespaceTrivia */: + case 4 /* NewLineTrivia */: + return 8 /* whiteSpace */; + case 71 /* Identifier */: default: if (ts.isTemplateLiteralKind(token)) { - return 6; + return 6 /* stringLiteral */; } - return 2; + return 2 /* identifier */; } } + /* @internal */ function getSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span) { return convertClassificationsToSpans(getEncodedSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span)); } ts.getSemanticClassifications = getSemanticClassifications; function checkForClassificationCancellation(cancellationToken, kind) { + // We don't want to actually call back into our host on every node to find out if we've + // been canceled. That would be an enormous amount of chattyness, along with the all + // the overhead of marshalling the data to/from the host. So instead we pick a few + // reasonable node kinds to bother checking on. These node kinds represent high level + // constructs that we would expect to see commonly, but just at a far less frequent + // interval. + // + // For example, in checker.ts (around 750k) we only have around 600 of these constructs. + // That means we're calling back into the host around every 1.2k of the file we process. + // Lib.d.ts has similar numbers. switch (kind) { - case 239: - case 235: - case 236: - case 234: + case 239 /* ModuleDeclaration */: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + case 234 /* FunctionDeclaration */: cancellationToken.throwIfCancellationRequested(); } } + /* @internal */ function getEncodedSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span) { var spans = []; sourceFile.forEachChild(function cb(node) { + // Only walk into nodes that intersect the requested span. if (!node || !ts.textSpanIntersectsWith(span, node.pos, node.getFullWidth())) { return; } checkForClassificationCancellation(cancellationToken, node.kind); + // Only bother calling into the typechecker if this is an identifier that + // could possibly resolve to a type name. This makes classification run + // in a third of the time it would normally take. if (ts.isIdentifier(node) && !ts.nodeIsMissing(node) && classifiableNames.has(node.escapedText)) { var symbol = typeChecker.getSymbolAtLocation(node); var type = symbol && classifySymbol(symbol, ts.getMeaningFromLocation(node), typeChecker); @@ -74586,7 +89525,7 @@ var ts; } node.forEachChild(cb); }); - return { spans: spans, endOfLineState: 0 }; + return { spans: spans, endOfLineState: 0 /* None */ }; function pushClassification(start, end, type) { spans.push(start); spans.push(end - start); @@ -74596,62 +89535,66 @@ var ts; ts.getEncodedSemanticClassifications = getEncodedSemanticClassifications; function classifySymbol(symbol, meaningAtPosition, checker) { var flags = symbol.getFlags(); - if ((flags & 2885600) === 0) { + if ((flags & 2885600 /* Classifiable */) === 0 /* None */) { return undefined; } - else if (flags & 32) { - return 11; + else if (flags & 32 /* Class */) { + return 11 /* className */; } - else if (flags & 384) { - return 12; + else if (flags & 384 /* Enum */) { + return 12 /* enumName */; } - else if (flags & 524288) { - return 16; + else if (flags & 524288 /* TypeAlias */) { + return 16 /* typeAliasName */; } - else if (flags & 1536) { - return meaningAtPosition & 4 || meaningAtPosition & 1 && hasValueSideModule(symbol) ? 14 : undefined; + else if (flags & 1536 /* Module */) { + // Only classify a module as such if + // - It appears in a namespace context. + // - There exists a module declaration which actually impacts the value side. + return meaningAtPosition & 4 /* Namespace */ || meaningAtPosition & 1 /* Value */ && hasValueSideModule(symbol) ? 14 /* moduleName */ : undefined; } - else if (flags & 2097152) { + else if (flags & 2097152 /* Alias */) { return classifySymbol(checker.getAliasedSymbol(symbol), meaningAtPosition, checker); } - else if (meaningAtPosition & 2) { - return flags & 64 ? 13 : flags & 262144 ? 15 : undefined; + else if (meaningAtPosition & 2 /* Type */) { + return flags & 64 /* Interface */ ? 13 /* interfaceName */ : flags & 262144 /* TypeParameter */ ? 15 /* typeParameterName */ : undefined; } else { return undefined; } } + /** Returns true if there exists a module that introduces entities on the value side. */ function hasValueSideModule(symbol) { return ts.some(symbol.declarations, function (declaration) { - return ts.isModuleDeclaration(declaration) && ts.getModuleInstanceState(declaration) === 1; + return ts.isModuleDeclaration(declaration) && ts.getModuleInstanceState(declaration) === 1 /* Instantiated */; }); } function getClassificationTypeName(type) { switch (type) { - case 1: return "comment"; - case 2: return "identifier"; - case 3: return "keyword"; - case 4: return "number"; - case 5: return "operator"; - case 6: return "string"; - case 8: return "whitespace"; - case 9: return "text"; - case 10: return "punctuation"; - case 11: return "class name"; - case 12: return "enum name"; - case 13: return "interface name"; - case 14: return "module name"; - case 15: return "type parameter name"; - case 16: return "type alias name"; - case 17: return "parameter name"; - case 18: return "doc comment tag name"; - case 19: return "jsx open tag name"; - case 20: return "jsx close tag name"; - case 21: return "jsx self closing tag name"; - case 22: return "jsx attribute"; - case 23: return "jsx text"; - case 24: return "jsx attribute string literal value"; - default: return undefined; + case 1 /* comment */: return "comment" /* comment */; + case 2 /* identifier */: return "identifier" /* identifier */; + case 3 /* keyword */: return "keyword" /* keyword */; + case 4 /* numericLiteral */: return "number" /* numericLiteral */; + case 5 /* operator */: return "operator" /* operator */; + case 6 /* stringLiteral */: return "string" /* stringLiteral */; + case 8 /* whiteSpace */: return "whitespace" /* whiteSpace */; + case 9 /* text */: return "text" /* text */; + case 10 /* punctuation */: return "punctuation" /* punctuation */; + case 11 /* className */: return "class name" /* className */; + case 12 /* enumName */: return "enum name" /* enumName */; + case 13 /* interfaceName */: return "interface name" /* interfaceName */; + case 14 /* moduleName */: return "module name" /* moduleName */; + case 15 /* typeParameterName */: return "type parameter name" /* typeParameterName */; + case 16 /* typeAliasName */: return "type alias name" /* typeAliasName */; + case 17 /* parameterName */: return "parameter name" /* parameterName */; + case 18 /* docCommentTagName */: return "doc comment tag name" /* docCommentTagName */; + case 19 /* jsxOpenTagName */: return "jsx open tag name" /* jsxOpenTagName */; + case 20 /* jsxCloseTagName */: return "jsx close tag name" /* jsxCloseTagName */; + case 21 /* jsxSelfClosingTagName */: return "jsx self closing tag name" /* jsxSelfClosingTagName */; + case 22 /* jsxAttribute */: return "jsx attribute" /* jsxAttribute */; + case 23 /* jsxText */: return "jsx text" /* jsxText */; + case 24 /* jsxAttributeStringLiteralValue */: return "jsx attribute string literal value" /* jsxAttributeStringLiteralValue */; + default: return undefined; // TODO: GH#18217 throw Debug.assertNever(type); } } function convertClassificationsToSpans(classifications) { @@ -74666,18 +89609,21 @@ var ts; } return result; } + /* @internal */ function getSyntacticClassifications(cancellationToken, sourceFile, span) { return convertClassificationsToSpans(getEncodedSyntacticClassifications(cancellationToken, sourceFile, span)); } ts.getSyntacticClassifications = getSyntacticClassifications; + /* @internal */ function getEncodedSyntacticClassifications(cancellationToken, sourceFile, span) { var spanStart = span.start; var spanLength = span.length; - var triviaScanner = ts.createScanner(6, false, sourceFile.languageVariant, sourceFile.text); - var mergeConflictScanner = ts.createScanner(6, false, sourceFile.languageVariant, sourceFile.text); + // Make a scanner we can get trivia from. + var triviaScanner = ts.createScanner(6 /* Latest */, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); + var mergeConflictScanner = ts.createScanner(6 /* Latest */, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); var result = []; processElement(sourceFile); - return { spans: result, endOfLineState: 0 }; + return { spans: result, endOfLineState: 0 /* None */ }; function pushClassification(start, length, type) { result.push(start); result.push(length); @@ -74687,35 +89633,47 @@ var ts; triviaScanner.setTextPos(token.pos); while (true) { var start = triviaScanner.getTextPos(); + // only bother scanning if we have something that could be trivia. if (!ts.couldStartTrivia(sourceFile.text, start)) { return start; } var kind = triviaScanner.scan(); var end = triviaScanner.getTextPos(); var width = end - start; + // The moment we get something that isn't trivia, then stop processing. if (!ts.isTrivia(kind)) { return start; } switch (kind) { - case 4: - case 5: + case 4 /* NewLineTrivia */: + case 5 /* WhitespaceTrivia */: + // Don't bother with newlines/whitespace. continue; - case 2: - case 3: + case 2 /* SingleLineCommentTrivia */: + case 3 /* MultiLineCommentTrivia */: + // Only bother with the trivia if it at least intersects the span of interest. classifyComment(token, kind, start, width); + // Classifying a comment might cause us to reuse the trivia scanner + // (because of jsdoc comments). So after we classify the comment make + // sure we set the scanner position back to where it needs to be. triviaScanner.setTextPos(end); continue; - case 7: + case 7 /* ConflictMarkerTrivia */: var text = sourceFile.text; var ch = text.charCodeAt(start); - if (ch === 60 || ch === 62) { - pushClassification(start, width, 1); + // for the <<<<<<< and >>>>>>> markers, we just add them in as comments + // in the classification stream. + if (ch === 60 /* lessThan */ || ch === 62 /* greaterThan */) { + pushClassification(start, width, 1 /* comment */); continue; } - ts.Debug.assert(ch === 124 || ch === 61); + // for the ||||||| and ======== markers, add a comment for the first line, + // and then lex all subsequent lines up until the end of the conflict marker. + ts.Debug.assert(ch === 124 /* bar */ || ch === 61 /* equals */); classifyDisabledMergeCode(text, start, end); break; - case 6: + case 6 /* ShebangTrivia */: + // TODO: Maybe we should classify these. break; default: ts.Debug.assertNever(kind); @@ -74723,43 +89681,49 @@ var ts; } } function classifyComment(token, kind, start, width) { - if (kind === 3) { + if (kind === 3 /* MultiLineCommentTrivia */) { + // See if this is a doc comment. If so, we'll classify certain portions of it + // specially. var docCommentAndDiagnostics = ts.parseIsolatedJSDocComment(sourceFile.text, start, width); if (docCommentAndDiagnostics && docCommentAndDiagnostics.jsDoc) { + // TODO: This should be predicated on `token["kind"]` being compatible with `HasJSDoc["kind"]` docCommentAndDiagnostics.jsDoc.parent = token; classifyJSDocComment(docCommentAndDiagnostics.jsDoc); return; } } + // Simple comment. Just add as is. pushCommentRange(start, width); } function pushCommentRange(start, width) { - pushClassification(start, width, 1); + pushClassification(start, width, 1 /* comment */); } function classifyJSDocComment(docComment) { var pos = docComment.pos; if (docComment.tags) { for (var _i = 0, _a = docComment.tags; _i < _a.length; _i++) { var tag = _a[_i]; + // As we walk through each tag, classify the portion of text from the end of + // the last tag (or the start of the entire doc comment) as 'comment'. if (tag.pos !== pos) { pushCommentRange(pos, tag.pos - pos); } - pushClassification(tag.atToken.pos, tag.atToken.end - tag.atToken.pos, 10); - pushClassification(tag.tagName.pos, tag.tagName.end - tag.tagName.pos, 18); + pushClassification(tag.atToken.pos, tag.atToken.end - tag.atToken.pos, 10 /* punctuation */); // "@" + pushClassification(tag.tagName.pos, tag.tagName.end - tag.tagName.pos, 18 /* docCommentTagName */); // e.g. "param" pos = tag.tagName.end; switch (tag.kind) { - case 293: + case 293 /* JSDocParameterTag */: processJSDocParameterTag(tag); break; - case 297: + case 297 /* JSDocTemplateTag */: processJSDocTemplateTag(tag); pos = tag.end; break; - case 296: + case 296 /* JSDocTypeTag */: processElement(tag.typeExpression); pos = tag.end; break; - case 294: + case 294 /* JSDocReturnTag */: processElement(tag.typeExpression); pos = tag.end; break; @@ -74773,7 +89737,7 @@ var ts; function processJSDocParameterTag(tag) { if (tag.isNameFirst) { pushCommentRange(pos, tag.name.pos - pos); - pushClassification(tag.name.pos, tag.name.end - tag.name.pos, 17); + pushClassification(tag.name.pos, tag.name.end - tag.name.pos, 17 /* parameterName */); pos = tag.name.end; } if (tag.typeExpression) { @@ -74783,7 +89747,7 @@ var ts; } if (!tag.isNameFirst) { pushCommentRange(pos, tag.name.pos - pos); - pushClassification(tag.name.pos, tag.name.end - tag.name.pos, 17); + pushClassification(tag.name.pos, tag.name.end - tag.name.pos, 17 /* parameterName */); pos = tag.name.end; } } @@ -74795,13 +89759,15 @@ var ts; } } function classifyDisabledMergeCode(text, start, end) { + // Classify the line that the ||||||| or ======= marker is on as a comment. + // Then just lex all further tokens and add them to the result. var i; for (i = start; i < end; i++) { if (ts.isLineBreak(text.charCodeAt(i))) { break; } } - pushClassification(start, i - start, 1); + pushClassification(start, i - start, 1 /* comment */); mergeConflictScanner.setTextPos(i); while (mergeConflictScanner.getTextPos() < end) { classifyDisabledCodeToken(); @@ -74816,6 +89782,10 @@ var ts; pushClassification(start, end - start, type); } } + /** + * Returns true if node should be treated as classified and no further processing is required. + * False will mean that node is not classified and traverse routine should recurse into node contents. + */ function tryClassifyNode(node) { if (ts.isJSDoc(node)) { return true; @@ -74824,10 +89794,10 @@ var ts; return true; } var classifiedElementName = tryClassifyJsxElementName(node); - if (!ts.isToken(node) && node.kind !== 10 && classifiedElementName === undefined) { + if (!ts.isToken(node) && node.kind !== 10 /* JsxText */ && classifiedElementName === undefined) { return false; } - var tokenStart = node.kind === 10 ? node.pos : classifyLeadingTriviaAndGetTokenStart(node); + var tokenStart = node.kind === 10 /* JsxText */ ? node.pos : classifyLeadingTriviaAndGetTokenStart(node); var tokenWidth = node.end - tokenStart; ts.Debug.assert(tokenWidth >= 0); if (tokenWidth > 0) { @@ -74840,120 +89810,133 @@ var ts; } function tryClassifyJsxElementName(token) { switch (token.parent && token.parent.kind) { - case 257: + case 257 /* JsxOpeningElement */: if (token.parent.tagName === token) { - return 19; + return 19 /* jsxOpenTagName */; } break; - case 258: + case 258 /* JsxClosingElement */: if (token.parent.tagName === token) { - return 20; + return 20 /* jsxCloseTagName */; } break; - case 256: + case 256 /* JsxSelfClosingElement */: if (token.parent.tagName === token) { - return 21; + return 21 /* jsxSelfClosingTagName */; } break; - case 262: + case 262 /* JsxAttribute */: if (token.parent.name === token) { - return 22; + return 22 /* jsxAttribute */; } break; } return undefined; } + // for accurate classification, the actual token should be passed in. however, for + // cases like 'disabled merge code' classification, we just get the token kind and + // classify based on that instead. function classifyTokenType(tokenKind, token) { if (ts.isKeyword(tokenKind)) { - return 3; + return 3 /* keyword */; } - if (tokenKind === 27 || tokenKind === 29) { + // Special case `<` and `>`: If they appear in a generic context they are punctuation, + // not operators. + if (tokenKind === 27 /* LessThanToken */ || tokenKind === 29 /* GreaterThanToken */) { + // If the node owning the token has a type argument list or type parameter list, then + // we can effectively assume that a '<' and '>' belong to those lists. if (token && ts.getTypeArgumentOrTypeParameterList(token.parent)) { - return 10; + return 10 /* punctuation */; } } if (ts.isPunctuation(tokenKind)) { if (token) { var parent = token.parent; - if (tokenKind === 58) { - if (parent.kind === 232 || - parent.kind === 152 || - parent.kind === 149 || - parent.kind === 262) { - return 5; + if (tokenKind === 58 /* EqualsToken */) { + // the '=' in a variable declaration is special cased here. + if (parent.kind === 232 /* VariableDeclaration */ || + parent.kind === 152 /* PropertyDeclaration */ || + parent.kind === 149 /* Parameter */ || + parent.kind === 262 /* JsxAttribute */) { + return 5 /* operator */; } } - if (parent.kind === 200 || - parent.kind === 198 || - parent.kind === 199 || - parent.kind === 201) { - return 5; + if (parent.kind === 200 /* BinaryExpression */ || + parent.kind === 198 /* PrefixUnaryExpression */ || + parent.kind === 199 /* PostfixUnaryExpression */ || + parent.kind === 201 /* ConditionalExpression */) { + return 5 /* operator */; } } - return 10; + return 10 /* punctuation */; } - else if (tokenKind === 8) { - return 4; + else if (tokenKind === 8 /* NumericLiteral */) { + return 4 /* numericLiteral */; } - else if (tokenKind === 9) { - return token.parent.kind === 262 ? 24 : 6; + else if (tokenKind === 9 /* StringLiteral */) { + // TODO: GH#18217 + return token.parent.kind === 262 /* JsxAttribute */ ? 24 /* jsxAttributeStringLiteralValue */ : 6 /* stringLiteral */; } - else if (tokenKind === 12) { - return 6; + else if (tokenKind === 12 /* RegularExpressionLiteral */) { + // TODO: we should get another classification type for these literals. + return 6 /* stringLiteral */; } else if (ts.isTemplateLiteralKind(tokenKind)) { - return 6; + // TODO (drosen): we should *also* get another classification type for these literals. + return 6 /* stringLiteral */; } - else if (tokenKind === 10) { - return 23; + else if (tokenKind === 10 /* JsxText */) { + return 23 /* jsxText */; } - else if (tokenKind === 71) { + else if (tokenKind === 71 /* Identifier */) { if (token) { switch (token.parent.kind) { - case 235: + case 235 /* ClassDeclaration */: if (token.parent.name === token) { - return 11; + return 11 /* className */; } return; - case 148: + case 148 /* TypeParameter */: if (token.parent.name === token) { - return 15; + return 15 /* typeParameterName */; } return; - case 236: + case 236 /* InterfaceDeclaration */: if (token.parent.name === token) { - return 13; + return 13 /* interfaceName */; } return; - case 238: + case 238 /* EnumDeclaration */: if (token.parent.name === token) { - return 12; + return 12 /* enumName */; } return; - case 239: + case 239 /* ModuleDeclaration */: if (token.parent.name === token) { - return 14; + return 14 /* moduleName */; } return; - case 149: + case 149 /* Parameter */: if (token.parent.name === token) { - return ts.isThisIdentifier(token) ? 3 : 17; + return ts.isThisIdentifier(token) ? 3 /* keyword */ : 17 /* parameterName */; } return; } } - return 2; + return 2 /* identifier */; } } function processElement(element) { if (!element) { return; } + // Ignore nodes that don't intersect the original span to classify. if (ts.decodedTextSpanIntersectsWith(spanStart, spanLength, element.pos, element.getFullWidth())) { checkForClassificationCancellation(cancellationToken, element.kind); for (var _i = 0, _a = element.getChildren(sourceFile); _i < _a.length; _i++) { var child = _a[_i]; if (!tryClassifyNode(child)) { + // Recurse into our child nodes. processElement(child); } } @@ -74962,6 +89945,7 @@ var ts; } ts.getEncodedSyntacticClassifications = getEncodedSyntacticClassifications; })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var Completions; @@ -74989,27 +89973,35 @@ var ts; if (isPathRelativeToScript(literalValue) || ts.isRootedDiskPath(literalValue)) { var extensions = getSupportedExtensionsForModuleResolution(compilerOptions); if (compilerOptions.rootDirs) { - return getCompletionEntriesForDirectoryFragmentWithRootDirs(compilerOptions.rootDirs, literalValue, scriptDirectory, extensions, false, compilerOptions, host, scriptPath); + return getCompletionEntriesForDirectoryFragmentWithRootDirs(compilerOptions.rootDirs, literalValue, scriptDirectory, extensions, /*includeExtensions*/ false, compilerOptions, host, scriptPath); } else { - return getCompletionEntriesForDirectoryFragment(literalValue, scriptDirectory, extensions, false, host, scriptPath); + return getCompletionEntriesForDirectoryFragment(literalValue, scriptDirectory, extensions, /*includeExtensions*/ false, host, scriptPath); } } else { + // Check for node modules return getCompletionEntriesForNonRelativeModules(literalValue, scriptDirectory, compilerOptions, host, typeChecker); } } function getSupportedExtensionsForModuleResolution(compilerOptions) { var extensions = ts.getSupportedExtensions(compilerOptions); return compilerOptions.resolveJsonModule && ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.NodeJs ? - extensions.concat(".json") : + extensions.concat(".json" /* Json */) : extensions; } + /** + * Takes a script path and returns paths for all potential folders that could be merged with its + * containing folder via the "rootDirs" compiler option + */ function getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptPath, ignoreCase) { + // Make all paths absolute/normalized if they are not already rootDirs = rootDirs.map(function (rootDirectory) { return ts.normalizePath(ts.isRootedDiskPath(rootDirectory) ? rootDirectory : ts.combinePaths(basePath, rootDirectory)); }); + // Determine the path to the directory containing the script relative to the root directory it is contained within var relativeDirectory = ts.firstDefined(rootDirs, function (rootDirectory) { return ts.containsPath(rootDirectory, scriptPath, basePath, ignoreCase) ? scriptPath.substr(rootDirectory.length) : undefined; - }); + }); // TODO: GH#18217 + // Now find a path for each potential directory that is to be merged with the one containing the script return ts.deduplicate(rootDirs.map(function (rootDirectory) { return ts.combinePaths(rootDirectory, relativeDirectory); }), ts.equateStringsCaseSensitive, ts.compareStringsCaseSensitive); } function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs, fragment, scriptPath, extensions, includeExtensions, compilerOptions, host, exclude) { @@ -75023,12 +90015,19 @@ var ts; } return result; } + /** + * Given a path ending at a directory, gets the completions for the path, and filters for those entries containing the basename. + */ function getCompletionEntriesForDirectoryFragment(fragment, scriptPath, extensions, includeExtensions, host, exclude, result) { if (result === void 0) { result = []; } if (fragment === undefined) { fragment = ""; } fragment = ts.normalizeSlashes(fragment); + /** + * Remove the basename from the path. Note that we don't use the basename to filter completions; + * the client is responsible for refining completions. + */ if (!ts.hasTrailingDirectorySeparator(fragment)) { fragment = ts.getDirectoryPath(fragment); } @@ -75036,41 +90035,57 @@ var ts; fragment = "." + ts.directorySeparator; } fragment = ts.ensureTrailingDirectorySeparator(fragment); + // const absolutePath = normalizeAndPreserveTrailingSlash(isRootedDiskPath(fragment) ? fragment : combinePaths(scriptPath, fragment)); // TODO(rbuckton): should use resolvePaths var absolutePath = ts.resolvePath(scriptPath, fragment); var baseDirectory = ts.hasTrailingDirectorySeparator(absolutePath) ? absolutePath : ts.getDirectoryPath(absolutePath); var ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); if (tryDirectoryExists(host, baseDirectory)) { - var files = tryReadDirectory(host, baseDirectory, extensions, undefined, ["./*"]); + // Enumerate the available files if possible + var files = tryReadDirectory(host, baseDirectory, extensions, /*exclude*/ undefined, /*include*/ ["./*"]); if (files) { + /** + * Multiple file entries might map to the same truncated name once we remove extensions + * (happens iff includeExtensions === false)so we use a set-like data structure. Eg: + * + * both foo.ts and foo.tsx become foo + */ var foundFiles = ts.createMap(); for (var _i = 0, files_3 = files; _i < files_3.length; _i++) { var filePath = files_3[_i]; filePath = ts.normalizePath(filePath); - if (exclude && ts.comparePaths(filePath, exclude, scriptPath, ignoreCase) === 0) { + if (exclude && ts.comparePaths(filePath, exclude, scriptPath, ignoreCase) === 0 /* EqualTo */) { continue; } - var foundFileName = includeExtensions || ts.fileExtensionIs(filePath, ".json") ? ts.getBaseFileName(filePath) : ts.removeFileExtension(ts.getBaseFileName(filePath)); + var foundFileName = includeExtensions || ts.fileExtensionIs(filePath, ".json" /* Json */) ? ts.getBaseFileName(filePath) : ts.removeFileExtension(ts.getBaseFileName(filePath)); if (!foundFiles.has(foundFileName)) { foundFiles.set(foundFileName, true); } } ts.forEachKey(foundFiles, function (foundFile) { - result.push(nameAndKind(foundFile, "script")); + result.push(nameAndKind(foundFile, "script" /* scriptElement */)); }); } + // If possible, get folder completion as well var directories = tryGetDirectories(host, baseDirectory); if (directories) { for (var _a = 0, directories_1 = directories; _a < directories_1.length; _a++) { var directory = directories_1[_a]; var directoryName = ts.getBaseFileName(ts.normalizePath(directory)); if (directoryName !== "@types") { - result.push(nameAndKind(directoryName, "directory")); + result.push(nameAndKind(directoryName, "directory" /* directory */)); } } } } return result; } + /** + * Check all of the declared modules and those in node modules. Possible sources of modules: + * Modules that are found by the type checker + * Modules found relative to "baseUrl" compliler options (including patterns from "paths" compiler option) + * Modules from node_modules (i.e. those listed in package.json) + * This includes all files that are found in node_modules/moduleName/ with acceptable file extensions + */ function getCompletionEntriesForNonRelativeModules(fragment, scriptPath, compilerOptions, host, typeChecker) { var baseUrl = compilerOptions.baseUrl, paths = compilerOptions.paths; var result = []; @@ -75078,11 +90093,12 @@ var ts; if (baseUrl) { var projectDir = compilerOptions.project || host.getCurrentDirectory(); var absolute = ts.isRootedDiskPath(baseUrl) ? baseUrl : ts.combinePaths(projectDir, baseUrl); - getCompletionEntriesForDirectoryFragment(fragment, ts.normalizePath(absolute), fileExtensions, false, host, undefined, result); + getCompletionEntriesForDirectoryFragment(fragment, ts.normalizePath(absolute), fileExtensions, /*includeExtensions*/ false, host, /*exclude*/ undefined, result); for (var path in paths) { var patterns = paths[path]; if (paths.hasOwnProperty(path) && patterns) { var _loop_13 = function (name, kind) { + // Path mappings may provide a duplicate way to get to something we've already added, so don't add again. if (!result.some(function (entry) { return entry.name === name; })) { result.push(nameAndKind(name, kind)); } @@ -75097,16 +90113,18 @@ var ts; var fragmentDirectory = containsSlash(fragment) ? ts.hasTrailingDirectorySeparator(fragment) ? fragment : ts.getDirectoryPath(fragment) : undefined; for (var _c = 0, _d = getAmbientModuleCompletions(fragment, fragmentDirectory, typeChecker); _c < _d.length; _c++) { var ambientName = _d[_c]; - result.push(nameAndKind(ambientName, "external module name")); + result.push(nameAndKind(ambientName, "external module name" /* externalModuleName */)); } getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, result); if (ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.NodeJs) { + // If looking for a global package name, don't just include everything in `node_modules` because that includes dependencies' own dependencies. + // (But do if we didn't find anything, e.g. 'package.json' missing.) var foundGlobal = false; if (fragmentDirectory === undefined) { var _loop_14 = function (moduleName) { if (!result.some(function (entry) { return entry.name === moduleName; })) { foundGlobal = true; - result.push(nameAndKind(moduleName, "external module name")); + result.push(nameAndKind(moduleName, "external module name" /* externalModuleName */)); } }; for (var _e = 0, _f = enumerateNodeModulesVisibleToScript(host, scriptPath); _e < _f.length; _e++) { @@ -75118,7 +90136,7 @@ var ts; ts.forEachAncestorDirectory(scriptPath, function (ancestor) { var nodeModules = ts.combinePaths(ancestor, "node_modules"); if (tryDirectoryExists(host, nodeModules)) { - getCompletionEntriesForDirectoryFragment(fragment, nodeModules, fileExtensions, false, host, undefined, result); + getCompletionEntriesForDirectoryFragment(fragment, nodeModules, fileExtensions, /*includeExtensions*/ false, host, /*exclude*/ undefined, result); } }); } @@ -75127,11 +90145,12 @@ var ts; } function getCompletionsForPathMapping(path, patterns, fragment, baseUrl, fileExtensions, host) { if (!ts.endsWith(path, "*")) { - return !ts.stringContains(path, "*") && ts.startsWith(path, fragment) ? [{ name: path, kind: "directory" }] : ts.emptyArray; + // For a path mapping "foo": ["/x/y/z.ts"], add "foo" itself as a completion. + return !ts.stringContains(path, "*") && ts.startsWith(path, fragment) ? [{ name: path, kind: "directory" /* directory */ }] : ts.emptyArray; } var pathPrefix = path.slice(0, path.length - 1); if (!ts.startsWith(fragment, pathPrefix)) { - return [{ name: pathPrefix, kind: "directory" }]; + return [{ name: pathPrefix, kind: "directory" /* directory */ }]; } var remainingFragment = fragment.slice(pathPrefix.length); return ts.flatMap(patterns, function (pattern) { return getModulesForPathsPattern(remainingFragment, baseUrl, pattern, fileExtensions, host); }); @@ -75144,18 +90163,26 @@ var ts; if (!parsed) { return undefined; } + // The prefix has two effective parts: the directory path and the base component after the filepath that is not a + // full directory component. For example: directory/path/of/prefix/base* var normalizedPrefix = ts.resolvePath(parsed.prefix); var normalizedPrefixDirectory = ts.hasTrailingDirectorySeparator(parsed.prefix) ? normalizedPrefix : ts.getDirectoryPath(normalizedPrefix); var normalizedPrefixBase = ts.hasTrailingDirectorySeparator(parsed.prefix) ? "" : ts.getBaseFileName(normalizedPrefix); var fragmentHasPath = containsSlash(fragment); var fragmentDirectory = fragmentHasPath ? ts.hasTrailingDirectorySeparator(fragment) ? fragment : ts.getDirectoryPath(fragment) : undefined; + // Try and expand the prefix to include any path from the fragment so that we can limit the readDirectory call var expandedPrefixDirectory = fragmentHasPath ? ts.combinePaths(normalizedPrefixDirectory, normalizedPrefixBase + fragmentDirectory) : normalizedPrefixDirectory; var normalizedSuffix = ts.normalizePath(parsed.suffix); + // Need to normalize after combining: If we combinePaths("a", "../b"), we want "b" and not "a/../b". var baseDirectory = ts.normalizePath(ts.combinePaths(baseUrl, expandedPrefixDirectory)); var completePrefix = fragmentHasPath ? baseDirectory : ts.ensureTrailingDirectorySeparator(baseDirectory) + normalizedPrefixBase; + // If we have a suffix, then we need to read the directory all the way down. We could create a glob + // that encodes the suffix, but we would have to escape the character "?" which readDirectory + // doesn't support. For now, this is safer but slower var includeGlob = normalizedSuffix ? "**/*" : "./*"; - var matches = tryReadDirectory(host, baseDirectory, fileExtensions, undefined, [includeGlob]).map(function (name) { return ({ name: name, kind: "script" }); }); - var directories = tryGetDirectories(host, baseDirectory).map(function (d) { return ts.combinePaths(baseDirectory, d); }).map(function (name) { return ({ name: name, kind: "directory" }); }); + var matches = tryReadDirectory(host, baseDirectory, fileExtensions, /*exclude*/ undefined, [includeGlob]).map(function (name) { return ({ name: name, kind: "script" /* scriptElement */ }); }); + var directories = tryGetDirectories(host, baseDirectory).map(function (d) { return ts.combinePaths(baseDirectory, d); }).map(function (name) { return ({ name: name, kind: "directory" /* directory */ }); }); + // Trim away prefix and suffix return ts.mapDefined(ts.concatenate(matches, directories), function (_a) { var name = _a.name, kind = _a.kind; var normalizedMatch = ts.normalizePath(name); @@ -75170,8 +90197,12 @@ var ts; return path[0] === ts.directorySeparator ? path.slice(1) : path; } function getAmbientModuleCompletions(fragment, fragmentDirectory, checker) { + // Get modules that the type checker picked up var ambientModules = checker.getAmbientModules().map(function (sym) { return ts.stripQuotes(sym.name); }); var nonRelativeModuleNames = ambientModules.filter(function (moduleName) { return ts.startsWith(moduleName, fragment); }); + // Nested modules of the form "module-name/sub" need to be adjusted to only return the string + // after the last '/' that appears in the fragment because that's where the replacement span + // starts if (fragmentDirectory !== undefined) { var moduleNameWithSeparator_1 = ts.ensureTrailingDirectorySeparator(fragmentDirectory); return nonRelativeModuleNames.map(function (nonRelativeModuleName) { return ts.removePrefix(nonRelativeModuleName, moduleNameWithSeparator_1); }); @@ -75179,7 +90210,7 @@ var ts; return nonRelativeModuleNames; } function getTripleSlashReferenceCompletion(sourceFile, position, compilerOptions, host) { - var token = ts.getTokenAtPosition(sourceFile, position, false); + var token = ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); var commentRanges = ts.getLeadingCommentRanges(sourceFile.text, token.pos); var range = commentRanges && ts.find(commentRanges, function (commentRange) { return position >= commentRange.pos && position <= commentRange.end; }); if (!range) { @@ -75192,7 +90223,7 @@ var ts; } var prefix = match[1], kind = match[2], toComplete = match[3]; var scriptPath = ts.getDirectoryPath(sourceFile.path); - var names = kind === "path" ? getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, ts.getSupportedExtensions(compilerOptions), true, host, sourceFile.path) + var names = kind === "path" ? getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, ts.getSupportedExtensions(compilerOptions), /*includeExtensions*/ true, host, sourceFile.path) : kind === "types" ? getCompletionEntriesFromTypings(host, compilerOptions, scriptPath) : undefined; return names && addReplacementSpans(toComplete, range.pos + prefix.length, names); @@ -75200,6 +90231,7 @@ var ts; PathCompletions.getTripleSlashReferenceCompletion = getTripleSlashReferenceCompletion; function getCompletionEntriesFromTypings(host, options, scriptPath, result) { if (result === void 0) { result = []; } + // Check for typings specified in compiler options var seen = ts.createMap(); if (options.types) { for (var _i = 0, _a = options.types; _i < _a.length; _i++) { @@ -75213,13 +90245,14 @@ var ts; try { typeRoots = ts.getEffectiveTypeRoots(options, host); } - catch (_b) { } + catch ( /* Wrap in try catch because getEffectiveTypeRoots touches the filesystem */_b) { /* Wrap in try catch because getEffectiveTypeRoots touches the filesystem */ } if (typeRoots) { for (var _c = 0, typeRoots_2 = typeRoots; _c < typeRoots_2.length; _c++) { var root = typeRoots_2[_c]; getCompletionEntriesFromDirectories(root); } } + // Also get all @types typings installed in visible node_modules directories for (var _d = 0, _e = findPackageJsons(scriptPath, host); _d < _e.length; _d++) { var packageJson = _e[_d]; var typesDir = ts.combinePaths(ts.getDirectoryPath(packageJson), "node_modules/@types"); @@ -75244,7 +90277,7 @@ var ts; } function pushResult(moduleName) { if (!seen.has(moduleName)) { - result.push(nameAndKind(moduleName, "external module name")); + result.push(nameAndKind(moduleName, "external module name" /* externalModuleName */)); seen.set(moduleName, true); } } @@ -75254,7 +90287,7 @@ var ts; ts.forEachAncestorDirectory(directory, function (ancestor) { var currentConfigPath = ts.findConfigFile(ancestor, function (f) { return tryFileExists(host, f); }, "package.json"); if (!currentConfigPath) { - return true; + return true; // break out } paths.push(currentConfigPath); }); @@ -75266,7 +90299,8 @@ var ts; var result = []; for (var _i = 0, _a = findPackageJsons(scriptPath, host); _i < _a.length; _i++) { var packageJson = _a[_i]; - var contents = ts.readJson(packageJson, host); + var contents = ts.readJson(packageJson, host); // Cast to assert that readFile is defined + // Provide completions for all non @types dependencies for (var _b = 0, nodeModulesDependencyKeys_1 = nodeModulesDependencyKeys; _b < nodeModulesDependencyKeys_1.length; _b++) { var key = nodeModulesDependencyKeys_1[_b]; var dependencies = contents[key]; @@ -75281,20 +90315,35 @@ var ts; } return result; } + // Replace everything after the last directory separator that appears function getDirectoryFragmentTextSpan(text, textStart) { var index = Math.max(text.lastIndexOf(ts.directorySeparator), text.lastIndexOf("\\")); var offset = index !== -1 ? index + 1 : 0; + // If the range is an identifier, span is unnecessary. var length = text.length - offset; - return length === 0 || ts.isIdentifierText(text.substr(offset, length), 6) ? undefined : ts.createTextSpan(textStart + offset, length); + return length === 0 || ts.isIdentifierText(text.substr(offset, length), 6 /* ESNext */) ? undefined : ts.createTextSpan(textStart + offset, length); } + // Returns true if the path is explicitly relative to the script (i.e. relative to . or ..) function isPathRelativeToScript(path) { - if (path && path.length >= 2 && path.charCodeAt(0) === 46) { - var slashIndex = path.length >= 3 && path.charCodeAt(1) === 46 ? 2 : 1; + if (path && path.length >= 2 && path.charCodeAt(0) === 46 /* dot */) { + var slashIndex = path.length >= 3 && path.charCodeAt(1) === 46 /* dot */ ? 2 : 1; var slashCharCode = path.charCodeAt(slashIndex); - return slashCharCode === 47 || slashCharCode === 92; + return slashCharCode === 47 /* slash */ || slashCharCode === 92 /* backslash */; } return false; } + /** + * Matches a triple slash reference directive with an incomplete string literal for its path. Used + * to determine if the caret is currently within the string literal and capture the literal fragment + * for completions. + * For example, this matches + * + * /// + // The completion list at "1" will contain "div" with type any var tagName = location.parent.parent.openingElement.tagName; return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: false, entries: [{ name: tagName.getFullText(), - kind: "class", + kind: "class" /* classElement */, kindModifiers: undefined, sortText: "0", }] }; @@ -75433,16 +90490,20 @@ var ts; var entries = []; if (isUncheckedFile(sourceFile, compilerOptions)) { var uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, preferences, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap); - getJavaScriptCompletionEntries(sourceFile, location.pos, uniqueNames, compilerOptions.target, entries); + getJavaScriptCompletionEntries(sourceFile, location.pos, uniqueNames, compilerOptions.target, entries); // TODO: GH#18217 } else { - if ((!symbols || symbols.length === 0) && keywordFilters === 0) { + if ((!symbols || symbols.length === 0) && keywordFilters === 0 /* None */) { return undefined; } getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, preferences, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap); } + // TODO add filter for keyword based on type/value/namespace and also location + // Add all keywords if + // - this is not a member completion list (all the keywords) + // - other filters are enabled in required scenario so add those keywords var isMemberCompletion = isMemberCompletionKind(completionKind); - if (keywordFilters !== 0 || !isMemberCompletion) { + if (keywordFilters !== 0 /* None */ || !isMemberCompletion) { ts.addRange(entries, getKeywordCompletions(keywordFilters)); } for (var _i = 0, literals_1 = literals; _i < literals_1.length; _i++) { @@ -75456,9 +90517,9 @@ var ts; } function isMemberCompletionKind(kind) { switch (kind) { - case 0: - case 3: - case 2: + case 0 /* ObjectPropertyDeclaration */: + case 3 /* MemberLike */: + case 2 /* PropertyAccess */: return true; default: return false; @@ -75466,6 +90527,7 @@ var ts; } function getJavaScriptCompletionEntries(sourceFile, position, uniqueNames, target, entries) { ts.getNameTable(sourceFile).forEach(function (pos, name) { + // Skip identifiers produced only from the current location if (pos === position) { return; } @@ -75473,7 +90535,7 @@ var ts; if (ts.addToSeen(uniqueNames, realName) && ts.isIdentifierText(realName, target) && !ts.isStringANonContextualKeyword(realName)) { entries.push({ name: realName, - kind: "warning", + kind: "warning" /* warning */, kindModifiers: "", sortText: "1" }); @@ -75482,7 +90544,7 @@ var ts; } var completionNameForLiteral = JSON.stringify; function createCompletionEntryForLiteral(literal) { - return { name: completionNameForLiteral(literal), kind: "string", kindModifiers: "", sortText: "0" }; + return { name: completionNameForLiteral(literal), kind: "string" /* string */, kindModifiers: "" /* none */, sortText: "0" }; } function createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, isJsxInitializer, preferences) { var info = getCompletionEntryDisplayNameForSymbol(symbol, target, origin, kind); @@ -75495,9 +90557,12 @@ var ts; if (origin && origin.type === "this-type") { insertText = needsConvertPropertyAccess ? "this[" + quote(name, preferences) + "]" : "this." + name; } + // We should only have needsConvertPropertyAccess if there's a property access to convert. But see #21790. + // Somehow there was a global with a non-identifier name. Hopefully someone will complain about getting a "foo bar" global completion and provide a repro. else if ((origin && origin.type === "symbol-member" || needsConvertPropertyAccess) && propertyAccessToConvert) { insertText = needsConvertPropertyAccess ? "[" + quote(name, preferences) + "]" : "[" + name + "]"; - var dot = ts.findChildOfKind(propertyAccessToConvert, 23, sourceFile); + var dot = ts.findChildOfKind(propertyAccessToConvert, 23 /* DotToken */, sourceFile); + // If the text after the '.' starts with this name, write over it. Else, add new text. var end = ts.startsWith(name, propertyAccessToConvert.name.text) ? propertyAccessToConvert.name.end : dot.end; replacementSpan = ts.createTextSpanFromBounds(dot.getStart(sourceFile), end); } @@ -75512,6 +90577,13 @@ var ts; if (insertText !== undefined && !preferences.includeCompletionsWithInsertText) { return undefined; } + // TODO(drosen): Right now we just permit *all* semantic meanings when calling + // 'getSymbolKind' which is permissible given that it is backwards compatible; but + // really we should consider passing the meaning for the node so that we don't report + // that a suggestion for a value is an interface. We COULD also just do what + // 'getSymbolModifiers' does, which is to use the first declaration. + // Use a 'sortText' of 0' so that all symbol completion entries come before any other + // entries (like JavaScript identifier entries). return { name: name, kind: ts.SymbolDisplay.getSymbolKind(typeChecker, symbol, location), @@ -75538,7 +90610,7 @@ var ts; } function isRecommendedCompletionMatch(localSymbol, recommendedCompletion, checker) { return localSymbol === recommendedCompletion || - !!(localSymbol.flags & 1048576) && checker.getExportSymbolOfSymbol(localSymbol) === recommendedCompletion; + !!(localSymbol.flags & 1048576 /* ExportValue */) && checker.getExportSymbolOfSymbol(localSymbol) === recommendedCompletion; } function trueOrUndefined(b) { return b ? true : undefined; @@ -75548,6 +90620,10 @@ var ts; } function getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, target, log, kind, preferences, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap) { var start = ts.timestamp(); + // Tracks unique names. + // We don't set this for global variables or completions from external module exports, because we can have multiple of those. + // Based on the order we add things we will always see locals first, then globals, then module exports. + // So adding a completion for a local will prevent us from adding completions for external module exports sharing the same name. var uniques = ts.createMap(); for (var _i = 0, symbols_3 = symbols; _i < symbols_3.length; _i++) { var symbol = symbols_3[_i]; @@ -75560,7 +90636,8 @@ var ts; if (uniques.has(name)) { continue; } - if (!origin && !(symbol.parent === undefined && !ts.some(symbol.declarations, function (d) { return d.getSourceFile() === location.getSourceFile(); }))) { + // Latter case tests whether this is a global variable. + if (!origin && !(symbol.parent === undefined && !ts.some(symbol.declarations, function (d) { return d.getSourceFile() === location.getSourceFile(); }))) { // TODO: GH#18217 uniques.set(name, true); } entries.push(entry); @@ -75588,8 +90665,8 @@ var ts; uniques.set(name, true); entries.push({ name: name, - kindModifiers: "", - kind: "label", + kindModifiers: "" /* none */, + kind: "label" /* label */, sortText: "0" }); } @@ -75606,44 +90683,80 @@ var ts; })(StringLiteralCompletionKind || (StringLiteralCompletionKind = {})); function getStringLiteralCompletionEntries(sourceFile, node, position, typeChecker, compilerOptions, host) { switch (node.parent.kind) { - case 178: + case 178 /* LiteralType */: switch (node.parent.parent.kind) { - case 162: - return { kind: 2, types: getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(node.parent)), isNewIdentifier: false }; - case 176: + case 162 /* TypeReference */: + return { kind: 2 /* Types */, types: getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(node.parent)), isNewIdentifier: false }; + case 176 /* IndexedAccessType */: + // Get all apparent property names + // i.e. interface Foo { + // foo: string; + // bar: string; + // } + // let x: Foo["/*completion position*/"] return stringLiteralCompletionsFromProperties(typeChecker.getTypeFromTypeNode(node.parent.parent.objectType)); - case 179: - return { kind: 0, paths: Completions.PathCompletions.getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker) }; + case 179 /* ImportType */: + return { kind: 0 /* Paths */, paths: Completions.PathCompletions.getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker) }; default: return undefined; } - case 270: + case 270 /* PropertyAssignment */: if (ts.isObjectLiteralExpression(node.parent.parent) && node.parent.name === node) { + // Get quoted name of properties of the object literal expression + // i.e. interface ConfigFiles { + // 'jspm:dev': string + // } + // let files: ConfigFiles = { + // '/*completion position*/' + // } + // + // function foo(c: ConfigFiles) {} + // foo({ + // '/*completion position*/' + // }); return stringLiteralCompletionsFromProperties(typeChecker.getContextualType(node.parent.parent)); } return fromContextualType(); - case 186: { + case 186 /* ElementAccessExpression */: { var _a = node.parent, expression = _a.expression, argumentExpression = _a.argumentExpression; if (node === argumentExpression) { + // Get all names of properties on the expression + // i.e. interface A { + // 'prop1': string + // } + // let a: A; + // a['/*completion position*/'] return stringLiteralCompletionsFromProperties(typeChecker.getTypeAtLocation(expression)); } return undefined; } - case 187: - case 188: - if (!ts.isRequireCall(node.parent, false) && !ts.isImportCall(node.parent)) { + case 187 /* CallExpression */: + case 188 /* NewExpression */: + if (!ts.isRequireCall(node.parent, /*checkArgumentIsStringLiteralLike*/ false) && !ts.isImportCall(node.parent)) { var argumentInfo = ts.SignatureHelp.getArgumentInfoForCompletions(node, position, sourceFile); + // Get string literal completions from specialized signatures of the target + // i.e. declare function f(a: 'A'); + // f("/*completion position*/") return argumentInfo ? getStringLiteralCompletionsFromSignature(argumentInfo, typeChecker) : fromContextualType(); } - case 244: - case 250: - case 254: - return { kind: 0, paths: Completions.PathCompletions.getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker) }; + // falls through (is `require("")` or `import("")`) + case 244 /* ImportDeclaration */: + case 250 /* ExportDeclaration */: + case 254 /* ExternalModuleReference */: + // Get all known external module names or complete a path to a module + // i.e. import * as ns from "/*completion position*/"; + // var y = import("/*completion position*/"); + // import x = require("/*completion position*/"); + // var y = require("/*completion position*/"); + // export * from "/*completion position*/"; + return { kind: 0 /* Paths */, paths: Completions.PathCompletions.getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker) }; default: return fromContextualType(); } function fromContextualType() { - return { kind: 2, types: getStringLiteralTypes(getContextualTypeFromParent(node, typeChecker)), isNewIdentifier: false }; + // Get completion for string literal from string literal type + // i.e. var x: "hi" | "hello" = "/*completion position*/" + return { kind: 2 /* Types */, types: getStringLiteralTypes(getContextualTypeFromParent(node, typeChecker)), isNewIdentifier: false }; } } function getStringLiteralCompletionsFromSignature(argumentInfo, checker) { @@ -75655,13 +90768,13 @@ var ts; if (!candidate.hasRestParameter && argumentInfo.argumentCount > candidate.parameters.length) return; var type = checker.getParameterType(candidate, argumentInfo.argumentIndex); - isNewIdentifier = isNewIdentifier || !!(type.flags & 4); + isNewIdentifier = isNewIdentifier || !!(type.flags & 4 /* String */); return getStringLiteralTypes(type, uniques); }); - return { kind: 2, types: types, isNewIdentifier: isNewIdentifier }; + return { kind: 2 /* Types */, types: types, isNewIdentifier: isNewIdentifier }; } function stringLiteralCompletionsFromProperties(type) { - return type && { kind: 1, symbols: type.getApparentProperties(), hasIndexSignature: hasIndexSignature(type) }; + return type && { kind: 1 /* Properties */, symbols: type.getApparentProperties(), hasIndexSignature: hasIndexSignature(type) }; } function getStringLiteralTypes(type, uniques) { if (uniques === void 0) { uniques = ts.createMap(); } @@ -75670,7 +90783,7 @@ var ts; type = ts.skipConstraint(type); return type.isUnion() ? ts.flatMap(type.types, function (t) { return getStringLiteralTypes(t, uniques); }) - : type.isStringLiteral() && !(type.flags & 512) && ts.addToSeen(uniques, type.value) + : type.isStringLiteral() && !(type.flags & 512 /* EnumLiteral */) && ts.addToSeen(uniques, type.value) ? [type] : ts.emptyArray; } @@ -75680,13 +90793,17 @@ var ts; if (!completionData) { return { type: "none" }; } - if (completionData.kind !== 0) { + if (completionData.kind !== 0 /* Data */) { return { type: "request", request: completionData }; } var symbols = completionData.symbols, literals = completionData.literals, location = completionData.location, completionKind = completionData.completionKind, symbolToOriginInfoMap = completionData.symbolToOriginInfoMap, previousToken = completionData.previousToken, isJsxInitializer = completionData.isJsxInitializer; var literal = ts.find(literals, function (l) { return completionNameForLiteral(l) === entryId.name; }); if (literal !== undefined) return { type: "literal", literal: literal }; + // Find the symbol with the matching entry name. + // We don't need to perform character checks here because we're only comparing the + // name against 'entryName' (which is known to be good), not building a new + // completion entry. return ts.firstDefined(symbols, function (symbol) { var origin = symbolToOriginInfoMap[ts.getSymbolId(symbol)]; var info = getCompletionEntryDisplayNameForSymbol(symbol, compilerOptions.target, origin, completionKind); @@ -75696,7 +90813,8 @@ var ts; }) || { type: "none" }; } function getSymbolName(symbol, origin, target) { - return origin && origin.type === "export" && origin.isDefaultExport && symbol.escapedName === "default" + return origin && origin.type === "export" && origin.isDefaultExport && symbol.escapedName === "default" /* Default */ + // Name of "export default foo;" is "foo". Name of "export default 0" is the filename converted to camelCase. ? ts.firstDefined(symbol.declarations, function (d) { return ts.isExportAssignment(d) && ts.isIdentifier(d.expression) ? d.expression.text : undefined; }) || ts.codefix.moduleSymbolToValidIdentifier(origin.moduleSymbol, target) : symbol.name; @@ -75710,18 +90828,19 @@ var ts; var stringLiteralCompletions = !contextToken || !ts.isStringLiteralLike(contextToken) ? undefined : getStringLiteralCompletionEntries(sourceFile, contextToken, position, typeChecker, compilerOptions, host); - return stringLiteralCompletions && stringLiteralCompletionDetails(name, contextToken, stringLiteralCompletions, sourceFile, typeChecker, cancellationToken); + return stringLiteralCompletions && stringLiteralCompletionDetails(name, contextToken, stringLiteralCompletions, sourceFile, typeChecker, cancellationToken); // TODO: GH#18217 } + // Compute all the completion symbols again. var symbolCompletion = getSymbolCompletionFromEntryId(program, log, sourceFile, position, entryId); switch (symbolCompletion.type) { case "request": { var request = symbolCompletion.request; switch (request.kind) { - case 1: + case 1 /* JsDocTagName */: return ts.JsDoc.getJSDocTagNameCompletionDetails(name); - case 2: + case 2 /* JsDocTag */: return ts.JsDoc.getJSDocTagCompletionDetails(name); - case 3: + case 3 /* JsDocParameterName */: return ts.JsDoc.getJSDocParameterNameCompletionDetails(name); default: return ts.Debug.assertNever(request); @@ -75730,40 +90849,41 @@ var ts; case "symbol": { var symbol = symbolCompletion.symbol, location = symbolCompletion.location, symbolToOriginInfoMap = symbolCompletion.symbolToOriginInfoMap, previousToken = symbolCompletion.previousToken; var _a = getCompletionEntryCodeActionsAndSourceDisplay(symbolToOriginInfoMap, symbol, program, typeChecker, host, compilerOptions, sourceFile, previousToken, formatContext, getCanonicalFileName, program.getSourceFiles(), preferences), codeActions = _a.codeActions, sourceDisplay = _a.sourceDisplay; - return createCompletionDetailsForSymbol(symbol, typeChecker, sourceFile, location, cancellationToken, codeActions, sourceDisplay); + return createCompletionDetailsForSymbol(symbol, typeChecker, sourceFile, location, cancellationToken, codeActions, sourceDisplay); // TODO: GH#18217 } case "literal": { var literal = symbolCompletion.literal; - return createSimpleDetails(completionNameForLiteral(literal), "string", typeof literal === "string" ? ts.SymbolDisplayPartKind.stringLiteral : ts.SymbolDisplayPartKind.numericLiteral); + return createSimpleDetails(completionNameForLiteral(literal), "string" /* string */, typeof literal === "string" ? ts.SymbolDisplayPartKind.stringLiteral : ts.SymbolDisplayPartKind.numericLiteral); } case "none": - return allKeywordsCompletions().some(function (c) { return c.name === name; }) ? createSimpleDetails(name, "keyword", ts.SymbolDisplayPartKind.keyword) : undefined; + // Didn't find a symbol with this name. See if we can find a keyword instead. + return allKeywordsCompletions().some(function (c) { return c.name === name; }) ? createSimpleDetails(name, "keyword" /* keyword */, ts.SymbolDisplayPartKind.keyword) : undefined; default: ts.Debug.assertNever(symbolCompletion); } } Completions.getCompletionEntryDetails = getCompletionEntryDetails; function createSimpleDetails(name, kind, kind2) { - return createCompletionDetails(name, "", kind, [ts.displayPart(name, kind2)]); + return createCompletionDetails(name, "" /* none */, kind, [ts.displayPart(name, kind2)]); } function createCompletionDetailsForSymbol(symbol, checker, sourceFile, location, cancellationToken, codeActions, sourceDisplay) { var _a = checker.runWithCancellationToken(cancellationToken, function (checker) { - return ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, sourceFile, location, location, 7); + return ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, sourceFile, location, location, 7 /* All */); }), displayParts = _a.displayParts, documentation = _a.documentation, symbolKind = _a.symbolKind, tags = _a.tags; return createCompletionDetails(symbol.name, ts.SymbolDisplay.getSymbolModifiers(symbol), symbolKind, displayParts, documentation, tags, codeActions, sourceDisplay); } function stringLiteralCompletionDetails(name, location, completion, sourceFile, checker, cancellationToken) { switch (completion.kind) { - case 0: { + case 0 /* Paths */: { var match = ts.find(completion.paths, function (p) { return p.name === name; }); - return match && createCompletionDetails(name, "", match.kind, [ts.textPart(name)]); + return match && createCompletionDetails(name, "" /* none */, match.kind, [ts.textPart(name)]); } - case 1: { + case 1 /* Properties */: { var match = ts.find(completion.symbols, function (s) { return s.name === name; }); return match && createCompletionDetailsForSymbol(match, checker, sourceFile, location, cancellationToken); } - case 2: - return ts.find(completion.types, function (t) { return t.value === name; }) ? createCompletionDetails(name, "", "type", [ts.textPart(name)]) : undefined; + case 2 /* Types */: + return ts.find(completion.types, function (t) { return t.value === name; }) ? createCompletionDetails(name, "" /* none */, "type" /* typeElement */, [ts.textPart(name)]) : undefined; default: return ts.Debug.assertNever(completion); } @@ -75803,9 +90923,11 @@ var ts; CompletionKind[CompletionKind["None"] = 5] = "None"; })(CompletionKind || (CompletionKind = {})); function getRecommendedCompletion(previousToken, contextualType, checker) { + // For a union, return the first one with a recommended completion. return ts.firstDefined(contextualType && (contextualType.isUnion() ? contextualType.types : [contextualType]), function (type) { var symbol = type && type.symbol; - return symbol && (symbol.flags & (8 | 384 | 32) && !ts.isAbstractConstructorSymbol(symbol)) + // Don't include make a recommended completion for an abstract class + return symbol && (symbol.flags & (8 /* EnumMember */ | 384 /* Enum */ | 32 /* Class */) && !ts.isAbstractConstructorSymbol(symbol)) ? getFirstSymbolInChain(symbol, previousToken, checker) : undefined; }); @@ -75813,30 +90935,32 @@ var ts; function getContextualType(previousToken, position, sourceFile, checker) { var parent = previousToken.parent; switch (previousToken.kind) { - case 71: + case 71 /* Identifier */: return getContextualTypeFromParent(previousToken, checker); - case 58: + case 58 /* EqualsToken */: switch (parent.kind) { - case 232: - return checker.getContextualType(parent.initializer); - case 200: + case 232 /* VariableDeclaration */: + return checker.getContextualType(parent.initializer); // TODO: GH#18217 + case 200 /* BinaryExpression */: return checker.getTypeAtLocation(parent.left); - case 262: + case 262 /* JsxAttribute */: return checker.getContextualTypeForJsxAttribute(parent); default: return undefined; } - case 94: + case 94 /* NewKeyword */: return checker.getContextualType(parent); - case 73: + case 73 /* CaseKeyword */: return getSwitchedType(ts.cast(parent, ts.isCaseClause), checker); - case 17: - return ts.isJsxExpression(parent) && parent.parent.kind !== 255 ? checker.getContextualTypeForJsxAttribute(parent.parent) : undefined; + case 17 /* OpenBraceToken */: + return ts.isJsxExpression(parent) && parent.parent.kind !== 255 /* JsxElement */ ? checker.getContextualTypeForJsxAttribute(parent.parent) : undefined; default: var argInfo = ts.SignatureHelp.getArgumentInfoForCompletions(previousToken, position, sourceFile); return argInfo - ? checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex + (previousToken.kind === 26 ? 1 : 0)) + // At `,`, treat this as the next argument after the comma. + ? checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex + (previousToken.kind === 26 /* CommaToken */ ? 1 : 0)) : isEqualityOperatorKind(previousToken.kind) && ts.isBinaryExpression(parent) && isEqualityOperatorKind(parent.operatorToken.kind) + // completion at `x ===/**/` should be for the right side ? checker.getTypeAtLocation(parent.left) : checker.getContextualType(previousToken); } @@ -75844,15 +90968,15 @@ var ts; function getContextualTypeFromParent(node, checker) { var parent = node.parent; switch (parent.kind) { - case 188: + case 188 /* NewExpression */: return checker.getContextualType(parent); - case 200: { + case 200 /* BinaryExpression */: { var _a = parent, left = _a.left, operatorToken = _a.operatorToken, right = _a.right; return isEqualityOperatorKind(operatorToken.kind) ? checker.getTypeAtLocation(node === right ? left : right) : checker.getContextualType(node); } - case 266: + case 266 /* CaseClause */: return parent.expression === node ? getSwitchedType(parent, checker) : undefined; default: return checker.getContextualType(node); @@ -75862,68 +90986,101 @@ var ts; return checker.getTypeAtLocation(caseClause.parent.parent.expression); } function getFirstSymbolInChain(symbol, enclosingDeclaration, checker) { - var chain = checker.getAccessibleSymbolChain(symbol, enclosingDeclaration, 67108863, false); + var chain = checker.getAccessibleSymbolChain(symbol, enclosingDeclaration, /*meaning*/ 67108863 /* All */, /*useOnlyExternalAliasing*/ false); if (chain) return ts.first(chain); return symbol.parent && (isModuleSymbol(symbol.parent) ? symbol : getFirstSymbolInChain(symbol.parent, enclosingDeclaration, checker)); } function isModuleSymbol(symbol) { - return symbol.declarations.some(function (d) { return d.kind === 274; }); + return symbol.declarations.some(function (d) { return d.kind === 274 /* SourceFile */; }); } function getCompletionData(program, log, sourceFile, isUncheckedFile, position, preferences, detailsEntryId) { var typeChecker = program.getTypeChecker(); var start = ts.timestamp(); - var currentToken = ts.getTokenAtPosition(sourceFile, position, false); + var currentToken = ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); // TODO: GH#15853 + // We will check for jsdoc comments with insideComment and getJsDocTagAtPosition. (TODO: that seems rather inefficient to check the same thing so many times.) log("getCompletionData: Get current token: " + (ts.timestamp() - start)); start = ts.timestamp(); + // Completion not allowed inside comments, bail out if this is the case var insideComment = ts.isInComment(sourceFile, position, currentToken); log("getCompletionData: Is inside comment: " + (ts.timestamp() - start)); var insideJsDocTagTypeExpression = false; var isInSnippetScope = false; if (insideComment) { if (ts.hasDocComment(sourceFile, position)) { - if (sourceFile.text.charCodeAt(position - 1) === 64) { - return { kind: 1 }; + if (sourceFile.text.charCodeAt(position - 1) === 64 /* at */) { + // The current position is next to the '@' sign, when no tag name being provided yet. + // Provide a full list of tag names + return { kind: 1 /* JsDocTagName */ }; } else { + // When completion is requested without "@", we will have check to make sure that + // there are no comments prefix the request position. We will only allow "*" and space. + // e.g + // /** |c| /* + // + // /** + // |c| + // */ + // + // /** + // * |c| + // */ + // + // /** + // * |c| + // */ var lineStart = ts.getLineStartPositionForPosition(position, sourceFile); if (!(sourceFile.text.substring(lineStart, position).match(/[^\*|\s|(/\*\*)]/))) { - return { kind: 2 }; + return { kind: 2 /* JsDocTag */ }; } } } + // Completion should work inside certain JsDoc tags. For example: + // /** @type {number | string} */ + // Completion should work in the brackets var tag = getJsDocTagAtPosition(currentToken, position); if (tag) { if (tag.tagName.pos <= position && position <= tag.tagName.end) { - return { kind: 1 }; + return { kind: 1 /* JsDocTagName */ }; } - if (isTagWithTypeExpression(tag) && tag.typeExpression && tag.typeExpression.kind === 278) { - currentToken = ts.getTokenAtPosition(sourceFile, position, true); + if (isTagWithTypeExpression(tag) && tag.typeExpression && tag.typeExpression.kind === 278 /* JSDocTypeExpression */) { + currentToken = ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ true); if (!currentToken || (!ts.isDeclarationName(currentToken) && - (currentToken.parent.kind !== 299 || + (currentToken.parent.kind !== 299 /* JSDocPropertyTag */ || currentToken.parent.name !== currentToken))) { + // Use as type location if inside tag's type expression insideJsDocTagTypeExpression = isCurrentlyEditingNode(tag.typeExpression); } } if (ts.isJSDocParameterTag(tag) && (ts.nodeIsMissing(tag.name) || tag.name.pos <= position && position <= tag.name.end)) { - return { kind: 3, tag: tag }; + return { kind: 3 /* JsDocParameterName */, tag: tag }; } } if (!insideJsDocTagTypeExpression) { + // Proceed if the current position is in jsDoc tag expression; otherwise it is a normal + // comment or the plain text part of a jsDoc comment, so no completion should be available log("Returning an empty list because completion was inside a regular comment or plain text part of a JsDoc comment."); return undefined; } } start = ts.timestamp(); - var previousToken = ts.findPrecedingToken(position, sourceFile, undefined, insideJsDocTagTypeExpression); + var previousToken = ts.findPrecedingToken(position, sourceFile, /*startNode*/ undefined, insideJsDocTagTypeExpression); // TODO: GH#18217 log("getCompletionData: Get previous token 1: " + (ts.timestamp() - start)); + // The decision to provide completion depends on the contextToken, which is determined through the previousToken. + // Note: 'previousToken' (and thus 'contextToken') can be undefined if we are the beginning of the file var contextToken = previousToken; + // Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS| + // Skip this partial identifier and adjust the contextToken to the token that precedes it. if (contextToken && position <= contextToken.end && (ts.isIdentifier(contextToken) || ts.isKeyword(contextToken.kind))) { var start_4 = ts.timestamp(); - contextToken = ts.findPrecedingToken(contextToken.getFullStart(), sourceFile, undefined, insideJsDocTagTypeExpression); + contextToken = ts.findPrecedingToken(contextToken.getFullStart(), sourceFile, /*startNode*/ undefined, insideJsDocTagTypeExpression); // TODO: GH#18217 log("getCompletionData: Get previous token 2: " + (ts.timestamp() - start_4)); } + // Find the node where completion is requested on. + // Also determine whether we are trying to complete with members of that node + // or attributes of a JSX tag. var node = currentToken; var propertyAccessToConvert; var isRightOfDot = false; @@ -75932,73 +91089,83 @@ var ts; var isJsxInitializer = false; var location = ts.getTouchingPropertyName(sourceFile, position); if (contextToken) { + // Bail out if this is a known invalid completion location if (isCompletionListBlocker(contextToken)) { log("Returning an empty list because completion was requested in an invalid position."); return undefined; } var parent = contextToken.parent; - if (contextToken.kind === 23) { + if (contextToken.kind === 23 /* DotToken */) { isRightOfDot = true; switch (parent.kind) { - case 185: + case 185 /* PropertyAccessExpression */: propertyAccessToConvert = parent; node = propertyAccessToConvert.expression; break; - case 146: + case 146 /* QualifiedName */: node = parent.left; break; - case 179: - case 210: + case 179 /* ImportType */: + case 210 /* MetaProperty */: node = parent; break; default: + // There is nothing that precedes the dot, so this likely just a stray character + // or leading into a '...' token. Just bail out instead. return undefined; } } - else if (sourceFile.languageVariant === 1) { - if (parent && parent.kind === 185) { + else if (sourceFile.languageVariant === 1 /* JSX */) { + // + // If the tagname is a property access expression, we will then walk up to the top most of property access expression. + // Then, try to get a JSX container and its associated attributes type. + if (parent && parent.kind === 185 /* PropertyAccessExpression */) { contextToken = parent; parent = parent.parent; } + // Fix location if (currentToken.parent === location) { switch (currentToken.kind) { - case 29: - if (currentToken.parent.kind === 255 || currentToken.parent.kind === 257) { + case 29 /* GreaterThanToken */: + if (currentToken.parent.kind === 255 /* JsxElement */ || currentToken.parent.kind === 257 /* JsxOpeningElement */) { location = currentToken; } break; - case 41: - if (currentToken.parent.kind === 256) { + case 41 /* SlashToken */: + if (currentToken.parent.kind === 256 /* JsxSelfClosingElement */) { location = currentToken; } break; } } switch (parent.kind) { - case 258: - if (contextToken.kind === 41) { + case 258 /* JsxClosingElement */: + if (contextToken.kind === 41 /* SlashToken */) { isStartingCloseTag = true; location = contextToken; } break; - case 200: - if (!(parent.left.flags & 32768)) { + case 200 /* BinaryExpression */: + if (!(parent.left.flags & 32768 /* ThisNodeHasError */)) { + // It has a left-hand side, so we're not in an opening JSX tag. break; } - case 256: - case 255: - case 257: - if (contextToken.kind === 27) { + // falls through + case 256 /* JsxSelfClosingElement */: + case 255 /* JsxElement */: + case 257 /* JsxOpeningElement */: + if (contextToken.kind === 27 /* LessThanToken */) { isRightOfOpenTag = true; location = contextToken; } break; - case 262: + case 262 /* JsxAttribute */: switch (previousToken.kind) { - case 58: + case 58 /* EqualsToken */: isJsxInitializer = true; break; - case 71: + case 71 /* Identifier */: + // For `
x$ + // + // the cursor is outside of both the 'x' and the arrow function 'xyz => x', + // so 'xyz' is not returned in our results. + // + // We define 'adjustedPosition' so that we may appropriately account for + // being at the end of an identifier. The intention is that if requesting completion + // at the end of an identifier, it should be effectively equivalent to requesting completion + // anywhere inside/at the beginning of the identifier. So in the previous case, the + // 'adjustedPosition' will work as if requesting completion in the following: + // + // xyz => $x + // + // If previousToken !== contextToken, then + // - 'contextToken' was adjusted to the token prior to 'previousToken' + // because we were at the end of an identifier. + // - 'previousToken' is defined. var adjustedPosition = previousToken !== contextToken ? previousToken.getStart() : position; var scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; isInSnippetScope = isSnippetScope(scopeNode); - var symbolMeanings = 67901928 | 67216319 | 1920 | 2097152; + var symbolMeanings = 67901928 /* Type */ | 67216319 /* Value */ | 1920 /* Namespace */ | 2097152 /* Alias */; symbols = ts.Debug.assertEachDefined(typeChecker.getSymbolsInScope(scopeNode, symbolMeanings), "getSymbolsInScope() should all be defined"); - if (preferences.includeCompletionsWithInsertText && scopeNode.kind !== 274) { + // Need to insert 'this.' before properties of `this` type, so only do that if `includeInsertTextCompletions` + if (preferences.includeCompletionsWithInsertText && scopeNode.kind !== 274 /* SourceFile */) { var thisType = typeChecker.tryGetThisTypeAt(scopeNode); if (thisType) { - for (var _i = 0, _a = getPropertiesForCompletion(thisType, typeChecker, true); _i < _a.length; _i++) { + for (var _i = 0, _a = getPropertiesForCompletion(thisType, typeChecker, /*isForAccess*/ true); _i < _a.length; _i++) { var symbol = _a[_i]; symbolToOriginInfoMap[ts.getSymbolId(symbol)] = { type: "this-type" }; symbols.push(symbol); @@ -76181,24 +91394,30 @@ var ts; filterGlobalCompletion(symbols); } function shouldOfferImportCompletions() { + // If not already a module, must have modules enabled and not currently be in a commonjs module. (TODO: import completions for commonjs) if (!preferences.includeCompletionsForModuleExports) return false; + // If already using ES6 modules, OK to continue using them. if (sourceFile.externalModuleIndicator) return true; + // If already using commonjs, don't introduce ES6. if (sourceFile.commonJsModuleIndicator) return false; + // If some file is using ES6 modules, assume that it's OK to add more. if (ts.programContainsEs6Modules(program)) return true; + // For JS, stay on the safe side. if (isUncheckedFile) return false; + // If module transpilation is enabled or we're targeting es6 or above, or not emitting, OK. return ts.compilerOptionsIndicateEs6Modules(program.getCompilerOptions()); } function isSnippetScope(scopeNode) { switch (scopeNode.kind) { - case 274: - case 202: - case 265: - case 213: + case 274 /* SourceFile */: + case 202 /* TemplateExpression */: + case 265 /* JsxExpression */: + case 213 /* Block */: return true; default: return ts.isStatement(scopeNode); @@ -76208,57 +91427,64 @@ var ts; var isTypeOnlyCompletion = insideJsDocTagTypeExpression || !isContextTokenValueLocation(contextToken) && (ts.isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken)); var allowTypes = isTypeOnlyCompletion || !isContextTokenValueLocation(contextToken) && ts.isPossiblyTypeArgumentPosition(contextToken, sourceFile); if (isTypeOnlyCompletion) - keywordFilters = 5; + keywordFilters = 5 /* TypeKeywords */; ts.filterMutate(symbols, function (symbol) { if (!ts.isSourceFile(location)) { + // export = /**/ here we want to get all meanings, so any symbol is ok if (ts.isExportAssignment(location.parent)) { return true; } symbol = ts.skipAlias(symbol, typeChecker); + // import m = /**/ <-- It can only access namespace (if typing import = x. this would get member symbols and not namespace) if (ts.isInRightSideOfInternalImportEqualsDeclaration(location)) { - return !!(symbol.flags & 1920); + return !!(symbol.flags & 1920 /* Namespace */); } if (allowTypes) { + // Its a type, but you can reach it by namespace.type as well var symbolAllowedAsType = symbolCanBeReferencedAtTypeLocation(symbol); if (symbolAllowedAsType || isTypeOnlyCompletion) { return symbolAllowedAsType; } } } - return !!(ts.getCombinedLocalAndExportSymbolFlags(symbol) & 67216319); + // expressions are value space (which includes the value namespaces) + return !!(ts.getCombinedLocalAndExportSymbolFlags(symbol) & 67216319 /* Value */); }); } function isContextTokenValueLocation(contextToken) { return contextToken && - contextToken.kind === 103 && - (contextToken.parent.kind === 165 || ts.isTypeOfExpression(contextToken.parent)); + contextToken.kind === 103 /* TypeOfKeyword */ && + (contextToken.parent.kind === 165 /* TypeQuery */ || ts.isTypeOfExpression(contextToken.parent)); } function isContextTokenTypeLocation(contextToken) { if (contextToken) { var parentKind = contextToken.parent.kind; switch (contextToken.kind) { - case 56: - return parentKind === 152 || - parentKind === 151 || - parentKind === 149 || - parentKind === 232 || + case 56 /* ColonToken */: + return parentKind === 152 /* PropertyDeclaration */ || + parentKind === 151 /* PropertySignature */ || + parentKind === 149 /* Parameter */ || + parentKind === 232 /* VariableDeclaration */ || ts.isFunctionLikeKind(parentKind); - case 58: - return parentKind === 237; - case 118: - return parentKind === 208; + case 58 /* EqualsToken */: + return parentKind === 237 /* TypeAliasDeclaration */; + case 118 /* AsKeyword */: + return parentKind === 208 /* AsExpression */; } } return false; } function symbolCanBeReferencedAtTypeLocation(symbol) { symbol = symbol.exportSymbol || symbol; + // This is an alias, follow what it aliases symbol = ts.skipAlias(symbol, typeChecker); - if (symbol.flags & 67901928) { + if (symbol.flags & 67901928 /* Type */) { return true; } - if (symbol.flags & 1536) { + if (symbol.flags & 1536 /* Module */) { var exportedSymbols = typeChecker.getExportsOfModule(symbol); + // If the exported symbols contains type, + // symbol can be referenced at locations where type is allowed return exportedSymbols.some(symbolCanBeReferencedAtTypeLocation); } return false; @@ -76267,20 +91493,28 @@ var ts; var tokenTextLowerCase = tokenText.toLowerCase(); var seenResolvedModules = ts.createMap(); ts.codefix.forEachExternalModuleToImportFrom(typeChecker, sourceFile, program.getSourceFiles(), function (moduleSymbol) { + // Perf -- ignore other modules if this is a request for details if (detailsEntryId && detailsEntryId.source && ts.stripQuotes(moduleSymbol.name) !== detailsEntryId.source) { return; } var resolvedModuleSymbol = typeChecker.resolveExternalModuleSymbol(moduleSymbol); + // resolvedModuleSymbol may be a namespace. A namespace may be `export =` by multiple module declarations, but only keep the first one. if (!ts.addToSeen(seenResolvedModules, ts.getSymbolId(resolvedModuleSymbol))) { return; } for (var _i = 0, _a = typeChecker.getExportsOfModule(moduleSymbol); _i < _a.length; _i++) { var symbol = _a[_i]; + // Don't add a completion for a re-export, only for the original. + // The actual import fix might end up coming from a re-export -- we don't compute that until getting completion details. + // This is just to avoid adding duplicate completion entries. + // + // If `symbol.parent !== ...`, this comes from an `export * from "foo"` re-export. Those don't create new symbols. + // If `some(...)`, this comes from an `export { foo } from "foo"` re-export, which creates a new symbol (thus isn't caught by the first check). if (typeChecker.getMergedSymbol(symbol.parent) !== resolvedModuleSymbol || ts.some(symbol.declarations, function (d) { return ts.isExportSpecifier(d) && !!d.parent.parent.moduleSpecifier; })) { continue; } - var isDefaultExport = symbol.name === "default"; + var isDefaultExport = symbol.name === "default" /* Default */; if (isDefaultExport) { symbol = ts.getLocalSymbolForExportDefault(symbol) || symbol; } @@ -76292,6 +91526,11 @@ var ts; } }); } + /** + * True if you could remove some characters in `a` to get `b`. + * E.g., true for "abcdef" and "bdf". + * But not true for "abcdef" and "dbf". + */ function stringContainsCharactersInOrder(str, characters) { if (characters.length === 0) { return true; @@ -76305,8 +91544,13 @@ var ts; } } } + // Did not find all characters return false; } + /** + * Finds the first node that "embraces" the position, so that one may + * accurately aggregate locals from the closest containing scope. + */ function getScopeNode(initialToken, position, sourceFile) { var scope = initialToken; while (scope && !ts.positionBelongsToNode(scope, position, sourceFile)) { @@ -76324,15 +91568,15 @@ var ts; return result; } function isInJsxText(contextToken) { - if (contextToken.kind === 10) { + if (contextToken.kind === 10 /* JsxText */) { return true; } - if (contextToken.kind === 29 && contextToken.parent) { - if (contextToken.parent.kind === 257) { + if (contextToken.kind === 29 /* GreaterThanToken */ && contextToken.parent) { + if (contextToken.parent.kind === 257 /* JsxOpeningElement */) { return true; } - if (contextToken.parent.kind === 258 || contextToken.parent.kind === 256) { - return !!contextToken.parent.parent && contextToken.parent.parent.kind === 255; + if (contextToken.parent.kind === 258 /* JsxClosingElement */ || contextToken.parent.kind === 256 /* JsxSelfClosingElement */) { + return !!contextToken.parent.parent && contextToken.parent.parent.kind === 255 /* JsxElement */; } } return false; @@ -76341,149 +91585,201 @@ var ts; if (previousToken) { var containingNodeKind = previousToken.parent.kind; switch (previousToken.kind) { - case 26: - return containingNodeKind === 187 - || containingNodeKind === 155 - || containingNodeKind === 188 - || containingNodeKind === 183 - || containingNodeKind === 200 - || containingNodeKind === 163; - case 19: - return containingNodeKind === 187 - || containingNodeKind === 155 - || containingNodeKind === 188 - || containingNodeKind === 191 - || containingNodeKind === 173; - case 21: - return containingNodeKind === 183 - || containingNodeKind === 160 - || containingNodeKind === 147; - case 129: - case 130: + case 26 /* CommaToken */: + return containingNodeKind === 187 /* CallExpression */ // func( a, | + || containingNodeKind === 155 /* Constructor */ // constructor( a, | /* public, protected, private keywords are allowed here, so show completion */ + || containingNodeKind === 188 /* NewExpression */ // new C(a, | + || containingNodeKind === 183 /* ArrayLiteralExpression */ // [a, | + || containingNodeKind === 200 /* BinaryExpression */ // const x = (a, | + || containingNodeKind === 163 /* FunctionType */; // var x: (s: string, list| + case 19 /* OpenParenToken */: + return containingNodeKind === 187 /* CallExpression */ // func( | + || containingNodeKind === 155 /* Constructor */ // constructor( | + || containingNodeKind === 188 /* NewExpression */ // new C(a| + || containingNodeKind === 191 /* ParenthesizedExpression */ // const x = (a| + || containingNodeKind === 173 /* ParenthesizedType */; // function F(pred: (a| /* this can become an arrow function, where 'a' is the argument */ + case 21 /* OpenBracketToken */: + return containingNodeKind === 183 /* ArrayLiteralExpression */ // [ | + || containingNodeKind === 160 /* IndexSignature */ // [ | : string ] + || containingNodeKind === 147 /* ComputedPropertyName */; // [ | /* this can become an index signature */ + case 129 /* ModuleKeyword */: // module | + case 130 /* NamespaceKeyword */: // namespace | return true; - case 23: - return containingNodeKind === 239; - case 17: - return containingNodeKind === 235; - case 58: - return containingNodeKind === 232 - || containingNodeKind === 200; - case 14: - return containingNodeKind === 202; - case 15: - return containingNodeKind === 211; - case 114: - case 112: - case 113: - return containingNodeKind === 152; + case 23 /* DotToken */: + return containingNodeKind === 239 /* ModuleDeclaration */; // module A.| + case 17 /* OpenBraceToken */: + return containingNodeKind === 235 /* ClassDeclaration */; // class A{ | + case 58 /* EqualsToken */: + return containingNodeKind === 232 /* VariableDeclaration */ // const x = a| + || containingNodeKind === 200 /* BinaryExpression */; // x = a| + case 14 /* TemplateHead */: + return containingNodeKind === 202 /* TemplateExpression */; // `aa ${| + case 15 /* TemplateMiddle */: + return containingNodeKind === 211 /* TemplateSpan */; // `aa ${10} dd ${| + case 114 /* PublicKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: + return containingNodeKind === 152 /* PropertyDeclaration */; // class A{ public | } + // Previous token may have been a keyword that was converted to an identifier. switch (keywordForNode(previousToken)) { - case 114: - case 113: - case 112: + case 114 /* PublicKeyword */: + case 113 /* ProtectedKeyword */: + case 112 /* PrivateKeyword */: return true; } } return false; } function isInStringOrRegularExpressionOrTemplateLiteral(contextToken) { + // To be "in" one of these literals, the position has to be: + // 1. entirely within the token text. + // 2. at the end position of an unterminated token. + // 3. at the end of a regular expression (due to trailing flags like '/foo/g'). return (ts.isRegularExpressionLiteral(contextToken) || ts.isStringTextContainingNode(contextToken)) && (ts.rangeContainsPositionExclusive(ts.createTextRangeFromSpan(ts.createTextSpanFromNode(contextToken)), position) || position === contextToken.end && (!!contextToken.isUnterminated || ts.isRegularExpressionLiteral(contextToken))); } + /** + * Aggregates relevant symbols for completion in object literals and object binding patterns. + * Relevant symbols are stored in the captured 'symbols' variable. + * + * @returns true if 'symbols' was successfully populated; false otherwise. + */ function tryGetObjectLikeCompletionSymbols() { var objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken); if (!objectLikeContainer) - return 0; - completionKind = 0; + return 0 /* Continue */; + // We're looking up possible property names from contextual/inferred/declared type. + completionKind = 0 /* ObjectPropertyDeclaration */; var typeMembers; var existingMembers; - if (objectLikeContainer.kind === 184) { + if (objectLikeContainer.kind === 184 /* ObjectLiteralExpression */) { var typeForObject = typeChecker.getContextualType(objectLikeContainer); if (!typeForObject) - return 2; + return 2 /* Fail */; isNewIdentifierLocation = hasIndexSignature(typeForObject); - typeMembers = getPropertiesForCompletion(typeForObject, typeChecker, false); + typeMembers = getPropertiesForCompletion(typeForObject, typeChecker, /*isForAccess*/ false); existingMembers = objectLikeContainer.properties; } else { - ts.Debug.assert(objectLikeContainer.kind === 180); + ts.Debug.assert(objectLikeContainer.kind === 180 /* ObjectBindingPattern */); + // We are *only* completing on properties from the type being destructured. isNewIdentifierLocation = false; var rootDeclaration = ts.getRootDeclaration(objectLikeContainer.parent); if (!ts.isVariableLike(rootDeclaration)) return ts.Debug.fail("Root declaration is not variable-like."); - var canGetType = ts.hasInitializer(rootDeclaration) || ts.hasType(rootDeclaration) || rootDeclaration.parent.parent.kind === 222; - if (!canGetType && rootDeclaration.kind === 149) { + // We don't want to complete using the type acquired by the shape + // of the binding pattern; we are only interested in types acquired + // through type declaration or inference. + // Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed - + // type of parameter will flow in from the contextual type of the function + var canGetType = ts.hasInitializer(rootDeclaration) || ts.hasType(rootDeclaration) || rootDeclaration.parent.parent.kind === 222 /* ForOfStatement */; + if (!canGetType && rootDeclaration.kind === 149 /* Parameter */) { if (ts.isExpression(rootDeclaration.parent)) { canGetType = !!typeChecker.getContextualType(rootDeclaration.parent); } - else if (rootDeclaration.parent.kind === 154 || rootDeclaration.parent.kind === 157) { + else if (rootDeclaration.parent.kind === 154 /* MethodDeclaration */ || rootDeclaration.parent.kind === 157 /* SetAccessor */) { canGetType = ts.isExpression(rootDeclaration.parent.parent) && !!typeChecker.getContextualType(rootDeclaration.parent.parent); } } if (canGetType) { var typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer); if (!typeForObject) - return 2; - typeMembers = typeChecker.getPropertiesOfType(typeForObject).filter(function (symbol) { return !(ts.getDeclarationModifierFlagsFromSymbol(symbol) & 24); }); + return 2 /* Fail */; + // In a binding pattern, get only known properties. Everywhere else we will get all possible properties. + typeMembers = typeChecker.getPropertiesOfType(typeForObject).filter(function (symbol) { return !(ts.getDeclarationModifierFlagsFromSymbol(symbol) & 24 /* NonPublicAccessibilityModifier */); }); existingMembers = objectLikeContainer.elements; } } if (typeMembers && typeMembers.length > 0) { + // Add filtered items to the completion list symbols = filterObjectMembersList(typeMembers, ts.Debug.assertDefined(existingMembers)); } - return 1; + return 1 /* Success */; } + /** + * Aggregates relevant symbols for completion in import clauses and export clauses + * whose declarations have a module specifier; for instance, symbols will be aggregated for + * + * import { | } from "moduleName"; + * export { a as foo, | } from "moduleName"; + * + * but not for + * + * export { | }; + * + * Relevant symbols are stored in the captured 'symbols' variable. + * + * @returns true if 'symbols' was successfully populated; false otherwise. + */ function tryGetImportOrExportClauseCompletionSymbols() { - var namedImportsOrExports = contextToken && (contextToken.kind === 17 || contextToken.kind === 26) + // `import { |` or `import { a as 0, | }` + var namedImportsOrExports = contextToken && (contextToken.kind === 17 /* OpenBraceToken */ || contextToken.kind === 26 /* CommaToken */) ? ts.tryCast(contextToken.parent, ts.isNamedImportsOrExports) : undefined; if (!namedImportsOrExports) - return 0; - var moduleSpecifier = (namedImportsOrExports.kind === 247 ? namedImportsOrExports.parent.parent : namedImportsOrExports.parent).moduleSpecifier; - var moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier); + return 0 /* Continue */; + // cursor is in an import clause + // try to show exported member for imported module + var moduleSpecifier = (namedImportsOrExports.kind === 247 /* NamedImports */ ? namedImportsOrExports.parent.parent : namedImportsOrExports.parent).moduleSpecifier; + var moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier); // TODO: GH#18217 if (!moduleSpecifierSymbol) - return 2; - completionKind = 3; + return 2 /* Fail */; + completionKind = 3 /* MemberLike */; isNewIdentifierLocation = false; var exports = typeChecker.getExportsAndPropertiesOfModule(moduleSpecifierSymbol); var existing = ts.arrayToSet(namedImportsOrExports.elements, function (n) { return isCurrentlyEditingNode(n) ? undefined : (n.propertyName || n.name).escapedText; }); - symbols = exports.filter(function (e) { return e.escapedName !== "default" && !existing.get(e.escapedName); }); - return 1; + symbols = exports.filter(function (e) { return e.escapedName !== "default" /* Default */ && !existing.get(e.escapedName); }); + return 1 /* Success */; } + /** + * Aggregates relevant symbols for completion in class declaration + * Relevant symbols are stored in the captured 'symbols' variable. + */ function tryGetClassLikeCompletionSymbols() { var decl = tryGetObjectTypeDeclarationCompletionContainer(sourceFile, contextToken, location); if (!decl) - return 0; - completionKind = 3; + return 0 /* Continue */; + // We're looking up possible property names from parent type. + completionKind = 3 /* MemberLike */; + // Declaring new property/method/accessor isNewIdentifierLocation = true; - keywordFilters = ts.isClassLike(decl) ? 1 : 2; + keywordFilters = ts.isClassLike(decl) ? 1 /* ClassElementKeywords */ : 2 /* InterfaceElementKeywords */; + // If you're in an interface you don't want to repeat things from super-interface. So just stop here. if (!ts.isClassLike(decl)) - return 1; + return 1 /* Success */; var classElement = contextToken.parent; - var classElementModifierFlags = ts.isClassElement(classElement) ? ts.getModifierFlags(classElement) : 0; - if (contextToken.kind === 71 && !isCurrentlyEditingNode(contextToken)) { + var classElementModifierFlags = ts.isClassElement(classElement) ? ts.getModifierFlags(classElement) : 0 /* None */; + // If this is context token is not something we are editing now, consider if this would lead to be modifier + if (contextToken.kind === 71 /* Identifier */ && !isCurrentlyEditingNode(contextToken)) { switch (contextToken.getText()) { case "private": - classElementModifierFlags = classElementModifierFlags | 8; + classElementModifierFlags = classElementModifierFlags | 8 /* Private */; break; case "static": - classElementModifierFlags = classElementModifierFlags | 32; + classElementModifierFlags = classElementModifierFlags | 32 /* Static */; break; } } - if (!(classElementModifierFlags & 8)) { + // No member list for private methods + if (!(classElementModifierFlags & 8 /* Private */)) { + // List of property symbols of base type that are not private and already implemented var baseSymbols = ts.flatMap(ts.getAllSuperTypeNodes(decl), function (baseTypeNode) { - var type = typeChecker.getTypeAtLocation(baseTypeNode); - return typeChecker.getPropertiesOfType(classElementModifierFlags & 32 ? typeChecker.getTypeOfSymbolAtLocation(type.symbol, decl) : type); + var type = typeChecker.getTypeAtLocation(baseTypeNode); // TODO: GH#18217 + return typeChecker.getPropertiesOfType(classElementModifierFlags & 32 /* Static */ ? typeChecker.getTypeOfSymbolAtLocation(type.symbol, decl) : type); }); symbols = filterClassMembersList(baseSymbols, decl.members, classElementModifierFlags); } - return 1; + return 1 /* Success */; } + /** + * Returns the immediate owning object literal or binding pattern of a context token, + * on the condition that one exists and that the context implies completion should be given. + */ function tryGetObjectLikeCompletionContainer(contextToken) { if (contextToken) { switch (contextToken.kind) { - case 17: - case 26: + case 17 /* OpenBraceToken */: // const x = { | + case 26 /* CommaToken */: // const x = { a: 0, | var parent = contextToken.parent; if (ts.isObjectLiteralExpression(parent) || ts.isObjectBindingPattern(parent)) { return parent; @@ -76497,12 +91793,16 @@ var ts; return !!node.parent && ts.isParameter(node.parent) && ts.isConstructorDeclaration(node.parent.parent) && (ts.isParameterPropertyModifier(node.kind) || ts.isDeclarationName(node)); } + /** + * Returns the immediate owning class declaration of a context token, + * on the condition that one exists and that the context implies completion should be given. + */ function tryGetConstructorLikeCompletionContainer(contextToken) { if (contextToken) { var parent = contextToken.parent; switch (contextToken.kind) { - case 19: - case 26: + case 19 /* OpenParenToken */: + case 26 /* CommaToken */: return ts.isConstructorDeclaration(contextToken.parent) ? contextToken.parent : undefined; default: if (isConstructorParameterCompletion(contextToken)) { @@ -76532,32 +91832,52 @@ var ts; if (contextToken) { var parent = contextToken.parent; switch (contextToken.kind) { - case 28: - case 41: - case 71: - case 185: - case 263: - case 262: - case 264: - if (parent && (parent.kind === 256 || parent.kind === 257)) { + case 28 /* LessThanSlashToken */: + case 41 /* SlashToken */: + case 71 /* Identifier */: + case 185 /* PropertyAccessExpression */: + case 263 /* JsxAttributes */: + case 262 /* JsxAttribute */: + case 264 /* JsxSpreadAttribute */: + if (parent && (parent.kind === 256 /* JsxSelfClosingElement */ || parent.kind === 257 /* JsxOpeningElement */)) { return parent; } - else if (parent.kind === 262) { + else if (parent.kind === 262 /* JsxAttribute */) { + // Currently we parse JsxOpeningLikeElement as: + // JsxOpeningLikeElement + // attributes: JsxAttributes + // properties: NodeArray return parent.parent.parent; } break; - case 9: - if (parent && ((parent.kind === 262) || (parent.kind === 264))) { + // The context token is the closing } or " of an attribute, which means + // its parent is a JsxExpression, whose parent is a JsxAttribute, + // whose parent is a JsxOpeningLikeElement + case 9 /* StringLiteral */: + if (parent && ((parent.kind === 262 /* JsxAttribute */) || (parent.kind === 264 /* JsxSpreadAttribute */))) { + // Currently we parse JsxOpeningLikeElement as: + // JsxOpeningLikeElement + // attributes: JsxAttributes + // properties: NodeArray return parent.parent.parent; } break; - case 18: + case 18 /* CloseBraceToken */: if (parent && - parent.kind === 265 && - parent.parent && parent.parent.kind === 262) { + parent.kind === 265 /* JsxExpression */ && + parent.parent && parent.parent.kind === 262 /* JsxAttribute */) { + // Currently we parse JsxOpeningLikeElement as: + // JsxOpeningLikeElement + // attributes: JsxAttributes + // properties: NodeArray + // each JsxAttribute can have initializer as JsxExpression return parent.parent.parent.parent; } - if (parent && parent.kind === 264) { + if (parent && parent.kind === 264 /* JsxSpreadAttribute */) { + // Currently we parse JsxOpeningLikeElement as: + // JsxOpeningLikeElement + // attributes: JsxAttributes + // properties: NodeArray return parent.parent.parent; } break; @@ -76565,111 +91885,132 @@ var ts; } return undefined; } + /** + * @returns true if we are certain that the currently edited location must define a new location; false otherwise. + */ function isSolelyIdentifierDefinitionLocation(contextToken) { var parent = contextToken.parent; var containingNodeKind = parent.kind; switch (contextToken.kind) { - case 26: - return containingNodeKind === 232 || - containingNodeKind === 233 || - containingNodeKind === 214 || - containingNodeKind === 238 || + case 26 /* CommaToken */: + return containingNodeKind === 232 /* VariableDeclaration */ || + containingNodeKind === 233 /* VariableDeclarationList */ || + containingNodeKind === 214 /* VariableStatement */ || + containingNodeKind === 238 /* EnumDeclaration */ || // enum a { foo, | isFunctionLikeButNotConstructor(containingNodeKind) || - containingNodeKind === 236 || - containingNodeKind === 181 || - containingNodeKind === 237 || + containingNodeKind === 236 /* InterfaceDeclaration */ || // interface A= contextToken.pos); - case 23: - return containingNodeKind === 181; - case 56: - return containingNodeKind === 182; - case 21: - return containingNodeKind === 181; - case 19: - return containingNodeKind === 269 || + case 23 /* DotToken */: + return containingNodeKind === 181 /* ArrayBindingPattern */; // var [.| + case 56 /* ColonToken */: + return containingNodeKind === 182 /* BindingElement */; // var {x :html| + case 21 /* OpenBracketToken */: + return containingNodeKind === 181 /* ArrayBindingPattern */; // var [x| + case 19 /* OpenParenToken */: + return containingNodeKind === 269 /* CatchClause */ || isFunctionLikeButNotConstructor(containingNodeKind); - case 17: - return containingNodeKind === 238; - case 27: - return containingNodeKind === 235 || - containingNodeKind === 205 || - containingNodeKind === 236 || - containingNodeKind === 237 || + case 17 /* OpenBraceToken */: + return containingNodeKind === 238 /* EnumDeclaration */; // enum a { | + case 27 /* LessThanToken */: + return containingNodeKind === 235 /* ClassDeclaration */ || // class A< | + containingNodeKind === 205 /* ClassExpression */ || // var C = class D< | + containingNodeKind === 236 /* InterfaceDeclaration */ || // interface A< | + containingNodeKind === 237 /* TypeAliasDeclaration */ || // type List< | ts.isFunctionLikeKind(containingNodeKind); - case 115: - return containingNodeKind === 152 && !ts.isClassLike(parent.parent); - case 24: - return containingNodeKind === 149 || - (!!parent.parent && parent.parent.kind === 181); - case 114: - case 112: - case 113: - return containingNodeKind === 149 && !ts.isConstructorDeclaration(parent.parent); - case 118: - return containingNodeKind === 248 || - containingNodeKind === 252 || - containingNodeKind === 246; - case 125: - case 136: + case 115 /* StaticKeyword */: + return containingNodeKind === 152 /* PropertyDeclaration */ && !ts.isClassLike(parent.parent); + case 24 /* DotDotDotToken */: + return containingNodeKind === 149 /* Parameter */ || + (!!parent.parent && parent.parent.kind === 181 /* ArrayBindingPattern */); // var [...z| + case 114 /* PublicKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: + return containingNodeKind === 149 /* Parameter */ && !ts.isConstructorDeclaration(parent.parent); + case 118 /* AsKeyword */: + return containingNodeKind === 248 /* ImportSpecifier */ || + containingNodeKind === 252 /* ExportSpecifier */ || + containingNodeKind === 246 /* NamespaceImport */; + case 125 /* GetKeyword */: + case 136 /* SetKeyword */: if (isFromObjectTypeDeclaration(contextToken)) { return false; } - case 75: - case 83: - case 109: - case 89: - case 104: - case 91: - case 110: - case 76: - case 116: - case 139: + // falls through + case 75 /* ClassKeyword */: + case 83 /* EnumKeyword */: + case 109 /* InterfaceKeyword */: + case 89 /* FunctionKeyword */: + case 104 /* VarKeyword */: + case 91 /* ImportKeyword */: + case 110 /* LetKeyword */: + case 76 /* ConstKeyword */: + case 116 /* YieldKeyword */: + case 139 /* TypeKeyword */: // type htm| return true; } + // If the previous token is keyword correspoding to class member completion keyword + // there will be completion available here if (isClassMemberCompletionKeyword(keywordForNode(contextToken)) && isFromObjectTypeDeclaration(contextToken)) { return false; } if (isConstructorParameterCompletion(contextToken)) { + // constructor parameter completion is available only if + // - its modifier of the constructor parameter or + // - its name of the parameter and not being edited + // eg. constructor(a |<- this shouldnt show completion if (!ts.isIdentifier(contextToken) || ts.isParameterPropertyModifier(keywordForNode(contextToken)) || isCurrentlyEditingNode(contextToken)) { return false; } } + // Previous token may have been a keyword that was converted to an identifier. switch (keywordForNode(contextToken)) { - case 117: - case 120: - case 75: - case 76: - case 124: - case 83: - case 89: - case 109: - case 110: - case 112: - case 113: - case 114: - case 115: - case 104: - case 116: + case 117 /* AbstractKeyword */: + case 120 /* AsyncKeyword */: + case 75 /* ClassKeyword */: + case 76 /* ConstKeyword */: + case 124 /* DeclareKeyword */: + case 83 /* EnumKeyword */: + case 89 /* FunctionKeyword */: + case 109 /* InterfaceKeyword */: + case 110 /* LetKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: + case 114 /* PublicKeyword */: + case 115 /* StaticKeyword */: + case 104 /* VarKeyword */: + case 116 /* YieldKeyword */: return true; } return ts.isDeclarationName(contextToken) && !ts.isJsxAttribute(contextToken.parent) + // Don't block completions if we're in `class C /**/`, because we're *past* the end of the identifier and might want to complete `extends`. + // If `contextToken !== previousToken`, this is `class C ex/**/`. && !(ts.isClassLike(contextToken.parent) && (contextToken !== previousToken || position > previousToken.end)); } function isFunctionLikeButNotConstructor(kind) { - return ts.isFunctionLikeKind(kind) && kind !== 155; + return ts.isFunctionLikeKind(kind) && kind !== 155 /* Constructor */; } function isDotOfNumericLiteral(contextToken) { - if (contextToken.kind === 8) { + if (contextToken.kind === 8 /* NumericLiteral */) { var text = contextToken.getFullText(); return text.charAt(text.length - 1) === "."; } return false; } + /** + * Filters out completion suggestions for named imports or exports. + * + * @returns Symbols to be suggested in an object binding pattern or object literal expression, barring those whose declarations + * do not occur at the current position and have not otherwise been typed. + */ function filterObjectMembersList(contextualMemberSymbols, existingMembers) { if (existingMembers.length === 0) { return contextualMemberSymbols; @@ -76677,48 +92018,63 @@ var ts; var existingMemberNames = ts.createUnderscoreEscapedMap(); for (var _i = 0, existingMembers_1 = existingMembers; _i < existingMembers_1.length; _i++) { var m = existingMembers_1[_i]; - if (m.kind !== 270 && - m.kind !== 271 && - m.kind !== 182 && - m.kind !== 154 && - m.kind !== 156 && - m.kind !== 157) { + // Ignore omitted expressions for missing members + if (m.kind !== 270 /* PropertyAssignment */ && + m.kind !== 271 /* ShorthandPropertyAssignment */ && + m.kind !== 182 /* BindingElement */ && + m.kind !== 154 /* MethodDeclaration */ && + m.kind !== 156 /* GetAccessor */ && + m.kind !== 157 /* SetAccessor */) { continue; } + // If this is the current item we are editing right now, do not filter it out if (isCurrentlyEditingNode(m)) { continue; } var existingName = void 0; if (ts.isBindingElement(m) && m.propertyName) { - if (m.propertyName.kind === 71) { + // include only identifiers in completion list + if (m.propertyName.kind === 71 /* Identifier */) { existingName = m.propertyName.escapedText; } } else { + // TODO: Account for computed property name + // NOTE: if one only performs this step when m.name is an identifier, + // things like '__proto__' are not filtered out. var name = ts.getNameOfDeclaration(m); existingName = ts.isPropertyNameLiteral(name) ? ts.getEscapedTextOfIdentifierOrLiteral(name) : undefined; } - existingMemberNames.set(existingName, true); + existingMemberNames.set(existingName, true); // TODO: GH#18217 } return contextualMemberSymbols.filter(function (m) { return !existingMemberNames.get(m.escapedName); }); } + /** + * Filters out completion suggestions for class elements. + * + * @returns Symbols to be suggested in an class element depending on existing memebers and symbol flags + */ function filterClassMembersList(baseSymbols, existingMembers, currentClassElementModifierFlags) { var existingMemberNames = ts.createUnderscoreEscapedMap(); for (var _i = 0, existingMembers_2 = existingMembers; _i < existingMembers_2.length; _i++) { var m = existingMembers_2[_i]; - if (m.kind !== 152 && - m.kind !== 154 && - m.kind !== 156 && - m.kind !== 157) { + // Ignore omitted expressions for missing members + if (m.kind !== 152 /* PropertyDeclaration */ && + m.kind !== 154 /* MethodDeclaration */ && + m.kind !== 156 /* GetAccessor */ && + m.kind !== 157 /* SetAccessor */) { continue; } + // If this is the current item we are editing right now, do not filter it out if (isCurrentlyEditingNode(m)) { continue; } - if (ts.hasModifier(m, 8)) { + // Dont filter member even if the name matches if it is declared private in the list + if (ts.hasModifier(m, 8 /* Private */)) { continue; } - if (ts.hasModifier(m, 32) !== !!(currentClassElementModifierFlags & 32)) { + // do not filter it out if the static presence doesnt match + if (ts.hasModifier(m, 32 /* Static */) !== !!(currentClassElementModifierFlags & 32 /* Static */)) { continue; } var existingName = ts.getPropertyNameForPropertyNameNode(m.name); @@ -76729,17 +92085,24 @@ var ts; return baseSymbols.filter(function (propertySymbol) { return !existingMemberNames.has(propertySymbol.escapedName) && !!propertySymbol.declarations && - !(ts.getDeclarationModifierFlagsFromSymbol(propertySymbol) & 8); + !(ts.getDeclarationModifierFlagsFromSymbol(propertySymbol) & 8 /* Private */); }); } + /** + * Filters out completion suggestions from 'symbols' according to existing JSX attributes. + * + * @returns Symbols to be suggested in a JSX element, barring those whose attributes + * do not occur at the current position and have not otherwise been typed. + */ function filterJsxAttributes(symbols, attributes) { var seenNames = ts.createUnderscoreEscapedMap(); for (var _i = 0, attributes_1 = attributes; _i < attributes_1.length; _i++) { var attr = attributes_1[_i]; + // If this is the current item we are editing right now, do not filter it out if (isCurrentlyEditingNode(attr)) { continue; } - if (attr.kind === 262) { + if (attr.kind === 262 /* JsxAttribute */) { seenNames.set(attr.name.escapedText, true); } } @@ -76752,7 +92115,10 @@ var ts; function getCompletionEntryDisplayNameForSymbol(symbol, target, origin, kind) { var name = getSymbolName(symbol, origin, target); if (name === undefined - || symbol.flags & 1536 && ts.startsWithQuote(name) + // If the symbol is external module, don't show it in the completion list + // (i.e declare module "http" { const x; } | // <= request completion here, "http" should not be there) + || symbol.flags & 1536 /* Module */ && ts.startsWithQuote(name) + // If the symbol is the internal name of an ES symbol, it is not a valid entry. Internal names for ES symbols start with "__@" || ts.isKnownSymbol(symbol)) { return undefined; } @@ -76760,28 +92126,31 @@ var ts; if (ts.isIdentifierText(name, target)) return validIdentiferResult; switch (kind) { - case 3: + case 3 /* MemberLike */: return undefined; - case 0: + case 0 /* ObjectPropertyDeclaration */: + // TODO: GH#18169 return { name: JSON.stringify(name), needsConvertPropertyAccess: false }; - case 2: - case 1: - return name.charCodeAt(0) === 32 ? undefined : { name: name, needsConvertPropertyAccess: true }; - case 5: - case 4: + case 2 /* PropertyAccess */: + case 1 /* Global */: // For a 'this.' completion it will be in a global context, but may have a non-identifier name. + // Don't add a completion for a name starting with a space. See https://github.com/Microsoft/TypeScript/pull/20547 + return name.charCodeAt(0) === 32 /* space */ ? undefined : { name: name, needsConvertPropertyAccess: true }; + case 5 /* None */: + case 4 /* String */: return validIdentiferResult; default: ts.Debug.assertNever(kind); } } + // A cache of completion entries for keywords, these do not change between sessions var _keywordCompletions = []; var allKeywordsCompletions = ts.memoize(function () { var res = []; - for (var i = 72; i <= 145; i++) { + for (var i = 72 /* FirstKeyword */; i <= 145 /* LastKeyword */; i++) { res.push({ name: ts.tokenToString(i), - kind: "keyword", - kindModifiers: "", + kind: "keyword" /* keyword */, + kindModifiers: "" /* none */, sortText: "0" }); } @@ -76791,17 +92160,18 @@ var ts; return _keywordCompletions[keywordFilter] || (_keywordCompletions[keywordFilter] = allKeywordsCompletions().filter(function (entry) { var kind = ts.stringToToken(entry.name); switch (keywordFilter) { - case 0: - return kind !== 140; - case 1: + case 0 /* None */: + // "undefined" is a global variable, so don't need a keyword completion for it. + return kind !== 140 /* UndefinedKeyword */; + case 1 /* ClassElementKeywords */: return isClassMemberCompletionKeyword(kind); - case 2: + case 2 /* InterfaceElementKeywords */: return isInterfaceOrTypeLiteralCompletionKeyword(kind); - case 3: + case 3 /* ConstructorParameterKeywords */: return ts.isParameterPropertyModifier(kind); - case 4: + case 4 /* FunctionLikeBodyKeywords */: return !isClassMemberCompletionKeyword(kind); - case 5: + case 5 /* TypeKeywords */: return ts.isTypeKeyword(kind); default: return ts.Debug.assertNever(keywordFilter); @@ -76809,34 +92179,35 @@ var ts; })); } function isInterfaceOrTypeLiteralCompletionKeyword(kind) { - return kind === 132; + return kind === 132 /* ReadonlyKeyword */; } function isClassMemberCompletionKeyword(kind) { switch (kind) { - case 117: - case 123: - case 125: - case 136: - case 120: + case 117 /* AbstractKeyword */: + case 123 /* ConstructorKeyword */: + case 125 /* GetKeyword */: + case 136 /* SetKeyword */: + case 120 /* AsyncKeyword */: return true; default: return ts.isClassMemberModifier(kind); } } function keywordForNode(node) { - return ts.isIdentifier(node) ? node.originalKeywordKind || 0 : node.kind; + return ts.isIdentifier(node) ? node.originalKeywordKind || 0 /* Unknown */ : node.kind; } function isEqualityOperatorKind(kind) { switch (kind) { - case 34: - case 32: - case 35: - case 33: + case 34 /* EqualsEqualsEqualsToken */: + case 32 /* EqualsEqualsToken */: + case 35 /* ExclamationEqualsEqualsToken */: + case 33 /* ExclamationEqualsToken */: return true; default: return false; } } + /** Get the corresponding JSDocTag node if the position is in a jsDoc comment */ function getJsDocTagAtPosition(node, position) { var jsDoc = getJsDocHavingNode(node).jsDoc; if (!jsDoc) @@ -76857,52 +92228,65 @@ var ts; if (!ts.isToken(node)) return node; switch (node.kind) { - case 104: - case 110: - case 76: + case 104 /* VarKeyword */: + case 110 /* LetKeyword */: + case 76 /* ConstKeyword */: + // if the current token is var, let or const, skip the VariableDeclarationList return node.parent.parent; default: return node.parent; } } + /** + * Gets all properties on a type, but if that type is a union of several types, + * excludes array-like types or callable/constructable types. + */ function getPropertiesForCompletion(type, checker, isForAccess) { if (!(type.isUnion())) { return ts.Debug.assertEachDefined(type.getApparentProperties(), "getApparentProperties() should all be defined"); } + // If we're providing completions for an object literal, skip primitive, array-like, or callable types since those shouldn't be implemented by object literals. var filteredTypes = isForAccess ? type.types : type.types.filter(function (memberType) { - return !(memberType.flags & 32764 || checker.isArrayLikeType(memberType) || ts.typeHasCallOrConstructSignatures(memberType, checker)); + return !(memberType.flags & 32764 /* Primitive */ || checker.isArrayLikeType(memberType) || ts.typeHasCallOrConstructSignatures(memberType, checker)); }); return ts.Debug.assertEachDefined(checker.getAllPossiblePropertiesOfTypes(filteredTypes), "getAllPossiblePropertiesOfTypes() should all be defined"); } + /** + * Returns the immediate owning class declaration of a context token, + * on the condition that one exists and that the context implies completion should be given. + */ function tryGetObjectTypeDeclarationCompletionContainer(sourceFile, contextToken, location) { + // class c { method() { } | method2() { } } switch (location.kind) { - case 300: + case 300 /* SyntaxList */: return ts.tryCast(location.parent, ts.isObjectTypeDeclaration); - case 1: + case 1 /* EndOfFileToken */: var cls = ts.tryCast(ts.lastOrUndefined(ts.cast(location.parent, ts.isSourceFile).statements), ts.isObjectTypeDeclaration); - if (cls && !ts.findChildOfKind(cls, 18, sourceFile)) { + if (cls && !ts.findChildOfKind(cls, 18 /* CloseBraceToken */, sourceFile)) { return cls; } } if (!contextToken) return undefined; switch (contextToken.kind) { - case 25: - case 18: + case 25 /* SemicolonToken */: // class c {getValue(): number; | } + case 18 /* CloseBraceToken */: // class c { method() { } | } + // class c { method() { } b| } return isFromObjectTypeDeclaration(location) && location.parent.name === location ? location.parent.parent : ts.tryCast(location, ts.isObjectTypeDeclaration); - case 17: - case 26: + case 17 /* OpenBraceToken */: // class c { | + case 26 /* CommaToken */: // class c {getValue(): number, | } return ts.tryCast(contextToken.parent, ts.isObjectTypeDeclaration); default: if (!isFromObjectTypeDeclaration(contextToken)) return undefined; var isValidKeyword = ts.isClassLike(contextToken.parent.parent) ? isClassMemberCompletionKeyword : isInterfaceOrTypeLiteralCompletionKeyword; - return (isValidKeyword(contextToken.kind) || ts.isIdentifier(contextToken) && isValidKeyword(ts.stringToToken(contextToken.text))) + return (isValidKeyword(contextToken.kind) || ts.isIdentifier(contextToken) && isValidKeyword(ts.stringToToken(contextToken.text))) // TODO: GH#18217 ? contextToken.parent.parent : undefined; } } + // TODO: GH#19856 Would like to return `node is Node & { parent: (ClassElement | TypeElement) & { parent: ObjectTypeDeclaration } }` but then compilation takes > 10 minutes function isFromObjectTypeDeclaration(node) { return node.parent && ts.isClassOrTypeElement(node.parent) && ts.isObjectTypeDeclaration(node.parent.parent); } @@ -76917,23 +92301,25 @@ var ts; case '"': case "'": case "`": + // Only automatically bring up completions if this is an opening quote. return isStringLiteralOrTemplate(contextToken) && position === contextToken.getStart(sourceFile) + 1; case "<": - return contextToken.kind === 27 && contextToken.parent.kind !== 200; + // Opening JSX tag + return contextToken.kind === 27 /* LessThanToken */ && contextToken.parent.kind !== 200 /* BinaryExpression */; case "/": return ts.isStringLiteralLike(contextToken) ? !!ts.tryGetImportFromModuleSpecifier(contextToken) - : contextToken.kind === 41 && ts.isJsxClosingElement(contextToken.parent); + : contextToken.kind === 41 /* SlashToken */ && ts.isJsxClosingElement(contextToken.parent); default: return ts.Debug.assertNever(triggerCharacter); } } function isStringLiteralOrTemplate(node) { switch (node.kind) { - case 9: - case 13: - case 202: - case 189: + case 9 /* StringLiteral */: + case 13 /* NoSubstitutionTemplateLiteral */: + case 202 /* TemplateExpression */: + case 189 /* TaggedTemplateExpression */: return true; default: return false; @@ -76941,6 +92327,7 @@ var ts; } })(Completions = ts.Completions || (ts.Completions = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var DocumentHighlights; @@ -76948,6 +92335,7 @@ var ts; function getDocumentHighlights(program, cancellationToken, sourceFile, position, sourceFilesToSearch) { var node = ts.getTouchingPropertyName(sourceFile, position); if (node.parent && (ts.isJsxOpeningElement(node.parent) && node.parent.tagName === node || ts.isJsxClosingElement(node.parent))) { + // For a JSX element, just highlight the matching tag, not all references. var _a = node.parent.parent, openingElement = _a.openingElement, closingElement = _a.closingElement; var highlightSpans = [openingElement, closingElement].map(function (_a) { var tagName = _a.tagName; @@ -76962,12 +92350,12 @@ var ts; return { fileName: sourceFile.fileName, textSpan: ts.createTextSpanFromNode(node, sourceFile), - kind: "none" + kind: "none" /* none */ }; } function getSemanticDocumentHighlights(position, node, program, cancellationToken, sourceFilesToSearch) { var sourceFilesSet = ts.arrayToSet(sourceFilesToSearch, function (f) { return f.fileName; }); - var referenceEntries = ts.FindAllReferences.getReferenceEntriesForNode(position, node, program, sourceFilesToSearch, cancellationToken, undefined, sourceFilesSet); + var referenceEntries = ts.FindAllReferences.getReferenceEntriesForNode(position, node, program, sourceFilesToSearch, cancellationToken, /*options*/ undefined, sourceFilesSet); if (!referenceEntries) return undefined; var map = ts.arrayToMultiMap(referenceEntries.map(ts.FindAllReferences.toHighlightSpan), function (e) { return e.fileName; }, function (e) { return e.span; }); @@ -76989,40 +92377,40 @@ var ts; } function getHighlightSpans(node, sourceFile) { switch (node.kind) { - case 90: - case 82: + case 90 /* IfKeyword */: + case 82 /* ElseKeyword */: return ts.isIfStatement(node.parent) ? getIfElseOccurrences(node.parent, sourceFile) : undefined; - case 96: + case 96 /* ReturnKeyword */: return useParent(node.parent, ts.isReturnStatement, getReturnOccurrences); - case 100: + case 100 /* ThrowKeyword */: return useParent(node.parent, ts.isThrowStatement, getThrowOccurrences); - case 102: - case 74: - case 87: - var tryStatement = node.kind === 74 ? node.parent.parent : node.parent; + case 102 /* TryKeyword */: + case 74 /* CatchKeyword */: + case 87 /* FinallyKeyword */: + var tryStatement = node.kind === 74 /* CatchKeyword */ ? node.parent.parent : node.parent; return useParent(tryStatement, ts.isTryStatement, getTryCatchFinallyOccurrences); - case 98: + case 98 /* SwitchKeyword */: return useParent(node.parent, ts.isSwitchStatement, getSwitchCaseDefaultOccurrences); - case 73: - case 79: + case 73 /* CaseKeyword */: + case 79 /* DefaultKeyword */: return useParent(node.parent.parent.parent, ts.isSwitchStatement, getSwitchCaseDefaultOccurrences); - case 72: - case 77: + case 72 /* BreakKeyword */: + case 77 /* ContinueKeyword */: return useParent(node.parent, ts.isBreakOrContinueStatement, getBreakOrContinueStatementOccurrences); - case 88: - case 106: - case 81: - return useParent(node.parent, function (n) { return ts.isIterationStatement(n, true); }, getLoopBreakContinueOccurrences); - case 123: - return getFromAllDeclarations(ts.isConstructorDeclaration, [123]); - case 125: - case 136: - return getFromAllDeclarations(ts.isAccessor, [125, 136]); - case 121: + case 88 /* ForKeyword */: + case 106 /* WhileKeyword */: + case 81 /* DoKeyword */: + return useParent(node.parent, function (n) { return ts.isIterationStatement(n, /*lookInLabeledStatements*/ true); }, getLoopBreakContinueOccurrences); + case 123 /* ConstructorKeyword */: + return getFromAllDeclarations(ts.isConstructorDeclaration, [123 /* ConstructorKeyword */]); + case 125 /* GetKeyword */: + case 136 /* SetKeyword */: + return getFromAllDeclarations(ts.isAccessor, [125 /* GetKeyword */, 136 /* SetKeyword */]); + case 121 /* AwaitKeyword */: return useParent(node.parent, ts.isAwaitExpression, getAsyncAndAwaitOccurrences); - case 120: + case 120 /* AsyncKeyword */: return highlightSpans(getAsyncAndAwaitOccurrences(node)); - case 116: + case 116 /* YieldKeyword */: return highlightSpans(getYieldOccurrences(node)); default: return ts.isModifierKind(node.kind) && (ts.isDeclaration(node.parent) || ts.isVariableStatement(node.parent)) @@ -77041,22 +92429,35 @@ var ts; return nodes && nodes.map(function (node) { return getHighlightSpanForNode(node, sourceFile); }); } } + /** + * Aggregates all throw-statements within this node *without* crossing + * into function boundaries and try-blocks with catch-clauses. + */ function aggregateOwnedThrowStatements(node) { if (ts.isThrowStatement(node)) { return [node]; } else if (ts.isTryStatement(node)) { + // Exceptions thrown within a try block lacking a catch clause are "owned" in the current context. return ts.concatenate(node.catchClause ? aggregateOwnedThrowStatements(node.catchClause) : node.tryBlock && aggregateOwnedThrowStatements(node.tryBlock), node.finallyBlock && aggregateOwnedThrowStatements(node.finallyBlock)); } + // Do not cross function boundaries. return ts.isFunctionLike(node) ? undefined : flatMapChildren(node, aggregateOwnedThrowStatements); } + /** + * For lack of a better name, this function takes a throw statement and returns the + * nearest ancestor that is a try-block (whose try statement has a catch clause), + * function-block, or source file. + */ function getThrowStatementOwner(throwStatement) { var child = throwStatement; while (child.parent) { var parent = child.parent; - if (ts.isFunctionBlock(parent) || parent.kind === 274) { + if (ts.isFunctionBlock(parent) || parent.kind === 274 /* SourceFile */) { return parent; } + // A throw-statement is only owned by a try-statement if the try-statement has + // a catch clause, and if the throw-statement occurs within the try block. if (ts.isTryStatement(parent) && parent.tryBlock === child && parent.catchClause) { return child; } @@ -77084,17 +92485,20 @@ var ts; function getBreakOrContinueOwner(statement) { return ts.findAncestor(statement, function (node) { switch (node.kind) { - case 227: - if (statement.kind === 223) { + case 227 /* SwitchStatement */: + if (statement.kind === 223 /* ContinueStatement */) { return false; } - case 220: - case 221: - case 222: - case 219: - case 218: + // falls through + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 219 /* WhileStatement */: + case 218 /* DoStatement */: return !statement.label || isLabeledBy(node, statement.label.escapedText); default: + // Don't cross function boundaries. + // TODO: GH#20090 return ts.isFunctionLike(node) && "quit"; } }); @@ -77110,33 +92514,37 @@ var ts; }); } function getNodesToSearchForModifier(declaration, modifierFlag) { + // Types of node whose children might have modifiers. var container = declaration.parent; switch (container.kind) { - case 240: - case 274: - case 213: - case 266: - case 267: - if (modifierFlag & 128 && ts.isClassDeclaration(declaration)) { + case 240 /* ModuleBlock */: + case 274 /* SourceFile */: + case 213 /* Block */: + case 266 /* CaseClause */: + case 267 /* DefaultClause */: + // Container is either a class declaration or the declaration is a classDeclaration + if (modifierFlag & 128 /* Abstract */ && ts.isClassDeclaration(declaration)) { return declaration.members.concat([declaration]); } else { return container.statements; } - case 155: - case 154: - case 234: + case 155 /* Constructor */: + case 154 /* MethodDeclaration */: + case 234 /* FunctionDeclaration */: return container.parameters.concat((ts.isClassLike(container.parent) ? container.parent.members : [])); - case 235: - case 205: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: var nodes = container.members; - if (modifierFlag & 28) { + // If we're an accessibility modifier, we're in an instance member and should search + // the constructor's parameter list for instance members as well. + if (modifierFlag & 28 /* AccessibilityModifier */) { var constructor = ts.find(container.members, ts.isConstructorDeclaration); if (constructor) { return nodes.concat(constructor.parameters); } } - else if (modifierFlag & 128) { + else if (modifierFlag & 128 /* Abstract */) { return nodes.concat([container]); } return nodes; @@ -77157,11 +92565,12 @@ var ts; } function getLoopBreakContinueOccurrences(loopNode) { var keywords = []; - if (pushKeywordIf(keywords, loopNode.getFirstToken(), 88, 106, 81)) { - if (loopNode.kind === 218) { + if (pushKeywordIf(keywords, loopNode.getFirstToken(), 88 /* ForKeyword */, 106 /* WhileKeyword */, 81 /* DoKeyword */)) { + // If we succeeded and got a do-while loop, then start looking for a 'while' keyword. + if (loopNode.kind === 218 /* DoStatement */) { var loopTokens = loopNode.getChildren(); for (var i = loopTokens.length - 1; i >= 0; i--) { - if (pushKeywordIf(keywords, loopTokens[i], 106)) { + if (pushKeywordIf(keywords, loopTokens[i], 106 /* WhileKeyword */)) { break; } } @@ -77169,7 +92578,7 @@ var ts; } ts.forEach(aggregateAllBreakAndContinueStatements(loopNode.statement), function (statement) { if (ownsBreakOrContinueStatement(loopNode, statement)) { - pushKeywordIf(keywords, statement.getFirstToken(), 72, 77); + pushKeywordIf(keywords, statement.getFirstToken(), 72 /* BreakKeyword */, 77 /* ContinueKeyword */); } }); return keywords; @@ -77178,13 +92587,13 @@ var ts; var owner = getBreakOrContinueOwner(breakOrContinueStatement); if (owner) { switch (owner.kind) { - case 220: - case 221: - case 222: - case 218: - case 219: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 218 /* DoStatement */: + case 219 /* WhileStatement */: return getLoopBreakContinueOccurrences(owner); - case 227: + case 227 /* SwitchStatement */: return getSwitchCaseDefaultOccurrences(owner); } } @@ -77192,12 +92601,13 @@ var ts; } function getSwitchCaseDefaultOccurrences(switchStatement) { var keywords = []; - pushKeywordIf(keywords, switchStatement.getFirstToken(), 98); + pushKeywordIf(keywords, switchStatement.getFirstToken(), 98 /* SwitchKeyword */); + // Go through each clause in the switch statement, collecting the 'case'/'default' keywords. ts.forEach(switchStatement.caseBlock.clauses, function (clause) { - pushKeywordIf(keywords, clause.getFirstToken(), 73, 79); + pushKeywordIf(keywords, clause.getFirstToken(), 73 /* CaseKeyword */, 79 /* DefaultKeyword */); ts.forEach(aggregateAllBreakAndContinueStatements(clause), function (statement) { if (ownsBreakOrContinueStatement(switchStatement, statement)) { - pushKeywordIf(keywords, statement.getFirstToken(), 72); + pushKeywordIf(keywords, statement.getFirstToken(), 72 /* BreakKeyword */); } }); }); @@ -77205,13 +92615,13 @@ var ts; } function getTryCatchFinallyOccurrences(tryStatement, sourceFile) { var keywords = []; - pushKeywordIf(keywords, tryStatement.getFirstToken(), 102); + pushKeywordIf(keywords, tryStatement.getFirstToken(), 102 /* TryKeyword */); if (tryStatement.catchClause) { - pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), 74); + pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), 74 /* CatchKeyword */); } if (tryStatement.finallyBlock) { - var finallyKeyword = ts.findChildOfKind(tryStatement, 87, sourceFile); - pushKeywordIf(keywords, finallyKeyword, 87); + var finallyKeyword = ts.findChildOfKind(tryStatement, 87 /* FinallyKeyword */, sourceFile); + pushKeywordIf(keywords, finallyKeyword, 87 /* FinallyKeyword */); } return keywords; } @@ -77222,11 +92632,13 @@ var ts; } var keywords = []; ts.forEach(aggregateOwnedThrowStatements(owner), function (throwStatement) { - keywords.push(ts.findChildOfKind(throwStatement, 100, sourceFile)); + keywords.push(ts.findChildOfKind(throwStatement, 100 /* ThrowKeyword */, sourceFile)); }); + // If the "owner" is a function, then we equate 'return' and 'throw' statements in their + // ability to "jump out" of the function, and include occurrences for both. if (ts.isFunctionBlock(owner)) { ts.forEachReturnStatement(owner, function (returnStatement) { - keywords.push(ts.findChildOfKind(returnStatement, 96, sourceFile)); + keywords.push(ts.findChildOfKind(returnStatement, 96 /* ReturnKeyword */, sourceFile)); }); } return keywords; @@ -77238,10 +92650,11 @@ var ts; } var keywords = []; ts.forEachReturnStatement(ts.cast(func.body, ts.isBlock), function (returnStatement) { - keywords.push(ts.findChildOfKind(returnStatement, 96, sourceFile)); + keywords.push(ts.findChildOfKind(returnStatement, 96 /* ReturnKeyword */, sourceFile)); }); + // Include 'throw' statements that do not occur within a try block. ts.forEach(aggregateOwnedThrowStatements(func.body), function (throwStatement) { - keywords.push(ts.findChildOfKind(throwStatement, 100, sourceFile)); + keywords.push(ts.findChildOfKind(throwStatement, 100 /* ThrowKeyword */, sourceFile)); }); return keywords; } @@ -77253,13 +92666,13 @@ var ts; var keywords = []; if (func.modifiers) { func.modifiers.forEach(function (modifier) { - pushKeywordIf(keywords, modifier, 120); + pushKeywordIf(keywords, modifier, 120 /* AsyncKeyword */); }); } ts.forEachChild(func, function (child) { traverseWithoutCrossingFunction(child, function (node) { if (ts.isAwaitExpression(node)) { - pushKeywordIf(keywords, node.getFirstToken(), 121); + pushKeywordIf(keywords, node.getFirstToken(), 121 /* AwaitKeyword */); } }); }); @@ -77274,12 +92687,13 @@ var ts; ts.forEachChild(func, function (child) { traverseWithoutCrossingFunction(child, function (node) { if (ts.isYieldExpression(node)) { - pushKeywordIf(keywords, node.getFirstToken(), 116); + pushKeywordIf(keywords, node.getFirstToken(), 116 /* YieldKeyword */); } }); }); return keywords; } + // Do not cross function/class/interface/module/type boundaries. function traverseWithoutCrossingFunction(node, cb) { cb(node); if (!ts.isFunctionLike(node) && !ts.isClassLike(node) && !ts.isInterfaceDeclaration(node) && !ts.isModuleDeclaration(node) && !ts.isTypeAliasDeclaration(node) && !ts.isTypeNode(node)) { @@ -77289,11 +92703,14 @@ var ts; function getIfElseOccurrences(ifStatement, sourceFile) { var keywords = getIfElseKeywords(ifStatement, sourceFile); var result = []; + // We'd like to highlight else/ifs together if they are only separated by whitespace + // (i.e. the keywords are separated by no comments, no newlines). for (var i = 0; i < keywords.length; i++) { - if (keywords[i].kind === 82 && i < keywords.length - 1) { + if (keywords[i].kind === 82 /* ElseKeyword */ && i < keywords.length - 1) { var elseKeyword = keywords[i]; - var ifKeyword = keywords[i + 1]; + var ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword. var shouldCombineElseAndIf = true; + // Avoid recalculating getStart() by iterating backwards. for (var j = ifKeyword.getStart(sourceFile) - 1; j >= elseKeyword.end; j--) { if (!ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(j))) { shouldCombineElseAndIf = false; @@ -77304,26 +92721,30 @@ var ts; result.push({ fileName: sourceFile.fileName, textSpan: ts.createTextSpanFromBounds(elseKeyword.getStart(), ifKeyword.end), - kind: "reference" + kind: "reference" /* reference */ }); - i++; + i++; // skip the next keyword continue; } } + // Ordinary case: just highlight the keyword. result.push(getHighlightSpanForNode(keywords[i], sourceFile)); } return result; } function getIfElseKeywords(ifStatement, sourceFile) { var keywords = []; + // Traverse upwards through all parent if-statements linked by their else-branches. while (ts.isIfStatement(ifStatement.parent) && ifStatement.parent.elseStatement === ifStatement) { ifStatement = ifStatement.parent; } + // Now traverse back down through the else branches, aggregating if/else keywords of if-statements. while (true) { var children = ifStatement.getChildren(sourceFile); - pushKeywordIf(keywords, children[0], 90); + pushKeywordIf(keywords, children[0], 90 /* IfKeyword */); + // Generally the 'else' keyword is second-to-last, so we traverse backwards. for (var i = children.length - 1; i >= 0; i--) { - if (pushKeywordIf(keywords, children[i], 82)) { + if (pushKeywordIf(keywords, children[i], 82 /* ElseKeyword */)) { break; } } @@ -77334,6 +92755,10 @@ var ts; } return keywords; } + /** + * Whether or not a 'node' is preceded by a label of the given string. + * Note: 'node' cannot be a SourceFile. + */ function isLabeledBy(node, labelName) { return !!ts.findAncestor(node.parent, function (owner) { return !ts.isLabeledStatement(owner) ? "quit" : owner.label.escapedText === labelName; }); } @@ -77345,8 +92770,11 @@ var ts; return createDocumentRegistryInternal(useCaseSensitiveFileNames, currentDirectory); } ts.createDocumentRegistry = createDocumentRegistry; + /*@internal*/ function createDocumentRegistryInternal(useCaseSensitiveFileNames, currentDirectory, externalCache) { if (currentDirectory === void 0) { currentDirectory = ""; } + // Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have + // for those settings. var buckets = ts.createMap(); var getCanonicalFileName = ts.createGetCanonicalFileName(!!useCaseSensitiveFileNames); function getKeyForCompilationSettings(settings) { @@ -77357,7 +92785,7 @@ var ts; if (!bucket && createIfMissing) { buckets.set(key, bucket = ts.createMap()); } - return bucket; + return bucket; // TODO: GH#18217 } function reportStats() { var bucketInfoArray = ts.arrayFrom(buckets.keys()).filter(function (name) { return name && name.charAt(0) === "_"; }).map(function (name) { @@ -77383,7 +92811,7 @@ var ts; return acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind); } function acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind) { - return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, true, scriptKind); + return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ true, scriptKind); } function updateDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) { var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); @@ -77391,12 +92819,12 @@ var ts; return updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind); } function updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind) { - return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, false, scriptKind); + return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ false, scriptKind); } function acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, acquiring, scriptKind) { - var bucket = getBucketForCompilationSettings(key, true); + var bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ true); var entry = bucket.get(path); - var scriptTarget = scriptKind === 6 ? 100 : compilationSettings.target; + var scriptTarget = scriptKind === 6 /* JSON */ ? 100 /* JSON */ : compilationSettings.target; if (!entry && externalCache) { var sourceFile = externalCache.getDocument(key, path); if (sourceFile) { @@ -77409,7 +92837,8 @@ var ts; } } if (!entry) { - var sourceFile = ts.createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, false, scriptKind); + // Have never seen this file with these settings. Create a new source file for it. + var sourceFile = ts.createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, /*setNodeParents*/ false, scriptKind); // TODO: GH#18217 if (externalCache) { externalCache.setDocument(key, path, sourceFile); } @@ -77420,12 +92849,20 @@ var ts; bucket.set(path, entry); } else { + // We have an entry for this file. However, it may be for a different version of + // the script snapshot. If so, update it appropriately. Otherwise, we can just + // return it as is. if (entry.sourceFile.version !== version) { - entry.sourceFile = ts.updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version, scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot)); + entry.sourceFile = ts.updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version, scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot)); // TODO: GH#18217 if (externalCache) { externalCache.setDocument(key, path, entry.sourceFile); } } + // If we're acquiring, then this is the first time this LS is asking for this document. + // Increase our ref count so we know there's another LS using the document. If we're + // not acquiring, then that means the LS is 'updating' the file instead, and that means + // it has already acquired the document previously. As such, we do not need to increase + // the ref count. if (acquiring) { entry.languageServiceRefCount++; } @@ -77439,7 +92876,7 @@ var ts; return releaseDocumentWithKey(path, key); } function releaseDocumentWithKey(path, key) { - var bucket = getBucketForCompilationSettings(key, false); + var bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ false); ts.Debug.assert(bucket !== undefined); var entry = bucket.get(path); entry.languageServiceRefCount--; @@ -77469,10 +92906,13 @@ var ts; } ts.createDocumentRegistryInternal = createDocumentRegistryInternal; })(ts || (ts = {})); +/* Code for finding imports of an exported symbol. Used only by FindAllReferences. */ +/* @internal */ var ts; (function (ts) { var FindAllReferences; (function (FindAllReferences) { + /** Creates the imports map and returns an ImportTracker that uses it. Call this lazily to avoid calling `getDirectImportsMap` unnecessarily. */ function createImportTracker(sourceFiles, sourceFilesSet, checker, cancellationToken) { var allDirectImports = getDirectImportsMap(sourceFiles, checker, cancellationToken); return function (exportSymbol, exportInfo, isForRename) { @@ -77492,6 +92932,7 @@ var ts; ImportExport[ImportExport["Import"] = 0] = "Import"; ImportExport[ImportExport["Export"] = 1] = "Export"; })(ImportExport = FindAllReferences.ImportExport || (FindAllReferences.ImportExport = {})); + /** Returns import statements that directly reference the exporting module, and a list of files that may access the module through a namespace. */ function getImportersForExport(sourceFiles, sourceFilesSet, allDirectImports, _a, checker, cancellationToken) { var exportingModuleSymbol = _a.exportingModuleSymbol, exportKind = _a.exportKind; var markSeenDirectImport = ts.nodeSeenTracker(); @@ -77503,14 +92944,17 @@ var ts; return { directImports: directImports, indirectUsers: getIndirectUsers() }; function getIndirectUsers() { if (isAvailableThroughGlobal) { + // It has `export as namespace`, so anything could potentially use it. return sourceFiles; } + // Module augmentations may use this module's exports without importing it. for (var _i = 0, _a = exportingModuleSymbol.declarations; _i < _a.length; _i++) { var decl = _a[_i]; if (ts.isExternalModuleAugmentation(decl) && sourceFilesSet.has(decl.getSourceFile().fileName)) { addIndirectUser(decl); } } + // This may return duplicates (if there are multiple module declarations in a single source file, all importing the same thing as a namespace), but `State.markSearchedSymbol` will handle that. return indirectUserDeclarations.map(ts.getSourceFileOfNode); } function handleDirectImports(exportingModuleSymbol) { @@ -77523,43 +92967,46 @@ var ts; } cancellationToken.throwIfCancellationRequested(); switch (direct.kind) { - case 187: + case 187 /* CallExpression */: if (!isAvailableThroughGlobal) { var parent = direct.parent; - if (exportKind === 2 && parent.kind === 232) { + if (exportKind === 2 /* ExportEquals */ && parent.kind === 232 /* VariableDeclaration */) { var name = parent.name; - if (name.kind === 71) { + if (name.kind === 71 /* Identifier */) { directImports.push(name); break; } } + // Don't support re-exporting 'require()' calls, so just add a single indirect user. addIndirectUser(direct.getSourceFile()); } break; - case 71: + case 71 /* Identifier */: // for 'const x = require("y"); + break; // TODO: GH#23879 + case 243 /* ImportEqualsDeclaration */: + handleNamespaceImport(direct, direct.name, ts.hasModifier(direct, 1 /* Export */), /*alreadyAddedDirect*/ false); break; - case 243: - handleNamespaceImport(direct, direct.name, ts.hasModifier(direct, 1), false); - break; - case 244: + case 244 /* ImportDeclaration */: directImports.push(direct); var namedBindings = direct.importClause && direct.importClause.namedBindings; - if (namedBindings && namedBindings.kind === 246) { - handleNamespaceImport(direct, namedBindings.name, false, true); + if (namedBindings && namedBindings.kind === 246 /* NamespaceImport */) { + handleNamespaceImport(direct, namedBindings.name, /*isReExport*/ false, /*alreadyAddedDirect*/ true); } else if (!isAvailableThroughGlobal && ts.isDefaultImport(direct)) { - addIndirectUser(getSourceFileLikeForImportDeclaration(direct)); + addIndirectUser(getSourceFileLikeForImportDeclaration(direct)); // Add a check for indirect uses to handle synthetic default imports } break; - case 250: + case 250 /* ExportDeclaration */: if (!direct.exportClause) { + // This is `export * from "foo"`, so imports of this module may import the export too. handleDirectImports(getContainingModuleSymbol(direct, checker)); } else { + // This is `export { foo } from "foo"` and creates an alias symbol, so recursive search will get handle re-exports. directImports.push(direct); } break; - case 179: + case 179 /* ImportType */: directImports.push(direct); break; default: @@ -77569,13 +93016,14 @@ var ts; } } function handleNamespaceImport(importDeclaration, name, isReExport, alreadyAddedDirect) { - if (exportKind === 2) { + if (exportKind === 2 /* ExportEquals */) { + // This is a direct import, not import-as-namespace. if (!alreadyAddedDirect) directImports.push(importDeclaration); } else if (!isAvailableThroughGlobal) { var sourceFileLike = getSourceFileLikeForImportDeclaration(importDeclaration); - ts.Debug.assert(sourceFileLike.kind === 274 || sourceFileLike.kind === 239); + ts.Debug.assert(sourceFileLike.kind === 274 /* SourceFile */ || sourceFileLike.kind === 239 /* ModuleDeclaration */); if (isReExport || findNamespaceReExports(sourceFileLike, name, checker)) { addIndirectUsers(sourceFileLike); } @@ -77588,16 +93036,17 @@ var ts; ts.Debug.assert(!isAvailableThroughGlobal); var isNew = markSeenIndirectUser(sourceFileLike); if (isNew) { - indirectUserDeclarations.push(sourceFileLike); + indirectUserDeclarations.push(sourceFileLike); // TODO: GH#18217 } return isNew; } + /** Adds a module and all of its transitive dependencies as possible indirect users. */ function addIndirectUsers(sourceFileLike) { if (!addIndirectUser(sourceFileLike)) { return; } var moduleSymbol = checker.getMergedSymbol(sourceFileLike.symbol); - ts.Debug.assert(!!(moduleSymbol.flags & 1536)); + ts.Debug.assert(!!(moduleSymbol.flags & 1536 /* Module */)); var directImports = getDirectImports(moduleSymbol); if (directImports) { for (var _i = 0, directImports_1 = directImports; _i < directImports_1.length; _i++) { @@ -77610,6 +93059,11 @@ var ts; return allDirectImports.get(ts.getSymbolId(moduleSymbol).toString()); } } + /** + * Given the set of direct imports of a module, we need to find which ones import the particular exported symbol. + * The returned `importSearches` will result in the entire source file being searched. + * But re-exports will be placed in 'singleReferences' since they cannot be locally referenced. + */ function getSearchesFromDirectImports(directImports, exportSymbol, exportKind, checker, isForRename) { var importSearches = []; var singleReferences = []; @@ -77624,42 +93078,44 @@ var ts; } return { importSearches: importSearches, singleReferences: singleReferences }; function handleImport(decl) { - if (decl.kind === 243) { + if (decl.kind === 243 /* ImportEqualsDeclaration */) { if (isExternalModuleImportEquals(decl)) { handleNamespaceImportLike(decl.name); } return; } - if (decl.kind === 71) { + if (decl.kind === 71 /* Identifier */) { handleNamespaceImportLike(decl); return; } - if (decl.kind === 179) { + if (decl.kind === 179 /* ImportType */) { if (decl.qualifier) { if (ts.isIdentifier(decl.qualifier) && decl.qualifier.escapedText === ts.symbolName(exportSymbol)) { singleReferences.push(decl.qualifier); } } - else if (exportKind === 2) { + else if (exportKind === 2 /* ExportEquals */) { singleReferences.push(decl.argument.literal); } return; } - if (decl.moduleSpecifier.kind !== 9) { + // Ignore if there's a grammar error + if (decl.moduleSpecifier.kind !== 9 /* StringLiteral */) { return; } - if (decl.kind === 250) { + if (decl.kind === 250 /* ExportDeclaration */) { searchForNamedImport(decl.exportClause); return; } var _a = decl.importClause || { name: undefined, namedBindings: undefined }, name = _a.name, namedBindings = _a.namedBindings; if (namedBindings) { switch (namedBindings.kind) { - case 246: + case 246 /* NamespaceImport */: handleNamespaceImportLike(namedBindings.name); break; - case 247: - if (exportKind === 0 || exportKind === 1) { + case 247 /* NamedImports */: + // 'default' might be accessed as a named import `{ default as foo }`. + if (exportKind === 0 /* Named */ || exportKind === 1 /* Default */) { searchForNamedImport(namedBindings); } break; @@ -77667,13 +93123,22 @@ var ts; ts.Debug.assertNever(namedBindings); } } - if (name && (exportKind === 1 || exportKind === 2) && (!isForRename || name.escapedText === ts.symbolEscapedNameNoDefault(exportSymbol))) { + // `export =` might be imported by a default import if `--allowSyntheticDefaultImports` is on, so this handles both ExportKind.Default and ExportKind.ExportEquals. + // If a default import has the same name as the default export, allow to rename it. + // Given `import f` and `export default function f`, we will rename both, but for `import g` we will rename just that. + if (name && (exportKind === 1 /* Default */ || exportKind === 2 /* ExportEquals */) && (!isForRename || name.escapedText === ts.symbolEscapedNameNoDefault(exportSymbol))) { var defaultImportAlias = checker.getSymbolAtLocation(name); addSearch(name, defaultImportAlias); } } + /** + * `import x = require("./x") or `import * as x from "./x"`. + * An `export =` may be imported by this syntax, so it may be a direct import. + * If it's not a direct import, it will be in `indirectUsers`, so we don't have to do anything here. + */ function handleNamespaceImportLike(importName) { - if (exportKind === 2 && (!isForRename || isNameMatch(importName.escapedText))) { + // Don't rename an import that already has a different name than the export. + if (exportKind === 2 /* ExportEquals */ && (!isForRename || isNameMatch(importName.escapedText))) { addSearch(importName, checker.getSymbolAtLocation(importName)); } } @@ -77688,23 +93153,29 @@ var ts; continue; } if (propertyName) { + // This is `import { foo as bar } from "./a"` or `export { foo as bar } from "./a"`. `foo` isn't a local in the file, so just add it as a single reference. singleReferences.push(propertyName); + // If renaming `{ foo as bar }`, don't touch `bar`, just `foo`. + // But do rename `foo` in ` { default as foo }` if that's the original export name. if (!isForRename || name.escapedText === exportSymbol.escapedName) { + // Search locally for `bar`. addSearch(name, checker.getSymbolAtLocation(name)); } } else { - var localSymbol = element.kind === 252 && element.propertyName - ? checker.getExportSpecifierLocalTargetSymbol(element) + var localSymbol = element.kind === 252 /* ExportSpecifier */ && element.propertyName + ? checker.getExportSpecifierLocalTargetSymbol(element) // For re-exporting under a different name, we want to get the re-exported symbol. : checker.getSymbolAtLocation(name); addSearch(name, localSymbol); } } } function isNameMatch(name) { - return name === exportSymbol.escapedName || exportKind !== 0 && name === "default"; + // Use name of "default" even in `export =` case because we may have allowSyntheticDefaultImports + return name === exportSymbol.escapedName || exportKind !== 0 /* Named */ && name === "default" /* Default */; } } + /** Returns 'true' is the namespace 'name' is re-exported from this module, and 'false' if it is only used locally. */ function findNamespaceReExports(sourceFileLike, name, checker) { var namespaceImportSymbol = checker.getSymbolAtLocation(name); return !!forEachPossibleImportOrExportStatement(sourceFileLike, function (statement) { @@ -77721,7 +93192,7 @@ var ts; for (var _i = 0, sourceFiles_5 = sourceFiles; _i < sourceFiles_5.length; _i++) { var referencingFile = sourceFiles_5[_i]; var searchSourceFile = searchModuleSymbol.valueDeclaration; - if (searchSourceFile.kind === 274) { + if (searchSourceFile.kind === 274 /* SourceFile */) { for (var _a = 0, _b = referencingFile.referencedFiles; _a < _b.length; _a++) { var ref = _b[_a]; if (program.getSourceFileFromReference(referencingFile, ref) === searchSourceFile) { @@ -77746,6 +93217,7 @@ var ts; return refs; } FindAllReferences.findModuleReferences = findModuleReferences; + /** Returns a map from a module symbol Id to all import statements that directly reference the module. */ function getDirectImportsMap(sourceFiles, checker, cancellationToken) { var map = ts.createMap(); for (var _i = 0, sourceFiles_6 = sourceFiles; _i < sourceFiles_6.length; _i++) { @@ -77765,11 +93237,13 @@ var ts; } return map; } + /** Iterates over all statements at the top level or in module declarations. Returns the first truthy result. */ function forEachPossibleImportOrExportStatement(sourceFileLike, action) { - return ts.forEach(sourceFileLike.kind === 274 ? sourceFileLike.statements : sourceFileLike.body.statements, function (statement) { + return ts.forEach(sourceFileLike.kind === 274 /* SourceFile */ ? sourceFileLike.statements : sourceFileLike.body.statements, function (statement) { return action(statement) || (isAmbientModuleDeclaration(statement) && ts.forEach(statement.body && statement.body.statements, action)); }); } + /** Calls `action` for each import, re-export, or require() in a file. */ function forEachImport(sourceFile, action) { if (sourceFile.externalModuleIndicator || sourceFile.imports !== undefined) { for (var _i = 0, _a = sourceFile.imports; _i < _a.length; _i++) { @@ -77780,15 +93254,15 @@ var ts; else { forEachPossibleImportOrExportStatement(sourceFile, function (statement) { switch (statement.kind) { - case 250: - case 244: { + case 250 /* ExportDeclaration */: + case 244 /* ImportDeclaration */: { var decl = statement; if (decl.moduleSpecifier && ts.isStringLiteral(decl.moduleSpecifier)) { action(decl, decl.moduleSpecifier); } break; } - case 243: { + case 243 /* ImportEqualsDeclaration */: { var decl = statement; if (isExternalModuleImportEquals(decl)) { action(decl, decl.moduleReference.expression); @@ -77799,15 +93273,24 @@ var ts; }); } } + /** + * Given a local reference, we might notice that it's an import/export and recursively search for references of that. + * If at an import, look locally for the symbol it imports. + * If an an export, look for all imports of it. + * This doesn't handle export specifiers; that is done in `getReferencesAtExportSpecifier`. + * @param comingFromExport If we are doing a search for all exports, don't bother looking backwards for the imported symbol, since that's the reason we're here. + */ function getImportOrExportSymbol(node, symbol, checker, comingFromExport) { return comingFromExport ? getExport() : getExport() || getImport(); function getExport() { var parent = node.parent; var grandParent = parent.parent; if (symbol.exportSymbol) { - if (parent.kind === 185) { + if (parent.kind === 185 /* PropertyAccessExpression */) { + // When accessing an export of a JS module, there's no alias. The symbol will still be flagged as an export even though we're at the use. + // So check that we are at the declaration. return symbol.declarations.some(function (d) { return d === parent; }) && ts.isBinaryExpression(grandParent) - ? getSpecialPropertyExport(grandParent, false) + ? getSpecialPropertyExport(grandParent, /*useLhsSymbol*/ false) : undefined; } else { @@ -77816,53 +93299,59 @@ var ts; } else { var exportNode = getExportNode(parent, node); - if (exportNode && ts.hasModifier(exportNode, 1)) { + if (exportNode && ts.hasModifier(exportNode, 1 /* Export */)) { if (ts.isImportEqualsDeclaration(exportNode) && exportNode.moduleReference === node) { + // We're at `Y` in `export import X = Y`. This is not the exported symbol, the left-hand-side is. So treat this as an import statement. if (comingFromExport) { return undefined; } var lhsSymbol = checker.getSymbolAtLocation(exportNode.name); - return { kind: 0, symbol: lhsSymbol, isNamedImport: false }; + return { kind: 0 /* Import */, symbol: lhsSymbol, isNamedImport: false }; } else { return exportInfo(symbol, getExportKindForDeclaration(exportNode)); } } + // If we are in `export = a;` or `export default a;`, `parent` is the export assignment. else if (ts.isExportAssignment(parent)) { return getExportAssignmentExport(parent); } + // If we are in `export = class A {};` (or `export = class A {};`) at `A`, `parent.parent` is the export assignment. else if (ts.isExportAssignment(grandParent)) { return getExportAssignmentExport(grandParent); } + // Similar for `module.exports =` and `exports.A =`. else if (ts.isBinaryExpression(parent)) { - return getSpecialPropertyExport(parent, true); + return getSpecialPropertyExport(parent, /*useLhsSymbol*/ true); } else if (ts.isBinaryExpression(grandParent)) { - return getSpecialPropertyExport(grandParent, true); + return getSpecialPropertyExport(grandParent, /*useLhsSymbol*/ true); } else if (ts.isJSDocTypedefTag(parent)) { - return exportInfo(symbol, 0); + return exportInfo(symbol, 0 /* Named */); } } function getExportAssignmentExport(ex) { + // Get the symbol for the `export =` node; its parent is the module it's the export of. var exportingModuleSymbol = ts.Debug.assertDefined(ex.symbol.parent, "Expected export symbol to have a parent"); - var exportKind = ex.isExportEquals ? 2 : 1; - return { kind: 1, symbol: symbol, exportInfo: { exportingModuleSymbol: exportingModuleSymbol, exportKind: exportKind } }; + var exportKind = ex.isExportEquals ? 2 /* ExportEquals */ : 1 /* Default */; + return { kind: 1 /* Export */, symbol: symbol, exportInfo: { exportingModuleSymbol: exportingModuleSymbol, exportKind: exportKind } }; } function getSpecialPropertyExport(node, useLhsSymbol) { var kind; switch (ts.getSpecialPropertyAssignmentKind(node)) { - case 1: - kind = 0; + case 1 /* ExportsProperty */: + kind = 0 /* Named */; break; - case 2: - kind = 2; + case 2 /* ModuleExports */: + kind = 2 /* ExportEquals */; break; default: return undefined; } var sym = useLhsSymbol ? checker.getSymbolAtLocation(ts.cast(node.left, ts.isPropertyAccessExpression).name) : symbol; - if (sym && !(checker.getMergedSymbol(sym.parent).flags & 1536)) { + // Better detection for GH#20803 + if (sym && !(checker.getMergedSymbol(sym.parent).flags & 1536 /* Module */)) { ts.Debug.fail("Special property assignment kind does not have a module as its parent. Assignment is " + ts.Debug.showSymbol(sym) + ", parent is " + ts.Debug.showSymbol(sym.parent)); } return sym && exportInfo(sym, kind); @@ -77872,48 +93361,57 @@ var ts; var isImport = isNodeImport(node); if (!isImport) return undefined; + // A symbol being imported is always an alias. So get what that aliases to find the local symbol. var importedSymbol = checker.getImmediateAliasedSymbol(symbol); if (!importedSymbol) return undefined; + // Search on the local symbol in the exporting module, not the exported symbol. importedSymbol = skipExportSpecifierSymbol(importedSymbol, checker); + // Similarly, skip past the symbol for 'export =' if (importedSymbol.escapedName === "export=") { importedSymbol = getExportEqualsLocalSymbol(importedSymbol, checker); } + // If the import has a different name than the export, do not continue searching. + // If `importedName` is undefined, do continue searching as the export is anonymous. + // (All imports returned from this function will be ignored anyway if we are in rename and this is a not a named export.) var importedName = ts.symbolEscapedNameNoDefault(importedSymbol); - if (importedName === undefined || importedName === "default" || importedName === symbol.escapedName) { - return __assign({ kind: 0, symbol: importedSymbol }, isImport); + if (importedName === undefined || importedName === "default" /* Default */ || importedName === symbol.escapedName) { + return __assign({ kind: 0 /* Import */, symbol: importedSymbol }, isImport); } } function exportInfo(symbol, kind) { var exportInfo = getExportInfo(symbol, kind, checker); - return exportInfo && { kind: 1, symbol: symbol, exportInfo: exportInfo }; + return exportInfo && { kind: 1 /* Export */, symbol: symbol, exportInfo: exportInfo }; } + // Not meant for use with export specifiers or export assignment. function getExportKindForDeclaration(node) { - return ts.hasModifier(node, 512) ? 1 : 0; + return ts.hasModifier(node, 512 /* Default */) ? 1 /* Default */ : 0 /* Named */; } } FindAllReferences.getImportOrExportSymbol = getImportOrExportSymbol; function getExportEqualsLocalSymbol(importedSymbol, checker) { - if (importedSymbol.flags & 2097152) { + if (importedSymbol.flags & 2097152 /* Alias */) { return ts.Debug.assertDefined(checker.getImmediateAliasedSymbol(importedSymbol)); } var decl = importedSymbol.valueDeclaration; - if (ts.isExportAssignment(decl)) { + if (ts.isExportAssignment(decl)) { // `export = class {}` return ts.Debug.assertDefined(decl.expression.symbol); } - else if (ts.isBinaryExpression(decl)) { + else if (ts.isBinaryExpression(decl)) { // `module.exports = class {}` return ts.Debug.assertDefined(decl.right.symbol); } - else if (ts.isSourceFile(decl)) { + else if (ts.isSourceFile(decl)) { // json module return ts.Debug.assertDefined(decl.symbol); } return ts.Debug.fail(); } + // If a reference is a class expression, the exported node would be its parent. + // If a reference is a variable declaration, the exported node would be the variable statement. function getExportNode(parent, node) { - if (parent.kind === 232) { + if (parent.kind === 232 /* VariableDeclaration */) { var p = parent; return p.name !== node ? undefined : - p.parent.kind === 269 ? undefined : p.parent.parent.kind === 214 ? p.parent.parent : undefined; + p.parent.kind === 269 /* CatchClause */ ? undefined : p.parent.parent.kind === 214 /* VariableStatement */ ? p.parent.parent : undefined; } else { return parent; @@ -77922,14 +93420,15 @@ var ts; function isNodeImport(node) { var parent = node.parent; switch (parent.kind) { - case 243: + case 243 /* ImportEqualsDeclaration */: return parent.name === node && isExternalModuleImportEquals(parent) ? { isNamedImport: false } : undefined; - case 248: + case 248 /* ImportSpecifier */: + // For a rename import `{ foo as bar }`, don't search for the imported symbol. Just find local uses of `bar`. return parent.propertyName ? undefined : { isNamedImport: true }; - case 245: - case 246: + case 245 /* ImportClause */: + case 246 /* NamespaceImport */: ts.Debug.assert(parent.name === node); return { isNamedImport: false }; default: @@ -77939,12 +93438,15 @@ var ts; function getExportInfo(exportSymbol, exportKind, checker) { var moduleSymbol = exportSymbol.parent; if (!moduleSymbol) - return undefined; - var exportingModuleSymbol = checker.getMergedSymbol(moduleSymbol); + return undefined; // This can happen if an `export` is not at the top-level (which is a compile error). + var exportingModuleSymbol = checker.getMergedSymbol(moduleSymbol); // Need to get merged symbol in case there's an augmentation. + // `export` may appear in a namespace. In that case, just rely on global search. return ts.isExternalModuleSymbol(exportingModuleSymbol) ? { exportingModuleSymbol: exportingModuleSymbol, exportKind: exportKind } : undefined; } FindAllReferences.getExportInfo = getExportInfo; + /** If at an export specifier, go to the symbol it refers to. */ function skipExportSpecifierSymbol(symbol, checker) { + // For `export { foo } from './bar", there's nothing to skip, because it does not create a new alias. But `export { foo } does. if (symbol.declarations) { for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var declaration = _a[_i]; @@ -77959,24 +93461,25 @@ var ts; return checker.getMergedSymbol(getSourceFileLikeForImportDeclaration(importer).symbol); } function getSourceFileLikeForImportDeclaration(node) { - if (node.kind === 187) { + if (node.kind === 187 /* CallExpression */) { return node.getSourceFile(); } var parent = node.parent; - if (parent.kind === 274) { + if (parent.kind === 274 /* SourceFile */) { return parent; } - ts.Debug.assert(parent.kind === 240); + ts.Debug.assert(parent.kind === 240 /* ModuleBlock */); return ts.cast(parent.parent, isAmbientModuleDeclaration); } function isAmbientModuleDeclaration(node) { - return node.kind === 239 && node.name.kind === 9; + return node.kind === 239 /* ModuleDeclaration */ && node.name.kind === 9 /* StringLiteral */; } function isExternalModuleImportEquals(eq) { - return eq.moduleReference.kind === 254 && eq.moduleReference.expression.kind === 9; + return eq.moduleReference.kind === 254 /* ExternalModuleReference */ && eq.moduleReference.expression.kind === 9 /* StringLiteral */; } })(FindAllReferences = ts.FindAllReferences || (ts.FindAllReferences = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var FindAllReferences; @@ -77991,6 +93494,7 @@ var ts; var checker = program.getTypeChecker(); return !referencedSymbols || !referencedSymbols.length ? undefined : ts.mapDefined(referencedSymbols, function (_a) { var definition = _a.definition, references = _a.references; + // Only include referenced symbols that have a valid definition. return definition && { definition: checker.runWithCancellationToken(cancellationToken, function (checker) { return definitionToReferencedSymbolDefinitionInfo(definition, checker, node); }), references: references.map(toReferenceEntry) @@ -78006,20 +93510,25 @@ var ts; } FindAllReferences.getImplementationsAtPosition = getImplementationsAtPosition; function getImplementationReferenceEntries(program, cancellationToken, sourceFiles, node, position) { - if (node.kind === 274) { + if (node.kind === 274 /* SourceFile */) { return undefined; } var checker = program.getTypeChecker(); - if (node.parent.kind === 271) { + // If invoked directly on a shorthand property assignment, then return + // the declaration of the symbol being assigned (not the symbol being assigned to). + if (node.parent.kind === 271 /* ShorthandPropertyAssignment */) { var result_6 = []; FindAllReferences.Core.getReferenceEntriesForShorthandPropertyAssignment(node, checker, function (node) { return result_6.push(nodeEntry(node)); }); return result_6; } - else if (node.kind === 97 || ts.isSuperProperty(node.parent)) { + else if (node.kind === 97 /* SuperKeyword */ || ts.isSuperProperty(node.parent)) { + // References to and accesses on the super keyword only have one possible implementation, so no + // need to "Find all References" var symbol = checker.getSymbolAtLocation(node); return symbol.valueDeclaration && [nodeEntry(symbol.valueDeclaration)]; } else { + // Perform "Find all References" and retrieve only those that are implementations return getReferenceEntriesForNode(position, node, program, sourceFiles, cancellationToken, { implementations: true }); } } @@ -78048,22 +93557,22 @@ var ts; } case "label": { var node_3 = def.node; - return { node: node_3, name: node_3.text, kind: "label", displayParts: [ts.displayPart(node_3.text, ts.SymbolDisplayPartKind.text)] }; + return { node: node_3, name: node_3.text, kind: "label" /* label */, displayParts: [ts.displayPart(node_3.text, ts.SymbolDisplayPartKind.text)] }; } case "keyword": { var node_4 = def.node; var name_4 = ts.tokenToString(node_4.kind); - return { node: node_4, name: name_4, kind: "keyword", displayParts: [{ text: name_4, kind: "keyword" }] }; + return { node: node_4, name: name_4, kind: "keyword" /* keyword */, displayParts: [{ text: name_4, kind: "keyword" /* keyword */ }] }; } case "this": { var node_5 = def.node; var symbol = checker.getSymbolAtLocation(node_5); var displayParts_2 = symbol && ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, node_5.getSourceFile(), ts.getContainerNode(node_5), node_5).displayParts || [ts.textPart("this")]; - return { node: node_5, name: "this", kind: "var", displayParts: displayParts_2 }; + return { node: node_5, name: "this", kind: "var" /* variableElement */, displayParts: displayParts_2 }; } case "string": { var node_6 = def.node; - return { node: node_6, name: node_6.text, kind: "var", displayParts: [ts.displayPart(ts.getTextOfNode(node_6), ts.SymbolDisplayPartKind.stringLiteral)] }; + return { node: node_6, name: node_6.text, kind: "var" /* variableElement */, displayParts: [ts.displayPart(ts.getTextOfNode(node_6), ts.SymbolDisplayPartKind.stringLiteral)] }; } default: return ts.Debug.assertNever(def); @@ -78071,7 +93580,7 @@ var ts; })(); var node = info.node, name = info.name, kind = info.kind, displayParts = info.displayParts; var sourceFile = node.getSourceFile(); - return { containerKind: "", containerName: "", fileName: sourceFile.fileName, kind: kind, name: name, textSpan: getTextSpan(ts.isComputedPropertyName(node) ? node.expression : node, sourceFile), displayParts: displayParts }; + return { containerKind: "" /* unknown */, containerName: "", fileName: sourceFile.fileName, kind: kind, name: name, textSpan: getTextSpan(ts.isComputedPropertyName(node) ? node.expression : node, sourceFile), displayParts: displayParts }; } function getDefinitionKindAndDisplayParts(symbol, checker, node) { var meaning = FindAllReferences.Core.getIntersectingMeaningFromDeclarations(node, symbol); @@ -78089,7 +93598,7 @@ var ts; fileName: sourceFile.fileName, textSpan: getTextSpan(node, sourceFile), isWriteAccess: isWriteAccessForReference(node), - isDefinition: node.kind === 79 + isDefinition: node.kind === 79 /* DefaultKeyword */ || ts.isAnyDeclarationName(node) || ts.isLiteralComputedPropertyDeclarationName(node), isInString: isInString, @@ -78103,7 +93612,7 @@ var ts; } else { var textSpan = entry.textSpan, fileName = entry.fileName; - return { textSpan: textSpan, fileName: fileName, kind: "", displayParts: [] }; + return { textSpan: textSpan, fileName: fileName, kind: "" /* unknown */, displayParts: [] }; } } function implementationKindDisplayParts(node, checker) { @@ -78111,16 +93620,16 @@ var ts; if (symbol) { return getDefinitionKindAndDisplayParts(symbol, checker, node); } - else if (node.kind === 184) { + else if (node.kind === 184 /* ObjectLiteralExpression */) { return { - kind: "interface", - displayParts: [ts.punctuationPart(19), ts.textPart("object literal"), ts.punctuationPart(20)] + kind: "interface" /* interfaceElement */, + displayParts: [ts.punctuationPart(19 /* OpenParenToken */), ts.textPart("object literal"), ts.punctuationPart(20 /* CloseParenToken */)] }; } - else if (node.kind === 205) { + else if (node.kind === 205 /* ClassExpression */) { return { - kind: "local class", - displayParts: [ts.punctuationPart(19), ts.textPart("anonymous local class"), ts.punctuationPart(20)] + kind: "local class" /* localClassElement */, + displayParts: [ts.punctuationPart(19 /* OpenParenToken */), ts.textPart("anonymous local class"), ts.punctuationPart(20 /* CloseParenToken */)] }; } else { @@ -78130,14 +93639,14 @@ var ts; function toHighlightSpan(entry) { if (entry.type === "span") { var fileName = entry.fileName, textSpan = entry.textSpan; - return { fileName: fileName, span: { textSpan: textSpan, kind: "reference" } }; + return { fileName: fileName, span: { textSpan: textSpan, kind: "reference" /* reference */ } }; } var node = entry.node, isInString = entry.isInString; var sourceFile = node.getSourceFile(); var writeAccess = isWriteAccessForReference(node); var span = { textSpan: getTextSpan(node, sourceFile), - kind: writeAccess ? "writtenReference" : "reference", + kind: writeAccess ? "writtenReference" /* writtenReference */ : "reference" /* reference */, isInString: isInString }; return { fileName: sourceFile.fileName, span: span }; @@ -78146,28 +93655,32 @@ var ts; function getTextSpan(node, sourceFile) { var start = node.getStart(sourceFile); var end = node.getEnd(); - if (node.kind === 9) { + if (node.kind === 9 /* StringLiteral */) { start += 1; end -= 1; } return ts.createTextSpanFromBounds(start, end); } + /** A node is considered a writeAccess iff it is a name of a declaration or a target of an assignment */ function isWriteAccessForReference(node) { - return node.kind === 79 || ts.isAnyDeclarationName(node) || ts.isWriteAccess(node); + return node.kind === 79 /* DefaultKeyword */ || ts.isAnyDeclarationName(node) || ts.isWriteAccess(node); } })(FindAllReferences = ts.FindAllReferences || (ts.FindAllReferences = {})); })(ts || (ts = {})); +/** Encapsulates the core find-all-references algorithm. */ +/* @internal */ (function (ts) { var FindAllReferences; (function (FindAllReferences) { var Core; (function (Core) { + /** Core find-all-references algorithm. Handles special cases before delegating to `getReferencedSymbolsForSymbol`. */ function getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options, sourceFilesSet) { if (options === void 0) { options = {}; } if (sourceFilesSet === void 0) { sourceFilesSet = ts.arrayToSet(sourceFiles, function (f) { return f.fileName; }); } if (ts.isSourceFile(node)) { var reference = ts.GoToDefinition.getReferenceAtPosition(node, position, program); - return reference && getReferencedSymbolsForModule(program, program.getTypeChecker().getMergedSymbol(reference.file.symbol), false, sourceFiles, sourceFilesSet); + return reference && getReferencedSymbolsForModule(program, program.getTypeChecker().getMergedSymbol(reference.file.symbol), /*excludeImportTypeOfExportEquals*/ false, sourceFiles, sourceFilesSet); } if (!options.implementations) { var special = getReferencedSymbolsSpecial(node, sourceFiles, cancellationToken); @@ -78177,17 +93690,21 @@ var ts; } var checker = program.getTypeChecker(); var symbol = checker.getSymbolAtLocation(node); + // Could not find a symbol e.g. unknown identifier if (!symbol) { + // String literal might be a property (and thus have a symbol), so do this here rather than in getReferencedSymbolsSpecial. return !options.implementations && ts.isStringLiteral(node) ? getReferencesForStringLiteral(node, sourceFiles, cancellationToken) : undefined; } var moduleReferences = ts.emptyArray; var moduleSourceFile = isModuleSymbol(symbol); var referencedNode = node; if (moduleSourceFile) { - var exportEquals = symbol.exports.get("export="); + var exportEquals = symbol.exports.get("export=" /* ExportEquals */); + // If !!exportEquals, we're about to add references to `import("mod")` anyway, so don't double-count them. moduleReferences = getReferencedSymbolsForModule(program, symbol, !!exportEquals, sourceFiles, sourceFilesSet); if (!exportEquals || !sourceFilesSet.has(moduleSourceFile.fileName)) return moduleReferences; + // Continue to get references to 'export ='. symbol = ts.skipAlias(exportEquals, checker); referencedNode = undefined; } @@ -78195,7 +93712,7 @@ var ts; } Core.getReferencedSymbolsForNode = getReferencedSymbolsForNode; function isModuleSymbol(symbol) { - return symbol.flags & 1536 ? ts.find(symbol.declarations, ts.isSourceFile) : undefined; + return symbol.flags & 1536 /* Module */ ? ts.find(symbol.declarations, ts.isSourceFile) : undefined; } function getReferencedSymbolsForModule(program, symbol, excludeImportTypeOfExportEquals, sourceFiles, sourceFilesSet) { ts.Debug.assert(!!symbol.valueDeclaration); @@ -78208,6 +93725,7 @@ var ts; return undefined; } } + // import("foo") with no qualifier will reference the `export =` of the module, which may be referenced anyway. return { type: "node", node: reference.literal }; } else { @@ -78221,54 +93739,66 @@ var ts; for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var decl = _a[_i]; switch (decl.kind) { - case 274: + case 274 /* SourceFile */: + // Don't include the source file itself. (This may not be ideal behavior, but awkward to include an entire file as a reference.) break; - case 239: + case 239 /* ModuleDeclaration */: if (sourceFilesSet.has(decl.getSourceFile().fileName)) { references.push({ type: "node", node: decl.name }); } break; default: + // This may be merged with something. ts.Debug.fail("Expected a module symbol to be declared by a SourceFile or ModuleDeclaration."); } } return references.length ? [{ definition: { type: "symbol", symbol: symbol }, references: references }] : ts.emptyArray; } + /** getReferencedSymbols for special node kinds. */ function getReferencedSymbolsSpecial(node, sourceFiles, cancellationToken) { if (ts.isTypeKeyword(node.kind)) { return getAllReferencesForKeyword(sourceFiles, node.kind, cancellationToken); } + // Labels if (ts.isJumpStatementTarget(node)) { var labelDefinition = ts.getTargetLabel(node.parent, node.text); + // if we have a label definition, look within its statement for references, if not, then + // the label is undefined and we have no results.. return labelDefinition && getLabelReferencesInNode(labelDefinition.parent, labelDefinition); } else if (ts.isLabelOfLabeledStatement(node)) { + // it is a label definition and not a target, search within the parent labeledStatement return getLabelReferencesInNode(node.parent, node); } if (ts.isThis(node)) { return getReferencesForThisKeyword(node, sourceFiles, cancellationToken); } - if (node.kind === 97) { + if (node.kind === 97 /* SuperKeyword */) { return getReferencesForSuperKeyword(node); } return undefined; } + /** Core find-all-references algorithm for a normal symbol. */ function getReferencedSymbolsForSymbol(symbol, node, sourceFiles, sourceFilesSet, checker, cancellationToken, options) { symbol = node && skipPastExportOrImportSpecifierOrUnion(symbol, node, checker) || symbol; - var searchMeaning = node ? getIntersectingMeaningFromDeclarations(node, symbol) : 7; + // Compute the meaning from the location and the symbol it references + var searchMeaning = node ? getIntersectingMeaningFromDeclarations(node, symbol) : 7 /* All */; var result = []; - var state = new State(sourceFiles, sourceFilesSet, node ? getSpecialSearchKind(node) : 0, checker, cancellationToken, searchMeaning, options, result); - if (node && node.kind === 79) { + var state = new State(sourceFiles, sourceFilesSet, node ? getSpecialSearchKind(node) : 0 /* None */, checker, cancellationToken, searchMeaning, options, result); + if (node && node.kind === 79 /* DefaultKeyword */) { addReference(node, symbol, state); - searchForImportsOfExport(node, symbol, { exportingModuleSymbol: ts.Debug.assertDefined(symbol.parent, "Expected export symbol to have a parent"), exportKind: 1 }, state); + searchForImportsOfExport(node, symbol, { exportingModuleSymbol: ts.Debug.assertDefined(symbol.parent, "Expected export symbol to have a parent"), exportKind: 1 /* Default */ }, state); } else { - var search = state.createSearch(node, symbol, undefined, { allSearchSymbols: node ? populateSearchSymbolSet(symbol, node, checker, !!options.implementations) : [symbol] }); + var search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: node ? populateSearchSymbolSet(symbol, node, checker, !!options.implementations) : [symbol] }); + // Try to get the smallest valid scope that we can limit our search to; + // otherwise we'll need to search globally (i.e. include each file). var scope = getSymbolScope(symbol); if (scope) { - getReferencesInContainer(scope, scope.getSourceFile(), search, state, !(ts.isSourceFile(scope) && !ts.contains(sourceFiles, scope))); + getReferencesInContainer(scope, scope.getSourceFile(), search, state, /*addReferencesHere*/ !(ts.isSourceFile(scope) && !ts.contains(sourceFiles, scope))); } else { + // Global search for (var _i = 0, _a = state.sourceFiles; _i < _a.length; _i++) { var sourceFile = _a[_i]; state.cancellationToken.throwIfCancellationRequested(); @@ -78280,27 +93810,32 @@ var ts; } function getSpecialSearchKind(node) { switch (node.kind) { - case 123: - return 1; - case 71: + case 123 /* ConstructorKeyword */: + return 1 /* Constructor */; + case 71 /* Identifier */: if (ts.isClassLike(node.parent)) { ts.Debug.assert(node.parent.name === node); - return 2; + return 2 /* Class */; } + // falls through default: - return 0; + return 0 /* None */; } } + /** Handle a few special cases relating to export/import specifiers. */ function skipPastExportOrImportSpecifierOrUnion(symbol, node, checker) { var parent = node.parent; if (ts.isExportSpecifier(parent)) { return getLocalSymbolForExportSpecifier(node, symbol, parent, checker); } if (ts.isImportSpecifier(parent) && parent.propertyName === node) { + // We're at `foo` in `import { foo as bar }`. Probably intended to find all refs on the original, not just on the import. return checker.getImmediateAliasedSymbol(symbol); } + // If the symbol is declared as part of a declaration like `{ type: "a" } | { type: "b" }`, use the property on the union type to get more references. return ts.firstDefined(symbol.declarations, function (decl) { if (!decl.parent) { + // Assertions for GH#21814. We should be handling SourceFile symbols in `getReferencedSymbolsForModule` instead of getting here. ts.Debug.fail("Unexpected symbol at " + ts.Debug.showSyntaxKind(node) + ": " + ts.Debug.showSymbol(symbol)); } return ts.isTypeLiteralNode(decl.parent) && ts.isUnionTypeNode(decl.parent.parent) @@ -78314,8 +93849,14 @@ var ts; SpecialSearchKind[SpecialSearchKind["Constructor"] = 1] = "Constructor"; SpecialSearchKind[SpecialSearchKind["Class"] = 2] = "Class"; })(SpecialSearchKind || (SpecialSearchKind = {})); - var State = (function () { - function State(sourceFiles, sourceFilesSet, specialSearchKind, checker, cancellationToken, searchMeaning, options, result) { + /** + * Holds all state needed for the finding references. + * Unlike `Search`, there is only one `State`. + */ + var State = /** @class */ (function () { + function State(sourceFiles, sourceFilesSet, + /** True if we're searching for constructor references. */ + specialSearchKind, checker, cancellationToken, searchMeaning, options, result) { this.sourceFiles = sourceFiles; this.sourceFilesSet = sourceFilesSet; this.specialSearchKind = specialSearchKind; @@ -78324,27 +93865,57 @@ var ts; this.searchMeaning = searchMeaning; this.options = options; this.result = result; + /** Cache for `explicitlyinheritsFrom`. */ this.inheritsFromCache = ts.createMap(); + /** + * Type nodes can contain multiple references to the same type. For example: + * let x: Foo & (Foo & Bar) = ... + * Because we are returning the implementation locations and not the identifier locations, + * duplicate entries would be returned here as each of the type references is part of + * the same implementation. For that reason, check before we add a new entry. + */ this.markSeenContainingTypeReference = ts.nodeSeenTracker(); + /** + * It's possible that we will encounter the right side of `export { foo as bar } from "x";` more than once. + * For example: + * // b.ts + * export { foo as bar } from "./a"; + * import { bar } from "./b"; + * + * Normally at `foo as bar` we directly add `foo` and do not locally search for it (since it doesn't declare a local). + * But another reference to it may appear in the same source file. + * See `tests/cases/fourslash/transitiveExportImports3.ts`. + */ this.markSeenReExportRHS = ts.nodeSeenTracker(); this.symbolIdToReferences = []; + // Source file ID → symbol ID → Whether the symbol has been searched for in the source file. this.sourceFileToSeenSymbols = []; } State.prototype.includesSourceFile = function (sourceFile) { return this.sourceFilesSet.has(sourceFile.fileName); }; + /** Gets every place to look for references of an exported symbols. See `ImportsResult` in `importTracker.ts` for more documentation. */ State.prototype.getImportSearches = function (exportSymbol, exportInfo) { if (!this.importTracker) this.importTracker = FindAllReferences.createImportTracker(this.sourceFiles, this.sourceFilesSet, this.checker, this.cancellationToken); return this.importTracker(exportSymbol, exportInfo, !!this.options.isForRename); }; + /** @param allSearchSymbols set of additinal symbols for use by `includes`. */ State.prototype.createSearch = function (location, symbol, comingFrom, searchOptions) { if (searchOptions === void 0) { searchOptions = {}; } + // Note: if this is an external module symbol, the name doesn't include quotes. + // Note: getLocalSymbolForExportDefault handles `export default class C {}`, but not `export default C` or `export { C as default }`. + // The other two forms seem to be handled downstream (e.g. in `skipPastExportOrImportSpecifier`), so special-casing the first form + // here appears to be intentional). var _a = searchOptions.text, text = _a === void 0 ? ts.stripQuotes(ts.unescapeLeadingUnderscores((ts.getLocalSymbolForExportDefault(symbol) || symbol).escapedName)) : _a, _b = searchOptions.allSearchSymbols, allSearchSymbols = _b === void 0 ? [symbol] : _b; var escapedText = ts.escapeLeadingUnderscores(text); var parents = this.options.implementations && location ? getParentSymbolsOfPropertyAccess(location, symbol, this.checker) : undefined; return { symbol: symbol, comingFrom: comingFrom, text: text, escapedText: escapedText, parents: parents, allSearchSymbols: allSearchSymbols, includes: function (sym) { return ts.contains(allSearchSymbols, sym); } }; }; + /** + * Callback to add references for a particular searched symbol. + * This initializes a reference group, so only call this if you will add at least one reference. + */ State.prototype.referenceAdder = function (searchSymbol) { var symbolId = ts.getSymbolId(searchSymbol); var references = this.symbolIdToReferences[symbolId]; @@ -78354,12 +93925,14 @@ var ts; } return function (node) { return references.push(FindAllReferences.nodeEntry(node)); }; }; + /** Add a reference with no associated definition. */ State.prototype.addStringOrCommentReference = function (fileName, textSpan) { this.result.push({ definition: undefined, references: [{ type: "span", fileName: fileName, textSpan: textSpan }] }); }; + /** Returns `true` the first time we search for a symbol in a file and `false` afterwards. */ State.prototype.markSearchedSymbols = function (sourceFile, symbols) { var sourceId = ts.getNodeId(sourceFile); var seenSymbols = this.sourceFileToSeenSymbols[sourceId] || (this.sourceFileToSeenSymbols[sourceId] = ts.createMap()); @@ -78372,8 +93945,10 @@ var ts; }; return State; }()); + /** Search for all imports of a given exported symbol using `State.getImportSearches`. */ function searchForImportsOfExport(exportLocation, exportSymbol, exportInfo, state) { var _a = state.getImportSearches(exportSymbol, exportInfo), importSearches = _a.importSearches, singleReferences = _a.singleReferences, indirectUsers = _a.indirectUsers; + // For `import { foo as bar }` just add the reference to `foo`, and don't otherwise search in the file. if (singleReferences.length) { var addRef = state.referenceAdder(exportSymbol); for (var _i = 0, singleReferences_1 = singleReferences; _i < singleReferences_1.length; _i++) { @@ -78382,20 +93957,22 @@ var ts; addRef(singleRef); } } + // For each import, find all references to that import in its source file. for (var _b = 0, importSearches_1 = importSearches; _b < importSearches_1.length; _b++) { var _c = importSearches_1[_b], importLocation = _c[0], importSymbol = _c[1]; - getReferencesInSourceFile(importLocation.getSourceFile(), state.createSearch(importLocation, importSymbol, 1), state); + getReferencesInSourceFile(importLocation.getSourceFile(), state.createSearch(importLocation, importSymbol, 1 /* Export */), state); } if (indirectUsers.length) { var indirectSearch = void 0; switch (exportInfo.exportKind) { - case 0: - indirectSearch = state.createSearch(exportLocation, exportSymbol, 1); + case 0 /* Named */: + indirectSearch = state.createSearch(exportLocation, exportSymbol, 1 /* Export */); break; - case 1: - indirectSearch = state.options.isForRename ? undefined : state.createSearch(exportLocation, exportSymbol, 1, { text: "default" }); + case 1 /* Default */: + // Search for a property access to '.default'. This can't be renamed. + indirectSearch = state.options.isForRename ? undefined : state.createSearch(exportLocation, exportSymbol, 1 /* Export */, { text: "default" }); break; - case 2: + case 2 /* ExportEquals */: break; } if (indirectSearch) { @@ -78411,17 +93988,22 @@ var ts; return false; if (!state.options.isForRename) return true; + // Don't rename an import type `import("./module-name")` when renaming `name` in `export = name;` if (!ts.isIdentifier(singleRef)) return false; - return !((ts.isExportSpecifier(singleRef.parent) || ts.isImportSpecifier(singleRef.parent)) && singleRef.escapedText === "default"); + // At `default` in `import { default as x }` or `export { default as x }`, do add a reference, but do not rename. + return !((ts.isExportSpecifier(singleRef.parent) || ts.isImportSpecifier(singleRef.parent)) && singleRef.escapedText === "default" /* Default */); } + // Go to the symbol we imported from and find references for it. function searchForImportedSymbol(symbol, state) { for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var declaration = _a[_i]; var exportingFile = declaration.getSourceFile(); - getReferencesInSourceFile(exportingFile, state.createSearch(declaration, symbol, 0), state, state.includesSourceFile(exportingFile)); + // Need to search in the file even if it's not in the search-file set, because it might export the symbol. + getReferencesInSourceFile(exportingFile, state.createSearch(declaration, symbol, 0 /* Import */), state, state.includesSourceFile(exportingFile)); } } + /** Search for all occurences of an identifier in a source file (and filter out the ones that match). */ function searchForName(sourceFile, search, state) { if (ts.getNameTable(sourceFile).get(search.escapedText) !== undefined) { getReferencesInSourceFile(sourceFile, search, state); @@ -78433,9 +94015,9 @@ var ts; : undefined; } function getObjectBindingElementWithoutPropertyName(symbol) { - var bindingElement = ts.getDeclarationOfKind(symbol, 182); + var bindingElement = ts.getDeclarationOfKind(symbol, 182 /* BindingElement */); if (bindingElement && - bindingElement.parent.kind === 180 && + bindingElement.parent.kind === 180 /* ObjectBindingPattern */ && ts.isIdentifier(bindingElement.name) && !bindingElement.propertyName) { return bindingElement; @@ -78445,26 +94027,47 @@ var ts; var bindingElement = getObjectBindingElementWithoutPropertyName(symbol); return bindingElement && ts.getPropertySymbolFromBindingElement(checker, bindingElement); } + /** + * Determines the smallest scope in which a symbol may have named references. + * Note that not every construct has been accounted for. This function can + * probably be improved. + * + * @returns undefined if the scope cannot be determined, implying that + * a reference to a symbol can occur anywhere. + */ function getSymbolScope(symbol) { + // If this is the symbol of a named function expression or named class expression, + // then named references are limited to its own scope. var declarations = symbol.declarations, flags = symbol.flags, parent = symbol.parent, valueDeclaration = symbol.valueDeclaration; - if (valueDeclaration && (valueDeclaration.kind === 192 || valueDeclaration.kind === 205)) { + if (valueDeclaration && (valueDeclaration.kind === 192 /* FunctionExpression */ || valueDeclaration.kind === 205 /* ClassExpression */)) { return valueDeclaration; } if (!declarations) { return undefined; } - if (flags & (4 | 8192)) { - var privateDeclaration = ts.find(declarations, function (d) { return ts.hasModifier(d, 8); }); + // If this is private property or method, the scope is the containing class + if (flags & (4 /* Property */ | 8192 /* Method */)) { + var privateDeclaration = ts.find(declarations, function (d) { return ts.hasModifier(d, 8 /* Private */); }); if (privateDeclaration) { - return ts.getAncestor(privateDeclaration, 235); + return ts.getAncestor(privateDeclaration, 235 /* ClassDeclaration */); } + // Else this is a public property and could be accessed from anywhere. return undefined; } + // If symbol is of object binding pattern element without property name we would want to + // look for property too and that could be anywhere if (getObjectBindingElementWithoutPropertyName(symbol)) { return undefined; } - var exposedByParent = parent && !(symbol.flags & 262144); - if (exposedByParent && !((parent.flags & 1536) && ts.isExternalModuleSymbol(parent) && !parent.globalExports)) { + /* + If the symbol has a parent, it's globally visible unless: + - It's a private property (handled above). + - It's a type parameter. + - The parent is an external module: then we should only search in the module (and recurse on the export later). + - But if the parent has `export as namespace`, the symbol is globally visible through that namespace. + */ + var exposedByParent = parent && !(symbol.flags & 262144 /* TypeParameter */); + if (exposedByParent && !((parent.flags & 1536 /* Module */) && ts.isExternalModuleSymbol(parent) && !parent.globalExports)) { return undefined; } var scope; @@ -78472,15 +94075,25 @@ var ts; var declaration = declarations_10[_i]; var container = ts.getContainerNode(declaration); if (scope && scope !== container) { + // Different declarations have different containers, bail out return undefined; } - if (!container || container.kind === 274 && !ts.isExternalOrCommonJsModule(container)) { + if (!container || container.kind === 274 /* SourceFile */ && !ts.isExternalOrCommonJsModule(container)) { + // This is a global variable and not an external module, any declaration defined + // within this scope is visible outside the file return undefined; } + // The search scope is the container node scope = container; } - return exposedByParent ? scope.getSourceFile() : scope; + // If symbol.parent, this means we are in an export of an external module. (Otherwise we would have returned `undefined` above.) + // For an export of a module, we may be in a declaration file, and it may be accessed elsewhere. E.g.: + // declare module "a" { export type T = number; } + // declare module "b" { import { T } from "a"; export const x: T; } + // So we must search the whole source file. (Because we will mark the source file as seen, we we won't return to it when searching for imports.) + return exposedByParent ? scope.getSourceFile() : scope; // TODO: GH#18217 } + /** Used as a quick check for whether a symbol is used at all in a file (besides its definition). */ function isSymbolReferencedInFile(definition, checker, sourceFile) { return eachSymbolReferenceInFile(definition, checker, sourceFile, function () { return true; }) || false; } @@ -78493,7 +94106,7 @@ var ts; var token = _a[_i]; if (!ts.isIdentifier(token) || token === definition || token.escapedText !== definition.escapedText) continue; - var referenceSymbol = checker.getSymbolAtLocation(token); + var referenceSymbol = checker.getSymbolAtLocation(token); // See GH#19955 for why the type annotation is necessary if (referenceSymbol === symbol || checker.getShorthandAssignmentValueSymbol(token.parent) === symbol || ts.isExportSpecifier(token.parent) && getLocalSymbolForExportSpecifier(token, referenceSymbol, token.parent, checker) === symbol) { @@ -78511,6 +94124,9 @@ var ts; function getPossibleSymbolReferencePositions(sourceFile, symbolName, container) { if (container === void 0) { container = sourceFile; } var positions = []; + /// TODO: Cache symbol existence for files to save text search + // Also, need to make this work for unicode escapes. + // Be resilient in the face of a symbol with no name or zero length name if (!symbolName || !symbolName.length) { return positions; } @@ -78519,11 +94135,15 @@ var ts; var symbolNameLength = symbolName.length; var position = text.indexOf(symbolName, container.pos); while (position >= 0) { + // If we are past the end, stop looking if (position > container.end) break; + // We found a match. Make sure it's not part of a larger word (i.e. the char + // before and after it have to be a non-identifier char). var endPosition = position + symbolNameLength; - if ((position === 0 || !ts.isIdentifierPart(text.charCodeAt(position - 1), 6)) && - (endPosition === sourceLength || !ts.isIdentifierPart(text.charCodeAt(endPosition), 6))) { + if ((position === 0 || !ts.isIdentifierPart(text.charCodeAt(position - 1), 6 /* Latest */)) && + (endPosition === sourceLength || !ts.isIdentifierPart(text.charCodeAt(endPosition), 6 /* Latest */))) { + // Found a real match. Keep searching. positions.push(position); } position = text.indexOf(symbolName, position + symbolNameLength + 1); @@ -78534,22 +94154,24 @@ var ts; var sourceFile = container.getSourceFile(); var labelName = targetLabel.text; var references = ts.mapDefined(getPossibleSymbolReferenceNodes(sourceFile, labelName, container), function (node) { + // Only pick labels that are either the target label, or have a target that is the target label return node === targetLabel || (ts.isJumpStatementTarget(node) && ts.getTargetLabel(node, labelName) === targetLabel) ? FindAllReferences.nodeEntry(node) : undefined; }); return [{ definition: { type: "label", node: targetLabel }, references: references }]; } function isValidReferencePosition(node, searchSymbolName) { + // Compare the length so we filter out strict superstrings of the symbol we are looking for switch (node.kind) { - case 71: + case 71 /* Identifier */: return node.text.length === searchSymbolName.length; - case 9: { + case 9 /* StringLiteral */: { var str = node; return (ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(str) || ts.isNameOfModuleDeclaration(node) || ts.isExpressionOfExternalModuleImportEqualsDeclaration(node)) && str.text.length === searchSymbolName.length; } - case 8: + case 8 /* NumericLiteral */: return ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node) && node.text.length === searchSymbolName.length; - case 79: + case 79 /* DefaultKeyword */: return "default".length === searchSymbolName.length; default: return false; @@ -78569,6 +94191,11 @@ var ts; state.cancellationToken.throwIfCancellationRequested(); return getReferencesInContainer(sourceFile, sourceFile, search, state, addReferencesHere); } + /** + * Search within node "container" for references for a search value, where the search value is defined as a + * tuple of(searchSymbol, searchText, searchLocation, and searchMeaning). + * searchLocation: a node where the search value + */ function getReferencesInContainer(container, sourceFile, search, state, addReferencesHere) { if (!state.markSearchedSymbols(sourceFile, search.allSearchSymbols)) { return; @@ -78584,7 +94211,14 @@ var ts; function getReferencesAtLocation(sourceFile, position, search, state, addReferencesHere) { var referenceLocation = ts.getTouchingPropertyName(sourceFile, position); if (!isValidReferencePosition(referenceLocation, search.text)) { + // This wasn't the start of a token. Check to see if it might be a + // match in a comment or string if that's what the caller is asking + // for. if (!state.options.implementations && (state.options.findInStrings && ts.isInString(sourceFile, position) || state.options.findInComments && ts.isInNonReferenceComment(sourceFile, position))) { + // In the case where we're looking inside comments/strings, we don't have + // an actual definition. So just use 'undefined' here. Features like + // 'Rename' won't care (as they ignore the definitions), and features like + // 'FindReferences' will just filter out these results. state.addStringOrCommentReference(sourceFile.fileName, ts.createTextSpan(position, search.text.length)); } return; @@ -78597,10 +94231,11 @@ var ts; } var parent = referenceLocation.parent; if (ts.isImportSpecifier(parent) && parent.propertyName === referenceLocation) { + // This is added through `singleReferences` in ImportsResult. If we happen to see it again, don't add it again. return; } if (ts.isExportSpecifier(parent)) { - ts.Debug.assert(referenceLocation.kind === 71); + ts.Debug.assert(referenceLocation.kind === 71 /* Identifier */); getReferencesAtExportSpecifier(referenceLocation, referenceSymbol, parent, search, state, addReferencesHere); return; } @@ -78610,14 +94245,14 @@ var ts; return; } switch (state.specialSearchKind) { - case 0: + case 0 /* None */: if (addReferencesHere) addReference(referenceLocation, relatedSymbol, state); break; - case 1: + case 1 /* Constructor */: addConstructorReferences(referenceLocation, sourceFile, search, state); break; - case 2: + case 2 /* Class */: addClassStaticThisReferences(referenceLocation, search, state); break; default: @@ -78633,11 +94268,14 @@ var ts; return; } if (!propertyName) { - if (!(state.options.isForRename && name.escapedText === "default")) { + // Don't rename at `export { default } from "m";`. (but do continue to search for imports of the re-export) + if (!(state.options.isForRename && name.escapedText === "default" /* Default */)) { addRef(); } } else if (referenceLocation === propertyName) { + // For `export { foo as bar } from "baz"`, "`foo`" will be added from the singleReferences for import searches of the original export. + // For `export { foo as bar };`, where `foo` is a local, so add it now. if (!exportDeclaration.moduleSpecifier) { addRef(); } @@ -78650,14 +94288,16 @@ var ts; addRef(); } } + // For `export { foo as bar }`, rename `foo`, but not `bar`. if (!(referenceLocation === propertyName && state.options.isForRename)) { - var exportKind = referenceLocation.originalKeywordKind === 79 ? 1 : 0; + var exportKind = referenceLocation.originalKeywordKind === 79 /* DefaultKeyword */ ? 1 /* Default */ : 0 /* Named */; var exportInfo = FindAllReferences.getExportInfo(referenceSymbol, exportKind, state.checker); if (!exportInfo) return ts.Debug.fail(); searchForImportsOfExport(referenceLocation, referenceSymbol, exportInfo, state); } - if (search.comingFrom !== 1 && exportDeclaration.moduleSpecifier && !propertyName) { + // At `export { x } from "foo"`, also search for the imported symbol `"foo".x`. + if (search.comingFrom !== 1 /* Export */ && exportDeclaration.moduleSpecifier && !propertyName) { var imported = state.checker.getExportSpecifierLocalTargetSymbol(exportSpecifier); if (imported) searchForImportedSymbol(imported, state); @@ -78674,30 +94314,41 @@ var ts; var parent = exportSpecifier.parent, propertyName = exportSpecifier.propertyName, name = exportSpecifier.name; ts.Debug.assert(propertyName === referenceLocation || name === referenceLocation); if (propertyName) { + // Given `export { foo as bar } [from "someModule"]`: It's an alias at `foo`, but at `bar` it's a new symbol. return propertyName === referenceLocation; } else { + // `export { foo } from "foo"` is a re-export. + // `export { foo };` is not a re-export, it creates an alias for the local variable `foo`. return !parent.parent.moduleSpecifier; } } function getImportOrExportReferences(referenceLocation, referenceSymbol, search, state) { - var importOrExport = FindAllReferences.getImportOrExportSymbol(referenceLocation, referenceSymbol, state.checker, search.comingFrom === 1); + var importOrExport = FindAllReferences.getImportOrExportSymbol(referenceLocation, referenceSymbol, state.checker, search.comingFrom === 1 /* Export */); if (!importOrExport) return; var symbol = importOrExport.symbol; - if (importOrExport.kind === 0) { + if (importOrExport.kind === 0 /* Import */) { if (!state.options.isForRename || importOrExport.isNamedImport) { searchForImportedSymbol(symbol, state); } } else { + // We don't check for `state.isForRename`, even for default exports, because importers that previously matched the export name should be updated to continue matching. searchForImportsOfExport(referenceLocation, symbol, importOrExport.exportInfo, state); } } function getReferenceForShorthandProperty(_a, search, state) { var flags = _a.flags, valueDeclaration = _a.valueDeclaration; var shorthandValueSymbol = state.checker.getShorthandAssignmentValueSymbol(valueDeclaration); - if (!(flags & 33554432) && search.includes(shorthandValueSymbol)) { + /* + * Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment + * has two meanings: property name and property value. Therefore when we do findAllReference at the position where + * an identifier is declared, the language service should return the position of the variable declaration as well as + * the position in short-hand property assignment excluding property accessing. However, if we do findAllReference at the + * position of property accessing, the referenceEntry of such position will be handled in the first case. + */ + if (!(flags & 33554432 /* Transient */) && search.includes(shorthandValueSymbol)) { addReference(ts.getNameOfDeclaration(valueDeclaration), shorthandValueSymbol, state); } } @@ -78710,16 +94361,19 @@ var ts; addRef(referenceLocation); } } + /** Adds references when a constructor is used with `new this()` in its own class and `super()` calls in subclasses. */ function addConstructorReferences(referenceLocation, sourceFile, search, state) { if (ts.isNewExpressionTarget(referenceLocation)) { addReference(referenceLocation, search.symbol, state); } var pusher = function () { return state.referenceAdder(search.symbol); }; if (ts.isClassLike(referenceLocation.parent)) { - ts.Debug.assert(referenceLocation.kind === 79 || referenceLocation.parent.name === referenceLocation); + ts.Debug.assert(referenceLocation.kind === 79 /* DefaultKeyword */ || referenceLocation.parent.name === referenceLocation); + // This is the class declaration containing the constructor. findOwnConstructorReferences(search.symbol, sourceFile, pusher()); } else { + // If this class appears in `extends C`, then the extending class' "super" calls are references. var classExtending = tryGetClassByExtendingIdentifier(referenceLocation); if (classExtending) { findSuperConstructorAccesses(classExtending, pusher()); @@ -78735,12 +94389,12 @@ var ts; var addRef = state.referenceAdder(search.symbol); for (var _i = 0, _a = classLike.members; _i < _a.length; _i++) { var member = _a[_i]; - if (!(ts.isMethodOrAccessor(member) && ts.hasModifier(member, 32))) { + if (!(ts.isMethodOrAccessor(member) && ts.hasModifier(member, 32 /* Static */))) { continue; } if (member.body) { member.body.forEachChild(function cb(node) { - if (node.kind === 99) { + if (node.kind === 99 /* ThisKeyword */) { addRef(node); } else if (!ts.isFunctionLike(node) && !ts.isClassLike(node)) { @@ -78750,19 +94404,23 @@ var ts; } } } + /** + * `classSymbol` is the class where the constructor was defined. + * Reference the constructor and all calls to `new this()`. + */ function findOwnConstructorReferences(classSymbol, sourceFile, addNode) { - for (var _i = 0, _a = classSymbol.members.get("__constructor").declarations; _i < _a.length; _i++) { + for (var _i = 0, _a = classSymbol.members.get("__constructor" /* Constructor */).declarations; _i < _a.length; _i++) { var decl = _a[_i]; - var ctrKeyword = ts.findChildOfKind(decl, 123, sourceFile); - ts.Debug.assert(decl.kind === 155 && !!ctrKeyword); + var ctrKeyword = ts.findChildOfKind(decl, 123 /* ConstructorKeyword */, sourceFile); + ts.Debug.assert(decl.kind === 155 /* Constructor */ && !!ctrKeyword); addNode(ctrKeyword); } classSymbol.exports.forEach(function (member) { var decl = member.valueDeclaration; - if (decl && decl.kind === 154) { + if (decl && decl.kind === 154 /* MethodDeclaration */) { var body = decl.body; if (body) { - forEachDescendantOfKind(body, 99, function (thisKeyword) { + forEachDescendantOfKind(body, 99 /* ThisKeyword */, function (thisKeyword) { if (ts.isNewExpressionTarget(thisKeyword)) { addNode(thisKeyword); } @@ -78771,17 +94429,18 @@ var ts; } }); } + /** Find references to `super` in the constructor of an extending class. */ function findSuperConstructorAccesses(cls, addNode) { - var ctr = cls.symbol.members.get("__constructor"); + var ctr = cls.symbol.members.get("__constructor" /* Constructor */); if (!ctr) { return; } for (var _i = 0, _a = ctr.declarations; _i < _a.length; _i++) { var decl = _a[_i]; - ts.Debug.assert(decl.kind === 155); + ts.Debug.assert(decl.kind === 155 /* Constructor */); var body = decl.body; if (body) { - forEachDescendantOfKind(body, 97, function (node) { + forEachDescendantOfKind(body, 97 /* SuperKeyword */, function (node) { if (ts.isCallExpressionTarget(node)) { addNode(node); } @@ -78790,21 +94449,26 @@ var ts; } } function addImplementationReferences(refNode, addReference, state) { + // Check if we found a function/propertyAssignment/method with an implementation or initializer if (ts.isDeclarationName(refNode) && isImplementation(refNode.parent)) { addReference(refNode); return; } - if (refNode.kind !== 71) { + if (refNode.kind !== 71 /* Identifier */) { return; } - if (refNode.parent.kind === 271) { + if (refNode.parent.kind === 271 /* ShorthandPropertyAssignment */) { + // Go ahead and dereference the shorthand assignment by going to its definition getReferenceEntriesForShorthandPropertyAssignment(refNode, state.checker, addReference); } + // Check if the node is within an extends or implements clause var containingClass = getContainingClassIfInHeritageClause(refNode); if (containingClass) { addReference(containingClass); return; } + // If we got a type reference, try and see if the reference applies to any expressions that can implement an interface + // Find the first node whose parent isn't a type node -- i.e., the highest type node. var typeNode = ts.findAncestor(refNode, function (a) { return !ts.isQualifiedName(a.parent) && !ts.isTypeNode(a.parent) && !ts.isTypeElement(a.parent); }); var typeHavingNode = typeNode.parent; if (ts.hasType(typeHavingNode) && typeHavingNode.type === typeNode && state.markSeenContainingTypeReference(typeHavingNode)) { @@ -78813,7 +94477,7 @@ var ts; } else if (ts.isFunctionLike(typeHavingNode) && typeHavingNode.body) { var body = typeHavingNode.body; - if (body.kind === 213) { + if (body.kind === 213 /* Block */) { ts.forEachReturnStatement(body, function (returnStatement) { if (returnStatement.expression) addIfImplementation(returnStatement.expression); @@ -78836,20 +94500,42 @@ var ts; return ts.isIdentifier(node) || ts.isPropertyAccessExpression(node) ? getContainingClassIfInHeritageClause(node.parent) : ts.isExpressionWithTypeArguments(node) ? ts.tryCast(node.parent.parent, ts.isClassLike) : undefined; } + /** + * Returns true if this is an expression that can be considered an implementation + */ function isImplementationExpression(node) { switch (node.kind) { - case 191: + case 191 /* ParenthesizedExpression */: return isImplementationExpression(node.expression); - case 193: - case 192: - case 184: - case 205: - case 183: + case 193 /* ArrowFunction */: + case 192 /* FunctionExpression */: + case 184 /* ObjectLiteralExpression */: + case 205 /* ClassExpression */: + case 183 /* ArrayLiteralExpression */: return true; default: return false; } } + /** + * Determines if the parent symbol occurs somewhere in the child's ancestry. If the parent symbol + * is an interface, determines if some ancestor of the child symbol extends or inherits from it. + * Also takes in a cache of previous results which makes this slightly more efficient and is + * necessary to avoid potential loops like so: + * class A extends B { } + * class B extends A { } + * + * We traverse the AST rather than using the type checker because users are typically only interested + * in explicit implementations of an interface/class when calling "Go to Implementation". Sibling + * implementations of types that share a common ancestor with the type whose implementation we are + * searching for need to be filtered out of the results. The type checker doesn't let us make the + * distinction between structurally compatible implementations and explicit implementations, so we + * must use the AST. + * + * @param symbol A class or interface Symbol + * @param parent Another class or interface Symbol + * @param cachedResults A map of symbol id pairs (i.e. "child,parent") to booleans indicating previous results + */ function explicitlyInheritsFrom(symbol, parent, cachedResults, checker) { if (symbol === parent) { return true; @@ -78859,6 +94545,7 @@ var ts; if (cached !== undefined) { return cached; } + // Set the key so that we don't infinitely recurse cachedResults.set(key, false); var inherits = symbol.declarations.some(function (declaration) { return ts.getAllSuperTypeNodes(declaration).some(function (typeReference) { @@ -78870,81 +94557,92 @@ var ts; return inherits; } function getReferencesForSuperKeyword(superKeyword) { - var searchSpaceNode = ts.getSuperContainer(superKeyword, false); + var searchSpaceNode = ts.getSuperContainer(superKeyword, /*stopOnFunctions*/ false); if (!searchSpaceNode) { return undefined; } - var staticFlag = 32; + // Whether 'super' occurs in a static context within a class. + var staticFlag = 32 /* Static */; switch (searchSpaceNode.kind) { - case 152: - case 151: - case 154: - case 153: - case 155: - case 156: - case 157: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: staticFlag &= ts.getModifierFlags(searchSpaceNode); - searchSpaceNode = searchSpaceNode.parent; + searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class break; default: return undefined; } var sourceFile = searchSpaceNode.getSourceFile(); var references = ts.mapDefined(getPossibleSymbolReferenceNodes(sourceFile, "super", searchSpaceNode), function (node) { - if (node.kind !== 97) { + if (node.kind !== 97 /* SuperKeyword */) { return; } - var container = ts.getSuperContainer(node, false); - return container && (32 & ts.getModifierFlags(container)) === staticFlag && container.parent.symbol === searchSpaceNode.symbol ? FindAllReferences.nodeEntry(node) : undefined; + var container = ts.getSuperContainer(node, /*stopOnFunctions*/ false); + // If we have a 'super' container, we must have an enclosing class. + // Now make sure the owning class is the same as the search-space + // and has the same static qualifier as the original 'super's owner. + return container && (32 /* Static */ & ts.getModifierFlags(container)) === staticFlag && container.parent.symbol === searchSpaceNode.symbol ? FindAllReferences.nodeEntry(node) : undefined; }); return [{ definition: { type: "symbol", symbol: searchSpaceNode.symbol }, references: references }]; } function getReferencesForThisKeyword(thisOrSuperKeyword, sourceFiles, cancellationToken) { - var searchSpaceNode = ts.getThisContainer(thisOrSuperKeyword, false); - var staticFlag = 32; + var searchSpaceNode = ts.getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false); + // Whether 'this' occurs in a static context within a class. + var staticFlag = 32 /* Static */; switch (searchSpaceNode.kind) { - case 154: - case 153: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: if (ts.isObjectLiteralMethod(searchSpaceNode)) { break; } - case 152: - case 151: - case 155: - case 156: - case 157: + // falls through + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: staticFlag &= ts.getModifierFlags(searchSpaceNode); - searchSpaceNode = searchSpaceNode.parent; + searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class break; - case 274: + case 274 /* SourceFile */: if (ts.isExternalModule(searchSpaceNode)) { return undefined; } - case 234: - case 192: + // falls through + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: break; + // Computed properties in classes are not handled here because references to this are illegal, + // so there is no point finding references to them. default: return undefined; } - var references = ts.flatMap(searchSpaceNode.kind === 274 ? sourceFiles : [searchSpaceNode.getSourceFile()], function (sourceFile) { + var references = ts.flatMap(searchSpaceNode.kind === 274 /* SourceFile */ ? sourceFiles : [searchSpaceNode.getSourceFile()], function (sourceFile) { cancellationToken.throwIfCancellationRequested(); return getPossibleSymbolReferenceNodes(sourceFile, "this", ts.isSourceFile(searchSpaceNode) ? sourceFile : searchSpaceNode).filter(function (node) { if (!ts.isThis(node)) { return false; } - var container = ts.getThisContainer(node, false); + var container = ts.getThisContainer(node, /* includeArrowFunctions */ false); switch (searchSpaceNode.kind) { - case 192: - case 234: + case 192 /* FunctionExpression */: + case 234 /* FunctionDeclaration */: return searchSpaceNode.symbol === container.symbol; - case 154: - case 153: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: return ts.isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol; - case 205: - case 235: - return container.parent && searchSpaceNode.symbol === container.parent.symbol && (ts.getModifierFlags(container) & 32) === staticFlag; - case 274: - return container.kind === 274 && !ts.isExternalModule(container); + case 205 /* ClassExpression */: + case 235 /* ClassDeclaration */: + // Make sure the container belongs to the same class + // and has the appropriate static modifier from the original container. + return container.parent && searchSpaceNode.symbol === container.parent.symbol && (ts.getModifierFlags(container) & 32 /* Static */) === staticFlag; + case 274 /* SourceFile */: + return container.kind === 274 /* SourceFile */ && !ts.isExternalModule(container); } }); }).map(function (n) { return FindAllReferences.nodeEntry(n); }); @@ -78957,7 +94655,7 @@ var ts; var references = ts.flatMap(sourceFiles, function (sourceFile) { cancellationToken.throwIfCancellationRequested(); return ts.mapDefined(getPossibleSymbolReferenceNodes(sourceFile, node.text), function (ref) { - return ts.isStringLiteral(ref) && ref.text === node.text ? FindAllReferences.nodeEntry(ref, true) : undefined; + return ts.isStringLiteral(ref) && ref.text === node.text ? FindAllReferences.nodeEntry(ref, /*isInString*/ true) : undefined; }); }); return [{ @@ -78965,21 +94663,41 @@ var ts; references: references }]; } + // For certain symbol kinds, we need to include other symbols in the search set. + // This is not needed when searching for re-exports. function populateSearchSymbolSet(symbol, location, checker, implementations) { var result = []; - forEachRelatedSymbol(symbol, location, checker, function (sym, root, base) { result.push(base || root || sym); }, function () { return !implementations; }); + forEachRelatedSymbol(symbol, location, checker, function (sym, root, base) { result.push(base || root || sym); }, + /*allowBaseTypes*/ function () { return !implementations; }); return result; } function forEachRelatedSymbol(symbol, location, checker, cbSymbol, allowBaseTypes) { var containingObjectLiteralElement = ts.getContainingObjectLiteralElement(location); if (containingObjectLiteralElement) { + // If the location is in a context sensitive location (i.e. in an object literal) try + // to get a contextual type for it, and add the property symbol from the contextual + // type to the search set var res_1 = ts.firstDefined(getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker), fromRoot); if (res_1) return res_1; + // If the location is name of property symbol from object literal destructuring pattern + // Search the property symbol + // for ( { property: p2 } of elems) { } var propertySymbol = getPropertySymbolOfDestructuringAssignment(location, checker); var res1 = propertySymbol && cbSymbol(propertySymbol); if (res1) return res1; + /* Because in short-hand property assignment, location has two meaning : property name and as value of the property + * When we do findAllReference at the position of the short-hand property assignment, we would want to have references to position of + * property name and variable declaration of the identifier. + * Like in below example, when querying for all references for an identifier 'name', of the property assignment, the language service + * should show both 'name' in 'obj' and 'name' in variable declaration + * const name = "Foo"; + * const obj = { name }; + * In order to do that, we will populate the search set with the value symbol of the identifier as a value of the property assignment + * so that when matching with potential reference symbol, both symbols from property declaration and variable declaration + * will be included correctly. + */ var shorthandValueSymbol = checker.getShorthandAssignmentValueSymbol(location.parent); var res2 = shorthandValueSymbol && cbSymbol(shorthandValueSymbol); if (res2) @@ -78989,16 +94707,26 @@ var ts; if (res) return res; if (symbol.valueDeclaration && ts.isParameterPropertyDeclaration(symbol.valueDeclaration)) { + // For a parameter property, now try on the other symbol (property if this was a parameter, parameter if this was a property). var paramProps = checker.getSymbolsOfParameterPropertyDeclaration(ts.cast(symbol.valueDeclaration, ts.isParameter), symbol.name); - ts.Debug.assert(paramProps.length === 2 && !!(paramProps[0].flags & 1) && !!(paramProps[1].flags & 4)); - return fromRoot(symbol.flags & 1 ? paramProps[1] : paramProps[0]); + ts.Debug.assert(paramProps.length === 2 && !!(paramProps[0].flags & 1 /* FunctionScopedVariable */) && !!(paramProps[1].flags & 4 /* Property */)); // is [parameter, property] + return fromRoot(symbol.flags & 1 /* FunctionScopedVariable */ ? paramProps[1] : paramProps[0]); } + // If this is symbol of binding element without propertyName declaration in Object binding pattern + // Include the property in the search var bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol, checker); return bindingElementPropertySymbol && fromRoot(bindingElementPropertySymbol); function fromRoot(sym) { + // If this is a union property: + // - In populateSearchSymbolsSet we will add all the symbols from all its source symbols in all unioned types. + // - In findRelatedSymbol, we will just use the union symbol if any source symbol is included in the search. + // If the symbol is an instantiation from a another symbol (e.g. widened symbol): + // - In populateSearchSymbolsSet, add the root the list + // - In findRelatedSymbol, return the source symbol if that is in the search. (Do not return the instantiation symbol.) return ts.firstDefined(checker.getRootSymbols(sym), function (rootSymbol) { return cbSymbol(sym, rootSymbol) - || (rootSymbol.parent && rootSymbol.parent.flags & (32 | 64) && allowBaseTypes(rootSymbol) + // Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions + || (rootSymbol.parent && rootSymbol.parent.flags & (32 /* Class */ | 64 /* Interface */) && allowBaseTypes(rootSymbol) ? ts.getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, checker, function (base) { return cbSymbol(sym, rootSymbol, base); }) : undefined); }); @@ -79007,24 +94735,40 @@ var ts; function getRelatedSymbol(search, referenceSymbol, referenceLocation, state) { var checker = state.checker; return forEachRelatedSymbol(referenceSymbol, referenceLocation, checker, function (sym, rootSymbol, baseSymbol) { return search.includes(baseSymbol || rootSymbol || sym) - ? rootSymbol && !(ts.getCheckFlags(sym) & 6) ? rootSymbol : sym - : undefined; }, function (rootSymbol) { + // For a base type, use the symbol for the derived type. For a synthetic (e.g. union) property, use the union symbol. + ? rootSymbol && !(ts.getCheckFlags(sym) & 6 /* Synthetic */) ? rootSymbol : sym + : undefined; }, + /*allowBaseTypes*/ function (rootSymbol) { return !(search.parents && !search.parents.some(function (parent) { return explicitlyInheritsFrom(rootSymbol.parent, parent, state.inheritsFromCache, checker); })); }); } + /** Gets all symbols for one property. Does not get symbols for every property. */ function getPropertySymbolsFromContextualType(node, checker) { var contextualType = checker.getContextualType(node.parent); var name = ts.getNameFromPropertyName(node.name); var symbol = contextualType && name && contextualType.getProperty(name); return symbol ? [symbol] : - contextualType && contextualType.isUnion() ? ts.mapDefined(contextualType.types, function (t) { return t.getProperty(name); }) : ts.emptyArray; + contextualType && contextualType.isUnion() ? ts.mapDefined(contextualType.types, function (t) { return t.getProperty(name); }) : ts.emptyArray; // TODO: GH#18217 } + /** + * Given an initial searchMeaning, extracted from a location, widen the search scope based on the declarations + * of the corresponding symbol. e.g. if we are searching for "Foo" in value position, but "Foo" references a class + * then we need to widen the search to include type positions as well. + * On the contrary, if we are searching for "Bar" in type position and we trace bar to an interface, and an uninstantiated + * module, we want to keep the search limited to only types, as the two declarations (interface and uninstantiated module) + * do not intersect in any of the three spaces. + */ function getIntersectingMeaningFromDeclarations(node, symbol) { var meaning = ts.getMeaningFromLocation(node); var declarations = symbol.declarations; if (declarations) { var lastIterationMeaning = void 0; do { + // The result is order-sensitive, for instance if initialMeaning === Namespace, and declarations = [class, instantiated module] + // we need to consider both as they initialMeaning intersects with the module in the namespace space, and the module + // intersects with the class in the value space. + // To achieve that we will keep iterating until the result stabilizes. + // Remember the last meaning lastIterationMeaning = meaning; for (var _i = 0, declarations_11 = declarations; _i < declarations_11.length; _i++) { var declaration = declarations_11[_i]; @@ -79039,7 +94783,7 @@ var ts; } Core.getIntersectingMeaningFromDeclarations = getIntersectingMeaningFromDeclarations; function isImplementation(node) { - return !!(node.flags & 4194304) + return !!(node.flags & 4194304 /* Ambient */) || (ts.isVariableLike(node) ? ts.hasInitializer(node) : ts.isFunctionLikeDeclaration(node) ? !!node.body : ts.isClassLike(node) || ts.isModuleOrEnumDeclaration(node)); @@ -79050,7 +94794,7 @@ var ts; if (shorthandSymbol) { for (var _i = 0, _a = shorthandSymbol.getDeclarations(); _i < _a.length; _i++) { var declaration = _a[_i]; - if (ts.getMeaningFromDeclaration(declaration) & 1) { + if (ts.getMeaningFromDeclaration(declaration) & 1 /* Value */) { addReference(declaration); } } @@ -79065,20 +94809,28 @@ var ts; forEachDescendantOfKind(child, kind, action); }); } + /** Get `C` given `N` if `N` is in the position `class C extends N` or `class C extends foo.N` where `N` is an identifier. */ function tryGetClassByExtendingIdentifier(node) { return ts.tryGetClassExtendingExpressionWithTypeArguments(ts.climbPastPropertyAccess(node).parent); } + /** + * If we are just looking for implementations and this is a property access expression, we need to get the + * symbol of the local type of the symbol the property is being accessed on. This is because our search + * symbol may have a different parent symbol if the local type's symbol does not declare the property + * being accessed (i.e. it is declared in some parent class or interface) + */ function getParentSymbolsOfPropertyAccess(location, symbol, checker) { var propertyAccessExpression = ts.isRightSideOfPropertyAccess(location) ? location.parent : undefined; var lhsType = propertyAccessExpression && checker.getTypeAtLocation(propertyAccessExpression.expression); var res = ts.mapDefined(lhsType && (lhsType.isUnionOrIntersection() ? lhsType.types : lhsType.symbol === symbol.parent ? undefined : [lhsType]), function (t) { - return t.symbol && t.symbol.flags & (32 | 64) ? t.symbol : undefined; + return t.symbol && t.symbol.flags & (32 /* Class */ | 64 /* Interface */) ? t.symbol : undefined; }); return res.length === 0 ? undefined : res; } })(Core = FindAllReferences.Core || (FindAllReferences.Core = {})); })(FindAllReferences = ts.FindAllReferences || (ts.FindAllReferences = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { function getEditsForFileRename(program, oldFileOrDirPath, newFileOrDirPath, host, formatContext, preferences) { @@ -79118,7 +94870,8 @@ var ts; var foundExactMatch = updatePaths(property); if (!foundExactMatch && propertyName === "include" && ts.isArrayLiteralExpression(property.initializer)) { var includes = ts.mapDefined(property.initializer.elements, function (e) { return ts.isStringLiteral(e) ? e.text : undefined; }); - var matchers = ts.getFileMatcherPatterns(configDir, [], includes, useCaseSensitiveFileNames, currentDirectory); + var matchers = ts.getFileMatcherPatterns(configDir, /*excludes*/ [], includes, useCaseSensitiveFileNames, currentDirectory); + // If there isn't some include for this, add a new one. if (!ts.getRegexFromPattern(ts.Debug.assertDefined(matchers.includeFilePattern), useCaseSensitiveFileNames).test(newFileOrDirPath)) { changeTracker.insertNodeAfter(configFile, ts.last(property.initializer.elements), ts.createStringLiteral(relativePath(newFileOrDirPath))); } @@ -79146,6 +94899,7 @@ var ts; } }); function updatePaths(property) { + // Type annotation needed due to #7294 var elements = ts.isArrayLiteralExpression(property.initializer) ? property.initializer.elements : [property.initializer]; var foundExactMatch = false; for (var _i = 0, elements_5 = elements; _i < elements_5.length; _i++) { @@ -79166,7 +94920,7 @@ var ts; return false; } function relativePath(path) { - return ts.getRelativePathFromDirectory(configDir, path, !useCaseSensitiveFileNames); + return ts.getRelativePathFromDirectory(configDir, path, /*ignoreCase*/ !useCaseSensitiveFileNames); } } function updateImports(program, changeTracker, oldToNew, newToOld, host, getCanonicalFileName, preferences) { @@ -79186,8 +94940,11 @@ var ts; return newAbsolute === undefined ? undefined : ts.ensurePathIsNonModuleName(ts.getRelativePathFromDirectory(newImportFromDirectory, newAbsolute, getCanonicalFileName)); }, function (importLiteral) { var toImport = oldFromNew !== undefined + // If we're at the new location (file was already renamed), need to redo module resolution starting from the old location. + // TODO:GH#18217 ? getSourceFileToImportFromResolved(ts.resolveModuleName(importLiteral.text, oldImportFromPath, program.getCompilerOptions(), host), oldToNew, program) : getSourceFileToImport(importLiteral, sourceFile, program, host, oldToNew); + // If neither the importing source file nor the imported file moved, do nothing. return toImport === undefined || !toImport.updated && !importingSourceFileMoved ? undefined : ts.moduleSpecifiers.getModuleSpecifier(program.getCompilerOptions(), sourceFile, newImportFromPath, toImport.newFileName, host, preferences); @@ -79208,7 +94965,7 @@ var ts; var symbol = program.getTypeChecker().getSymbolAtLocation(importLiteral); if (symbol) { if (symbol.declarations.some(function (d) { return ts.isAmbientModule(d); })) - return undefined; + return undefined; // No need to update if it's an ambient module var oldFileName = ts.find(symbol.declarations, ts.isSourceFile).fileName; var newFileName = oldToNew(oldFileName); return newFileName === undefined ? { newFileName: oldFileName, updated: false } : { newFileName: newFileName, updated: true }; @@ -79257,6 +95014,7 @@ var ts; } } })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var GoToDefinition; @@ -79271,31 +95029,54 @@ var ts; return undefined; } var parent = node.parent; + // Labels if (ts.isJumpStatementTarget(node)) { var label = ts.getTargetLabel(node.parent, node.text); - return label ? [createDefinitionInfoFromName(label, "label", node.text, undefined)] : undefined; + return label ? [createDefinitionInfoFromName(label, "label" /* label */, node.text, /*containerName*/ undefined)] : undefined; // TODO: GH#18217 } var typeChecker = program.getTypeChecker(); var symbol = getSymbol(node, typeChecker); + // Could not find a symbol e.g. node is string or number keyword, + // or the symbol was an internal symbol and does not have a declaration e.g. undefined symbol if (!symbol) { return getDefinitionInfoForIndexSignatures(node, typeChecker); } var calledDeclaration = tryGetSignatureDeclaration(typeChecker, node); if (calledDeclaration) { var sigInfo = createDefinitionFromSignatureDeclaration(typeChecker, calledDeclaration); + // For a function, if this is the original function definition, return just sigInfo. + // If this is the original constructor definition, parent is the class. if (typeChecker.getRootSymbols(symbol).some(function (s) { return symbolMatchesSignature(s, calledDeclaration); }) || - symbol.declarations.some(function (d) { return ts.isVariableDeclaration(d) && !!d.initializer && ts.isRequireCall(d.initializer, false); })) { + // TODO: GH#23742 Following check shouldn't be necessary if 'require' is an alias + symbol.declarations.some(function (d) { return ts.isVariableDeclaration(d) && !!d.initializer && ts.isRequireCall(d.initializer, /*checkArgumentIsStringLiteralLike*/ false); })) { return [sigInfo]; } else { var defs = getDefinitionFromSymbol(typeChecker, symbol, node); - return node.kind === 97 ? [sigInfo].concat(defs) : defs.concat([sigInfo]); + // For a 'super()' call, put the signature first, else put the variable first. + return node.kind === 97 /* SuperKeyword */ ? [sigInfo].concat(defs) : defs.concat([sigInfo]); } } - if (node.parent.kind === 271) { + // Because name in short-hand property assignment has two different meanings: property name and property value, + // using go-to-definition at such position should go to the variable declaration of the property value rather than + // go to the declaration of the property name (in this case stay at the same position). However, if go-to-definition + // is performed at the location of property access, we would like to go to definition of the property in the short-hand + // assignment. This case and others are handled by the following code. + if (node.parent.kind === 271 /* ShorthandPropertyAssignment */) { var shorthandSymbol_1 = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); return shorthandSymbol_1 ? shorthandSymbol_1.declarations.map(function (decl) { return createDefinitionInfo(decl, typeChecker, shorthandSymbol_1, node); }) : []; } + // If the node is the name of a BindingElement within an ObjectBindingPattern instead of just returning the + // declaration the symbol (which is itself), we should try to get to the original type of the ObjectBindingPattern + // and return the property declaration for the referenced property. + // For example: + // import('./foo').then(({ b/*goto*/ar }) => undefined); => should get use to the declaration in file "./foo" + // + // function bar(onfulfilled: (value: T) => void) { //....} + // interface Test { + // pr/*destination*/op1: number + // } + // bar(({pr/*goto*/op1})=>{}); if (ts.isPropertyName(node) && ts.isBindingElement(parent) && ts.isObjectBindingPattern(parent.parent) && (node === (parent.propertyName || parent.name))) { var type = typeChecker.getTypeAtLocation(parent.parent); @@ -79306,6 +95087,15 @@ var ts; } } } + // If the current location we want to find its definition is in an object literal, try to get the contextual type for the + // object literal, lookup the property symbol in the contextual type, and use this for goto-definition. + // For example + // interface Props{ + // /*first*/prop1: number + // prop2: boolean + // } + // function Foo(arg: Props) {} + // Foo( { pr/*1*/op1: 10, prop2: true }) var element = ts.getContainingObjectLiteralElement(node); if (element && typeChecker.getContextualType(element.parent)) { return ts.flatMap(ts.getPropertySymbolsFromContextualType(typeChecker, element), function (propertySymbol) { @@ -79315,6 +95105,10 @@ var ts; return getDefinitionFromSymbol(typeChecker, symbol, node); } GoToDefinition.getDefinitionAtPosition = getDefinitionAtPosition; + /** + * True if we should not add definitions for both the signature symbol and the definition symbol. + * True for `const |f = |() => 0`, false for `function |f() {} const |g = f;`. + */ function symbolMatchesSignature(s, calledDeclaration) { return s === calledDeclaration.symbol || s === calledDeclaration.symbol.parent || ts.isVariableDeclaration(calledDeclaration.parent) && s === calledDeclaration.parent.symbol; @@ -79328,7 +95122,7 @@ var ts; var typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position); if (typeReferenceDirective) { var reference = program.getResolvedTypeReferenceDirectives().get(typeReferenceDirective.fileName); - var file = reference && program.getSourceFile(reference.resolvedFileName); + var file = reference && program.getSourceFile(reference.resolvedFileName); // TODO:GH#18217 return file && { fileName: typeReferenceDirective.fileName, file: file }; } var libReferenceDirective = findReferenceInPosition(sourceFile.libReferenceDirectives, position); @@ -79339,6 +95133,7 @@ var ts; return undefined; } GoToDefinition.getReferenceAtPosition = getReferenceAtPosition; + /// Goto type function getTypeDefinitionAtPosition(typeChecker, sourceFile, position) { var node = ts.getTouchingPropertyName(sourceFile, position); if (node === sourceFile) { @@ -79349,7 +95144,7 @@ var ts; if (!type) { return undefined; } - if (type.isUnion() && !(type.flags & 32)) { + if (type.isUnion() && !(type.flags & 32 /* Enum */)) { return ts.flatMap(type.types, function (t) { return t.symbol && getDefinitionFromSymbol(typeChecker, t.symbol, node); }); } return type.symbol && getDefinitionFromSymbol(typeChecker, type.symbol, node); @@ -79360,6 +95155,7 @@ var ts; if (!definitions || definitions.length === 0) { return undefined; } + // Check if position is on triple slash reference. var comment = findReferenceInPosition(sourceFile.referencedFiles, position) || findReferenceInPosition(sourceFile.typeReferenceDirectives, position) || findReferenceInPosition(sourceFile.libReferenceDirectives, position); @@ -79371,18 +95167,23 @@ var ts; return { definitions: definitions, textSpan: textSpan }; } GoToDefinition.getDefinitionAndBoundSpan = getDefinitionAndBoundSpan; + // At 'x.foo', see if the type of 'x' has an index signature, and if so find its declarations. function getDefinitionInfoForIndexSignatures(node, checker) { if (!ts.isPropertyAccessExpression(node.parent) || node.parent.name !== node) return; var type = checker.getTypeAtLocation(node.parent.expression); return ts.mapDefined(type.isUnionOrIntersection() ? type.types : [type], function (nonUnionType) { - var info = checker.getIndexInfoOfType(nonUnionType, 0); + var info = checker.getIndexInfoOfType(nonUnionType, 0 /* String */); return info && info.declaration && createDefinitionFromSignatureDeclaration(checker, info.declaration); }); } function getSymbol(node, checker) { var symbol = checker.getSymbolAtLocation(node); - if (symbol && symbol.flags & 2097152 && shouldSkipAlias(node, symbol.declarations[0])) { + // If this is an alias, and the request came at the declaration location + // get the aliased symbol instead. This allows for goto def on an import e.g. + // import {A, B} from "mod"; + // to jump to the implementation directly. + if (symbol && symbol.flags & 2097152 /* Alias */ && shouldSkipAlias(node, symbol.declarations[0])) { var aliased = checker.getAliasedSymbol(symbol); if (aliased.declarations) { return aliased; @@ -79390,19 +95191,24 @@ var ts; } return symbol; } + // Go to the original declaration for cases: + // + // (1) when the aliased symbol was declared in the location(parent). + // (2) when the aliased symbol is originating from an import. + // function shouldSkipAlias(node, declaration) { - if (node.kind !== 71) { + if (node.kind !== 71 /* Identifier */) { return false; } if (node.parent === declaration) { return true; } switch (declaration.kind) { - case 245: - case 243: + case 245 /* ImportClause */: + case 243 /* ImportEqualsDeclaration */: return true; - case 248: - return declaration.parent.kind === 247; + case 248 /* ImportSpecifier */: + return declaration.parent.kind === 247 /* NamedImports */; default: return false; } @@ -79410,14 +95216,16 @@ var ts; function getDefinitionFromSymbol(typeChecker, symbol, node) { return getConstructSignatureDefinition() || getCallSignatureDefinition() || ts.map(symbol.declarations, function (declaration) { return createDefinitionInfo(declaration, typeChecker, symbol, node); }); function getConstructSignatureDefinition() { - if (symbol.flags & 32 && (ts.isNewExpressionTarget(node) || node.kind === 123)) { + // Applicable only if we are in a new expression, or we are on a constructor declaration + // and in either case the symbol has a construct signature definition, i.e. class + if (symbol.flags & 32 /* Class */ && (ts.isNewExpressionTarget(node) || node.kind === 123 /* ConstructorKeyword */)) { var cls = ts.find(symbol.declarations, ts.isClassLike) || ts.Debug.fail("Expected declaration to have at least one class-like declaration"); - return getSignatureDefinition(cls.members, true); + return getSignatureDefinition(cls.members, /*selectConstructors*/ true); } } function getCallSignatureDefinition() { return ts.isCallExpressionTarget(node) || ts.isNewExpressionTarget(node) || ts.isNameOfFunctionDeclaration(node) - ? getSignatureDefinition(symbol.declarations, false) + ? getSignatureDefinition(symbol.declarations, /*selectConstructors*/ false) : undefined; } function getSignatureDefinition(signatureDeclarations, selectConstructors) { @@ -79430,12 +95238,14 @@ var ts; : undefined; } } + /** Creates a DefinitionInfo from a Declaration, using the declaration's name if possible. */ function createDefinitionInfo(declaration, checker, symbol, node) { - var symbolName = checker.symbolToString(symbol); + var symbolName = checker.symbolToString(symbol); // Do not get scoped name, just the name of the symbol var symbolKind = ts.SymbolDisplay.getSymbolKind(checker, symbol, node); var containerName = symbol.parent ? checker.symbolToString(symbol.parent, node) : ""; return createDefinitionInfoFromName(declaration, symbolKind, symbolName, containerName); } + /** Creates a DefinitionInfo directly from the name of a declaration. */ function createDefinitionInfoFromName(declaration, symbolKind, symbolName, containerName) { var name = ts.getNameOfDeclaration(declaration) || declaration; var sourceFile = name.getSourceFile(); @@ -79459,12 +95269,13 @@ var ts; return { fileName: targetFileName, textSpan: ts.createTextSpanFromBounds(0, 0), - kind: "script", + kind: "script" /* scriptElement */, name: name, containerName: undefined, containerKind: undefined, }; } + /** Returns a CallLikeExpression where `node` is the target being invoked. */ function getAncestorCallLikeExpression(node) { var target = climbPastManyPropertyAccesses(node); var callLike = target.parent; @@ -79476,10 +95287,12 @@ var ts; function tryGetSignatureDeclaration(typeChecker, node) { var callLike = getAncestorCallLikeExpression(node); var signature = callLike && typeChecker.getResolvedSignature(callLike); + // Don't go to a function type, go to the value having that type. return ts.tryCast(signature && signature.declaration, function (d) { return ts.isFunctionLike(d) && !ts.isFunctionTypeNode(d); }); } })(GoToDefinition = ts.GoToDefinition || (ts.GoToDefinition = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var JsDoc; @@ -79531,6 +95344,12 @@ var ts; var jsDocTagNameCompletionEntries; var jsDocTagCompletionEntries; function getJsDocCommentsFromDeclarations(declarations) { + // Only collect doc comments from duplicate declarations once: + // In case of a union property there might be same declaration multiple times + // which only varies in type parameter + // Eg. const a: Array | Array; a.length + // The property length will have two declarations of property length coming + // from Array - Array and Array var documentationComment = []; forEachUnique(declarations, function (declaration) { for (var _i = 0, _a = getCommentHavingNodes(declaration); _i < _a.length; _i++) { @@ -79548,17 +95367,18 @@ var ts; JsDoc.getJsDocCommentsFromDeclarations = getJsDocCommentsFromDeclarations; function getCommentHavingNodes(declaration) { switch (declaration.kind) { - case 293: - case 299: + case 293 /* JSDocParameterTag */: + case 299 /* JSDocPropertyTag */: return [declaration]; - case 292: - case 298: + case 292 /* JSDocCallbackTag */: + case 298 /* JSDocTypedefTag */: return [declaration, declaration.parent]; default: return ts.getJSDocCommentsAndTags(declaration); } } function getJsDocTagsFromDeclarations(declarations) { + // Only collect doc comments from duplicate declarations once. var tags = []; forEachUnique(declarations, function (declaration) { for (var _i = 0, _a = ts.getJSDocTags(declaration); _i < _a.length; _i++) { @@ -79572,16 +95392,16 @@ var ts; function getCommentText(tag) { var comment = tag.comment; switch (tag.kind) { - case 290: + case 290 /* JSDocAugmentsTag */: return withNode(tag.class); - case 297: + case 297 /* JSDocTemplateTag */: return withList(tag.typeParameters); - case 296: + case 296 /* JSDocTypeTag */: return withNode(tag.typeExpression); - case 298: - case 292: - case 299: - case 293: + case 298 /* JSDocTypedefTag */: + case 292 /* JSDocCallbackTag */: + case 299 /* JSDocPropertyTag */: + case 293 /* JSDocParameterTag */: var name = tag.name; return name ? withNode(name) : comment; default: @@ -79597,6 +95417,11 @@ var ts; return comment === undefined ? s : s + " " + comment; } } + /** + * Iterates through 'array' by index and performs the callback on each element of array until the callback + * returns a truthy value, then returns that value. + * If no such value is found, the callback is applied to each element of array and undefined is returned. + */ function forEachUnique(array, callback) { if (array) { for (var i = 0; i < array.length; i++) { @@ -79614,7 +95439,7 @@ var ts; return jsDocTagNameCompletionEntries || (jsDocTagNameCompletionEntries = ts.map(jsDocTagNames, function (tagName) { return { name: tagName, - kind: "keyword", + kind: "keyword" /* keyword */, kindModifiers: "", sortText: "0", }; @@ -79626,7 +95451,7 @@ var ts; return jsDocTagCompletionEntries || (jsDocTagCompletionEntries = ts.map(jsDocTagNames, function (tagName) { return { name: "@" + tagName, - kind: "keyword", + kind: "keyword" /* keyword */, kindModifiers: "", sortText: "0" }; @@ -79636,7 +95461,7 @@ var ts; function getJSDocTagCompletionDetails(name) { return { name: name, - kind: "", + kind: "" /* unknown */, kindModifiers: "", displayParts: [ts.textPart(name)], documentation: ts.emptyArray, @@ -79658,18 +95483,18 @@ var ts; if (!ts.isIdentifier(param.name)) return undefined; var name = param.name.text; - if (jsdoc.tags.some(function (t) { return t !== tag && ts.isJSDocParameterTag(t) && ts.isIdentifier(t.name) && t.name.escapedText === name; }) + if (jsdoc.tags.some(function (t) { return t !== tag && ts.isJSDocParameterTag(t) && ts.isIdentifier(t.name) && t.name.escapedText === name; }) // TODO: GH#18217 || nameThusFar !== undefined && !ts.startsWith(name, nameThusFar)) { return undefined; } - return { name: name, kind: "parameter", kindModifiers: "", sortText: "0" }; + return { name: name, kind: "parameter" /* parameterElement */, kindModifiers: "", sortText: "0" }; }); } JsDoc.getJSDocParameterNameCompletions = getJSDocParameterNameCompletions; function getJSDocParameterNameCompletionDetails(name) { return { name: name, - kind: "parameter", + kind: "parameter" /* parameterElement */, kindModifiers: "", displayParts: [ts.textPart(name)], documentation: ts.emptyArray, @@ -79678,11 +95503,35 @@ var ts; }; } JsDoc.getJSDocParameterNameCompletionDetails = getJSDocParameterNameCompletionDetails; + /** + * Checks if position points to a valid position to add JSDoc comments, and if so, + * returns the appropriate template. Otherwise returns an empty string. + * Valid positions are + * - outside of comments, statements, and expressions, and + * - preceding a: + * - function/constructor/method declaration + * - class declarations + * - variable statements + * - namespace declarations + * - interface declarations + * - method signatures + * - type alias declarations + * + * Hosts should ideally check that: + * - The line is all whitespace up to 'position' before performing the insertion. + * - If the keystroke sequence "/\*\*" induced the call, we also check that the next + * non-whitespace character is '*', which (approximately) indicates whether we added + * the second '*' to complete an existing (JSDoc) comment. + * @param fileName The file in which to perform the check. + * @param position The (character-indexed) position in the file where the check should + * be performed. + */ function getDocCommentTemplateAtPosition(newLine, sourceFile, position) { + // Check if in a context where we don't want to perform any insertion if (ts.isInString(sourceFile, position) || ts.isInComment(sourceFile, position) || ts.hasDocComment(sourceFile, position)) { return undefined; } - var tokenAtPos = ts.getTokenAtPosition(sourceFile, position, false); + var tokenAtPos = ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); var tokenStart = tokenAtPos.getStart(sourceFile); if (!tokenAtPos || tokenStart < position) { return undefined; @@ -79696,12 +95545,21 @@ var ts; return undefined; } if (!parameters || parameters.length === 0) { + // if there are no parameters, just complete to a single line JSDoc comment var singleLineResult = "/** */"; return { newText: singleLineResult, caretOffset: 3 }; } var posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position); var lineStart = sourceFile.getLineStarts()[posLineAndChar.line]; + // replace non-whitespace characters in prefix with spaces. var indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character).replace(/\S/i, function () { return " "; }); + // A doc comment consists of the following + // * The opening comment line + // * the first line (without a param) for the object's untagged info (this is also where the caret ends up) + // * the '@param'-tagged lines + // * TODO: other tags. + // * the closing comment line + // * if the caret was directly in front of the object, then we add an extra line and indentation. var preamble = "/**" + newLine + indentationStr + " * "; var result = preamble + newLine + @@ -79714,7 +95572,7 @@ var ts; function parameterDocComments(parameters, isJavaScriptFile, indentationStr, newLine) { return parameters.map(function (_a, i) { var name = _a.name, dotDotDotToken = _a.dotDotDotToken; - var paramName = name.kind === 71 ? name.text : "param" + i; + var paramName = name.kind === 71 /* Identifier */ ? name.text : "param" + i; var type = isJavaScriptFile ? (dotDotDotToken ? "{...any} " : "{any} ") : ""; return indentationStr + " * @param " + type + paramName + newLine; }).join(""); @@ -79722,20 +95580,20 @@ var ts; function getCommentOwnerInfo(tokenAtPos) { for (var commentOwner = tokenAtPos; commentOwner; commentOwner = commentOwner.parent) { switch (commentOwner.kind) { - case 234: - case 154: - case 155: - case 153: + case 234 /* FunctionDeclaration */: + case 154 /* MethodDeclaration */: + case 155 /* Constructor */: + case 153 /* MethodSignature */: var parameters = commentOwner.parameters; return { commentOwner: commentOwner, parameters: parameters }; - case 235: - case 236: - case 151: - case 238: - case 273: - case 237: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + case 151 /* PropertySignature */: + case 238 /* EnumDeclaration */: + case 273 /* EnumMember */: + case 237 /* TypeAliasDeclaration */: return { commentOwner: commentOwner }; - case 214: { + case 214 /* VariableStatement */: { var varStatement = commentOwner; var varDeclarations = varStatement.declarationList.declarations; var parameters_1 = varDeclarations.length === 1 && varDeclarations[0].initializer @@ -79743,13 +95601,16 @@ var ts; : undefined; return { commentOwner: commentOwner, parameters: parameters_1 }; } - case 274: + case 274 /* SourceFile */: return undefined; - case 239: - return commentOwner.parent.kind === 239 ? undefined : { commentOwner: commentOwner }; - case 200: { + case 239 /* ModuleDeclaration */: + // If in walking up the tree, we hit a a nested namespace declaration, + // then we must be somewhere within a dotted namespace name; however we don't + // want to give back a JSDoc template for the 'b' or 'c' in 'namespace a.b.c { }'. + return commentOwner.parent.kind === 239 /* ModuleDeclaration */ ? undefined : { commentOwner: commentOwner }; + case 200 /* BinaryExpression */: { var be = commentOwner; - if (ts.getSpecialPropertyAssignmentKind(be) === 0) { + if (ts.getSpecialPropertyAssignmentKind(be) === 0 /* None */) { return undefined; } var parameters_2 = ts.isFunctionLike(be.right) ? be.right.parameters : ts.emptyArray; @@ -79758,15 +95619,23 @@ var ts; } } } + /** + * Digs into an an initializer or RHS operand of an assignment operation + * to get the parameters of an apt signature corresponding to a + * function expression or a class expression. + * + * @param rightHandSide the expression which may contain an appropriate set of parameters + * @returns the parameters of a signature found on the RHS if one exists; otherwise 'emptyArray'. + */ function getParametersFromRightHandSideOfAssignment(rightHandSide) { - while (rightHandSide.kind === 191) { + while (rightHandSide.kind === 191 /* ParenthesizedExpression */) { rightHandSide = rightHandSide.expression; } switch (rightHandSide.kind) { - case 192: - case 193: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: return rightHandSide.parameters; - case 205: { + case 205 /* ClassExpression */: { var ctr = ts.find(rightHandSide.members, ts.isConstructorDeclaration); return ctr ? ctr.parameters : ts.emptyArray; } @@ -79775,6 +95644,7 @@ var ts; } })(JsDoc = ts.JsDoc || (ts.JsDoc = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var NavigateTo; @@ -79786,13 +95656,14 @@ var ts; var rawItems = []; var _loop_16 = function (sourceFile) { cancellationToken.throwIfCancellationRequested(); - if (excludeDtsFiles && ts.fileExtensionIs(sourceFile.fileName, ".d.ts")) { + if (excludeDtsFiles && ts.fileExtensionIs(sourceFile.fileName, ".d.ts" /* Dts */)) { return "continue"; } sourceFile.getNamedDeclarations().forEach(function (declarations, name) { getItemsFromNamedDeclaration(patternMatcher, name, declarations, checker, sourceFile.fileName, rawItems); }); }; + // Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[] for (var _i = 0, sourceFiles_7 = sourceFiles; _i < sourceFiles_7.length; _i++) { var sourceFile = sourceFiles_7[_i]; _loop_16(sourceFile); @@ -79805,30 +95676,33 @@ var ts; } NavigateTo.getNavigateToItems = getNavigateToItems; function getItemsFromNamedDeclaration(patternMatcher, name, declarations, checker, fileName, rawItems) { + // First do a quick check to see if the name of the declaration matches the + // last portion of the (possibly) dotted name they're searching for. var match = patternMatcher.getMatchForLastSegmentOfPattern(name); if (!match) { - return; + return; // continue to next named declarations } for (var _i = 0, declarations_12 = declarations; _i < declarations_12.length; _i++) { var declaration = declarations_12[_i]; if (!shouldKeepItem(declaration, checker)) continue; if (patternMatcher.patternContainsDots) { - var fullMatch = patternMatcher.getFullMatch(getContainers(declaration), name); + var fullMatch = patternMatcher.getFullMatch(getContainers(declaration), name); // TODO: GH#18217 if (fullMatch) { rawItems.push({ name: name, fileName: fileName, matchKind: fullMatch.kind, isCaseSensitive: fullMatch.isCaseSensitive, declaration: declaration }); } } else { + // If the pattern has dots in it, then also see if the declaration container matches as well. rawItems.push({ name: name, fileName: fileName, matchKind: match.kind, isCaseSensitive: match.isCaseSensitive, declaration: declaration }); } } } function shouldKeepItem(declaration, checker) { switch (declaration.kind) { - case 245: - case 248: - case 243: + case 245 /* ImportClause */: + case 248 /* ImportSpecifier */: + case 243 /* ImportEqualsDeclaration */: var importer = checker.getSymbolAtLocation(declaration.name); var imported = checker.getAliasedSymbol(importer); return importer.escapedName !== imported.escapedName; @@ -79842,13 +95716,17 @@ var ts; containers.unshift(ts.getTextOfIdentifierOrLiteral(name)); return true; } - else if (name && name.kind === 147) { - return tryAddComputedPropertyName(name.expression, containers, true); + else if (name && name.kind === 147 /* ComputedPropertyName */) { + return tryAddComputedPropertyName(name.expression, containers, /*includeLastPortion*/ true); } else { + // Don't know how to add this. return false; } } + // Only added the names of computed properties if they're simple dotted expressions, like: + // + // [X.Y.Z]() { } function tryAddComputedPropertyName(expression, containers, includeLastPortion) { if (ts.isPropertyNameLiteral(expression)) { var text = ts.getTextOfIdentifierOrLiteral(expression); @@ -79861,16 +95739,19 @@ var ts; if (includeLastPortion) { containers.unshift(expression.name.text); } - return tryAddComputedPropertyName(expression.expression, containers, true); + return tryAddComputedPropertyName(expression.expression, containers, /*includeLastPortion*/ true); } return false; } function getContainers(declaration) { var containers = []; + // First, if we started with a computed property name, then add all but the last + // portion into the container array. var name = ts.getNameOfDeclaration(declaration); - if (name.kind === 147 && !tryAddComputedPropertyName(name.expression, containers, false)) { + if (name.kind === 147 /* ComputedPropertyName */ && !tryAddComputedPropertyName(name.expression, containers, /*includeLastPortion*/ false)) { return undefined; } + // Now, walk up our containers, adding all their names to the container array. var container = ts.getContainerNode(declaration); while (container) { if (!tryAddSingleDeclarationName(container, containers)) { @@ -79881,6 +95762,7 @@ var ts; return containers; } function compareNavigateToItems(i1, i2) { + // TODO(cyrusn): get the gamut of comparisons that VS already uses here. return ts.compareValues(i1.matchKind, i2.matchKind) || ts.compareStringsCaseSensitiveUI(i1.name, i2.name); } @@ -79896,21 +95778,43 @@ var ts; isCaseSensitive: rawItem.isCaseSensitive, fileName: rawItem.fileName, textSpan: ts.createTextSpanFromNode(declaration), + // TODO(jfreeman): What should be the containerName when the container has a computed name? containerName: containerName ? containerName.text : "", - containerKind: containerName ? ts.getNodeKind(container) : "" + containerKind: containerName ? ts.getNodeKind(container) : "" /* unknown */ // TODO: GH#18217 Just use `container ? ...` }; } })(NavigateTo = ts.NavigateTo || (ts.NavigateTo = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var NavigationBar; (function (NavigationBar) { + /** + * Matches all whitespace characters in a string. Eg: + * + * "app. + * + * onactivated" + * + * matches because of the newline, whereas + * + * "app.onactivated" + * + * does not match. + */ var whiteSpaceRegex = /\s+/g; + // Keep sourceFile handy so we don't have to search for it every time we need to call `getText`. var curCancellationToken; var curSourceFile; + /** + * For performance, we keep navigation bar parents on a stack rather than passing them through each recursion. + * `parent` is the current parent and is *not* stored in parentsStack. + * `startNode` sets a new parent and `endNode` returns to the previous parent. + */ var parentsStack = []; var parent; + // NavigationBarItem requires an array, but will not mutate it, so just give it this for performance. var emptyChildItemArray = []; function getNavigationBarItems(sourceFile, cancellationToken) { curCancellationToken = cancellationToken; @@ -79980,12 +95884,18 @@ var ts; indent: parent.indent + 1 }; } + /** + * Add a new level of NavigationBarNodes. + * This pushes to the stack, so you must call `endNode` when you are done adding to this node. + */ function startNode(node) { var navNode = emptyNavigationBarNode(node); pushChild(parent, navNode); + // Save the old parent parentsStack.push(parent); parent = navNode; } + /** Call after calling `startNode` and adding children to it. */ function endNode() { if (parent.children) { mergeChildren(parent.children); @@ -79998,15 +95908,18 @@ var ts; addChildrenRecursively(child); endNode(); } + /** Look for navigation bar items in node's subtree, adding them to the current `parent`. */ function addChildrenRecursively(node) { curCancellationToken.throwIfCancellationRequested(); if (!node || ts.isToken(node)) { return; } switch (node.kind) { - case 155: + case 155 /* Constructor */: + // Get parameter properties, and treat them as being on the *same* level as the constructor, not under it. var ctr = node; addNodeWithRecursiveChild(ctr, ctr.body); + // Parameter properties are children of the class, not the constructor. for (var _i = 0, _a = ctr.parameters; _i < _a.length; _i++) { var param = _a[_i]; if (ts.isParameterPropertyDeclaration(param)) { @@ -80014,28 +95927,33 @@ var ts; } } break; - case 154: - case 156: - case 157: - case 153: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 153 /* MethodSignature */: if (!ts.hasDynamicName(node)) { addNodeWithRecursiveChild(node, node.body); } break; - case 152: - case 151: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: if (!ts.hasDynamicName(node)) { addLeafNode(node); } break; - case 245: + case 245 /* ImportClause */: var importClause = node; + // Handle default import case e.g.: + // import d from "mod"; if (importClause.name) { addLeafNode(importClause); } + // Handle named bindings in imports e.g.: + // import * as NS from "mod"; + // import {a, b as B} from "mod"; var namedBindings = importClause.namedBindings; if (namedBindings) { - if (namedBindings.kind === 246) { + if (namedBindings.kind === 246 /* NamespaceImport */) { addLeafNode(namedBindings); } else { @@ -80046,17 +95964,19 @@ var ts; } } break; - case 182: - case 232: + case 182 /* BindingElement */: + case 232 /* VariableDeclaration */: var _d = node, name = _d.name, initializer = _d.initializer; if (ts.isBindingPattern(name)) { addChildrenRecursively(name); } else if (initializer && isFunctionOrClassExpression(initializer)) { if (initializer.name) { + // Don't add a node for the VariableDeclaration, just for the initializer. addChildrenRecursively(initializer); } else { + // Add a node for the VariableDeclaration, but not for the initializer. startNode(node); ts.forEachChild(initializer, addChildrenRecursively); endNode(); @@ -80066,12 +95986,12 @@ var ts; addNodeWithRecursiveChild(node, initializer); } break; - case 193: - case 234: - case 192: + case 193 /* ArrowFunction */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: addNodeWithRecursiveChild(node, node.body); break; - case 238: + case 238 /* EnumDeclaration */: startNode(node); for (var _e = 0, _f = node.members; _e < _f.length; _e++) { var member = _f[_e]; @@ -80081,9 +96001,9 @@ var ts; } endNode(); break; - case 235: - case 205: - case 236: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 236 /* InterfaceDeclaration */: startNode(node); for (var _g = 0, _h = node.members; _g < _h.length; _g++) { var member = _h[_g]; @@ -80091,34 +96011,35 @@ var ts; } endNode(); break; - case 239: + case 239 /* ModuleDeclaration */: addNodeWithRecursiveChild(node, getInteriorModule(node).body); break; - case 252: - case 243: - case 160: - case 158: - case 159: - case 237: + case 252 /* ExportSpecifier */: + case 243 /* ImportEqualsDeclaration */: + case 160 /* IndexSignature */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 237 /* TypeAliasDeclaration */: addLeafNode(node); break; - case 200: { + case 200 /* BinaryExpression */: { var special = ts.getSpecialPropertyAssignmentKind(node); switch (special) { - case 1: - case 2: - case 3: - case 6: + case 1 /* ExportsProperty */: + case 2 /* ModuleExports */: + case 3 /* PrototypeProperty */: + case 6 /* Prototype */: addNodeWithRecursiveChild(node, node.right); break; - case 4: - case 5: - case 0: + case 4 /* ThisProperty */: + case 5 /* Property */: + case 0 /* None */: break; default: ts.Debug.assertNever(special); } } + // falls through default: if (ts.hasJSDocNodes(node)) { ts.forEach(node.jsDoc, function (jsDoc) { @@ -80132,12 +96053,14 @@ var ts; ts.forEachChild(node, addChildrenRecursively); } } + /** Merge declarations of the same kind. */ function mergeChildren(children) { var nameToItems = ts.createMap(); ts.filterMutate(children, function (child) { var declName = ts.getNameOfDeclaration(child.node); var name = declName && nodeText(declName); if (!name) { + // Anonymous items are never merged. return true; } var itemsWithSameName = nameToItems.get(name); @@ -80172,25 +96095,30 @@ var ts; } return false; } + /** a and b have the same name, but they may not be mergeable. */ function shouldReallyMerge(a, b) { if (a.kind !== b.kind) { return false; } switch (a.kind) { - case 152: - case 154: - case 156: - case 157: - return ts.hasModifier(a, 32) === ts.hasModifier(b, 32); - case 239: + case 152 /* PropertyDeclaration */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + return ts.hasModifier(a, 32 /* Static */) === ts.hasModifier(b, 32 /* Static */); + case 239 /* ModuleDeclaration */: return areSameModule(a, b); default: return true; } } + // We use 1 NavNode to represent 'A.B.C', but there are multiple source nodes. + // Only merge module nodes that have the same chain. Don't merge 'A.B.C' with 'A'! function areSameModule(a, b) { - return a.body.kind === b.body.kind && (a.body.kind !== 239 || areSameModule(a.body, b.body)); + // TODO: GH#18217 + return a.body.kind === b.body.kind && (a.body.kind !== 239 /* ModuleDeclaration */ || areSameModule(a.body, b.body)); } + /** Merge source into target. Source should be thrown away after this is called. */ function merge(target, source) { var _a; target.additionalNodes = target.additionalNodes || []; @@ -80204,32 +96132,38 @@ var ts; sortChildren(target.children); } } + /** Recursively ensure that each NavNode's children are in sorted order. */ function sortChildren(children) { children.sort(compareChildren); } function compareChildren(child1, child2) { - return ts.compareStringsCaseSensitiveUI(tryGetName(child1.node), tryGetName(child2.node)) + return ts.compareStringsCaseSensitiveUI(tryGetName(child1.node), tryGetName(child2.node)) // TODO: GH#18217 || ts.compareValues(navigationBarNodeKind(child1), navigationBarNodeKind(child2)); } + /** + * This differs from getItemName because this is just used for sorting. + * We only sort nodes by name that have a more-or-less "direct" name, as opposed to `new()` and the like. + * So `new()` can still come before an `aardvark` method. + */ function tryGetName(node) { - if (node.kind === 239) { + if (node.kind === 239 /* ModuleDeclaration */) { return getModuleName(node); } var declName = ts.getNameOfDeclaration(node); if (declName) { - return ts.unescapeLeadingUnderscores(ts.getPropertyNameForPropertyNameNode(declName)); + return ts.unescapeLeadingUnderscores(ts.getPropertyNameForPropertyNameNode(declName)); // TODO: GH#18217 } switch (node.kind) { - case 192: - case 193: - case 205: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 205 /* ClassExpression */: return getFunctionOrClassName(node); default: return undefined; } } function getItemName(node, name) { - if (node.kind === 239) { + if (node.kind === 239 /* ModuleDeclaration */) { return getModuleName(node); } if (name) { @@ -80239,32 +96173,36 @@ var ts; } } switch (node.kind) { - case 274: + case 274 /* SourceFile */: var sourceFile = node; return ts.isExternalModule(sourceFile) ? "\"" + ts.escapeString(ts.getBaseFileName(ts.removeFileExtension(ts.normalizePath(sourceFile.fileName)))) + "\"" : ""; - case 193: - case 234: - case 192: - case 235: - case 205: - if (ts.getModifierFlags(node) & 512) { + case 193 /* ArrowFunction */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + if (ts.getModifierFlags(node) & 512 /* Default */) { return "default"; } + // We may get a string with newlines or other whitespace in the case of an object dereference + // (eg: "app\n.onactivated"), so we should remove the whitespace for readabiltiy in the + // navigation bar. return getFunctionOrClassName(node); - case 155: + case 155 /* Constructor */: return "constructor"; - case 159: + case 159 /* ConstructSignature */: return "new()"; - case 158: + case 158 /* CallSignature */: return "()"; - case 160: + case 160 /* IndexSignature */: return "[]"; default: return ""; } } + /** Flattens the NavNode tree to a list, keeping only the top-level items. */ function topLevelItems(root) { var topLevel = []; function recur(item) { @@ -80282,25 +96220,25 @@ var ts; return topLevel; function isTopLevel(item) { switch (navigationBarNodeKind(item)) { - case 235: - case 205: - case 238: - case 236: - case 239: - case 274: - case 237: - case 298: - case 292: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 238 /* EnumDeclaration */: + case 236 /* InterfaceDeclaration */: + case 239 /* ModuleDeclaration */: + case 274 /* SourceFile */: + case 237 /* TypeAliasDeclaration */: + case 298 /* JSDocTypedefTag */: + case 292 /* JSDocCallbackTag */: return true; - case 155: - case 154: - case 156: - case 157: - case 232: + case 155 /* Constructor */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 232 /* VariableDeclaration */: return hasSomeImportantChild(item); - case 193: - case 234: - case 192: + case 193 /* ArrowFunction */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: return isTopLevelFunctionDeclaration(item); default: return false; @@ -80310,10 +96248,10 @@ var ts; return false; } switch (navigationBarNodeKind(item.parent)) { - case 240: - case 274: - case 154: - case 155: + case 240 /* ModuleBlock */: + case 274 /* SourceFile */: + case 154 /* MethodDeclaration */: + case 155 /* Constructor */: return true; default: return hasSomeImportantChild(item); @@ -80322,7 +96260,7 @@ var ts; function hasSomeImportantChild(item) { return ts.some(item.children, function (child) { var childKind = navigationBarNodeKind(child); - return childKind !== 232 && childKind !== 182; + return childKind !== 232 /* VariableDeclaration */ && childKind !== 182 /* BindingElement */; }); } } @@ -80372,28 +96310,34 @@ var ts; return spans; } function getModuleName(moduleDeclaration) { + // We want to maintain quotation marks. if (ts.isAmbientModule(moduleDeclaration)) { return ts.getTextOfNode(moduleDeclaration.name); } + // Otherwise, we need to aggregate each identifier to build up the qualified name. var result = []; result.push(ts.getTextOfIdentifierOrLiteral(moduleDeclaration.name)); - while (moduleDeclaration.body && moduleDeclaration.body.kind === 239) { + while (moduleDeclaration.body && moduleDeclaration.body.kind === 239 /* ModuleDeclaration */) { moduleDeclaration = moduleDeclaration.body; result.push(ts.getTextOfIdentifierOrLiteral(moduleDeclaration.name)); } return result.join("."); } + /** + * For 'module A.B.C', we want to get the node for 'C'. + * We store 'A' as associated with a NavNode, and use getModuleName to traverse down again. + */ function getInteriorModule(decl) { - return decl.body.kind === 239 ? getInteriorModule(decl.body) : decl; + return decl.body.kind === 239 /* ModuleDeclaration */ ? getInteriorModule(decl.body) : decl; // TODO: GH#18217 } function isComputedProperty(member) { - return !member.name || member.name.kind === 147; + return !member.name || member.name.kind === 147 /* ComputedPropertyName */; } function getNodeSpan(node) { - return node.kind === 274 ? ts.createTextSpanFromRange(node) : ts.createTextSpanFromNode(node, curSourceFile); + return node.kind === 274 /* SourceFile */ ? ts.createTextSpanFromRange(node) : ts.createTextSpanFromNode(node, curSourceFile); } function getModifiers(node) { - if (node.parent && node.parent.kind === 232) { + if (node.parent && node.parent.kind === 232 /* VariableDeclaration */) { node = node.parent; } return ts.getNodeModifiers(node); @@ -80402,17 +96346,21 @@ var ts; if (node.name && ts.getFullWidth(node.name) > 0) { return ts.declarationNameToString(node.name); } - else if (node.parent.kind === 232) { + // See if it is a var initializer. If so, use the var name. + else if (node.parent.kind === 232 /* VariableDeclaration */) { return ts.declarationNameToString(node.parent.name); } - else if (node.parent.kind === 200 && - node.parent.operatorToken.kind === 58) { + // See if it is of the form " = function(){...}". If so, use the text from the left-hand side. + else if (node.parent.kind === 200 /* BinaryExpression */ && + node.parent.operatorToken.kind === 58 /* EqualsToken */) { return nodeText(node.parent.left).replace(whiteSpaceRegex, ""); } - else if (node.parent.kind === 270 && node.parent.name) { + // See if it is a property assignment, and if so use the property name + else if (node.parent.kind === 270 /* PropertyAssignment */ && node.parent.name) { return nodeText(node.parent.name); } - else if (ts.getModifierFlags(node) & 512) { + // Default exports are named "default" + else if (ts.getModifierFlags(node) & 512 /* Default */) { return "default"; } else { @@ -80421,9 +96369,9 @@ var ts; } function isFunctionOrClassExpression(node) { switch (node.kind) { - case 193: - case 192: - case 205: + case 193 /* ArrowFunction */: + case 192 /* FunctionExpression */: + case 205 /* ClassExpression */: return true; default: return false; @@ -80431,20 +96379,29 @@ var ts; } })(NavigationBar = ts.NavigationBar || (ts.NavigationBar = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var OrganizeImports; (function (OrganizeImports) { + /** + * Organize imports by: + * 1) Removing unused imports + * 2) Coalescing imports from the same module + * 3) Sorting imports + */ function organizeImports(sourceFile, formatContext, host, program, _preferences) { var changeTracker = ts.textChanges.ChangeTracker.fromContext({ host: host, formatContext: formatContext }); var coalesceAndOrganizeImports = function (importGroup) { return coalesceImports(removeUnusedImports(importGroup, sourceFile, program)); }; + // All of the old ImportDeclarations in the file, in syntactic order. var topLevelImportDecls = sourceFile.statements.filter(ts.isImportDeclaration); organizeImportsWorker(topLevelImportDecls, coalesceAndOrganizeImports); + // All of the old ExportDeclarations in the file, in syntactic order. var topLevelExportDecls = sourceFile.statements.filter(ts.isExportDeclaration); organizeImportsWorker(topLevelExportDecls, coalesceExports); for (var _i = 0, _a = sourceFile.statements.filter(ts.isAmbientModule); _i < _a.length; _i++) { var ambientModule = _a[_i]; - var ambientModuleBody = getModuleBlock(ambientModule); + var ambientModuleBody = getModuleBlock(ambientModule); // TODO: GH#18217 var ambientModuleImportDecls = ambientModuleBody.statements.filter(ts.isImportDeclaration); organizeImportsWorker(ambientModuleImportDecls, coalesceAndOrganizeImports); var ambientModuleExportDecls = ambientModuleBody.statements.filter(ts.isExportDeclaration); @@ -80455,6 +96412,11 @@ var ts; if (ts.length(oldImportDecls) === 0) { return; } + // Special case: normally, we'd expect leading and trailing trivia to follow each import + // around as it's sorted. However, we do not want this to happen for leading trivia + // on the first import because it is probably the header comment for the file. + // Consider: we could do a more careful check that this trivia is actually a header, + // but the consequences of being wrong are very minor. ts.suppressLeadingTrivia(oldImportDecls[0]); var oldImportGroups = ts.group(oldImportDecls, function (importDecl) { return getExternalModuleName(importDecl.moduleSpecifier); }); var sortedImportGroups = ts.stableSort(oldImportGroups, function (group1, group2) { return compareModuleSpecifiers(group1[0].moduleSpecifier, group2[0].moduleSpecifier); }); @@ -80463,6 +96425,7 @@ var ts; ? coalesce(importGroup) : importGroup; }); + // Delete or replace the first import. if (newImportDecls.length === 0) { changeTracker.deleteNode(sourceFile, oldImportDecls[0], { useNonAdjustedStartPosition: true, @@ -80470,12 +96433,14 @@ var ts; }); } else { + // Note: Delete the surrounding trivia because it will have been retained in newImportDecls. changeTracker.replaceNodeWithNodes(sourceFile, oldImportDecls[0], newImportDecls, { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: false, suffix: ts.getNewLineOrDefaultFromHost(host, formatContext.options), }); } + // Delete any subsequent imports. for (var i = 1; i < oldImportDecls.length; i++) { changeTracker.deleteNode(sourceFile, oldImportDecls[i]); } @@ -80489,26 +96454,30 @@ var ts; function removeUnusedImports(oldImports, sourceFile, program) { var typeChecker = program.getTypeChecker(); var jsxNamespace = typeChecker.getJsxNamespace(); - var jsxElementsPresent = !!(sourceFile.transformFlags & 4); + var jsxElementsPresent = !!(sourceFile.transformFlags & 4 /* ContainsJsx */); var usedImports = []; for (var _i = 0, oldImports_1 = oldImports; _i < oldImports_1.length; _i++) { var importDecl = oldImports_1[_i]; var importClause = importDecl.importClause; if (!importClause) { + // Imports without import clauses are assumed to be included for their side effects and are not removed. usedImports.push(importDecl); continue; } var name = importClause.name, namedBindings = importClause.namedBindings; + // Default import if (name && !isDeclarationUsed(name)) { name = undefined; } if (namedBindings) { if (ts.isNamespaceImport(namedBindings)) { + // Namespace import if (!isDeclarationUsed(namedBindings.name)) { namedBindings = undefined; } } else { + // List of named imports var newElements = namedBindings.elements.filter(function (e) { return isDeclarationUsed(e.name); }); if (newElements.length < namedBindings.elements.length) { namedBindings = newElements.length @@ -80523,6 +96492,7 @@ var ts; } return usedImports; function isDeclarationUsed(identifier) { + // The JSX factory symbol is always used if JSX elements are present - even if they are not allowed. return jsxElementsPresent && (identifier.text === jsxNamespace) || ts.FindAllReferences.Core.isSymbolReferencedInFile(identifier, typeChecker, sourceFile); } } @@ -80531,6 +96501,10 @@ var ts; ? specifier.text : undefined; } + /* @internal */ // Internal for testing + /** + * @param importGroup a list of ImportDeclarations, all with the same module name. + */ function coalesceImports(importGroup) { if (importGroup.length === 0) { return importGroup; @@ -80540,17 +96514,21 @@ var ts; if (importWithoutClause) { coalescedImports.push(importWithoutClause); } + // Normally, we don't combine default and namespace imports, but it would be silly to + // produce two import declarations in this special case. if (defaultImports.length === 1 && namespaceImports.length === 1 && namedImports.length === 0) { + // Add the namespace import to the existing default ImportDeclaration. var defaultImport = defaultImports[0]; - coalescedImports.push(updateImportDeclarationAndClause(defaultImport, defaultImport.importClause.name, namespaceImports[0].importClause.namedBindings)); + coalescedImports.push(updateImportDeclarationAndClause(defaultImport, defaultImport.importClause.name, namespaceImports[0].importClause.namedBindings)); // TODO: GH#18217 return coalescedImports; } var sortedNamespaceImports = ts.stableSort(namespaceImports, function (i1, i2) { return compareIdentifiers(i1.importClause.namedBindings.name, i2.importClause.namedBindings.name); - }); + }); // TODO: GH#18217 for (var _i = 0, sortedNamespaceImports_1 = sortedNamespaceImports; _i < sortedNamespaceImports_1.length; _i++) { var namespaceImport = sortedNamespaceImports_1[_i]; - coalescedImports.push(updateImportDeclarationAndClause(namespaceImport, undefined, namespaceImport.importClause.namedBindings)); + // Drop the name, if any + coalescedImports.push(updateImportDeclarationAndClause(namespaceImport, /*name*/ undefined, namespaceImport.importClause.namedBindings)); // TODO: GH#18217 } if (defaultImports.length === 0 && namedImports.length === 0) { return coalescedImports; @@ -80563,10 +96541,10 @@ var ts; else { for (var _b = 0, defaultImports_1 = defaultImports; _b < defaultImports_1.length; _b++) { var defaultImport = defaultImports_1[_b]; - newImportSpecifiers.push(ts.createImportSpecifier(ts.createIdentifier("default"), defaultImport.importClause.name)); + newImportSpecifiers.push(ts.createImportSpecifier(ts.createIdentifier("default"), defaultImport.importClause.name)); // TODO: GH#18217 } } - newImportSpecifiers.push.apply(newImportSpecifiers, ts.flatMap(namedImports, function (i) { return i.importClause.namedBindings.elements; })); + newImportSpecifiers.push.apply(newImportSpecifiers, ts.flatMap(namedImports, function (i) { return i.importClause.namedBindings.elements; })); // TODO: GH#18217 var sortedImportSpecifiers = sortSpecifiers(newImportSpecifiers); var importDecl = defaultImports.length > 0 ? defaultImports[0] @@ -80577,9 +96555,16 @@ var ts; : ts.createNamedImports(ts.emptyArray) : namedImports.length === 0 ? ts.createNamedImports(sortedImportSpecifiers) - : ts.updateNamedImports(namedImports[0].importClause.namedBindings, sortedImportSpecifiers); + : ts.updateNamedImports(namedImports[0].importClause.namedBindings, sortedImportSpecifiers); // TODO: GH#18217 coalescedImports.push(updateImportDeclarationAndClause(importDecl, newDefaultImport, newNamedImports)); return coalescedImports; + /* + * Returns entire import declarations because they may already have been rewritten and + * may lack parent pointers. The desired parts can easily be recovered based on the + * categorization. + * + * NB: There may be overlap between `defaultImports` and `namespaceImports`/`namedImports`. + */ function getCategorizedImports(importGroup) { var importWithoutClause; var defaultImports = []; @@ -80588,6 +96573,8 @@ var ts; for (var _i = 0, importGroup_1 = importGroup; _i < importGroup_1.length; _i++) { var importDeclaration = importGroup_1[_i]; if (importDeclaration.importClause === undefined) { + // Only the first such import is interesting - the others are redundant. + // Note: Unfortunately, we will lose trivia that was on this node. importWithoutClause = importWithoutClause || importDeclaration; continue; } @@ -80613,6 +96600,10 @@ var ts; } } OrganizeImports.coalesceImports = coalesceImports; + /* @internal */ // Internal for testing + /** + * @param exportGroup a list of ExportDeclarations, all with the same module name. + */ function coalesceExports(exportGroup) { if (exportGroup.length === 0) { return exportGroup; @@ -80631,12 +96622,19 @@ var ts; var exportDecl = namedExports[0]; coalescedExports.push(ts.updateExportDeclaration(exportDecl, exportDecl.decorators, exportDecl.modifiers, ts.updateNamedExports(exportDecl.exportClause, sortedExportSpecifiers), exportDecl.moduleSpecifier)); return coalescedExports; + /* + * Returns entire export declarations because they may already have been rewritten and + * may lack parent pointers. The desired parts can easily be recovered based on the + * categorization. + */ function getCategorizedExports(exportGroup) { var exportWithoutClause; var namedExports = []; for (var _i = 0, exportGroup_1 = exportGroup; _i < exportGroup_1.length; _i++) { var exportDeclaration = exportGroup_1[_i]; if (exportDeclaration.exportClause === undefined) { + // Only the first such export is interesting - the others are redundant. + // Note: Unfortunately, we will lose trivia that was on this node. exportWithoutClause = exportWithoutClause || exportDeclaration; } else { @@ -80651,7 +96649,8 @@ var ts; } OrganizeImports.coalesceExports = coalesceExports; function updateImportDeclarationAndClause(importDeclaration, name, namedBindings) { - return ts.updateImportDeclaration(importDeclaration, importDeclaration.decorators, importDeclaration.modifiers, ts.updateImportClause(importDeclaration.importClause, name, namedBindings), importDeclaration.moduleSpecifier); + return ts.updateImportDeclaration(importDeclaration, importDeclaration.decorators, importDeclaration.modifiers, ts.updateImportClause(importDeclaration.importClause, name, namedBindings), // TODO: GH#18217 + importDeclaration.moduleSpecifier); } function sortSpecifiers(specifiers) { return ts.stableSort(specifiers, function (s1, s2) { @@ -80659,6 +96658,7 @@ var ts; compareIdentifiers(s1.name, s2.name); }); } + /* internal */ // Exported for testing function compareModuleSpecifiers(m1, m2) { var name1 = getExternalModuleName(m1); var name2 = getExternalModuleName(m2); @@ -80672,6 +96672,7 @@ var ts; } })(OrganizeImports = ts.OrganizeImports || (ts.OrganizeImports = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var OutliningElementsCollector; @@ -80702,7 +96703,7 @@ var ts; } var lastImport = current - 1; if (lastImport !== firstImport) { - out.push(createOutliningSpanFromBounds(ts.findChildOfKind(statements[firstImport], 91, sourceFile).getStart(sourceFile), statements[lastImport].getEnd(), "imports")); + out.push(createOutliningSpanFromBounds(ts.findChildOfKind(statements[firstImport], 91 /* ImportKeyword */, sourceFile).getStart(sourceFile), statements[lastImport].getEnd(), "imports" /* Imports */)); } } function visitNonImportNode(n) { @@ -80717,6 +96718,7 @@ var ts; out.push(span); depthRemaining--; if (ts.isIfStatement(n) && n.elseStatement && ts.isIfStatement(n.elseStatement)) { + // Consider an 'else if' to be on the same depth as the 'if'. visitNonImportNode(n.expression); visitNonImportNode(n.thenStatement); depthRemaining++; @@ -80742,7 +96744,7 @@ var ts; } if (!result[1]) { var span = ts.createTextSpanFromBounds(sourceFile.text.indexOf("//", currentLineStart), lineEnd); - regions.push(createOutliningSpan(span, "region", span, false, result[2] || "#region")); + regions.push(createOutliningSpan(span, "region" /* Region */, span, /*autoCollapse*/ false, result[2] || "#region")); } else { var region = regions.pop(); @@ -80765,16 +96767,18 @@ var ts; var _a = comments_3[_i], kind = _a.kind, pos = _a.pos, end = _a.end; cancellationToken.throwIfCancellationRequested(); switch (kind) { - case 2: + case 2 /* SingleLineCommentTrivia */: + // For single line comments, combine consecutive ones (2 or more) into + // a single span from the start of the first till the end of the last if (singleLineCommentCount === 0) { firstSingleLineCommentStart = pos; } lastSingleLineCommentEnd = end; singleLineCommentCount++; break; - case 3: + case 3 /* MultiLineCommentTrivia */: combineAndAddMultipleSingleLineComments(); - out.push(createOutliningSpanFromBounds(pos, end, "comment")); + out.push(createOutliningSpanFromBounds(pos, end, "comment" /* Comment */)); singleLineCommentCount = 0; break; default: @@ -80783,8 +96787,9 @@ var ts; } combineAndAddMultipleSingleLineComments(); function combineAndAddMultipleSingleLineComments() { + // Only outline spans of two or more consecutive single line comments if (singleLineCommentCount > 1) { - out.push(createOutliningSpanFromBounds(firstSingleLineCommentStart, lastSingleLineCommentEnd, "comment")); + out.push(createOutliningSpanFromBounds(firstSingleLineCommentStart, lastSingleLineCommentEnd, "comment" /* Comment */)); } } } @@ -80793,59 +96798,69 @@ var ts; } function getOutliningSpanForNode(n, sourceFile) { switch (n.kind) { - case 213: + case 213 /* Block */: if (ts.isFunctionBlock(n)) { - return spanForNode(n.parent, n.parent.kind !== 193); + return spanForNode(n.parent, /*autoCollapse*/ n.parent.kind !== 193 /* ArrowFunction */); } + // Check if the block is standalone, or 'attached' to some parent statement. + // If the latter, we want to collapse the block, but consider its hint span + // to be the entire span of the parent. switch (n.parent.kind) { - case 218: - case 221: - case 222: - case 220: - case 217: - case 219: - case 226: - case 269: + case 218 /* DoStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 220 /* ForStatement */: + case 217 /* IfStatement */: + case 219 /* WhileStatement */: + case 226 /* WithStatement */: + case 269 /* CatchClause */: return spanForNode(n.parent); - case 230: + case 230 /* TryStatement */: + // Could be the try-block, or the finally-block. var tryStatement = n.parent; if (tryStatement.tryBlock === n) { return spanForNode(n.parent); } else if (tryStatement.finallyBlock === n) { - return spanForNode(ts.findChildOfKind(tryStatement, 87, sourceFile)); + return spanForNode(ts.findChildOfKind(tryStatement, 87 /* FinallyKeyword */, sourceFile)); } + // falls through default: - return createOutliningSpan(ts.createTextSpanFromNode(n, sourceFile), "code"); + // Block was a standalone block. In this case we want to only collapse + // the span of the block, independent of any parent span. + return createOutliningSpan(ts.createTextSpanFromNode(n, sourceFile), "code" /* Code */); } - case 240: + case 240 /* ModuleBlock */: return spanForNode(n.parent); - case 235: - case 236: - case 238: - case 241: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + case 238 /* EnumDeclaration */: + case 241 /* CaseBlock */: return spanForNode(n); - case 184: + case 184 /* ObjectLiteralExpression */: return spanForObjectOrArrayLiteral(n); - case 183: - return spanForObjectOrArrayLiteral(n, 21); + case 183 /* ArrayLiteralExpression */: + return spanForObjectOrArrayLiteral(n, 21 /* OpenBracketToken */); } function spanForObjectOrArrayLiteral(node, open) { - if (open === void 0) { open = 17; } - return spanForNode(node, false, !ts.isArrayLiteralExpression(node.parent), open); + if (open === void 0) { open = 17 /* OpenBraceToken */; } + // If the block has no leading keywords and is inside an array literal, + // we only want to collapse the span of the block. + // Otherwise, the collapsed section will include the end of the previous line. + return spanForNode(node, /*autoCollapse*/ false, /*useFullStart*/ !ts.isArrayLiteralExpression(node.parent), open); } function spanForNode(hintSpanNode, autoCollapse, useFullStart, open) { if (autoCollapse === void 0) { autoCollapse = false; } if (useFullStart === void 0) { useFullStart = true; } - if (open === void 0) { open = 17; } + if (open === void 0) { open = 17 /* OpenBraceToken */; } var openToken = ts.findChildOfKind(n, open, sourceFile); - var close = open === 17 ? 18 : 22; + var close = open === 17 /* OpenBraceToken */ ? 18 /* CloseBraceToken */ : 22 /* CloseBracketToken */; var closeToken = ts.findChildOfKind(n, close, sourceFile); if (!openToken || !closeToken) { return undefined; } var textSpan = ts.createTextSpanFromBounds(useFullStart ? openToken.getFullStart() : openToken.getStart(sourceFile), closeToken.getEnd()); - return createOutliningSpan(textSpan, "code", ts.createTextSpanFromNode(hintSpanNode, sourceFile), autoCollapse); + return createOutliningSpan(textSpan, "code" /* Code */, ts.createTextSpanFromNode(hintSpanNode, sourceFile), autoCollapse); } } function createOutliningSpan(textSpan, kind, hintSpan, autoCollapse, bannerText) { @@ -80856,8 +96871,10 @@ var ts; } })(OutliningElementsCollector = ts.OutliningElementsCollector || (ts.OutliningElementsCollector = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { + // Note(cyrusn): this enum is ordered from strongest match type to weakest match type. var PatternMatchKind; (function (PatternMatchKind) { PatternMatchKind[PatternMatchKind["exact"] = 0] = "exact"; @@ -80872,8 +96889,13 @@ var ts; }; } function createPatternMatcher(pattern) { + // We'll often see the same candidate string many times when searching (For example, when + // we see the name of a module that is used everywhere, or the name of an overload). As + // such, we cache the information we compute about the candidate for the life of this + // pattern matcher so we don't have to compute it multiple times. var stringToWordSpans = ts.createMap(); var dotSeparatedSegments = pattern.trim().split(".").map(function (p) { return createSegment(p.trim()); }); + // A segment is considered invalid if we couldn't find any words in it. if (dotSeparatedSegments.some(function (segment) { return !segment.subWordTextChunks.length; })) return undefined; return { @@ -80884,12 +96906,19 @@ var ts; } ts.createPatternMatcher = createPatternMatcher; function getFullMatch(candidateContainers, candidate, dotSeparatedSegments, stringToWordSpans) { + // First, check that the last part of the dot separated pattern matches the name of the + // candidate. If not, then there's no point in proceeding and doing the more + // expensive work. var candidateMatch = matchSegment(candidate, ts.last(dotSeparatedSegments), stringToWordSpans); if (!candidateMatch) { return undefined; } candidateContainers = candidateContainers || []; + // -1 because the last part was checked against the name, and only the rest + // of the parts are checked against the container. if (dotSeparatedSegments.length - 1 > candidateContainers.length) { + // There weren't enough container parts to match against the pattern parts. + // So this definitely doesn't match. return undefined; } var bestMatch; @@ -80908,30 +96937,49 @@ var ts; function matchTextChunk(candidate, chunk, stringToWordSpans) { var index = indexOfIgnoringCase(candidate, chunk.textLowerCase); if (index === 0) { - return createPatternMatch(chunk.text.length === candidate.length ? PatternMatchKind.exact : PatternMatchKind.prefix, ts.startsWith(candidate, chunk.text)); + // a) Check if the word is a prefix of the candidate, in a case insensitive or + // sensitive manner. If it does, return that there was an exact match if the word and candidate are the same length, else a prefix match. + return createPatternMatch(chunk.text.length === candidate.length ? PatternMatchKind.exact : PatternMatchKind.prefix, /*isCaseSensitive:*/ ts.startsWith(candidate, chunk.text)); } if (chunk.isLowerCase) { if (index === -1) return undefined; + // b) If the part is entirely lowercase, then check if it is contained anywhere in the + // candidate in a case insensitive manner. If so, return that there was a substring + // match. + // + // Note: We only have a substring match if the lowercase part is prefix match of some + // word part. That way we don't match something like 'Class' when the user types 'a'. + // But we would match 'FooAttribute' (since 'Attribute' starts with 'a'). var wordSpans = getWordSpans(candidate, stringToWordSpans); for (var _i = 0, wordSpans_1 = wordSpans; _i < wordSpans_1.length; _i++) { var span = wordSpans_1[_i]; - if (partStartsWith(candidate, span, chunk.text, true)) { - return createPatternMatch(PatternMatchKind.substring, partStartsWith(candidate, span, chunk.text, false)); + if (partStartsWith(candidate, span, chunk.text, /*ignoreCase:*/ true)) { + return createPatternMatch(PatternMatchKind.substring, /*isCaseSensitive:*/ partStartsWith(candidate, span, chunk.text, /*ignoreCase:*/ false)); } } + // c) Is the pattern a substring of the candidate starting on one of the candidate's word boundaries? + // We could check every character boundary start of the candidate for the pattern. However, that's + // an m * n operation in the wost case. Instead, find the first instance of the pattern + // substring, and see if it starts on a capital letter. It seems unlikely that the user will try to + // filter the list based on a substring that starts on a capital letter and also with a lowercase one. + // (Pattern: fogbar, Candidate: quuxfogbarFogBar). if (chunk.text.length < candidate.length && isUpperCaseLetter(candidate.charCodeAt(index))) { - return createPatternMatch(PatternMatchKind.substring, false); + return createPatternMatch(PatternMatchKind.substring, /*isCaseSensitive:*/ false); } } else { + // d) If the part was not entirely lowercase, then check if it is contained in the + // candidate in a case *sensitive* manner. If so, return that there was a substring + // match. if (candidate.indexOf(chunk.text) > 0) { - return createPatternMatch(PatternMatchKind.substring, true); + return createPatternMatch(PatternMatchKind.substring, /*isCaseSensitive:*/ true); } + // e) If the part was not entirely lowercase, then attempt a camel cased match as well. if (chunk.characterSpans.length > 0) { var candidateParts = getWordSpans(candidate, stringToWordSpans); - var isCaseSensitive = tryCamelCaseMatch(candidate, candidateParts, chunk, false) ? true - : tryCamelCaseMatch(candidate, candidateParts, chunk, true) ? false : undefined; + var isCaseSensitive = tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ false) ? true + : tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ true) ? false : undefined; if (isCaseSensitive !== undefined) { return createPatternMatch(PatternMatchKind.camelCase, isCaseSensitive); } @@ -80939,11 +96987,53 @@ var ts; } } function matchSegment(candidate, segment, stringToWordSpans) { - if (every(segment.totalTextChunk.text, function (ch) { return ch !== 32 && ch !== 42; })) { + // First check if the segment matches as is. This is also useful if the segment contains + // characters we would normally strip when splitting into parts that we also may want to + // match in the candidate. For example if the segment is "@int" and the candidate is + // "@int", then that will show up as an exact match here. + // + // Note: if the segment contains a space or an asterisk then we must assume that it's a + // multi-word segment. + if (every(segment.totalTextChunk.text, function (ch) { return ch !== 32 /* space */ && ch !== 42 /* asterisk */; })) { var match = matchTextChunk(candidate, segment.totalTextChunk, stringToWordSpans); if (match) return match; } + // The logic for pattern matching is now as follows: + // + // 1) Break the segment passed in into words. Breaking is rather simple and a + // good way to think about it that if gives you all the individual alphanumeric words + // of the pattern. + // + // 2) For each word try to match the word against the candidate value. + // + // 3) Matching is as follows: + // + // a) Check if the word is a prefix of the candidate, in a case insensitive or + // sensitive manner. If it does, return that there was an exact match if the word and candidate are the same length, else a prefix match. + // + // If the word is entirely lowercase: + // b) Then check if it is contained anywhere in the + // candidate in a case insensitive manner. If so, return that there was a substring + // match. + // + // Note: We only have a substring match if the lowercase part is prefix match of + // some word part. That way we don't match something like 'Class' when the user + // types 'a'. But we would match 'FooAttribute' (since 'Attribute' starts with + // 'a'). + // + // c) The word is all lower case. Is it a case insensitive substring of the candidate starting + // on a part boundary of the candidate? + // + // Else: + // d) If the word was not entirely lowercase, then check if it is contained in the + // candidate in a case *sensitive* manner. If so, return that there was a substring + // match. + // + // e) If the word was not entirely lowercase, then attempt a camel cased match as + // well. + // + // Only if all words have some sort of match is the pattern considered matched. var subWordTextChunks = segment.subWordTextChunks; var bestMatch; for (var _i = 0, subWordTextChunks_1 = subWordTextChunks; _i < subWordTextChunks_1.length; _i++) { @@ -80956,12 +97046,12 @@ var ts; return ts.min(a, b, compareMatches); } function compareMatches(a, b) { - return a === undefined ? 1 : b === undefined ? -1 + return a === undefined ? 1 /* GreaterThan */ : b === undefined ? -1 /* LessThan */ : ts.compareValues(a.kind, b.kind) || ts.compareBooleans(!a.isCaseSensitive, !b.isCaseSensitive); } function partStartsWith(candidate, candidateSpan, pattern, ignoreCase, patternSpan) { if (patternSpan === void 0) { patternSpan = { start: 0, length: pattern.length }; } - return patternSpan.length <= candidateSpan.length + return patternSpan.length <= candidateSpan.length // If pattern part is longer than the candidate part there can never be a match. && everyInRange(0, patternSpan.length, function (i) { return equalChars(pattern.charCodeAt(patternSpan.start + i), candidate.charCodeAt(candidateSpan.start + i), ignoreCase); }); } function equalChars(ch1, ch2, ignoreCase) { @@ -80969,22 +97059,35 @@ var ts; } function tryCamelCaseMatch(candidate, candidateParts, chunk, ignoreCase) { var chunkCharacterSpans = chunk.characterSpans; + // Note: we may have more pattern parts than candidate parts. This is because multiple + // pattern parts may match a candidate part. For example "SiUI" against "SimpleUI". + // We'll have 3 pattern parts Si/U/I against two candidate parts Simple/UI. However, U + // and I will both match in UI. var currentCandidate = 0; var currentChunkSpan = 0; var firstMatch; var contiguous; while (true) { + // Let's consider our termination cases if (currentChunkSpan === chunkCharacterSpans.length) { return true; } else if (currentCandidate === candidateParts.length) { + // No match, since we still have more of the pattern to hit return false; } var candidatePart = candidateParts[currentCandidate]; var gotOneMatchThisCandidate = false; + // Consider the case of matching SiUI against SimpleUIElement. The candidate parts + // will be Simple/UI/Element, and the pattern parts will be Si/U/I. We'll match 'Si' + // against 'Simple' first. Then we'll match 'U' against 'UI'. However, we want to + // still keep matching pattern parts against that candidate part. for (; currentChunkSpan < chunkCharacterSpans.length; currentChunkSpan++) { var chunkCharacterSpan = chunkCharacterSpans[currentChunkSpan]; if (gotOneMatchThisCandidate) { + // We've already gotten one pattern part match in this candidate. We will + // only continue trying to consumer pattern parts if the last part and this + // part are both upper case. if (!isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan - 1].start)) || !isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan].start))) { break; @@ -80995,12 +97098,20 @@ var ts; } gotOneMatchThisCandidate = true; firstMatch = firstMatch === undefined ? currentCandidate : firstMatch; + // If we were contiguous, then keep that value. If we weren't, then keep that + // value. If we don't know, then set the value to 'true' as an initial match is + // obviously contiguous. contiguous = contiguous === undefined ? true : contiguous; candidatePart = ts.createTextSpan(candidatePart.start + chunkCharacterSpan.length, candidatePart.length - chunkCharacterSpan.length); } + // Check if we matched anything at all. If we didn't, then we need to unset the + // contiguous bit if we currently had it set. + // If we haven't set the bit yet, then that means we haven't matched anything so + // far, and we don't want to change that. if (!gotOneMatchThisCandidate && contiguous !== undefined) { contiguous = false; } + // Move onto the next candidate. currentCandidate++; } } @@ -81011,25 +97122,32 @@ var ts; }; } function isUpperCaseLetter(ch) { - if (ch >= 65 && ch <= 90) { + // Fast check for the ascii range. + if (ch >= 65 /* A */ && ch <= 90 /* Z */) { return true; } - if (ch < 127 || !ts.isUnicodeIdentifierStart(ch, 6)) { + if (ch < 127 /* maxAsciiCharacter */ || !ts.isUnicodeIdentifierStart(ch, 6 /* Latest */)) { return false; } + // TODO: find a way to determine this for any unicode characters in a + // non-allocating manner. var str = String.fromCharCode(ch); return str === str.toUpperCase(); } function isLowerCaseLetter(ch) { - if (ch >= 97 && ch <= 122) { + // Fast check for the ascii range. + if (ch >= 97 /* a */ && ch <= 122 /* z */) { return true; } - if (ch < 127 || !ts.isUnicodeIdentifierStart(ch, 6)) { + if (ch < 127 /* maxAsciiCharacter */ || !ts.isUnicodeIdentifierStart(ch, 6 /* Latest */)) { return false; } + // TODO: find a way to determine this for any unicode characters in a + // non-allocating manner. var str = String.fromCharCode(ch); return str === str.toLowerCase(); } + // Assumes 'value' is already lowercase. function indexOfIgnoringCase(str, value) { var n = str.length - value.length; var _loop_17 = function (start) { @@ -81045,19 +97163,23 @@ var ts; return -1; } function toLowerCase(ch) { - if (ch >= 65 && ch <= 90) { - return 97 + (ch - 65); + // Fast convert for the ascii range. + if (ch >= 65 /* A */ && ch <= 90 /* Z */) { + return 97 /* a */ + (ch - 65 /* A */); } - if (ch < 127) { + if (ch < 127 /* maxAsciiCharacter */) { return ch; } + // TODO: find a way to compute this for any unicode characters in a + // non-allocating manner. return String.fromCharCode(ch).toLowerCase().charCodeAt(0); } function isDigit(ch) { - return ch >= 48 && ch <= 57; + // TODO(cyrusn): Find a way to support this for unicode digits. + return ch >= 48 /* _0 */ && ch <= 57 /* _9 */; } function isWordChar(ch) { - return isUpperCaseLetter(ch) || isLowerCaseLetter(ch) || isDigit(ch) || ch === 95 || ch === 36; + return isUpperCaseLetter(ch) || isLowerCaseLetter(ch) || isDigit(ch) || ch === 95 /* _ */ || ch === 36 /* $ */; } function breakPatternIntoTextChunks(pattern) { var result = []; @@ -81092,12 +97214,12 @@ var ts; characterSpans: breakIntoCharacterSpans(text) }; } - function breakIntoCharacterSpans(identifier) { - return breakIntoSpans(identifier, false); + /* @internal */ function breakIntoCharacterSpans(identifier) { + return breakIntoSpans(identifier, /*word:*/ false); } ts.breakIntoCharacterSpans = breakIntoCharacterSpans; - function breakIntoWordSpans(identifier) { - return breakIntoSpans(identifier, true); + /* @internal */ function breakIntoWordSpans(identifier) { + return breakIntoSpans(identifier, /*word:*/ true); } ts.breakIntoWordSpans = breakIntoWordSpans; function breakIntoSpans(identifier, word) { @@ -81126,37 +97248,51 @@ var ts; } function charIsPunctuation(ch) { switch (ch) { - case 33: - case 34: - case 35: - case 37: - case 38: - case 39: - case 40: - case 41: - case 42: - case 44: - case 45: - case 46: - case 47: - case 58: - case 59: - case 63: - case 64: - case 91: - case 92: - case 93: - case 95: - case 123: - case 125: + case 33 /* exclamation */: + case 34 /* doubleQuote */: + case 35 /* hash */: + case 37 /* percent */: + case 38 /* ampersand */: + case 39 /* singleQuote */: + case 40 /* openParen */: + case 41 /* closeParen */: + case 42 /* asterisk */: + case 44 /* comma */: + case 45 /* minus */: + case 46 /* dot */: + case 47 /* slash */: + case 58 /* colon */: + case 59 /* semicolon */: + case 63 /* question */: + case 64 /* at */: + case 91 /* openBracket */: + case 92 /* backslash */: + case 93 /* closeBracket */: + case 95 /* _ */: + case 123 /* openBrace */: + case 125 /* closeBrace */: return true; } return false; } function isAllPunctuation(identifier, start, end) { - return every(identifier, function (ch) { return charIsPunctuation(ch) && ch !== 95; }, start, end); + return every(identifier, function (ch) { return charIsPunctuation(ch) && ch !== 95 /* _ */; }, start, end); } function transitionFromUpperToLower(identifier, index, wordStart) { + // Cases this supports: + // 1) IDisposable -> I, Disposable + // 2) UIElement -> UI, Element + // 3) HTMLDocument -> HTML, Document + // + // etc. + // We have a transition from an upper to a lower letter here. But we only + // want to break if all the letters that preceded are uppercase. i.e. if we + // have "Foo" we don't want to break that into "F, oo". But if we have + // "IFoo" or "UIFoo", then we want to break that into "I, Foo" and "UI, + // Foo". i.e. the last uppercase letter belongs to the lowercase letters + // that follows. Note: this will make the following not split properly: + // "HELLOthere". However, these sorts of names do not show up in .Net + // programs. return index !== wordStart && index + 1 < identifier.length && isUpperCaseLetter(identifier.charCodeAt(index)) @@ -81166,6 +97302,19 @@ var ts; function transitionFromLowerToUpper(identifier, word, index) { var lastIsUpper = isUpperCaseLetter(identifier.charCodeAt(index - 1)); var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index)); + // See if the casing indicates we're starting a new word. Note: if we're breaking on + // words, then just seeing an upper case character isn't enough. Instead, it has to + // be uppercase and the previous character can't be uppercase. + // + // For example, breaking "AddMetadata" on words would make: Add Metadata + // + // on characters would be: A dd M etadata + // + // Break "AM" on words would be: AM + // + // on characters would be: A M + // + // We break the search string on characters. But we break the symbol name on words. return currentIsUpper && (!word || !lastIsUpper); } function everyInRange(start, end, pred) { @@ -81188,7 +97337,7 @@ var ts; if (readImportFiles === void 0) { readImportFiles = true; } if (detectJavaScriptImports === void 0) { detectJavaScriptImports = false; } var pragmaContext = { - languageVersion: 1, + languageVersion: 1 /* ES5 */, pragmas: undefined, checkJsDirective: undefined, referencedFiles: [], @@ -81203,14 +97352,16 @@ var ts; var lastToken; var currentToken; var braceNesting = 0; + // assume that text represent an external module if it contains at least one top level import/export + // ambient modules that are found inside external modules are interpreted as module augmentations var externalModule = false; function nextToken() { lastToken = currentToken; currentToken = ts.scanner.scan(); - if (currentToken === 17) { + if (currentToken === 17 /* OpenBraceToken */) { braceNesting++; } - else if (currentToken === 18) { + else if (currentToken === 18 /* CloseBraceToken */) { braceNesting--; } return currentToken; @@ -81235,13 +97386,17 @@ var ts; externalModule = true; } } + /** + * Returns true if at least one token was consumed from the stream + */ function tryConsumeDeclare() { var token = ts.scanner.getToken(); - if (token === 124) { + if (token === 124 /* DeclareKeyword */) { + // declare module "mod" token = nextToken(); - if (token === 129) { + if (token === 129 /* ModuleKeyword */) { token = nextToken(); - if (token === 9) { + if (token === 9 /* StringLiteral */) { recordAmbientExternalModule(); } } @@ -81249,70 +97404,84 @@ var ts; } return false; } + /** + * Returns true if at least one token was consumed from the stream + */ function tryConsumeImport() { - if (lastToken === 23) { + if (lastToken === 23 /* DotToken */) { return false; } var token = ts.scanner.getToken(); - if (token === 91) { + if (token === 91 /* ImportKeyword */) { token = nextToken(); - if (token === 19) { + if (token === 19 /* OpenParenToken */) { token = nextToken(); - if (token === 9) { + if (token === 9 /* StringLiteral */) { + // import("mod"); recordModuleName(); return true; } } - else if (token === 9) { + else if (token === 9 /* StringLiteral */) { + // import "mod"; recordModuleName(); return true; } else { - if (token === 71 || ts.isKeyword(token)) { + if (token === 71 /* Identifier */ || ts.isKeyword(token)) { token = nextToken(); - if (token === 143) { + if (token === 143 /* FromKeyword */) { token = nextToken(); - if (token === 9) { + if (token === 9 /* StringLiteral */) { + // import d from "mod"; recordModuleName(); return true; } } - else if (token === 58) { - if (tryConsumeRequireCall(true)) { + else if (token === 58 /* EqualsToken */) { + if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) { return true; } } - else if (token === 26) { + else if (token === 26 /* CommaToken */) { + // consume comma and keep going token = nextToken(); } else { + // unknown syntax return true; } } - if (token === 17) { + if (token === 17 /* OpenBraceToken */) { token = nextToken(); - while (token !== 18 && token !== 1) { + // consume "{ a as B, c, d as D}" clauses + // make sure that it stops on EOF + while (token !== 18 /* CloseBraceToken */ && token !== 1 /* EndOfFileToken */) { token = nextToken(); } - if (token === 18) { + if (token === 18 /* CloseBraceToken */) { token = nextToken(); - if (token === 143) { + if (token === 143 /* FromKeyword */) { token = nextToken(); - if (token === 9) { + if (token === 9 /* StringLiteral */) { + // import {a as A} from "mod"; + // import d, {a, b as B} from "mod" recordModuleName(); } } } } - else if (token === 39) { + else if (token === 39 /* AsteriskToken */) { token = nextToken(); - if (token === 118) { + if (token === 118 /* AsKeyword */) { token = nextToken(); - if (token === 71 || ts.isKeyword(token)) { + if (token === 71 /* Identifier */ || ts.isKeyword(token)) { token = nextToken(); - if (token === 143) { + if (token === 143 /* FromKeyword */) { token = nextToken(); - if (token === 9) { + if (token === 9 /* StringLiteral */) { + // import * as NS from "mod" + // import d, * as NS from "mod" recordModuleName(); } } @@ -81326,39 +97495,44 @@ var ts; } function tryConsumeExport() { var token = ts.scanner.getToken(); - if (token === 84) { + if (token === 84 /* ExportKeyword */) { markAsExternalModuleIfTopLevel(); token = nextToken(); - if (token === 17) { + if (token === 17 /* OpenBraceToken */) { token = nextToken(); - while (token !== 18 && token !== 1) { + // consume "{ a as B, c, d as D}" clauses + // make sure it stops on EOF + while (token !== 18 /* CloseBraceToken */ && token !== 1 /* EndOfFileToken */) { token = nextToken(); } - if (token === 18) { + if (token === 18 /* CloseBraceToken */) { token = nextToken(); - if (token === 143) { + if (token === 143 /* FromKeyword */) { token = nextToken(); - if (token === 9) { + if (token === 9 /* StringLiteral */) { + // export {a as A} from "mod"; + // export {a, b as B} from "mod" recordModuleName(); } } } } - else if (token === 39) { + else if (token === 39 /* AsteriskToken */) { token = nextToken(); - if (token === 143) { + if (token === 143 /* FromKeyword */) { token = nextToken(); - if (token === 9) { + if (token === 9 /* StringLiteral */) { + // export * from "mod" recordModuleName(); } } } - else if (token === 91) { + else if (token === 91 /* ImportKeyword */) { token = nextToken(); - if (token === 71 || ts.isKeyword(token)) { + if (token === 71 /* Identifier */ || ts.isKeyword(token)) { token = nextToken(); - if (token === 58) { - if (tryConsumeRequireCall(true)) { + if (token === 58 /* EqualsToken */) { + if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) { return true; } } @@ -81370,11 +97544,12 @@ var ts; } function tryConsumeRequireCall(skipCurrentToken) { var token = skipCurrentToken ? nextToken() : ts.scanner.getToken(); - if (token === 133) { + if (token === 133 /* RequireKeyword */) { token = nextToken(); - if (token === 19) { + if (token === 19 /* OpenParenToken */) { token = nextToken(); - if (token === 9) { + if (token === 9 /* StringLiteral */) { + // require("mod"); recordModuleName(); } } @@ -81384,27 +97559,33 @@ var ts; } function tryConsumeDefine() { var token = ts.scanner.getToken(); - if (token === 71 && ts.scanner.getTokenValue() === "define") { + if (token === 71 /* Identifier */ && ts.scanner.getTokenValue() === "define") { token = nextToken(); - if (token !== 19) { + if (token !== 19 /* OpenParenToken */) { return true; } token = nextToken(); - if (token === 9) { + if (token === 9 /* StringLiteral */) { + // looks like define ("modname", ... - skip string literal and comma token = nextToken(); - if (token === 26) { + if (token === 26 /* CommaToken */) { token = nextToken(); } else { + // unexpected token return true; } } - if (token !== 21) { + // should be start of dependency list + if (token !== 21 /* OpenBracketToken */) { return true; } + // skip open bracket token = nextToken(); - while (token !== 22 && token !== 1) { - if (token === 9) { + // scan until ']' or EOF + while (token !== 22 /* CloseBracketToken */ && token !== 1 /* EndOfFileToken */) { + // record string literals as module names + if (token === 9 /* StringLiteral */) { recordModuleName(); } token = nextToken(); @@ -81416,14 +97597,30 @@ var ts; function processImports() { ts.scanner.setText(sourceText); nextToken(); + // Look for: + // import "mod"; + // import d from "mod" + // import {a as A } from "mod"; + // import * as NS from "mod" + // import d, {a, b as B} from "mod" + // import i = require("mod"); + // import("mod"); + // export * from "mod" + // export {a as b} from "mod" + // export import i = require("mod") + // (for JavaScript files) require("mod") + // Do not look for: + // AnySymbol.import("mod") + // AnySymbol.nested.import("mod") while (true) { - if (ts.scanner.getToken() === 1) { + if (ts.scanner.getToken() === 1 /* EndOfFileToken */) { break; } + // check if at least one of alternative have moved scanner forward if (tryConsumeDeclare() || tryConsumeImport() || tryConsumeExport() || - (detectJavaScriptImports && (tryConsumeRequireCall(false) || tryConsumeDefine()))) { + (detectJavaScriptImports && (tryConsumeRequireCall(/*skipCurrentToken*/ false) || tryConsumeDefine()))) { continue; } else { @@ -81438,7 +97635,9 @@ var ts; ts.processCommentPragmas(pragmaContext, sourceText); ts.processPragmasIntoFields(pragmaContext, ts.noop); if (externalModule) { + // for external modules module all nested ambient modules are augmentations if (ambientExternalModules) { + // move all detected ambient modules to imported files since they need to be resolved for (var _i = 0, ambientExternalModules_1 = ambientExternalModules; _i < ambientExternalModules_1.length; _i++) { var decl = ambientExternalModules_1[_i]; importedFiles.push(decl.ref); @@ -81447,6 +97646,7 @@ var ts; return { referencedFiles: pragmaContext.referencedFiles, typeReferenceDirectives: pragmaContext.typeReferenceDirectives, libReferenceDirectives: pragmaContext.libReferenceDirectives, importedFiles: importedFiles, isLibFile: !!pragmaContext.hasNoDefaultLib, ambientExternalModules: undefined }; } else { + // for global scripts ambient modules still can have augmentations - look for ambient modules with depth > 0 var ambientModuleNames = void 0; if (ambientExternalModules) { for (var _a = 0, ambientExternalModules_2 = ambientExternalModules; _a < ambientExternalModules_2.length; _a++) { @@ -81467,6 +97667,7 @@ var ts; } ts.preProcessFile = preProcessFile; })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var Rename; @@ -81492,19 +97693,23 @@ var ts; var symbol = typeChecker.getSymbolAtLocation(node); if (!symbol) return; + // Only allow a symbol to be renamed if it actually has at least one declaration. var declarations = symbol.declarations; if (!declarations || declarations.length === 0) return; + // Disallow rename for elements that are defined in the standard TypeScript library. if (declarations.some(isDefinedInLibraryFile)) { return getRenameInfoError(ts.Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library); } - if (ts.isIdentifier(node) && node.originalKeywordKind === 79 && symbol.parent.flags & 1536) { + // Cannot rename `default` as in `import { default as foo } from "./someModule"; + if (ts.isIdentifier(node) && node.originalKeywordKind === 79 /* DefaultKeyword */ && symbol.parent.flags & 1536 /* Module */) { return undefined; } + // Can't rename a module name. if (ts.isStringLiteralLike(node) && ts.tryGetImportFromModuleSpecifier(node)) return undefined; var kind = ts.SymbolDisplay.getSymbolKind(typeChecker, symbol, node); - var specifierName = (ts.isImportOrExportSpecifierName(node) || ts.isStringOrNumericLiteral(node) && node.parent.kind === 147) + var specifierName = (ts.isImportOrExportSpecifierName(node) || ts.isStringOrNumericLiteral(node) && node.parent.kind === 147 /* ComputedPropertyName */) ? ts.stripQuotes(ts.getTextOfIdentifierOrLiteral(node)) : undefined; var displayName = specifierName || typeChecker.symbolToString(symbol); @@ -81523,6 +97728,7 @@ var ts; }; } function getRenameInfoError(diagnostic) { + // TODO: GH#18217 return { canRename: false, localizedErrorMessage: ts.getLocaleSpecificMessage(diagnostic), @@ -81536,7 +97742,8 @@ var ts; function createTriggerSpanForNode(node, sourceFile) { var start = node.getStart(sourceFile); var width = node.getWidth(sourceFile); - if (node.kind === 9) { + if (node.kind === 9 /* StringLiteral */) { + // Exclude the quotes start += 1; width -= 2; } @@ -81544,11 +97751,11 @@ var ts; } function nodeIsEligibleForRename(node) { switch (node.kind) { - case 71: - case 9: - case 99: + case 71 /* Identifier */: + case 9 /* StringLiteral */: + case 99 /* ThisKeyword */: return true; - case 8: + case 8 /* NumericLiteral */: return ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node); default: return false; @@ -81556,6 +97763,7 @@ var ts; } })(Rename = ts.Rename || (ts.Rename = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var SignatureHelp; @@ -81574,17 +97782,22 @@ var ts; })(InvocationKind || (InvocationKind = {})); function getSignatureHelpItems(program, sourceFile, position, cancellationToken) { var typeChecker = program.getTypeChecker(); + // Decide whether to show signature help var startingToken = ts.findTokenOnLeftOfPosition(sourceFile, position); if (!startingToken) { + // We are at the beginning of the file return undefined; } var argumentInfo = getContainingArgumentInfo(startingToken, position, sourceFile); if (!argumentInfo) return undefined; cancellationToken.throwIfCancellationRequested(); + // Semantic filtering of signature help var candidateInfo = getCandidateInfo(argumentInfo, typeChecker); cancellationToken.throwIfCancellationRequested(); if (!candidateInfo) { + // We didn't have any sig help items produced by the TS compiler. If this is a JS + // file, then see if we can figure out anything better. if (ts.isSourceFileJavaScript(sourceFile)) { return createJavaScriptSignatureHelpItems(argumentInfo, program, cancellationToken); } @@ -81595,19 +97808,20 @@ var ts; SignatureHelp.getSignatureHelpItems = getSignatureHelpItems; function getCandidateInfo(argumentInfo, checker) { var invocation = argumentInfo.invocation; - if (invocation.kind === 0) { + if (invocation.kind === 0 /* Call */) { var candidates = []; - var resolvedSignature = checker.getResolvedSignature(invocation.node, candidates, argumentInfo.argumentCount); + var resolvedSignature = checker.getResolvedSignature(invocation.node, candidates, argumentInfo.argumentCount); // TODO: GH#18217 return candidates.length === 0 ? undefined : { candidates: candidates, resolvedSignature: resolvedSignature }; } else { - var type = checker.getTypeAtLocation(invocation.called); + var type = checker.getTypeAtLocation(invocation.called); // TODO: GH#18217 var signatures = ts.isNewExpression(invocation.called.parent) ? type.getConstructSignatures() : type.getCallSignatures(); var candidates = signatures.filter(function (candidate) { return !!candidate.typeParameters && candidate.typeParameters.length >= argumentInfo.argumentCount; }); return candidates.length === 0 ? undefined : { candidates: candidates, resolvedSignature: ts.first(candidates) }; } } function createJavaScriptSignatureHelpItems(argumentInfo, program, cancellationToken) { + // See if we can find some symbol with the call expression name that has call signatures. var expression = getExpressionFromInvocation(argumentInfo.invocation); var name = ts.isIdentifier(expression) ? expression : ts.isPropertyAccessExpression(expression) ? expression.name : undefined; if (!name || !name.escapedText) { @@ -81647,50 +97861,79 @@ var ts; } function getArgumentInfoForCompletions(node, position, sourceFile) { var info = getImmediatelyContainingArgumentInfo(node, position, sourceFile); - return !info || info.kind === 0 || info.invocation.kind === 1 ? undefined + return !info || info.kind === 0 /* TypeArguments */ || info.invocation.kind === 1 /* TypeArgs */ ? undefined : { invocation: info.invocation.node, argumentCount: info.argumentCount, argumentIndex: info.argumentIndex }; } SignatureHelp.getArgumentInfoForCompletions = getArgumentInfoForCompletions; + /** + * Returns relevant information for the argument list and the current argument if we are + * in the argument of an invocation; returns undefined otherwise. + */ function getImmediatelyContainingArgumentInfo(node, position, sourceFile) { var parent = node.parent; if (ts.isCallOrNewExpression(parent)) { var invocation = parent; var list = void 0; var argumentIndex = void 0; - if (node.kind === 27 || node.kind === 19) { + // There are 3 cases to handle: + // 1. The token introduces a list, and should begin a signature help session + // 2. The token is either not associated with a list, or ends a list, so the session should end + // 3. The token is buried inside a list, and should give signature help + // + // The following are examples of each: + // + // Case 1: + // foo<#T, U>(#a, b) -> The token introduces a list, and should begin a signature help session + // Case 2: + // fo#o#(a, b)# -> The token is either not associated with a list, or ends a list, so the session should end + // Case 3: + // foo(a#, #b#) -> The token is buried inside a list, and should give signature help + // Find out if 'node' is an argument, a type argument, or neither + if (node.kind === 27 /* LessThanToken */ || node.kind === 19 /* OpenParenToken */) { + // Find the list that starts right *after* the < or ( token. + // If the user has just opened a list, consider this item 0. list = getChildListThatStartsWithOpenerToken(parent, node, sourceFile); ts.Debug.assert(list !== undefined); argumentIndex = 0; } else { + // findListItemInfo can return undefined if we are not in parent's argument list + // or type argument list. This includes cases where the cursor is: + // - To the right of the closing parenthesis, non-substitution template, or template tail. + // - Between the type arguments and the arguments (greater than token) + // - On the target of the call (parent.func) + // - On the 'new' keyword in a 'new' expression list = ts.findContainingList(node); if (!list) return undefined; argumentIndex = getArgumentIndex(list, node); } - var kind = parent.typeArguments && parent.typeArguments.pos === list.pos ? 0 : 1; + var kind = parent.typeArguments && parent.typeArguments.pos === list.pos ? 0 /* TypeArguments */ : 1 /* CallArguments */; var argumentCount = getArgumentCount(list); if (argumentIndex !== 0) { ts.Debug.assertLessThan(argumentIndex, argumentCount); } var argumentsSpan = getApplicableSpanForArguments(list, sourceFile); - return { kind: kind, invocation: { kind: 0, node: invocation }, argumentsSpan: argumentsSpan, argumentIndex: argumentIndex, argumentCount: argumentCount }; + return { kind: kind, invocation: { kind: 0 /* Call */, node: invocation }, argumentsSpan: argumentsSpan, argumentIndex: argumentIndex, argumentCount: argumentCount }; } else if (ts.isNoSubstitutionTemplateLiteral(node) && ts.isTaggedTemplateExpression(parent)) { + // Check if we're actually inside the template; + // otherwise we'll fall out and return undefined. if (ts.isInsideTemplateLiteral(node, position, sourceFile)) { - return getArgumentListInfoForTemplate(parent, 0, sourceFile); + return getArgumentListInfoForTemplate(parent, /*argumentIndex*/ 0, sourceFile); } } - else if (ts.isTemplateHead(node) && parent.parent.kind === 189) { + else if (ts.isTemplateHead(node) && parent.parent.kind === 189 /* TaggedTemplateExpression */) { var templateExpression = parent; var tagExpression = templateExpression.parent; - ts.Debug.assert(templateExpression.kind === 202); + ts.Debug.assert(templateExpression.kind === 202 /* TemplateExpression */); var argumentIndex = ts.isInsideTemplateLiteral(node, position, sourceFile) ? 0 : 1; return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile); } else if (ts.isTemplateSpan(parent) && ts.isTaggedTemplateExpression(parent.parent.parent)) { var templateSpan = parent; var tagExpression = parent.parent.parent; + // If we're just after a template tail, don't show signature help. if (ts.isTemplateTail(node) && !ts.isInsideTemplateLiteral(node, position, sourceFile)) { return undefined; } @@ -81699,11 +97942,16 @@ var ts; return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile); } else if (ts.isJsxOpeningLikeElement(parent)) { + // Provide a signature help for JSX opening element or JSX self-closing element. + // This is not guarantee that JSX tag-name is resolved into stateless function component. (that is done in "getSignatureHelpItems") + // i.e + // export function MainButton(props: ButtonProps, context: any): JSX.Element { ... } + // ' 'b'. So, in this case the arg count will be 2. However, there + // is a small subtlety. If you have "Foo(a,)", then the child list will just have + // 'a' ''. So, in the case where the last child is a comma, we increase the + // arg count by one to compensate. + // + // Note: this subtlety only applies to the last comma. If you had "Foo(a,," then + // we'll have: 'a' '' '' + // That will give us 2 non-commas. We then add one for the last comma, giving us an + // arg count of 3. var listChildren = argumentsList.getChildren(); - var argumentCount = ts.countWhere(listChildren, function (arg) { return arg.kind !== 26; }); - if (listChildren.length > 0 && ts.last(listChildren).kind === 26) { + var argumentCount = ts.countWhere(listChildren, function (arg) { return arg.kind !== 26 /* CommaToken */; }); + if (listChildren.length > 0 && ts.last(listChildren).kind === 26 /* CommaToken */) { argumentCount++; } return argumentCount; } + // spanIndex is either the index for a given template span. + // This does not give appropriate results for a NoSubstitutionTemplateLiteral function getArgumentIndexForTemplatePiece(spanIndex, node, position, sourceFile) { + // Because the TemplateStringsArray is the first argument, we have to offset each substitution expression by 1. + // There are three cases we can encounter: + // 1. We are precisely in the template literal (argIndex = 0). + // 2. We are in or to the right of the substitution expression (argIndex = spanIndex + 1). + // 3. We are directly to the right of the template literal, but because we look for the token on the left, + // not enough to put us in the substitution expression; we should consider ourselves part of + // the *next* span's expression by offsetting the index (argIndex = (spanIndex + 1) + 1). + // + // tslint:disable no-double-space + // Example: f `# abcd $#{# 1 + 1# }# efghi ${ #"#hello"# } # ` + // ^ ^ ^ ^ ^ ^ ^ ^ ^ + // Case: 1 1 3 2 1 3 2 2 1 + // tslint:enable no-double-space ts.Debug.assert(position >= node.getStart(), "Assumed 'position' could not occur before node."); if (ts.isTemplateLiteralToken(node)) { if (ts.isInsideTemplateLiteral(node, position, sourceFile)) { @@ -81752,37 +98037,56 @@ var ts; return spanIndex + 1; } function getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile) { + // argumentCount is either 1 or (numSpans + 1) to account for the template strings array argument. var argumentCount = ts.isNoSubstitutionTemplateLiteral(tagExpression.template) ? 1 : tagExpression.template.templateSpans.length + 1; if (argumentIndex !== 0) { ts.Debug.assertLessThan(argumentIndex, argumentCount); } return { - kind: 2, - invocation: { kind: 0, node: tagExpression }, + kind: 2 /* TaggedTemplateArguments */, + invocation: { kind: 0 /* Call */, node: tagExpression }, argumentsSpan: getApplicableSpanForTaggedTemplate(tagExpression, sourceFile), argumentIndex: argumentIndex, argumentCount: argumentCount }; } function getApplicableSpanForArguments(argumentsList, sourceFile) { + // We use full start and skip trivia on the end because we want to include trivia on + // both sides. For example, + // + // foo( /*comment */ a, b, c /*comment*/ ) + // | | + // + // The applicable span is from the first bar to the second bar (inclusive, + // but not including parentheses) var applicableSpanStart = argumentsList.getFullStart(); - var applicableSpanEnd = ts.skipTrivia(sourceFile.text, argumentsList.getEnd(), false); + var applicableSpanEnd = ts.skipTrivia(sourceFile.text, argumentsList.getEnd(), /*stopAfterLineBreak*/ false); return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); } function getApplicableSpanForTaggedTemplate(taggedTemplate, sourceFile) { var template = taggedTemplate.template; var applicableSpanStart = template.getStart(); var applicableSpanEnd = template.getEnd(); - if (template.kind === 202) { + // We need to adjust the end position for the case where the template does not have a tail. + // Otherwise, we will not show signature help past the expression. + // For example, + // + // ` ${ 1 + 1 foo(10) + // | | + // This is because a Missing node has no width. However, what we actually want is to include trivia + // leading up to the next token in case the user is about to type in a TemplateMiddle or TemplateTail. + if (template.kind === 202 /* TemplateExpression */) { var lastSpan = ts.last(template.templateSpans); if (lastSpan.literal.getFullWidth() === 0) { - applicableSpanEnd = ts.skipTrivia(sourceFile.text, applicableSpanEnd, false); + applicableSpanEnd = ts.skipTrivia(sourceFile.text, applicableSpanEnd, /*stopAfterLineBreak*/ false); } } return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); } function getContainingArgumentInfo(node, position, sourceFile) { var _loop_20 = function (n) { + // If the node is not a subspan of its parent, this is a big problem. + // There have been crashes that might be caused by this violation. ts.Debug.assert(ts.rangeContainsRange(n.parent, n), "Not a subspan", function () { return "Child: " + ts.Debug.showSyntaxKind(n) + ", parent: " + ts.Debug.showSyntaxKind(n.parent); }); var argumentInfo = getImmediatelyContainingArgumentInfo(n, position, sourceFile); if (argumentInfo) { @@ -81803,15 +98107,15 @@ var ts; return children[indexOfOpenerToken + 1]; } function getExpressionFromInvocation(invocation) { - return invocation.kind === 0 ? ts.getInvokedExpression(invocation.node) : invocation.called; + return invocation.kind === 0 /* Call */ ? ts.getInvokedExpression(invocation.node) : invocation.called; } - var signatureHelpNodeBuilderFlags = 8192 | 3112960 | 16384; + var signatureHelpNodeBuilderFlags = 8192 /* OmitParameterModifiers */ | 3112960 /* IgnoreErrors */ | 16384 /* UseAliasDefinedOutsideCurrentScope */; function createSignatureHelpItems(candidates, resolvedSignature, argumentListInfo, sourceFile, typeChecker) { var argumentCount = argumentListInfo.argumentCount, applicableSpan = argumentListInfo.argumentsSpan, invocation = argumentListInfo.invocation, argumentIndex = argumentListInfo.argumentIndex; - var isTypeParameterList = argumentListInfo.kind === 0; - var enclosingDeclaration = invocation.kind === 0 ? invocation.node : invocation.called; + var isTypeParameterList = argumentListInfo.kind === 0 /* TypeArguments */; + var enclosingDeclaration = invocation.kind === 0 /* Call */ ? invocation.node : invocation.called; var callTargetSymbol = typeChecker.getSymbolAtLocation(getExpressionFromInvocation(invocation)); - var callTargetDisplayParts = callTargetSymbol && ts.symbolToDisplayParts(typeChecker, callTargetSymbol, undefined, undefined); + var callTargetDisplayParts = callTargetSymbol && ts.symbolToDisplayParts(typeChecker, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined); var printer = ts.createPrinter({ removeComments: true }); var items = candidates.map(function (candidateSignature) { var signatureHelpParameters; @@ -81822,15 +98126,15 @@ var ts; } var isVariadic; if (isTypeParameterList) { - isVariadic = false; - prefixDisplayParts.push(ts.punctuationPart(27)); + isVariadic = false; // type parameter lists are not variadic + prefixDisplayParts.push(ts.punctuationPart(27 /* LessThanToken */)); var typeParameters = (candidateSignature.target || candidateSignature).typeParameters; signatureHelpParameters = typeParameters && typeParameters.length > 0 ? ts.map(typeParameters, createSignatureHelpParameterForTypeParameter) : ts.emptyArray; - suffixDisplayParts.push(ts.punctuationPart(29)); + suffixDisplayParts.push(ts.punctuationPart(29 /* GreaterThanToken */)); var parameterParts = ts.mapToDisplayParts(function (writer) { var thisParameter = candidateSignature.thisParameter ? [typeChecker.symbolToParameterDeclaration(candidateSignature.thisParameter, enclosingDeclaration, signatureHelpNodeBuilderFlags)] : []; var params = ts.createNodeArray(thisParameter.concat(candidateSignature.parameters.map(function (param) { return typeChecker.symbolToParameterDeclaration(param, enclosingDeclaration, signatureHelpNodeBuilderFlags); }))); - printer.writeList(1296, params, sourceFile, writer); + printer.writeList(1296 /* CallExpressionArguments */, params, sourceFile, writer); }); ts.addRange(suffixDisplayParts, parameterParts); } @@ -81839,23 +98143,23 @@ var ts; var typeParameterParts = ts.mapToDisplayParts(function (writer) { if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) { var args = ts.createNodeArray(candidateSignature.typeParameters.map(function (p) { return typeChecker.typeParameterToDeclaration(p, enclosingDeclaration); })); - printer.writeList(26896, args, sourceFile, writer); + printer.writeList(26896 /* TypeParameters */, args, sourceFile, writer); } }); ts.addRange(prefixDisplayParts, typeParameterParts); - prefixDisplayParts.push(ts.punctuationPart(19)); + prefixDisplayParts.push(ts.punctuationPart(19 /* OpenParenToken */)); signatureHelpParameters = ts.map(candidateSignature.parameters, createSignatureHelpParameterForParameter); - suffixDisplayParts.push(ts.punctuationPart(20)); + suffixDisplayParts.push(ts.punctuationPart(20 /* CloseParenToken */)); } var returnTypeParts = ts.mapToDisplayParts(function (writer) { writer.writePunctuation(":"); writer.writeSpace(" "); var predicate = typeChecker.getTypePredicateOfSignature(candidateSignature); if (predicate) { - typeChecker.writeTypePredicate(predicate, enclosingDeclaration, undefined, writer); + typeChecker.writeTypePredicate(predicate, enclosingDeclaration, /*flags*/ undefined, writer); } else { - typeChecker.writeType(typeChecker.getReturnTypeOfSignature(candidateSignature), enclosingDeclaration, undefined, writer); + typeChecker.writeType(typeChecker.getReturnTypeOfSignature(candidateSignature), enclosingDeclaration, /*flags*/ undefined, writer); } }); ts.addRange(suffixDisplayParts, returnTypeParts); @@ -81863,7 +98167,7 @@ var ts; isVariadic: isVariadic, prefixDisplayParts: prefixDisplayParts, suffixDisplayParts: suffixDisplayParts, - separatorDisplayParts: [ts.punctuationPart(26), ts.spacePart()], + separatorDisplayParts: [ts.punctuationPart(26 /* CommaToken */), ts.spacePart()], parameters: signatureHelpParameters, documentation: candidateSignature.getDocumentationComment(typeChecker), tags: candidateSignature.getJsDocTags() @@ -81873,12 +98177,12 @@ var ts; ts.Debug.assertLessThan(argumentIndex, argumentCount); } var selectedItemIndex = candidates.indexOf(resolvedSignature); - ts.Debug.assert(selectedItemIndex !== -1); + ts.Debug.assert(selectedItemIndex !== -1); // If candidates is non-empty it should always include bestSignature. We check for an empty candidates before calling this function. return { items: items, applicableSpan: applicableSpan, selectedItemIndex: selectedItemIndex, argumentIndex: argumentIndex, argumentCount: argumentCount }; function createSignatureHelpParameterForParameter(parameter) { var displayParts = ts.mapToDisplayParts(function (writer) { var param = typeChecker.symbolToParameterDeclaration(parameter, enclosingDeclaration, signatureHelpNodeBuilderFlags); - printer.writeNode(4, param, sourceFile, writer); + printer.writeNode(4 /* Unspecified */, param, sourceFile, writer); }); return { name: parameter.name, @@ -81890,7 +98194,7 @@ var ts; function createSignatureHelpParameterForTypeParameter(typeParameter) { var displayParts = ts.mapToDisplayParts(function (writer) { var param = typeChecker.typeParameterToDeclaration(typeParameter, enclosingDeclaration); - printer.writeNode(4, param, sourceFile, writer); + printer.writeNode(4 /* Unspecified */, param, sourceFile, writer); }); return { name: typeParameter.symbol.name, @@ -81902,6 +98206,7 @@ var ts; } })(SignatureHelp = ts.SignatureHelp || (ts.SignatureHelp = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { function computeSuggestionDiagnostics(sourceFile, program, cancellationToken) { @@ -81934,7 +98239,7 @@ var ts; function check(node) { if (isJsFile) { switch (node.kind) { - case 192: + case 192 /* FunctionExpression */: var decl = ts.getDeclarationOfJSInitializer(node); if (decl) { var symbol_3 = decl.symbol; @@ -81943,7 +98248,8 @@ var ts; break; } } - case 234: + // falls through if no diagnostic was created + case 234 /* FunctionDeclaration */: var symbol = node.symbol; if (symbol.members && (symbol.members.size > 0)) { diags.push(ts.createDiagnosticForNode(ts.isVariableDeclaration(node.parent) ? node.parent.name : node, ts.Diagnostics.This_constructor_function_may_be_converted_to_a_class_declaration)); @@ -81954,10 +98260,10 @@ var ts; else { if (ts.isVariableStatement(node) && node.parent === sourceFile && - node.declarationList.flags & 2 && + node.declarationList.flags & 2 /* Const */ && node.declarationList.declarations.length === 1) { var init = node.declarationList.declarations[0].initializer; - if (init && ts.isRequireCall(init, true)) { + if (init && ts.isRequireCall(init, /*checkArgumentIsStringLiteralLike*/ true)) { diags.push(ts.createDiagnosticForNode(init, ts.Diagnostics.require_call_may_be_converted_to_an_import)); } } @@ -81969,19 +98275,20 @@ var ts; } } ts.computeSuggestionDiagnostics = computeSuggestionDiagnostics; + // convertToEs6Module only works on top-level, so don't trigger it if commonjs code only appears in nested scopes. function containsTopLevelCommonjs(sourceFile) { return sourceFile.statements.some(function (statement) { switch (statement.kind) { - case 214: + case 214 /* VariableStatement */: return statement.declarationList.declarations.some(function (decl) { - return ts.isRequireCall(propertyAccessLeftHandSide(decl.initializer), true); - }); - case 216: { + return ts.isRequireCall(propertyAccessLeftHandSide(decl.initializer), /*checkArgumentIsStringLiteralLike*/ true); + }); // TODO: GH#18217 + case 216 /* ExpressionStatement */: { var expression = statement.expression; if (!ts.isBinaryExpression(expression)) - return ts.isRequireCall(expression, true); + return ts.isRequireCall(expression, /*checkArgumentIsStringLiteralLike*/ true); var kind = ts.getSpecialPropertyAssignmentKind(expression); - return kind === 1 || kind === 2; + return kind === 1 /* ExportsProperty */ || kind === 2 /* ModuleExports */; } default: return false; @@ -81993,12 +98300,12 @@ var ts; } function importNameForConvertToDefaultImport(node) { switch (node.kind) { - case 244: + case 244 /* ImportDeclaration */: var importClause = node.importClause, moduleSpecifier = node.moduleSpecifier; - return importClause && !importClause.name && importClause.namedBindings && importClause.namedBindings.kind === 246 && ts.isStringLiteral(moduleSpecifier) + return importClause && !importClause.name && importClause.namedBindings && importClause.namedBindings.kind === 246 /* NamespaceImport */ && ts.isStringLiteral(moduleSpecifier) ? importClause.namedBindings.name : undefined; - case 243: + case 243 /* ImportEqualsDeclaration */: return node.name; default: return undefined; @@ -82008,119 +98315,130 @@ var ts; return ts.isBinaryExpression(commonJsModuleIndicator) ? commonJsModuleIndicator.left : commonJsModuleIndicator; } })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var SymbolDisplay; (function (SymbolDisplay) { + // TODO(drosen): use contextual SemanticMeaning. function getSymbolKind(typeChecker, symbol, location) { var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location); - if (result !== "") { + if (result !== "" /* unknown */) { return result; } var flags = ts.getCombinedLocalAndExportSymbolFlags(symbol); - if (flags & 32) { - return ts.getDeclarationOfKind(symbol, 205) ? - "local class" : "class"; + if (flags & 32 /* Class */) { + return ts.getDeclarationOfKind(symbol, 205 /* ClassExpression */) ? + "local class" /* localClassElement */ : "class" /* classElement */; } - if (flags & 384) - return "enum"; - if (flags & 524288) - return "type"; - if (flags & 64) - return "interface"; - if (flags & 262144) - return "type parameter"; - if (flags & 262144) - return "type parameter"; - if (flags & 8) - return "enum member"; - if (flags & 2097152) - return "alias"; - if (flags & 1536) - return "module"; + if (flags & 384 /* Enum */) + return "enum" /* enumElement */; + if (flags & 524288 /* TypeAlias */) + return "type" /* typeElement */; + if (flags & 64 /* Interface */) + return "interface" /* interfaceElement */; + if (flags & 262144 /* TypeParameter */) + return "type parameter" /* typeParameterElement */; + if (flags & 262144 /* TypeParameter */) + return "type parameter" /* typeParameterElement */; + if (flags & 8 /* EnumMember */) + return "enum member" /* enumMemberElement */; + if (flags & 2097152 /* Alias */) + return "alias" /* alias */; + if (flags & 1536 /* Module */) + return "module" /* moduleElement */; return result; } SymbolDisplay.getSymbolKind = getSymbolKind; function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location) { var roots = typeChecker.getRootSymbols(symbol); + // If this is a method from a mapped type, leave as a method so long as it still has a call signature. if (roots.length === 1 - && ts.first(roots).flags & 8192 + && ts.first(roots).flags & 8192 /* Method */ + // Ensure the mapped version is still a method, as opposed to `{ [K in keyof I]: number }`. && typeChecker.getTypeOfSymbolAtLocation(symbol, location).getNonNullableType().getCallSignatures().length !== 0) { - return "method"; + return "method" /* memberFunctionElement */; } if (typeChecker.isUndefinedSymbol(symbol)) { - return "var"; + return "var" /* variableElement */; } if (typeChecker.isArgumentsSymbol(symbol)) { - return "local var"; + return "local var" /* localVariableElement */; } - if (location.kind === 99 && ts.isExpression(location)) { - return "parameter"; + if (location.kind === 99 /* ThisKeyword */ && ts.isExpression(location)) { + return "parameter" /* parameterElement */; } var flags = ts.getCombinedLocalAndExportSymbolFlags(symbol); - if (flags & 3) { + if (flags & 3 /* Variable */) { if (ts.isFirstDeclarationOfSymbolParameter(symbol)) { - return "parameter"; + return "parameter" /* parameterElement */; } else if (symbol.valueDeclaration && ts.isConst(symbol.valueDeclaration)) { - return "const"; + return "const" /* constElement */; } else if (ts.forEach(symbol.declarations, ts.isLet)) { - return "let"; + return "let" /* letElement */; } - return isLocalVariableOrFunction(symbol) ? "local var" : "var"; + return isLocalVariableOrFunction(symbol) ? "local var" /* localVariableElement */ : "var" /* variableElement */; } - if (flags & 16) - return isLocalVariableOrFunction(symbol) ? "local function" : "function"; - if (flags & 32768) - return "getter"; - if (flags & 65536) - return "setter"; - if (flags & 8192) - return "method"; - if (flags & 16384) - return "constructor"; - if (flags & 4) { - if (flags & 33554432 && symbol.checkFlags & 6) { + if (flags & 16 /* Function */) + return isLocalVariableOrFunction(symbol) ? "local function" /* localFunctionElement */ : "function" /* functionElement */; + if (flags & 32768 /* GetAccessor */) + return "getter" /* memberGetAccessorElement */; + if (flags & 65536 /* SetAccessor */) + return "setter" /* memberSetAccessorElement */; + if (flags & 8192 /* Method */) + return "method" /* memberFunctionElement */; + if (flags & 16384 /* Constructor */) + return "constructor" /* constructorImplementationElement */; + if (flags & 4 /* Property */) { + if (flags & 33554432 /* Transient */ && symbol.checkFlags & 6 /* Synthetic */) { + // If union property is result of union of non method (property/accessors/variables), it is labeled as property var unionPropertyKind = ts.forEach(typeChecker.getRootSymbols(symbol), function (rootSymbol) { var rootSymbolFlags = rootSymbol.getFlags(); - if (rootSymbolFlags & (98308 | 3)) { - return "property"; + if (rootSymbolFlags & (98308 /* PropertyOrAccessor */ | 3 /* Variable */)) { + return "property" /* memberVariableElement */; } - ts.Debug.assert(!!(rootSymbolFlags & (8192 | 16))); + // May be a Function if this was from `typeof N` with `namespace N { function f();. }`. + ts.Debug.assert(!!(rootSymbolFlags & (8192 /* Method */ | 16 /* Function */))); }); if (!unionPropertyKind) { + // If this was union of all methods, + // make sure it has call signatures before we can label it as method var typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location); if (typeOfUnionProperty.getCallSignatures().length) { - return "method"; + return "method" /* memberFunctionElement */; } - return "property"; + return "property" /* memberVariableElement */; } return unionPropertyKind; } + // If we requested completions after `x.` at the top-level, we may be at a source file location. switch (location.parent && location.parent.kind) { - case 257: - case 255: - case 256: - return location.kind === 71 ? "property" : "JSX attribute"; - case 262: - return "JSX attribute"; + // If we've typed a character of the attribute name, will be 'JsxAttribute', else will be 'JsxOpeningElement'. + case 257 /* JsxOpeningElement */: + case 255 /* JsxElement */: + case 256 /* JsxSelfClosingElement */: + return location.kind === 71 /* Identifier */ ? "property" /* memberVariableElement */ : "JSX attribute" /* jsxAttribute */; + case 262 /* JsxAttribute */: + return "JSX attribute" /* jsxAttribute */; default: - return "property"; + return "property" /* memberVariableElement */; } } - return ""; + return "" /* unknown */; } function getSymbolModifiers(symbol) { var nodeModifiers = symbol && symbol.declarations && symbol.declarations.length > 0 ? ts.getNodeModifiers(symbol.declarations[0]) - : ""; - var symbolModifiers = symbol && symbol.flags & 16777216 ? - "optional" - : ""; + : "" /* none */; + var symbolModifiers = symbol && symbol.flags & 16777216 /* Optional */ ? + "optional" /* optionalModifier */ + : "" /* none */; return nodeModifiers && symbolModifiers ? nodeModifiers + "," + symbolModifiers : nodeModifiers || symbolModifiers; } SymbolDisplay.getSymbolModifiers = getSymbolModifiers; + // TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, enclosingDeclaration, location, semanticMeaning, alias) { if (semanticMeaning === void 0) { semanticMeaning = ts.getMeaningFromLocation(location); } var displayParts = []; @@ -82129,23 +98447,27 @@ var ts; var symbolFlags = ts.getCombinedLocalAndExportSymbolFlags(symbol); var symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location); var hasAddedSymbolInfo = false; - var isThisExpression = location.kind === 99 && ts.isExpression(location); + var isThisExpression = location.kind === 99 /* ThisKeyword */ && ts.isExpression(location); var type; var printer; var documentationFromAlias; var tagsFromAlias; - if (symbolKind !== "" || symbolFlags & 32 || symbolFlags & 2097152) { - if (symbolKind === "getter" || symbolKind === "setter") { - symbolKind = "property"; + // Class at constructor site need to be shown as constructor apart from property,method, vars + if (symbolKind !== "" /* unknown */ || symbolFlags & 32 /* Class */ || symbolFlags & 2097152 /* Alias */) { + // If it is accessor they are allowed only if location is at name of the accessor + if (symbolKind === "getter" /* memberGetAccessorElement */ || symbolKind === "setter" /* memberSetAccessorElement */) { + symbolKind = "property" /* memberVariableElement */; } var signature = void 0; type = isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol.exportSymbol || symbol, location); - if (location.parent && location.parent.kind === 185) { + if (location.parent && location.parent.kind === 185 /* PropertyAccessExpression */) { var right = location.parent.name; + // Either the location is on the right of a property access, or on the left and the right is missing if (right === location || (right && right.getFullWidth() === 0)) { location = location.parent; } } + // try get the call/construct signature from the type if it matches var callExpressionLike = void 0; if (ts.isCallOrNewExpression(location)) { callExpressionLike = location; @@ -82158,23 +98480,26 @@ var ts; } if (callExpressionLike) { var candidateSignatures = []; - signature = typeChecker.getResolvedSignature(callExpressionLike, candidateSignatures); - var useConstructSignatures = callExpressionLike.kind === 188 || (ts.isCallExpression(callExpressionLike) && callExpressionLike.expression.kind === 97); + signature = typeChecker.getResolvedSignature(callExpressionLike, candidateSignatures); // TODO: GH#18217 + var useConstructSignatures = callExpressionLike.kind === 188 /* NewExpression */ || (ts.isCallExpression(callExpressionLike) && callExpressionLike.expression.kind === 97 /* SuperKeyword */); var allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); if (!ts.contains(allSignatures, signature.target) && !ts.contains(allSignatures, signature)) { + // Get the first signature if there is one -- allSignatures may contain + // either the original signature or its target, so check for either signature = allSignatures.length ? allSignatures[0] : undefined; } if (signature) { - if (useConstructSignatures && (symbolFlags & 32)) { - symbolKind = "constructor"; + if (useConstructSignatures && (symbolFlags & 32 /* Class */)) { + // Constructor + symbolKind = "constructor" /* constructorImplementationElement */; addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); } - else if (symbolFlags & 2097152) { - symbolKind = "alias"; + else if (symbolFlags & 2097152 /* Alias */) { + symbolKind = "alias" /* alias */; pushSymbolKind(symbolKind); displayParts.push(ts.spacePart()); if (useConstructSignatures) { - displayParts.push(ts.keywordPart(94)); + displayParts.push(ts.keywordPart(94 /* NewKeyword */)); displayParts.push(ts.spacePart()); } addFullSymbolName(symbol); @@ -82183,139 +98508,154 @@ var ts; addPrefixForAnyFunctionOrVar(symbol, symbolKind); } switch (symbolKind) { - case "JSX attribute": - case "property": - case "var": - case "const": - case "let": - case "parameter": - case "local var": - displayParts.push(ts.punctuationPart(56)); + case "JSX attribute" /* jsxAttribute */: + case "property" /* memberVariableElement */: + case "var" /* variableElement */: + case "const" /* constElement */: + case "let" /* letElement */: + case "parameter" /* parameterElement */: + case "local var" /* localVariableElement */: + // If it is call or construct signature of lambda's write type name + displayParts.push(ts.punctuationPart(56 /* ColonToken */)); displayParts.push(ts.spacePart()); - if (!(ts.getObjectFlags(type) & 16) && type.symbol) { - ts.addRange(displayParts, ts.symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, undefined, 4 | 1)); + if (!(ts.getObjectFlags(type) & 16 /* Anonymous */) && type.symbol) { + ts.addRange(displayParts, ts.symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, 4 /* AllowAnyNodeKind */ | 1 /* WriteTypeParametersOrArguments */)); displayParts.push(ts.lineBreakPart()); } if (useConstructSignatures) { - displayParts.push(ts.keywordPart(94)); + displayParts.push(ts.keywordPart(94 /* NewKeyword */)); displayParts.push(ts.spacePart()); } - addSignatureDisplayParts(signature, allSignatures, 262144); + addSignatureDisplayParts(signature, allSignatures, 262144 /* WriteArrowStyleSignature */); break; default: + // Just signature addSignatureDisplayParts(signature, allSignatures); } hasAddedSymbolInfo = true; } } - else if ((ts.isNameOfFunctionDeclaration(location) && !(symbolFlags & 98304)) || - (location.kind === 123 && location.parent.kind === 155)) { + else if ((ts.isNameOfFunctionDeclaration(location) && !(symbolFlags & 98304 /* Accessor */)) || // name of function declaration + (location.kind === 123 /* ConstructorKeyword */ && location.parent.kind === 155 /* Constructor */)) { // At constructor keyword of constructor declaration + // get the signature from the declaration and write it var functionDeclaration_1 = location.parent; + // Use function declaration to write the signatures only if the symbol corresponding to this declaration var locationIsSymbolDeclaration = ts.find(symbol.declarations, function (declaration) { - return declaration === (location.kind === 123 ? functionDeclaration_1.parent : functionDeclaration_1); + return declaration === (location.kind === 123 /* ConstructorKeyword */ ? functionDeclaration_1.parent : functionDeclaration_1); }); if (locationIsSymbolDeclaration) { - var allSignatures = functionDeclaration_1.kind === 155 ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures(); + var allSignatures = functionDeclaration_1.kind === 155 /* Constructor */ ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures(); if (!typeChecker.isImplementationOfOverload(functionDeclaration_1)) { - signature = typeChecker.getSignatureFromDeclaration(functionDeclaration_1); + signature = typeChecker.getSignatureFromDeclaration(functionDeclaration_1); // TODO: GH#18217 } else { signature = allSignatures[0]; } - if (functionDeclaration_1.kind === 155) { - symbolKind = "constructor"; + if (functionDeclaration_1.kind === 155 /* Constructor */) { + // show (constructor) Type(...) signature + symbolKind = "constructor" /* constructorImplementationElement */; addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); } else { - addPrefixForAnyFunctionOrVar(functionDeclaration_1.kind === 158 && - !(type.symbol.flags & 2048 || type.symbol.flags & 4096) ? type.symbol : symbol, symbolKind); + // (function/method) symbol(..signature) + addPrefixForAnyFunctionOrVar(functionDeclaration_1.kind === 158 /* CallSignature */ && + !(type.symbol.flags & 2048 /* TypeLiteral */ || type.symbol.flags & 4096 /* ObjectLiteral */) ? type.symbol : symbol, symbolKind); } addSignatureDisplayParts(signature, allSignatures); hasAddedSymbolInfo = true; } } } - if (symbolFlags & 32 && !hasAddedSymbolInfo && !isThisExpression) { + if (symbolFlags & 32 /* Class */ && !hasAddedSymbolInfo && !isThisExpression) { addAliasPrefixIfNecessary(); - if (ts.getDeclarationOfKind(symbol, 205)) { - pushSymbolKind("local class"); + if (ts.getDeclarationOfKind(symbol, 205 /* ClassExpression */)) { + // Special case for class expressions because we would like to indicate that + // the class name is local to the class body (similar to function expression) + // (local class) class + pushSymbolKind("local class" /* localClassElement */); } else { - displayParts.push(ts.keywordPart(75)); + // Class declaration has name which is not local. + displayParts.push(ts.keywordPart(75 /* ClassKeyword */)); } displayParts.push(ts.spacePart()); addFullSymbolName(symbol); writeTypeParametersOfSymbol(symbol, sourceFile); } - if ((symbolFlags & 64) && (semanticMeaning & 2)) { + if ((symbolFlags & 64 /* Interface */) && (semanticMeaning & 2 /* Type */)) { prefixNextMeaning(); - displayParts.push(ts.keywordPart(109)); + displayParts.push(ts.keywordPart(109 /* InterfaceKeyword */)); displayParts.push(ts.spacePart()); addFullSymbolName(symbol); writeTypeParametersOfSymbol(symbol, sourceFile); } - if (symbolFlags & 524288) { + if (symbolFlags & 524288 /* TypeAlias */) { prefixNextMeaning(); - displayParts.push(ts.keywordPart(139)); + displayParts.push(ts.keywordPart(139 /* TypeKeyword */)); displayParts.push(ts.spacePart()); addFullSymbolName(symbol); writeTypeParametersOfSymbol(symbol, sourceFile); displayParts.push(ts.spacePart()); - displayParts.push(ts.operatorPart(58)); + displayParts.push(ts.operatorPart(58 /* EqualsToken */)); displayParts.push(ts.spacePart()); - ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, typeChecker.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration, 8388608)); + ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, typeChecker.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration, 8388608 /* InTypeAlias */)); } - if (symbolFlags & 384) { + if (symbolFlags & 384 /* Enum */) { prefixNextMeaning(); if (ts.forEach(symbol.declarations, ts.isConstEnumDeclaration)) { - displayParts.push(ts.keywordPart(76)); + displayParts.push(ts.keywordPart(76 /* ConstKeyword */)); displayParts.push(ts.spacePart()); } - displayParts.push(ts.keywordPart(83)); + displayParts.push(ts.keywordPart(83 /* EnumKeyword */)); displayParts.push(ts.spacePart()); addFullSymbolName(symbol); } - if (symbolFlags & 1536) { + if (symbolFlags & 1536 /* Module */) { prefixNextMeaning(); - var declaration = ts.getDeclarationOfKind(symbol, 239); - var isNamespace = declaration && declaration.name && declaration.name.kind === 71; - displayParts.push(ts.keywordPart(isNamespace ? 130 : 129)); + var declaration = ts.getDeclarationOfKind(symbol, 239 /* ModuleDeclaration */); + var isNamespace = declaration && declaration.name && declaration.name.kind === 71 /* Identifier */; + displayParts.push(ts.keywordPart(isNamespace ? 130 /* NamespaceKeyword */ : 129 /* ModuleKeyword */)); displayParts.push(ts.spacePart()); addFullSymbolName(symbol); } - if ((symbolFlags & 262144) && (semanticMeaning & 2)) { + if ((symbolFlags & 262144 /* TypeParameter */) && (semanticMeaning & 2 /* Type */)) { prefixNextMeaning(); - displayParts.push(ts.punctuationPart(19)); + displayParts.push(ts.punctuationPart(19 /* OpenParenToken */)); displayParts.push(ts.textPart("type parameter")); - displayParts.push(ts.punctuationPart(20)); + displayParts.push(ts.punctuationPart(20 /* CloseParenToken */)); displayParts.push(ts.spacePart()); addFullSymbolName(symbol); if (symbol.parent) { + // Class/Interface type parameter addInPrefix(); addFullSymbolName(symbol.parent, enclosingDeclaration); writeTypeParametersOfSymbol(symbol.parent, enclosingDeclaration); } else { - var decl = ts.getDeclarationOfKind(symbol, 148); + // Method/function type parameter + var decl = ts.getDeclarationOfKind(symbol, 148 /* TypeParameter */); if (decl === undefined) return ts.Debug.fail(); var declaration = decl.parent; if (declaration) { if (ts.isFunctionLikeKind(declaration.kind)) { addInPrefix(); - var signature = typeChecker.getSignatureFromDeclaration(declaration); - if (declaration.kind === 159) { - displayParts.push(ts.keywordPart(94)); + var signature = typeChecker.getSignatureFromDeclaration(declaration); // TODO: GH#18217 + if (declaration.kind === 159 /* ConstructSignature */) { + displayParts.push(ts.keywordPart(94 /* NewKeyword */)); displayParts.push(ts.spacePart()); } - else if (declaration.kind !== 158 && declaration.name) { + else if (declaration.kind !== 158 /* CallSignature */ && declaration.name) { addFullSymbolName(declaration.symbol); } - ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, sourceFile, 32)); + ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, sourceFile, 32 /* WriteTypeArgumentsOfSignature */)); } - else if (declaration.kind === 237) { + else if (declaration.kind === 237 /* TypeAliasDeclaration */) { + // Type alias type parameter + // For example + // type list = T[]; // Both T will go through same code path addInPrefix(); - displayParts.push(ts.keywordPart(139)); + displayParts.push(ts.keywordPart(139 /* TypeKeyword */)); displayParts.push(ts.spacePart()); addFullSymbolName(declaration.symbol); writeTypeParametersOfSymbol(declaration.symbol, sourceFile); @@ -82323,21 +98663,21 @@ var ts; } } } - if (symbolFlags & 8) { - symbolKind = "enum member"; + if (symbolFlags & 8 /* EnumMember */) { + symbolKind = "enum member" /* enumMemberElement */; addPrefixForAnyFunctionOrVar(symbol, "enum member"); var declaration = symbol.declarations[0]; - if (declaration.kind === 273) { + if (declaration.kind === 273 /* EnumMember */) { var constantValue = typeChecker.getConstantValue(declaration); if (constantValue !== undefined) { displayParts.push(ts.spacePart()); - displayParts.push(ts.operatorPart(58)); + displayParts.push(ts.operatorPart(58 /* EqualsToken */)); displayParts.push(ts.spacePart()); displayParts.push(ts.displayPart(ts.getTextOfConstantValue(constantValue), typeof constantValue === "number" ? ts.SymbolDisplayPartKind.numericLiteral : ts.SymbolDisplayPartKind.stringLiteral)); } } } - if (symbolFlags & 2097152) { + if (symbolFlags & 2097152 /* Alias */) { prefixNextMeaning(); if (!hasAddedSymbolInfo) { var resolvedSymbol = typeChecker.getAliasedSymbol(symbol); @@ -82346,7 +98686,7 @@ var ts; var declarationName = ts.getNameOfDeclaration(resolvedNode); if (declarationName) { var isExternalModuleDeclaration = ts.isModuleWithStringLiteralName(resolvedNode) && - ts.hasModifier(resolvedNode, 2); + ts.hasModifier(resolvedNode, 2 /* Ambient */); var shouldUseAliasName = symbol.name !== "default" && !isExternalModuleDeclaration; var resolvedInfo = getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, resolvedSymbol, ts.getSourceFileOfNode(resolvedNode), resolvedNode, declarationName, semanticMeaning, shouldUseAliasName ? symbol : resolvedSymbol); displayParts.push.apply(displayParts, resolvedInfo.displayParts); @@ -82357,41 +98697,41 @@ var ts; } } switch (symbol.declarations[0].kind) { - case 242: - displayParts.push(ts.keywordPart(84)); + case 242 /* NamespaceExportDeclaration */: + displayParts.push(ts.keywordPart(84 /* ExportKeyword */)); displayParts.push(ts.spacePart()); - displayParts.push(ts.keywordPart(130)); + displayParts.push(ts.keywordPart(130 /* NamespaceKeyword */)); break; - case 249: - displayParts.push(ts.keywordPart(84)); + case 249 /* ExportAssignment */: + displayParts.push(ts.keywordPart(84 /* ExportKeyword */)); displayParts.push(ts.spacePart()); - displayParts.push(ts.keywordPart(symbol.declarations[0].isExportEquals ? 58 : 79)); + displayParts.push(ts.keywordPart(symbol.declarations[0].isExportEquals ? 58 /* EqualsToken */ : 79 /* DefaultKeyword */)); break; - case 252: - displayParts.push(ts.keywordPart(84)); + case 252 /* ExportSpecifier */: + displayParts.push(ts.keywordPart(84 /* ExportKeyword */)); break; default: - displayParts.push(ts.keywordPart(91)); + displayParts.push(ts.keywordPart(91 /* ImportKeyword */)); } displayParts.push(ts.spacePart()); addFullSymbolName(symbol); ts.forEach(symbol.declarations, function (declaration) { - if (declaration.kind === 243) { + if (declaration.kind === 243 /* ImportEqualsDeclaration */) { var importEqualsDeclaration = declaration; if (ts.isExternalModuleImportEqualsDeclaration(importEqualsDeclaration)) { displayParts.push(ts.spacePart()); - displayParts.push(ts.operatorPart(58)); + displayParts.push(ts.operatorPart(58 /* EqualsToken */)); displayParts.push(ts.spacePart()); - displayParts.push(ts.keywordPart(133)); - displayParts.push(ts.punctuationPart(19)); + displayParts.push(ts.keywordPart(133 /* RequireKeyword */)); + displayParts.push(ts.punctuationPart(19 /* OpenParenToken */)); displayParts.push(ts.displayPart(ts.getTextOfNode(ts.getExternalModuleImportEqualsDeclarationExpression(importEqualsDeclaration)), ts.SymbolDisplayPartKind.stringLiteral)); - displayParts.push(ts.punctuationPart(20)); + displayParts.push(ts.punctuationPart(20 /* CloseParenToken */)); } else { var internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference); if (internalAliasSymbol) { displayParts.push(ts.spacePart()); - displayParts.push(ts.operatorPart(58)); + displayParts.push(ts.operatorPart(58 /* EqualsToken */)); displayParts.push(ts.spacePart()); addFullSymbolName(internalAliasSymbol, enclosingDeclaration); } @@ -82401,26 +98741,28 @@ var ts; }); } if (!hasAddedSymbolInfo) { - if (symbolKind !== "") { + if (symbolKind !== "" /* unknown */) { if (type) { if (isThisExpression) { prefixNextMeaning(); - displayParts.push(ts.keywordPart(99)); + displayParts.push(ts.keywordPart(99 /* ThisKeyword */)); } else { addPrefixForAnyFunctionOrVar(symbol, symbolKind); } - if (symbolKind === "property" || - symbolKind === "JSX attribute" || - symbolFlags & 3 || - symbolKind === "local var" || + // For properties, variables and local vars: show the type + if (symbolKind === "property" /* memberVariableElement */ || + symbolKind === "JSX attribute" /* jsxAttribute */ || + symbolFlags & 3 /* Variable */ || + symbolKind === "local var" /* localVariableElement */ || isThisExpression) { - displayParts.push(ts.punctuationPart(56)); + displayParts.push(ts.punctuationPart(56 /* ColonToken */)); displayParts.push(ts.spacePart()); - if (type.symbol && type.symbol.flags & 262144) { + // If the type is type parameter, format it specially + if (type.symbol && type.symbol.flags & 262144 /* TypeParameter */) { var typeParameterParts = ts.mapToDisplayParts(function (writer) { var param = typeChecker.typeParameterToDeclaration(type, enclosingDeclaration); - getPrinter().writeNode(4, param, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosingDeclaration)), writer); + getPrinter().writeNode(4 /* Unspecified */, param, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosingDeclaration)), writer); }); ts.addRange(displayParts, typeParameterParts); } @@ -82428,12 +98770,12 @@ var ts; ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, type, enclosingDeclaration)); } } - else if (symbolFlags & 16 || - symbolFlags & 8192 || - symbolFlags & 16384 || - symbolFlags & 131072 || - symbolFlags & 98304 || - symbolKind === "method") { + else if (symbolFlags & 16 /* Function */ || + symbolFlags & 8192 /* Method */ || + symbolFlags & 16384 /* Constructor */ || + symbolFlags & 131072 /* Signature */ || + symbolFlags & 98304 /* Accessor */ || + symbolKind === "method" /* memberFunctionElement */) { var allSignatures = type.getNonNullableType().getCallSignatures(); if (allSignatures.length) { addSignatureDisplayParts(allSignatures[0], allSignatures); @@ -82448,11 +98790,14 @@ var ts; if (!documentation) { documentation = symbol.getDocumentationComment(typeChecker); tags = symbol.getJsDocTags(); - if (documentation.length === 0 && symbolFlags & 4) { - if (symbol.parent && ts.forEach(symbol.parent.declarations, function (declaration) { return declaration.kind === 274; })) { + if (documentation.length === 0 && symbolFlags & 4 /* Property */) { + // For some special property access expressions like `exports.foo = foo` or `module.exports.foo = foo` + // there documentation comments might be attached to the right hand side symbol of their declarations. + // The pattern of such special property access is that the parent symbol is the symbol of the file. + if (symbol.parent && ts.forEach(symbol.parent.declarations, function (declaration) { return declaration.kind === 274 /* SourceFile */; })) { for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var declaration = _a[_i]; - if (!declaration.parent || declaration.parent.kind !== 200) { + if (!declaration.parent || declaration.parent.kind !== 200 /* BinaryExpression */) { continue; } var rhsSymbol = typeChecker.getSymbolAtLocation(declaration.parent.right); @@ -82489,23 +98834,23 @@ var ts; } function addAliasPrefixIfNecessary() { if (alias) { - pushSymbolKind("alias"); + pushSymbolKind("alias" /* alias */); displayParts.push(ts.spacePart()); } } function addInPrefix() { displayParts.push(ts.spacePart()); - displayParts.push(ts.keywordPart(92)); + displayParts.push(ts.keywordPart(92 /* InKeyword */)); displayParts.push(ts.spacePart()); } function addFullSymbolName(symbolToDisplay, enclosingDeclaration) { if (alias && symbolToDisplay === symbol) { symbolToDisplay = alias; } - var fullSymbolDisplayParts = ts.symbolToDisplayParts(typeChecker, symbolToDisplay, enclosingDeclaration || sourceFile, undefined, 1 | 2 | 4); + var fullSymbolDisplayParts = ts.symbolToDisplayParts(typeChecker, symbolToDisplay, enclosingDeclaration || sourceFile, /*meaning*/ undefined, 1 /* WriteTypeParametersOrArguments */ | 2 /* UseOnlyExternalAliasing */ | 4 /* AllowAnyNodeKind */); ts.addRange(displayParts, fullSymbolDisplayParts); - if (symbol.flags & 16777216) { - displayParts.push(ts.punctuationPart(55)); + if (symbol.flags & 16777216 /* Optional */) { + displayParts.push(ts.punctuationPart(55 /* QuestionToken */)); } } function addPrefixForAnyFunctionOrVar(symbol, symbolKind) { @@ -82520,31 +98865,31 @@ var ts; } function pushSymbolKind(symbolKind) { switch (symbolKind) { - case "var": - case "function": - case "let": - case "const": - case "constructor": + case "var" /* variableElement */: + case "function" /* functionElement */: + case "let" /* letElement */: + case "const" /* constElement */: + case "constructor" /* constructorImplementationElement */: displayParts.push(ts.textOrKeywordPart(symbolKind)); return; default: - displayParts.push(ts.punctuationPart(19)); + displayParts.push(ts.punctuationPart(19 /* OpenParenToken */)); displayParts.push(ts.textOrKeywordPart(symbolKind)); - displayParts.push(ts.punctuationPart(20)); + displayParts.push(ts.punctuationPart(20 /* CloseParenToken */)); return; } } function addSignatureDisplayParts(signature, allSignatures, flags) { - if (flags === void 0) { flags = 0; } - ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags | 32)); + if (flags === void 0) { flags = 0 /* None */; } + ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags | 32 /* WriteTypeArgumentsOfSignature */)); if (allSignatures.length > 1) { displayParts.push(ts.spacePart()); - displayParts.push(ts.punctuationPart(19)); - displayParts.push(ts.operatorPart(37)); + displayParts.push(ts.punctuationPart(19 /* OpenParenToken */)); + displayParts.push(ts.operatorPart(37 /* PlusToken */)); displayParts.push(ts.displayPart((allSignatures.length - 1).toString(), ts.SymbolDisplayPartKind.numericLiteral)); displayParts.push(ts.spacePart()); displayParts.push(ts.textPart(allSignatures.length === 2 ? "overload" : "overloads")); - displayParts.push(ts.punctuationPart(20)); + displayParts.push(ts.punctuationPart(20 /* CloseParenToken */)); } documentation = signature.getDocumentationComment(typeChecker); tags = signature.getJsDocTags(); @@ -82552,7 +98897,7 @@ var ts; function writeTypeParametersOfSymbol(symbol, enclosingDeclaration) { var typeParameterParts = ts.mapToDisplayParts(function (writer) { var params = typeChecker.symbolToTypeParameterDeclarations(symbol, enclosingDeclaration); - getPrinter().writeList(26896, params, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosingDeclaration)), writer); + getPrinter().writeList(26896 /* TypeParameters */, params, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosingDeclaration)), writer); }); ts.addRange(displayParts, typeParameterParts); } @@ -82560,20 +98905,24 @@ var ts; SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind; function isLocalVariableOrFunction(symbol) { if (symbol.parent) { - return false; + return false; // This is exported symbol } return ts.forEach(symbol.declarations, function (declaration) { - if (declaration.kind === 192) { + // Function expressions are local + if (declaration.kind === 192 /* FunctionExpression */) { return true; } - if (declaration.kind !== 232 && declaration.kind !== 234) { + if (declaration.kind !== 232 /* VariableDeclaration */ && declaration.kind !== 234 /* FunctionDeclaration */) { return false; } + // If the parent is not sourceFile or module block it is local variable for (var parent = declaration.parent; !ts.isFunctionBlock(parent); parent = parent.parent) { - if (parent.kind === 274 || parent.kind === 240) { + // Reached source file or module block + if (parent.kind === 274 /* SourceFile */ || parent.kind === 240 /* ModuleBlock */) { return false; } } + // parent is in function block return true; }); } @@ -82581,13 +98930,27 @@ var ts; })(ts || (ts = {})); var ts; (function (ts) { + /* + * This function will compile source text from 'input' argument using specified compiler options. + * If not options are provided - it will use a set of default compiler options. + * Extra compiler options that will unconditionally be used by this function are: + * - isolatedModules = true + * - allowNonTsExtensions = true + * - noLib = true + * - noResolve = true + */ function transpileModule(input, transpileOptions) { var diagnostics = []; var options = transpileOptions.compilerOptions ? fixupCompilerOptions(transpileOptions.compilerOptions, diagnostics) : ts.getDefaultCompilerOptions(); options.isolatedModules = true; + // transpileModule does not write anything to disk so there is no need to verify that there are no conflicts between input and output paths. options.suppressOutputPathCheck = true; + // Filename can be non-ts file. options.allowNonTsExtensions = true; + // We are not returning a sourceFile for lib file when asked by the program, + // so pass --noLib to avoid reporting a file not found error. options.noLib = true; + // Clear out other settings that would not be used in transpiling this module options.lib = undefined; options.types = undefined; options.noEmit = undefined; @@ -82598,9 +98961,12 @@ var ts; options.declarationDir = undefined; options.out = undefined; options.outFile = undefined; + // We are not doing a full typecheck, we are not resolving the whole context, + // so pass --noResolve to avoid reporting missing file errors. options.noResolve = true; + // if jsx is specified then treat file as .tsx var inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts"); - var sourceFile = ts.createSourceFile(inputFileName, input, options.target); + var sourceFile = ts.createSourceFile(inputFileName, input, options.target); // TODO: GH#18217 if (transpileOptions.moduleName) { sourceFile.moduleName = transpileOptions.moduleName; } @@ -82608,8 +98974,10 @@ var ts; sourceFile.renamedDependencies = ts.createMapFromTemplate(transpileOptions.renamedDependencies); } var newLine = ts.getNewLineCharacter(options); + // Output var outputText; var sourceMapText; + // Create a compilerHost object to allow the compiler to read and write files var compilerHost = { getSourceFile: function (fileName) { return fileName === ts.normalizePath(inputFileName) ? sourceFile : undefined; }, writeFile: function (name, text) { @@ -82634,23 +99002,31 @@ var ts; }; var program = ts.createProgram([inputFileName], options, compilerHost); if (transpileOptions.reportDiagnostics) { - ts.addRange(diagnostics, program.getSyntacticDiagnostics(sourceFile)); - ts.addRange(diagnostics, program.getOptionsDiagnostics()); + ts.addRange(/*to*/ diagnostics, /*from*/ program.getSyntacticDiagnostics(sourceFile)); + ts.addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics()); } - program.emit(undefined, undefined, undefined, undefined, transpileOptions.transformers); + // Emit + program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ undefined, transpileOptions.transformers); if (outputText === undefined) return ts.Debug.fail("Output generation failed"); return { outputText: outputText, diagnostics: diagnostics, sourceMapText: sourceMapText }; } ts.transpileModule = transpileModule; + /* + * This is a shortcut function for transpileModule - it accepts transpileOptions as parameters and returns only outputText part of the result. + */ function transpile(input, compilerOptions, fileName, diagnostics, moduleName) { var output = transpileModule(input, { compilerOptions: compilerOptions, fileName: fileName, reportDiagnostics: !!diagnostics, moduleName: moduleName }); + // addRange correctly handles cases when wither 'from' or 'to' argument is missing ts.addRange(diagnostics, output.diagnostics); return output.outputText; } ts.transpile = transpile; var commandLineOptionsStringToEnum; + /** JS users may pass in string values for enum compiler options (such as ModuleKind), so convert. */ + /*@internal*/ function fixupCompilerOptions(options, diagnostics) { + // Lazily create this value to fix module loading errors. commandLineOptionsStringToEnum = commandLineOptionsStringToEnum || ts.filter(ts.optionDeclarations, function (o) { return typeof o.type === "object" && !ts.forEachEntry(o.type, function (v) { return typeof v !== "number"; }); }); @@ -82660,11 +99036,14 @@ var ts; return "continue"; } var value = options[opt.name]; + // Value should be a key of opt.type if (ts.isString(value)) { + // If value is not a string, this will fail options[opt.name] = ts.parseCustomTypeOption(opt, value, diagnostics); } else { if (!ts.forEachEntry(opt.type, function (v) { return v === value; })) { + // Supplied value isn't a valid enum value. diagnostics.push(ts.createCompilerDiagnosticForInvalidCustomType(opt)); } } @@ -82677,6 +99056,7 @@ var ts; } ts.fixupCompilerOptions = fixupCompilerOptions; })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var formatting; @@ -82690,7 +99070,7 @@ var ts; FormattingRequestKind[FormattingRequestKind["FormatOnOpeningCurlyBrace"] = 4] = "FormatOnOpeningCurlyBrace"; FormattingRequestKind[FormattingRequestKind["FormatOnClosingCurlyBrace"] = 5] = "FormatOnClosingCurlyBrace"; })(FormattingRequestKind = formatting.FormattingRequestKind || (formatting.FormattingRequestKind = {})); - var FormattingContext = (function () { + var FormattingContext = /** @class */ (function () { function FormattingContext(sourceFile, formattingRequestKind, options) { this.sourceFile = sourceFile; this.formattingRequestKind = formattingRequestKind; @@ -82707,6 +99087,7 @@ var ts; this.nextTokenSpan = nextRange; this.nextTokenParent = nextTokenParent; this.contextNode = commonParent; + // drop cached results this.contextNodeAllOnSameLine = undefined; this.nextNodeAllOnSameLine = undefined; this.tokensAreOnSameLine = undefined; @@ -82751,8 +99132,8 @@ var ts; return startLine === endLine; }; FormattingContext.prototype.BlockIsOnOneLine = function (node) { - var openBrace = ts.findChildOfKind(node, 17, this.sourceFile); - var closeBrace = ts.findChildOfKind(node, 18, this.sourceFile); + var openBrace = ts.findChildOfKind(node, 17 /* OpenBraceToken */, this.sourceFile); + var closeBrace = ts.findChildOfKind(node, 18 /* CloseBraceToken */, this.sourceFile); if (openBrace && closeBrace) { var startLine = this.sourceFile.getLineAndCharacterOfPosition(openBrace.getEnd()).line; var endLine = this.sourceFile.getLineAndCharacterOfPosition(closeBrace.getStart(this.sourceFile)).line; @@ -82765,12 +99146,13 @@ var ts; formatting.FormattingContext = FormattingContext; })(formatting = ts.formatting || (ts.formatting = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var formatting; (function (formatting) { - var standardScanner = ts.createScanner(6, false, 0); - var jsxScanner = ts.createScanner(6, false, 1); + var standardScanner = ts.createScanner(6 /* Latest */, /*skipTrivia*/ false, 0 /* Standard */); + var jsxScanner = ts.createScanner(6 /* Latest */, /*skipTrivia*/ false, 1 /* JSX */); var ScanAction; (function (ScanAction) { ScanAction[ScanAction["Scan"] = 0] = "Scan"; @@ -82781,7 +99163,7 @@ var ts; ScanAction[ScanAction["RescanJsxText"] = 5] = "RescanJsxText"; })(ScanAction || (ScanAction = {})); function getFormattingScanner(text, languageVariant, startPos, endPos, cb) { - var scanner = languageVariant === 1 ? jsxScanner : standardScanner; + var scanner = languageVariant === 1 /* JSX */ ? jsxScanner : standardScanner; scanner.setText(text); scanner.setTextPos(startPos); var wasNewLine = true; @@ -82805,7 +99187,7 @@ var ts; lastTokenInfo = undefined; var isStarted = scanner.getStartPos() !== startPos; if (isStarted) { - wasNewLine = !!trailingTrivia && ts.last(trailingTrivia).kind === 4; + wasNewLine = !!trailingTrivia && ts.last(trailingTrivia).kind === 4 /* NewLineTrivia */; } else { scanner.scan(); @@ -82813,11 +99195,13 @@ var ts; leadingTrivia = undefined; trailingTrivia = undefined; var pos = scanner.getStartPos(); + // Read leading trivia and token while (pos < endPos) { var t = scanner.getToken(); if (!ts.isTrivia(t)) { break; } + // consume leading trivia scanner.scan(); var item = { pos: pos, @@ -82831,11 +99215,11 @@ var ts; } function shouldRescanGreaterThanToken(node) { switch (node.kind) { - case 31: - case 66: - case 67: - case 47: - case 46: + case 31 /* GreaterThanEqualsToken */: + case 66 /* GreaterThanGreaterThanEqualsToken */: + case 67 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + case 47 /* GreaterThanGreaterThanGreaterThanToken */: + case 46 /* GreaterThanGreaterThanToken */: return true; } return false; @@ -82843,46 +99227,56 @@ var ts; function shouldRescanJsxIdentifier(node) { if (node.parent) { switch (node.parent.kind) { - case 262: - case 257: - case 258: - case 256: - return ts.isKeyword(node.kind) || node.kind === 71; + case 262 /* JsxAttribute */: + case 257 /* JsxOpeningElement */: + case 258 /* JsxClosingElement */: + case 256 /* JsxSelfClosingElement */: + // May parse an identifier like `module-layout`; that will be scanned as a keyword at first, but we should parse the whole thing to get an identifier. + return ts.isKeyword(node.kind) || node.kind === 71 /* Identifier */; } } return false; } function shouldRescanJsxText(node) { - return node.kind === 10; + return node.kind === 10 /* JsxText */; } function shouldRescanSlashToken(container) { - return container.kind === 12; + return container.kind === 12 /* RegularExpressionLiteral */; } function shouldRescanTemplateToken(container) { - return container.kind === 15 || - container.kind === 16; + return container.kind === 15 /* TemplateMiddle */ || + container.kind === 16 /* TemplateTail */; } function startsWithSlashToken(t) { - return t === 41 || t === 63; + return t === 41 /* SlashToken */ || t === 63 /* SlashEqualsToken */; } function readTokenInfo(n) { ts.Debug.assert(isOnToken()); + // normally scanner returns the smallest available token + // check the kind of context node to determine if scanner should have more greedy behavior and consume more text. var expectedScanAction = shouldRescanGreaterThanToken(n) - ? 1 + ? 1 /* RescanGreaterThanToken */ : shouldRescanSlashToken(n) - ? 2 + ? 2 /* RescanSlashToken */ : shouldRescanTemplateToken(n) - ? 3 + ? 3 /* RescanTemplateToken */ : shouldRescanJsxIdentifier(n) - ? 4 + ? 4 /* RescanJsxIdentifier */ : shouldRescanJsxText(n) - ? 5 - : 0; + ? 5 /* RescanJsxText */ + : 0 /* Scan */; if (lastTokenInfo && expectedScanAction === lastScanAction) { + // readTokenInfo was called before with the same expected scan action. + // No need to re-scan text, return existing 'lastTokenInfo' + // it is ok to call fixTokenKind here since it does not affect + // what portion of text is consumed. In contrast rescanning can change it, + // i.e. for '>=' when originally scanner eats just one character + // and rescanning forces it to consume more. return fixTokenKind(lastTokenInfo, n); } if (scanner.getStartPos() !== savedPos) { ts.Debug.assert(lastTokenInfo !== undefined); + // readTokenInfo was called before but scan action differs - rescan text scanner.setTextPos(savedPos); scanner.scan(); } @@ -82892,6 +99286,7 @@ var ts; end: scanner.getTextPos(), kind: currentToken }; + // consume trailing trivia if (trailingTrivia) { trailingTrivia = undefined; } @@ -82909,7 +99304,8 @@ var ts; trailingTrivia = []; } trailingTrivia.push(trivia); - if (currentToken === 4) { + if (currentToken === 4 /* NewLineTrivia */) { + // move past new line scanner.scan(); break; } @@ -82919,37 +99315,37 @@ var ts; } function getNextToken(n, expectedScanAction) { var token = scanner.getToken(); - lastScanAction = 0; + lastScanAction = 0 /* Scan */; switch (expectedScanAction) { - case 1: - if (token === 29) { - lastScanAction = 1; + case 1 /* RescanGreaterThanToken */: + if (token === 29 /* GreaterThanToken */) { + lastScanAction = 1 /* RescanGreaterThanToken */; var newToken = scanner.reScanGreaterToken(); ts.Debug.assert(n.kind === newToken); return newToken; } break; - case 2: + case 2 /* RescanSlashToken */: if (startsWithSlashToken(token)) { - lastScanAction = 2; + lastScanAction = 2 /* RescanSlashToken */; var newToken = scanner.reScanSlashToken(); ts.Debug.assert(n.kind === newToken); return newToken; } break; - case 3: - if (token === 18) { - lastScanAction = 3; + case 3 /* RescanTemplateToken */: + if (token === 18 /* CloseBraceToken */) { + lastScanAction = 3 /* RescanTemplateToken */; return scanner.reScanTemplateToken(); } break; - case 4: - lastScanAction = 4; + case 4 /* RescanJsxIdentifier */: + lastScanAction = 4 /* RescanJsxIdentifier */; return scanner.scanJsxIdentifier(); - case 5: - lastScanAction = 5; + case 5 /* RescanJsxText */: + lastScanAction = 5 /* RescanJsxText */; return scanner.reScanJsxToken(); - case 0: + case 0 /* Scan */: break; default: ts.Debug.assertNever(expectedScanAction); @@ -82959,8 +99355,12 @@ var ts; function isOnToken() { var current = lastTokenInfo ? lastTokenInfo.token.kind : scanner.getToken(); var startPos = lastTokenInfo ? lastTokenInfo.token.pos : scanner.getStartPos(); - return startPos < endPos && current !== 1 && !ts.isTrivia(current); + return startPos < endPos && current !== 1 /* EndOfFileToken */ && !ts.isTrivia(current); } + // when containing node in the tree is token + // but its kind differs from the kind that was returned by the scanner, + // then kind needs to be fixed. This might happen in cases + // when parser interprets token differently, i.e keyword treated as identifier function fixTokenKind(tokenInfo, container) { if (ts.isToken(container) && tokenInfo.token.kind !== container.kind) { tokenInfo.token.kind = container.kind; @@ -82980,6 +99380,7 @@ var ts; formatting.getFormattingScanner = getFormattingScanner; })(formatting = ts.formatting || (ts.formatting = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var formatting; @@ -82999,13 +99400,14 @@ var ts; })(RuleFlags = formatting.RuleFlags || (formatting.RuleFlags = {})); })(formatting = ts.formatting || (ts.formatting = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var formatting; (function (formatting) { function getAllRules() { var allTokens = []; - for (var token = 0; token <= 145; token++) { + for (var token = 0 /* FirstToken */; token <= 145 /* LastToken */; token++) { allTokens.push(token); } function anyTokenExcept() { @@ -83016,200 +99418,262 @@ var ts; return { tokens: allTokens.filter(function (t) { return !tokens.some(function (t2) { return t2 === t; }); }), isSpecific: false }; } var anyToken = { tokens: allTokens, isSpecific: false }; - var anyTokenIncludingMultilineComments = tokenRangeFrom(allTokens.concat([3])); - var keywords = tokenRangeFromRange(72, 145); - var binaryOperators = tokenRangeFromRange(27, 70); - var binaryKeywordOperators = [92, 93, 145, 118, 127]; - var unaryPrefixOperators = [43, 44, 52, 51]; + var anyTokenIncludingMultilineComments = tokenRangeFrom(allTokens.concat([3 /* MultiLineCommentTrivia */])); + var keywords = tokenRangeFromRange(72 /* FirstKeyword */, 145 /* LastKeyword */); + var binaryOperators = tokenRangeFromRange(27 /* FirstBinaryOperator */, 70 /* LastBinaryOperator */); + var binaryKeywordOperators = [92 /* InKeyword */, 93 /* InstanceOfKeyword */, 145 /* OfKeyword */, 118 /* AsKeyword */, 127 /* IsKeyword */]; + var unaryPrefixOperators = [43 /* PlusPlusToken */, 44 /* MinusMinusToken */, 52 /* TildeToken */, 51 /* ExclamationToken */]; var unaryPrefixExpressions = [ - 8, 71, 19, 21, - 17, 99, 94 + 8 /* NumericLiteral */, 71 /* Identifier */, 19 /* OpenParenToken */, 21 /* OpenBracketToken */, + 17 /* OpenBraceToken */, 99 /* ThisKeyword */, 94 /* NewKeyword */ ]; - var unaryPreincrementExpressions = [71, 19, 99, 94]; - var unaryPostincrementExpressions = [71, 20, 22, 94]; - var unaryPredecrementExpressions = [71, 19, 99, 94]; - var unaryPostdecrementExpressions = [71, 20, 22, 94]; - var comments = [2, 3]; - var typeNames = [71].concat(ts.typeKeywords); + var unaryPreincrementExpressions = [71 /* Identifier */, 19 /* OpenParenToken */, 99 /* ThisKeyword */, 94 /* NewKeyword */]; + var unaryPostincrementExpressions = [71 /* Identifier */, 20 /* CloseParenToken */, 22 /* CloseBracketToken */, 94 /* NewKeyword */]; + var unaryPredecrementExpressions = [71 /* Identifier */, 19 /* OpenParenToken */, 99 /* ThisKeyword */, 94 /* NewKeyword */]; + var unaryPostdecrementExpressions = [71 /* Identifier */, 20 /* CloseParenToken */, 22 /* CloseBracketToken */, 94 /* NewKeyword */]; + var comments = [2 /* SingleLineCommentTrivia */, 3 /* MultiLineCommentTrivia */]; + var typeNames = [71 /* Identifier */].concat(ts.typeKeywords); + // Place a space before open brace in a function declaration + // TypeScript: Function can have return types, which can be made of tons of different token kinds var functionOpenBraceLeftTokenRange = anyTokenIncludingMultilineComments; - var typeScriptOpenBraceLeftTokenRange = tokenRangeFrom([71, 3, 75, 84, 91]); - var controlOpenBraceLeftTokenRange = tokenRangeFrom([20, 3, 81, 102, 87, 82]); + // Place a space before open brace in a TypeScript declaration that has braces as children (class, module, enum, etc) + var typeScriptOpenBraceLeftTokenRange = tokenRangeFrom([71 /* Identifier */, 3 /* MultiLineCommentTrivia */, 75 /* ClassKeyword */, 84 /* ExportKeyword */, 91 /* ImportKeyword */]); + // Place a space before open brace in a control flow construct + var controlOpenBraceLeftTokenRange = tokenRangeFrom([20 /* CloseParenToken */, 3 /* MultiLineCommentTrivia */, 81 /* DoKeyword */, 102 /* TryKeyword */, 87 /* FinallyKeyword */, 82 /* ElseKeyword */]); + // These rules are higher in priority than user-configurable var highPriorityCommonRules = [ - rule("IgnoreBeforeComment", anyToken, comments, formatting.anyContext, 1), - rule("IgnoreAfterLineComment", 2, anyToken, formatting.anyContext, 1), - rule("NotSpaceBeforeColon", anyToken, 56, [isNonJsxSameLineTokenContext, isNotBinaryOpContext, isNotTypeAnnotationContext], 8), - rule("SpaceAfterColon", 56, anyToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 2), - rule("NoSpaceBeforeQuestionMark", anyToken, 55, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 8), - rule("SpaceAfterQuestionMarkInConditionalOperator", 55, anyToken, [isNonJsxSameLineTokenContext, isConditionalOperatorContext], 2), - rule("NoSpaceAfterQuestionMark", 55, anyToken, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceBeforeDot", anyToken, 23, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceAfterDot", 23, anyToken, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceBetweenImportParenInImportType", 91, 19, [isNonJsxSameLineTokenContext, isImportTypeContext], 8), - rule("NoSpaceAfterUnaryPrefixOperator", unaryPrefixOperators, unaryPrefixExpressions, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 8), - rule("NoSpaceAfterUnaryPreincrementOperator", 43, unaryPreincrementExpressions, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceAfterUnaryPredecrementOperator", 44, unaryPredecrementExpressions, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceBeforeUnaryPostincrementOperator", unaryPostincrementExpressions, 43, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceBeforeUnaryPostdecrementOperator", unaryPostdecrementExpressions, 44, [isNonJsxSameLineTokenContext], 8), - rule("SpaceAfterPostincrementWhenFollowedByAdd", 43, 37, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2), - rule("SpaceAfterAddWhenFollowedByUnaryPlus", 37, 37, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2), - rule("SpaceAfterAddWhenFollowedByPreincrement", 37, 43, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2), - rule("SpaceAfterPostdecrementWhenFollowedBySubtract", 44, 38, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2), - rule("SpaceAfterSubtractWhenFollowedByUnaryMinus", 38, 38, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2), - rule("SpaceAfterSubtractWhenFollowedByPredecrement", 38, 44, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2), - rule("NoSpaceAfterCloseBrace", 18, [26, 25], [isNonJsxSameLineTokenContext], 8), - rule("NewLineBeforeCloseBraceInBlockContext", anyTokenIncludingMultilineComments, 18, [isMultilineBlockContext], 4), - rule("SpaceAfterCloseBrace", 18, anyTokenExcept(20), [isNonJsxSameLineTokenContext, isAfterCodeBlockContext], 2), - rule("SpaceBetweenCloseBraceAndElse", 18, 82, [isNonJsxSameLineTokenContext], 2), - rule("SpaceBetweenCloseBraceAndWhile", 18, 106, [isNonJsxSameLineTokenContext], 2), - rule("NoSpaceBetweenEmptyBraceBrackets", 17, 18, [isNonJsxSameLineTokenContext, isObjectContext], 8), - rule("SpaceAfterConditionalClosingParen", 20, 21, [isControlDeclContext], 2), - rule("NoSpaceBetweenFunctionKeywordAndStar", 89, 39, [isFunctionDeclarationOrFunctionExpressionContext], 8), - rule("SpaceAfterStarInGeneratorDeclaration", 39, [71, 19], [isFunctionDeclarationOrFunctionExpressionContext], 2), - rule("SpaceAfterFunctionInFuncDecl", 89, anyToken, [isFunctionDeclContext], 2), - rule("NewLineAfterOpenBraceInBlockContext", 17, anyToken, [isMultilineBlockContext], 4), - rule("SpaceAfterGetSetInMember", [125, 136], 71, [isFunctionDeclContext], 2), - rule("NoSpaceBetweenYieldKeywordAndStar", 116, 39, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], 8), - rule("SpaceBetweenYieldOrYieldStarAndOperand", [116, 39], anyToken, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], 2), - rule("NoSpaceBetweenReturnAndSemicolon", 96, 25, [isNonJsxSameLineTokenContext], 8), - rule("SpaceAfterCertainKeywords", [104, 100, 94, 80, 96, 103, 121], anyToken, [isNonJsxSameLineTokenContext], 2), - rule("SpaceAfterLetConstInVariableDeclaration", [110, 76], anyToken, [isNonJsxSameLineTokenContext, isStartOfVariableDeclarationList], 2), - rule("NoSpaceBeforeOpenParenInFuncCall", anyToken, 19, [isNonJsxSameLineTokenContext, isFunctionCallOrNewContext, isPreviousTokenNotComma], 8), - rule("SpaceBeforeBinaryKeywordOperator", anyToken, binaryKeywordOperators, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2), - rule("SpaceAfterBinaryKeywordOperator", binaryKeywordOperators, anyToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2), - rule("SpaceAfterVoidOperator", 105, anyToken, [isNonJsxSameLineTokenContext, isVoidOpContext], 2), - rule("SpaceBetweenAsyncAndOpenParen", 120, 19, [isArrowFunctionContext, isNonJsxSameLineTokenContext], 2), - rule("SpaceBetweenAsyncAndFunctionKeyword", 120, 89, [isNonJsxSameLineTokenContext], 2), - rule("NoSpaceBetweenTagAndTemplateString", [71, 20], [13, 14], [isNonJsxSameLineTokenContext], 8), - rule("SpaceBeforeJsxAttribute", anyToken, 71, [isNextTokenParentJsxAttribute, isNonJsxSameLineTokenContext], 2), - rule("SpaceBeforeSlashInJsxOpeningElement", anyToken, 41, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], 2), - rule("NoSpaceBeforeGreaterThanTokenInJsxOpeningElement", 41, 29, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], 8), - rule("NoSpaceBeforeEqualInJsxAttribute", anyToken, 58, [isJsxAttributeContext, isNonJsxSameLineTokenContext], 8), - rule("NoSpaceAfterEqualInJsxAttribute", 58, anyToken, [isJsxAttributeContext, isNonJsxSameLineTokenContext], 8), - rule("NoSpaceAfterModuleImport", [129, 133], 19, [isNonJsxSameLineTokenContext], 8), + // Leave comments alone + rule("IgnoreBeforeComment", anyToken, comments, formatting.anyContext, 1 /* Ignore */), + rule("IgnoreAfterLineComment", 2 /* SingleLineCommentTrivia */, anyToken, formatting.anyContext, 1 /* Ignore */), + rule("NotSpaceBeforeColon", anyToken, 56 /* ColonToken */, [isNonJsxSameLineTokenContext, isNotBinaryOpContext, isNotTypeAnnotationContext], 8 /* Delete */), + rule("SpaceAfterColon", 56 /* ColonToken */, anyToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 2 /* Space */), + rule("NoSpaceBeforeQuestionMark", anyToken, 55 /* QuestionToken */, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 8 /* Delete */), + // insert space after '?' only when it is used in conditional operator + rule("SpaceAfterQuestionMarkInConditionalOperator", 55 /* QuestionToken */, anyToken, [isNonJsxSameLineTokenContext, isConditionalOperatorContext], 2 /* Space */), + // in other cases there should be no space between '?' and next token + rule("NoSpaceAfterQuestionMark", 55 /* QuestionToken */, anyToken, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceBeforeDot", anyToken, 23 /* DotToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceAfterDot", 23 /* DotToken */, anyToken, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceBetweenImportParenInImportType", 91 /* ImportKeyword */, 19 /* OpenParenToken */, [isNonJsxSameLineTokenContext, isImportTypeContext], 8 /* Delete */), + // Special handling of unary operators. + // Prefix operators generally shouldn't have a space between + // them and their target unary expression. + rule("NoSpaceAfterUnaryPrefixOperator", unaryPrefixOperators, unaryPrefixExpressions, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 8 /* Delete */), + rule("NoSpaceAfterUnaryPreincrementOperator", 43 /* PlusPlusToken */, unaryPreincrementExpressions, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceAfterUnaryPredecrementOperator", 44 /* MinusMinusToken */, unaryPredecrementExpressions, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceBeforeUnaryPostincrementOperator", unaryPostincrementExpressions, 43 /* PlusPlusToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceBeforeUnaryPostdecrementOperator", unaryPostdecrementExpressions, 44 /* MinusMinusToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + // More unary operator special-casing. + // DevDiv 181814: Be careful when removing leading whitespace + // around unary operators. Examples: + // 1 - -2 --X--> 1--2 + // a + ++b --X--> a+++b + rule("SpaceAfterPostincrementWhenFollowedByAdd", 43 /* PlusPlusToken */, 37 /* PlusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */), + rule("SpaceAfterAddWhenFollowedByUnaryPlus", 37 /* PlusToken */, 37 /* PlusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */), + rule("SpaceAfterAddWhenFollowedByPreincrement", 37 /* PlusToken */, 43 /* PlusPlusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */), + rule("SpaceAfterPostdecrementWhenFollowedBySubtract", 44 /* MinusMinusToken */, 38 /* MinusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */), + rule("SpaceAfterSubtractWhenFollowedByUnaryMinus", 38 /* MinusToken */, 38 /* MinusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */), + rule("SpaceAfterSubtractWhenFollowedByPredecrement", 38 /* MinusToken */, 44 /* MinusMinusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */), + rule("NoSpaceAfterCloseBrace", 18 /* CloseBraceToken */, [26 /* CommaToken */, 25 /* SemicolonToken */], [isNonJsxSameLineTokenContext], 8 /* Delete */), + // For functions and control block place } on a new line [multi-line rule] + rule("NewLineBeforeCloseBraceInBlockContext", anyTokenIncludingMultilineComments, 18 /* CloseBraceToken */, [isMultilineBlockContext], 4 /* NewLine */), + // Space/new line after }. + rule("SpaceAfterCloseBrace", 18 /* CloseBraceToken */, anyTokenExcept(20 /* CloseParenToken */), [isNonJsxSameLineTokenContext, isAfterCodeBlockContext], 2 /* Space */), + // Special case for (}, else) and (}, while) since else & while tokens are not part of the tree which makes SpaceAfterCloseBrace rule not applied + // Also should not apply to }) + rule("SpaceBetweenCloseBraceAndElse", 18 /* CloseBraceToken */, 82 /* ElseKeyword */, [isNonJsxSameLineTokenContext], 2 /* Space */), + rule("SpaceBetweenCloseBraceAndWhile", 18 /* CloseBraceToken */, 106 /* WhileKeyword */, [isNonJsxSameLineTokenContext], 2 /* Space */), + rule("NoSpaceBetweenEmptyBraceBrackets", 17 /* OpenBraceToken */, 18 /* CloseBraceToken */, [isNonJsxSameLineTokenContext, isObjectContext], 8 /* Delete */), + // Add a space after control dec context if the next character is an open bracket ex: 'if (false)[a, b] = [1, 2];' -> 'if (false) [a, b] = [1, 2];' + rule("SpaceAfterConditionalClosingParen", 20 /* CloseParenToken */, 21 /* OpenBracketToken */, [isControlDeclContext], 2 /* Space */), + rule("NoSpaceBetweenFunctionKeywordAndStar", 89 /* FunctionKeyword */, 39 /* AsteriskToken */, [isFunctionDeclarationOrFunctionExpressionContext], 8 /* Delete */), + rule("SpaceAfterStarInGeneratorDeclaration", 39 /* AsteriskToken */, [71 /* Identifier */, 19 /* OpenParenToken */], [isFunctionDeclarationOrFunctionExpressionContext], 2 /* Space */), + rule("SpaceAfterFunctionInFuncDecl", 89 /* FunctionKeyword */, anyToken, [isFunctionDeclContext], 2 /* Space */), + // Insert new line after { and before } in multi-line contexts. + rule("NewLineAfterOpenBraceInBlockContext", 17 /* OpenBraceToken */, anyToken, [isMultilineBlockContext], 4 /* NewLine */), + // For get/set members, we check for (identifier,identifier) since get/set don't have tokens and they are represented as just an identifier token. + // Though, we do extra check on the context to make sure we are dealing with get/set node. Example: + // get x() {} + // set x(val) {} + rule("SpaceAfterGetSetInMember", [125 /* GetKeyword */, 136 /* SetKeyword */], 71 /* Identifier */, [isFunctionDeclContext], 2 /* Space */), + rule("NoSpaceBetweenYieldKeywordAndStar", 116 /* YieldKeyword */, 39 /* AsteriskToken */, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], 8 /* Delete */), + rule("SpaceBetweenYieldOrYieldStarAndOperand", [116 /* YieldKeyword */, 39 /* AsteriskToken */], anyToken, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], 2 /* Space */), + rule("NoSpaceBetweenReturnAndSemicolon", 96 /* ReturnKeyword */, 25 /* SemicolonToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("SpaceAfterCertainKeywords", [104 /* VarKeyword */, 100 /* ThrowKeyword */, 94 /* NewKeyword */, 80 /* DeleteKeyword */, 96 /* ReturnKeyword */, 103 /* TypeOfKeyword */, 121 /* AwaitKeyword */], anyToken, [isNonJsxSameLineTokenContext], 2 /* Space */), + rule("SpaceAfterLetConstInVariableDeclaration", [110 /* LetKeyword */, 76 /* ConstKeyword */], anyToken, [isNonJsxSameLineTokenContext, isStartOfVariableDeclarationList], 2 /* Space */), + rule("NoSpaceBeforeOpenParenInFuncCall", anyToken, 19 /* OpenParenToken */, [isNonJsxSameLineTokenContext, isFunctionCallOrNewContext, isPreviousTokenNotComma], 8 /* Delete */), + // Special case for binary operators (that are keywords). For these we have to add a space and shouldn't follow any user options. + rule("SpaceBeforeBinaryKeywordOperator", anyToken, binaryKeywordOperators, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */), + rule("SpaceAfterBinaryKeywordOperator", binaryKeywordOperators, anyToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */), + rule("SpaceAfterVoidOperator", 105 /* VoidKeyword */, anyToken, [isNonJsxSameLineTokenContext, isVoidOpContext], 2 /* Space */), + // Async-await + rule("SpaceBetweenAsyncAndOpenParen", 120 /* AsyncKeyword */, 19 /* OpenParenToken */, [isArrowFunctionContext, isNonJsxSameLineTokenContext], 2 /* Space */), + rule("SpaceBetweenAsyncAndFunctionKeyword", 120 /* AsyncKeyword */, 89 /* FunctionKeyword */, [isNonJsxSameLineTokenContext], 2 /* Space */), + // Template string + rule("NoSpaceBetweenTagAndTemplateString", [71 /* Identifier */, 20 /* CloseParenToken */], [13 /* NoSubstitutionTemplateLiteral */, 14 /* TemplateHead */], [isNonJsxSameLineTokenContext], 8 /* Delete */), + // JSX opening elements + rule("SpaceBeforeJsxAttribute", anyToken, 71 /* Identifier */, [isNextTokenParentJsxAttribute, isNonJsxSameLineTokenContext], 2 /* Space */), + rule("SpaceBeforeSlashInJsxOpeningElement", anyToken, 41 /* SlashToken */, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], 2 /* Space */), + rule("NoSpaceBeforeGreaterThanTokenInJsxOpeningElement", 41 /* SlashToken */, 29 /* GreaterThanToken */, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceBeforeEqualInJsxAttribute", anyToken, 58 /* EqualsToken */, [isJsxAttributeContext, isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceAfterEqualInJsxAttribute", 58 /* EqualsToken */, anyToken, [isJsxAttributeContext, isNonJsxSameLineTokenContext], 8 /* Delete */), + // TypeScript-specific rules + // Use of module as a function call. e.g.: import m2 = module("m2"); + rule("NoSpaceAfterModuleImport", [129 /* ModuleKeyword */, 133 /* RequireKeyword */], 19 /* OpenParenToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + // Add a space around certain TypeScript keywords rule("SpaceAfterCertainTypeScriptKeywords", [ - 117, - 75, - 124, - 79, - 83, - 84, - 85, - 125, - 108, - 91, - 109, - 129, - 130, - 112, - 114, - 113, - 132, - 136, - 115, - 139, - 143, - 128, - 126, - ], anyToken, [isNonJsxSameLineTokenContext], 2), - rule("SpaceBeforeCertainTypeScriptKeywords", anyToken, [85, 108, 143], [isNonJsxSameLineTokenContext], 2), - rule("SpaceAfterModuleName", 9, 17, [isModuleDeclContext], 2), - rule("SpaceBeforeArrow", anyToken, 36, [isNonJsxSameLineTokenContext], 2), - rule("SpaceAfterArrow", 36, anyToken, [isNonJsxSameLineTokenContext], 2), - rule("NoSpaceAfterEllipsis", 24, 71, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceAfterOptionalParameters", 55, [20, 26], [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 8), - rule("NoSpaceBetweenEmptyInterfaceBraceBrackets", 17, 18, [isNonJsxSameLineTokenContext, isObjectTypeContext], 8), - rule("NoSpaceBeforeOpenAngularBracket", typeNames, 27, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8), - rule("NoSpaceBetweenCloseParenAndAngularBracket", 20, 27, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8), - rule("NoSpaceAfterOpenAngularBracket", 27, anyToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8), - rule("NoSpaceBeforeCloseAngularBracket", anyToken, 29, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8), - rule("NoSpaceAfterCloseAngularBracket", 29, [19, 21, 29, 26], [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext, isNotFunctionDeclContext], 8), - rule("SpaceBeforeAt", [20, 71], 57, [isNonJsxSameLineTokenContext], 2), - rule("NoSpaceAfterAt", 57, anyToken, [isNonJsxSameLineTokenContext], 8), + 117 /* AbstractKeyword */, + 75 /* ClassKeyword */, + 124 /* DeclareKeyword */, + 79 /* DefaultKeyword */, + 83 /* EnumKeyword */, + 84 /* ExportKeyword */, + 85 /* ExtendsKeyword */, + 125 /* GetKeyword */, + 108 /* ImplementsKeyword */, + 91 /* ImportKeyword */, + 109 /* InterfaceKeyword */, + 129 /* ModuleKeyword */, + 130 /* NamespaceKeyword */, + 112 /* PrivateKeyword */, + 114 /* PublicKeyword */, + 113 /* ProtectedKeyword */, + 132 /* ReadonlyKeyword */, + 136 /* SetKeyword */, + 115 /* StaticKeyword */, + 139 /* TypeKeyword */, + 143 /* FromKeyword */, + 128 /* KeyOfKeyword */, + 126 /* InferKeyword */, + ], anyToken, [isNonJsxSameLineTokenContext], 2 /* Space */), + rule("SpaceBeforeCertainTypeScriptKeywords", anyToken, [85 /* ExtendsKeyword */, 108 /* ImplementsKeyword */, 143 /* FromKeyword */], [isNonJsxSameLineTokenContext], 2 /* Space */), + // Treat string literals in module names as identifiers, and add a space between the literal and the opening Brace braces, e.g.: module "m2" { + rule("SpaceAfterModuleName", 9 /* StringLiteral */, 17 /* OpenBraceToken */, [isModuleDeclContext], 2 /* Space */), + // Lambda expressions + rule("SpaceBeforeArrow", anyToken, 36 /* EqualsGreaterThanToken */, [isNonJsxSameLineTokenContext], 2 /* Space */), + rule("SpaceAfterArrow", 36 /* EqualsGreaterThanToken */, anyToken, [isNonJsxSameLineTokenContext], 2 /* Space */), + // Optional parameters and let args + rule("NoSpaceAfterEllipsis", 24 /* DotDotDotToken */, 71 /* Identifier */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceAfterOptionalParameters", 55 /* QuestionToken */, [20 /* CloseParenToken */, 26 /* CommaToken */], [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 8 /* Delete */), + // Remove spaces in empty interface literals. e.g.: x: {} + rule("NoSpaceBetweenEmptyInterfaceBraceBrackets", 17 /* OpenBraceToken */, 18 /* CloseBraceToken */, [isNonJsxSameLineTokenContext, isObjectTypeContext], 8 /* Delete */), + // generics and type assertions + rule("NoSpaceBeforeOpenAngularBracket", typeNames, 27 /* LessThanToken */, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8 /* Delete */), + rule("NoSpaceBetweenCloseParenAndAngularBracket", 20 /* CloseParenToken */, 27 /* LessThanToken */, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8 /* Delete */), + rule("NoSpaceAfterOpenAngularBracket", 27 /* LessThanToken */, anyToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8 /* Delete */), + rule("NoSpaceBeforeCloseAngularBracket", anyToken, 29 /* GreaterThanToken */, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8 /* Delete */), + rule("NoSpaceAfterCloseAngularBracket", 29 /* GreaterThanToken */, [19 /* OpenParenToken */, 21 /* OpenBracketToken */, 29 /* GreaterThanToken */, 26 /* CommaToken */], [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext, isNotFunctionDeclContext /*To prevent an interference with the SpaceBeforeOpenParenInFuncDecl rule*/], 8 /* Delete */), + // decorators + rule("SpaceBeforeAt", [20 /* CloseParenToken */, 71 /* Identifier */], 57 /* AtToken */, [isNonJsxSameLineTokenContext], 2 /* Space */), + rule("NoSpaceAfterAt", 57 /* AtToken */, anyToken, [isNonJsxSameLineTokenContext], 8 /* Delete */), + // Insert space after @ in decorator rule("SpaceAfterDecorator", anyToken, [ - 117, - 71, - 84, - 79, - 75, - 115, - 114, - 112, - 113, - 125, - 136, - 21, - 39, - ], [isEndOfDecoratorContextOnSameLine], 2), - rule("NoSpaceBeforeNonNullAssertionOperator", anyToken, 51, [isNonJsxSameLineTokenContext, isNonNullAssertionContext], 8), - rule("NoSpaceAfterNewKeywordOnConstructorSignature", 94, 19, [isNonJsxSameLineTokenContext, isConstructorSignatureContext], 8), + 117 /* AbstractKeyword */, + 71 /* Identifier */, + 84 /* ExportKeyword */, + 79 /* DefaultKeyword */, + 75 /* ClassKeyword */, + 115 /* StaticKeyword */, + 114 /* PublicKeyword */, + 112 /* PrivateKeyword */, + 113 /* ProtectedKeyword */, + 125 /* GetKeyword */, + 136 /* SetKeyword */, + 21 /* OpenBracketToken */, + 39 /* AsteriskToken */, + ], [isEndOfDecoratorContextOnSameLine], 2 /* Space */), + rule("NoSpaceBeforeNonNullAssertionOperator", anyToken, 51 /* ExclamationToken */, [isNonJsxSameLineTokenContext, isNonNullAssertionContext], 8 /* Delete */), + rule("NoSpaceAfterNewKeywordOnConstructorSignature", 94 /* NewKeyword */, 19 /* OpenParenToken */, [isNonJsxSameLineTokenContext, isConstructorSignatureContext], 8 /* Delete */), ]; + // These rules are applied after high priority var userConfigurableRules = [ - rule("SpaceAfterConstructor", 123, 19, [isOptionEnabled("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], 2), - rule("NoSpaceAfterConstructor", 123, 19, [isOptionDisabledOrUndefined("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], 8), - rule("SpaceAfterComma", 26, anyToken, [isOptionEnabled("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNextTokenNotCloseBracket], 2), - rule("NoSpaceAfterComma", 26, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext], 8), - rule("SpaceAfterAnonymousFunctionKeyword", 89, 19, [isOptionEnabled("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], 2), - rule("NoSpaceAfterAnonymousFunctionKeyword", 89, 19, [isOptionDisabledOrUndefined("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], 8), - rule("SpaceAfterKeywordInControl", keywords, 19, [isOptionEnabled("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], 2), - rule("NoSpaceAfterKeywordInControl", keywords, 19, [isOptionDisabledOrUndefined("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], 8), - rule("SpaceAfterOpenParen", 19, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 2), - rule("SpaceBeforeCloseParen", anyToken, 20, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 2), - rule("SpaceBetweenOpenParens", 19, 19, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 2), - rule("NoSpaceBetweenParens", 19, 20, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceAfterOpenParen", 19, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 8), - rule("NoSpaceBeforeCloseParen", anyToken, 20, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 8), - rule("SpaceAfterOpenBracket", 21, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 2), - rule("SpaceBeforeCloseBracket", anyToken, 22, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 2), - rule("NoSpaceBetweenBrackets", 21, 22, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceAfterOpenBracket", 21, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 8), - rule("NoSpaceBeforeCloseBracket", anyToken, 22, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 8), - rule("SpaceAfterOpenBrace", 17, anyToken, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], 2), - rule("SpaceBeforeCloseBrace", anyToken, 18, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], 2), - rule("NoSpaceBetweenEmptyBraceBrackets", 17, 18, [isNonJsxSameLineTokenContext, isObjectContext], 8), - rule("NoSpaceAfterOpenBrace", 17, anyToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], 8), - rule("NoSpaceBeforeCloseBrace", anyToken, 18, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], 8), - rule("SpaceAfterTemplateHeadAndMiddle", [14, 15], anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 2), - rule("SpaceBeforeTemplateMiddleAndTail", anyToken, [15, 16], [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 2), - rule("NoSpaceAfterTemplateHeadAndMiddle", [14, 15], anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 8), - rule("NoSpaceBeforeTemplateMiddleAndTail", anyToken, [15, 16], [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 8), - rule("SpaceAfterOpenBraceInJsxExpression", 17, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 2), - rule("SpaceBeforeCloseBraceInJsxExpression", anyToken, 18, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 2), - rule("NoSpaceAfterOpenBraceInJsxExpression", 17, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 8), - rule("NoSpaceBeforeCloseBraceInJsxExpression", anyToken, 18, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 8), - rule("SpaceAfterSemicolonInFor", 25, anyToken, [isOptionEnabled("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], 2), - rule("NoSpaceAfterSemicolonInFor", 25, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], 8), - rule("SpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 2), - rule("SpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 2), - rule("NoSpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 8), - rule("NoSpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 8), - rule("SpaceBeforeOpenParenInFuncDecl", anyToken, 19, [isOptionEnabled("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], 2), - rule("NoSpaceBeforeOpenParenInFuncDecl", anyToken, 19, [isOptionDisabledOrUndefined("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], 8), - rule("NewLineBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, 17, [isOptionEnabled("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isBeforeMultilineBlockContext], 4, 1), - rule("NewLineBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, 17, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeMultilineBlockContext], 4, 1), - rule("NewLineBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, 17, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isBeforeMultilineBlockContext], 4, 1), - rule("SpaceAfterTypeAssertion", 29, anyToken, [isOptionEnabled("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], 2), - rule("NoSpaceAfterTypeAssertion", 29, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], 8), - rule("SpaceBeforeTypeAnnotation", anyToken, 56, [isOptionEnabled("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], 2), - rule("NoSpaceBeforeTypeAnnotation", anyToken, 56, [isOptionDisabledOrUndefined("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], 8), + // Treat constructor as an identifier in a function declaration, and remove spaces between constructor and following left parentheses + rule("SpaceAfterConstructor", 123 /* ConstructorKeyword */, 19 /* OpenParenToken */, [isOptionEnabled("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], 2 /* Space */), + rule("NoSpaceAfterConstructor", 123 /* ConstructorKeyword */, 19 /* OpenParenToken */, [isOptionDisabledOrUndefined("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("SpaceAfterComma", 26 /* CommaToken */, anyToken, [isOptionEnabled("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNextTokenNotCloseBracket], 2 /* Space */), + rule("NoSpaceAfterComma", 26 /* CommaToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext], 8 /* Delete */), + // Insert space after function keyword for anonymous functions + rule("SpaceAfterAnonymousFunctionKeyword", 89 /* FunctionKeyword */, 19 /* OpenParenToken */, [isOptionEnabled("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], 2 /* Space */), + rule("NoSpaceAfterAnonymousFunctionKeyword", 89 /* FunctionKeyword */, 19 /* OpenParenToken */, [isOptionDisabledOrUndefined("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], 8 /* Delete */), + // Insert space after keywords in control flow statements + rule("SpaceAfterKeywordInControl", keywords, 19 /* OpenParenToken */, [isOptionEnabled("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], 2 /* Space */), + rule("NoSpaceAfterKeywordInControl", keywords, 19 /* OpenParenToken */, [isOptionDisabledOrUndefined("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], 8 /* Delete */), + // Insert space after opening and before closing nonempty parenthesis + rule("SpaceAfterOpenParen", 19 /* OpenParenToken */, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 2 /* Space */), + rule("SpaceBeforeCloseParen", anyToken, 20 /* CloseParenToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 2 /* Space */), + rule("SpaceBetweenOpenParens", 19 /* OpenParenToken */, 19 /* OpenParenToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 2 /* Space */), + rule("NoSpaceBetweenParens", 19 /* OpenParenToken */, 20 /* CloseParenToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceAfterOpenParen", 19 /* OpenParenToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceBeforeCloseParen", anyToken, 20 /* CloseParenToken */, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 8 /* Delete */), + // Insert space after opening and before closing nonempty brackets + rule("SpaceAfterOpenBracket", 21 /* OpenBracketToken */, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 2 /* Space */), + rule("SpaceBeforeCloseBracket", anyToken, 22 /* CloseBracketToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 2 /* Space */), + rule("NoSpaceBetweenBrackets", 21 /* OpenBracketToken */, 22 /* CloseBracketToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceAfterOpenBracket", 21 /* OpenBracketToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceBeforeCloseBracket", anyToken, 22 /* CloseBracketToken */, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 8 /* Delete */), + // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}. + rule("SpaceAfterOpenBrace", 17 /* OpenBraceToken */, anyToken, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], 2 /* Space */), + rule("SpaceBeforeCloseBrace", anyToken, 18 /* CloseBraceToken */, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], 2 /* Space */), + rule("NoSpaceBetweenEmptyBraceBrackets", 17 /* OpenBraceToken */, 18 /* CloseBraceToken */, [isNonJsxSameLineTokenContext, isObjectContext], 8 /* Delete */), + rule("NoSpaceAfterOpenBrace", 17 /* OpenBraceToken */, anyToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceBeforeCloseBrace", anyToken, 18 /* CloseBraceToken */, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], 8 /* Delete */), + // Insert space after opening and before closing template string braces + rule("SpaceAfterTemplateHeadAndMiddle", [14 /* TemplateHead */, 15 /* TemplateMiddle */], anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 2 /* Space */), + rule("SpaceBeforeTemplateMiddleAndTail", anyToken, [15 /* TemplateMiddle */, 16 /* TemplateTail */], [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 2 /* Space */), + rule("NoSpaceAfterTemplateHeadAndMiddle", [14 /* TemplateHead */, 15 /* TemplateMiddle */], anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceBeforeTemplateMiddleAndTail", anyToken, [15 /* TemplateMiddle */, 16 /* TemplateTail */], [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 8 /* Delete */), + // No space after { and before } in JSX expression + rule("SpaceAfterOpenBraceInJsxExpression", 17 /* OpenBraceToken */, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 2 /* Space */), + rule("SpaceBeforeCloseBraceInJsxExpression", anyToken, 18 /* CloseBraceToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 2 /* Space */), + rule("NoSpaceAfterOpenBraceInJsxExpression", 17 /* OpenBraceToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 8 /* Delete */), + rule("NoSpaceBeforeCloseBraceInJsxExpression", anyToken, 18 /* CloseBraceToken */, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 8 /* Delete */), + // Insert space after semicolon in for statement + rule("SpaceAfterSemicolonInFor", 25 /* SemicolonToken */, anyToken, [isOptionEnabled("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], 2 /* Space */), + rule("NoSpaceAfterSemicolonInFor", 25 /* SemicolonToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], 8 /* Delete */), + // Insert space before and after binary operators + rule("SpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */), + rule("SpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */), + rule("NoSpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 8 /* Delete */), + rule("NoSpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 8 /* Delete */), + rule("SpaceBeforeOpenParenInFuncDecl", anyToken, 19 /* OpenParenToken */, [isOptionEnabled("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], 2 /* Space */), + rule("NoSpaceBeforeOpenParenInFuncDecl", anyToken, 19 /* OpenParenToken */, [isOptionDisabledOrUndefined("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], 8 /* Delete */), + // Open Brace braces after control block + rule("NewLineBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, 17 /* OpenBraceToken */, [isOptionEnabled("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isBeforeMultilineBlockContext], 4 /* NewLine */, 1 /* CanDeleteNewLines */), + // Open Brace braces after function + // TypeScript: Function can have return types, which can be made of tons of different token kinds + rule("NewLineBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, 17 /* OpenBraceToken */, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeMultilineBlockContext], 4 /* NewLine */, 1 /* CanDeleteNewLines */), + // Open Brace braces after TypeScript module/class/interface + rule("NewLineBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, 17 /* OpenBraceToken */, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isBeforeMultilineBlockContext], 4 /* NewLine */, 1 /* CanDeleteNewLines */), + rule("SpaceAfterTypeAssertion", 29 /* GreaterThanToken */, anyToken, [isOptionEnabled("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], 2 /* Space */), + rule("NoSpaceAfterTypeAssertion", 29 /* GreaterThanToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], 8 /* Delete */), + rule("SpaceBeforeTypeAnnotation", anyToken, 56 /* ColonToken */, [isOptionEnabled("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], 2 /* Space */), + rule("NoSpaceBeforeTypeAnnotation", anyToken, 56 /* ColonToken */, [isOptionDisabledOrUndefined("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], 8 /* Delete */), ]; + // These rules are lower in priority than user-configurable. Rules earlier in this list have priority over rules later in the list. var lowPriorityCommonRules = [ - rule("NoSpaceBeforeSemicolon", anyToken, 25, [isNonJsxSameLineTokenContext], 8), - rule("SpaceBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, 17, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 2, 1), - rule("SpaceBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, 17, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 2, 1), - rule("SpaceBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, 17, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 2, 1), - rule("NoSpaceBeforeComma", anyToken, 26, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceBeforeOpenBracket", anyTokenExcept(120, 73), 21, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceAfterCloseBracket", 22, anyToken, [isNonJsxSameLineTokenContext, isNotBeforeBlockInFunctionDeclarationContext], 8), - rule("SpaceAfterSemicolon", 25, anyToken, [isNonJsxSameLineTokenContext], 2), - rule("SpaceBetweenForAndAwaitKeyword", 88, 121, [isNonJsxSameLineTokenContext], 2), - rule("SpaceBetweenStatements", [20, 81, 82, 73], anyToken, [isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNotForContext], 2), - rule("SpaceAfterTryFinally", [102, 87], 17, [isNonJsxSameLineTokenContext], 2), + // Space after keyword but not before ; or : or ? + rule("NoSpaceBeforeSemicolon", anyToken, 25 /* SemicolonToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("SpaceBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, 17 /* OpenBraceToken */, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 2 /* Space */, 1 /* CanDeleteNewLines */), + rule("SpaceBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, 17 /* OpenBraceToken */, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 2 /* Space */, 1 /* CanDeleteNewLines */), + rule("SpaceBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, 17 /* OpenBraceToken */, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 2 /* Space */, 1 /* CanDeleteNewLines */), + rule("NoSpaceBeforeComma", anyToken, 26 /* CommaToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + // No space before and after indexer `x[]` + rule("NoSpaceBeforeOpenBracket", anyTokenExcept(120 /* AsyncKeyword */, 73 /* CaseKeyword */), 21 /* OpenBracketToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceAfterCloseBracket", 22 /* CloseBracketToken */, anyToken, [isNonJsxSameLineTokenContext, isNotBeforeBlockInFunctionDeclarationContext], 8 /* Delete */), + rule("SpaceAfterSemicolon", 25 /* SemicolonToken */, anyToken, [isNonJsxSameLineTokenContext], 2 /* Space */), + // Remove extra space between for and await + rule("SpaceBetweenForAndAwaitKeyword", 88 /* ForKeyword */, 121 /* AwaitKeyword */, [isNonJsxSameLineTokenContext], 2 /* Space */), + // Add a space between statements. All keywords except (do,else,case) has open/close parens after them. + // So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any] + rule("SpaceBetweenStatements", [20 /* CloseParenToken */, 81 /* DoKeyword */, 82 /* ElseKeyword */, 73 /* CaseKeyword */], anyToken, [isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNotForContext], 2 /* Space */), + // This low-pri rule takes care of "try {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter. + rule("SpaceAfterTryFinally", [102 /* TryKeyword */, 87 /* FinallyKeyword */], 17 /* OpenBraceToken */, [isNonJsxSameLineTokenContext], 2 /* Space */), ]; return highPriorityCommonRules.concat(userConfigurableRules, lowPriorityCommonRules); } formatting.getAllRules = getAllRules; function rule(debugName, left, right, context, action, flags) { - if (flags === void 0) { flags = 0; } + if (flags === void 0) { flags = 0 /* None */; } return { leftTokenRange: toTokenRange(left), rightTokenRange: toTokenRange(right), rule: { debugName: debugName, context: context, action: action, flags: flags } }; } function tokenRangeFrom(tokens) { @@ -83228,6 +99692,9 @@ var ts; } return tokenRangeFrom(tokens); } + /// + /// Contexts + /// function isOptionEnabled(optionName) { return function (context) { return context.options && context.options.hasOwnProperty(optionName) && !!context.options[optionName]; }; } @@ -83244,37 +99711,45 @@ var ts; return function (context) { return !context.options || !context.options.hasOwnProperty(optionName) || !!context.options[optionName]; }; } function isForContext(context) { - return context.contextNode.kind === 220; + return context.contextNode.kind === 220 /* ForStatement */; } function isNotForContext(context) { return !isForContext(context); } function isBinaryOpContext(context) { switch (context.contextNode.kind) { - case 200: - case 201: - case 171: - case 208: - case 252: - case 248: - case 161: - case 169: - case 170: + case 200 /* BinaryExpression */: + case 201 /* ConditionalExpression */: + case 171 /* ConditionalType */: + case 208 /* AsExpression */: + case 252 /* ExportSpecifier */: + case 248 /* ImportSpecifier */: + case 161 /* TypePredicate */: + case 169 /* UnionType */: + case 170 /* IntersectionType */: return true; - case 182: - case 237: - case 243: - case 232: - case 149: - case 273: - case 152: - case 151: - return context.currentTokenSpan.kind === 58 || context.nextTokenSpan.kind === 58; - case 221: - case 148: - return context.currentTokenSpan.kind === 92 || context.nextTokenSpan.kind === 92; - case 222: - return context.currentTokenSpan.kind === 145 || context.nextTokenSpan.kind === 145; + // equals in binding elements: function foo([[x, y] = [1, 2]]) + case 182 /* BindingElement */: + // equals in type X = ... + case 237 /* TypeAliasDeclaration */: + // equal in import a = module('a'); + case 243 /* ImportEqualsDeclaration */: + // equal in let a = 0; + case 232 /* VariableDeclaration */: + // equal in p = 0; + case 149 /* Parameter */: + case 273 /* EnumMember */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + return context.currentTokenSpan.kind === 58 /* EqualsToken */ || context.nextTokenSpan.kind === 58 /* EqualsToken */; + // "in" keyword in for (let x in []) { } + case 221 /* ForInStatement */: + // "in" keyword in [P in keyof T]: T[P] + case 148 /* TypeParameter */: + return context.currentTokenSpan.kind === 92 /* InKeyword */ || context.nextTokenSpan.kind === 92 /* InKeyword */; + // Technically, "of" is not a binary operator, but format it the same way as "in" + case 222 /* ForOfStatement */: + return context.currentTokenSpan.kind === 145 /* OfKeyword */ || context.nextTokenSpan.kind === 145 /* OfKeyword */; } return false; } @@ -83286,24 +99761,25 @@ var ts; } function isTypeAnnotationContext(context) { var contextKind = context.contextNode.kind; - return contextKind === 152 || - contextKind === 151 || - contextKind === 149 || - contextKind === 232 || + return contextKind === 152 /* PropertyDeclaration */ || + contextKind === 151 /* PropertySignature */ || + contextKind === 149 /* Parameter */ || + contextKind === 232 /* VariableDeclaration */ || ts.isFunctionLikeKind(contextKind); } function isConditionalOperatorContext(context) { - return context.contextNode.kind === 201 || - context.contextNode.kind === 171; + return context.contextNode.kind === 201 /* ConditionalExpression */ || + context.contextNode.kind === 171 /* ConditionalType */; } function isSameLineTokenOrBeforeBlockContext(context) { return context.TokensAreOnSameLine() || isBeforeBlockContext(context); } function isBraceWrappedContext(context) { - return context.contextNode.kind === 180 || - context.contextNode.kind === 177 || + return context.contextNode.kind === 180 /* ObjectBindingPattern */ || + context.contextNode.kind === 177 /* MappedType */ || isSingleLineBlockContext(context); } + // This check is done before an open brace in a control construct, a function, or a typescript block declaration function isBeforeMultilineBlockContext(context) { return isBeforeBlockContext(context) && !(context.NextNodeAllOnSameLine() || context.NextNodeBlockIsOnOneLine()); } @@ -83319,31 +99795,38 @@ var ts; function isBeforeBlockContext(context) { return nodeIsBlockContext(context.nextTokenParent); } + // IMPORTANT!!! This method must return true ONLY for nodes with open and close braces as immediate children function nodeIsBlockContext(node) { if (nodeIsTypeScriptDeclWithBlockContext(node)) { + // This means we are in a context that looks like a block to the user, but in the grammar is actually not a node (it's a class, module, enum, object type literal, etc). return true; } switch (node.kind) { - case 213: - case 241: - case 184: - case 240: + case 213 /* Block */: + case 241 /* CaseBlock */: + case 184 /* ObjectLiteralExpression */: + case 240 /* ModuleBlock */: return true; } return false; } function isFunctionDeclContext(context) { switch (context.contextNode.kind) { - case 234: - case 154: - case 153: - case 156: - case 157: - case 158: - case 192: - case 155: - case 193: - case 236: + case 234 /* FunctionDeclaration */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + // case SyntaxKind.MemberFunctionDeclaration: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + // case SyntaxKind.MethodSignature: + case 158 /* CallSignature */: + case 192 /* FunctionExpression */: + case 155 /* Constructor */: + case 193 /* ArrowFunction */: + // case SyntaxKind.ConstructorDeclaration: + // case SyntaxKind.SimpleArrowFunctionExpression: + // case SyntaxKind.ParenthesizedArrowFunctionExpression: + case 236 /* InterfaceDeclaration */: // This one is not truly a function, but for formatting purposes, it acts just like one return true; } return false; @@ -83352,39 +99835,40 @@ var ts; return !isFunctionDeclContext(context); } function isFunctionDeclarationOrFunctionExpressionContext(context) { - return context.contextNode.kind === 234 || context.contextNode.kind === 192; + return context.contextNode.kind === 234 /* FunctionDeclaration */ || context.contextNode.kind === 192 /* FunctionExpression */; } function isTypeScriptDeclWithBlockContext(context) { return nodeIsTypeScriptDeclWithBlockContext(context.contextNode); } function nodeIsTypeScriptDeclWithBlockContext(node) { switch (node.kind) { - case 235: - case 205: - case 236: - case 238: - case 166: - case 239: - case 250: - case 251: - case 244: - case 247: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 236 /* InterfaceDeclaration */: + case 238 /* EnumDeclaration */: + case 166 /* TypeLiteral */: + case 239 /* ModuleDeclaration */: + case 250 /* ExportDeclaration */: + case 251 /* NamedExports */: + case 244 /* ImportDeclaration */: + case 247 /* NamedImports */: return true; } return false; } function isAfterCodeBlockContext(context) { switch (context.currentTokenParent.kind) { - case 235: - case 239: - case 238: - case 269: - case 240: - case 227: + case 235 /* ClassDeclaration */: + case 239 /* ModuleDeclaration */: + case 238 /* EnumDeclaration */: + case 269 /* CatchClause */: + case 240 /* ModuleBlock */: + case 227 /* SwitchStatement */: return true; - case 213: { + case 213 /* Block */: { var blockParent = context.currentTokenParent.parent; - if (!blockParent || blockParent.kind !== 193 && blockParent.kind !== 192) { + // In a codefix scenario, we can't rely on parents being set. So just always return true. + if (!blockParent || blockParent.kind !== 193 /* ArrowFunction */ && blockParent.kind !== 192 /* FunctionExpression */) { return true; } } @@ -83393,62 +99877,64 @@ var ts; } function isControlDeclContext(context) { switch (context.contextNode.kind) { - case 217: - case 227: - case 220: - case 221: - case 222: - case 219: - case 230: - case 218: - case 226: - case 269: + case 217 /* IfStatement */: + case 227 /* SwitchStatement */: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 219 /* WhileStatement */: + case 230 /* TryStatement */: + case 218 /* DoStatement */: + case 226 /* WithStatement */: + // TODO + // case SyntaxKind.ElseClause: + case 269 /* CatchClause */: return true; default: return false; } } function isObjectContext(context) { - return context.contextNode.kind === 184; + return context.contextNode.kind === 184 /* ObjectLiteralExpression */; } function isFunctionCallContext(context) { - return context.contextNode.kind === 187; + return context.contextNode.kind === 187 /* CallExpression */; } function isNewContext(context) { - return context.contextNode.kind === 188; + return context.contextNode.kind === 188 /* NewExpression */; } function isFunctionCallOrNewContext(context) { return isFunctionCallContext(context) || isNewContext(context); } function isPreviousTokenNotComma(context) { - return context.currentTokenSpan.kind !== 26; + return context.currentTokenSpan.kind !== 26 /* CommaToken */; } function isNextTokenNotCloseBracket(context) { - return context.nextTokenSpan.kind !== 22; + return context.nextTokenSpan.kind !== 22 /* CloseBracketToken */; } function isArrowFunctionContext(context) { - return context.contextNode.kind === 193; + return context.contextNode.kind === 193 /* ArrowFunction */; } function isImportTypeContext(context) { - return context.contextNode.kind === 179; + return context.contextNode.kind === 179 /* ImportType */; } function isNonJsxSameLineTokenContext(context) { - return context.TokensAreOnSameLine() && context.contextNode.kind !== 10; + return context.TokensAreOnSameLine() && context.contextNode.kind !== 10 /* JsxText */; } function isNonJsxElementOrFragmentContext(context) { - return context.contextNode.kind !== 255 && context.contextNode.kind !== 259; + return context.contextNode.kind !== 255 /* JsxElement */ && context.contextNode.kind !== 259 /* JsxFragment */; } function isJsxExpressionContext(context) { - return context.contextNode.kind === 265 || context.contextNode.kind === 264; + return context.contextNode.kind === 265 /* JsxExpression */ || context.contextNode.kind === 264 /* JsxSpreadAttribute */; } function isNextTokenParentJsxAttribute(context) { - return context.nextTokenParent.kind === 262; + return context.nextTokenParent.kind === 262 /* JsxAttribute */; } function isJsxAttributeContext(context) { - return context.contextNode.kind === 262; + return context.contextNode.kind === 262 /* JsxAttribute */; } function isJsxSelfClosingElementContext(context) { - return context.contextNode.kind === 256; + return context.contextNode.kind === 256 /* JsxSelfClosingElement */; } function isNotBeforeBlockInFunctionDeclarationContext(context) { return !isFunctionDeclContext(context) && !isBeforeBlockContext(context); @@ -83463,45 +99949,45 @@ var ts; while (ts.isExpressionNode(node)) { node = node.parent; } - return node.kind === 150; + return node.kind === 150 /* Decorator */; } function isStartOfVariableDeclarationList(context) { - return context.currentTokenParent.kind === 233 && + return context.currentTokenParent.kind === 233 /* VariableDeclarationList */ && context.currentTokenParent.getStart(context.sourceFile) === context.currentTokenSpan.pos; } function isNotFormatOnEnter(context) { - return context.formattingRequestKind !== 2; + return context.formattingRequestKind !== 2 /* FormatOnEnter */; } function isModuleDeclContext(context) { - return context.contextNode.kind === 239; + return context.contextNode.kind === 239 /* ModuleDeclaration */; } function isObjectTypeContext(context) { - return context.contextNode.kind === 166; + return context.contextNode.kind === 166 /* TypeLiteral */; // && context.contextNode.parent.kind !== SyntaxKind.InterfaceDeclaration; } function isConstructorSignatureContext(context) { - return context.contextNode.kind === 159; + return context.contextNode.kind === 159 /* ConstructSignature */; } function isTypeArgumentOrParameterOrAssertion(token, parent) { - if (token.kind !== 27 && token.kind !== 29) { + if (token.kind !== 27 /* LessThanToken */ && token.kind !== 29 /* GreaterThanToken */) { return false; } switch (parent.kind) { - case 162: - case 190: - case 237: - case 235: - case 205: - case 236: - case 234: - case 192: - case 193: - case 154: - case 153: - case 158: - case 159: - case 187: - case 188: - case 207: + case 162 /* TypeReference */: + case 190 /* TypeAssertionExpression */: + case 237 /* TypeAliasDeclaration */: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 236 /* InterfaceDeclaration */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 187 /* CallExpression */: + case 188 /* NewExpression */: + case 207 /* ExpressionWithTypeArguments */: return true; default: return false; @@ -83512,19 +99998,20 @@ var ts; isTypeArgumentOrParameterOrAssertion(context.nextTokenSpan, context.nextTokenParent); } function isTypeAssertionContext(context) { - return context.contextNode.kind === 190; + return context.contextNode.kind === 190 /* TypeAssertionExpression */; } function isVoidOpContext(context) { - return context.currentTokenSpan.kind === 105 && context.currentTokenParent.kind === 196; + return context.currentTokenSpan.kind === 105 /* VoidKeyword */ && context.currentTokenParent.kind === 196 /* VoidExpression */; } function isYieldOrYieldStarWithOperand(context) { - return context.contextNode.kind === 203 && context.contextNode.expression !== undefined; + return context.contextNode.kind === 203 /* YieldExpression */ && context.contextNode.expression !== undefined; } function isNonNullAssertionContext(context) { - return context.contextNode.kind === 209; + return context.contextNode.kind === 209 /* NonNullExpression */; } })(formatting = ts.formatting || (ts.formatting = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var formatting; @@ -83548,7 +100035,9 @@ var ts; }; } function buildMap(rules) { + // Map from bucket index to array of rules var map = new Array(mapRowLength * mapRowLength); + // This array is used only during construction of the rulesbucket in the map var rulesBucketConstructionStateList = new Array(map.length); for (var _i = 0, rules_1 = rules; _i < rules_1.length; _i++) { var rule = rules_1[_i]; @@ -83569,12 +100058,12 @@ var ts; return map; } function getRuleBucketIndex(row, column) { - ts.Debug.assert(row <= 145 && column <= 145, "Must compute formatting context from tokens"); + ts.Debug.assert(row <= 145 /* LastKeyword */ && column <= 145 /* LastKeyword */, "Must compute formatting context from tokens"); return (row * mapRowLength) + column; } var maskBitSize = 5; - var mask = 31; - var mapRowLength = 145 + 1; + var mask = 31; // MaskBitSize bits + var mapRowLength = 145 /* LastToken */ + 1; var RulesPosition; (function (RulesPosition) { RulesPosition[RulesPosition["IgnoreRulesSpecific"] = 0] = "IgnoreRulesSpecific"; @@ -83584,8 +100073,23 @@ var ts; RulesPosition[RulesPosition["NoContextRulesSpecific"] = maskBitSize * 4] = "NoContextRulesSpecific"; RulesPosition[RulesPosition["NoContextRulesAny"] = maskBitSize * 5] = "NoContextRulesAny"; })(RulesPosition || (RulesPosition = {})); + // The Rules list contains all the inserted rules into a rulebucket in the following order: + // 1- Ignore rules with specific token combination + // 2- Ignore rules with any token combination + // 3- Context rules with specific token combination + // 4- Context rules with any token combination + // 5- Non-context rules with specific token combination + // 6- Non-context rules with any token combination + // + // The member rulesInsertionIndexBitmap is used to describe the number of rules + // in each sub-bucket (above) hence can be used to know the index of where to insert + // the next rule. It's a bitmap which contains 6 different sections each is given 5 bits. + // + // Example: + // In order to insert a rule to the end of sub-bucket (3), we get the index by adding + // the values in the bitmap segments 3rd, 2nd, and 1st. function addRule(rules, rule, specificTokens, constructionState, rulesBucketIndex) { - var position = rule.action === 1 + var position = rule.action === 1 /* Ignore */ ? specificTokens ? RulesPosition.IgnoreRulesSpecific : RulesPosition.IgnoreRulesAny : rule.context !== formatting.anyContext ? specificTokens ? RulesPosition.ContextRulesSpecific : RulesPosition.ContextRulesAny @@ -83609,6 +100113,7 @@ var ts; } })(formatting = ts.formatting || (ts.formatting = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var formatting; @@ -83622,42 +100127,64 @@ var ts; if (line === 0) { return []; } + // After the enter key, the cursor is now at a new line. The new line may or may not contain non-whitespace characters. + // If the new line has only whitespaces, we won't want to format this line, because that would remove the indentation as + // trailing whitespaces. So the end of the formatting span should be the later one between: + // 1. the end of the previous line + // 2. the last non-whitespace character in the current line var endOfFormatSpan = ts.getEndLinePosition(line, sourceFile); while (ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(endOfFormatSpan))) { endOfFormatSpan--; } + // if the character at the end of the span is a line break, we shouldn't include it, because it indicates we don't want to + // touch the current line at all. Also, on some OSes the line break consists of two characters (\r\n), we should test if the + // previous character before the end of format span is line break character as well. if (ts.isLineBreak(sourceFile.text.charCodeAt(endOfFormatSpan))) { endOfFormatSpan--; } var span = { + // get start position for the previous line pos: ts.getStartPositionOfLine(line - 1, sourceFile), + // end value is exclusive so add 1 to the result end: endOfFormatSpan + 1 }; - return formatSpan(span, sourceFile, formatContext, 2); + return formatSpan(span, sourceFile, formatContext, 2 /* FormatOnEnter */); } formatting.formatOnEnter = formatOnEnter; function formatOnSemicolon(position, sourceFile, formatContext) { - var semicolon = findImmediatelyPrecedingTokenOfKind(position, 25, sourceFile); - return formatNodeLines(findOutermostNodeWithinListLevel(semicolon), sourceFile, formatContext, 3); + var semicolon = findImmediatelyPrecedingTokenOfKind(position, 25 /* SemicolonToken */, sourceFile); + return formatNodeLines(findOutermostNodeWithinListLevel(semicolon), sourceFile, formatContext, 3 /* FormatOnSemicolon */); } formatting.formatOnSemicolon = formatOnSemicolon; function formatOnOpeningCurly(position, sourceFile, formatContext) { - var openingCurly = findImmediatelyPrecedingTokenOfKind(position, 17, sourceFile); + var openingCurly = findImmediatelyPrecedingTokenOfKind(position, 17 /* OpenBraceToken */, sourceFile); if (!openingCurly) { return []; } var curlyBraceRange = openingCurly.parent; var outermostNode = findOutermostNodeWithinListLevel(curlyBraceRange); + /** + * We limit the span to end at the opening curly to handle the case where + * the brace matched to that just typed will be incorrect after further edits. + * For example, we could type the opening curly for the following method + * body without brace-matching activated: + * ``` + * class C { + * foo() + * } + * ``` + * and we wouldn't want to move the closing brace. + */ var textRange = { pos: ts.getLineStartPositionForPosition(outermostNode.getStart(sourceFile), sourceFile), end: position }; - return formatSpan(textRange, sourceFile, formatContext, 4); + return formatSpan(textRange, sourceFile, formatContext, 4 /* FormatOnOpeningCurlyBrace */); } formatting.formatOnOpeningCurly = formatOnOpeningCurly; function formatOnClosingCurly(position, sourceFile, formatContext) { - var precedingToken = findImmediatelyPrecedingTokenOfKind(position, 18, sourceFile); - return formatNodeLines(findOutermostNodeWithinListLevel(precedingToken), sourceFile, formatContext, 5); + var precedingToken = findImmediatelyPrecedingTokenOfKind(position, 18 /* CloseBraceToken */, sourceFile); + return formatNodeLines(findOutermostNodeWithinListLevel(precedingToken), sourceFile, formatContext, 5 /* FormatOnClosingCurlyBrace */); } formatting.formatOnClosingCurly = formatOnClosingCurly; function formatDocument(sourceFile, formatContext) { @@ -83665,23 +100192,41 @@ var ts; pos: 0, end: sourceFile.text.length }; - return formatSpan(span, sourceFile, formatContext, 0); + return formatSpan(span, sourceFile, formatContext, 0 /* FormatDocument */); } formatting.formatDocument = formatDocument; function formatSelection(start, end, sourceFile, formatContext) { + // format from the beginning of the line var span = { pos: ts.getLineStartPositionForPosition(start, sourceFile), end: end, }; - return formatSpan(span, sourceFile, formatContext, 1); + return formatSpan(span, sourceFile, formatContext, 1 /* FormatSelection */); } formatting.formatSelection = formatSelection; + /** + * Validating `expectedTokenKind` ensures the token was typed in the context we expect (eg: not a comment). + * @param expectedTokenKind The kind of the last token constituting the desired parent node. + */ function findImmediatelyPrecedingTokenOfKind(end, expectedTokenKind, sourceFile) { var precedingToken = ts.findPrecedingToken(end, sourceFile); return precedingToken && precedingToken.kind === expectedTokenKind && end === precedingToken.getEnd() ? precedingToken : undefined; } + /** + * Finds the highest node enclosing `node` at the same list level as `node` + * and whose end does not exceed `node.end`. + * + * Consider typing the following + * ``` + * let x = 1; + * while (true) { + * } + * ``` + * Upon typing the closing curly, we want to format the entire `while`-statement, but not the preceding + * variable declaration. + */ function findOutermostNodeWithinListLevel(node) { var current = node; while (current && @@ -83692,23 +100237,26 @@ var ts; } return current; } + // Returns true if node is a element in some list in parent + // i.e. parent is class declaration with the list of members and node is one of members. function isListElement(parent, node) { switch (parent.kind) { - case 235: - case 236: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: return ts.rangeContainsRange(parent.members, node); - case 239: + case 239 /* ModuleDeclaration */: var body = parent.body; - return !!body && body.kind === 240 && ts.rangeContainsRange(body.statements, node); - case 274: - case 213: - case 240: + return !!body && body.kind === 240 /* ModuleBlock */ && ts.rangeContainsRange(body.statements, node); + case 274 /* SourceFile */: + case 213 /* Block */: + case 240 /* ModuleBlock */: return ts.rangeContainsRange(parent.statements, node); - case 269: + case 269 /* CatchClause */: return ts.rangeContainsRange(parent.block.statements, node); } return false; } + /** find node that fully contains given text range */ function findEnclosingNode(range, sourceFile) { return find(sourceFile); function find(n) { @@ -83722,27 +100270,37 @@ var ts; return n; } } + /** formatting is not applied to ranges that contain parse errors. + * This function will return a predicate that for a given text range will tell + * if there are any parse errors that overlap with the range. + */ function prepareRangeContainsErrorFunction(errors, originalRange) { if (!errors.length) { return rangeHasNoErrors; } + // pick only errors that fall in range var sorted = errors - .filter(function (d) { return ts.rangeOverlapsWithStartEnd(originalRange, d.start, d.start + d.length); }) + .filter(function (d) { return ts.rangeOverlapsWithStartEnd(originalRange, d.start, d.start + d.length); }) // TODO: GH#18217 .sort(function (e1, e2) { return e1.start - e2.start; }); if (!sorted.length) { return rangeHasNoErrors; } var index = 0; return function (r) { + // in current implementation sequence of arguments [r1, r2...] is monotonically increasing. + // 'index' tracks the index of the most recent error that was checked. while (true) { if (index >= sorted.length) { + // all errors in the range were already checked -> no error in specified range return false; } var error = sorted[index]; if (r.end <= error.start) { + // specified range ends before the error refered by 'index' - no error in range return false; } if (ts.startEndOverlapsWithStartEnd(r.pos, r.end, error.start, error.start + error.length)) { + // specified range overlaps with error range return true; } index++; @@ -83752,6 +100310,11 @@ var ts; return false; } } + /** + * Start of the original range might fall inside the comment - scanner will not yield appropriate results + * This function will look for token that is located before the start of target range + * and return its end as start position for the scanner. + */ function getScanStartPosition(enclosingNode, originalRange, sourceFile) { var start = enclosingNode.getStart(sourceFile); if (start === originalRange.pos && enclosingNode.end === originalRange.end) { @@ -83759,19 +100322,37 @@ var ts; } var precedingToken = ts.findPrecedingToken(originalRange.pos, sourceFile); if (!precedingToken) { + // no preceding token found - start from the beginning of enclosing node return enclosingNode.pos; } + // preceding token ends after the start of original range (i.e when originalRange.pos falls in the middle of literal) + // start from the beginning of enclosingNode to handle the entire 'originalRange' if (precedingToken.end >= originalRange.pos) { return enclosingNode.pos; } return precedingToken.end; } + /* + * For cases like + * if (a || + * b ||$ + * c) {...} + * If we hit Enter at $ we want line ' b ||' to be indented. + * Formatting will be applied to the last two lines. + * Node that fully encloses these lines is binary expression 'a ||...'. + * Initial indentation for this node will be 0. + * Binary expressions don't introduce new indentation scopes, however it is possible + * that some parent node on the same line does - like if statement in this case. + * Note that we are considering parents only from the same line with initial node - + * if parent is on the different line - its delta was already contributed + * to the initial indentation. + */ function getOwnOrInheritedDelta(n, options, sourceFile) { - var previousLine = -1; + var previousLine = -1 /* Unknown */; var child; while (n) { var line = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)).line; - if (previousLine !== -1 && line !== previousLine) { + if (previousLine !== -1 /* Unknown */ && line !== previousLine) { break; } if (formatting.SmartIndenter.shouldIndentChildNode(options, n, child, sourceFile)) { @@ -83783,9 +100364,11 @@ var ts; } return 0; } + /* @internal */ function formatNodeGivenIndentation(node, sourceFileLike, languageVariant, initialIndentation, delta, formatContext) { var range = { pos: 0, end: sourceFileLike.text.length }; - return formatting.getFormattingScanner(sourceFileLike.text, languageVariant, range.pos, range.end, function (scanner) { return formatSpanWorker(range, node, initialIndentation, delta, scanner, formatContext, 1, function (_) { return false; }, sourceFileLike); }); + return formatting.getFormattingScanner(sourceFileLike.text, languageVariant, range.pos, range.end, function (scanner) { return formatSpanWorker(range, node, initialIndentation, delta, scanner, formatContext, 1 /* FormatSelection */, function (_) { return false; }, // assume that node does not have any errors + sourceFileLike); }); } formatting.formatNodeGivenIndentation = formatNodeGivenIndentation; function formatNodeLines(node, sourceFile, formatContext, requestKind) { @@ -83799,11 +100382,13 @@ var ts; return formatSpan(span, sourceFile, formatContext, requestKind); } function formatSpan(originalRange, sourceFile, formatContext, requestKind) { + // find the smallest node that fully wraps the range and compute the initial indentation for the node var enclosingNode = findEnclosingNode(originalRange, sourceFile); return formatting.getFormattingScanner(sourceFile.text, sourceFile.languageVariant, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end, function (scanner) { return formatSpanWorker(originalRange, enclosingNode, formatting.SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, formatContext.options), getOwnOrInheritedDelta(enclosingNode, formatContext.options, sourceFile), scanner, formatContext, requestKind, prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange), sourceFile); }); } function formatSpanWorker(originalRange, enclosingNode, initialIndentation, delta, formattingScanner, _a, requestKind, rangeContainsError, sourceFile) { var options = _a.options, getRule = _a.getRule; + // formatting context is used by rules provider var formattingContext = new formatting.FormattingContext(sourceFile, requestKind, options); var previousRange; var previousParent; @@ -83823,15 +100408,23 @@ var ts; if (!formattingScanner.isOnToken()) { var leadingTrivia = formattingScanner.getCurrentLeadingTrivia(); if (leadingTrivia) { - processTrivia(leadingTrivia, enclosingNode, enclosingNode, undefined); + processTrivia(leadingTrivia, enclosingNode, enclosingNode, /*dynamicIndentation*/ undefined); // TODO: GH#18217 trimTrailingWhitespacesForRemainingRange(); } } return edits; + // local functions + /** Tries to compute the indentation for a list element. + * If list element is not in range then + * function will pick its actual indentation + * so it can be pushed downstream as inherited indentation. + * If list element is in the range - its indentation will be equal + * to inherited indentation from its predecessors. + */ function tryComputeIndentationForListItem(startPos, endPos, parentStartLine, range, inheritedIndentation) { if (ts.rangeOverlapsWithStartEnd(range, startPos, endPos) || - ts.rangeContainsStartEnd(range, startPos, endPos)) { - if (inheritedIndentation !== -1) { + ts.rangeContainsStartEnd(range, startPos, endPos) /* Not to miss zero-range nodes e.g. JsxText */) { + if (inheritedIndentation !== -1 /* Unknown */) { return inheritedIndentation; } } @@ -83840,22 +100433,29 @@ var ts; var startLinePosition = ts.getLineStartPositionForPosition(startPos, sourceFile); var column = formatting.SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, startPos, sourceFile, options); if (startLine !== parentStartLine || startPos === column) { + // Use the base indent size if it is greater than + // the indentation of the inherited predecessor. var baseIndentSize = formatting.SmartIndenter.getBaseIndentation(options); return baseIndentSize > column ? baseIndentSize : column; } } - return -1; + return -1 /* Unknown */; } function computeIndentation(node, startLine, inheritedIndentation, parent, parentDynamicIndentation, effectiveParentStartLine) { var delta = formatting.SmartIndenter.shouldIndentChildNode(options, node) ? options.indentSize : 0; if (effectiveParentStartLine === startLine) { + // if node is located on the same line with the parent + // - inherit indentation from the parent + // - push children if either parent of node itself has non-zero delta return { indentation: startLine === lastIndentedLine ? indentationOnLastIndentedLine : parentDynamicIndentation.getIndentation(), delta: Math.min(options.indentSize, parentDynamicIndentation.getDelta(node) + delta) }; } - else if (inheritedIndentation === -1) { - if (node.kind === 19 && startLine === lastIndentedLine) { + else if (inheritedIndentation === -1 /* Unknown */) { + if (node.kind === 19 /* OpenParenToken */ && startLine === lastIndentedLine) { + // the is used for chaining methods formatting + // - we need to get the indentation on last line and the delta of parent return { indentation: indentationOnLastIndentedLine, delta: parentDynamicIndentation.getDelta(node) }; } else if (formatting.SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile)) { @@ -83874,18 +100474,19 @@ var ts; return node.modifiers[0].kind; } switch (node.kind) { - case 235: return 75; - case 236: return 109; - case 234: return 89; - case 238: return 238; - case 156: return 125; - case 157: return 136; - case 154: + case 235 /* ClassDeclaration */: return 75 /* ClassKeyword */; + case 236 /* InterfaceDeclaration */: return 109 /* InterfaceKeyword */; + case 234 /* FunctionDeclaration */: return 89 /* FunctionKeyword */; + case 238 /* EnumDeclaration */: return 238 /* EnumDeclaration */; + case 156 /* GetAccessor */: return 125 /* GetKeyword */; + case 157 /* SetAccessor */: return 136 /* SetKeyword */; + case 154 /* MethodDeclaration */: if (node.asteriskToken) { - return 39; + return 39 /* AsteriskToken */; } - case 152: - case 149: + // falls through + case 152 /* PropertyDeclaration */: + case 149 /* Parameter */: return ts.getNameOfDeclaration(node).kind; } } @@ -83893,12 +100494,16 @@ var ts; return { getIndentationForComment: function (kind, tokenIndentation, container) { switch (kind) { - case 18: - case 22: - case 20: + // preceding comment to the token that closes the indentation scope inherits the indentation from the scope + // .. { + // // comment + // } + case 18 /* CloseBraceToken */: + case 22 /* CloseBracketToken */: + case 20 /* CloseParenToken */: return indentation + getDelta(container); } - return tokenIndentation !== -1 ? tokenIndentation : indentation; + return tokenIndentation !== -1 /* Unknown */ ? tokenIndentation : indentation; }, getIndentationForToken: function (line, kind, container) { return shouldAddDelta(line, kind, container) ? indentation + getDelta(container) : indentation; @@ -83914,35 +100519,39 @@ var ts; }; function shouldAddDelta(line, kind, container) { switch (kind) { - case 17: - case 18: - case 19: - case 20: - case 82: - case 106: - case 57: + // open and close brace, 'else' and 'while' (in do statement) tokens has indentation of the parent + case 17 /* OpenBraceToken */: + case 18 /* CloseBraceToken */: + case 19 /* OpenParenToken */: + case 20 /* CloseParenToken */: + case 82 /* ElseKeyword */: + case 106 /* WhileKeyword */: + case 57 /* AtToken */: return false; - case 41: - case 29: + case 41 /* SlashToken */: + case 29 /* GreaterThanToken */: switch (container.kind) { - case 257: - case 258: - case 256: + case 257 /* JsxOpeningElement */: + case 258 /* JsxClosingElement */: + case 256 /* JsxSelfClosingElement */: return false; } break; - case 21: - case 22: - if (container.kind !== 177) { + case 21 /* OpenBracketToken */: + case 22 /* CloseBracketToken */: + if (container.kind !== 177 /* MappedType */) { return false; } break; } + // if token line equals to the line of containing node (this is a first token in the node) - use node indentation return nodeStartLine !== line + // if this token is the first token following the list of decorators, we do not need to indent && !(node.decorators && kind === getFirstNonDecoratorTokenOfNode(node)); } function getDelta(child) { - return formatting.SmartIndenter.nodeWillIndentChild(options, node, child, sourceFile, true) ? delta : 0; + // Delta value should be zero when the node explicitly prevents indentation of the child node + return formatting.SmartIndenter.nodeWillIndentChild(options, node, child, sourceFile, /*indentByDefault*/ true) ? delta : 0; } } function processNode(node, contextNode, nodeStartLine, undecoratedNodeStartLine, indentation, delta) { @@ -83950,12 +100559,26 @@ var ts; return; } var nodeDynamicIndentation = getDynamicIndentation(node, nodeStartLine, indentation, delta); + // a useful observations when tracking context node + // / + // [a] + // / | \ + // [b] [c] [d] + // node 'a' is a context node for nodes 'b', 'c', 'd' + // except for the leftmost leaf token in [b] - in this case context node ('e') is located somewhere above 'a' + // this rule can be applied recursively to child nodes of 'a'. + // + // context node is set to parent node value after processing every child node + // context node is set to parent of the token after processing every token var childContextNode = contextNode; + // if there are any tokens that logically belong to node and interleave child nodes + // such tokens will be consumed in processChildNode for the child that follows them ts.forEachChild(node, function (child) { - processChildNode(child, -1, node, nodeDynamicIndentation, nodeStartLine, undecoratedNodeStartLine, false); + processChildNode(child, /*inheritedIndentation*/ -1 /* Unknown */, node, nodeDynamicIndentation, nodeStartLine, undecoratedNodeStartLine, /*isListItem*/ false); }, function (nodes) { processChildNodes(nodes, node, nodeStartLine, nodeDynamicIndentation); }); + // proceed any tokens in the node that are located after child nodes while (formattingScanner.isOnToken()) { var tokenInfo = formattingScanner.readTokenInfo(node); if (tokenInfo.token.end > node.end) { @@ -83970,13 +100593,15 @@ var ts; if (child.decorators) { undecoratedChildStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(child, sourceFile)).line; } - var childIndentationAmount = -1; + // if child is a list item - try to get its indentation, only if parent is within the original range. + var childIndentationAmount = -1 /* Unknown */; if (isListItem && ts.rangeContainsRange(originalRange, parent)) { childIndentationAmount = tryComputeIndentationForListItem(childStartPos, child.end, parentStartLine, originalRange, inheritedIndentation); - if (childIndentationAmount !== -1) { + if (childIndentationAmount !== -1 /* Unknown */) { inheritedIndentation = childIndentationAmount; } } + // child node is outside the target range - do not dive inside if (!ts.rangeOverlapsWithStartEnd(originalRange, child.pos, child.end)) { if (child.end < originalRange.pos) { formattingScanner.skipToEndOf(child); @@ -83987,8 +100612,10 @@ var ts; return inheritedIndentation; } while (formattingScanner.isOnToken()) { + // proceed any parent tokens that are located prior to child.getStart() var tokenInfo = formattingScanner.readTokenInfo(node); if (tokenInfo.token.end > childStartPos) { + // stop when formatting scanner advances past the beginning of the child break; } consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, node); @@ -83996,21 +100623,23 @@ var ts; if (!formattingScanner.isOnToken()) { return inheritedIndentation; } - if (ts.isToken(child) && child.kind !== 10) { + // JSX text shouldn't affect indenting + if (ts.isToken(child) && child.kind !== 10 /* JsxText */) { + // if child node is a token, it does not impact indentation, proceed it using parent indentation scope rules var tokenInfo = formattingScanner.readTokenInfo(child); ts.Debug.assert(tokenInfo.token.end === child.end, "Token end is child end"); consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, child); return inheritedIndentation; } - var effectiveParentStartLine = child.kind === 150 ? childStartLine : undecoratedParentStartLine; + var effectiveParentStartLine = child.kind === 150 /* Decorator */ ? childStartLine : undecoratedParentStartLine; var childIndentation = computeIndentation(child, childStartLine, childIndentationAmount, node, parentDynamicIndentation, effectiveParentStartLine); processNode(child, childContextNode, childStartLine, undecoratedChildStartLine, childIndentation.indentation, childIndentation.delta); - if (child.kind === 10) { + if (child.kind === 10 /* JsxText */) { var range = { pos: child.getStart(), end: child.getEnd() }; - indentMultilineCommentOrJsxText(range, childIndentation.indentation, true, false); + indentMultilineCommentOrJsxText(range, childIndentation.indentation, /*firstLineIsIndented*/ true, /*indentFinalLine*/ false); } childContextNode = node; - if (isFirstListItem && parent.kind === 183 && inheritedIndentation === -1) { + if (isFirstListItem && parent.kind === 183 /* ArrayLiteralExpression */ && inheritedIndentation === -1 /* Unknown */) { inheritedIndentation = childIndentation.indentation; } return inheritedIndentation; @@ -84021,32 +100650,41 @@ var ts; var listEndToken = getCloseTokenForOpenToken(listStartToken); var listDynamicIndentation = parentDynamicIndentation; var startLine = parentStartLine; - if (listStartToken !== 0) { + if (listStartToken !== 0 /* Unknown */) { + // introduce a new indentation scope for lists (including list start and end tokens) while (formattingScanner.isOnToken()) { var tokenInfo = formattingScanner.readTokenInfo(parent); if (tokenInfo.token.end > nodes.pos) { + // stop when formatting scanner moves past the beginning of node list break; } else if (tokenInfo.token.kind === listStartToken) { + // consume list start token startLine = sourceFile.getLineAndCharacterOfPosition(tokenInfo.token.pos).line; - var indentation_2 = computeIndentation(tokenInfo.token, startLine, -1, parent, parentDynamicIndentation, parentStartLine); + var indentation_2 = computeIndentation(tokenInfo.token, startLine, -1 /* Unknown */, parent, parentDynamicIndentation, parentStartLine); listDynamicIndentation = getDynamicIndentation(parent, parentStartLine, indentation_2.indentation, indentation_2.delta); consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation, parent); } else { + // consume any tokens that precede the list as child elements of 'node' using its indentation scope consumeTokenAndAdvanceScanner(tokenInfo, parent, parentDynamicIndentation, parent); } } } - var inheritedIndentation = -1; + var inheritedIndentation = -1 /* Unknown */; for (var i = 0; i < nodes.length; i++) { var child = nodes[i]; - inheritedIndentation = processChildNode(child, inheritedIndentation, node, listDynamicIndentation, startLine, startLine, true, i === 0); + inheritedIndentation = processChildNode(child, inheritedIndentation, node, listDynamicIndentation, startLine, startLine, /*isListItem*/ true, /*isFirstListItem*/ i === 0); } - if (listEndToken !== 0) { + if (listEndToken !== 0 /* Unknown */) { if (formattingScanner.isOnToken()) { var tokenInfo = formattingScanner.readTokenInfo(parent); + // consume the list end token only if it is still belong to the parent + // there might be the case when current token matches end token but does not considered as one + // function (x: function) <-- + // without this check close paren will be interpreted as list end token for function expression which is wrong if (tokenInfo.token.kind === listEndToken && ts.rangeContainsRange(parent, tokenInfo.token)) { + // consume list end token consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation, parent); } } @@ -84059,20 +100697,23 @@ var ts; if (currentTokenInfo.leadingTrivia) { processTrivia(currentTokenInfo.leadingTrivia, parent, childContextNode, dynamicIndentation); } - var lineAction = 0; + var lineAction = 0 /* None */; var isTokenInRange = ts.rangeContainsRange(originalRange, currentTokenInfo.token); var tokenStart = sourceFile.getLineAndCharacterOfPosition(currentTokenInfo.token.pos); if (isTokenInRange) { var rangeHasError = rangeContainsError(currentTokenInfo.token); + // save previousRange since processRange will overwrite this value with current one var savePreviousRange = previousRange; lineAction = processRange(currentTokenInfo.token, tokenStart, parent, childContextNode, dynamicIndentation); + // do not indent comments\token if token range overlaps with some error if (!rangeHasError) { - if (lineAction === 0) { + if (lineAction === 0 /* None */) { + // indent token only if end line of previous range does not match start line of the token var prevEndLine = savePreviousRange && sourceFile.getLineAndCharacterOfPosition(savePreviousRange.end).line; indentToken = lastTriviaWasNewLine && tokenStart.line !== prevEndLine; } else { - indentToken = lineAction === 1; + indentToken = lineAction === 1 /* LineAdded */; } } } @@ -84082,7 +100723,7 @@ var ts; if (indentToken) { var tokenIndentation = (isTokenInRange && !rangeContainsError(currentTokenInfo.token)) ? dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind, container) : - -1; + -1 /* Unknown */; var indentNextTokenOrTrivia = true; if (currentTokenInfo.leadingTrivia) { var commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind, tokenIndentation, container); @@ -84090,26 +100731,27 @@ var ts; var triviaItem = _a[_i]; var triviaInRange = ts.rangeContainsRange(originalRange, triviaItem); switch (triviaItem.kind) { - case 3: + case 3 /* MultiLineCommentTrivia */: if (triviaInRange) { - indentMultilineCommentOrJsxText(triviaItem, commentIndentation, !indentNextTokenOrTrivia); + indentMultilineCommentOrJsxText(triviaItem, commentIndentation, /*firstLineIsIndented*/ !indentNextTokenOrTrivia); } indentNextTokenOrTrivia = false; break; - case 2: + case 2 /* SingleLineCommentTrivia */: if (indentNextTokenOrTrivia && triviaInRange) { - insertIndentation(triviaItem.pos, commentIndentation, false); + insertIndentation(triviaItem.pos, commentIndentation, /*lineAdded*/ false); } indentNextTokenOrTrivia = false; break; - case 4: + case 4 /* NewLineTrivia */: indentNextTokenOrTrivia = true; break; } } } - if (tokenIndentation !== -1 && indentNextTokenOrTrivia) { - insertIndentation(currentTokenInfo.token.pos, tokenIndentation, lineAction === 1); + // indent token only if is it is in target range and does not overlap with any error ranges + if (tokenIndentation !== -1 /* Unknown */ && indentNextTokenOrTrivia) { + insertIndentation(currentTokenInfo.token.pos, tokenIndentation, lineAction === 1 /* LineAdded */); lastIndentedLine = tokenStart.line; indentationOnLastIndentedLine = tokenIndentation; } @@ -84127,11 +100769,13 @@ var ts; } } } + // TODO: GH#18217 use an enum instead of `boolean | undefined` function processRange(range, rangeStart, parent, contextNode, dynamicIndentation) { var rangeHasError = rangeContainsError(range); - var lineAction = 0; + var lineAction = 0 /* None */; if (!rangeHasError) { if (!previousRange) { + // trim whitespaces starting from the beginning of the span up to the current line var originalStart = sourceFile.getLineAndCharacterOfPosition(originalRange.pos); trimTrailingWhitespacesForLines(originalStart.line, rangeStart.line); } @@ -84149,29 +100793,36 @@ var ts; formattingContext.updateContext(previousItem, previousParent, currentItem, currentParent, contextNode); var rule = getRule(formattingContext); var trimTrailingWhitespaces; - var lineAction = 0; + var lineAction = 0 /* None */; if (rule) { lineAction = applyRuleEdits(rule, previousItem, previousStartLine, currentItem, currentStartLine); switch (lineAction) { - case 2: + case 2 /* LineRemoved */: + // Handle the case where the next line is moved to be the end of this line. + // In this case we don't indent the next line in the next pass. if (currentParent.getStart(sourceFile) === currentItem.pos) { - dynamicIndentation.recomputeIndentation(false); + dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ false); } break; - case 1: + case 1 /* LineAdded */: + // Handle the case where token2 is moved to the new line. + // In this case we indent token2 in the next pass but we set + // sameLineIndent flag to notify the indenter that the indentation is within the line. if (currentParent.getStart(sourceFile) === currentItem.pos) { - dynamicIndentation.recomputeIndentation(true); + dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ true); } break; default: - ts.Debug.assert(lineAction === 0); + ts.Debug.assert(lineAction === 0 /* None */); } - trimTrailingWhitespaces = !(rule.action & 8) && rule.flags !== 1; + // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line + trimTrailingWhitespaces = !(rule.action & 8 /* Delete */) && rule.flags !== 1 /* CanDeleteNewLines */; } else { trimTrailingWhitespaces = true; } if (currentStartLine !== previousStartLine && trimTrailingWhitespaces) { + // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line trimTrailingWhitespacesForLines(previousStartLine, currentStartLine, previousItem); } return lineAction; @@ -84179,6 +100830,8 @@ var ts; function insertIndentation(pos, indentation, lineAdded) { var indentationString = getIndentationString(indentation, options); if (lineAdded) { + // new line is added before the token by the formatting rules + // insert indentation string at the very beginning of the token recordReplace(pos, 0, indentationString); } else { @@ -84192,7 +100845,7 @@ var ts; function characterToColumn(startLinePosition, characterInLine) { var column = 0; for (var i = 0; i < characterInLine; i++) { - if (sourceFile.text.charCodeAt(startLinePosition + i) === 9) { + if (sourceFile.text.charCodeAt(startLinePosition + i) === 9 /* tab */) { column += options.tabSize - column % options.tabSize; } else { @@ -84206,12 +100859,14 @@ var ts; } function indentMultilineCommentOrJsxText(commentRange, indentation, firstLineIsIndented, indentFinalLine) { if (indentFinalLine === void 0) { indentFinalLine = true; } + // split comment in lines var startLine = sourceFile.getLineAndCharacterOfPosition(commentRange.pos).line; var endLine = sourceFile.getLineAndCharacterOfPosition(commentRange.end).line; var parts; if (startLine === endLine) { if (!firstLineIsIndented) { - insertIndentation(commentRange.pos, indentation, false); + // treat as single line comment + insertIndentation(commentRange.pos, indentation, /*lineAdded*/ false); } return; } @@ -84237,6 +100892,7 @@ var ts; startIndex = 1; startLine++; } + // shift all parts on the delta size var delta = indentation - nonWhitespaceColumnInFirstPart.column; for (var i = startIndex; i < parts.length; i++, startLine++) { var startLinePos_1 = ts.getStartPositionOfLine(startLine, sourceFile); @@ -84257,6 +100913,7 @@ var ts; for (var line = line1; line < line2; line++) { var lineStartPosition = ts.getStartPositionOfLine(line, sourceFile); var lineEndPosition = ts.getEndLinePosition(line, sourceFile); + // do not trim whitespaces in comments or template expression if (range && (ts.isComment(range.kind) || ts.isStringOrRegularExpressionOrTemplateLiteral(range.kind)) && range.pos <= lineEndPosition && range.end > lineEndPosition) { continue; } @@ -84267,6 +100924,10 @@ var ts; } } } + /** + * @param start The position of the first character in range + * @param end The position of the last character in range + */ function getTrailingWhitespaceStartPosition(start, end) { var pos = end; while (pos >= start && ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(pos))) { @@ -84277,6 +100938,9 @@ var ts; } return -1; } + /** + * Trimming will be done for lines after the previous range + */ function trimTrailingWhitespacesForRemainingRange() { var startPosition = previousRange ? previousRange.end : originalRange.pos; var startLine = sourceFile.getLineAndCharacterOfPosition(startPosition).line; @@ -84296,35 +100960,42 @@ var ts; function applyRuleEdits(rule, previousRange, previousStartLine, currentRange, currentStartLine) { var onLaterLine = currentStartLine !== previousStartLine; switch (rule.action) { - case 1: - return 0; - case 8: + case 1 /* Ignore */: + // no action required + return 0 /* None */; + case 8 /* Delete */: if (previousRange.end !== currentRange.pos) { + // delete characters starting from t1.end up to t2.pos exclusive recordDelete(previousRange.end, currentRange.pos - previousRange.end); - return onLaterLine ? 2 : 0; + return onLaterLine ? 2 /* LineRemoved */ : 0 /* None */; } break; - case 4: - if (rule.flags !== 1 && previousStartLine !== currentStartLine) { - return 0; + case 4 /* NewLine */: + // exit early if we on different lines and rule cannot change number of newlines + // if line1 and line2 are on subsequent lines then no edits are required - ok to exit + // if line1 and line2 are separated with more than one newline - ok to exit since we cannot delete extra new lines + if (rule.flags !== 1 /* CanDeleteNewLines */ && previousStartLine !== currentStartLine) { + return 0 /* None */; } + // edit should not be applied if we have one line feed between elements var lineDelta = currentStartLine - previousStartLine; if (lineDelta !== 1) { recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.newLineCharacter); - return onLaterLine ? 0 : 1; + return onLaterLine ? 0 /* None */ : 1 /* LineAdded */; } break; - case 2: - if (rule.flags !== 1 && previousStartLine !== currentStartLine) { - return 0; + case 2 /* Space */: + // exit early if we on different lines and rule cannot change number of newlines + if (rule.flags !== 1 /* CanDeleteNewLines */ && previousStartLine !== currentStartLine) { + return 0 /* None */; } var posDelta = currentRange.pos - previousRange.end; - if (posDelta !== 1 || sourceFile.text.charCodeAt(previousRange.end) !== 32) { + if (posDelta !== 1 || sourceFile.text.charCodeAt(previousRange.end) !== 32 /* space */) { recordReplace(previousRange.end, currentRange.pos - previousRange.end, " "); - return onLaterLine ? 2 : 0; + return onLaterLine ? 2 /* LineRemoved */ : 0 /* None */; } } - return 0; + return 0 /* None */; } } var LineAction; @@ -84333,8 +101004,12 @@ var ts; LineAction[LineAction["LineAdded"] = 1] = "LineAdded"; LineAction[LineAction["LineRemoved"] = 2] = "LineRemoved"; })(LineAction || (LineAction = {})); - function getRangeOfEnclosingComment(sourceFile, position, onlyMultiLine, precedingToken, tokenAtPosition, predicate) { - if (tokenAtPosition === void 0) { tokenAtPosition = ts.getTokenAtPosition(sourceFile, position, false); } + /** + * @param precedingToken pass `null` if preceding token was already computed and result was `undefined`. + */ + function getRangeOfEnclosingComment(sourceFile, position, onlyMultiLine, precedingToken, // tslint:disable-line:no-null-keyword + tokenAtPosition, predicate) { + if (tokenAtPosition === void 0) { tokenAtPosition = ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); } var tokenStart = tokenAtPosition.getStart(sourceFile); if (tokenStart <= position && position < tokenAtPosition.getEnd()) { return undefined; @@ -84342,6 +101017,8 @@ var ts; if (precedingToken === undefined) { precedingToken = ts.findPrecedingToken(position, sourceFile); } + // Between two consecutive tokens, all comments are either trailing on the former + // or leading on the latter (and none are in both lists). var trailingRangesOfPreviousToken = precedingToken && ts.getTrailingCommentRanges(sourceFile.text, precedingToken.end); var leadingCommentRangesOfNextToken = ts.getLeadingCommentRangesOfNode(tokenAtPosition, sourceFile); var commentRanges = trailingRangesOfPreviousToken && leadingCommentRangesOfNextToken ? @@ -84350,9 +101027,22 @@ var ts; if (commentRanges) { for (var _i = 0, commentRanges_1 = commentRanges; _i < commentRanges_1.length; _i++) { var range = commentRanges_1[_i]; + // The end marker of a single-line comment does not include the newline character. + // With caret at `^`, in the following case, we are inside a comment (^ denotes the cursor position): + // + // // asdf ^\n + // + // But for closed multi-line comments, we don't want to be inside the comment in the following case: + // + // /* asdf */^ + // + // However, unterminated multi-line comments *do* contain their end. + // + // Internally, we represent the end of the comment at the newline and closing '/', respectively. + // if ((range.pos < position && position < range.end || - position === range.end && (range.kind === 2 || position === sourceFile.getFullWidth()))) { - return (range.kind === 3 || !onlyMultiLine) && (!predicate || predicate(range)) ? range : undefined; + position === range.end && (range.kind === 2 /* SingleLineCommentTrivia */ || position === sourceFile.getFullWidth()))) { + return (range.kind === 3 /* MultiLineCommentTrivia */ || !onlyMultiLine) && (!predicate || predicate(range)) ? range : undefined; } } } @@ -84361,48 +101051,49 @@ var ts; formatting.getRangeOfEnclosingComment = getRangeOfEnclosingComment; function getOpenTokenForList(node, list) { switch (node.kind) { - case 155: - case 234: - case 192: - case 154: - case 153: - case 193: + case 155 /* Constructor */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 193 /* ArrowFunction */: if (node.typeParameters === list) { - return 27; + return 27 /* LessThanToken */; } else if (node.parameters === list) { - return 19; + return 19 /* OpenParenToken */; } break; - case 187: - case 188: + case 187 /* CallExpression */: + case 188 /* NewExpression */: if (node.typeArguments === list) { - return 27; + return 27 /* LessThanToken */; } else if (node.arguments === list) { - return 19; + return 19 /* OpenParenToken */; } break; - case 162: + case 162 /* TypeReference */: if (node.typeArguments === list) { - return 27; + return 27 /* LessThanToken */; } } - return 0; + return 0 /* Unknown */; } function getCloseTokenForOpenToken(kind) { switch (kind) { - case 19: - return 20; - case 27: - return 29; + case 19 /* OpenParenToken */: + return 20 /* CloseParenToken */; + case 27 /* LessThanToken */: + return 29 /* GreaterThanToken */; } - return 0; + return 0 /* Unknown */; } var internedSizes; var internedTabsIndentation; var internedSpacesIndentation; function getIndentationString(indentation, options) { + // reset interned strings if FormatCodeOptions were changed var resetInternedStrings = !internedSizes || (internedSizes.tabSize !== options.tabSize || internedSizes.indentSize !== options.indentSize); if (resetInternedStrings) { internedSizes = { tabSize: options.tabSize, indentSize: options.indentSize }; @@ -84443,6 +101134,7 @@ var ts; formatting.getIndentationString = getIndentationString; })(formatting = ts.formatting || (ts.formatting = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var formatting; @@ -84453,33 +101145,55 @@ var ts; (function (Value) { Value[Value["Unknown"] = -1] = "Unknown"; })(Value || (Value = {})); + /** + * @param assumeNewLineBeforeCloseBrace + * `false` when called on text from a real source file. + * `true` when we need to assume `position` is on a newline. + * + * This is useful for codefixes. Consider + * ``` + * function f() { + * |} + * ``` + * with `position` at `|`. + * + * When inserting some text after an open brace, we would like to get indentation as if a newline was already there. + * By default indentation at `position` will be 0 so 'assumeNewLineBeforeCloseBrace' overrides this behavior. + */ function getIndentation(position, sourceFile, options, assumeNewLineBeforeCloseBrace) { if (assumeNewLineBeforeCloseBrace === void 0) { assumeNewLineBeforeCloseBrace = false; } if (position > sourceFile.text.length) { - return getBaseIndentation(options); + return getBaseIndentation(options); // past EOF } + // no indentation when the indent style is set to none, + // so we can return fast if (options.indentStyle === ts.IndentStyle.None) { return 0; } var precedingToken = ts.findPrecedingToken(position, sourceFile); - var enclosingCommentRange = formatting.getRangeOfEnclosingComment(sourceFile, position, true, precedingToken || null); + var enclosingCommentRange = formatting.getRangeOfEnclosingComment(sourceFile, position, /*onlyMultiLine*/ true, precedingToken || null); // tslint:disable-line:no-null-keyword if (enclosingCommentRange) { return getCommentIndent(sourceFile, position, options, enclosingCommentRange); } if (!precedingToken) { return getBaseIndentation(options); } + // no indentation in string \regex\template literals var precedingTokenIsLiteral = ts.isStringOrRegularExpressionOrTemplateLiteral(precedingToken.kind); if (precedingTokenIsLiteral && precedingToken.getStart(sourceFile) <= position && position < precedingToken.end) { return 0; } var lineAtPosition = sourceFile.getLineAndCharacterOfPosition(position).line; + // indentation is first non-whitespace character in a previous line + // for block indentation, we should look for a line which contains something that's not + // whitespace. if (options.indentStyle === ts.IndentStyle.Block) { return getBlockIndent(sourceFile, position, options); } - if (precedingToken.kind === 26 && precedingToken.parent.kind !== 200) { + if (precedingToken.kind === 26 /* CommaToken */ && precedingToken.parent.kind !== 200 /* BinaryExpression */) { + // previous token is comma that separates items in list - find the previous item and try to derive indentation from it var actualIndentation = getActualIndentationForListItemBeforeComma(precedingToken, sourceFile, options); - if (actualIndentation !== -1) { + if (actualIndentation !== -1 /* Unknown */) { return actualIndentation; } } @@ -84499,9 +101213,11 @@ var ts; return column; } var firstNonWhitespaceCharacterCode = sourceFile.text.charCodeAt(startPostionOfLine + character); - return firstNonWhitespaceCharacterCode === 42 ? column - 1 : column; + return firstNonWhitespaceCharacterCode === 42 /* asterisk */ ? column - 1 : column; } function getBlockIndent(sourceFile, position, options) { + // move backwards until we find a line with a non-whitespace character, + // then find the first non-whitespace character for that line. var current = position; while (current > 0) { var char = sourceFile.text.charCodeAt(current); @@ -84514,33 +101230,38 @@ var ts; return findFirstNonWhitespaceColumn(lineStart, current, sourceFile, options); } function getSmartIndent(sourceFile, position, precedingToken, lineAtPosition, assumeNewLineBeforeCloseBrace, options) { + // try to find node that can contribute to indentation and includes 'position' starting from 'precedingToken' + // if such node is found - compute initial indentation for 'position' inside this node var previous; var current = precedingToken; while (current) { - if (ts.positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(options, current, previous, sourceFile, true)) { + if (ts.positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(options, current, previous, sourceFile, /*isNextChild*/ true)) { var currentStart = getStartLineAndCharacterForNode(current, sourceFile); var nextTokenKind = nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile); - var indentationDelta = nextTokenKind !== 0 - ? assumeNewLineBeforeCloseBrace && nextTokenKind === 2 ? options.indentSize : 0 + var indentationDelta = nextTokenKind !== 0 /* Unknown */ + // handle cases when codefix is about to be inserted before the close brace + ? assumeNewLineBeforeCloseBrace && nextTokenKind === 2 /* CloseBrace */ ? options.indentSize : 0 : lineAtPosition !== currentStart.line ? options.indentSize : 0; - return getIndentationForNodeWorker(current, currentStart, undefined, indentationDelta, sourceFile, true, options); + return getIndentationForNodeWorker(current, currentStart, /*ignoreActualIndentationRange*/ undefined, indentationDelta, sourceFile, /*isNextChild*/ true, options); // TODO: GH#18217 } + // check if current node is a list item - if yes, take indentation from it var actualIndentation = getActualIndentationForListItem(current, sourceFile, options); - if (actualIndentation !== -1) { + if (actualIndentation !== -1 /* Unknown */) { return actualIndentation; } actualIndentation = getLineIndentationWhenExpressionIsInMultiLine(current, sourceFile, options); - if (actualIndentation !== -1) { - return actualIndentation + options.indentSize; + if (actualIndentation !== -1 /* Unknown */) { + return actualIndentation + options.indentSize; // TODO: GH#18217 } previous = current; current = current.parent; } + // no parent was found - return the base indentation of the SourceFile return getBaseIndentation(options); } function getIndentationForNode(n, ignoreActualIndentationRange, sourceFile, options) { var start = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); - return getIndentationForNodeWorker(n, start, ignoreActualIndentationRange, 0, sourceFile, false, options); + return getIndentationForNodeWorker(n, start, ignoreActualIndentationRange, /*indentationDelta*/ 0, sourceFile, /*isNextChild*/ false, options); } SmartIndenter.getIndentationForNode = getIndentationForNode; function getBaseIndentation(options) { @@ -84549,6 +101270,9 @@ var ts; SmartIndenter.getBaseIndentation = getBaseIndentation; function getIndentationForNodeWorker(current, currentStart, ignoreActualIndentationRange, indentationDelta, sourceFile, isNextChild, options) { var parent = current.parent; + // Walk up the tree and collect indentation for parent-child node pairs. Indentation is not added if + // * parent and child nodes start on the same line, or + // * parent is an IfStatement and child starts on the same line as an 'else clause'. while (parent) { var useActualIndentation = true; if (ignoreActualIndentationRange) { @@ -84556,8 +101280,9 @@ var ts; useActualIndentation = start < ignoreActualIndentationRange.pos || start > ignoreActualIndentationRange.end; } if (useActualIndentation) { + // check if current node is a list item - if yes, take indentation from it var actualIndentation = getActualIndentationForListItem(current, sourceFile, options); - if (actualIndentation !== -1) { + if (actualIndentation !== -1 /* Unknown */) { return actualIndentation + indentationDelta; } } @@ -84565,18 +101290,28 @@ var ts; var parentAndChildShareLine = containingListOrParentStart.line === currentStart.line || childStartsOnTheSameLineWithElseInIfStatement(parent, current, currentStart.line, sourceFile); if (useActualIndentation) { + // try to fetch actual indentation for current node from source text var actualIndentation = getActualIndentationForNode(current, parent, currentStart, parentAndChildShareLine, sourceFile, options); - if (actualIndentation !== -1) { + if (actualIndentation !== -1 /* Unknown */) { return actualIndentation + indentationDelta; } actualIndentation = getLineIndentationWhenExpressionIsInMultiLine(current, sourceFile, options); - if (actualIndentation !== -1) { + if (actualIndentation !== -1 /* Unknown */) { return actualIndentation + indentationDelta; } } + // increase indentation if parent node wants its content to be indented and parent and child nodes don't start on the same line if (shouldIndentChildNode(options, parent, current, sourceFile, isNextChild) && !parentAndChildShareLine) { indentationDelta += options.indentSize; } + // In our AST, a call argument's `parent` is the call-expression, not the argument list. + // We would like to increase indentation based on the relationship between an argument and its argument-list, + // so we spoof the starting position of the (parent) call-expression to match the (non-parent) argument-list. + // But, the spoofed start-value could then cause a problem when comparing the start position of the call-expression + // to *its* parent (in the case of an iife, an expression statement), adding an extra level of indentation. + // + // Instead, when at an argument, we unspoof the starting position of the enclosing call expression + // *after* applying indentation for the argument. var useTrueStart = isArgumentAndStartLineOverlapsExpressionBeingCalled(parent, current, currentStart.line, sourceFile); current = parent; parent = current.parent; @@ -84589,20 +101324,31 @@ var ts; var startPos = containingList ? containingList.pos : parent.getStart(sourceFile); return sourceFile.getLineAndCharacterOfPosition(startPos); } + /* + * Function returns Value.Unknown if indentation cannot be determined + */ function getActualIndentationForListItemBeforeComma(commaToken, sourceFile, options) { + // previous token is comma that separates items in list - find the previous item and try to derive indentation from it var commaItemInfo = ts.findListItemInfo(commaToken); if (commaItemInfo && commaItemInfo.listItemIndex > 0) { return deriveActualIndentationFromList(commaItemInfo.list.getChildren(), commaItemInfo.listItemIndex - 1, sourceFile, options); } else { - return -1; + // handle broken code gracefully + return -1 /* Unknown */; } } + /* + * Function returns Value.Unknown if actual indentation for node should not be used (i.e because node is nested expression) + */ function getActualIndentationForNode(current, parent, currentLineAndChar, parentAndChildShareLine, sourceFile, options) { + // actual indentation is used for statements\declarations if one of cases below is true: + // - parent is SourceFile - by default immediate children of SourceFile are not indented except when user indents them manually + // - parent and child are not on the same line var useActualIndentation = (ts.isDeclaration(current) || ts.isStatementButNotDeclaration(current)) && - (parent.kind === 274 || !parentAndChildShareLine); + (parent.kind === 274 /* SourceFile */ || !parentAndChildShareLine); if (!useActualIndentation) { - return -1; + return -1 /* Unknown */; } return findColumnForFirstNonWhitespaceCharacterInLine(currentLineAndChar, sourceFile, options); } @@ -84615,16 +101361,25 @@ var ts; function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile) { var nextToken = ts.findNextToken(precedingToken, current, sourceFile); if (!nextToken) { - return 0; + return 0 /* Unknown */; } - if (nextToken.kind === 17) { - return 1; + if (nextToken.kind === 17 /* OpenBraceToken */) { + // open braces are always indented at the parent level + return 1 /* OpenBrace */; } - else if (nextToken.kind === 18) { + else if (nextToken.kind === 18 /* CloseBraceToken */) { + // close braces are indented at the parent level if they are located on the same line with cursor + // this means that if new line will be added at $ position, this case will be indented + // class A { + // $ + // } + /// and this one - not + // class A { + // $} var nextTokenStartLine = getStartLineAndCharacterForNode(nextToken, sourceFile).line; - return lineAtPosition === nextTokenStartLine ? 2 : 0; + return lineAtPosition === nextTokenStartLine ? 2 /* CloseBrace */ : 0 /* Unknown */; } - return 0; + return 0 /* Unknown */; } function getStartLineAndCharacterForNode(n, sourceFile) { return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); @@ -84639,8 +101394,8 @@ var ts; } SmartIndenter.isArgumentAndStartLineOverlapsExpressionBeingCalled = isArgumentAndStartLineOverlapsExpressionBeingCalled; function childStartsOnTheSameLineWithElseInIfStatement(parent, child, childStartLine, sourceFile) { - if (parent.kind === 217 && parent.elseStatement === child) { - var elseKeyword = ts.findChildOfKind(parent, 82, sourceFile); + if (parent.kind === 217 /* IfStatement */ && parent.elseStatement === child) { + var elseKeyword = ts.findChildOfKind(parent, 82 /* ElseKeyword */, sourceFile); ts.Debug.assert(elseKeyword !== undefined); var elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line; return elseKeywordStartLine === childStartLine; @@ -84655,40 +101410,40 @@ var ts; if (node.parent) { var end = node.end; switch (node.parent.kind) { - case 162: + case 162 /* TypeReference */: return getListIfStartEndIsInListRange(node.parent.typeArguments, node.getStart(sourceFile), end); - case 184: + case 184 /* ObjectLiteralExpression */: return node.parent.properties; - case 183: + case 183 /* ArrayLiteralExpression */: return node.parent.elements; - case 234: - case 192: - case 193: - case 154: - case 153: - case 158: - case 155: - case 164: - case 159: { + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 158 /* CallSignature */: + case 155 /* Constructor */: + case 164 /* ConstructorType */: + case 159 /* ConstructSignature */: { var start = node.getStart(sourceFile); return getListIfStartEndIsInListRange(node.parent.typeParameters, start, end) || getListIfStartEndIsInListRange(node.parent.parameters, start, end); } - case 235: + case 235 /* ClassDeclaration */: return getListIfStartEndIsInListRange(node.parent.typeParameters, node.getStart(sourceFile), end); - case 188: - case 187: { + case 188 /* NewExpression */: + case 187 /* CallExpression */: { var start = node.getStart(sourceFile); return getListIfStartEndIsInListRange(node.parent.typeArguments, start, end) || getListIfStartEndIsInListRange(node.parent.arguments, start, end); } - case 233: + case 233 /* VariableDeclarationList */: return getListIfStartEndIsInListRange(node.parent.declarations, node.getStart(sourceFile), end); - case 247: - case 251: + case 247 /* NamedImports */: + case 251 /* NamedExports */: return getListIfStartEndIsInListRange(node.parent.elements, node.getStart(sourceFile), end); - case 180: - case 181: + case 180 /* ObjectBindingPattern */: + case 181 /* ArrayBindingPattern */: return getListIfStartEndIsInListRange(node.parent.elements, node.getStart(sourceFile), end); } } @@ -84703,33 +101458,35 @@ var ts; return deriveActualIndentationFromList(containingList, index, sourceFile, options); } } - return -1; + return -1 /* Unknown */; } function getLineIndentationWhenExpressionIsInMultiLine(node, sourceFile, options) { - if (node.kind === 20) { - return -1; + // actual indentation should not be used when: + // - node is close parenthesis - this is the end of the expression + if (node.kind === 20 /* CloseParenToken */) { + return -1 /* Unknown */; } if (node.parent && ts.isCallOrNewExpression(node.parent) && node.parent.expression !== node) { var fullCallOrNewExpression = node.parent.expression; var startingExpression = getStartingExpression(fullCallOrNewExpression); if (fullCallOrNewExpression === startingExpression) { - return -1; + return -1 /* Unknown */; } var fullCallOrNewExpressionEnd = sourceFile.getLineAndCharacterOfPosition(fullCallOrNewExpression.end); var startingExpressionEnd = sourceFile.getLineAndCharacterOfPosition(startingExpression.end); if (fullCallOrNewExpressionEnd.line === startingExpressionEnd.line) { - return -1; + return -1 /* Unknown */; } return findColumnForFirstNonWhitespaceCharacterInLine(fullCallOrNewExpressionEnd, sourceFile, options); } - return -1; + return -1 /* Unknown */; function getStartingExpression(node) { while (true) { switch (node.kind) { - case 187: - case 188: - case 185: - case 186: + case 187 /* CallExpression */: + case 188 /* NewExpression */: + case 185 /* PropertyAccessExpression */: + case 186 /* ElementAccessExpression */: node = node.expression; break; default: @@ -84741,23 +101498,33 @@ var ts; function deriveActualIndentationFromList(list, index, sourceFile, options) { ts.Debug.assert(index >= 0 && index < list.length); var node = list[index]; + // walk toward the start of the list starting from current node and check if the line is the same for all items. + // if end line for item [i - 1] differs from the start line for item [i] - find column of the first non-whitespace character on the line of item [i] var lineAndCharacter = getStartLineAndCharacterForNode(node, sourceFile); for (var i = index - 1; i >= 0; i--) { - if (list[i].kind === 26) { + if (list[i].kind === 26 /* CommaToken */) { continue; } + // skip list items that ends on the same line with the current list element var prevEndLine = sourceFile.getLineAndCharacterOfPosition(list[i].end).line; if (prevEndLine !== lineAndCharacter.line) { return findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options); } lineAndCharacter = getStartLineAndCharacterForNode(list[i], sourceFile); } - return -1; + return -1 /* Unknown */; } function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options) { var lineStart = sourceFile.getPositionOfLineAndCharacter(lineAndCharacter.line, 0); return findFirstNonWhitespaceColumn(lineStart, lineStart + lineAndCharacter.character, sourceFile, options); } + /** + * Character is the actual index of the character since the beginning of the line. + * Column - position of the character after expanding tabs to spaces. + * "0\t2$" + * value of 'character' for '$' is 3 + * value of 'column' for '$' is 6 (assuming that tab size is 4) + */ function findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options) { var character = 0; var column = 0; @@ -84766,7 +101533,7 @@ var ts; if (!ts.isWhiteSpaceSingleLine(ch)) { break; } - if (ch === 9) { + if (ch === 9 /* tab */) { column += options.tabSize + (column % options.tabSize); } else { @@ -84782,111 +101549,118 @@ var ts; } SmartIndenter.findFirstNonWhitespaceColumn = findFirstNonWhitespaceColumn; function nodeWillIndentChild(settings, parent, child, sourceFile, indentByDefault) { - var childKind = child ? child.kind : 0; + var childKind = child ? child.kind : 0 /* Unknown */; switch (parent.kind) { - case 216: - case 235: - case 205: - case 236: - case 238: - case 237: - case 183: - case 213: - case 240: - case 184: - case 166: - case 177: - case 168: - case 241: - case 267: - case 266: - case 191: - case 185: - case 187: - case 188: - case 214: - case 249: - case 225: - case 201: - case 181: - case 180: - case 257: - case 260: - case 256: - case 265: - case 153: - case 158: - case 159: - case 149: - case 163: - case 164: - case 173: - case 189: - case 197: - case 251: - case 247: - case 252: - case 248: - case 152: + case 216 /* ExpressionStatement */: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 236 /* InterfaceDeclaration */: + case 238 /* EnumDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 183 /* ArrayLiteralExpression */: + case 213 /* Block */: + case 240 /* ModuleBlock */: + case 184 /* ObjectLiteralExpression */: + case 166 /* TypeLiteral */: + case 177 /* MappedType */: + case 168 /* TupleType */: + case 241 /* CaseBlock */: + case 267 /* DefaultClause */: + case 266 /* CaseClause */: + case 191 /* ParenthesizedExpression */: + case 185 /* PropertyAccessExpression */: + case 187 /* CallExpression */: + case 188 /* NewExpression */: + case 214 /* VariableStatement */: + case 249 /* ExportAssignment */: + case 225 /* ReturnStatement */: + case 201 /* ConditionalExpression */: + case 181 /* ArrayBindingPattern */: + case 180 /* ObjectBindingPattern */: + case 257 /* JsxOpeningElement */: + case 260 /* JsxOpeningFragment */: + case 256 /* JsxSelfClosingElement */: + case 265 /* JsxExpression */: + case 153 /* MethodSignature */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 149 /* Parameter */: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 173 /* ParenthesizedType */: + case 189 /* TaggedTemplateExpression */: + case 197 /* AwaitExpression */: + case 251 /* NamedExports */: + case 247 /* NamedImports */: + case 252 /* ExportSpecifier */: + case 248 /* ImportSpecifier */: + case 152 /* PropertyDeclaration */: return true; - case 232: - case 270: - if (!settings.indentMultiLineObjectLiteralBeginningOnBlankLine && sourceFile && childKind === 184) { + case 232 /* VariableDeclaration */: + case 270 /* PropertyAssignment */: + if (!settings.indentMultiLineObjectLiteralBeginningOnBlankLine && sourceFile && childKind === 184 /* ObjectLiteralExpression */) { // TODO: GH#18217 return rangeIsOnOneLine(sourceFile, child); } return true; - case 218: - case 219: - case 221: - case 222: - case 220: - case 217: - case 234: - case 192: - case 154: - case 193: - case 155: - case 156: - case 157: - return childKind !== 213; - case 250: - return childKind !== 251; - case 244: - return childKind !== 245 || - (!!child.namedBindings && child.namedBindings.kind !== 247); - case 255: - return childKind !== 258; - case 259: - return childKind !== 261; - case 170: - case 169: - if (childKind === 166) { + case 218 /* DoStatement */: + case 219 /* WhileStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 220 /* ForStatement */: + case 217 /* IfStatement */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 154 /* MethodDeclaration */: + case 193 /* ArrowFunction */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + return childKind !== 213 /* Block */; + case 250 /* ExportDeclaration */: + return childKind !== 251 /* NamedExports */; + case 244 /* ImportDeclaration */: + return childKind !== 245 /* ImportClause */ || + (!!child.namedBindings && child.namedBindings.kind !== 247 /* NamedImports */); + case 255 /* JsxElement */: + return childKind !== 258 /* JsxClosingElement */; + case 259 /* JsxFragment */: + return childKind !== 261 /* JsxClosingFragment */; + case 170 /* IntersectionType */: + case 169 /* UnionType */: + if (childKind === 166 /* TypeLiteral */) { return false; } + // falls through } + // No explicit rule for given nodes so the result will follow the default value argument return indentByDefault; } SmartIndenter.nodeWillIndentChild = nodeWillIndentChild; function isControlFlowEndingStatement(kind, parent) { switch (kind) { - case 225: - case 229: { - if (parent.kind !== 213) { + case 225 /* ReturnStatement */: + case 229 /* ThrowStatement */: { + if (parent.kind !== 213 /* Block */) { return true; } var grandParent = parent.parent; - return !(grandParent && grandParent.kind === 192 || grandParent.kind === 234); + // In a function, we may want to write inner functions after this. + return !(grandParent && grandParent.kind === 192 /* FunctionExpression */ || grandParent.kind === 234 /* FunctionDeclaration */); } - case 223: - case 224: + case 223 /* ContinueStatement */: + case 224 /* BreakStatement */: return true; default: return false; } } + /** + * True when the parent node should indent the given child by an explicit rule. + * @param isNextChild If true, we are judging indent of a hypothetical child *after* this one, not the current child. + */ function shouldIndentChildNode(settings, parent, child, sourceFile, isNextChild) { if (isNextChild === void 0) { isNextChild = false; } - return nodeWillIndentChild(settings, parent, child, sourceFile, false) + return nodeWillIndentChild(settings, parent, child, sourceFile, /*indentByDefault*/ false) && !(isNextChild && child && isControlFlowEndingStatement(child.kind, parent)); } SmartIndenter.shouldIndentChildNode = shouldIndentChildNode; @@ -84899,10 +101673,15 @@ var ts; })(SmartIndenter = formatting.SmartIndenter || (formatting.SmartIndenter = {})); })(formatting = ts.formatting || (ts.formatting = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var textChanges; (function (textChanges_3) { + /** + * Currently for simplicity we store recovered positions on the node itself. + * It can be changed to side-table later if we decide that current design is too invasive. + */ function getPos(n) { var result = n.__pos; ts.Debug.assert(typeof result === "number"); @@ -84927,7 +101706,7 @@ var ts; Position[Position["Start"] = 1] = "Start"; })(Position = textChanges_3.Position || (textChanges_3.Position = {})); function skipWhitespacesAndLineBreaks(text, start) { - return ts.skipTrivia(text, start, false, true); + return ts.skipTrivia(text, start, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); } function hasCommentsBeforeLineBreak(text, start) { var i = start; @@ -84937,7 +101716,7 @@ var ts; i++; continue; } - return ch === 47; + return ch === 47 /* slash */; } return false; } @@ -84967,10 +101746,20 @@ var ts; var fullStartLine = ts.getLineStartPositionForPosition(fullStart, sourceFile); var startLine = ts.getLineStartPositionForPosition(start, sourceFile); if (startLine === fullStartLine) { + // full start and start of the node are on the same line + // a, b; + // ^ ^ + // | start + // fullstart + // when b is replaced - we usually want to keep the leading trvia + // when b is deleted - we delete it return position === Position.Start ? start : fullStart; } + // get start position of the line following the line that contains fullstart position + // (but only if the fullstart isn't the very beginning of the file) var nextLineStart = fullStart > 0 ? 1 : 0; var adjustedStartPosition = ts.getStartPositionOfLine(ts.getLineOfLocalPosition(sourceFile, fullStartLine) + nextLineStart, sourceFile); + // skip whitespaces/newlines adjustedStartPosition = skipWhitespacesAndLineBreaks(sourceFile.text, adjustedStartPosition); return ts.getStartPositionOfLine(ts.getLineOfLocalPosition(sourceFile, adjustedStartPosition), sourceFile); } @@ -84979,13 +101768,16 @@ var ts; if (options.useNonAdjustedEndPosition || ts.isExpression(node)) { return end; } - var newEnd = ts.skipTrivia(sourceFile.text, end, true); + var newEnd = ts.skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true); return newEnd !== end && ts.isLineBreak(sourceFile.text.charCodeAt(newEnd - 1)) ? newEnd : end; } + /** + * Checks if 'candidate' argument is a legal separator in the list that contains 'node' as an element + */ function isSeparator(node, candidate) { - return !!candidate && !!node.parent && (candidate.kind === 26 || (candidate.kind === 25 && node.parent.kind === 184)); + return !!candidate && !!node.parent && (candidate.kind === 26 /* CommaToken */ || (candidate.kind === 25 /* SemicolonToken */ && node.parent.kind === 184 /* ObjectLiteralExpression */)); } function spaces(count) { var s = ""; @@ -84994,14 +101786,15 @@ var ts; } return s; } - var ChangeTracker = (function () { + var ChangeTracker = /** @class */ (function () { + /** Public for tests only. Other callers should use `ChangeTracker.with`. */ function ChangeTracker(newLineCharacter, formatContext) { this.newLineCharacter = newLineCharacter; this.formatContext = formatContext; this.changes = []; this.newFiles = []; - this.deletedNodesInLists = new ts.NodeSet(); - this.classesWithNodesInsertedAtStart = ts.createMap(); + this.deletedNodesInLists = new ts.NodeSet(); // Stores ids of nodes in lists that we already deleted. Used to avoid deleting `, ` twice in `a, b`. + this.classesWithNodesInsertedAtStart = ts.createMap(); // Set implemented as Map } ChangeTracker.fromContext = function (context) { return new ChangeTracker(ts.getNewLineOrDefaultFromHost(context.host, context.formatContext.options), context.formatContext); @@ -85015,6 +101808,7 @@ var ts; this.changes.push({ kind: ChangeKind.Remove, sourceFile: sourceFile, range: range }); return this; }; + /** Warning: This deletes comments too. See `copyComments` in `convertFunctionToEs6Class`. */ ChangeTracker.prototype.deleteNode = function (sourceFile, node, options) { if (options === void 0) { options = {}; } var startPosition = getAdjustedStartPosition(sourceFile, node, options, Position.FullStart); @@ -85049,6 +101843,8 @@ var ts; this.deleteNode(sourceFile, node); return this; } + // Note: We will only delete a comma *after* a node. This will leave a trailing comma if we delete the last node. + // That's handled in the end by `finishTrailingCommaAfterDeletingNodesInList`. ts.Debug.assert(!this.deletedNodesInLists.has(node), "Deleting a node twice"); this.deletedNodesInLists.add(node); this.deleteRange(sourceFile, { @@ -85085,7 +101881,7 @@ var ts; }; ChangeTracker.prototype.nextCommaToken = function (sourceFile, node) { var next = ts.findNextToken(node, node.parent, sourceFile); - return next && next.kind === 26 ? next : undefined; + return next && next.kind === 26 /* CommaToken */ ? next : undefined; }; ChangeTracker.prototype.replacePropertyAssignment = function (sourceFile, oldNode, newNode) { var suffix = this.nextCommaToken(sourceFile, oldNode) ? "" : ("," + this.newLineCharacter); @@ -85117,8 +101913,12 @@ var ts; ChangeTracker.prototype.insertCommentBeforeLine = function (sourceFile, lineNumber, position, commentText) { var lineStartPosition = ts.getStartPositionOfLine(lineNumber, sourceFile); var startPosition = ts.getFirstNonSpaceCharacterPosition(sourceFile.text, lineStartPosition); + // First try to see if we can put the comment on the previous line. + // We need to make sure that we are not in the middle of a string literal or a comment. + // If so, we do not want to separate the node from its comment if we can. + // Otherwise, add an extra new line immediately before the error span. var insertAtLineStart = isValidLocationToAddComment(sourceFile, startPosition); - var token = ts.getTouchingToken(sourceFile, insertAtLineStart ? startPosition : position, false); + var token = ts.getTouchingToken(sourceFile, insertAtLineStart ? startPosition : position, /*includeJsDocComment*/ false); var indent = sourceFile.text.slice(lineStartPosition, startPosition); var text = (insertAtLineStart ? "" : this.newLineCharacter) + "//" + commentText + this.newLineCharacter + indent; this.insertText(sourceFile, token.getStart(sourceFile), text); @@ -85129,36 +101929,39 @@ var ts; ChangeTracker.prototype.insertText = function (sourceFile, pos, text) { this.replaceRangeWithText(sourceFile, ts.createTextRange(pos), text); }; + /** Prefer this over replacing a node with another that has a type annotation, as it avoids reformatting the other parts of the node. */ ChangeTracker.prototype.tryInsertTypeAnnotation = function (sourceFile, node, type) { var endNode; if (ts.isFunctionLike(node)) { - endNode = ts.findChildOfKind(node, 20, sourceFile); + endNode = ts.findChildOfKind(node, 20 /* CloseParenToken */, sourceFile); if (!endNode) { if (!ts.isArrowFunction(node)) - return; + return; // Function missing parentheses, give up + // If no `)`, is an arrow function `x => x`, so use the end of the first parameter endNode = ts.first(node.parameters); } } else { - endNode = node.kind !== 232 && node.questionToken ? node.questionToken : node.name; + endNode = node.kind !== 232 /* VariableDeclaration */ && node.questionToken ? node.questionToken : node.name; } this.insertNodeAt(sourceFile, endNode.end, type, { prefix: ": " }); }; ChangeTracker.prototype.insertTypeParameters = function (sourceFile, node, typeParameters) { - var start = (ts.findChildOfKind(node, 19, sourceFile) || ts.first(node.parameters)).getStart(sourceFile); + // If no `(`, is an arrow function `x => x`, so use the pos of the first parameter + var start = (ts.findChildOfKind(node, 19 /* OpenParenToken */, sourceFile) || ts.first(node.parameters)).getStart(sourceFile); this.insertNodesAt(sourceFile, start, typeParameters, { prefix: "<", suffix: ">" }); }; ChangeTracker.prototype.getOptionsForInsertNodeBefore = function (before, doubleNewlines) { if (ts.isStatement(before) || ts.isClassElement(before)) { return { suffix: doubleNewlines ? this.newLineCharacter + this.newLineCharacter : this.newLineCharacter }; } - else if (ts.isVariableDeclaration(before)) { + else if (ts.isVariableDeclaration(before)) { // insert `x = 1, ` into `const x = 1, y = 2; return { suffix: ", " }; } else if (ts.isParameter(before)) { return {}; } - return ts.Debug.failBadSyntaxKind(before); + return ts.Debug.failBadSyntaxKind(before); // We haven't handled this kind of node yet -- add it }; ChangeTracker.prototype.insertNodeAtConstructorStart = function (sourceFile, ctr, newStatement) { var firstStatement = ts.firstOrUndefined(ctr.body.statements); @@ -85179,7 +101982,7 @@ var ts; } }; ChangeTracker.prototype.replaceConstructorBody = function (sourceFile, ctr, statements) { - this.replaceNode(sourceFile, ctr.body, ts.createBlock(statements, true)); + this.replaceNode(sourceFile, ctr.body, ts.createBlock(statements, /*multiLine*/ true)); }; ChangeTracker.prototype.insertNodeAtEndOfScope = function (sourceFile, scope, newNode) { var pos = getAdjustedStartPosition(sourceFile, scope.getLastToken(), {}, Position.Start); @@ -85197,7 +102000,8 @@ var ts; ChangeTracker.prototype.getInsertNodeAtClassStartPrefixSuffix = function (sourceFile, cls) { if (cls.members.length === 0) { if (ts.addToSeen(this.classesWithNodesInsertedAtStart, ts.getNodeId(cls), cls)) { - var shouldSuffix = ts.positionsAreOnSameLine.apply(void 0, getClassBraceEnds(cls, sourceFile).concat([sourceFile])); + // For `class C {\n}`, don't add the trailing "\n" + var shouldSuffix = ts.positionsAreOnSameLine.apply(void 0, getClassBraceEnds(cls, sourceFile).concat([sourceFile])); // TODO: GH#4130 remove 'as any' return { prefix: this.newLineCharacter, suffix: shouldSuffix ? this.newLineCharacter : "" }; } else { @@ -85222,8 +102026,10 @@ var ts; }; ChangeTracker.prototype.insertNodeAfterWorker = function (sourceFile, after, newNode) { if (needSemicolonBetween(after, newNode)) { - if (sourceFile.text.charCodeAt(after.end - 1) !== 59) { - this.replaceRange(sourceFile, ts.createTextRange(after.end), ts.createToken(25)); + // check if previous statement ends with semicolon + // if not - insert semicolon to preserve the code from changing the meaning due to ASI + if (sourceFile.text.charCodeAt(after.end - 1) !== 59 /* semicolon */) { + this.replaceRange(sourceFile, ts.createTextRange(after.end), ts.createToken(25 /* SemicolonToken */)); } } var endPosition = getAdjustedEndPosition(sourceFile, after, {}); @@ -85249,34 +102055,43 @@ var ts; else if (ts.isParameter(node)) { return {}; } - return ts.Debug.failBadSyntaxKind(node); + return ts.Debug.failBadSyntaxKind(node); // We haven't handled this kind of node yet -- add it }; ChangeTracker.prototype.insertName = function (sourceFile, node, name) { ts.Debug.assert(!node.name); - if (node.kind === 193) { - var arrow = ts.findChildOfKind(node, 36, sourceFile); - var lparen = ts.findChildOfKind(node, 19, sourceFile); + if (node.kind === 193 /* ArrowFunction */) { + var arrow = ts.findChildOfKind(node, 36 /* EqualsGreaterThanToken */, sourceFile); + var lparen = ts.findChildOfKind(node, 19 /* OpenParenToken */, sourceFile); if (lparen) { - this.insertNodesAt(sourceFile, lparen.getStart(sourceFile), [ts.createToken(89), ts.createIdentifier(name)], { joiner: " " }); + // `() => {}` --> `function f() {}` + this.insertNodesAt(sourceFile, lparen.getStart(sourceFile), [ts.createToken(89 /* FunctionKeyword */), ts.createIdentifier(name)], { joiner: " " }); this.deleteNode(sourceFile, arrow); } else { + // `x => {}` -> `function f(x) {}` this.insertText(sourceFile, ts.first(node.parameters).getStart(sourceFile), "function " + name + "("); - this.replaceRange(sourceFile, arrow, ts.createToken(20)); + // Replacing full range of arrow to get rid of the leading space -- replace ` =>` with `)` + this.replaceRange(sourceFile, arrow, ts.createToken(20 /* CloseParenToken */)); } - if (node.body.kind !== 213) { - this.insertNodesAt(sourceFile, node.body.getStart(sourceFile), [ts.createToken(17), ts.createToken(96)], { joiner: " ", suffix: " " }); - this.insertNodesAt(sourceFile, node.body.end, [ts.createToken(25), ts.createToken(18)], { joiner: " " }); + if (node.body.kind !== 213 /* Block */) { + // `() => 0` => `function f() { return 0; }` + this.insertNodesAt(sourceFile, node.body.getStart(sourceFile), [ts.createToken(17 /* OpenBraceToken */), ts.createToken(96 /* ReturnKeyword */)], { joiner: " ", suffix: " " }); + this.insertNodesAt(sourceFile, node.body.end, [ts.createToken(25 /* SemicolonToken */), ts.createToken(18 /* CloseBraceToken */)], { joiner: " " }); } } else { - var pos = ts.findChildOfKind(node, node.kind === 192 ? 89 : 75, sourceFile).end; + var pos = ts.findChildOfKind(node, node.kind === 192 /* FunctionExpression */ ? 89 /* FunctionKeyword */ : 75 /* ClassKeyword */, sourceFile).end; this.insertNodeAt(sourceFile, pos, ts.createIdentifier(name), { prefix: " " }); } }; ChangeTracker.prototype.insertExportModifier = function (sourceFile, node) { this.insertText(sourceFile, node.getStart(sourceFile), "export "); }; + /** + * This function should be used to insert nodes in lists when nodes don't carry separators as the part of the node range, + * i.e. arguments in arguments lists, parameters in parameter lists etc. + * Note that separators are part of the node in statements and class elements. + */ ChangeTracker.prototype.insertNodeInListAfter = function (sourceFile, after, newNode, containingList) { if (containingList === void 0) { containingList = ts.formatting.SmartIndenter.getContainingList(after, sourceFile); } if (!containingList) { @@ -85289,19 +102104,53 @@ var ts; } var end = after.getEnd(); if (index !== containingList.length - 1) { - var nextToken = ts.getTokenAtPosition(sourceFile, after.end, false); + // any element except the last one + // use next sibling as an anchor + var nextToken = ts.getTokenAtPosition(sourceFile, after.end, /*includeJsDocComment*/ false); if (nextToken && isSeparator(after, nextToken)) { + // for list + // a, b, c + // create change for adding 'e' after 'a' as + // - find start of next element after a (it is b) + // - use this start as start and end position in final change + // - build text of change by formatting the text of node + separator + whitespace trivia of b + // in multiline case it will work as + // a, + // b, + // c, + // result - '*' denotes leading trivia that will be inserted after new text (displayed as '#') + // a,* + // ***insertedtext# + // ###b, + // c, + // find line and character of the next element var lineAndCharOfNextElement = ts.getLineAndCharacterOfPosition(sourceFile, skipWhitespacesAndLineBreaks(sourceFile.text, containingList[index + 1].getFullStart())); + // find line and character of the token that precedes next element (usually it is separator) var lineAndCharOfNextToken = ts.getLineAndCharacterOfPosition(sourceFile, nextToken.end); var prefix = void 0; var startPos = void 0; if (lineAndCharOfNextToken.line === lineAndCharOfNextElement.line) { + // next element is located on the same line with separator: + // a,$$$$b + // ^ ^ + // | |-next element + // |-separator + // where $$$ is some leading trivia + // for a newly inserted node we'll maintain the same relative position comparing to separator and replace leading trivia with spaces + // a, x,$$$$b + // ^ ^ ^ + // | | |-next element + // | |-new inserted node padded with spaces + // |-separator startPos = nextToken.end; prefix = spaces(lineAndCharOfNextElement.character - lineAndCharOfNextToken.character); } else { + // next element is located on different line that separator + // let insert position be the beginning of the line that contains next element startPos = ts.getStartPositionOfLine(lineAndCharOfNextElement.line, sourceFile); } + // write separator and leading trivia of the next element as suffix var suffix = "" + ts.tokenToString(nextToken.kind) + sourceFile.text.substring(nextToken.end, containingList[index + 1].getStart(sourceFile)); this.replaceRange(sourceFile, ts.createTextRange(startPos, containingList[index + 1].getStart(sourceFile)), newNode, { prefix: prefix, suffix: suffix }); } @@ -85311,22 +102160,35 @@ var ts; var afterStartLinePosition = ts.getLineStartPositionForPosition(afterStart, sourceFile); var separator = void 0; var multilineList = false; + // insert element after the last element in the list that has more than one item + // pick the element preceding the after element to: + // - pick the separator + // - determine if list is a multiline if (containingList.length === 1) { - separator = 26; + // if list has only one element then we'll format is as multiline if node has comment in trailing trivia, or as singleline otherwise + // i.e. var x = 1 // this is x + // | new element will be inserted at this position + separator = 26 /* CommaToken */; } else { + // element has more than one element, pick separator from the list var tokenBeforeInsertPosition = ts.findPrecedingToken(after.pos, sourceFile); - separator = isSeparator(after, tokenBeforeInsertPosition) ? tokenBeforeInsertPosition.kind : 26; + separator = isSeparator(after, tokenBeforeInsertPosition) ? tokenBeforeInsertPosition.kind : 26 /* CommaToken */; + // determine if list is multiline by checking lines of after element and element that precedes it. var afterMinusOneStartLinePosition = ts.getLineStartPositionForPosition(containingList[index - 1].getStart(sourceFile), sourceFile); multilineList = afterMinusOneStartLinePosition !== afterStartLinePosition; } if (hasCommentsBeforeLineBreak(sourceFile.text, after.end)) { + // in this case we'll always treat containing list as multiline multilineList = true; } if (multilineList) { + // insert separator immediately following the 'after' node to preserve comments in trailing trivia this.replaceRange(sourceFile, ts.createTextRange(end), ts.createToken(separator)); + // use the same indentation as 'after' item var indentation = ts.formatting.SmartIndenter.findFirstNonWhitespaceColumn(afterStartLinePosition, afterStart, sourceFile, this.formatContext.options); - var insertPos = ts.skipTrivia(sourceFile.text, end, true, false); + // insert element before the line break on the line that contains 'after' element + var insertPos = ts.skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true, /*stopAtComments*/ false); if (insertPos !== end && ts.isLineBreak(sourceFile.text.charCodeAt(insertPos - 1))) { insertPos--; } @@ -85343,6 +102205,7 @@ var ts; this.classesWithNodesInsertedAtStart.forEach(function (cls) { var sourceFile = cls.getSourceFile(); var _a = getClassBraceEnds(cls, sourceFile), openBraceEnd = _a[0], closeBraceEnd = _a[1]; + // For `class C { }` remove the whitespace inside the braces. if (ts.positionsAreOnSameLine(openBraceEnd, closeBraceEnd, sourceFile) && openBraceEnd !== closeBraceEnd - 1) { _this.deleteRange(sourceFile, ts.createTextRange(openBraceEnd, closeBraceEnd - 1)); } @@ -85361,6 +102224,12 @@ var ts; } }); }; + /** + * Note: after calling this, the TextChanges object must be discarded! + * @param validate only for tests + * The reason we must validate as part of this method is that `getNonFormattedText` changes the node's positions, + * so we can only call this once and can't get the non-formatted text separately. + */ ChangeTracker.prototype.getChanges = function (validate) { this.finishClassesWithNodesInsertedAtStart(); this.finishTrailingCommaAfterDeletingNodesInList(); @@ -85377,23 +102246,27 @@ var ts; return ChangeTracker; }()); textChanges_3.ChangeTracker = ChangeTracker; + // find first non-whitespace position in the leading trivia of the node function startPositionToDeleteNodeInList(sourceFile, node) { - return ts.skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, {}, Position.FullStart), false, true); + return ts.skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, {}, Position.FullStart), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); } function getClassBraceEnds(cls, sourceFile) { - return [ts.findChildOfKind(cls, 17, sourceFile).end, ts.findChildOfKind(cls, 18, sourceFile).end]; + return [ts.findChildOfKind(cls, 17 /* OpenBraceToken */, sourceFile).end, ts.findChildOfKind(cls, 18 /* CloseBraceToken */, sourceFile).end]; } var changesToText; (function (changesToText) { function getTextChangesFromChanges(changes, newLineCharacter, formatContext, validate) { return ts.group(changes, function (c) { return c.sourceFile.path; }).map(function (changesInFile) { var sourceFile = changesInFile[0].sourceFile; + // order changes by start position + // If the start position is the same, put the shorter range first, since an empty range (x, x) may precede (x, y) but not vice-versa. var normalized = ts.stableSort(changesInFile, function (a, b) { return (a.range.pos - b.range.pos) || (a.range.end - b.range.end); }); var _loop_22 = function (i) { ts.Debug.assert(normalized[i].range.end <= normalized[i + 1].range.pos, "Changes overlap", function () { return JSON.stringify(normalized[i].range) + " and " + JSON.stringify(normalized[i + 1].range); }); }; + // verify that change intervals do not overlap, except possibly at end points. for (var i = 0; i < normalized.length - 1; i++) { _loop_22(i); } @@ -85405,8 +102278,9 @@ var ts; } changesToText.getTextChangesFromChanges = getTextChangesFromChanges; function newFileChanges(oldFile, fileName, statements, newLineCharacter, formatContext) { + // TODO: this emits the file, parses it back, then formats it that -- may be a less roundabout way to do this var nonFormattedText = statements.map(function (s) { return getNonformattedText(s, oldFile, newLineCharacter).text; }).join(newLineCharacter); - var sourceFile = ts.createSourceFile(fileName, nonFormattedText, 6, true); + var sourceFile = ts.createSourceFile(fileName, nonFormattedText, 6 /* ESNext */, /*setParentNodes*/ true); var changes = ts.formatting.formatDocument(sourceFile, formatContext); var text = applyChanges(nonFormattedText, changes); return { fileName: fileName, textChanges: [ts.createTextChange(ts.createTextSpan(0, 0), text)], isNewFile: true }; @@ -85422,11 +102296,13 @@ var ts; var _a = change.options, options = _a === void 0 ? {} : _a, pos = change.range.pos; var format = function (n) { return getFormattedTextOfNode(n, sourceFile, pos, options, newLineCharacter, formatContext, validate); }; var text = change.kind === ChangeKind.ReplaceWithMultipleNodes - ? change.nodes.map(function (n) { return ts.removeSuffix(format(n), newLineCharacter); }).join(change.options.joiner || newLineCharacter) + ? change.nodes.map(function (n) { return ts.removeSuffix(format(n), newLineCharacter); }).join(change.options.joiner || newLineCharacter) // TODO: GH#18217 : format(change.node); + // strip initial indentation (spaces or tabs) if text will be inserted in the middle of the line var noIndent = (options.preserveLeadingWhitespace || options.indentation !== undefined || ts.getLineStartPositionForPosition(pos, sourceFile) === pos) ? text : text.replace(/^\s+/, ""); return (options.prefix || "") + noIndent + (options.suffix || ""); } + /** Note: this may mutate `nodeIn`. */ function getFormattedTextOfNode(nodeIn, sourceFile, pos, _a, newLineCharacter, formatContext, validate) { var indentation = _a.indentation, prefix = _a.prefix, delta = _a.delta; var _b = getNonformattedText(nodeIn, sourceFile, newLineCharacter), node = _b.node, text = _b.text; @@ -85443,10 +102319,11 @@ var ts; var changes = ts.formatting.formatNodeGivenIndentation(node, file, sourceFile.languageVariant, initialIndentation, delta, formatContext); return applyChanges(text, changes); } + /** Note: output node may be mutated input node. */ function getNonformattedText(node, sourceFile, newLineCharacter) { var writer = new Writer(newLineCharacter); - var newLine = newLineCharacter === "\n" ? 1 : 0; - ts.createPrinter({ newLine: newLine }, writer).writeNode(4, node, sourceFile, writer); + var newLine = newLineCharacter === "\n" ? 1 /* LineFeed */ : 0 /* CarriageReturnLineFeed */; + ts.createPrinter({ newLine: newLine }, writer).writeNode(4 /* Unspecified */, node, sourceFile, writer); return { text: writer.getText(), node: assignPositionsToNode(node) }; } })(changesToText || (changesToText = {})); @@ -85462,7 +102339,8 @@ var ts; return ts.skipTrivia(s, 0) === s.length; } function assignPositionsToNode(node) { - var visited = ts.visitEachChild(node, assignPositionsToNode, ts.nullTransformationContext, assignPositionsToNodeArray, assignPositionsToNode); + var visited = ts.visitEachChild(node, assignPositionsToNode, ts.nullTransformationContext, assignPositionsToNodeArray, assignPositionsToNode); // TODO: GH#18217 + // create proxy node for non synthesized nodes var newNode = ts.nodeIsSynthesized(visited) ? visited : Object.create(visited); newNode.pos = getPos(node); newNode.end = getEnd(node); @@ -85473,12 +102351,13 @@ var ts; if (!visited) { return visited; } + // clone nodearray if necessary var nodeArray = visited === nodes ? ts.createNodeArray(visited.slice(0)) : visited; nodeArray.pos = getPos(nodes); nodeArray.end = getEnd(nodes); return nodeArray; } - var Writer = (function () { + var Writer = /** @class */ (function () { function Writer(newLine) { var _this = this; this.lastNonTriviaPosition = 0; @@ -85520,44 +102399,45 @@ var ts; while (ts.isWhiteSpaceLike(s.charCodeAt(s.length - i - 1))) { i++; } + // trim trailing whitespaces this.lastNonTriviaPosition -= i; } }; Writer.prototype.write = function (s) { this.writer.write(s); - this.setLastNonTriviaPosition(s, false); + this.setLastNonTriviaPosition(s, /*force*/ false); }; Writer.prototype.writeKeyword = function (s) { this.writer.writeKeyword(s); - this.setLastNonTriviaPosition(s, false); + this.setLastNonTriviaPosition(s, /*force*/ false); }; Writer.prototype.writeOperator = function (s) { this.writer.writeOperator(s); - this.setLastNonTriviaPosition(s, false); + this.setLastNonTriviaPosition(s, /*force*/ false); }; Writer.prototype.writePunctuation = function (s) { this.writer.writePunctuation(s); - this.setLastNonTriviaPosition(s, false); + this.setLastNonTriviaPosition(s, /*force*/ false); }; Writer.prototype.writeParameter = function (s) { this.writer.writeParameter(s); - this.setLastNonTriviaPosition(s, false); + this.setLastNonTriviaPosition(s, /*force*/ false); }; Writer.prototype.writeProperty = function (s) { this.writer.writeProperty(s); - this.setLastNonTriviaPosition(s, false); + this.setLastNonTriviaPosition(s, /*force*/ false); }; Writer.prototype.writeSpace = function (s) { this.writer.writeSpace(s); - this.setLastNonTriviaPosition(s, false); + this.setLastNonTriviaPosition(s, /*force*/ false); }; Writer.prototype.writeStringLiteral = function (s) { this.writer.writeStringLiteral(s); - this.setLastNonTriviaPosition(s, false); + this.setLastNonTriviaPosition(s, /*force*/ false); }; Writer.prototype.writeSymbol = function (s, sym) { this.writer.writeSymbol(s, sym); - this.setLastNonTriviaPosition(s, false); + this.setLastNonTriviaPosition(s, /*force*/ false); }; Writer.prototype.writeTextOfNode = function (text, node) { this.writer.writeTextOfNode(text, node); @@ -85576,11 +102456,11 @@ var ts; }; Writer.prototype.rawWrite = function (s) { this.writer.rawWrite(s); - this.setLastNonTriviaPosition(s, false); + this.setLastNonTriviaPosition(s, /*force*/ false); }; Writer.prototype.writeLiteral = function (s) { this.writer.writeLiteral(s); - this.setLastNonTriviaPosition(s, true); + this.setLastNonTriviaPosition(s, /*force*/ true); }; Writer.prototype.getTextPos = function () { return this.writer.getTextPos(); @@ -85611,17 +102491,20 @@ var ts; position = shebang.length; advancePastLineBreak(); } + // For a source file, it is possible there are detached comments we should not skip var ranges = ts.getLeadingCommentRanges(text, position); if (!ranges) return position; - if (ranges.length && ranges[0].kind === 3 && ts.isPinnedComment(text, ranges[0].pos)) { + // However we should still skip a pinned comment at the top + if (ranges.length && ranges[0].kind === 3 /* MultiLineCommentTrivia */ && ts.isPinnedComment(text, ranges[0].pos)) { position = ranges[0].end; advancePastLineBreak(); ranges = ranges.slice(1); } + // As well as any triple slash references for (var _i = 0, ranges_1 = ranges; _i < ranges_1.length; _i++) { var range = ranges_1[_i]; - if (range.kind === 2 && ts.isRecognizedTripleSlashComment(text, range.pos, range.end)) { + if (range.kind === 2 /* SingleLineCommentTrivia */ && ts.isRecognizedTripleSlashComment(text, range.pos, range.end)) { position = range.end; advancePastLineBreak(); continue; @@ -85634,7 +102517,7 @@ var ts; var charCode = text.charCodeAt(position); if (ts.isLineBreak(charCode)) { position++; - if (position < text.length && charCode === 13 && text.charCodeAt(position) === 10) { + if (position < text.length && charCode === 13 /* carriageReturn */ && text.charCodeAt(position) === 10 /* lineFeed */) { position++; } } @@ -85646,11 +102529,12 @@ var ts; } textChanges_3.isValidLocationToAddComment = isValidLocationToAddComment; function needSemicolonBetween(a, b) { - return (ts.isPropertySignature(a) || ts.isPropertyDeclaration(a)) && ts.isClassOrTypeElement(b) && b.name.kind === 147 - || ts.isStatementButNotDeclaration(a) && ts.isStatementButNotDeclaration(b); + return (ts.isPropertySignature(a) || ts.isPropertyDeclaration(a)) && ts.isClassOrTypeElement(b) && b.name.kind === 147 /* ComputedPropertyName */ + || ts.isStatementButNotDeclaration(a) && ts.isStatementButNotDeclaration(b); // TODO: only if b would start with a `(` or `[` } })(textChanges = ts.textChanges || (ts.textChanges = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -85663,7 +102547,7 @@ var ts; : ts.getLocaleSpecificMessage(diag); } function createCodeFixActionNoFixId(fixName, changes, description) { - return createCodeFixActionWorker(fixName, diagnosticToString(description), changes, undefined, undefined); + return createCodeFixActionWorker(fixName, diagnosticToString(description), changes, /*fixId*/ undefined, /*fixAllDescription*/ undefined); } codefix.createCodeFixActionNoFixId = createCodeFixActionNoFixId; function createCodeFixAction(fixName, changes, description, fixId, fixAllDescription, command) { @@ -85696,6 +102580,7 @@ var ts; } codefix.getFixes = getFixes; function getAllFixes(context) { + // Currently fixId is always a string. return fixIdToRegistration.get(ts.cast(context.fixId, ts.isString)).getAllCodeActions(context); } codefix.getAllFixes = getAllFixes; @@ -85725,11 +102610,15 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var refactor; (function (refactor_1) { + // A map with the refactor code as key, the refactor itself as value + // e.g. nonSuggestableRefactors[refactorCode] -> the refactor you want var refactors = ts.createMap(); + /** @param name An unique code associated with each refactor. Does not have to be human-readable. */ function registerRefactor(name, refactor) { refactors.set(name, refactor); } @@ -85752,6 +102641,7 @@ var ts; } ts.getRefactorContextSpan = getRefactorContextSpan; })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -85768,14 +102658,15 @@ var ts; getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { return makeChange(changes, diag.file, diag.start); }); }, }); function makeChange(changeTracker, sourceFile, pos) { - var token = ts.getTokenAtPosition(sourceFile, pos, false); + var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); var decorator = ts.findAncestor(token, ts.isDecorator); ts.Debug.assert(!!decorator, "Expected position to be owned by a decorator."); - var replacement = ts.createCall(decorator.expression, undefined, undefined); + var replacement = ts.createCall(decorator.expression, /*typeArguments*/ undefined, /*argumentsArray*/ undefined); changeTracker.replaceNode(sourceFile, decorator.expression, replacement); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -85799,7 +102690,8 @@ var ts; }); }, }); function getDeclaration(file, pos) { - var name = ts.getTokenAtPosition(file, pos, false); + var name = ts.getTokenAtPosition(file, pos, /*includeJsDocComment*/ false); + // For an arrow function with no name, 'name' lands on the first parameter. return ts.tryCast(ts.isParameter(name.parent) ? name.parent.parent : name.parent, parameterShouldGetTypeFromJSDoc); } function parameterShouldGetTypeFromJSDoc(node) { @@ -85818,9 +102710,9 @@ var ts; if (typeParameters.length) changes.insertTypeParameters(sourceFile, decl, typeParameters); } - var needParens = ts.isArrowFunction(decl) && !ts.findChildOfKind(decl, 19, sourceFile); + var needParens = ts.isArrowFunction(decl) && !ts.findChildOfKind(decl, 19 /* OpenParenToken */, sourceFile); if (needParens) - changes.insertNodeBefore(sourceFile, ts.first(decl.parameters), ts.createToken(19)); + changes.insertNodeBefore(sourceFile, ts.first(decl.parameters), ts.createToken(19 /* OpenParenToken */)); for (var _i = 0, _a = decl.parameters; _i < _a.length; _i++) { var param = _a[_i]; if (!param.type) { @@ -85830,7 +102722,7 @@ var ts; } } if (needParens) - changes.insertNodeAfter(sourceFile, ts.last(decl.parameters), ts.createToken(20)); + changes.insertNodeAfter(sourceFile, ts.last(decl.parameters), ts.createToken(20 /* CloseParenToken */)); if (!decl.type) { var returnType = ts.getJSDocReturnType(decl); if (returnType) @@ -85838,37 +102730,37 @@ var ts; } } else { - var jsdocType = ts.Debug.assertDefined(ts.getJSDocType(decl)); - ts.Debug.assert(!decl.type); + var jsdocType = ts.Debug.assertDefined(ts.getJSDocType(decl)); // If not defined, shouldn't have been an error to fix + ts.Debug.assert(!decl.type); // If defined, shouldn't have been an error to fix. changes.tryInsertTypeAnnotation(sourceFile, decl, transformJSDocType(jsdocType)); } } function isDeclarationWithType(node) { return ts.isFunctionLikeDeclaration(node) || - node.kind === 232 || - node.kind === 151 || - node.kind === 152; + node.kind === 232 /* VariableDeclaration */ || + node.kind === 151 /* PropertySignature */ || + node.kind === 152 /* PropertyDeclaration */; } function transformJSDocType(node) { switch (node.kind) { - case 279: - case 280: + case 279 /* JSDocAllType */: + case 280 /* JSDocUnknownType */: return ts.createTypeReferenceNode("any", ts.emptyArray); - case 283: + case 283 /* JSDocOptionalType */: return transformJSDocOptionalType(node); - case 282: + case 282 /* JSDocNonNullableType */: return transformJSDocType(node.type); - case 281: + case 281 /* JSDocNullableType */: return transformJSDocNullableType(node); - case 285: + case 285 /* JSDocVariadicType */: return transformJSDocVariadicType(node); - case 284: + case 284 /* JSDocFunctionType */: return transformJSDocFunctionType(node); - case 162: + case 162 /* TypeReference */: return transformJSDocTypeReference(node); default: - var visited = ts.visitEachChild(node, transformJSDocType, undefined); - ts.setEmitFlags(visited, 1); + var visited = ts.visitEachChild(node, transformJSDocType, /*context*/ undefined); // TODO: GH#18217 + ts.setEmitFlags(visited, 1 /* SingleLine */); return visited; } } @@ -85886,9 +102778,9 @@ var ts; } function transformJSDocParameter(node) { var index = node.parent.parameters.indexOf(node); - var isRest = node.type.kind === 285 && index === node.parent.parameters.length - 1; + var isRest = node.type.kind === 285 /* JSDocVariadicType */ && index === node.parent.parameters.length - 1; // TODO: GH#18217 var name = node.name || (isRest ? "rest" : "arg" + index); - var dotdotdot = isRest ? ts.createToken(24) : node.dotDotDotToken; + var dotdotdot = isRest ? ts.createToken(24 /* DotDotDotToken */) : node.dotDotDotToken; return ts.createParameter(node.decorators, node.modifiers, dotdotdot, name, node.questionToken, ts.visitNode(node.type, transformJSDocType), node.initializer); } function transformJSDocTypeReference(node) { @@ -85923,13 +102815,19 @@ var ts; return ts.createTypeReferenceNode(name, args); } function transformJSDocIndexSignature(node) { - var index = ts.createParameter(undefined, undefined, undefined, node.typeArguments[0].kind === 134 ? "n" : "s", undefined, ts.createTypeReferenceNode(node.typeArguments[0].kind === 134 ? "number" : "string", []), undefined); - var indexSignature = ts.createTypeLiteralNode([ts.createIndexSignature(undefined, undefined, [index], node.typeArguments[1])]); - ts.setEmitFlags(indexSignature, 1); + var index = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, node.typeArguments[0].kind === 134 /* NumberKeyword */ ? "n" : "s", + /*questionToken*/ undefined, ts.createTypeReferenceNode(node.typeArguments[0].kind === 134 /* NumberKeyword */ ? "number" : "string", []), + /*initializer*/ undefined); + var indexSignature = ts.createTypeLiteralNode([ts.createIndexSignature(/*decorators*/ undefined, /*modifiers*/ undefined, [index], node.typeArguments[1])]); + ts.setEmitFlags(indexSignature, 1 /* SingleLine */); return indexSignature; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -85947,28 +102845,29 @@ var ts; }); function doChange(changes, sourceFile, position, checker) { var deletedNodes = []; - var ctorSymbol = checker.getSymbolAtLocation(ts.getTokenAtPosition(sourceFile, position, false)); - if (!ctorSymbol || !(ctorSymbol.flags & (16 | 3))) { + var ctorSymbol = checker.getSymbolAtLocation(ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false)); + if (!ctorSymbol || !(ctorSymbol.flags & (16 /* Function */ | 3 /* Variable */))) { + // Bad input return undefined; } var ctorDeclaration = ctorSymbol.valueDeclaration; var precedingNode; var newClassDeclaration; switch (ctorDeclaration.kind) { - case 234: + case 234 /* FunctionDeclaration */: precedingNode = ctorDeclaration; deleteNode(ctorDeclaration); newClassDeclaration = createClassFromFunctionDeclaration(ctorDeclaration); break; - case 232: + case 232 /* VariableDeclaration */: precedingNode = ctorDeclaration.parent.parent; newClassDeclaration = createClassFromVariableDeclaration(ctorDeclaration); if (ctorDeclaration.parent.declarations.length === 1) { - ts.copyComments(precedingNode, newClassDeclaration, sourceFile); + ts.copyComments(precedingNode, newClassDeclaration, sourceFile); // TODO: GH#18217 deleteNode(precedingNode); } else { - deleteNode(ctorDeclaration, true); + deleteNode(ctorDeclaration, /*inList*/ true); } break; } @@ -85976,6 +102875,7 @@ var ts; return undefined; } ts.copyComments(ctorDeclaration, newClassDeclaration, sourceFile); + // Because the preceding node could be touched, we need to insert nodes before delete nodes. changes.insertNodeAfter(sourceFile, precedingNode, newClassDeclaration); for (var _i = 0, deletedNodes_1 = deletedNodes; _i < deletedNodes_1.length; _i++) { var _a = deletedNodes_1[_i], node = _a.node, inList = _a.inList; @@ -85988,23 +102888,26 @@ var ts; } function deleteNode(node, inList) { if (inList === void 0) { inList = false; } + // If parent node has already been deleted, do nothing if (!deletedNodes.some(function (n) { return ts.isNodeDescendantOf(node, n.node); })) { deletedNodes.push({ node: node, inList: inList }); } } function createClassElementsFromSymbol(symbol) { var memberElements = []; + // all instance members are stored in the "member" array of symbol if (symbol.members) { symbol.members.forEach(function (member) { - var memberElement = createClassElement(member, undefined); + var memberElement = createClassElement(member, /*modifiers*/ undefined); if (memberElement) { memberElements.push(memberElement); } }); } + // all static members are stored in the "exports" array of symbol if (symbol.exports) { symbol.exports.forEach(function (member) { - var memberElement = createClassElement(member, [ts.createToken(115)]); + var memberElement = createClassElement(member, [ts.createToken(115 /* StaticKeyword */)]); if (memberElement) { memberElements.push(memberElement); } @@ -86012,10 +102915,13 @@ var ts; } return memberElements; function shouldConvertDeclaration(_target, source) { + // Right now the only thing we can convert are function expressions - other values shouldn't get + // transformed. We can update this once ES public class properties are available. return ts.isFunctionLike(source); } function createClassElement(symbol, modifiers) { - if (!(symbol.flags & 8192)) { + // Right now the only thing we can convert are function expressions, which are marked as methods + if (!(symbol.flags & 8192 /* Method */)) { return; } var memberDeclaration = symbol.valueDeclaration; @@ -86023,40 +102929,48 @@ var ts; if (!shouldConvertDeclaration(memberDeclaration, assignmentBinaryExpression.right)) { return; } - var nodeToDelete = assignmentBinaryExpression.parent && assignmentBinaryExpression.parent.kind === 216 + // delete the entire statement if this expression is the sole expression to take care of the semicolon at the end + var nodeToDelete = assignmentBinaryExpression.parent && assignmentBinaryExpression.parent.kind === 216 /* ExpressionStatement */ ? assignmentBinaryExpression.parent : assignmentBinaryExpression; deleteNode(nodeToDelete); if (!assignmentBinaryExpression.right) { - return ts.createProperty([], modifiers, symbol.name, undefined, undefined, undefined); + return ts.createProperty([], modifiers, symbol.name, /*questionToken*/ undefined, + /*type*/ undefined, /*initializer*/ undefined); } switch (assignmentBinaryExpression.right.kind) { - case 192: { + case 192 /* FunctionExpression */: { var functionExpression = assignmentBinaryExpression.right; - var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(functionExpression, 120)); - var method = ts.createMethod(undefined, fullModifiers, undefined, memberDeclaration.name, undefined, undefined, functionExpression.parameters, undefined, functionExpression.body); + var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(functionExpression, 120 /* AsyncKeyword */)); + var method = ts.createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined, + /*typeParameters*/ undefined, functionExpression.parameters, /*type*/ undefined, functionExpression.body); ts.copyComments(assignmentBinaryExpression, method, sourceFile); return method; } - case 193: { + case 193 /* ArrowFunction */: { var arrowFunction = assignmentBinaryExpression.right; var arrowFunctionBody = arrowFunction.body; var bodyBlock = void 0; - if (arrowFunctionBody.kind === 213) { + // case 1: () => { return [1,2,3] } + if (arrowFunctionBody.kind === 213 /* Block */) { bodyBlock = arrowFunctionBody; } + // case 2: () => [1,2,3] else { bodyBlock = ts.createBlock([ts.createReturn(arrowFunctionBody)]); } - var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(arrowFunction, 120)); - var method = ts.createMethod(undefined, fullModifiers, undefined, memberDeclaration.name, undefined, undefined, arrowFunction.parameters, undefined, bodyBlock); + var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(arrowFunction, 120 /* AsyncKeyword */)); + var method = ts.createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined, + /*typeParameters*/ undefined, arrowFunction.parameters, /*type*/ undefined, bodyBlock); ts.copyComments(assignmentBinaryExpression, method, sourceFile); return method; } default: { + // Don't try to declare members in JavaScript files if (ts.isSourceFileJavaScript(sourceFile)) { return; } - var prop = ts.createProperty(undefined, modifiers, memberDeclaration.name, undefined, undefined, assignmentBinaryExpression.right); + var prop = ts.createProperty(/*decorators*/ undefined, modifiers, memberDeclaration.name, /*questionToken*/ undefined, + /*type*/ undefined, assignmentBinaryExpression.right); ts.copyComments(assignmentBinaryExpression.parent, prop, sourceFile); return prop; } @@ -86065,27 +102979,31 @@ var ts; } function createClassFromVariableDeclaration(node) { var initializer = node.initializer; - if (!initializer || initializer.kind !== 192) { + if (!initializer || initializer.kind !== 192 /* FunctionExpression */) { return undefined; } - if (node.name.kind !== 71) { + if (node.name.kind !== 71 /* Identifier */) { return undefined; } var memberElements = createClassElementsFromSymbol(node.symbol); if (initializer.body) { - memberElements.unshift(ts.createConstructor(undefined, undefined, initializer.parameters, initializer.body)); + memberElements.unshift(ts.createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, initializer.parameters, initializer.body)); } - var modifiers = getModifierKindFromSource(precedingNode, 84); - var cls = ts.createClassDeclaration(undefined, modifiers, node.name, undefined, undefined, memberElements); + var modifiers = getModifierKindFromSource(precedingNode, 84 /* ExportKeyword */); + var cls = ts.createClassDeclaration(/*decorators*/ undefined, modifiers, node.name, + /*typeParameters*/ undefined, /*heritageClauses*/ undefined, memberElements); + // Don't call copyComments here because we'll already leave them in place return cls; } function createClassFromFunctionDeclaration(node) { var memberElements = createClassElementsFromSymbol(ctorSymbol); if (node.body) { - memberElements.unshift(ts.createConstructor(undefined, undefined, node.parameters, node.body)); + memberElements.unshift(ts.createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, node.parameters, node.body)); } - var modifiers = getModifierKindFromSource(node, 84); - var cls = ts.createClassDeclaration(undefined, modifiers, node.name, undefined, undefined, memberElements); + var modifiers = getModifierKindFromSource(node, 84 /* ExportKeyword */); + var cls = ts.createClassDeclaration(/*decorators*/ undefined, modifiers, node.name, + /*typeParameters*/ undefined, /*heritageClauses*/ undefined, memberElements); + // Don't call copyComments here because we'll already leave them in place return cls; } } @@ -86094,6 +103012,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -86111,6 +103030,7 @@ var ts; } } }); + // No support for fix-all since this applies to the whole file at once anyway. return [codefix.createCodeFixActionNoFixId("convertToEs6Module", changes, ts.Diagnostics.Convert_to_ES6_module)]; }, }); @@ -86123,17 +103043,18 @@ var ts; } var importNode = ts.importFromModuleSpecifier(moduleSpecifier); switch (importNode.kind) { - case 243: - changes.replaceNode(importingFile, importNode, ts.makeImport(importNode.name, undefined, moduleSpecifier, quotePreference)); + case 243 /* ImportEqualsDeclaration */: + changes.replaceNode(importingFile, importNode, ts.makeImport(importNode.name, /*namedImports*/ undefined, moduleSpecifier, quotePreference)); break; - case 187: - if (ts.isRequireCall(importNode, false)) { + case 187 /* CallExpression */: + if (ts.isRequireCall(importNode, /*checkArgumentIsStringLiteralLike*/ false)) { changes.replaceNode(importingFile, importNode, ts.createPropertyAccess(ts.getSynthesizedDeepClone(importNode), "default")); } break; } } } + /** @returns Whether we converted a `module.exports =` to a default export. */ function convertFileToEs6Module(sourceFile, checker, changes, target, quotePreference) { var identifiers = { original: collectFreeIdentifiers(sourceFile), additional: ts.createMap() }; var exports = collectExportRenames(sourceFile, checker, identifiers); @@ -86151,7 +103072,8 @@ var ts; forEachExportReference(sourceFile, function (node) { var _a = node.name, text = _a.text, originalKeywordKind = _a.originalKeywordKind; if (!res.has(text) && (originalKeywordKind !== undefined && ts.isNonContextualKeyword(originalKeywordKind) - || checker.resolveName(node.name.text, node, 67216319, true))) { + || checker.resolveName(node.name.text, node, 67216319 /* Value */, /*excludeGlobals*/ true))) { + // Unconditionally add an underscore in case `text` is a keyword. res.set(text, makeUniqueName("_" + text, identifiers)); } }); @@ -86170,31 +103092,33 @@ var ts; sourceFile.forEachChild(function recur(node) { if (ts.isPropertyAccessExpression(node) && ts.isExportsOrModuleExportsOrAlias(sourceFile, node.expression)) { var parent = node.parent; - cb(node, ts.isBinaryExpression(parent) && parent.left === node && parent.operatorToken.kind === 58); + cb(node, ts.isBinaryExpression(parent) && parent.left === node && parent.operatorToken.kind === 58 /* EqualsToken */); } node.forEachChild(recur); }); } function convertStatement(sourceFile, statement, checker, changes, identifiers, target, exports, quotePreference) { switch (statement.kind) { - case 214: + case 214 /* VariableStatement */: convertVariableStatement(sourceFile, statement, changes, checker, identifiers, target, quotePreference); return false; - case 216: { + case 216 /* ExpressionStatement */: { var expression = statement.expression; switch (expression.kind) { - case 187: { - if (ts.isRequireCall(expression, true)) { - changes.replaceNode(sourceFile, statement, ts.makeImport(undefined, undefined, expression.arguments[0], quotePreference)); + case 187 /* CallExpression */: { + if (ts.isRequireCall(expression, /*checkArgumentIsStringLiteralLike*/ true)) { + // For side-effecting require() call, just make a side-effecting import. + changes.replaceNode(sourceFile, statement, ts.makeImport(/*name*/ undefined, /*namedImports*/ undefined, expression.arguments[0], quotePreference)); } return false; } - case 200: { + case 200 /* BinaryExpression */: { var operatorToken = expression.operatorToken; - return operatorToken.kind === 58 && convertAssignment(sourceFile, checker, expression, changes, exports); + return operatorToken.kind === 58 /* EqualsToken */ && convertAssignment(sourceFile, checker, expression, changes, exports); } } } + // falls through default: return false; } @@ -86206,35 +103130,41 @@ var ts; var name = decl.name, initializer = decl.initializer; if (initializer) { if (ts.isExportsOrModuleExportsOrAlias(sourceFile, initializer)) { + // `const alias = module.exports;` can be removed. foundImport = true; return []; } - else if (ts.isRequireCall(initializer, true)) { + else if (ts.isRequireCall(initializer, /*checkArgumentIsStringLiteralLike*/ true)) { foundImport = true; return convertSingleImport(sourceFile, name, initializer.arguments[0], changes, checker, identifiers, target, quotePreference); } - else if (ts.isPropertyAccessExpression(initializer) && ts.isRequireCall(initializer.expression, true)) { + else if (ts.isPropertyAccessExpression(initializer) && ts.isRequireCall(initializer.expression, /*checkArgumentIsStringLiteralLike*/ true)) { foundImport = true; return convertPropertyAccessImport(name, initializer.name.text, initializer.expression.arguments[0], identifiers, quotePreference); } } - return ts.createVariableStatement(undefined, ts.createVariableDeclarationList([decl], declarationList.flags)); + // Move it out to its own variable statement. (This will not be used if `!foundImport`) + return ts.createVariableStatement(/*modifiers*/ undefined, ts.createVariableDeclarationList([decl], declarationList.flags)); }); if (foundImport) { + // useNonAdjustedEndPosition to ensure we don't eat the newline after the statement. changes.replaceNodeWithNodes(sourceFile, statement, newNodes); } } + /** Converts `const name = require("moduleSpecifier").propertyName` */ function convertPropertyAccessImport(name, propertyName, moduleSpecifier, identifiers, quotePreference) { switch (name.kind) { - case 180: - case 181: { + case 180 /* ObjectBindingPattern */: + case 181 /* ArrayBindingPattern */: { + // `const [a, b] = require("c").d` --> `import { d } from "c"; const [a, b] = d;` var tmp = makeUniqueName(propertyName, identifiers); return [ makeSingleImport(tmp, propertyName, moduleSpecifier, quotePreference), - makeConst(undefined, name, ts.createIdentifier(tmp)), + makeConst(/*modifiers*/ undefined, name, ts.createIdentifier(tmp)), ]; } - case 71: + case 71 /* Identifier */: + // `const a = require("b").c` --> `import { c as a } from "./b"; return [makeSingleImport(name.text, propertyName, moduleSpecifier, quotePreference)]; default: return ts.Debug.assertNever(name); @@ -86247,11 +103177,12 @@ var ts; } if (ts.isExportsOrModuleExportsOrAlias(sourceFile, left)) { if (ts.isExportsOrModuleExportsOrAlias(sourceFile, right)) { + // `const alias = module.exports;` or `module.exports = alias;` can be removed. changes.deleteNode(sourceFile, assignment.parent); } else { var replacement = ts.isObjectLiteralExpression(right) ? tryChangeModuleExportsObject(right) - : ts.isRequireCall(right, true) ? convertReExportAll(right.arguments[0], checker) + : ts.isRequireCall(right, /*checkArgumentIsStringLiteralLike*/ true) ? convertReExportAll(right.arguments[0], checker) : undefined; if (replacement) { changes.replaceNodeWithNodes(sourceFile, assignment.parent, replacement[0]); @@ -86268,18 +103199,23 @@ var ts; } return false; } + /** + * Convert `module.exports = { ... }` to individual exports.. + * We can't always do this if the module has interesting members -- then it will be a default export instead. + */ function tryChangeModuleExportsObject(object) { var statements = ts.mapAllOrFail(object.properties, function (prop) { switch (prop.kind) { - case 156: - case 157: - case 271: - case 272: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + // TODO: Maybe we should handle this? See fourslash test `refactorConvertToEs6Module_export_object_shorthand.ts`. + case 271 /* ShorthandPropertyAssignment */: + case 272 /* SpreadAssignment */: return undefined; - case 270: + case 270 /* PropertyAssignment */: return !ts.isIdentifier(prop.name) ? undefined : convertExportsDotXEquals_replaceNode(prop.name.text, prop.initializer); - case 154: - return !ts.isIdentifier(prop.name) ? undefined : functionExpressionToDeclaration(prop.name.text, [ts.createToken(84)], prop); + case 154 /* MethodDeclaration */: + return !ts.isIdentifier(prop.name) ? undefined : functionExpressionToDeclaration(prop.name.text, [ts.createToken(84 /* ExportKeyword */)], prop); default: ts.Debug.assertNever(prop); } @@ -86287,11 +103223,16 @@ var ts; return statements && [statements, false]; } function convertNamedExport(sourceFile, assignment, changes, exports) { + // If "originalKeywordKind" was set, this is e.g. `exports. var text = assignment.left.name.text; var rename = exports.get(text); if (rename !== undefined) { + /* + const _class = 0; + export { _class as class }; + */ var newNodes = [ - makeConst(undefined, rename, assignment.right), + makeConst(/*modifiers*/ undefined, rename, assignment.right), makeExportDeclaration([ts.createExportSpecifier(rename, text)]), ]; changes.replaceNodeWithNodes(sourceFile, assignment.parent, newNodes); @@ -86301,6 +103242,7 @@ var ts; } } function convertReExportAll(reExported, checker) { + // `module.exports = require("x");` ==> `export * from "x"; export { default } from "x";` var moduleSpecifier = reExported.text; var moduleSymbol = checker.getSymbolAtLocation(reExported); var exports = moduleSymbol ? moduleSymbol.exports : ts.emptyUnderscoreEscapedMap; @@ -86308,87 +103250,113 @@ var ts; ? [[reExportDefault(moduleSpecifier)], true] : !exports.has("default") ? [[reExportStar(moduleSpecifier)], false] + // If there's some non-default export, must include both `export *` and `export default`. : exports.size > 1 ? [[reExportStar(moduleSpecifier), reExportDefault(moduleSpecifier)], true] : [[reExportDefault(moduleSpecifier)], true]; } function reExportStar(moduleSpecifier) { - return makeExportDeclaration(undefined, moduleSpecifier); + return makeExportDeclaration(/*exportClause*/ undefined, moduleSpecifier); } function reExportDefault(moduleSpecifier) { - return makeExportDeclaration([ts.createExportSpecifier(undefined, "default")], moduleSpecifier); + return makeExportDeclaration([ts.createExportSpecifier(/*propertyName*/ undefined, "default")], moduleSpecifier); } function convertExportsPropertyAssignment(_a, sourceFile, changes) { var left = _a.left, right = _a.right, parent = _a.parent; var name = left.name.text; if ((ts.isFunctionExpression(right) || ts.isArrowFunction(right) || ts.isClassExpression(right)) && (!right.name || right.name.text === name)) { - changes.replaceRange(sourceFile, { pos: left.getStart(sourceFile), end: right.getStart(sourceFile) }, ts.createToken(84), { suffix: " " }); + // `exports.f = function() {}` -> `export function f() {}` -- Replace `exports.f = ` with `export `, and insert the name after `function`. + changes.replaceRange(sourceFile, { pos: left.getStart(sourceFile), end: right.getStart(sourceFile) }, ts.createToken(84 /* ExportKeyword */), { suffix: " " }); if (!right.name) changes.insertName(sourceFile, right, name); - var semi = ts.findChildOfKind(parent, 25, sourceFile); + var semi = ts.findChildOfKind(parent, 25 /* SemicolonToken */, sourceFile); if (semi) changes.deleteNode(sourceFile, semi, { useNonAdjustedEndPosition: true }); } else { - changes.replaceNodeRangeWithNodes(sourceFile, left.expression, ts.findChildOfKind(left, 23, sourceFile), [ts.createToken(84), ts.createToken(76)], { joiner: " ", suffix: " " }); + // `exports.f = function g() {}` -> `export const f = function g() {}` -- just replace `exports.` with `export const ` + changes.replaceNodeRangeWithNodes(sourceFile, left.expression, ts.findChildOfKind(left, 23 /* DotToken */, sourceFile), [ts.createToken(84 /* ExportKeyword */), ts.createToken(76 /* ConstKeyword */)], { joiner: " ", suffix: " " }); } } + // TODO: GH#22492 this will cause an error if a change has been made inside the body of the node. function convertExportsDotXEquals_replaceNode(name, exported) { - var modifiers = [ts.createToken(84)]; + var modifiers = [ts.createToken(84 /* ExportKeyword */)]; switch (exported.kind) { - case 192: { + case 192 /* FunctionExpression */: { var expressionName = exported.name; if (expressionName && expressionName.text !== name) { + // `exports.f = function g() {}` -> `export const f = function g() {}` return exportConst(); } } - case 193: + // falls through + case 193 /* ArrowFunction */: + // `exports.f = function() {}` --> `export function f() {}` return functionExpressionToDeclaration(name, modifiers, exported); - case 205: + case 205 /* ClassExpression */: + // `exports.C = class {}` --> `export class C {}` return classExpressionToDeclaration(name, modifiers, exported); default: return exportConst(); } function exportConst() { - return makeConst(modifiers, ts.createIdentifier(name), exported); + // `exports.x = 0;` --> `export const x = 0;` + return makeConst(modifiers, ts.createIdentifier(name), exported); // TODO: GH#18217 } } + /** + * Converts `const <> = require("x");`. + * Returns nodes that will replace the variable declaration for the commonjs import. + * May also make use `changes` to remove qualifiers at the use sites of imports, to change `mod.x` to `x`. + */ function convertSingleImport(file, name, moduleSpecifier, changes, checker, identifiers, target, quotePreference) { switch (name.kind) { - case 180: { + case 180 /* ObjectBindingPattern */: { var importSpecifiers = ts.mapAllOrFail(name.elements, function (e) { return e.dotDotDotToken || e.initializer || e.propertyName && !ts.isIdentifier(e.propertyName) || !ts.isIdentifier(e.name) ? undefined : makeImportSpecifier(e.propertyName && e.propertyName.text, e.name.text); - }); + }); // tslint:disable-line no-unnecessary-type-assertion (TODO: GH#18217) if (importSpecifiers) { - return [ts.makeImport(undefined, importSpecifiers, moduleSpecifier, quotePreference)]; + return [ts.makeImport(/*name*/ undefined, importSpecifiers, moduleSpecifier, quotePreference)]; } } - case 181: { + // falls through -- object destructuring has an interesting pattern and must be a variable declaration + case 181 /* ArrayBindingPattern */: { + /* + import x from "x"; + const [a, b, c] = x; + */ var tmp = makeUniqueName(codefix.moduleSpecifierToValidIdentifier(moduleSpecifier.text, target), identifiers); return [ - ts.makeImport(ts.createIdentifier(tmp), undefined, moduleSpecifier, quotePreference), - makeConst(undefined, ts.getSynthesizedDeepClone(name), ts.createIdentifier(tmp)), + ts.makeImport(ts.createIdentifier(tmp), /*namedImports*/ undefined, moduleSpecifier, quotePreference), + makeConst(/*modifiers*/ undefined, ts.getSynthesizedDeepClone(name), ts.createIdentifier(tmp)), ]; } - case 71: + case 71 /* Identifier */: return convertSingleIdentifierImport(file, name, moduleSpecifier, changes, checker, identifiers, quotePreference); default: return ts.Debug.assertNever(name); } } + /** + * Convert `import x = require("x").` + * Also converts uses like `x.y()` to `y()` and uses a named import. + */ function convertSingleIdentifierImport(file, name, moduleSpecifier, changes, checker, identifiers, quotePreference) { var nameSymbol = checker.getSymbolAtLocation(name); + // Maps from module property name to name actually used. (The same if there isn't shadowing.) var namedBindingsNames = ts.createMap(); + // True if there is some non-property use like `x()` or `f(x)`. var needDefaultImport = false; for (var _i = 0, _a = identifiers.original.get(name.text); _i < _a.length; _i++) { var use = _a[_i]; if (checker.getSymbolAtLocation(use) !== nameSymbol || use === name) { + // This was a use of a different symbol with the same name, due to shadowing. Ignore. continue; } var parent = use.parent; if (ts.isPropertyAccessExpression(parent)) { var expression = parent.expression, propertyName = parent.name.text; - ts.Debug.assert(expression === use); + ts.Debug.assert(expression === use); // Else shouldn't have been in `collectIdentifiers` var idName = namedBindingsNames.get(propertyName); if (idName === undefined) { idName = makeUniqueName(propertyName, identifiers); @@ -86405,10 +103373,12 @@ var ts; return ts.createImportSpecifier(propertyName === idName ? undefined : ts.createIdentifier(propertyName), ts.createIdentifier(idName)); })); if (!namedBindings) { + // If it was unused, ensure that we at least import *something*. needDefaultImport = true; } return [ts.makeImport(needDefaultImport ? ts.getSynthesizedDeepClone(name) : undefined, namedBindings, moduleSpecifier, quotePreference)]; } + // Identifiers helpers function makeUniqueName(name, identifiers) { while (identifiers.original.has(name) || identifiers.additional.has(name)) { name = "_" + name; @@ -86421,6 +103391,10 @@ var ts; forEachFreeIdentifier(file, function (id) { return map.add(id.text, id); }); return map; } + /** + * A free identifier is an identifier that can be accessed through name lookup as a local variable. + * In the expression `x.y`, `x` is a free identifier, but `y` is not. + */ function forEachFreeIdentifier(node, cb) { if (ts.isIdentifier(node) && isFreeIdentifier(node)) cb(node); @@ -86429,38 +103403,44 @@ var ts; function isFreeIdentifier(node) { var parent = node.parent; switch (parent.kind) { - case 185: + case 185 /* PropertyAccessExpression */: return parent.name !== node; - case 182: + case 182 /* BindingElement */: return parent.propertyName !== node; - case 248: + case 248 /* ImportSpecifier */: return parent.propertyName !== node; default: return true; } } + // Node helpers function functionExpressionToDeclaration(name, additionalModifiers, fn) { - return ts.createFunctionDeclaration(ts.getSynthesizedDeepClones(fn.decorators), ts.concatenate(additionalModifiers, ts.getSynthesizedDeepClones(fn.modifiers)), ts.getSynthesizedDeepClone(fn.asteriskToken), name, ts.getSynthesizedDeepClones(fn.typeParameters), ts.getSynthesizedDeepClones(fn.parameters), ts.getSynthesizedDeepClone(fn.type), ts.convertToFunctionBody(ts.getSynthesizedDeepClone(fn.body))); + return ts.createFunctionDeclaration(ts.getSynthesizedDeepClones(fn.decorators), // TODO: GH#19915 Don't think this is even legal. + ts.concatenate(additionalModifiers, ts.getSynthesizedDeepClones(fn.modifiers)), ts.getSynthesizedDeepClone(fn.asteriskToken), name, ts.getSynthesizedDeepClones(fn.typeParameters), ts.getSynthesizedDeepClones(fn.parameters), ts.getSynthesizedDeepClone(fn.type), ts.convertToFunctionBody(ts.getSynthesizedDeepClone(fn.body))); } function classExpressionToDeclaration(name, additionalModifiers, cls) { - return ts.createClassDeclaration(ts.getSynthesizedDeepClones(cls.decorators), ts.concatenate(additionalModifiers, ts.getSynthesizedDeepClones(cls.modifiers)), name, ts.getSynthesizedDeepClones(cls.typeParameters), ts.getSynthesizedDeepClones(cls.heritageClauses), ts.getSynthesizedDeepClones(cls.members)); + return ts.createClassDeclaration(ts.getSynthesizedDeepClones(cls.decorators), // TODO: GH#19915 Don't think this is even legal. + ts.concatenate(additionalModifiers, ts.getSynthesizedDeepClones(cls.modifiers)), name, ts.getSynthesizedDeepClones(cls.typeParameters), ts.getSynthesizedDeepClones(cls.heritageClauses), ts.getSynthesizedDeepClones(cls.members)); } function makeSingleImport(localName, propertyName, moduleSpecifier, quotePreference) { return propertyName === "default" - ? ts.makeImport(ts.createIdentifier(localName), undefined, moduleSpecifier, quotePreference) - : ts.makeImport(undefined, [makeImportSpecifier(propertyName, localName)], moduleSpecifier, quotePreference); + ? ts.makeImport(ts.createIdentifier(localName), /*namedImports*/ undefined, moduleSpecifier, quotePreference) + : ts.makeImport(/*name*/ undefined, [makeImportSpecifier(propertyName, localName)], moduleSpecifier, quotePreference); } function makeImportSpecifier(propertyName, name) { return ts.createImportSpecifier(propertyName !== undefined && propertyName !== name ? ts.createIdentifier(propertyName) : undefined, ts.createIdentifier(name)); } function makeConst(modifiers, name, init) { - return ts.createVariableStatement(modifiers, ts.createVariableDeclarationList([ts.createVariableDeclaration(name, undefined, init)], 2)); + return ts.createVariableStatement(modifiers, ts.createVariableDeclarationList([ts.createVariableDeclaration(name, /*type*/ undefined, init)], 2 /* Const */)); } function makeExportDeclaration(exportSpecifiers, moduleSpecifier) { - return ts.createExportDeclaration(undefined, undefined, exportSpecifiers && ts.createNamedExports(exportSpecifiers), moduleSpecifier === undefined ? undefined : ts.createLiteral(moduleSpecifier)); + return ts.createExportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, exportSpecifiers && ts.createNamedExports(exportSpecifiers), moduleSpecifier === undefined ? undefined : ts.createLiteral(moduleSpecifier)); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -86486,24 +103466,25 @@ var ts; }); }, }); function getQualifiedName(sourceFile, pos) { - var qualifiedName = ts.findAncestor(ts.getTokenAtPosition(sourceFile, pos, true), ts.isQualifiedName); + var qualifiedName = ts.findAncestor(ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ true), ts.isQualifiedName); ts.Debug.assert(!!qualifiedName, "Expected position to be owned by a qualified name."); return ts.isIdentifier(qualifiedName.left) ? qualifiedName : undefined; } function doChange(changeTracker, sourceFile, qualifiedName) { var rightText = qualifiedName.right.text; - var replacement = ts.createIndexedAccessTypeNode(ts.createTypeReferenceNode(qualifiedName.left, undefined), ts.createLiteralTypeNode(ts.createLiteral(rightText))); + var replacement = ts.createIndexedAccessTypeNode(ts.createTypeReferenceNode(qualifiedName.left, /*typeArguments*/ undefined), ts.createLiteralTypeNode(ts.createLiteral(rightText))); changeTracker.replaceNode(sourceFile, qualifiedName, replacement); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; (function (codefix) { var errorCodes = [ts.Diagnostics.Class_0_incorrectly_implements_interface_1.code, ts.Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass.code]; - var fixId = "fixClassIncorrectlyImplementsInterface"; + var fixId = "fixClassIncorrectlyImplementsInterface"; // TODO: share a group with fixClassDoesntImplementInheritedAbstractMember? codefix.registerCodeFix({ errorCodes: errorCodes, getCodeActions: function (context) { @@ -86530,22 +103511,24 @@ var ts; }, }); function getClass(sourceFile, pos) { - return ts.Debug.assertDefined(ts.getContainingClass(ts.getTokenAtPosition(sourceFile, pos, false))); + return ts.Debug.assertDefined(ts.getContainingClass(ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false))); } function symbolPointsToNonPrivateMember(symbol) { - return !(ts.getModifierFlags(symbol.valueDeclaration) & 8); + return !(ts.getModifierFlags(symbol.valueDeclaration) & 8 /* Private */); } function addMissingDeclarations(checker, implementedTypeNode, sourceFile, classDeclaration, changeTracker, preferences) { var maybeHeritageClauseSymbol = getHeritageClauseSymbolTable(classDeclaration, checker); + // Note that this is ultimately derived from a map indexed by symbol names, + // so duplicates cannot occur. var implementedType = checker.getTypeAtLocation(implementedTypeNode); var implementedTypeSymbols = checker.getPropertiesOfType(implementedType); var nonPrivateAndNotExistedInHeritageClauseMembers = implementedTypeSymbols.filter(ts.and(symbolPointsToNonPrivateMember, function (symbol) { return !maybeHeritageClauseSymbol.has(symbol.escapedName); })); var classType = checker.getTypeAtLocation(classDeclaration); if (!classType.getNumberIndexType()) { - createMissingIndexSignatureDeclaration(implementedType, 1); + createMissingIndexSignatureDeclaration(implementedType, 1 /* Number */); } if (!classType.getStringIndexType()) { - createMissingIndexSignatureDeclaration(implementedType, 0); + createMissingIndexSignatureDeclaration(implementedType, 0 /* String */); } codefix.createMissingMemberNodes(classDeclaration, nonPrivateAndNotExistedInHeritageClauseMembers, checker, preferences, function (member) { return changeTracker.insertNodeAtClassStart(sourceFile, classDeclaration, member); }); function createMissingIndexSignatureDeclaration(type, kind) { @@ -86565,6 +103548,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -86581,10 +103565,12 @@ var ts; getCodeActions: function (context) { return context.errorCode === ts.Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code ? getActionsForUMDImport(context) : getActionsForNonUMDImport(context); }, + // TODO: GH#20315 fixIds: [], getAllCodeActions: ts.notImplemented, }); function createCodeAction(descriptionDiagnostic, diagnosticArgs, changes) { + // TODO: GH#20315 return codefix.createCodeFixActionNoFixId("import", changes, [descriptionDiagnostic].concat(diagnosticArgs)); } function convertToImportCodeFixContext(context, symbolToken, symbolName) { @@ -86613,6 +103599,7 @@ var ts; function getImportCompletionAction(exportedSymbol, moduleSymbol, sourceFile, symbolName, host, program, checker, compilerOptions, allSourceFiles, formatContext, getCanonicalFileName, symbolToken, preferences) { var exportInfos = getAllReExportingModules(exportedSymbol, moduleSymbol, symbolName, sourceFile, checker, allSourceFiles); ts.Debug.assert(exportInfos.some(function (info) { return info.moduleSymbol === moduleSymbol; })); + // We sort the best codefixes first, so taking `first` is best for completions. var moduleSpecifier = ts.first(getNewImportInfos(program, sourceFile, exportInfos, host, preferences)).moduleSpecifier; var ctx = { host: host, program: program, checker: checker, compilerOptions: compilerOptions, sourceFile: sourceFile, formatContext: formatContext, symbolName: symbolName, getCanonicalFileName: getCanonicalFileName, symbolToken: symbolToken, preferences: preferences }; return { moduleSpecifier: moduleSpecifier, codeAction: ts.first(getCodeActionsForImport(exportInfos, ctx)) }; @@ -86621,14 +103608,15 @@ var ts; function getAllReExportingModules(exportedSymbol, exportingModuleSymbol, symbolName, sourceFile, checker, allSourceFiles) { var result = []; forEachExternalModule(checker, allSourceFiles, function (moduleSymbol, moduleFile) { + // Don't import from a re-export when looking "up" like to `./index` or `../index`. if (moduleFile && moduleSymbol !== exportingModuleSymbol && ts.startsWith(sourceFile.fileName, ts.getDirectoryPath(moduleFile.fileName))) { return; } for (var _i = 0, _a = checker.getExportsOfModule(moduleSymbol); _i < _a.length; _i++) { var exported = _a[_i]; - if ((exported.escapedName === "default" || exported.name === symbolName) && ts.skipAlias(exported, checker) === exportedSymbol) { - var isDefaultExport = checker.tryGetMemberInModuleExports("default", moduleSymbol) === exported; - result.push({ moduleSymbol: moduleSymbol, importKind: isDefaultExport ? 1 : 0 }); + if ((exported.escapedName === "default" /* Default */ || exported.name === symbolName) && ts.skipAlias(exported, checker) === exportedSymbol) { + var isDefaultExport = checker.tryGetMemberInModuleExports("default" /* Default */, moduleSymbol) === exported; + result.push({ moduleSymbol: moduleSymbol, importKind: isDefaultExport ? 1 /* Default */ : 0 /* Named */ }); } } }); @@ -86646,11 +103634,23 @@ var ts; if (addToExisting) { useExisting.push(addToExisting); } - else { + else { // Don't bother providing an action to add a new import if we can add to an existing one. getCodeActionsForAddImport(exportInfos, context, existingImports, addNew); } } function tryUseExistingNamespaceImport(existingImports, context, symbolToken, checker) { + // It is possible that multiple import statements with the same specifier exist in the file. + // e.g. + // + // import * as ns from "foo"; + // import { member1, member2 } from "foo"; + // + // member3/**/ <-- cusor here + // + // in this case we should provie 2 actions: + // 1. change "member3" to "ns.member3" + // 2. add "member3" to the second import statement's import list + // and it is up to the user to decide which one fits best. return !symbolToken || !ts.isIdentifier(symbolToken) ? undefined : ts.firstDefined(existingImports, function (_a) { var declaration = _a.declaration; var namespace = getNamespaceImportName(declaration); @@ -86665,7 +103665,7 @@ var ts; function tryAddToExistingImport(existingImports, context) { return ts.firstDefined(existingImports, function (_a) { var declaration = _a.declaration, importKind = _a.importKind; - if (declaration.kind === 244 && declaration.importClause) { + if (declaration.kind === 244 /* ImportDeclaration */ && declaration.importClause) { var changes = tryUpdateExistingImport(context, declaration.importClause, importKind); if (changes) { var moduleSpecifierWithoutQuotes = ts.stripQuotes(declaration.moduleSpecifier.getText()); @@ -86675,9 +103675,9 @@ var ts; }); } function getNamespaceImportName(declaration) { - if (declaration.kind === 244) { + if (declaration.kind === 244 /* ImportDeclaration */) { var namedBindings = declaration.importClause && ts.isImportClause(declaration.importClause) && declaration.importClause.namedBindings; - return namedBindings && namedBindings.kind === 246 ? namedBindings.name : undefined; + return namedBindings && namedBindings.kind === 246 /* NamespaceImport */ ? namedBindings.name : undefined; } else { return declaration.name; @@ -86688,7 +103688,7 @@ var ts; var imports = _b.imports; return ts.mapDefined(imports, function (moduleSpecifier) { var i = ts.importFromModuleSpecifier(moduleSpecifier); - return (i.kind === 244 || i.kind === 243) + return (i.kind === 244 /* ImportDeclaration */ || i.kind === 243 /* ImportEqualsDeclaration */) && checker.getSymbolAtLocation(moduleSpecifier) === moduleSymbol ? { declaration: i, importKind: importKind } : undefined; }); } @@ -86697,21 +103697,28 @@ var ts; var sourceFile = context.sourceFile, symbolName = context.symbolName, preferences = context.preferences; var moduleSpecifierWithoutQuotes = ts.stripQuotes(moduleSpecifier); var quotedModuleSpecifier = ts.makeStringLiteral(moduleSpecifierWithoutQuotes, ts.getQuotePreference(sourceFile, preferences)); - var importDecl = importKind !== 3 - ? ts.createImportDeclaration(undefined, undefined, createImportClauseOfKind(importKind, symbolName), quotedModuleSpecifier) - : ts.createImportEqualsDeclaration(undefined, undefined, ts.createIdentifier(symbolName), ts.createExternalModuleReference(quotedModuleSpecifier)); + var importDecl = importKind !== 3 /* Equals */ + ? ts.createImportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, createImportClauseOfKind(importKind, symbolName), quotedModuleSpecifier) + : ts.createImportEqualsDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, ts.createIdentifier(symbolName), ts.createExternalModuleReference(quotedModuleSpecifier)); var changes = ChangeTracker.with(context, function (t) { return ts.insertImport(t, sourceFile, importDecl); }); + // if this file doesn't have any import statements, insert an import statement and then insert a new line + // between the only import statement and user code. Otherwise just insert the statement because chances + // are there are already a new line separating code and import statements. return createCodeAction(ts.Diagnostics.Import_0_from_module_1, [symbolName, moduleSpecifierWithoutQuotes], changes); } function createImportClauseOfKind(kind, symbolName) { var id = ts.createIdentifier(symbolName); switch (kind) { - case 1: - return ts.createImportClause(id, undefined); - case 2: - return ts.createImportClause(undefined, ts.createNamespaceImport(id)); - case 0: - return ts.createImportClause(undefined, ts.createNamedImports([ts.createImportSpecifier(undefined, id)])); + case 1 /* Default */: + return ts.createImportClause(id, /*namedBindings*/ undefined); + case 2 /* Namespace */: + return ts.createImportClause(/*name*/ undefined, ts.createNamespaceImport(id)); + case 0 /* Named */: + return ts.createImportClause(/*name*/ undefined, ts.createNamedImports([ts.createImportSpecifier(/*propertyName*/ undefined, id)])); default: ts.Debug.assertNever(kind); } @@ -86722,6 +103729,7 @@ var ts; var modulePathsGroups = ts.moduleSpecifiers.getModuleSpecifiers(moduleSymbol, program.getCompilerOptions(), sourceFile, host, program.getSourceFiles(), preferences); return modulePathsGroups.map(function (group) { return group.map(function (moduleSpecifier) { return ({ moduleSpecifier: moduleSpecifier, importKind: importKind }); }); }); }); + // Sort to keep the shortest paths first, but keep [relativePath, importRelativeToBaseUrl] groups together return ts.flatten(choicesForEachExportingModule.sort(function (a, b) { return ts.first(a).moduleSpecifier.length - ts.first(b).moduleSpecifier.length; })); } function getCodeActionsForAddImport(exportInfos, ctx, existingImports, addNew) { @@ -86736,9 +103744,9 @@ var ts; } function newImportInfoFromExistingSpecifier(_a) { var declaration = _a.declaration, importKind = _a.importKind; - var expression = declaration.kind === 244 + var expression = declaration.kind === 244 /* ImportDeclaration */ ? declaration.moduleSpecifier - : declaration.moduleReference.kind === 254 + : declaration.moduleReference.kind === 254 /* ExternalModuleReference */ ? declaration.moduleReference.expression : undefined; return expression && ts.isStringLiteral(expression) ? { moduleSpecifier: expression.text, importKind: importKind } : undefined; @@ -86746,29 +103754,30 @@ var ts; function tryUpdateExistingImport(context, importClause, importKind) { var symbolName = context.symbolName, sourceFile = context.sourceFile; var name = importClause.name; - var namedBindings = (importClause.kind !== 243 && importClause).namedBindings; + var namedBindings = (importClause.kind !== 243 /* ImportEqualsDeclaration */ && importClause).namedBindings; // TODO: GH#18217 switch (importKind) { - case 1: + case 1 /* Default */: return name ? undefined : ChangeTracker.with(context, function (t) { return t.replaceNode(sourceFile, importClause, ts.createImportClause(ts.createIdentifier(symbolName), namedBindings)); }); - case 0: { - var newImportSpecifier_1 = ts.createImportSpecifier(undefined, ts.createIdentifier(symbolName)); - if (namedBindings && namedBindings.kind === 247 && namedBindings.elements.length !== 0) { + case 0 /* Named */: { + var newImportSpecifier_1 = ts.createImportSpecifier(/*propertyName*/ undefined, ts.createIdentifier(symbolName)); + if (namedBindings && namedBindings.kind === 247 /* NamedImports */ && namedBindings.elements.length !== 0) { + // There are already named imports; add another. return ChangeTracker.with(context, function (t) { return t.insertNodeInListAfter(sourceFile, namedBindings.elements[namedBindings.elements.length - 1], newImportSpecifier_1); }); } - if (!namedBindings || namedBindings.kind === 247 && namedBindings.elements.length === 0) { + if (!namedBindings || namedBindings.kind === 247 /* NamedImports */ && namedBindings.elements.length === 0) { return ChangeTracker.with(context, function (t) { return t.replaceNode(sourceFile, importClause, ts.createImportClause(name, ts.createNamedImports([newImportSpecifier_1]))); }); } return undefined; } - case 2: + case 2 /* Namespace */: return namedBindings ? undefined : ChangeTracker.with(context, function (t) { return t.replaceNode(sourceFile, importClause, ts.createImportClause(name, ts.createNamespaceImport(ts.createIdentifier(symbolName)))); }); - case 3: + case 3 /* Equals */: return undefined; default: ts.Debug.assertNever(importKind); @@ -86776,23 +103785,35 @@ var ts; } function getCodeActionForUseExistingNamespaceImport(namespacePrefix, context, symbolToken) { var symbolName = context.symbolName, sourceFile = context.sourceFile; + /** + * Cases: + * import * as ns from "mod" + * import default, * as ns from "mod" + * import ns = require("mod") + * + * Because there is no import list, we alter the reference to include the + * namespace instead of altering the import declaration. For example, "foo" would + * become "ns.foo" + */ var changes = ChangeTracker.with(context, function (tracker) { return tracker.replaceNode(sourceFile, symbolToken, ts.createPropertyAccess(ts.createIdentifier(namespacePrefix), symbolToken)); }); return createCodeAction(ts.Diagnostics.Change_0_to_1, [symbolName, namespacePrefix + "." + symbolName], changes); } function getActionsForUMDImport(context) { - var token = ts.getTokenAtPosition(context.sourceFile, context.span.start, false); + var token = ts.getTokenAtPosition(context.sourceFile, context.span.start, /*includeJsDocComment*/ false); var checker = context.program.getTypeChecker(); var umdSymbol; if (ts.isIdentifier(token)) { + // try the identifier to see if it is the umd symbol umdSymbol = checker.getSymbolAtLocation(token); } if (!ts.isUMDExportSymbol(umdSymbol)) { + // The error wasn't for the symbolAtLocation, it was for the JSX tag itself, which needs access to e.g. `React`. var parent = token.parent; var isNodeOpeningLikeElement = ts.isJsxOpeningLikeElement(parent); - if ((ts.isJsxOpeningLikeElement && parent.tagName === token) || parent.kind === 260) { - umdSymbol = checker.resolveName(checker.getJsxNamespace(parent), isNodeOpeningLikeElement ? parent.tagName : parent, 67216319, false); + if ((ts.isJsxOpeningLikeElement && parent.tagName === token) || parent.kind === 260 /* JsxOpeningFragment */) { + umdSymbol = checker.resolveName(checker.getJsxNamespace(parent), isNodeOpeningLikeElement ? parent.tagName : parent, 67216319 /* Value */, /*excludeGlobals*/ false); } } if (ts.isUMDExportSymbol(umdSymbol)) { @@ -86804,35 +103825,41 @@ var ts; return undefined; } function getUmdImportKind(compilerOptions) { + // Import a synthetic `default` if enabled. if (ts.getAllowSyntheticDefaultImports(compilerOptions)) { - return 1; + return 1 /* Default */; } + // When a synthetic `default` is unavailable, use `import..require` if the module kind supports it. var moduleKind = ts.getEmitModuleKind(compilerOptions); switch (moduleKind) { case ts.ModuleKind.AMD: case ts.ModuleKind.CommonJS: case ts.ModuleKind.UMD: - return 3; + return 3 /* Equals */; case ts.ModuleKind.System: case ts.ModuleKind.ES2015: case ts.ModuleKind.ESNext: case ts.ModuleKind.None: - return 2; + // Fall back to the `import * as ns` style import. + return 2 /* Namespace */; default: return ts.Debug.assertNever(moduleKind); } } function getActionsForNonUMDImport(context) { + // This will always be an Identifier, since the diagnostics we fix only fail on identifiers. var sourceFile = context.sourceFile, span = context.span, program = context.program, cancellationToken = context.cancellationToken; var checker = program.getTypeChecker(); - var symbolToken = ts.getTokenAtPosition(sourceFile, span.start, false); + var symbolToken = ts.getTokenAtPosition(sourceFile, span.start, /*includeJsDocComment*/ false); + // If we're at ``, we must check if `Foo` is already in scope, and if so, get an import for `React` instead. var symbolName = ts.isJsxOpeningLikeElement(symbolToken.parent) && symbolToken.parent.tagName === symbolToken - && (!ts.isIdentifier(symbolToken) || ts.isIntrinsicJsxName(symbolToken.text) || checker.resolveName(symbolToken.text, symbolToken, 67108863, false)) + && (!ts.isIdentifier(symbolToken) || ts.isIntrinsicJsxName(symbolToken.text) || checker.resolveName(symbolToken.text, symbolToken, 67108863 /* All */, /*excludeGlobals*/ false)) ? checker.getJsxNamespace() : ts.isIdentifier(symbolToken) ? symbolToken.text : undefined; if (!symbolName) return undefined; + // "default" is a keyword and not a legal identifier for the import, so we don't expect it here ts.Debug.assert(symbolName !== "default"); var addToExistingDeclaration = []; var addNewDeclaration = []; @@ -86842,24 +103869,28 @@ var ts; return addToExistingDeclaration.concat(addNewDeclaration); } function getExportInfos(symbolName, currentTokenMeaning, cancellationToken, sourceFile, checker, program) { + // For each original symbol, keep all re-exports of that symbol together so we can call `getCodeActionsForImport` on the whole group at once. + // Maps symbol id to info for modules providing that symbol (original export + re-exports). var originalSymbolToExportInfos = ts.createMultiMap(); function addSymbol(moduleSymbol, exportedSymbol, importKind) { originalSymbolToExportInfos.add(ts.getUniqueSymbolId(exportedSymbol, checker).toString(), { moduleSymbol: moduleSymbol, importKind: importKind }); } forEachExternalModuleToImportFrom(checker, sourceFile, program.getSourceFiles(), function (moduleSymbol) { cancellationToken.throwIfCancellationRequested(); - var defaultExport = checker.tryGetMemberInModuleExports("default", moduleSymbol); + // check the default export + var defaultExport = checker.tryGetMemberInModuleExports("default" /* Default */, moduleSymbol); if (defaultExport) { var localSymbol = ts.getLocalSymbolForExportDefault(defaultExport); if ((localSymbol && localSymbol.escapedName === symbolName || getEscapedNameForExportDefault(defaultExport) === symbolName || moduleSymbolToValidIdentifier(moduleSymbol, program.getCompilerOptions().target) === symbolName) && checkSymbolHasMeaning(localSymbol || defaultExport, currentTokenMeaning)) { - addSymbol(moduleSymbol, localSymbol || defaultExport, 1); + addSymbol(moduleSymbol, localSymbol || defaultExport, 1 /* Default */); } } + // check exports with the same name var exportSymbolWithIdenticalName = checker.tryGetMemberInModuleExportsAndProperties(symbolName, moduleSymbol); if (exportSymbolWithIdenticalName && checkSymbolHasMeaning(exportSymbolWithIdenticalName, currentTokenMeaning)) { - addSymbol(moduleSymbol, exportSymbolWithIdenticalName, 0); + addSymbol(moduleSymbol, exportSymbolWithIdenticalName, 0 /* Named */); } function getEscapedNameForExportDefault(symbol) { return symbol.declarations && ts.firstDefined(symbol.declarations, function (declaration) { @@ -86869,7 +103900,7 @@ var ts; } } else if (ts.isExportSpecifier(declaration)) { - ts.Debug.assert(declaration.name.escapedText === "default"); + ts.Debug.assert(declaration.name.escapedText === "default" /* Default */); return declaration.propertyName && declaration.propertyName.escapedText; } }); @@ -86892,7 +103923,7 @@ var ts; function forEachExternalModule(checker, allSourceFiles, cb) { for (var _i = 0, _a = checker.getAmbientModules(); _i < _a.length; _i++) { var ambient = _a[_i]; - cb(ambient, undefined); + cb(ambient, /*sourceFile*/ undefined); } for (var _b = 0, allSourceFiles_1 = allSourceFiles; _b < allSourceFiles_1.length; _b++) { var sourceFile = allSourceFiles_1[_b]; @@ -86901,7 +103932,12 @@ var ts; } } } + /** + * Don't include something from a `node_modules` that isn't actually reachable by a global import. + * A relative import to node_modules is usually a bad idea. + */ function isImportablePath(fromPath, toPath) { + // If it's in a `node_modules` but is not reachable from here via a global import, don't bother. var toNodeModules = ts.forEachAncestorDirectory(toPath, function (ancestor) { return ts.getBaseFileName(ancestor) === "node_modules" ? ancestor : undefined; }); return toNodeModules === undefined || ts.startsWith(fromPath, ts.getDirectoryPath(toNodeModules)); } @@ -86932,11 +103968,13 @@ var ts; } lastCharWasValid = isValid; } + // Need `|| "_"` to ensure result isn't empty. return !ts.isStringANonContextualKeyword(res) ? res || "_" : "_" + res; } codefix.moduleSpecifierToValidIdentifier = moduleSpecifierToValidIdentifier; })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -86968,16 +104006,19 @@ var ts; }); }, }); function getInfo(sourceFile, pos, context) { - var node = ts.getTokenAtPosition(sourceFile, pos, false); + // This is the identifier of the misspelled word. eg: + // this.speling = 1; + // ^^^^^^^ + var node = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); // TODO: GH#15852 var checker = context.program.getTypeChecker(); var suggestion; if (ts.isPropertyAccessExpression(node.parent) && node.parent.name === node) { - ts.Debug.assert(node.kind === 71); + ts.Debug.assert(node.kind === 71 /* Identifier */); var containingType = checker.getTypeAtLocation(node.parent.expression); suggestion = checker.getSuggestionForNonexistentProperty(node, containingType); } else if (ts.isImportSpecifier(node.parent) && node.parent.name === node) { - ts.Debug.assert(node.kind === 71); + ts.Debug.assert(node.kind === 71 /* Identifier */); var importDeclaration = ts.findAncestor(node, ts.isImportDeclaration); var resolvedSourceFile = getResolvedSourceFileFromImportDeclaration(sourceFile, context, importDeclaration); if (resolvedSourceFile && resolvedSourceFile.symbol) { @@ -87002,14 +104043,14 @@ var ts; } function convertSemanticMeaningToSymbolFlags(meaning) { var flags = 0; - if (meaning & 4) { - flags |= 1920; + if (meaning & 4 /* Namespace */) { + flags |= 1920 /* Namespace */; } - if (meaning & 2) { - flags |= 67901928; + if (meaning & 2 /* Type */) { + flags |= 67901928 /* Type */; } - if (meaning & 1) { - flags |= 67216319; + if (meaning & 1 /* Value */) { + flags |= 67216319 /* Value */; } return flags; } @@ -87023,6 +104064,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87058,6 +104100,7 @@ var ts; if (!ts.addToSeen(seenNames, token.text)) { return; } + // Always prefer to add a method declaration if possible. if (call) { addMethodDeclaration(changes, classDeclarationSourceFile, classDeclaration, token, call, makeStatic, inJs, preferences); } @@ -87074,7 +104117,10 @@ var ts; }, }); function getInfo(tokenSourceFile, tokenPos, checker) { - var token = ts.getTokenAtPosition(tokenSourceFile, tokenPos, false); + // The identifier of the missing property. eg: + // this.missing = 1; + // ^^^^^^^ + var token = ts.getTokenAtPosition(tokenSourceFile, tokenPos, /*includeJsDocComment*/ false); if (!ts.isIdentifier(token)) { return undefined; } @@ -87099,7 +104145,7 @@ var ts; } function addMissingMemberInJs(changeTracker, classDeclarationSourceFile, classDeclaration, tokenName, makeStatic) { if (makeStatic) { - if (classDeclaration.kind === 205) { + if (classDeclaration.kind === 205 /* ClassExpression */) { return; } var className = classDeclaration.name.getText(); @@ -87125,20 +104171,24 @@ var ts; } function getTypeNode(checker, classDeclaration, token) { var typeNode; - if (token.parent.parent.kind === 200) { + if (token.parent.parent.kind === 200 /* BinaryExpression */) { var binaryExpression = token.parent.parent; var otherExpression = token.parent === binaryExpression.left ? binaryExpression.right : binaryExpression.left; - var widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(otherExpression))); + var widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(otherExpression))); // TODO: GH#18217 typeNode = checker.typeToTypeNode(widenedType, classDeclaration); } - return typeNode || ts.createKeywordTypeNode(119); + return typeNode || ts.createKeywordTypeNode(119 /* AnyKeyword */); } function createAddPropertyDeclarationAction(context, classDeclarationSourceFile, classDeclaration, makeStatic, tokenName, typeNode) { var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addPropertyDeclaration(t, classDeclarationSourceFile, classDeclaration, tokenName, typeNode, makeStatic); }); return codefix.createCodeFixAction(fixName, changes, [makeStatic ? ts.Diagnostics.Declare_static_property_0 : ts.Diagnostics.Declare_property_0, tokenName], fixId, ts.Diagnostics.Add_all_missing_members); } function addPropertyDeclaration(changeTracker, classDeclarationSourceFile, classDeclaration, tokenName, typeNode, makeStatic) { - var property = ts.createProperty(undefined, makeStatic ? [ts.createToken(115)] : undefined, tokenName, undefined, typeNode, undefined); + var property = ts.createProperty( + /*decorators*/ undefined, + /*modifiers*/ makeStatic ? [ts.createToken(115 /* StaticKeyword */)] : undefined, tokenName, + /*questionToken*/ undefined, typeNode, + /*initializer*/ undefined); var lastProp = getNodeToInsertPropertyAfter(classDeclaration); if (lastProp) { changeTracker.insertNodeAfter(classDeclarationSourceFile, lastProp, property); @@ -87147,6 +104197,7 @@ var ts; changeTracker.insertNodeAtClassStart(classDeclarationSourceFile, classDeclaration, property); } } + // Gets the last of the first run of PropertyDeclarations, or undefined if the class does not start with a PropertyDeclaration. function getNodeToInsertPropertyAfter(cls) { var res; for (var _i = 0, _a = cls.members; _i < _a.length; _i++) { @@ -87158,10 +104209,19 @@ var ts; return res; } function createAddIndexSignatureAction(context, classDeclarationSourceFile, classDeclaration, tokenName, typeNode) { - var stringTypeNode = ts.createKeywordTypeNode(137); - var indexingParameter = ts.createParameter(undefined, undefined, undefined, "x", undefined, stringTypeNode, undefined); - var indexSignature = ts.createIndexSignature(undefined, undefined, [indexingParameter], typeNode); + // Index signatures cannot have the static modifier. + var stringTypeNode = ts.createKeywordTypeNode(137 /* StringKeyword */); + var indexingParameter = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, "x", + /*questionToken*/ undefined, stringTypeNode, + /*initializer*/ undefined); + var indexSignature = ts.createIndexSignature( + /*decorators*/ undefined, + /*modifiers*/ undefined, [indexingParameter], typeNode); var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return t.insertNodeAtClassStart(classDeclarationSourceFile, classDeclaration, indexSignature); }); + // No fixId here because code-fix-all currently only works on adding individual named properties. return codefix.createCodeFixActionNoFixId(fixName, changes, [ts.Diagnostics.Add_index_signature_for_property_0, tokenName]); } function getActionForMethodDeclaration(context, classDeclarationSourceFile, classDeclaration, token, callExpression, makeStatic, inJs, preferences) { @@ -87170,7 +104230,7 @@ var ts; } function addMethodDeclaration(changeTracker, classDeclarationSourceFile, classDeclaration, token, callExpression, makeStatic, inJs, preferences) { var methodDeclaration = codefix.createMethodFromCallExpression(callExpression, token.text, inJs, makeStatic, preferences); - var containingMethodDeclaration = ts.getAncestor(callExpression, 154); + var containingMethodDeclaration = ts.getAncestor(callExpression, 154 /* MethodDeclaration */); if (containingMethodDeclaration && containingMethodDeclaration.parent === classDeclaration) { changeTracker.insertNodeAfter(classDeclarationSourceFile, containingMethodDeclaration, methodDeclaration); } @@ -87180,6 +104240,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87196,7 +104257,7 @@ var ts; var host = context.host, sourceFile = context.sourceFile, start = context.span.start; var packageName = getTypesPackageNameToInstall(host, sourceFile, start, context.errorCode); return packageName === undefined ? [] - : [codefix.createCodeFixAction(fixId, [], [ts.Diagnostics.Install_0, packageName], fixId, ts.Diagnostics.Install_all_missing_types_packages, getCommand(sourceFile.fileName, packageName))]; + : [codefix.createCodeFixAction(fixId, /*changes*/ [], [ts.Diagnostics.Install_0, packageName], fixId, ts.Diagnostics.Install_all_missing_types_packages, getCommand(sourceFile.fileName, packageName))]; }, fixIds: [fixId], getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (_, diag, commands) { @@ -87210,14 +104271,15 @@ var ts; return { type: "install package", file: fileName, packageName: packageName }; } function getTypesPackageNameToInstall(host, sourceFile, pos, diagCode) { - var moduleName = ts.cast(ts.getTokenAtPosition(sourceFile, pos, false), ts.isStringLiteral).text; + var moduleName = ts.cast(ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false), ts.isStringLiteral).text; var packageName = ts.getPackageName(moduleName).packageName; return diagCode === errorCodeCannotFindModule ? (ts.JsTyping.nodeCoreModules.has(packageName) ? "@types/node" : undefined) - : (host.isKnownTypesPackageName(packageName) ? ts.getTypesPackageName(packageName) : undefined); + : (host.isKnownTypesPackageName(packageName) ? ts.getTypesPackageName(packageName) : undefined); // TODO: GH#18217 } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87248,21 +104310,28 @@ var ts; }, }); function getClass(sourceFile, pos) { - var token = ts.getTokenAtPosition(sourceFile, pos, false); + // Token is the identifier in the case of a class declaration + // or the class keyword token in the case of a class expression. + var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); return ts.cast(token.parent, ts.isClassLike); } function addMissingMembers(classDeclaration, sourceFile, checker, changeTracker, preferences) { var extendsNode = ts.getClassExtendsHeritageClauseElement(classDeclaration); var instantiatedExtendsType = checker.getTypeAtLocation(extendsNode); + // Note that this is ultimately derived from a map indexed by symbol names, + // so duplicates cannot occur. var abstractAndNonPrivateExtendsSymbols = checker.getPropertiesOfType(instantiatedExtendsType).filter(symbolPointsToNonPrivateAndAbstractMember); codefix.createMissingMemberNodes(classDeclaration, abstractAndNonPrivateExtendsSymbols, checker, preferences, function (member) { return changeTracker.insertNodeAtClassStart(sourceFile, classDeclaration, member); }); } function symbolPointsToNonPrivateAndAbstractMember(symbol) { + // See `codeFixClassExtendAbstractProtectedProperty.ts` in https://github.com/Microsoft/TypeScript/pull/11547/files + // (now named `codeFixClassExtendAbstractPrivateProperty.ts`) var flags = ts.getModifierFlags(ts.first(symbol.getDeclarations())); - return !(flags & 8) && !!(flags & 128); + return !(flags & 8 /* Private */) && !!(flags & 128 /* Abstract */); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87283,7 +104352,7 @@ var ts; fixIds: [fixId], getAllCodeActions: function (context) { var sourceFile = context.sourceFile; - var seenClasses = ts.createMap(); + var seenClasses = ts.createMap(); // Ensure we only do this once per class. return codefix.codeFixAll(context, errorCodes, function (changes, diag) { var nodes = getNodes(diag.file, diag.start); if (!nodes) @@ -87300,11 +104369,13 @@ var ts; changes.deleteNode(sourceFile, superCall); } function getNodes(sourceFile, pos) { - var token = ts.getTokenAtPosition(sourceFile, pos, false); - if (token.kind !== 99) + var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); + if (token.kind !== 99 /* ThisKeyword */) return undefined; var constructor = ts.getContainingFunction(token); var superCall = findSuperCall(constructor.body); + // figure out if the `this` access is actually inside the supercall + // i.e. super(this.a), since in that case we won't suggest a fix return superCall && !superCall.expression.arguments.some(function (arg) { return ts.isPropertyAccessExpression(arg) && arg.expression === token; }) ? { constructor: constructor, superCall: superCall } : undefined; } function findSuperCall(n) { @@ -87316,6 +104387,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87336,16 +104408,17 @@ var ts; }); }, }); function getNode(sourceFile, pos) { - var token = ts.getTokenAtPosition(sourceFile, pos, false); - ts.Debug.assert(token.kind === 123); + var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); + ts.Debug.assert(token.kind === 123 /* ConstructorKeyword */); return token.parent; } function doChange(changes, sourceFile, ctr) { - var superCall = ts.createStatement(ts.createCall(ts.createSuper(), undefined, ts.emptyArray)); + var superCall = ts.createStatement(ts.createCall(ts.createSuper(), /*typeArguments*/ undefined, /*argumentsArray*/ ts.emptyArray)); changes.insertNodeAtConstructorStart(sourceFile, ctr, superCall); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87371,19 +104444,22 @@ var ts; }); }, }); function getNodes(sourceFile, pos) { - var token = ts.getTokenAtPosition(sourceFile, pos, false); + var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); var heritageClauses = ts.getContainingClass(token).heritageClauses; var extendsToken = heritageClauses[0].getFirstToken(); - return extendsToken.kind === 85 ? { extendsToken: extendsToken, heritageClauses: heritageClauses } : undefined; + return extendsToken.kind === 85 /* ExtendsKeyword */ ? { extendsToken: extendsToken, heritageClauses: heritageClauses } : undefined; } function doChanges(changes, sourceFile, extendsToken, heritageClauses) { - changes.replaceNode(sourceFile, extendsToken, ts.createToken(108)); + changes.replaceNode(sourceFile, extendsToken, ts.createToken(108 /* ImplementsKeyword */)); + // If there is already an implements clause, replace the implements keyword with a comma. if (heritageClauses.length === 2 && - heritageClauses[0].token === 85 && - heritageClauses[1].token === 108) { + heritageClauses[0].token === 85 /* ExtendsKeyword */ && + heritageClauses[1].token === 108 /* ImplementsKeyword */) { var implementsToken = heritageClauses[1].getFirstToken(); var implementsFullStart = implementsToken.getFullStart(); - changes.replaceRange(sourceFile, { pos: implementsFullStart, end: implementsFullStart }, ts.createToken(26)); + changes.replaceRange(sourceFile, { pos: implementsFullStart, end: implementsFullStart }, ts.createToken(26 /* CommaToken */)); + // Rough heuristic: delete trailing whitespace after keyword so that it's not excessive. + // (Trailing because leading might be indentation, which is more sensitive.) var text = sourceFile.text; var end = implementsToken.end; while (end < text.length && ts.isWhiteSpaceSingleLine(text.charCodeAt(end))) { @@ -87394,6 +104470,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87423,18 +104500,20 @@ var ts; }); }, }); function getInfo(sourceFile, pos, diagCode) { - var node = ts.getTokenAtPosition(sourceFile, pos, false); + var node = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); if (!ts.isIdentifier(node)) return undefined; return { node: node, className: diagCode === didYouMeanStaticMemberCode ? ts.getContainingClass(node).name.text : undefined }; } function doChange(changes, sourceFile, _a) { var node = _a.node, className = _a.className; + // TODO (https://github.com/Microsoft/TypeScript/issues/21246): use shared helper ts.suppressLeadingAndTrailingTrivia(node); changes.replaceNode(sourceFile, node, ts.createPropertyAccess(className ? ts.createIdentifier(className) : ts.createThis(), node)); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87455,23 +104534,23 @@ var ts; getCodeActions: function (context) { var errorCode = context.errorCode, sourceFile = context.sourceFile, program = context.program; var checker = program.getTypeChecker(); - var startToken = ts.getTokenAtPosition(sourceFile, context.span.start, false); + var startToken = ts.getTokenAtPosition(sourceFile, context.span.start, /*includeJsDocComment*/ false); var importDecl = tryGetFullImport(startToken); if (importDecl) { var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return t.deleteNode(sourceFile, importDecl); }); return [codefix.createCodeFixAction(fixName, changes, [ts.Diagnostics.Remove_import_from_0, ts.showModuleSpecifier(importDecl)], fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations)]; } - var delDestructure = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullDestructure(t, sourceFile, startToken, undefined, checker, false); }); + var delDestructure = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullDestructure(t, sourceFile, startToken, /*deleted*/ undefined, checker, /*isFixAll*/ false); }); if (delDestructure.length) { return [codefix.createCodeFixAction(fixName, delDestructure, ts.Diagnostics.Remove_destructuring, fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations)]; } - var delVar = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullVariableStatement(t, sourceFile, startToken, undefined); }); + var delVar = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullVariableStatement(t, sourceFile, startToken, /*deleted*/ undefined); }); if (delVar.length) { return [codefix.createCodeFixAction(fixName, delVar, ts.Diagnostics.Remove_variable_statement, fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations)]; } var token = getToken(sourceFile, ts.textSpanEnd(context.span)); var result = []; - var deletion = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteDeclaration(t, sourceFile, token, undefined, checker, false); }); + var deletion = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteDeclaration(t, sourceFile, token, /*deleted*/ undefined, checker, /*isFixAll*/ false); }); if (deletion.length) { result.push(codefix.createCodeFixAction(fixName, deletion, [ts.Diagnostics.Remove_declaration_for_Colon_0, token.getText(sourceFile)], fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations)); } @@ -87483,11 +104562,12 @@ var ts; }, fixIds: [fixIdPrefix, fixIdDelete], getAllCodeActions: function (context) { + // Track a set of deleted nodes that may be ancestors of other marked for deletion -- only delete the ancestors. var deleted = new ts.NodeSet(); var sourceFile = context.sourceFile, program = context.program; var checker = program.getTypeChecker(); return codefix.codeFixAll(context, errorCodes, function (changes, diag) { - var startToken = ts.getTokenAtPosition(sourceFile, diag.start, false); + var startToken = ts.getTokenAtPosition(sourceFile, diag.start, /*includeJsDocComment*/ false); var token = ts.findPrecedingToken(ts.textSpanEnd(diag), diag.file); switch (context.fixId) { case fixIdPrefix: @@ -87496,15 +104576,16 @@ var ts; } break; case fixIdDelete: + // Ignore if this range was already deleted. if (deleted.some(function (d) { return ts.rangeContainsPosition(d, diag.start); })) break; var importDecl = tryGetFullImport(startToken); if (importDecl) { changes.deleteNode(sourceFile, importDecl); } - else if (!tryDeleteFullDestructure(changes, sourceFile, startToken, deleted, checker, true) && + else if (!tryDeleteFullDestructure(changes, sourceFile, startToken, deleted, checker, /*isFixAll*/ true) && !tryDeleteFullVariableStatement(changes, sourceFile, startToken, deleted)) { - tryDeleteDeclaration(changes, sourceFile, token, deleted, checker, true); + tryDeleteDeclaration(changes, sourceFile, token, deleted, checker, /*isFixAll*/ true); } break; default: @@ -87513,25 +104594,26 @@ var ts; }); }, }); + // Sometimes the diagnostic span is an entire ImportDeclaration, so we should remove the whole thing. function tryGetFullImport(startToken) { - return startToken.kind === 91 ? ts.tryCast(startToken.parent, ts.isImportDeclaration) : undefined; + return startToken.kind === 91 /* ImportKeyword */ ? ts.tryCast(startToken.parent, ts.isImportDeclaration) : undefined; } function tryDeleteFullDestructure(changes, sourceFile, startToken, deletedAncestors, checker, isFixAll) { - if (startToken.kind !== 17 || !ts.isObjectBindingPattern(startToken.parent)) + if (startToken.kind !== 17 /* OpenBraceToken */ || !ts.isObjectBindingPattern(startToken.parent)) return false; var decl = ts.cast(startToken.parent, ts.isObjectBindingPattern).parent; switch (decl.kind) { - case 232: + case 232 /* VariableDeclaration */: tryDeleteVariableDeclaration(changes, sourceFile, decl, deletedAncestors); break; - case 149: + case 149 /* Parameter */: if (!mayDeleteParameter(decl, checker, isFixAll)) break; if (deletedAncestors) deletedAncestors.add(decl); changes.deleteNodeInList(sourceFile, decl); break; - case 182: + case 182 /* BindingElement */: if (deletedAncestors) deletedAncestors.add(decl); changes.deleteNode(sourceFile, decl); @@ -87546,29 +104628,31 @@ var ts; if (declarationList && declarationList.getChildren(sourceFile)[0] === startToken) { if (deletedAncestors) deletedAncestors.add(declarationList); - changes.deleteNode(sourceFile, declarationList.parent.kind === 214 ? declarationList.parent : declarationList); + changes.deleteNode(sourceFile, declarationList.parent.kind === 214 /* VariableStatement */ ? declarationList.parent : declarationList); return true; } return false; } function getToken(sourceFile, pos) { - var token = ts.findPrecedingToken(pos, sourceFile, undefined, true); - return token.kind === 22 ? ts.findPrecedingToken(pos - 1, sourceFile) : token; + var token = ts.findPrecedingToken(pos, sourceFile, /*startNode*/ undefined, /*includeJsDoc*/ true); + // this handles var ["computed"] = 12; + return token.kind === 22 /* CloseBracketToken */ ? ts.findPrecedingToken(pos - 1, sourceFile) : token; } function tryPrefixDeclaration(changes, errorCode, sourceFile, token) { + // Don't offer to prefix a property. if (errorCode !== ts.Diagnostics.Property_0_is_declared_but_its_value_is_never_read.code && ts.isIdentifier(token) && canPrefix(token)) { changes.replaceNode(sourceFile, token, ts.createIdentifier("_" + token.text)); } } function canPrefix(token) { switch (token.parent.kind) { - case 149: + case 149 /* Parameter */: return true; - case 232: { + case 232 /* VariableDeclaration */: { var varDecl = token.parent; switch (varDecl.parent.parent.kind) { - case 222: - case 221: + case 222 /* ForOfStatement */: + case 221 /* ForInStatement */: return true; } } @@ -87582,9 +104666,9 @@ var ts; } function deleteAssignments(changes, sourceFile, token, checker) { ts.FindAllReferences.Core.eachSymbolReferenceInFile(token, checker, sourceFile, function (ref) { - if (ref.parent.kind === 185) + if (ref.parent.kind === 185 /* PropertyAccessExpression */) ref = ref.parent; - if (ref.parent.kind === 200 && ref.parent.parent.kind === 216) { + if (ref.parent.kind === 200 /* BinaryExpression */ && ref.parent.parent.kind === 216 /* ExpressionStatement */) { changes.deleteNode(sourceFile, ref.parent.parent); } }); @@ -87592,29 +104676,37 @@ var ts; function tryDeleteDeclarationWorker(changes, sourceFile, token, deletedAncestors, checker, isFixAll) { var parent = token.parent; switch (parent.kind) { - case 232: + case 232 /* VariableDeclaration */: tryDeleteVariableDeclaration(changes, sourceFile, parent, deletedAncestors); break; - case 148: + case 148 /* TypeParameter */: var typeParameters = ts.getEffectiveTypeParameterDeclarations(parent.parent); if (typeParameters.length === 1) { var _a = ts.cast(typeParameters, ts.isNodeArray), pos = _a.pos, end = _a.end; - var previousToken = ts.getTokenAtPosition(sourceFile, pos - 1, false); - var nextToken = ts.getTokenAtPosition(sourceFile, end, false); - ts.Debug.assert(previousToken.kind === 27); - ts.Debug.assert(nextToken.kind === 29); + var previousToken = ts.getTokenAtPosition(sourceFile, pos - 1, /*includeJsDocComment*/ false); + var nextToken = ts.getTokenAtPosition(sourceFile, end, /*includeJsDocComment*/ false); + ts.Debug.assert(previousToken.kind === 27 /* LessThanToken */); + ts.Debug.assert(nextToken.kind === 29 /* GreaterThanToken */); changes.deleteNodeRange(sourceFile, previousToken, nextToken); } else { changes.deleteNodeInList(sourceFile, parent); } break; - case 149: + case 149 /* Parameter */: if (!mayDeleteParameter(parent, checker, isFixAll)) break; var oldFunction = parent.parent; if (ts.isArrowFunction(oldFunction) && oldFunction.parameters.length === 1) { - var newFunction = ts.updateArrowFunction(oldFunction, oldFunction.modifiers, oldFunction.typeParameters, undefined, oldFunction.type, oldFunction.equalsGreaterThanToken, oldFunction.body); + // Lambdas with exactly one parameter are special because, after removal, there + // must be an empty parameter list (i.e. `()`) and this won't necessarily be the + // case if the parameter is simply removed (e.g. in `x => 1`). + var newFunction = ts.updateArrowFunction(oldFunction, oldFunction.modifiers, oldFunction.typeParameters, + /*parameters*/ undefined, // TODO: GH#18217 + oldFunction.type, oldFunction.equalsGreaterThanToken, oldFunction.body); + // Drop leading and trailing trivia of the new function because we're only going + // to replace the span (vs the full span) of the old function - the old leading + // and trailing trivia will remain. ts.suppressLeadingAndTrailingTrivia(newFunction); changes.replaceNode(sourceFile, oldFunction, newFunction); } @@ -87622,9 +104714,9 @@ var ts; changes.deleteNodeInList(sourceFile, parent); } break; - case 182: { + case 182 /* BindingElement */: { var pattern = parent.parent; - var preserveComma = pattern.kind === 181 && parent !== ts.last(pattern.elements); + var preserveComma = pattern.kind === 181 /* ArrayBindingPattern */ && parent !== ts.last(pattern.elements); if (preserveComma) { changes.deleteNode(sourceFile, parent); } @@ -87633,29 +104725,33 @@ var ts; } break; } - case 243: - var importEquals = ts.getAncestor(token, 243); + // handle case where 'import a = A;' + case 243 /* ImportEqualsDeclaration */: + var importEquals = ts.getAncestor(token, 243 /* ImportEqualsDeclaration */); changes.deleteNode(sourceFile, importEquals); break; - case 248: + case 248 /* ImportSpecifier */: var namedImports = parent.parent; if (namedImports.elements.length === 1) { tryDeleteNamedImportBinding(changes, sourceFile, namedImports); } else { + // delete import specifier changes.deleteNodeInList(sourceFile, parent); } break; - case 245: + case 245 /* ImportClause */: // this covers both 'import |d|' and 'import |d,| *' var importClause = parent; - if (!importClause.namedBindings) { - changes.deleteNode(sourceFile, ts.getAncestor(importClause, 244)); + if (!importClause.namedBindings) { // |import d from './file'| + changes.deleteNode(sourceFile, ts.getAncestor(importClause, 244 /* ImportDeclaration */)); } else { + // import |d,| * as ns from './file' var start = importClause.name.getStart(sourceFile); - var nextToken = ts.getTokenAtPosition(sourceFile, importClause.name.end, false); - if (nextToken && nextToken.kind === 26) { - var end = ts.skipTrivia(sourceFile.text, nextToken.end, false, true); + var nextToken = ts.getTokenAtPosition(sourceFile, importClause.name.end, /*includeJsDocComment*/ false); + if (nextToken && nextToken.kind === 26 /* CommaToken */) { + // shift first non-whitespace position after comma to the start position of the node + var end = ts.skipTrivia(sourceFile.text, nextToken.end, /*stopAfterLineBreaks*/ false, /*stopAtComments*/ true); changes.deleteRange(sourceFile, { pos: start, end: end }); } else { @@ -87663,7 +104759,7 @@ var ts; } } break; - case 246: + case 246 /* NamespaceImport */: tryDeleteNamedImportBinding(changes, sourceFile, parent); break; default: @@ -87682,19 +104778,26 @@ var ts; } function tryDeleteNamedImportBinding(changes, sourceFile, namedBindings) { if (namedBindings.parent.name) { - var previousToken = ts.getTokenAtPosition(sourceFile, namedBindings.pos - 1, false); - if (previousToken && previousToken.kind === 26) { + // Delete named imports while preserving the default import + // import d|, * as ns| from './file' + // import d|, { a }| from './file' + var previousToken = ts.getTokenAtPosition(sourceFile, namedBindings.pos - 1, /*includeJsDocComment*/ false); + if (previousToken && previousToken.kind === 26 /* CommaToken */) { changes.deleteRange(sourceFile, { pos: previousToken.getStart(), end: namedBindings.end }); } } else { - var importDecl = ts.getAncestor(namedBindings, 244); + // Delete the entire import declaration + // |import * as ns from './file'| + // |import { a } from './file'| + var importDecl = ts.getAncestor(namedBindings, 244 /* ImportDeclaration */); changes.deleteNode(sourceFile, importDecl); } } + // token.parent is a variableDeclaration function tryDeleteVariableDeclaration(changes, sourceFile, varDecl, deletedAncestors) { switch (varDecl.parent.parent.kind) { - case 220: { + case 220 /* ForStatement */: { var forStatement = varDecl.parent.parent; var forInitializer = forStatement.initializer; if (forInitializer.declarations.length === 1) { @@ -87709,16 +104812,16 @@ var ts; } break; } - case 222: + case 222 /* ForOfStatement */: var forOfStatement = varDecl.parent.parent; - ts.Debug.assert(forOfStatement.initializer.kind === 233); + ts.Debug.assert(forOfStatement.initializer.kind === 233 /* VariableDeclarationList */); var forOfInitializer = forOfStatement.initializer; if (deletedAncestors) deletedAncestors.add(forOfInitializer.declarations[0]); changes.replaceNode(sourceFile, forOfInitializer.declarations[0], ts.createObjectLiteral()); break; - case 221: - case 230: + case 221 /* ForInStatement */: + case 230 /* TryStatement */: break; default: var variableStatement = varDecl.parent.parent; @@ -87737,22 +104840,26 @@ var ts; function mayDeleteParameter(p, checker, isFixAll) { var parent = p.parent; switch (parent.kind) { - case 154: + case 154 /* MethodDeclaration */: + // Don't remove a parameter if this overrides something var symbol = checker.getSymbolAtLocation(parent.name); if (ts.isMemberSymbolInBaseType(symbol, checker)) return false; - case 155: - case 234: - case 192: - case 193: { + // falls through + case 155 /* Constructor */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: { + // Can't remove a non-last parameter. Can remove a parameter in code-fix-all if future parameters are also unused. var parameters = parent.parameters; var index = parameters.indexOf(p); ts.Debug.assert(index !== -1); return isFixAll - ? parameters.slice(index + 1).every(function (p) { return p.name.kind === 71 && !p.symbol.isReferenced; }) + ? parameters.slice(index + 1).every(function (p) { return p.name.kind === 71 /* Identifier */ && !p.symbol.isReferenced; }) : index === parameters.length - 1; } - case 157: + case 157 /* SetAccessor */: + // Setter must have a parameter return false; default: return ts.Debug.failBadSyntaxKind(parent); @@ -87760,6 +104867,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87776,12 +104884,12 @@ var ts; getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { return doChange(changes, diag.file, diag.start); }); }, }); function doChange(changes, sourceFile, start) { - var token = ts.getTokenAtPosition(sourceFile, start, false); + var token = ts.getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false); var statement = ts.findAncestor(token, ts.isStatement); ts.Debug.assert(statement.getStart(sourceFile) === token.getStart(sourceFile)); var container = (ts.isBlock(statement.parent) ? statement.parent : statement).parent; switch (container.kind) { - case 217: + case 217 /* IfStatement */: if (container.elseStatement) { if (ts.isBlock(statement.parent)) { changes.deleteNodeRange(sourceFile, ts.first(statement.parent.statements), ts.last(statement.parent.statements)); @@ -87791,8 +104899,9 @@ var ts; } break; } - case 219: - case 220: + // falls through + case 219 /* WhileStatement */: + case 220 /* ForStatement */: changes.deleteNode(sourceFile, container); break; default: @@ -87805,18 +104914,20 @@ var ts; } } function shouldRemove(s) { + // Don't remove statements that can validly be used before they appear. return !ts.isFunctionDeclaration(s) && !isPurelyTypeDeclaration(s) && - !(ts.isVariableStatement(s) && !(ts.getCombinedNodeFlags(s) & (1 | 2)) && s.declarationList.declarations.some(function (d) { return !d.initializer; })); + // `var x;` may declare a variable used above + !(ts.isVariableStatement(s) && !(ts.getCombinedNodeFlags(s) & (1 /* Let */ | 2 /* Const */)) && s.declarationList.declarations.some(function (d) { return !d.initializer; })); } function isPurelyTypeDeclaration(s) { switch (s.kind) { - case 236: - case 237: + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: return true; - case 239: - return ts.getModuleInstanceState(s) !== 1; - case 238: - return ts.hasModifier(s, 2048); + case 239 /* ModuleDeclaration */: + return ts.getModuleInstanceState(s) !== 1 /* Instantiated */; + case 238 /* EnumDeclaration */: + return ts.hasModifier(s, 2048 /* Const */); default: return false; } @@ -87826,11 +104937,13 @@ var ts; ts.Debug.assert(index !== -1); return arr.slice(index); } + // Calls 'cb' with the start and end of each range where 'pred' is true. function split(arr, pred, cb) { ts.getRangesWhere(arr, pred, function (start, afterEnd) { return cb(arr[start], arr[afterEnd - 1]); }); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87847,16 +104960,18 @@ var ts; getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { return doChange(changes, diag.file, diag.start); }); }, }); function doChange(changes, sourceFile, start) { - var token = ts.getTokenAtPosition(sourceFile, start, false); + var token = ts.getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false); var labeledStatement = ts.cast(token.parent, ts.isLabeledStatement); var pos = token.getStart(sourceFile); var statementPos = labeledStatement.statement.getStart(sourceFile); + // If label is on a separate line, just delete the rest of that line, but not the indentation of the labeled statement. var end = ts.positionsAreOnSameLine(pos, statementPos, sourceFile) ? statementPos - : ts.skipTrivia(sourceFile.text, ts.findChildOfKind(labeledStatement, 56, sourceFile).end, true); + : ts.skipTrivia(sourceFile.text, ts.findChildOfKind(labeledStatement, 56 /* ColonToken */, sourceFile).end, /*stopAfterLineBreak*/ true); changes.deleteRange(sourceFile, { pos: pos, end: end }); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87875,8 +104990,10 @@ var ts; var typeNode = info.typeNode, type = info.type; var original = typeNode.getText(sourceFile); var actions = [fix(type, fixIdPlain, ts.Diagnostics.Change_all_jsdoc_style_types_to_TypeScript)]; - if (typeNode.kind === 281) { - actions.push(fix(checker.getNullableType(type, 8192), fixIdNullable, ts.Diagnostics.Change_all_jsdoc_style_types_to_TypeScript_and_add_undefined_to_nullable_types)); + if (typeNode.kind === 281 /* JSDocNullableType */) { + // for nullable types, suggest the flow-compatible `T | null | undefined` + // in addition to the jsdoc/closure-compatible `T | null` + actions.push(fix(checker.getNullableType(type, 8192 /* Undefined */), fixIdNullable, ts.Diagnostics.Change_all_jsdoc_style_types_to_TypeScript_and_add_undefined_to_nullable_types)); } return actions; function fix(type, fixId, fixAllDescription) { @@ -87893,37 +105010,39 @@ var ts; if (!info) return; var typeNode = info.typeNode, type = info.type; - var fixedType = typeNode.kind === 281 && fixId === fixIdNullable ? checker.getNullableType(type, 8192) : type; + var fixedType = typeNode.kind === 281 /* JSDocNullableType */ && fixId === fixIdNullable ? checker.getNullableType(type, 8192 /* Undefined */) : type; doChange(changes, sourceFile, typeNode, fixedType, checker); }); } }); function doChange(changes, sourceFile, oldTypeNode, newType, checker) { - changes.replaceNode(sourceFile, oldTypeNode, checker.typeToTypeNode(newType, oldTypeNode)); + changes.replaceNode(sourceFile, oldTypeNode, checker.typeToTypeNode(newType, /*enclosingDeclaration*/ oldTypeNode)); // TODO: GH#18217 } function getInfo(sourceFile, pos, checker) { - var decl = ts.findAncestor(ts.getTokenAtPosition(sourceFile, pos, false), isTypeContainer); + var decl = ts.findAncestor(ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false), isTypeContainer); var typeNode = decl && decl.type; return typeNode && { typeNode: typeNode, type: checker.getTypeFromTypeNode(typeNode) }; } function isTypeContainer(node) { + // NOTE: Some locations are not handled yet: + // MappedTypeNode.typeParameters and SignatureDeclaration.typeParameters, as well as CallExpression.typeArguments switch (node.kind) { - case 208: - case 158: - case 159: - case 234: - case 156: - case 160: - case 177: - case 154: - case 153: - case 149: - case 152: - case 151: - case 157: - case 237: - case 190: - case 232: + case 208 /* AsExpression */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 234 /* FunctionDeclaration */: + case 156 /* GetAccessor */: + case 160 /* IndexSignature */: + case 177 /* MappedType */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 149 /* Parameter */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 157 /* SetAccessor */: + case 237 /* TypeAliasDeclaration */: + case 190 /* TypeAssertionExpression */: + case 232 /* VariableDeclaration */: return true; default: return false; @@ -87931,6 +105050,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87969,22 +105089,22 @@ var ts; } } function getNodes(sourceFile, start) { - var token = ts.getTokenAtPosition(sourceFile, start, false); + var token = ts.getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false); var containingFunction = ts.getContainingFunction(token); if (!containingFunction) { return; } var insertBefore; switch (containingFunction.kind) { - case 154: + case 154 /* MethodDeclaration */: insertBefore = containingFunction.name; break; - case 234: - case 192: - insertBefore = ts.findChildOfKind(containingFunction, 89, sourceFile); + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + insertBefore = ts.findChildOfKind(containingFunction, 89 /* FunctionKeyword */, sourceFile); break; - case 193: - insertBefore = ts.findChildOfKind(containingFunction, 19, sourceFile) || ts.first(containingFunction.parameters); + case 193 /* ArrowFunction */: + insertBefore = ts.findChildOfKind(containingFunction, 19 /* OpenParenToken */, sourceFile) || ts.first(containingFunction.parameters); break; default: return; @@ -87998,14 +105118,15 @@ var ts; var insertBefore = _a.insertBefore, returnType = _a.returnType; if (returnType) { var entityName = ts.getEntityNameFromTypeNode(returnType); - if (!entityName || entityName.kind !== 71 || entityName.text !== "Promise") { + if (!entityName || entityName.kind !== 71 /* Identifier */ || entityName.text !== "Promise") { changes.replaceNode(sourceFile, returnType, ts.createTypeReferenceNode("Promise", ts.createNodeArray([returnType]))); } } - changes.insertModifierBefore(sourceFile, 120, insertBefore); + changes.insertModifierBefore(sourceFile, 120 /* AsyncKeyword */, insertBefore); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -88024,6 +105145,7 @@ var ts; return undefined; } var fixes = [ + // fixId unnecessary because adding `// @ts-nocheck` even once will ignore every error in the file. codefix.createCodeFixActionNoFixId(fixName, [codefix.createFileTextChanges(sourceFile.fileName, [ ts.createTextChange(sourceFile.checkJsDirective ? ts.createTextSpanFromBounds(sourceFile.checkJsDirective.pos, sourceFile.checkJsDirective.end) @@ -88047,16 +105169,24 @@ var ts; }); function makeChange(changes, sourceFile, position, seenLines) { var lineNumber = ts.getLineAndCharacterOfPosition(sourceFile, position).line; + // Only need to add `// @ts-ignore` for a line once. if (!seenLines || ts.addToSeen(seenLines, lineNumber)) { changes.insertCommentBeforeLine(sourceFile, lineNumber, position, " @ts-ignore"); } } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; (function (codefix) { + /** + * Finds members of the resolved type that are missing in the class pointed to by class decl + * and generates source code for the missing members. + * @param possiblyMissingSymbols The collection of symbols to filter and then get insertions for. + * @returns Empty string iff there are no member insertions. + */ function createMissingMemberNodes(classDeclaration, possiblyMissingSymbols, checker, preferences, out) { var classMembers = classDeclaration.symbol.members; for (var _i = 0, possiblyMissingSymbols_1 = possiblyMissingSymbols; _i < possiblyMissingSymbols_1.length; _i++) { @@ -88067,28 +105197,40 @@ var ts; } } codefix.createMissingMemberNodes = createMissingMemberNodes; + /** + * @returns Empty string iff there we can't figure out a representation for `symbol` in `enclosingDeclaration`. + */ function addNewNodeForMemberSymbol(symbol, enclosingDeclaration, checker, preferences, out) { var declarations = symbol.getDeclarations(); if (!(declarations && declarations.length)) { return undefined; } var declaration = declarations[0]; - var name = ts.getSynthesizedDeepClone(ts.getNameOfDeclaration(declaration), false); + var name = ts.getSynthesizedDeepClone(ts.getNameOfDeclaration(declaration), /*includeTrivia*/ false); var visibilityModifier = createVisibilityModifier(ts.getModifierFlags(declaration)); var modifiers = visibilityModifier ? ts.createNodeArray([visibilityModifier]) : undefined; var type = checker.getWidenedType(checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration)); - var optional = !!(symbol.flags & 16777216); + var optional = !!(symbol.flags & 16777216 /* Optional */); switch (declaration.kind) { - case 156: - case 157: - case 151: - case 152: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 151 /* PropertySignature */: + case 152 /* PropertyDeclaration */: var typeNode = checker.typeToTypeNode(type, enclosingDeclaration); - out(ts.createProperty(undefined, modifiers, name, optional ? ts.createToken(55) : undefined, typeNode, undefined)); + out(ts.createProperty( + /*decorators*/ undefined, modifiers, name, optional ? ts.createToken(55 /* QuestionToken */) : undefined, typeNode, + /*initializer*/ undefined)); break; - case 153: - case 154: - var signatures = checker.getSignaturesOfType(type, 0); + case 153 /* MethodSignature */: + case 154 /* MethodDeclaration */: + // The signature for the implementation appears as an entry in `signatures` iff + // there is only one signature. + // If there are overloads and an implementation signature, it appears as an + // extra declaration that isn't a signature for `type`. + // If there is more than one overload but no implementation signature + // (eg: an abstract method or interface declaration), there is a 1-1 + // correspondence of declarations and signatures. + var signatures = checker.getSignaturesOfType(type, 0 /* Call */); if (!ts.some(signatures)) { break; } @@ -88100,7 +105242,8 @@ var ts; } for (var _i = 0, signatures_8 = signatures; _i < signatures_8.length; _i++) { var signature = signatures_8[_i]; - outputMethod(signature, ts.getSynthesizedDeepClones(modifiers, false), ts.getSynthesizedDeepClone(name, false)); + // Need to ensure nodes are fresh each time so they can have different positions. + outputMethod(signature, ts.getSynthesizedDeepClones(modifiers, /*includeTrivia*/ false), ts.getSynthesizedDeepClone(name, /*includeTrivia*/ false)); } if (declarations.length > signatures.length) { var signature = checker.getSignatureFromDeclaration(declarations[declarations.length - 1]); @@ -88119,33 +105262,51 @@ var ts; } } function signatureToMethodDeclaration(checker, signature, enclosingDeclaration, modifiers, name, optional, body) { - var signatureDeclaration = checker.signatureToSignatureDeclaration(signature, 154, enclosingDeclaration, 256); + var signatureDeclaration = checker.signatureToSignatureDeclaration(signature, 154 /* MethodDeclaration */, enclosingDeclaration, 256 /* SuppressAnyReturnType */); if (!signatureDeclaration) { return undefined; } signatureDeclaration.decorators = undefined; signatureDeclaration.modifiers = modifiers; signatureDeclaration.name = name; - signatureDeclaration.questionToken = optional ? ts.createToken(55) : undefined; + signatureDeclaration.questionToken = optional ? ts.createToken(55 /* QuestionToken */) : undefined; signatureDeclaration.body = body; return signatureDeclaration; } function createMethodFromCallExpression(_a, methodName, inJs, makeStatic, preferences) { var typeArguments = _a.typeArguments, args = _a.arguments, parent = _a.parent; - return ts.createMethod(undefined, makeStatic ? [ts.createToken(115)] : undefined, ts.isYieldExpression(parent) ? ts.createToken(39) : undefined, methodName, undefined, inJs ? undefined : ts.map(typeArguments, function (_, i) { - return ts.createTypeParameterDeclaration(84 + typeArguments.length - 1 <= 90 ? String.fromCharCode(84 + i) : "T" + i); - }), createDummyParameters(args.length, undefined, undefined, inJs), inJs ? undefined : ts.createKeywordTypeNode(119), createStubbedMethodBody(preferences)); + return ts.createMethod( + /*decorators*/ undefined, + /*modifiers*/ makeStatic ? [ts.createToken(115 /* StaticKeyword */)] : undefined, + /*asteriskToken*/ ts.isYieldExpression(parent) ? ts.createToken(39 /* AsteriskToken */) : undefined, methodName, + /*questionToken*/ undefined, + /*typeParameters*/ inJs ? undefined : ts.map(typeArguments, function (_, i) { + return ts.createTypeParameterDeclaration(84 /* T */ + typeArguments.length - 1 <= 90 /* Z */ ? String.fromCharCode(84 /* T */ + i) : "T" + i); + }), + /*parameters*/ createDummyParameters(args.length, /*names*/ undefined, /*minArgumentCount*/ undefined, inJs), + /*type*/ inJs ? undefined : ts.createKeywordTypeNode(119 /* AnyKeyword */), createStubbedMethodBody(preferences)); } codefix.createMethodFromCallExpression = createMethodFromCallExpression; function createDummyParameters(argCount, names, minArgumentCount, inJs) { var parameters = []; for (var i = 0; i < argCount; i++) { - var newParameter = ts.createParameter(undefined, undefined, undefined, names && names[i] || "arg" + i, minArgumentCount !== undefined && i >= minArgumentCount ? ts.createToken(55) : undefined, inJs ? undefined : ts.createKeywordTypeNode(119), undefined); + var newParameter = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + /*name*/ names && names[i] || "arg" + i, + /*questionToken*/ minArgumentCount !== undefined && i >= minArgumentCount ? ts.createToken(55 /* QuestionToken */) : undefined, + /*type*/ inJs ? undefined : ts.createKeywordTypeNode(119 /* AnyKeyword */), + /*initializer*/ undefined); parameters.push(newParameter); } return parameters; } function createMethodImplementingSignatures(signatures, name, optional, modifiers, preferences) { + /** This is *a* signature with the maximal number of arguments, + * such that if there is a "maximal" signature without rest arguments, + * this is one of them. + */ var maxArgsSignature = signatures[0]; var minArgumentCount = signatures[0].minArgumentCount; var someSigHasRestParameter = false; @@ -88161,44 +105322,61 @@ var ts; } var maxNonRestArgs = maxArgsSignature.parameters.length - (maxArgsSignature.hasRestParameter ? 1 : 0); var maxArgsParameterSymbolNames = maxArgsSignature.parameters.map(function (symbol) { return symbol.name; }); - var parameters = createDummyParameters(maxNonRestArgs, maxArgsParameterSymbolNames, minArgumentCount, false); + var parameters = createDummyParameters(maxNonRestArgs, maxArgsParameterSymbolNames, minArgumentCount, /*inJs*/ false); if (someSigHasRestParameter) { - var anyArrayType = ts.createArrayTypeNode(ts.createKeywordTypeNode(119)); - var restParameter = ts.createParameter(undefined, undefined, ts.createToken(24), maxArgsParameterSymbolNames[maxNonRestArgs] || "rest", maxNonRestArgs >= minArgumentCount ? ts.createToken(55) : undefined, anyArrayType, undefined); + var anyArrayType = ts.createArrayTypeNode(ts.createKeywordTypeNode(119 /* AnyKeyword */)); + var restParameter = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, ts.createToken(24 /* DotDotDotToken */), maxArgsParameterSymbolNames[maxNonRestArgs] || "rest", + /*questionToken*/ maxNonRestArgs >= minArgumentCount ? ts.createToken(55 /* QuestionToken */) : undefined, anyArrayType, + /*initializer*/ undefined); parameters.push(restParameter); } - return createStubbedMethod(modifiers, name, optional, undefined, parameters, undefined, preferences); + return createStubbedMethod(modifiers, name, optional, + /*typeParameters*/ undefined, parameters, + /*returnType*/ undefined, preferences); } function createStubbedMethod(modifiers, name, optional, typeParameters, parameters, returnType, preferences) { - return ts.createMethod(undefined, modifiers, undefined, name, optional ? ts.createToken(55) : undefined, typeParameters, parameters, returnType, createStubbedMethodBody(preferences)); + return ts.createMethod( + /*decorators*/ undefined, modifiers, + /*asteriskToken*/ undefined, name, optional ? ts.createToken(55 /* QuestionToken */) : undefined, typeParameters, parameters, returnType, createStubbedMethodBody(preferences)); } function createStubbedMethodBody(preferences) { - return ts.createBlock([ts.createThrow(ts.createNew(ts.createIdentifier("Error"), undefined, [ts.createLiteral("Method not implemented.", preferences.quotePreference === "single")]))], true); + return ts.createBlock([ts.createThrow(ts.createNew(ts.createIdentifier("Error"), + /*typeArguments*/ undefined, [ts.createLiteral("Method not implemented.", /*isSingleQuote*/ preferences.quotePreference === "single")]))], + /*multiline*/ true); } function createVisibilityModifier(flags) { - if (flags & 4) { - return ts.createToken(114); + if (flags & 4 /* Public */) { + return ts.createToken(114 /* PublicKeyword */); } - else if (flags & 16) { - return ts.createToken(113); + else if (flags & 16 /* Protected */) { + return ts.createToken(113 /* ProtectedKeyword */); } return undefined; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; (function (codefix) { var fixId = "inferFromUsage"; var errorCodes = [ + // Variable declarations ts.Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code, + // Variable uses ts.Diagnostics.Variable_0_implicitly_has_an_1_type.code, + // Parameter declarations ts.Diagnostics.Parameter_0_implicitly_has_an_1_type.code, ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code, + // Get Accessor declarations ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation.code, ts.Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type.code, + // Set Accessor declarations ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation.code, + // Property declarations ts.Diagnostics.Member_0_implicitly_has_an_1_type.code, ]; codefix.registerCodeFix({ @@ -88206,11 +105384,11 @@ var ts; getCodeActions: function (context) { var sourceFile = context.sourceFile, program = context.program, start = context.span.start, errorCode = context.errorCode, cancellationToken = context.cancellationToken; if (ts.isSourceFileJavaScript(sourceFile)) { - return undefined; + return undefined; // TODO: GH#20113 } - var token = ts.getTokenAtPosition(sourceFile, start, false); + var token = ts.getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false); var declaration; - var changes = ts.textChanges.ChangeTracker.with(context, function (changes) { declaration = doChange(changes, sourceFile, token, errorCode, program, cancellationToken, ts.returnTrue); }); + var changes = ts.textChanges.ChangeTracker.with(context, function (changes) { declaration = doChange(changes, sourceFile, token, errorCode, program, cancellationToken, /*markSeenseen*/ ts.returnTrue); }); return changes.length === 0 ? undefined : [codefix.createCodeFixAction(fixId, changes, [getDiagnostic(errorCode, token), ts.getNameOfDeclaration(declaration).getText(sourceFile)], fixId, ts.Diagnostics.Infer_all_types_from_usage)]; }, @@ -88219,14 +105397,14 @@ var ts; var sourceFile = context.sourceFile, program = context.program, cancellationToken = context.cancellationToken; var markSeen = ts.nodeSeenTracker(); return codefix.codeFixAll(context, errorCodes, function (changes, err) { - doChange(changes, sourceFile, ts.getTokenAtPosition(err.file, err.start, false), err.code, program, cancellationToken, markSeen); + doChange(changes, sourceFile, ts.getTokenAtPosition(err.file, err.start, /*includeJsDocComment*/ false), err.code, program, cancellationToken, markSeen); }); }, }); function getDiagnostic(errorCode, token) { switch (errorCode) { case ts.Diagnostics.Parameter_0_implicitly_has_an_1_type.code: - return ts.isSetAccessor(ts.getContainingFunction(token)) ? ts.Diagnostics.Infer_type_of_0_from_usage : ts.Diagnostics.Infer_parameter_types_from_usage; + return ts.isSetAccessor(ts.getContainingFunction(token)) ? ts.Diagnostics.Infer_type_of_0_from_usage : ts.Diagnostics.Infer_parameter_types_from_usage; // TODO: GH#18217 case ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code: return ts.Diagnostics.Infer_parameter_types_from_usage; default: @@ -88234,14 +105412,15 @@ var ts; } } function doChange(changes, sourceFile, token, errorCode, program, cancellationToken, markSeen) { - if (!ts.isParameterPropertyModifier(token.kind) && token.kind !== 71 && token.kind !== 24) { + if (!ts.isParameterPropertyModifier(token.kind) && token.kind !== 71 /* Identifier */ && token.kind !== 24 /* DotDotDotToken */) { return undefined; } var parent = token.parent; switch (errorCode) { + // Variable and Property declarations case ts.Diagnostics.Member_0_implicitly_has_an_1_type.code: case ts.Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code: - if ((ts.isVariableDeclaration(parent) && markSeen(parent)) || ts.isPropertyDeclaration(parent) || ts.isPropertySignature(parent)) { + if ((ts.isVariableDeclaration(parent) && markSeen(parent)) || ts.isPropertyDeclaration(parent) || ts.isPropertySignature(parent)) { // handle bad location annotateVariableDeclaration(changes, sourceFile, parent, program, cancellationToken); return parent; } @@ -88260,11 +105439,13 @@ var ts; return undefined; } switch (errorCode) { + // Parameter declarations case ts.Diagnostics.Parameter_0_implicitly_has_an_1_type.code: if (ts.isSetAccessor(containingFunction)) { annotateSetAccessor(changes, sourceFile, containingFunction, program, cancellationToken); return containingFunction; } + // falls through case ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code: if (markSeen(containingFunction)) { var param = ts.cast(parent, ts.isParameter); @@ -88272,6 +105453,7 @@ var ts; return param; } return undefined; + // Get Accessor declarations case ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation.code: case ts.Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type.code: if (ts.isGetAccessor(containingFunction) && ts.isIdentifier(containingFunction.name)) { @@ -88279,6 +105461,7 @@ var ts; return containingFunction; } return undefined; + // Set Accessor declarations case ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation.code: if (ts.isSetAccessor(containingFunction)) { annotateSetAccessor(changes, sourceFile, containingFunction, program, cancellationToken); @@ -88296,11 +105479,11 @@ var ts; } function isApplicableFunctionForInference(declaration) { switch (declaration.kind) { - case 234: - case 154: - case 155: + case 234 /* FunctionDeclaration */: + case 154 /* MethodDeclaration */: + case 155 /* Constructor */: return true; - case 192: + case 192 /* FunctionExpression */: return !!declaration.name; } return false; @@ -88311,6 +105494,7 @@ var ts; } var types = inferTypeForParametersFromUsage(containingFunction, sourceFile, program, cancellationToken) || containingFunction.parameters.map(function (p) { return ts.isIdentifier(p.name) ? inferTypeForVariableFromUsage(p.name, program, cancellationToken) : undefined; }); + // We didn't actually find a set of type inference positions matching each parameter position if (!types || containingFunction.parameters.length !== types.length) { return; } @@ -88336,9 +105520,10 @@ var ts; function getTypeNodeIfAccessible(type, enclosingScope, checker) { var typeIsAccessible = true; var notAccessible = function () { typeIsAccessible = false; }; - var res = checker.typeToTypeNode(type, enclosingScope, undefined, { + var res = checker.typeToTypeNode(type, enclosingScope, /*flags*/ undefined, { trackSymbol: function (symbol, declaration, meaning) { - typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, false).accessibility === 0; + // TODO: GH#18217 + typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility === 0 /* Accessible */; }, reportInaccessibleThisError: notAccessible, reportPrivateInBaseOfClassExpression: notAccessible, @@ -88347,6 +105532,7 @@ var ts; return typeIsAccessible ? res : undefined; } function getReferences(token, program, cancellationToken) { + // Position shouldn't matter since token is not a SourceFile. return ts.mapDefined(ts.FindAllReferences.getReferenceEntriesForNode(-1, token, program, program.getSourceFiles(), cancellationToken), function (entry) { return entry.type === "node" ? ts.tryCast(entry.node, ts.isIdentifier) : undefined; }); @@ -88356,13 +105542,13 @@ var ts; } function inferTypeForParametersFromUsage(containingFunction, sourceFile, program, cancellationToken) { switch (containingFunction.kind) { - case 155: - case 192: - case 234: - case 154: - var isConstructor = containingFunction.kind === 155; + case 155 /* Constructor */: + case 192 /* FunctionExpression */: + case 234 /* FunctionDeclaration */: + case 154 /* MethodDeclaration */: + var isConstructor = containingFunction.kind === 155 /* Constructor */; var searchToken = isConstructor ? - ts.findChildOfKind(containingFunction, 123, sourceFile) : + ts.findChildOfKind(containingFunction, 123 /* ConstructorKeyword */, sourceFile) : containingFunction.name; if (searchToken) { return InferFromReference.inferTypeForParametersFromReferences(getReferences(searchToken, program, cancellationToken), containingFunction, program.getTypeChecker(), cancellationToken); @@ -88394,7 +105580,7 @@ var ts; cancellationToken.throwIfCancellationRequested(); inferTypeFromContext(reference, checker, usageContext); } - var isConstructor = declaration.kind === 155; + var isConstructor = declaration.kind === 155 /* Constructor */; var callContexts = isConstructor ? usageContext.constructContexts : usageContext.callContexts; return callContexts && declaration.parameters.map(function (parameter, parameterIndex) { var types = []; @@ -88416,7 +105602,7 @@ var ts; if (!types.length) { return undefined; } - var type = checker.getWidenedType(checker.getUnionType(types, 2)); + var type = checker.getWidenedType(checker.getUnionType(types, 2 /* Subtype */)); return isRest ? checker.createArrayType(type) : type; }); } @@ -88426,21 +105612,21 @@ var ts; node = node.parent; } switch (node.parent.kind) { - case 199: + case 199 /* PostfixUnaryExpression */: usageContext.isNumber = true; break; - case 198: + case 198 /* PrefixUnaryExpression */: inferTypeFromPrefixUnaryExpressionContext(node.parent, usageContext); break; - case 200: + case 200 /* BinaryExpression */: inferTypeFromBinaryExpressionContext(node, node.parent, checker, usageContext); break; - case 266: - case 267: + case 266 /* CaseClause */: + case 267 /* DefaultClause */: inferTypeFromSwitchStatementLabelContext(node.parent, checker, usageContext); break; - case 187: - case 188: + case 187 /* CallExpression */: + case 188 /* NewExpression */: if (node.parent.expression === node) { inferTypeFromCallExpressionContext(node.parent, checker, usageContext); } @@ -88448,21 +105634,22 @@ var ts; inferTypeFromContextualType(node, checker, usageContext); } break; - case 185: + case 185 /* PropertyAccessExpression */: inferTypeFromPropertyAccessExpressionContext(node.parent, checker, usageContext); break; - case 186: + case 186 /* ElementAccessExpression */: inferTypeFromPropertyElementExpressionContext(node.parent, node, checker, usageContext); break; - case 232: { + case 232 /* VariableDeclaration */: { var _a = node.parent, name = _a.name, initializer = _a.initializer; if (node === name) { - if (initializer) { + if (initializer) { // This can happen for `let x = null;` which still has an implicit-any error. addCandidateType(usageContext, checker.getTypeAtLocation(initializer)); } break; } } + // falls through default: return inferTypeFromContextualType(node, checker, usageContext); } @@ -88474,90 +105661,104 @@ var ts; } function inferTypeFromPrefixUnaryExpressionContext(node, usageContext) { switch (node.operator) { - case 43: - case 44: - case 38: - case 52: + case 43 /* PlusPlusToken */: + case 44 /* MinusMinusToken */: + case 38 /* MinusToken */: + case 52 /* TildeToken */: usageContext.isNumber = true; break; - case 37: + case 37 /* PlusToken */: usageContext.isNumberOrString = true; break; + // case SyntaxKind.ExclamationToken: + // no inferences here; } } function inferTypeFromBinaryExpressionContext(node, parent, checker, usageContext) { switch (parent.operatorToken.kind) { - case 40: - case 39: - case 41: - case 42: - case 45: - case 46: - case 47: - case 48: - case 49: - case 50: - case 60: - case 62: - case 61: - case 63: - case 64: - case 68: - case 69: - case 70: - case 65: - case 67: - case 66: - case 38: - case 27: - case 30: - case 29: - case 31: + // ExponentiationOperator + case 40 /* AsteriskAsteriskToken */: + // MultiplicativeOperator + case 39 /* AsteriskToken */: + case 41 /* SlashToken */: + case 42 /* PercentToken */: + // ShiftOperator + case 45 /* LessThanLessThanToken */: + case 46 /* GreaterThanGreaterThanToken */: + case 47 /* GreaterThanGreaterThanGreaterThanToken */: + // BitwiseOperator + case 48 /* AmpersandToken */: + case 49 /* BarToken */: + case 50 /* CaretToken */: + // CompoundAssignmentOperator + case 60 /* MinusEqualsToken */: + case 62 /* AsteriskAsteriskEqualsToken */: + case 61 /* AsteriskEqualsToken */: + case 63 /* SlashEqualsToken */: + case 64 /* PercentEqualsToken */: + case 68 /* AmpersandEqualsToken */: + case 69 /* BarEqualsToken */: + case 70 /* CaretEqualsToken */: + case 65 /* LessThanLessThanEqualsToken */: + case 67 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + case 66 /* GreaterThanGreaterThanEqualsToken */: + // AdditiveOperator + case 38 /* MinusToken */: + // RelationalOperator + case 27 /* LessThanToken */: + case 30 /* LessThanEqualsToken */: + case 29 /* GreaterThanToken */: + case 31 /* GreaterThanEqualsToken */: var operandType = checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left); - if (operandType.flags & 544) { + if (operandType.flags & 544 /* EnumLike */) { addCandidateType(usageContext, operandType); } else { usageContext.isNumber = true; } break; - case 59: - case 37: + case 59 /* PlusEqualsToken */: + case 37 /* PlusToken */: var otherOperandType = checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left); - if (otherOperandType.flags & 544) { + if (otherOperandType.flags & 544 /* EnumLike */) { addCandidateType(usageContext, otherOperandType); } - else if (otherOperandType.flags & 168) { + else if (otherOperandType.flags & 168 /* NumberLike */) { usageContext.isNumber = true; } - else if (otherOperandType.flags & 68) { + else if (otherOperandType.flags & 68 /* StringLike */) { usageContext.isString = true; } else { usageContext.isNumberOrString = true; } break; - case 58: - case 32: - case 34: - case 35: - case 33: + // AssignmentOperators + case 58 /* EqualsToken */: + case 32 /* EqualsEqualsToken */: + case 34 /* EqualsEqualsEqualsToken */: + case 35 /* ExclamationEqualsEqualsToken */: + case 33 /* ExclamationEqualsToken */: addCandidateType(usageContext, checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left)); break; - case 92: + case 92 /* InKeyword */: if (node === parent.left) { usageContext.isString = true; } break; - case 54: + // LogicalOperator + case 54 /* BarBarToken */: if (node === parent.left && - (node.parent.parent.kind === 232 || ts.isAssignmentExpression(node.parent.parent, true))) { + (node.parent.parent.kind === 232 /* VariableDeclaration */ || ts.isAssignmentExpression(node.parent.parent, /*excludeCompoundAssignment*/ true))) { + // var x = x || {}; + // TODO: use getFalsyflagsOfType addCandidateType(usageContext, checker.getTypeAtLocation(parent.right)); } break; - case 53: - case 26: - case 93: + case 53 /* AmpersandAmpersandToken */: + case 26 /* CommaToken */: + case 93 /* InstanceOfKeyword */: + // nothing to infer here break; } } @@ -88576,7 +105777,7 @@ var ts; } } inferTypeFromContext(parent, checker, callContext.returnType); - if (parent.kind === 187) { + if (parent.kind === 187 /* CallExpression */) { (usageContext.callContexts || (usageContext.callContexts = [])).push(callContext); } else { @@ -88601,7 +105802,7 @@ var ts; var indexType = checker.getTypeAtLocation(parent); var indexUsageContext = {}; inferTypeFromContext(parent, checker, indexUsageContext); - if (indexType.flags & 168) { + if (indexType.flags & 168 /* NumberLike */) { usageContext.numberIndexContext = indexUsageContext; } else { @@ -88620,15 +105821,15 @@ var ts; return checker.getStringType(); } else if (usageContext.candidateTypes) { - return checker.getWidenedType(checker.getUnionType(usageContext.candidateTypes.map(function (t) { return checker.getBaseTypeOfLiteralType(t); }), 2)); + return checker.getWidenedType(checker.getUnionType(usageContext.candidateTypes.map(function (t) { return checker.getBaseTypeOfLiteralType(t); }), 2 /* Subtype */)); } else if (usageContext.properties && hasCallContext(usageContext.properties.get("then"))) { - var paramType = getParameterTypeFromCallContexts(0, usageContext.properties.get("then").callContexts, false, checker); + var paramType = getParameterTypeFromCallContexts(0, usageContext.properties.get("then").callContexts, /*isRestParameter*/ false, checker); // TODO: GH#18217 var types = paramType.getCallSignatures().map(function (c) { return c.getReturnType(); }); - return checker.createPromiseType(types.length ? checker.getUnionType(types, 2) : checker.getAnyType()); + return checker.createPromiseType(types.length ? checker.getUnionType(types, 2 /* Subtype */) : checker.getAnyType()); } else if (usageContext.properties && hasCallContext(usageContext.properties.get("push"))) { - return checker.createArrayType(getParameterTypeFromCallContexts(0, usageContext.properties.get("push").callContexts, false, checker)); + return checker.createArrayType(getParameterTypeFromCallContexts(0, usageContext.properties.get("push").callContexts, /*isRestParameter*/ false, checker)); } else if (usageContext.properties || usageContext.callContexts || usageContext.constructContexts || usageContext.numberIndexContext || usageContext.stringIndexContext) { var members_6 = ts.createUnderscoreEscapedMap(); @@ -88638,7 +105839,7 @@ var ts; var numberIndexInfo = void 0; if (usageContext.properties) { usageContext.properties.forEach(function (context, name) { - var symbol = checker.createSymbol(4, name); + var symbol = checker.createSymbol(4 /* Property */, name); symbol.type = getTypeFromUsageContext(context, checker) || checker.getAnyType(); members_6.set(name, symbol); }); @@ -88656,12 +105857,12 @@ var ts; } } if (usageContext.numberIndexContext) { - numberIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.numberIndexContext, checker), false); + numberIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.numberIndexContext, checker), /*isReadonly*/ false); // TODO: GH#18217 } if (usageContext.stringIndexContext) { - stringIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.stringIndexContext, checker), false); + stringIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.stringIndexContext, checker), /*isReadonly*/ false); } - return checker.createAnonymousType(undefined, members_6, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); + return checker.createAnonymousType(/*symbol*/ undefined, members_6, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); // TODO: GH#18217 } else { return undefined; @@ -88683,7 +105884,7 @@ var ts; } } if (types.length) { - var type = checker.getWidenedType(checker.getUnionType(types, 2)); + var type = checker.getWidenedType(checker.getUnionType(types, 2 /* Subtype */)); return isRestParameter ? checker.createArrayType(type) : type; } return undefined; @@ -88691,15 +105892,16 @@ var ts; function getSignatureFromCallContext(callContext, checker) { var parameters = []; for (var i = 0; i < callContext.argumentTypes.length; i++) { - var symbol = checker.createSymbol(1, ts.escapeLeadingUnderscores("arg" + i)); + var symbol = checker.createSymbol(1 /* FunctionScopedVariable */, ts.escapeLeadingUnderscores("arg" + i)); symbol.type = checker.getWidenedType(checker.getBaseTypeOfLiteralType(callContext.argumentTypes[i])); parameters.push(symbol); } var returnType = getTypeFromUsageContext(callContext.returnType, checker) || checker.getVoidType(); - return checker.createSignature(undefined, undefined, undefined, parameters, returnType, undefined, callContext.argumentTypes.length, false, false); + // TODO: GH#18217 + return checker.createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, parameters, returnType, /*typePredicate*/ undefined, callContext.argumentTypes.length, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); } function addCandidateType(context, type) { - if (type && !(type.flags & 1) && !(type.flags & 32768)) { + if (type && !(type.flags & 1 /* Any */) && !(type.flags & 32768 /* Never */)) { (context.candidateTypes || (context.candidateTypes = [])).push(type); } } @@ -88709,6 +105911,7 @@ var ts; })(InferFromReference || (InferFromReference = {})); })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -88719,9 +105922,13 @@ var ts; var namespace = ts.getNamespaceDeclarationNode(node); var opts = context.program.getCompilerOptions(); var variations = []; - variations.push(createAction(context, sourceFile, node, ts.makeImport(namespace.name, undefined, node.moduleSpecifier, ts.getQuotePreference(sourceFile, context.preferences)))); + // import Bluebird from "bluebird"; + variations.push(createAction(context, sourceFile, node, ts.makeImport(namespace.name, /*namedImports*/ undefined, node.moduleSpecifier, ts.getQuotePreference(sourceFile, context.preferences)))); if (ts.getEmitModuleKind(opts) === ts.ModuleKind.CommonJS) { - variations.push(createAction(context, sourceFile, node, ts.createImportEqualsDeclaration(undefined, undefined, namespace.name, ts.createExternalModuleReference(node.moduleSpecifier)))); + // import Bluebird = require("bluebird"); + variations.push(createAction(context, sourceFile, node, ts.createImportEqualsDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, namespace.name, ts.createExternalModuleReference(node.moduleSpecifier)))); } return variations; } @@ -88738,8 +105945,8 @@ var ts; }); function getActionsForUsageOfInvalidImport(context) { var sourceFile = context.sourceFile; - var targetKind = ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures.code === context.errorCode ? 187 : 188; - var node = ts.findAncestor(ts.getTokenAtPosition(sourceFile, context.span.start, false), function (a) { return a.kind === targetKind && a.getStart() === context.span.start && a.getEnd() === (context.span.start + context.span.length); }); + var targetKind = ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures.code === context.errorCode ? 187 /* CallExpression */ : 188 /* NewExpression */; + var node = ts.findAncestor(ts.getTokenAtPosition(sourceFile, context.span.start, /*includeJsDocComment*/ false), function (a) { return a.kind === targetKind && a.getStart() === context.span.start && a.getEnd() === (context.span.start + context.span.length); }); if (!node) { return []; } @@ -88748,6 +105955,7 @@ var ts; } codefix.registerCodeFix({ errorCodes: [ + // The following error codes cover pretty much all assignability errors that could involve an expression ts.Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1.code, ts.Diagnostics.Type_0_does_not_satisfy_the_constraint_1.code, ts.Diagnostics.Type_0_is_not_assignable_to_type_1.code, @@ -88765,19 +105973,19 @@ var ts; }); function getActionsForInvalidImportLocation(context) { var sourceFile = context.sourceFile; - var node = ts.findAncestor(ts.getTokenAtPosition(sourceFile, context.span.start, false), function (a) { return a.getStart() === context.span.start && a.getEnd() === (context.span.start + context.span.length); }); + var node = ts.findAncestor(ts.getTokenAtPosition(sourceFile, context.span.start, /*includeJsDocComment*/ false), function (a) { return a.getStart() === context.span.start && a.getEnd() === (context.span.start + context.span.length); }); if (!node) { return []; } return getImportCodeFixesForExpression(context, node); } function getImportCodeFixesForExpression(context, expr) { - var type = context.program.getTypeChecker().getTypeAtLocation(expr); + var type = context.program.getTypeChecker().getTypeAtLocation(expr); // TODO: GH#18217 if (!(type.symbol && type.symbol.originatingImport)) { return []; } var fixes = []; - var relatedImport = type.symbol.originatingImport; + var relatedImport = type.symbol.originatingImport; // TODO: GH#18217 if (!ts.isImportCall(relatedImport)) { ts.addRange(fixes, getCodeFixesForImportDeclaration(context, relatedImport)); } @@ -88790,6 +105998,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -88839,7 +106048,7 @@ var ts; }, }); function getPropertyDeclaration(sourceFile, pos) { - var token = ts.getTokenAtPosition(sourceFile, pos, false); + var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); return ts.isIdentifier(token) ? ts.cast(token.parent, ts.isPropertyDeclaration) : undefined; } function getActionForAddMissingDefiniteAssignmentAssertion(context, propertyDeclaration) { @@ -88847,7 +106056,7 @@ var ts; return codefix.createCodeFixAction(fixName, changes, [ts.Diagnostics.Add_definite_assignment_assertion_to_property_0, propertyDeclaration.getText()], fixIdAddDefiniteAssignmentAssertions, ts.Diagnostics.Add_definite_assignment_assertions_to_all_uninitialized_properties); } function addDefiniteAssignmentAssertion(changeTracker, propertyDeclarationSourceFile, propertyDeclaration) { - var property = ts.updateProperty(propertyDeclaration, propertyDeclaration.decorators, propertyDeclaration.modifiers, propertyDeclaration.name, ts.createToken(51), propertyDeclaration.type, propertyDeclaration.initializer); + var property = ts.updateProperty(propertyDeclaration, propertyDeclaration.decorators, propertyDeclaration.modifiers, propertyDeclaration.name, ts.createToken(51 /* ExclamationToken */), propertyDeclaration.type, propertyDeclaration.initializer); changeTracker.replaceNode(propertyDeclarationSourceFile, propertyDeclaration, property); } function getActionForAddMissingUndefinedType(context, propertyDeclaration) { @@ -88855,8 +106064,8 @@ var ts; return codefix.createCodeFixAction(fixName, changes, [ts.Diagnostics.Add_undefined_type_to_property_0, propertyDeclaration.name.getText()], fixIdAddUndefinedType, ts.Diagnostics.Add_undefined_type_to_all_uninitialized_properties); } function addUndefinedType(changeTracker, propertyDeclarationSourceFile, propertyDeclaration) { - var undefinedTypeNode = ts.createKeywordTypeNode(140); - var type = propertyDeclaration.type; + var undefinedTypeNode = ts.createKeywordTypeNode(140 /* UndefinedKeyword */); + var type = propertyDeclaration.type; // TODO: GH#18217 var types = ts.isUnionTypeNode(type) ? type.types.concat(undefinedTypeNode) : [type, undefinedTypeNode]; changeTracker.replaceNode(propertyDeclarationSourceFile, type, ts.createUnionTypeNode(types)); } @@ -88873,10 +106082,10 @@ var ts; changeTracker.replaceNode(propertyDeclarationSourceFile, propertyDeclaration, property); } function getInitializer(checker, propertyDeclaration) { - return getDefaultValueFromType(checker, checker.getTypeFromTypeNode(propertyDeclaration.type)); + return getDefaultValueFromType(checker, checker.getTypeFromTypeNode(propertyDeclaration.type)); // TODO: GH#18217 } function getDefaultValueFromType(checker, type) { - if (type.flags & 256) { + if (type.flags & 256 /* BooleanLiteral */) { return type === checker.getFalseType() ? ts.createFalse() : ts.createTrue(); } else if (type.isLiteral()) { @@ -88887,12 +106096,12 @@ var ts; } else if (type.isClass()) { var classDeclaration = ts.getClassLikeDeclarationOfSymbol(type.symbol); - if (!classDeclaration || ts.hasModifier(classDeclaration, 128)) + if (!classDeclaration || ts.hasModifier(classDeclaration, 128 /* Abstract */)) return undefined; var constructorDeclaration = ts.getFirstConstructorWithBody(classDeclaration); if (constructorDeclaration && constructorDeclaration.parameters.length) return undefined; - return ts.createNew(ts.createIdentifier(type.symbol.name), undefined, undefined); + return ts.createNew(ts.createIdentifier(type.symbol.name), /*typeArguments*/ undefined, /*argumentsArray*/ undefined); } else if (checker.isArrayLikeType(type)) { return ts.createArrayLiteral(); @@ -88901,6 +106110,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -88919,18 +106129,19 @@ var ts; function doChange(changes, sourceFile, pos, program) { var _a = getInfo(sourceFile, pos), statement = _a.statement, name = _a.name, required = _a.required; changes.replaceNode(sourceFile, statement, ts.getAllowSyntheticDefaultImports(program.getCompilerOptions()) - ? ts.createImportDeclaration(undefined, undefined, ts.createImportClause(name, undefined), required) - : ts.createImportEqualsDeclaration(undefined, undefined, name, ts.createExternalModuleReference(required))); + ? ts.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, ts.createImportClause(name, /*namedBindings*/ undefined), required) + : ts.createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, name, ts.createExternalModuleReference(required))); } function getInfo(sourceFile, pos) { - var parent = ts.getTokenAtPosition(sourceFile, pos, false).parent; - if (!ts.isRequireCall(parent, true)) + var parent = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false).parent; + if (!ts.isRequireCall(parent, /*checkArgumentIsStringLiteralLike*/ true)) throw ts.Debug.failBadSyntaxKind(parent); var decl = ts.cast(parent.parent, ts.isVariableDeclaration); return { statement: ts.cast(decl.parent.parent, ts.isVariableStatement), name: ts.cast(decl.name, ts.isIdentifier), required: parent.arguments[0] }; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -88955,9 +106166,9 @@ var ts; }); }, }); function getInfo(sourceFile, pos) { - var name = ts.getTokenAtPosition(sourceFile, pos, false); + var name = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); if (!ts.isIdentifier(name)) - return undefined; + return undefined; // bad input var parent = name.parent; if (ts.isImportEqualsDeclaration(parent) && ts.isExternalModuleReference(parent.moduleReference)) { return { importNode: parent, name: name, moduleSpecifier: parent.moduleReference.expression }; @@ -88968,10 +106179,11 @@ var ts; } } function doChange(changes, sourceFile, info, preferences) { - changes.replaceNode(sourceFile, info.importNode, ts.makeImport(info.name, undefined, info.moduleSpecifier, ts.getQuotePreference(sourceFile, preferences))); + changes.replaceNode(sourceFile, info.importNode, ts.makeImport(info.name, /*namedImports*/ undefined, info.moduleSpecifier, ts.getQuotePreference(sourceFile, preferences))); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -88993,17 +106205,18 @@ var ts; }); }, }); function getImportTypeNode(sourceFile, pos) { - var token = ts.getTokenAtPosition(sourceFile, pos, false); - ts.Debug.assert(token.kind === 91); - ts.Debug.assert(token.parent.kind === 179); + var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); + ts.Debug.assert(token.kind === 91 /* ImportKeyword */); + ts.Debug.assert(token.parent.kind === 179 /* ImportType */); return token.parent; } function doChange(changes, sourceFile, importType) { - var newTypeNode = ts.updateImportTypeNode(importType, importType.argument, importType.qualifier, importType.typeArguments, true); + var newTypeNode = ts.updateImportTypeNode(importType, importType.argument, importType.qualifier, importType.typeArguments, /* isTypeOf */ true); changes.replaceNode(sourceFile, importType, newTypeNode); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -89030,7 +106243,7 @@ var ts; }); } }); function getInfo(sourceFile, pos) { - var token = ts.getTokenAtPosition(sourceFile, pos, false); + var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); var indexSignature = ts.cast(token.parent.parent, ts.isIndexSignatureDeclaration); if (ts.isClassDeclaration(indexSignature.parent)) return undefined; @@ -89046,7 +106259,7 @@ var ts; var otherMembers = members.filter(function (member) { return !ts.isIndexSignatureDeclaration(member); }); var parameter = ts.first(indexSignature.parameters); var mappedTypeParameter = ts.createTypeParameterDeclaration(ts.cast(parameter.name, ts.isIdentifier), parameter.type); - var mappedIntersectionType = ts.createMappedTypeNode(ts.hasReadonlyModifier(indexSignature) ? ts.createModifier(132) : undefined, mappedTypeParameter, indexSignature.questionToken, indexSignature.type); + var mappedIntersectionType = ts.createMappedTypeNode(ts.hasReadonlyModifier(indexSignature) ? ts.createModifier(132 /* ReadonlyKeyword */) : undefined, mappedTypeParameter, indexSignature.questionToken, indexSignature.type); var intersectionType = ts.createIntersectionTypeNode(ts.getAllSuperTypeNodes(container).concat([ mappedIntersectionType ], (otherMembers.length ? [ts.createTypeLiteralNode(otherMembers)] : ts.emptyArray))); @@ -89054,6 +106267,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var refactor; @@ -89068,8 +106282,8 @@ var ts; var i = getImportToConvert(context); if (!i) return undefined; - var description = i.kind === 246 ? ts.Diagnostics.Convert_namespace_import_to_named_imports.message : ts.Diagnostics.Convert_named_imports_to_namespace_import.message; - var actionName = i.kind === 246 ? actionNameNamespaceToNamed : actionNameNamedToNamespace; + var description = i.kind === 246 /* NamespaceImport */ ? ts.Diagnostics.Convert_namespace_import_to_named_imports.message : ts.Diagnostics.Convert_named_imports_to_namespace_import.message; + var actionName = i.kind === 246 /* NamespaceImport */ ? actionNameNamespaceToNamed : actionNameNamedToNamespace; return [{ name: refactorName, description: description, actions: [{ name: actionName, description: description }] }]; }, getEditsForAction: function (context, actionName) { @@ -89078,10 +106292,11 @@ var ts; return { edits: edits, renameFilename: undefined, renameLocation: undefined }; } }); + // Can convert imports of the form `import * as m from "m";` or `import d, { x, y } from "m";`. function getImportToConvert(context) { var file = context.file; var span = ts.getRefactorContextSpan(context); - var token = ts.getTokenAtPosition(file, span.start, false); + var token = ts.getTokenAtPosition(file, span.start, /*includeJsDocComment*/ false); var importDecl = ts.getParentNodeInSpan(token, file, span); if (!importDecl || !ts.isImportDeclaration(importDecl)) return undefined; @@ -89090,7 +106305,7 @@ var ts; } function doChange(sourceFile, program, changes, toConvert) { var checker = program.getTypeChecker(); - if (toConvert.kind === 246) { + if (toConvert.kind === 246 /* NamespaceImport */) { doChangeNamespaceToNamed(sourceFile, checker, changes, toConvert, ts.getAllowSyntheticDefaultImports(program.getCompilerOptions())); } else { @@ -89108,13 +106323,14 @@ var ts; else { var parent = ts.cast(id.parent, ts.isPropertyAccessExpression); var exportName = parent.name.text; - if (checker.resolveName(exportName, id, 67108863, true)) { + if (checker.resolveName(exportName, id, 67108863 /* All */, /*excludeGlobals*/ true)) { conflictingNames.set(exportName, true); } ts.Debug.assert(parent.expression === id); nodesToReplace.push(parent); } }); + // We may need to change `mod.x` to `_x` to avoid a name conflict. var exportNameToImportName = ts.createMap(); for (var _i = 0, nodesToReplace_1 = nodesToReplace; _i < nodesToReplace_1.length; _i++) { var propertyAccess = nodesToReplace_1[_i]; @@ -89131,7 +106347,8 @@ var ts; }); var importDecl = toConvert.parent.parent; if (usedAsNamespaceOrDefault && !allowSyntheticDefaultImports) { - changes.insertNodeAfter(sourceFile, importDecl, updateImport(importDecl, undefined, importSpecifiers)); + // Need to leave the namespace import alone + changes.insertNodeAfter(sourceFile, importDecl, updateImport(importDecl, /*defaultImportName*/ undefined, importSpecifiers)); } else { changes.replaceNode(sourceFile, importDecl, updateImport(importDecl, usedAsNamespaceOrDefault ? ts.createIdentifier(toConvert.name.text) : undefined, importSpecifiers)); @@ -89140,10 +106357,10 @@ var ts; function doChangeNamedToNamespace(sourceFile, checker, changes, toConvert) { var importDecl = toConvert.parent.parent; var moduleSpecifier = importDecl.moduleSpecifier; - var preferredName = moduleSpecifier && ts.isStringLiteral(moduleSpecifier) ? ts.codefix.moduleSpecifierToValidIdentifier(moduleSpecifier.text, 6) : "module"; + var preferredName = moduleSpecifier && ts.isStringLiteral(moduleSpecifier) ? ts.codefix.moduleSpecifierToValidIdentifier(moduleSpecifier.text, 6 /* ESNext */) : "module"; var namespaceNameConflicts = toConvert.elements.some(function (element) { return ts.FindAllReferences.Core.eachSymbolReferenceInFile(element.name, checker, sourceFile, function (id) { - return !!checker.resolveName(preferredName, id, 67108863, true); + return !!checker.resolveName(preferredName, id, 67108863 /* All */, /*excludeGlobals*/ true); }) || false; }); var namespaceImportName = namespaceNameConflicts ? ts.getUniqueName(preferredName, sourceFile) : preferredName; @@ -89171,15 +106388,16 @@ var ts; } changes.replaceNode(sourceFile, toConvert, ts.createNamespaceImport(ts.createIdentifier(namespaceImportName))); if (neededNamedImports.length) { - changes.insertNodeAfter(sourceFile, toConvert.parent.parent, updateImport(importDecl, undefined, neededNamedImports)); + changes.insertNodeAfter(sourceFile, toConvert.parent.parent, updateImport(importDecl, /*defaultImportName*/ undefined, neededNamedImports)); } } function updateImport(old, defaultImportName, elements) { - return ts.createImportDeclaration(undefined, undefined, ts.createImportClause(defaultImportName, elements && elements.length ? ts.createNamedImports(elements) : undefined), old.moduleSpecifier); + return ts.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, ts.createImportClause(defaultImportName, elements && elements.length ? ts.createNamedImports(elements) : undefined), old.moduleSpecifier); } })(generateGetAccessorAndSetAccessor = refactor.generateGetAccessorAndSetAccessor || (refactor.generateGetAccessorAndSetAccessor = {})); })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var refactor; @@ -89188,6 +106406,10 @@ var ts; (function (extractSymbol) { var refactorName = "Extract Symbol"; refactor.registerRefactor(refactorName, { getAvailableActions: getAvailableActions, getEditsForAction: getEditsForAction }); + /** + * Compute the associated code actions + * Exported for tests. + */ function getAvailableActions(context) { var rangeToExtract = getRangeToExtract(context.file, ts.getRefactorContextSpan(context)); var targetRange = rangeToExtract.targetRange; @@ -89196,6 +106418,7 @@ var ts; } var extractions = getPossibleExtractions(targetRange, context); if (extractions === undefined) { + // No extractions possible return undefined; } var functionActions = []; @@ -89205,7 +106428,11 @@ var ts; var i = 0; for (var _i = 0, extractions_1 = extractions; _i < extractions_1.length; _i++) { var _a = extractions_1[_i], functionExtraction = _a.functionExtraction, constantExtraction = _a.constantExtraction; + // Skip these since we don't have a way to report errors yet if (functionExtraction.errors.length === 0) { + // Don't issue refactorings with duplicated names. + // Scopes come back in "innermost first" order, so extractions will + // preferentially go into nearer scopes var description = functionExtraction.description; if (!usedFunctionNames.has(description)) { usedFunctionNames.set(description, true); @@ -89215,7 +106442,11 @@ var ts; }); } } + // Skip these since we don't have a way to report errors yet if (constantExtraction.errors.length === 0) { + // Don't issue refactorings with duplicated names. + // Scopes come back in "innermost first" order, so extractions will + // preferentially go into nearer scopes var description = constantExtraction.description; if (!usedConstantNames.has(description)) { usedConstantNames.set(description, true); @@ -89225,6 +106456,8 @@ var ts; }); } } + // *do* increment i anyway because we'll look for the i-th scope + // later when actually doing the refactoring if the user requests it i++; } var infos = []; @@ -89245,9 +106478,10 @@ var ts; return infos.length ? infos : undefined; } extractSymbol.getAvailableActions = getAvailableActions; + /* Exported for tests */ function getEditsForAction(context, actionName) { var rangeToExtract = getRangeToExtract(context.file, ts.getRefactorContextSpan(context)); - var targetRange = rangeToExtract.targetRange; + var targetRange = rangeToExtract.targetRange; // TODO:GH#18217 var parsedFunctionIndexMatch = /^function_scope_(\d+)$/.exec(actionName); if (parsedFunctionIndexMatch) { var index = +parsedFunctionIndexMatch[1]; @@ -89263,6 +106497,7 @@ var ts; ts.Debug.fail("Unrecognized action name"); } extractSymbol.getEditsForAction = getEditsForAction; + // Move these into diagnostic messages if they become user-facing var Messages; (function (Messages) { function createMessage(message) { @@ -89298,29 +106533,47 @@ var ts; RangeFacts[RangeFacts["IsGenerator"] = 2] = "IsGenerator"; RangeFacts[RangeFacts["IsAsyncFunction"] = 4] = "IsAsyncFunction"; RangeFacts[RangeFacts["UsesThis"] = 8] = "UsesThis"; + /** + * The range is in a function which needs the 'static' modifier in a class + */ RangeFacts[RangeFacts["InStaticRegion"] = 16] = "InStaticRegion"; })(RangeFacts || (RangeFacts = {})); + /** + * getRangeToExtract takes a span inside a text file and returns either an expression or an array + * of statements representing the minimum set of nodes needed to extract the entire span. This + * process may fail, in which case a set of errors is returned instead (these are currently + * not shown to the user, but can be used by us diagnostically) + */ + // exported only for tests function getRangeToExtract(sourceFile, span) { var length = span.length; if (length === 0) { return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractEmpty)] }; } - var start = ts.getParentNodeInSpan(ts.getTokenAtPosition(sourceFile, span.start, false), sourceFile, span); + // Walk up starting from the the start position until we find a non-SourceFile node that subsumes the selected span. + // This may fail (e.g. you select two statements in the root of a source file) + var start = ts.getParentNodeInSpan(ts.getTokenAtPosition(sourceFile, span.start, /*includeJsDocComment*/ false), sourceFile, span); + // Do the same for the ending position var end = ts.getParentNodeInSpan(ts.findTokenOnLeftOfPosition(sourceFile, ts.textSpanEnd(span)), sourceFile, span); var declarations = []; + // We'll modify these flags as we walk the tree to collect data + // about what things need to be done as part of the extraction. var rangeFacts = RangeFacts.None; if (!start || !end) { + // cannot find either start or end node return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; } if (start.parent !== end.parent) { + // start and end nodes belong to different subtrees return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; } if (start !== end) { + // start and end should be statements and parent should be either block or a source file if (!isBlockLike(start.parent)) { return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; } var statements = []; - var start2 = start; + var start2 = start; // TODO: GH#18217 Need to alias `start` to get this to compile. See https://github.com/Microsoft/TypeScript/issues/19955#issuecomment-344118248 for (var _i = 0, _a = start2.parent.statements; _i < _a.length; _i++) { var statement = _a[_i]; if (statement === start || statements.length) { @@ -89335,19 +106588,30 @@ var ts; } } if (!statements.length) { + // https://github.com/Microsoft/TypeScript/issues/20559 + // Ranges like [|case 1: break;|] will fail to populate `statements` because + // they will never find `start` in `start.parent.statements`. + // Consider: We could support ranges like [|case 1:|] by refining them to just + // the expression. return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; } return { targetRange: { range: statements, facts: rangeFacts, declarations: declarations } }; } if (ts.isReturnStatement(start) && !start.expression) { + // Makes no sense to extract an expression-less return statement. return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; } + // We have a single node (start) var node = refineNode(start); var errors = checkRootNode(node) || checkNode(node); if (errors) { return { errors: errors }; } - return { targetRange: { range: getStatementOrExpressionRange(node), facts: rangeFacts, declarations: declarations } }; + return { targetRange: { range: getStatementOrExpressionRange(node), facts: rangeFacts, declarations: declarations } }; // TODO: GH#18217 + /** + * Attempt to refine the extraction node (generally, by shrinking it) to produce better results. + * @param node The unrefined extraction node. + */ function refineNode(node) { if (ts.isReturnStatement(node)) { if (node.expression) { @@ -89367,6 +106631,7 @@ var ts; if (numInitializers === 1) { return lastInitializer; } + // No special handling if there are multiple initializers. } else if (ts.isVariableDeclaration(node)) { if (node.initializer) { @@ -89384,27 +106649,28 @@ var ts; function checkForStaticContext(nodeToCheck, containingClass) { var current = nodeToCheck; while (current !== containingClass) { - if (current.kind === 152) { - if (ts.hasModifier(current, 32)) { + if (current.kind === 152 /* PropertyDeclaration */) { + if (ts.hasModifier(current, 32 /* Static */)) { rangeFacts |= RangeFacts.InStaticRegion; } break; } - else if (current.kind === 149) { + else if (current.kind === 149 /* Parameter */) { var ctorOrMethod = ts.getContainingFunction(current); - if (ctorOrMethod.kind === 155) { + if (ctorOrMethod.kind === 155 /* Constructor */) { rangeFacts |= RangeFacts.InStaticRegion; } break; } - else if (current.kind === 154) { - if (ts.hasModifier(current, 32)) { + else if (current.kind === 154 /* MethodDeclaration */) { + if (ts.hasModifier(current, 32 /* Static */)) { rangeFacts |= RangeFacts.InStaticRegion; } } current = current.parent; } } + // Verifies whether we can actually extract this node or not. function checkNode(nodeToCheck) { var PermittedJumps; (function (PermittedJumps) { @@ -89413,42 +106679,53 @@ var ts; PermittedJumps[PermittedJumps["Continue"] = 2] = "Continue"; PermittedJumps[PermittedJumps["Return"] = 4] = "Return"; })(PermittedJumps || (PermittedJumps = {})); + // We believe it's true because the node is from the (unmodified) tree. ts.Debug.assert(nodeToCheck.pos <= nodeToCheck.end, "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809"); + // For understanding how skipTrivia functioned: ts.Debug.assert(!ts.positionIsSynthesized(nodeToCheck.pos), "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809"); if (!ts.isStatement(nodeToCheck) && !(ts.isExpressionNode(nodeToCheck) && isExtractableExpression(nodeToCheck))) { return [ts.createDiagnosticForNode(nodeToCheck, Messages.statementOrExpressionExpected)]; } - if (nodeToCheck.flags & 4194304) { + if (nodeToCheck.flags & 4194304 /* Ambient */) { return [ts.createDiagnosticForNode(nodeToCheck, Messages.cannotExtractAmbientBlock)]; } + // If we're in a class, see whether we're in a static region (static property initializer, static method, class constructor parameter default) var containingClass = ts.getContainingClass(nodeToCheck); if (containingClass) { checkForStaticContext(nodeToCheck, containingClass); } var errors; - var permittedJumps = 4; + var permittedJumps = 4 /* Return */; var seenLabels; visit(nodeToCheck); return errors; function visit(node) { if (errors) { + // already found an error - can stop now return true; } if (ts.isDeclaration(node)) { - var declaringNode = (node.kind === 232) ? node.parent.parent : node; - if (ts.hasModifier(declaringNode, 1)) { + var declaringNode = (node.kind === 232 /* VariableDeclaration */) ? node.parent.parent : node; + if (ts.hasModifier(declaringNode, 1 /* Export */)) { + // TODO: GH#18217 Silly to use `errors ||` since it's definitely not defined (see top of `visit`) + // Also, if we're only pushing one error, just use `let error: Diagnostic | undefined`! + // Also TODO: GH#19956 (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractExportedEntity)); return true; } declarations.push(node.symbol); } + // Some things can't be extracted in certain situations switch (node.kind) { - case 244: + case 244 /* ImportDeclaration */: (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractImport)); return true; - case 97: - if (node.parent.kind === 187) { - var containingClass_1 = ts.getContainingClass(node); + case 97 /* SuperKeyword */: + // For a super *constructor call*, we have to be extracting the entire class, + // but a super *method call* simply implies a 'this' reference + if (node.parent.kind === 187 /* CallExpression */) { + // Super constructor call + var containingClass_1 = ts.getContainingClass(node); // TODO:GH#18217 if (containingClass_1.pos < span.start || containingClass_1.end >= (span.start + span.length)) { (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractSuper)); return true; @@ -89461,43 +106738,49 @@ var ts; } if (ts.isFunctionLikeDeclaration(node) || ts.isClassLike(node)) { switch (node.kind) { - case 234: - case 235: + case 234 /* FunctionDeclaration */: + case 235 /* ClassDeclaration */: if (ts.isSourceFile(node.parent) && node.parent.externalModuleIndicator === undefined) { + // You cannot extract global declarations (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.functionWillNotBeVisibleInTheNewScope)); } break; } + // do not dive into functions or classes return false; } var savedPermittedJumps = permittedJumps; switch (node.kind) { - case 217: - permittedJumps = 0; + case 217 /* IfStatement */: + permittedJumps = 0 /* None */; break; - case 230: - permittedJumps = 0; + case 230 /* TryStatement */: + // forbid all jumps inside try blocks + permittedJumps = 0 /* None */; break; - case 213: - if (node.parent && node.parent.kind === 230 && node.parent.finallyBlock === node) { - permittedJumps = 4; + case 213 /* Block */: + if (node.parent && node.parent.kind === 230 /* TryStatement */ && node.parent.finallyBlock === node) { + // allow unconditional returns from finally blocks + permittedJumps = 4 /* Return */; } break; - case 266: - permittedJumps |= 1; + case 266 /* CaseClause */: + // allow unlabeled break inside case clauses + permittedJumps |= 1 /* Break */; break; default: - if (ts.isIterationStatement(node, false)) { - permittedJumps |= 1 | 2; + if (ts.isIterationStatement(node, /*lookInLabeledStatements*/ false)) { + // allow unlabeled break/continue inside loops + permittedJumps |= 1 /* Break */ | 2 /* Continue */; } break; } switch (node.kind) { - case 174: - case 99: + case 174 /* ThisType */: + case 99 /* ThisKeyword */: rangeFacts |= RangeFacts.UsesThis; break; - case 228: + case 228 /* LabeledStatement */: { var label = node.label; (seenLabels || (seenLabels = [])).push(label.escapedText); @@ -89505,30 +106788,32 @@ var ts; seenLabels.pop(); break; } - case 224: - case 223: + case 224 /* BreakStatement */: + case 223 /* ContinueStatement */: { var label = node.label; if (label) { if (!ts.contains(seenLabels, label.escapedText)) { + // attempts to jump to label that is not in range to be extracted (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange)); } } else { - if (!(permittedJumps & (node.kind === 224 ? 1 : 2))) { + if (!(permittedJumps & (node.kind === 224 /* BreakStatement */ ? 1 /* Break */ : 2 /* Continue */))) { + // attempt to break or continue in a forbidden context (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements)); } } break; } - case 197: + case 197 /* AwaitExpression */: rangeFacts |= RangeFacts.IsAsyncFunction; break; - case 203: + case 203 /* YieldExpression */: rangeFacts |= RangeFacts.IsGenerator; break; - case 225: - if (permittedJumps & 4) { + case 225 /* ReturnStatement */: + if (permittedJumps & 4 /* Return */) { rangeFacts |= RangeFacts.HasReturn; } else { @@ -89549,6 +106834,10 @@ var ts; return [node]; } else if (ts.isExpressionNode(node)) { + // If our selection is the expression in an ExpressionStatement, expand + // the selection to include the enclosing Statement (this stops us + // from trying to care about the return value of the extracted function + // and eliminates double semicolon insertion in certain scenarios) return ts.isExpressionStatement(node.parent) ? [node.parent] : node; } return undefined; @@ -89556,9 +106845,15 @@ var ts; function isScope(node) { return ts.isFunctionLikeDeclaration(node) || ts.isSourceFile(node) || ts.isModuleBlock(node) || ts.isClassLike(node); } + /** + * Computes possible places we could extract the function into. For example, + * you may be able to extract into a class method *or* local closure *or* namespace function, + * depending on what's in the extracted body. + */ function collectEnclosingScopes(range) { var current = isReadonlyArray(range.range) ? ts.first(range.range) : range.range; if (range.facts & RangeFacts.UsesThis) { + // if range uses this as keyword or as type inside the class then it can only be extracted to a method of the containing class var containingClass = ts.getContainingClass(current); if (containingClass) { var containingFunction = ts.findAncestor(current, ts.isFunctionLikeDeclaration); @@ -89570,12 +106865,19 @@ var ts; var scopes = []; while (true) { current = current.parent; - if (current.kind === 149) { + // A function parameter's initializer is actually in the outer scope, not the function declaration + if (current.kind === 149 /* Parameter */) { + // Skip all the way to the outer scope of the function that declared this parameter current = ts.findAncestor(current, function (parent) { return ts.isFunctionLikeDeclaration(parent); }).parent; } + // We want to find the nearest parent where we can place an "equivalent" sibling to the node we're extracting out of. + // Walk up to the closest parent of a place where we can logically put a sibling: + // * Function declaration + // * Class declaration or expression + // * Module/namespace or source file if (isScope(current)) { scopes.push(current); - if (current.kind === 274) { + if (current.kind === 274 /* SourceFile */) { return scopes; } } @@ -89584,7 +106886,7 @@ var ts; function getFunctionExtractionAtIndex(targetRange, context, requestedChangesIndex) { var _a = getPossibleExtractionsWorker(targetRange, context), scopes = _a.scopes, _b = _a.readsAndWrites, target = _b.target, usagesPerScope = _b.usagesPerScope, functionErrorsPerScope = _b.functionErrorsPerScope, exposedVariableDeclarations = _b.exposedVariableDeclarations; ts.Debug.assert(!functionErrorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?"); - context.cancellationToken.throwIfCancellationRequested(); + context.cancellationToken.throwIfCancellationRequested(); // TODO: GH#18217 return extractFunctionInScope(target, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], exposedVariableDeclarations, targetRange, context); } function getConstantExtractionAtIndex(targetRange, context, requestedChangesIndex) { @@ -89597,8 +106899,14 @@ var ts; : target.statements[0].expression; return extractConstantInScope(expression, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], targetRange.facts, context); } + /** + * Given a piece of text to extract ('targetRange'), computes a list of possible extractions. + * Each returned ExtractResultForScope corresponds to a possible target scope and is either a set of changes + * or an error explaining why we can't extract into that scope. + */ function getPossibleExtractions(targetRange, context) { var _a = getPossibleExtractionsWorker(targetRange, context), scopes = _a.scopes, _b = _a.readsAndWrites, functionErrorsPerScope = _b.functionErrorsPerScope, constantErrorsPerScope = _b.constantErrorsPerScope; + // Need the inner type annotation to avoid https://github.com/Microsoft/TypeScript/issues/7547 var extractions = scopes.map(function (scope, i) { var functionDescriptionPart = getDescriptionForFunctionInScope(scope); var constantDescriptionPart = getDescriptionForConstantInScope(scope); @@ -89609,11 +106917,11 @@ var ts; : getDescriptionForModuleLikeDeclaration(scope); var functionDescription; var constantDescription; - if (scopeDescription === 1) { + if (scopeDescription === 1 /* Global */) { functionDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1_scope), [functionDescriptionPart, "global"]); constantDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1_scope), [constantDescriptionPart, "global"]); } - else if (scopeDescription === 0) { + else if (scopeDescription === 0 /* Module */) { functionDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1_scope), [functionDescriptionPart, "module"]); constantDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1_scope), [constantDescriptionPart, "module"]); } @@ -89621,6 +106929,7 @@ var ts; functionDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1), [functionDescriptionPart, scopeDescription]); constantDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1), [constantDescriptionPart, scopeDescription]); } + // Customize the phrasing for the innermost scope to increase clarity. if (i === 0 && !ts.isClassLike(scope)) { constantDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_enclosing_scope), [constantDescriptionPart]); } @@ -89658,43 +106967,48 @@ var ts; } function getDescriptionForFunctionLikeDeclaration(scope) { switch (scope.kind) { - case 155: + case 155 /* Constructor */: return "constructor"; - case 192: - case 234: + case 192 /* FunctionExpression */: + case 234 /* FunctionDeclaration */: return scope.name ? "function '" + scope.name.text + "'" : "anonymous function"; - case 193: + case 193 /* ArrowFunction */: return "arrow function"; - case 154: + case 154 /* MethodDeclaration */: return "method '" + scope.name.getText(); - case 156: + case 156 /* GetAccessor */: return "'get " + scope.name.getText() + "'"; - case 157: + case 157 /* SetAccessor */: return "'set " + scope.name.getText() + "'"; default: throw ts.Debug.assertNever(scope); } } function getDescriptionForClassLikeDeclaration(scope) { - return scope.kind === 235 + return scope.kind === 235 /* ClassDeclaration */ ? scope.name ? "class '" + scope.name.text + "'" : "anonymous class declaration" : scope.name ? "class expression '" + scope.name.text + "'" : "anonymous class expression"; } function getDescriptionForModuleLikeDeclaration(scope) { - return scope.kind === 240 + return scope.kind === 240 /* ModuleBlock */ ? "namespace '" + scope.parent.name.getText() + "'" - : scope.externalModuleIndicator ? 0 : 1; + : scope.externalModuleIndicator ? 0 /* Module */ : 1 /* Global */; } var SpecialScope; (function (SpecialScope) { SpecialScope[SpecialScope["Module"] = 0] = "Module"; SpecialScope[SpecialScope["Global"] = 1] = "Global"; })(SpecialScope || (SpecialScope = {})); + /** + * Result of 'extractRange' operation for a specific scope. + * Stores either a list of changes that should be applied to extract a range or a list of errors + */ function extractFunctionInScope(node, scope, _a, exposedVariableDeclarations, range, context) { var usagesInScope = _a.usages, typeParameterUsages = _a.typeParameterUsages, substitutions = _a.substitutions; var checker = context.program.getTypeChecker(); + // Make a unique name for the extracted function var file = scope.getSourceFile(); var functionNameText = ts.getUniqueName(ts.isClassLike(scope) ? "newMethod" : "newFunction", file); var isJS = ts.isInJavaScriptFile(scope); @@ -89707,12 +107021,18 @@ var ts; var typeNode; if (!isJS) { var type = checker.getTypeOfSymbolAtLocation(usage.symbol, usage.node); + // Widen the type so we don't emit nonsense annotations like "function fn(x: 3) {" type = checker.getBaseTypeOfLiteralType(type); - typeNode = checker.typeToTypeNode(type, scope, 1); + typeNode = checker.typeToTypeNode(type, scope, 1 /* NoTruncation */); } - var paramDecl = ts.createParameter(undefined, undefined, undefined, name, undefined, typeNode); + var paramDecl = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + /*name*/ name, + /*questionToken*/ undefined, typeNode); parameters.push(paramDecl); - if (usage.usage === 2) { + if (usage.usage === 2 /* Write */) { (writes || (writes = [])).push(usage); } callArguments.push(ts.createIdentifier(name)); @@ -89722,93 +107042,130 @@ var ts; var typeParameters = sortedTypeParametersAndDeclarations.length === 0 ? undefined : sortedTypeParametersAndDeclarations.map(function (t) { return t.declaration; }); + // Strictly speaking, we should check whether each name actually binds to the appropriate type + // parameter. In cases of shadowing, they may not. var callTypeArguments = typeParameters !== undefined - ? typeParameters.map(function (decl) { return ts.createTypeReferenceNode(decl.name, undefined); }) + ? typeParameters.map(function (decl) { return ts.createTypeReferenceNode(decl.name, /*typeArguments*/ undefined); }) : undefined; + // Provide explicit return types for contextually-typed functions + // to avoid problems when there are literal types present if (ts.isExpression(node) && !isJS) { var contextualType = checker.getContextualType(node); - returnType = checker.typeToTypeNode(contextualType, scope, 1); + returnType = checker.typeToTypeNode(contextualType, scope, 1 /* NoTruncation */); // TODO: GH#18217 } var _b = transformFunctionBody(node, exposedVariableDeclarations, writes, substitutions, !!(range.facts & RangeFacts.HasReturn)), body = _b.body, returnValueProperty = _b.returnValueProperty; ts.suppressLeadingAndTrailingTrivia(body); var newFunction; if (ts.isClassLike(scope)) { - var modifiers = isJS ? [] : [ts.createToken(112)]; + // always create private method in TypeScript files + var modifiers = isJS ? [] : [ts.createToken(112 /* PrivateKeyword */)]; if (range.facts & RangeFacts.InStaticRegion) { - modifiers.push(ts.createToken(115)); + modifiers.push(ts.createToken(115 /* StaticKeyword */)); } if (range.facts & RangeFacts.IsAsyncFunction) { - modifiers.push(ts.createToken(120)); + modifiers.push(ts.createToken(120 /* AsyncKeyword */)); } - newFunction = ts.createMethod(undefined, modifiers.length ? modifiers : undefined, range.facts & RangeFacts.IsGenerator ? ts.createToken(39) : undefined, functionName, undefined, typeParameters, parameters, returnType, body); + newFunction = ts.createMethod( + /*decorators*/ undefined, modifiers.length ? modifiers : undefined, range.facts & RangeFacts.IsGenerator ? ts.createToken(39 /* AsteriskToken */) : undefined, functionName, + /*questionToken*/ undefined, typeParameters, parameters, returnType, body); } else { - newFunction = ts.createFunctionDeclaration(undefined, range.facts & RangeFacts.IsAsyncFunction ? [ts.createToken(120)] : undefined, range.facts & RangeFacts.IsGenerator ? ts.createToken(39) : undefined, functionName, typeParameters, parameters, returnType, body); + newFunction = ts.createFunctionDeclaration( + /*decorators*/ undefined, range.facts & RangeFacts.IsAsyncFunction ? [ts.createToken(120 /* AsyncKeyword */)] : undefined, range.facts & RangeFacts.IsGenerator ? ts.createToken(39 /* AsteriskToken */) : undefined, functionName, typeParameters, parameters, returnType, body); } var changeTracker = ts.textChanges.ChangeTracker.fromContext(context); var minInsertionPos = (isReadonlyArray(range.range) ? ts.last(range.range) : range.range).end; var nodeToInsertBefore = getNodeToInsertFunctionBefore(minInsertionPos, scope); if (nodeToInsertBefore) { - changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newFunction, true); + changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newFunction, /*blankLineBetween*/ true); } else { changeTracker.insertNodeAtEndOfScope(context.file, scope, newFunction); } var newNodes = []; + // replace range with function call var called = getCalledExpression(scope, range, functionNameText); - var call = ts.createCall(called, callTypeArguments, callArguments); + var call = ts.createCall(called, callTypeArguments, // Note that no attempt is made to take advantage of type argument inference + callArguments); if (range.facts & RangeFacts.IsGenerator) { - call = ts.createYield(ts.createToken(39), call); + call = ts.createYield(ts.createToken(39 /* AsteriskToken */), call); } if (range.facts & RangeFacts.IsAsyncFunction) { call = ts.createAwait(call); } if (exposedVariableDeclarations.length && !writes) { + // No need to mix declarations and writes. + // How could any variables be exposed if there's a return statement? ts.Debug.assert(!returnValueProperty); ts.Debug.assert(!(range.facts & RangeFacts.HasReturn)); if (exposedVariableDeclarations.length === 1) { + // Declaring exactly one variable: let x = newFunction(); var variableDeclaration = exposedVariableDeclarations[0]; - newNodes.push(ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.getSynthesizedDeepClone(variableDeclaration.name), ts.getSynthesizedDeepClone(variableDeclaration.type), call)], variableDeclaration.parent.flags))); + newNodes.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.getSynthesizedDeepClone(variableDeclaration.name), /*type*/ ts.getSynthesizedDeepClone(variableDeclaration.type), /*initializer*/ call)], // TODO (acasey): test binding patterns + variableDeclaration.parent.flags))); } else { + // Declaring multiple variables / return properties: + // let {x, y} = newFunction(); var bindingElements = []; var typeElements = []; var commonNodeFlags = exposedVariableDeclarations[0].parent.flags; var sawExplicitType = false; for (var _i = 0, exposedVariableDeclarations_1 = exposedVariableDeclarations; _i < exposedVariableDeclarations_1.length; _i++) { var variableDeclaration = exposedVariableDeclarations_1[_i]; - bindingElements.push(ts.createBindingElement(undefined, undefined, ts.getSynthesizedDeepClone(variableDeclaration.name))); - var variableType = checker.typeToTypeNode(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(variableDeclaration)), scope, 1); - typeElements.push(ts.createPropertySignature(undefined, variableDeclaration.symbol.name, undefined, variableType, undefined)); + bindingElements.push(ts.createBindingElement( + /*dotDotDotToken*/ undefined, + /*propertyName*/ undefined, + /*name*/ ts.getSynthesizedDeepClone(variableDeclaration.name))); + // Being returned through an object literal will have widened the type. + var variableType = checker.typeToTypeNode(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(variableDeclaration)), // TODO: GH#18217 + scope, 1 /* NoTruncation */); + typeElements.push(ts.createPropertySignature( + /*modifiers*/ undefined, + /*name*/ variableDeclaration.symbol.name, + /*questionToken*/ undefined, + /*type*/ variableType, + /*initializer*/ undefined)); sawExplicitType = sawExplicitType || variableDeclaration.type !== undefined; commonNodeFlags = commonNodeFlags & variableDeclaration.parent.flags; } var typeLiteral = sawExplicitType ? ts.createTypeLiteralNode(typeElements) : undefined; if (typeLiteral) { - ts.setEmitFlags(typeLiteral, 1); + ts.setEmitFlags(typeLiteral, 1 /* SingleLine */); } - newNodes.push(ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createObjectBindingPattern(bindingElements), typeLiteral, call)], commonNodeFlags))); + newNodes.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createObjectBindingPattern(bindingElements), + /*type*/ typeLiteral, + /*initializer*/ call)], commonNodeFlags))); } } else if (exposedVariableDeclarations.length || writes) { if (exposedVariableDeclarations.length) { + // CONSIDER: we're going to create one statement per variable, but we could actually preserve their original grouping. for (var _c = 0, exposedVariableDeclarations_2 = exposedVariableDeclarations; _c < exposedVariableDeclarations_2.length; _c++) { var variableDeclaration = exposedVariableDeclarations_2[_c]; var flags = variableDeclaration.parent.flags; - if (flags & 2) { - flags = (flags & ~2) | 1; + if (flags & 2 /* Const */) { + flags = (flags & ~2 /* Const */) | 1 /* Let */; } - newNodes.push(ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(variableDeclaration.symbol.name, getTypeDeepCloneUnionUndefined(variableDeclaration.type))], flags))); + newNodes.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(variableDeclaration.symbol.name, getTypeDeepCloneUnionUndefined(variableDeclaration.type))], flags))); } } if (returnValueProperty) { - newNodes.push(ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(returnValueProperty, getTypeDeepCloneUnionUndefined(returnType))], 1))); + // has both writes and return, need to create variable declaration to hold return value; + newNodes.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(returnValueProperty, getTypeDeepCloneUnionUndefined(returnType))], 1 /* Let */))); } var assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes); if (returnValueProperty) { assignments.unshift(ts.createShorthandPropertyAssignment(returnValueProperty)); } + // propagate writes back if (assignments.length === 1) { + // We would only have introduced a return value property if there had been + // other assignments to make. ts.Debug.assert(!returnValueProperty); newNodes.push(ts.createStatement(ts.createAssignment(assignments[0].name, call))); if (range.facts & RangeFacts.HasReturn) { @@ -89816,6 +107173,9 @@ var ts; } } else { + // emit e.g. + // { a, b, __return } = newFunction(a, b); + // return __return; newNodes.push(ts.createStatement(ts.createAssignment(ts.createObjectLiteral(assignments), call))); if (returnValueProperty) { newNodes.push(ts.createReturn(ts.createIdentifier(returnValueProperty))); @@ -89842,7 +107202,7 @@ var ts; var edits = changeTracker.getChanges(); var renameRange = isReadonlyArray(range.range) ? ts.first(range.range) : range.range; var renameFilename = renameRange.getSourceFile().fileName; - var renameLocation = ts.getRenameLocation(edits, renameFilename, functionNameText, false); + var renameLocation = ts.getRenameLocation(edits, renameFilename, functionNameText, /*isDeclaredBeforeUse*/ false); return { renameFilename: renameFilename, renameLocation: renameLocation, edits: edits }; function getTypeDeepCloneUnionUndefined(typeNode) { if (typeNode === undefined) { @@ -89853,62 +107213,85 @@ var ts; while (ts.isParenthesizedTypeNode(withoutParens)) { withoutParens = withoutParens.type; } - return ts.isUnionTypeNode(withoutParens) && ts.find(withoutParens.types, function (t) { return t.kind === 140; }) + return ts.isUnionTypeNode(withoutParens) && ts.find(withoutParens.types, function (t) { return t.kind === 140 /* UndefinedKeyword */; }) ? clone - : ts.createUnionTypeNode([clone, ts.createKeywordTypeNode(140)]); + : ts.createUnionTypeNode([clone, ts.createKeywordTypeNode(140 /* UndefinedKeyword */)]); } } + /** + * Result of 'extractRange' operation for a specific scope. + * Stores either a list of changes that should be applied to extract a range or a list of errors + */ function extractConstantInScope(node, scope, _a, rangeFacts, context) { var substitutions = _a.substitutions; var checker = context.program.getTypeChecker(); + // Make a unique name for the extracted variable var file = scope.getSourceFile(); var localNameText = ts.getUniqueName(ts.isClassLike(scope) ? "newProperty" : "newLocal", file); var isJS = ts.isInJavaScriptFile(scope); var variableType = isJS || !checker.isContextSensitive(node) ? undefined - : checker.typeToTypeNode(checker.getContextualType(node), scope, 1); + : checker.typeToTypeNode(checker.getContextualType(node), scope, 1 /* NoTruncation */); // TODO: GH#18217 var initializer = transformConstantInitializer(node, substitutions); ts.suppressLeadingAndTrailingTrivia(initializer); var changeTracker = ts.textChanges.ChangeTracker.fromContext(context); if (ts.isClassLike(scope)) { - ts.Debug.assert(!isJS); + ts.Debug.assert(!isJS); // See CannotExtractToJSClass var modifiers = []; - modifiers.push(ts.createToken(112)); + modifiers.push(ts.createToken(112 /* PrivateKeyword */)); if (rangeFacts & RangeFacts.InStaticRegion) { - modifiers.push(ts.createToken(115)); + modifiers.push(ts.createToken(115 /* StaticKeyword */)); } - modifiers.push(ts.createToken(132)); - var newVariable = ts.createProperty(undefined, modifiers, localNameText, undefined, variableType, initializer); + modifiers.push(ts.createToken(132 /* ReadonlyKeyword */)); + var newVariable = ts.createProperty( + /*decorators*/ undefined, modifiers, localNameText, + /*questionToken*/ undefined, variableType, initializer); var localReference = ts.createPropertyAccess(rangeFacts & RangeFacts.InStaticRegion - ? ts.createIdentifier(scope.name.getText()) + ? ts.createIdentifier(scope.name.getText()) // TODO: GH#18217 : ts.createThis(), ts.createIdentifier(localNameText)); + // Declare var maxInsertionPos = node.pos; var nodeToInsertBefore = getNodeToInsertPropertyBefore(maxInsertionPos, scope); - changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newVariable, true); + changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newVariable, /*blankLineBetween*/ true); + // Consume changeTracker.replaceNode(context.file, node, localReference); } else { var newVariableDeclaration = ts.createVariableDeclaration(localNameText, variableType, initializer); + // If the node is part of an initializer in a list of variable declarations, insert a new + // variable declaration into the list (in case it depends on earlier ones). + // CONSIDER: If the declaration list isn't const, we might want to split it into multiple + // lists so that the newly extracted one can be const. var oldVariableDeclaration = getContainingVariableDeclarationIfInList(node, scope); if (oldVariableDeclaration) { + // Declare + // CONSIDER: could detect that each is on a separate line (See `extractConstant_VariableList_MultipleLines` in `extractConstants.ts`) changeTracker.insertNodeBefore(context.file, oldVariableDeclaration, newVariableDeclaration); + // Consume var localReference = ts.createIdentifier(localNameText); changeTracker.replaceNode(context.file, node, localReference); } - else if (node.parent.kind === 216 && scope === ts.findAncestor(node, isScope)) { - var newVariableStatement = ts.createVariableStatement(undefined, ts.createVariableDeclarationList([newVariableDeclaration], 2)); + else if (node.parent.kind === 216 /* ExpressionStatement */ && scope === ts.findAncestor(node, isScope)) { + // If the parent is an expression statement and the target scope is the immediately enclosing one, + // replace the statement with the declaration. + var newVariableStatement = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([newVariableDeclaration], 2 /* Const */)); changeTracker.replaceNode(context.file, node.parent, newVariableStatement); } else { - var newVariableStatement = ts.createVariableStatement(undefined, ts.createVariableDeclarationList([newVariableDeclaration], 2)); + var newVariableStatement = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([newVariableDeclaration], 2 /* Const */)); + // Declare var nodeToInsertBefore = getNodeToInsertConstantBefore(node, scope); if (nodeToInsertBefore.pos === 0) { - changeTracker.insertNodeAtTopOfFile(context.file, newVariableStatement, false); + changeTracker.insertNodeAtTopOfFile(context.file, newVariableStatement, /*blankLineBetween*/ false); } else { - changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newVariableStatement, false); + changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newVariableStatement, /*blankLineBetween*/ false); } - if (node.parent.kind === 216) { + // Consume + if (node.parent.kind === 216 /* ExpressionStatement */) { + // If the parent is an expression statement, delete it. changeTracker.deleteNode(context.file, node.parent, ts.textChanges.useNonAdjustedPositions); } else { @@ -89919,7 +107302,7 @@ var ts; } var edits = changeTracker.getChanges(); var renameFilename = node.getSourceFile().fileName; - var renameLocation = ts.getRenameLocation(edits, renameFilename, localNameText, true); + var renameLocation = ts.getRenameLocation(edits, renameFilename, localNameText, /*isDeclaredBeforeUse*/ true); return { renameFilename: renameFilename, renameLocation: renameLocation, edits: edits }; } function getContainingVariableDeclarationIfInList(node, scope) { @@ -89958,7 +107341,7 @@ var ts; function getCalledExpression(scope, range, functionNameText) { var functionReference = ts.createIdentifier(functionNameText); if (ts.isClassLike(scope)) { - var lhs = range.facts & RangeFacts.InStaticRegion ? ts.createIdentifier(scope.name.text) : ts.createThis(); + var lhs = range.facts & RangeFacts.InStaticRegion ? ts.createIdentifier(scope.name.text) : ts.createThis(); // TODO: GH#18217 return ts.createPropertyAccess(lhs, functionReference); } else { @@ -89968,14 +107351,18 @@ var ts; function transformFunctionBody(body, exposedVariableDeclarations, writes, substitutions, hasReturn) { var hasWritesOrVariableDeclarations = writes !== undefined || exposedVariableDeclarations.length > 0; if (ts.isBlock(body) && !hasWritesOrVariableDeclarations && substitutions.size === 0) { - return { body: ts.createBlock(body.statements, true), returnValueProperty: undefined }; + // already block, no declarations or writes to propagate back, no substitutions - can use node as is + return { body: ts.createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined }; } var returnValueProperty; var ignoreReturns = false; var statements = ts.createNodeArray(ts.isBlock(body) ? body.statements.slice(0) : [ts.isStatement(body) ? body : ts.createReturn(body)]); + // rewrite body if either there are writes that should be propagated back via return statements or there are substitutions if (hasWritesOrVariableDeclarations || substitutions.size) { var rewrittenStatements = ts.visitNodes(statements, visitor).slice(); if (hasWritesOrVariableDeclarations && !hasReturn && ts.isStatement(body)) { + // add return at the end to propagate writes back in case if control flow falls out of the function body + // it is ok to know that range has at least one return since it we only allow unconditional returns var assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes); if (assignments.length === 1) { rewrittenStatements.push(ts.createReturn(assignments[0].name)); @@ -89984,13 +107371,13 @@ var ts; rewrittenStatements.push(ts.createReturn(ts.createObjectLiteral(assignments))); } } - return { body: ts.createBlock(rewrittenStatements, true), returnValueProperty: returnValueProperty }; + return { body: ts.createBlock(rewrittenStatements, /*multiLine*/ true), returnValueProperty: returnValueProperty }; } else { - return { body: ts.createBlock(statements, true), returnValueProperty: undefined }; + return { body: ts.createBlock(statements, /*multiLine*/ true), returnValueProperty: undefined }; } function visitor(node) { - if (!ignoreReturns && node.kind === 225 && hasWritesOrVariableDeclarations) { + if (!ignoreReturns && node.kind === 225 /* ReturnStatement */ && hasWritesOrVariableDeclarations) { var assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes); if (node.expression) { if (!returnValueProperty) { @@ -90026,7 +107413,7 @@ var ts; } function getStatementsOrClassElements(scope) { if (ts.isFunctionLikeDeclaration(scope)) { - var body = scope.body; + var body = scope.body; // TODO: GH#18217 if (ts.isBlock(body)) { return body.statements; } @@ -90042,6 +107429,10 @@ var ts; } return ts.emptyArray; } + /** + * If `scope` contains a function after `minPos`, then return the first such function. + * Otherwise, return `undefined`. + */ function getNodeToInsertFunctionBefore(minPos, scope) { return ts.find(getStatementsOrClassElements(scope), function (child) { return child.pos >= minPos && ts.isFunctionLikeDeclaration(child) && !ts.isConstructorDeclaration(child); @@ -90049,7 +107440,7 @@ var ts; } function getNodeToInsertPropertyBefore(maxPos, scope) { var members = scope.members; - ts.Debug.assert(members.length > 0); + ts.Debug.assert(members.length > 0); // There must be at least one child, since we extracted from one. var prevMember; var allProperties = true; for (var _i = 0, members_7 = members; _i < members_7.length; _i++) { @@ -90058,6 +107449,8 @@ var ts; return prevMember || members[0]; } if (allProperties && !ts.isPropertyDeclaration(member)) { + // If it is non-vacuously true that all preceding members are properties, + // insert before the current member (i.e. at the end of the list of properties). if (prevMember !== undefined) { return member; } @@ -90066,7 +107459,7 @@ var ts; prevMember = member; } if (prevMember === undefined) - return ts.Debug.fail(); + return ts.Debug.fail(); // If the loop didn't return, then it did set prevMember. return prevMember; } function getNodeToInsertConstantBefore(node, scope) { @@ -90088,9 +107481,11 @@ var ts; prevStatement = statement; } if (!prevStatement && ts.isCaseClause(curr)) { + // We must have been in the expression of the case clause. ts.Debug.assert(ts.isSwitchStatement(curr.parent.parent)); return curr.parent.parent; } + // There must be at least one statement since we started in one. return ts.Debug.assertDefined(prevStatement); } ts.Debug.assert(curr !== scope, "Didn't encounter a block-like before encountering scope"); @@ -90099,6 +107494,7 @@ var ts; function getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes) { var variableAssignments = ts.map(exposedVariableDeclarations, function (v) { return ts.createShorthandPropertyAssignment(v.symbol.name); }); var writeAssignments = ts.map(writes, function (w) { return ts.createShorthandPropertyAssignment(w.symbol.name); }); + // TODO: GH#18217 `variableAssignments` not possibly undefined! return variableAssignments === undefined ? writeAssignments : writeAssignments === undefined @@ -90108,6 +107504,15 @@ var ts; function isReadonlyArray(v) { return ts.isArray(v); } + /** + * Produces a range that spans the entirety of nodes, given a selection + * that might start/end in the middle of nodes. + * + * For example, when the user makes a selection like this + * v---v + * var someThing = foo + bar; + * this returns ^-------^ + */ function getEnclosingTextRange(targetRange, sourceFile) { return isReadonlyArray(targetRange.range) ? { pos: ts.first(targetRange.range).getStart(sourceFile), end: ts.last(targetRange.range).getEnd() } @@ -90115,17 +107520,19 @@ var ts; } var Usage; (function (Usage) { + // value should be passed to extracted method Usage[Usage["Read"] = 1] = "Read"; + // value should be passed to extracted method and propagated back Usage[Usage["Write"] = 2] = "Write"; })(Usage || (Usage = {})); function collectReadsAndWrites(targetRange, scopes, enclosingTextRange, sourceFile, checker, cancellationToken) { - var allTypeParameterUsages = ts.createMap(); + var allTypeParameterUsages = ts.createMap(); // Key is type ID var usagesPerScope = []; var substitutionsPerScope = []; var functionErrorsPerScope = []; var constantErrorsPerScope = []; var visibleDeclarationsInExtractedRange = []; - var exposedVariableSymbolSet = ts.createMap(); + var exposedVariableSymbolSet = ts.createMap(); // Key is symbol ID var exposedVariableDeclarations = []; var firstExposedNonVariableDeclaration; var expression = !isReadonlyArray(targetRange.range) @@ -90140,14 +107547,15 @@ var ts; var end = ts.last(statements).end; expressionDiagnostic = ts.createFileDiagnostic(sourceFile, start, end - start, Messages.expressionExpected); } - else if (checker.getTypeAtLocation(expression).flags & (4096 | 32768)) { + else if (checker.getTypeAtLocation(expression).flags & (4096 /* Void */ | 32768 /* Never */)) { // TODO: GH#18217 expressionDiagnostic = ts.createDiagnosticForNode(expression, Messages.uselessConstantType); } + // initialize results for (var _i = 0, scopes_1 = scopes; _i < scopes_1.length; _i++) { var scope = scopes_1[_i]; usagesPerScope.push({ usages: ts.createMap(), typeParameterUsages: ts.createMap(), substitutions: ts.createMap() }); substitutionsPerScope.push(ts.createMap()); - functionErrorsPerScope.push(ts.isFunctionLikeDeclaration(scope) && scope.kind !== 234 + functionErrorsPerScope.push(ts.isFunctionLikeDeclaration(scope) && scope.kind !== 234 /* FunctionDeclaration */ ? [ts.createDiagnosticForNode(scope, Messages.cannotExtractToOtherFunctionLike)] : []); var constantErrors = []; @@ -90158,6 +107566,7 @@ var ts; constantErrors.push(ts.createDiagnosticForNode(scope, Messages.cannotExtractToJSClass)); } if (ts.isArrowFunction(scope) && !ts.isBlock(scope.body)) { + // TODO (https://github.com/Microsoft/TypeScript/issues/18924): allow this constantErrors.push(ts.createDiagnosticForNode(scope, Messages.cannotExtractToExpressionArrowFunction)); } constantErrorsPerScope.push(constantErrors); @@ -90167,20 +107576,25 @@ var ts; var unmodifiedNode = isReadonlyArray(targetRange.range) ? ts.first(targetRange.range) : targetRange.range; var inGenericContext = isInGenericContext(unmodifiedNode); collectUsages(target); + // Unfortunately, this code takes advantage of the knowledge that the generated method + // will use the contextual type of an expression as the return type of the extracted + // method (and will therefore "use" all the types involved). if (inGenericContext && !isReadonlyArray(targetRange.range)) { - var contextualType = checker.getContextualType(targetRange.range); + var contextualType = checker.getContextualType(targetRange.range); // TODO: GH#18217 recordTypeParameterUsages(contextualType); } if (allTypeParameterUsages.size > 0) { - var seenTypeParameterUsages = ts.createMap(); + var seenTypeParameterUsages = ts.createMap(); // Key is type ID var i_1 = 0; for (var curr = unmodifiedNode; curr !== undefined && i_1 < scopes.length; curr = curr.parent) { if (curr === scopes[i_1]) { + // Copy current contents of seenTypeParameterUsages into scope. seenTypeParameterUsages.forEach(function (typeParameter, id) { usagesPerScope[i_1].typeParameterUsages.set(id, typeParameter); }); i_1++; } + // Note that we add the current node's type parameters *after* updating the corresponding scope. if (ts.isDeclarationWithTypeParameters(curr)) { for (var _a = 0, _b = ts.getEffectiveTypeParameterDeclarations(curr); _a < _b.length; _a++) { var typeParameterDecl = _b[_a]; @@ -90191,8 +107605,13 @@ var ts; } } } + // If we didn't get through all the scopes, then there were some that weren't in our + // parent chain (impossible at time of writing). A conservative solution would be to + // copy allTypeParameterUsages into all remaining scopes. ts.Debug.assert(i_1 === scopes.length); } + // If there are any declarations in the extracted block that are used in the same enclosing + // lexical scope, we can't move the extraction "up" as those declarations will become unreachable if (visibleDeclarationsInExtractedRange.length) { var containingLexicalScopeOfExtraction = ts.isBlockScope(scopes[0], scopes[0].parent) ? scopes[0] @@ -90201,6 +107620,9 @@ var ts; } var _loop_24 = function (i) { var scopeUsages = usagesPerScope[i]; + // Special case: in the innermost scope, all usages are available. + // (The computed value reflects the value at the top-level of the scope, but the + // local will actually be declared at the same level as the extracted expression). if (i > 0 && (scopeUsages.usages.size > 0 || scopeUsages.typeParameterUsages.size > 0)) { var errorNode = isReadonlyArray(targetRange.range) ? targetRange.range[0] : targetRange.range; constantErrorsPerScope[i].push(ts.createDiagnosticForNode(errorNode, Messages.cannotAccessVariablesFromNestedScopes)); @@ -90208,15 +107630,16 @@ var ts; var hasWrite = false; var readonlyClassPropertyWrite; usagesPerScope[i].usages.forEach(function (value) { - if (value.usage === 2) { + if (value.usage === 2 /* Write */) { hasWrite = true; - if (value.symbol.flags & 106500 && + if (value.symbol.flags & 106500 /* ClassMember */ && value.symbol.valueDeclaration && - ts.hasModifier(value.symbol.valueDeclaration, 64)) { + ts.hasModifier(value.symbol.valueDeclaration, 64 /* Readonly */)) { readonlyClassPropertyWrite = value.symbol.valueDeclaration; } } }); + // If an expression was extracted, then there shouldn't have been any variable declarations. ts.Debug.assert(isReadonlyArray(targetRange.range) || exposedVariableDeclarations.length === 0); if (hasWrite && !isReadonlyArray(targetRange.range)) { var diag = ts.createDiagnosticForNode(targetRange.range, Messages.cannotWriteInExpression); @@ -90242,6 +107665,9 @@ var ts; return !!ts.findAncestor(node, function (n) { return ts.isDeclarationWithTypeParameters(n) && ts.getEffectiveTypeParameterDeclarations(n).length !== 0; }); } function recordTypeParameterUsages(type) { + // PERF: This is potentially very expensive. `type` could be a library type with + // a lot of properties, each of which the walker will visit. Unfortunately, the + // solution isn't as trivial as filtering to user types because of (e.g.) Array. var symbolWalker = checker.getSymbolWalker(function () { return (cancellationToken.throwIfCancellationRequested(), true); }); var visitedTypes = symbolWalker.walkType(type).visitedTypes; for (var _i = 0, visitedTypes_1 = visitedTypes; _i < visitedTypes_1.length; _i++) { @@ -90252,22 +107678,24 @@ var ts; } } function collectUsages(node, valueUsage) { - if (valueUsage === void 0) { valueUsage = 1; } + if (valueUsage === void 0) { valueUsage = 1 /* Read */; } if (inGenericContext) { - var type = checker.getTypeAtLocation(node); + var type = checker.getTypeAtLocation(node); // TODO: GH#18217 recordTypeParameterUsages(type); } if (ts.isDeclaration(node) && node.symbol) { visibleDeclarationsInExtractedRange.push(node); } if (ts.isAssignmentExpression(node)) { - collectUsages(node.left, 2); + // use 'write' as default usage for values + collectUsages(node.left, 2 /* Write */); collectUsages(node.right); } else if (ts.isUnaryExpressionWithWrite(node)) { - collectUsages(node.operand, 2); + collectUsages(node.operand, 2 /* Write */); } else if (ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node)) { + // use 'write' as default usage for values ts.forEachChild(node, collectUsages); } else if (ts.isIdentifier(node)) { @@ -90280,7 +107708,7 @@ var ts; if (ts.isPropertyAccessExpression(node.parent) && node !== node.parent.expression) { return; } - recordUsage(node, valueUsage, ts.isPartOfTypeNode(node)); + recordUsage(node, valueUsage, /*isTypeNode*/ ts.isPartOfTypeNode(node)); } else { ts.forEachChild(node, collectUsages); @@ -90290,6 +107718,7 @@ var ts; var symbolId = recordUsagebySymbol(n, usage, isTypeNode); if (symbolId) { for (var i = 0; i < scopes.length; i++) { + // push substitution from map to map to simplify rewriting var substitution = substitutionsPerScope[i].get(symbolId); if (substitution) { usagesPerScope[i].substitutions.set(ts.getNodeId(n).toString(), substitution); @@ -90300,15 +107729,24 @@ var ts; function recordUsagebySymbol(identifier, usage, isTypeName) { var symbol = getSymbolReferencedByIdentifier(identifier); if (!symbol) { + // cannot find symbol - do nothing return undefined; } var symbolId = ts.getSymbolId(symbol).toString(); var lastUsage = seenUsages.get(symbolId); + // there are two kinds of value usages + // - reads - if range contains a read from the value located outside of the range then value should be passed as a parameter + // - writes - if range contains a write to a value located outside the range the value should be passed as a parameter and + // returned as a return value + // 'write' case is a superset of 'read' so if we already have processed 'write' of some symbol there is not need to handle 'read' + // since all information is already recorded if (lastUsage && lastUsage >= usage) { return symbolId; } seenUsages.set(symbolId, usage); if (lastUsage) { + // if we get here this means that we are trying to handle 'write' and 'read' was already processed + // walk scopes and update existing records. for (var _i = 0, usagesPerScope_1 = usagesPerScope; _i < usagesPerScope_1.length; _i++) { var perScope = usagesPerScope_1[_i]; var prevEntry = perScope.usages.get(identifier.text); @@ -90318,15 +107756,19 @@ var ts; } return symbolId; } + // find first declaration in this file var decls = symbol.getDeclarations(); var declInFile = decls && ts.find(decls, function (d) { return d.getSourceFile() === sourceFile; }); if (!declInFile) { return undefined; } if (ts.rangeContainsStartEnd(enclosingTextRange, declInFile.getStart(), declInFile.end)) { + // declaration is located in range to be extracted - do nothing return undefined; } - if (targetRange.facts & RangeFacts.IsGenerator && usage === 2) { + if (targetRange.facts & RangeFacts.IsGenerator && usage === 2 /* Write */) { + // this is write to a reference located outside of the target scope and range is extracted into generator + // currently this is unsupported scenario var diag = ts.createDiagnosticForNode(identifier, Messages.cannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators); for (var _a = 0, functionErrorsPerScope_1 = functionErrorsPerScope; _a < functionErrorsPerScope_1.length; _a++) { var errors = functionErrorsPerScope_1[_a]; @@ -90339,7 +107781,7 @@ var ts; } for (var i = 0; i < scopes.length; i++) { var scope = scopes[i]; - var resolvedSymbol = checker.resolveName(symbol.name, scope, symbol.flags, false); + var resolvedSymbol = checker.resolveName(symbol.name, scope, symbol.flags, /*excludeGlobals*/ false); if (resolvedSymbol === symbol) { continue; } @@ -90349,7 +107791,9 @@ var ts; substitutionsPerScope[i].set(symbolId, substitution); } else if (isTypeName) { - if (!(symbol.flags & 262144)) { + // If the symbol is a type parameter that won't be in scope, we'll pass it as a type argument + // so there's no problem. + if (!(symbol.flags & 262144 /* TypeParameter */)) { var diag = ts.createDiagnosticForNode(identifier, Messages.typeWillNotBeVisibleInTheNewScope); functionErrorsPerScope[i].push(diag); constantErrorsPerScope[i].push(diag); @@ -90363,9 +107807,11 @@ var ts; return symbolId; } function checkForUsedDeclarations(node) { + // If this node is entirely within the original extraction range, we don't need to do anything. if (node === targetRange.range || (isReadonlyArray(targetRange.range) && targetRange.range.indexOf(node) >= 0)) { return; } + // Otherwise check and recurse. var sym = ts.isIdentifier(node) ? getSymbolReferencedByIdentifier(node) : checker.getSymbolAtLocation(node); @@ -90380,13 +107826,20 @@ var ts; } } else { + // CONSIDER: this includes binding elements, which we could + // expose in the same way as variables. firstExposedNonVariableDeclaration = firstExposedNonVariableDeclaration || decl; } } } ts.forEachChild(node, checkForUsedDeclarations); } + /** + * Return the symbol referenced by an identifier (even if it declares a different symbol). + */ function getSymbolReferencedByIdentifier(identifier) { + // If the identifier is both a property name and its value, we're only interested in its value + // (since the name is a declaration and will be included in the extracted range). return identifier.parent && ts.isShorthandPropertyAssignment(identifier.parent) && identifier.parent.name === identifier ? checker.getShorthandAssignmentValueSymbol(identifier.parent) : checker.getSymbolAtLocation(identifier); @@ -90408,33 +107861,40 @@ var ts; : ts.createPropertyAccess(prefix, symbol.name); } } + /** + * Computes whether or not a node represents an expression in a position where it could + * be extracted. + * The isExpression() in utilities.ts returns some false positives we need to handle, + * such as `import x from 'y'` -- the 'y' is a StringLiteral but is *not* an expression + * in the sense of something that you could extract on + */ function isExtractableExpression(node) { var parent = node.parent; switch (parent.kind) { - case 273: + case 273 /* EnumMember */: return false; } switch (node.kind) { - case 9: - return parent.kind !== 244 && - parent.kind !== 248; - case 204: - case 180: - case 182: + case 9 /* StringLiteral */: + return parent.kind !== 244 /* ImportDeclaration */ && + parent.kind !== 248 /* ImportSpecifier */; + case 204 /* SpreadElement */: + case 180 /* ObjectBindingPattern */: + case 182 /* BindingElement */: return false; - case 71: - return parent.kind !== 182 && - parent.kind !== 248 && - parent.kind !== 252; + case 71 /* Identifier */: + return parent.kind !== 182 /* BindingElement */ && + parent.kind !== 248 /* ImportSpecifier */ && + parent.kind !== 252 /* ExportSpecifier */; } return true; } function isBlockLike(node) { switch (node.kind) { - case 213: - case 274: - case 240: - case 266: + case 213 /* Block */: + case 274 /* SourceFile */: + case 240 /* ModuleBlock */: + case 266 /* CaseClause */: return true; default: return false; @@ -90443,6 +107903,7 @@ var ts; })(extractSymbol = refactor.extractSymbol || (refactor.extractSymbol = {})); })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var refactor; @@ -90479,18 +107940,20 @@ var ts; ts.suppressLeadingAndTrailingTrivia(declaration); ts.suppressLeadingAndTrailingTrivia(container); var isInClassLike = ts.isClassLike(container); - var modifierFlags = ts.getModifierFlags(declaration) & ~64; + // avoid Readonly modifier because it will convert to get accessor + var modifierFlags = ts.getModifierFlags(declaration) & ~64 /* Readonly */; var accessorModifiers = isInClassLike - ? !modifierFlags || modifierFlags & 8 - ? getModifiers(isJS, isStatic, 114) + ? !modifierFlags || modifierFlags & 8 /* Private */ + ? getModifiers(isJS, isStatic, 114 /* PublicKeyword */) : ts.createNodeArray(ts.createModifiersFromModifierFlags(modifierFlags)) : undefined; - var fieldModifiers = isInClassLike ? getModifiers(isJS, isStatic, 112) : undefined; + var fieldModifiers = isInClassLike ? getModifiers(isJS, isStatic, 112 /* PrivateKeyword */) : undefined; updateFieldDeclaration(changeTracker, file, declaration, fieldName, fieldModifiers); var getAccessor = generateGetAccessor(fieldName, accessorName, type, accessorModifiers, isStatic, container); ts.suppressLeadingAndTrailingTrivia(getAccessor); insertAccessor(changeTracker, file, getAccessor, declaration, container); if (isReadonly) { + // readonly modifier only existed in classLikeDeclaration var constructor = ts.getFirstConstructorWithBody(container); if (constructor) { updateReadonlyPropertyInitializerStatementConstructor(changeTracker, context, constructor, fieldName, originalName); @@ -90505,7 +107968,7 @@ var ts; var renameFilename = file.fileName; var nameNeedRename = renameAccessor ? accessorName : fieldName; var renameLocationOffset = ts.isIdentifier(nameNeedRename) ? 0 : -1; - var renameLocation = renameLocationOffset + ts.getRenameLocation(edits, renameFilename, nameNeedRename.text, ts.isParameter(declaration)); + var renameLocation = renameLocationOffset + ts.getRenameLocation(edits, renameFilename, nameNeedRename.text, /*preferLastLocation*/ ts.isParameter(declaration)); return { renameFilename: renameFilename, renameLocation: renameLocation, edits: edits }; } function isConvertibleName(name) { @@ -90518,22 +107981,23 @@ var ts; return ts.isIdentifier(originalName) ? ts.createIdentifier(name) : ts.createLiteral(name); } function createAccessorAccessExpression(fieldName, isStatic, container) { - var leftHead = isStatic ? container.name : ts.createThis(); + var leftHead = isStatic ? container.name : ts.createThis(); // TODO: GH#18217 return ts.isIdentifier(fieldName) ? ts.createPropertyAccess(leftHead, fieldName) : ts.createElementAccess(leftHead, ts.createLiteral(fieldName)); } function getModifiers(isJS, isStatic, accessModifier) { - var modifiers = ts.append(!isJS ? [ts.createToken(accessModifier)] : undefined, isStatic ? ts.createToken(115) : undefined); + var modifiers = ts.append(!isJS ? [ts.createToken(accessModifier)] : undefined, isStatic ? ts.createToken(115 /* StaticKeyword */) : undefined); return modifiers && ts.createNodeArray(modifiers); } function startsWithUnderscore(name) { - return name.charCodeAt(0) === 95; + return name.charCodeAt(0) === 95 /* _ */; } function getConvertibleFieldAtPosition(context, file) { var startPosition = context.startPosition, endPosition = context.endPosition; - var node = ts.getTokenAtPosition(file, startPosition, false); + var node = ts.getTokenAtPosition(file, startPosition, /*includeJsDocComment*/ false); var declaration = ts.findAncestor(node.parent, isAcceptedDeclaration); - var meaning = 28 | 32 | 64; - if (!declaration || !ts.rangeOverlapsWithStartEnd(declaration.name, startPosition, endPosition) + // make sure declaration have AccessibilityModifier or Static Modifier or Readonly Modifier + var meaning = 28 /* AccessibilityModifier */ | 32 /* Static */ | 64 /* Readonly */; + if (!declaration || !ts.rangeOverlapsWithStartEnd(declaration.name, startPosition, endPosition) // TODO: GH#18217 || !isConvertibleName(declaration.name) || (ts.getModifierFlags(declaration) | meaning) !== meaning) return undefined; var name = declaration.name.text; @@ -90544,7 +108008,7 @@ var ts; isStatic: ts.hasStaticModifier(declaration), isReadonly: ts.hasReadonlyModifier(declaration), type: ts.getTypeAnnotationNode(declaration), - container: declaration.kind === 149 ? declaration.parent.parent : declaration.parent, + container: declaration.kind === 149 /* Parameter */ ? declaration.parent.parent : declaration.parent, originalName: declaration.name, declaration: declaration, fieldName: fieldName, @@ -90553,14 +108017,22 @@ var ts; }; } function generateGetAccessor(fieldName, accessorName, type, modifiers, isStatic, container) { - return ts.createGetAccessor(undefined, modifiers, accessorName, undefined, type, ts.createBlock([ + return ts.createGetAccessor( + /*decorators*/ undefined, modifiers, accessorName, + /*parameters*/ undefined, // TODO: GH#18217 + type, ts.createBlock([ ts.createReturn(createAccessorAccessExpression(fieldName, isStatic, container)) - ], true)); + ], /*multiLine*/ true)); } function generateSetAccessor(fieldName, accessorName, type, modifiers, isStatic, container) { - return ts.createSetAccessor(undefined, modifiers, accessorName, [ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), undefined, type)], ts.createBlock([ + return ts.createSetAccessor( + /*decorators*/ undefined, modifiers, accessorName, [ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, ts.createIdentifier("value"), + /*questionToken*/ undefined, type)], ts.createBlock([ ts.createStatement(ts.createAssignment(createAccessorAccessExpression(fieldName, isStatic, container), ts.createIdentifier("value"))) - ], true)); + ], /*multiLine*/ true)); } function updatePropertyDeclaration(changeTracker, file, declaration, fieldName, modifiers) { var property = ts.updateProperty(declaration, declaration.decorators, modifiers, fieldName, declaration.questionToken || declaration.exclamationToken, declaration.type, declaration.initializer); @@ -90609,6 +108081,7 @@ var ts; })(generateGetAccessorAndSetAccessor = refactor.generateGetAccessorAndSetAccessor || (refactor.generateGetAccessorAndSetAccessor = {})); })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var refactor; @@ -90639,9 +108112,11 @@ var ts; if (ts.isNamedDeclaration(startStatement) && startStatement.name && ts.rangeContainsRange(startStatement.name, range)) { return { toMove: [statements[startNodeIndex]], afterLast: statements[startNodeIndex + 1] }; } + // Can't only partially include the start node or be partially into the next node if (range.pos > startStatement.getStart(file)) return undefined; var afterEndNodeIndex = ts.findIndex(statements, function (s) { return s.end > range.end; }, startNodeIndex); + // Can't be partially into the next node if (afterEndNodeIndex !== -1 && (afterEndNodeIndex === 0 || statements[afterEndNodeIndex].getStart(file) < range.end)) return undefined; return { @@ -90656,9 +108131,11 @@ var ts; var extension = ts.extensionFromPath(oldFile.fileName); var newModuleName = makeUniqueModuleName(getNewModuleName(usage.movedSymbols), extension, currentDirectory, host); var newFileNameWithExtension = newModuleName + extension; + // If previous file was global, this is easy. changes.createNewFile(oldFile, ts.combinePaths(currentDirectory, newFileNameWithExtension), getNewStatementsAndRemoveFromOldFile(oldFile, usage, changes, toMove, program, newModuleName, preferences)); addNewFileToTsconfig(program, changes, oldFile.fileName, newFileNameWithExtension, ts.hostGetCanonicalFileName(host)); } + // Filters imports out of the range of statements to move. Imports will be copied to the new file anyway, and may still be needed in the old file. function getStatementsToMove(context) { var rangeToMove = getRangeToMove(context); if (rangeToMove === undefined) @@ -90675,12 +108152,12 @@ var ts; } function isPureImport(node) { switch (node.kind) { - case 244: + case 244 /* ImportDeclaration */: return true; - case 243: - return !ts.hasModifier(node, 1); - case 214: - return node.declarationList.declarations.every(function (d) { return !!d.initializer && ts.isRequireCall(d.initializer, true); }); + case 243 /* ImportEqualsDeclaration */: + return !ts.hasModifier(node, 1 /* Export */); + case 214 /* VariableStatement */: + return node.declarationList.declarations.every(function (d) { return !!d.initializer && ts.isRequireCall(d.initializer, /*checkArgumentIsStringLiteralLike*/ true); }); default: return false; } @@ -90742,10 +108219,10 @@ var ts; var shouldMove = function (name) { var symbol = ts.isBindingElement(name.parent) ? ts.getPropertySymbolFromBindingElement(checker, name.parent) - : ts.skipAlias(checker.getSymbolAtLocation(name), checker); + : ts.skipAlias(checker.getSymbolAtLocation(name), checker); // TODO: GH#18217 return !!symbol && movedSymbols.has(symbol); }; - deleteUnusedImports(sourceFile, importNode, changes, shouldMove); + deleteUnusedImports(sourceFile, importNode, changes, shouldMove); // These will be changed to imports from the new file var newModuleSpecifier = ts.combinePaths(ts.getDirectoryPath(moduleSpecifierFromImport(importNode).text), newModuleName); var newImportDeclaration = filterImport(importNode, ts.createLiteral(newModuleSpecifier), shouldMove); if (newImportDeclaration) @@ -90767,25 +108244,25 @@ var ts; } function getNamespaceLikeImport(node) { switch (node.kind) { - case 244: - return node.importClause && node.importClause.namedBindings && node.importClause.namedBindings.kind === 246 ? + case 244 /* ImportDeclaration */: + return node.importClause && node.importClause.namedBindings && node.importClause.namedBindings.kind === 246 /* NamespaceImport */ ? node.importClause.namedBindings.name : undefined; - case 243: + case 243 /* ImportEqualsDeclaration */: return node.name; - case 232: + case 232 /* VariableDeclaration */: return ts.tryCast(node.name, ts.isIdentifier); default: return ts.Debug.assertNever(node); } } function updateNamespaceLikeImport(changes, sourceFile, checker, movedSymbols, newModuleName, newModuleSpecifier, oldImportId, oldImportNode) { - var preferredNewNamespaceName = ts.codefix.moduleSpecifierToValidIdentifier(newModuleName, 6); + var preferredNewNamespaceName = ts.codefix.moduleSpecifierToValidIdentifier(newModuleName, 6 /* ESNext */); var needUniqueName = false; var toChange = []; ts.FindAllReferences.Core.eachSymbolReferenceInFile(oldImportId, checker, sourceFile, function (ref) { if (!ts.isPropertyAccessExpression(ref.parent)) return; - needUniqueName = needUniqueName || !!checker.resolveName(preferredNewNamespaceName, ref, 67108863, true); + needUniqueName = needUniqueName || !!checker.resolveName(preferredNewNamespaceName, ref, 67108863 /* All */, /*excludeGlobals*/ true); if (movedSymbols.has(checker.getSymbolAtLocation(ref.parent.name))) { toChange.push(ref); } @@ -90803,19 +108280,20 @@ var ts; var newNamespaceId = ts.createIdentifier(newNamespaceName); var newModuleString = ts.createLiteral(newModuleSpecifier); switch (node.kind) { - case 244: - return ts.createImportDeclaration(undefined, undefined, ts.createImportClause(undefined, ts.createNamespaceImport(newNamespaceId)), newModuleString); - case 243: - return ts.createImportEqualsDeclaration(undefined, undefined, newNamespaceId, ts.createExternalModuleReference(newModuleString)); - case 232: - return ts.createVariableDeclaration(newNamespaceId, undefined, createRequireCall(newModuleString)); + case 244 /* ImportDeclaration */: + return ts.createImportDeclaration( + /*decorators*/ undefined, /*modifiers*/ undefined, ts.createImportClause(/*name*/ undefined, ts.createNamespaceImport(newNamespaceId)), newModuleString); + case 243 /* ImportEqualsDeclaration */: + return ts.createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, newNamespaceId, ts.createExternalModuleReference(newModuleString)); + case 232 /* VariableDeclaration */: + return ts.createVariableDeclaration(newNamespaceId, /*type*/ undefined, createRequireCall(newModuleString)); default: return ts.Debug.assertNever(node); } } function moduleSpecifierFromImport(i) { - return (i.kind === 244 ? i.moduleSpecifier - : i.kind === 243 ? i.moduleReference.expression + return (i.kind === 244 /* ImportDeclaration */ ? i.moduleSpecifier + : i.kind === 243 /* ImportEqualsDeclaration */ ? i.moduleReference.expression : i.initializer.arguments[0]); } function forEachImportInStatement(statement, cb) { @@ -90831,7 +108309,7 @@ var ts; else if (ts.isVariableStatement(statement)) { for (var _i = 0, _a = statement.declarationList.declarations; _i < _a.length; _i++) { var decl = _a[_i]; - if (decl.initializer && ts.isRequireCall(decl.initializer, true)) { + if (decl.initializer && ts.isRequireCall(decl.initializer, /*checkArgumentIsStringLiteralLike*/ true)) { cb(decl); } } @@ -90841,8 +108319,8 @@ var ts; var defaultImport; var imports = []; newFileNeedExport.forEach(function (symbol) { - if (symbol.escapedName === "default") { - defaultImport = ts.createIdentifier(ts.symbolNameNoDefault(symbol)); + if (symbol.escapedName === "default" /* Default */) { + defaultImport = ts.createIdentifier(ts.symbolNameNoDefault(symbol)); // TODO: GH#18217 } else { imports.push(symbol.name); @@ -90853,23 +108331,23 @@ var ts; function makeImportOrRequire(defaultImport, imports, path, useEs6Imports, quotePreference) { path = ts.ensurePathIsNonModuleName(path); if (useEs6Imports) { - var specifiers = imports.map(function (i) { return ts.createImportSpecifier(undefined, ts.createIdentifier(i)); }); + var specifiers = imports.map(function (i) { return ts.createImportSpecifier(/*propertyName*/ undefined, ts.createIdentifier(i)); }); return ts.makeImportIfNecessary(defaultImport, specifiers, path, quotePreference); } else { - ts.Debug.assert(!defaultImport); - var bindingElements = imports.map(function (i) { return ts.createBindingElement(undefined, undefined, i); }); + ts.Debug.assert(!defaultImport); // If there's a default export, it should have been an es6 module. + var bindingElements = imports.map(function (i) { return ts.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, i); }); return bindingElements.length - ? makeVariableStatement(ts.createObjectBindingPattern(bindingElements), undefined, createRequireCall(ts.createLiteral(path))) + ? makeVariableStatement(ts.createObjectBindingPattern(bindingElements), /*type*/ undefined, createRequireCall(ts.createLiteral(path))) : undefined; } } function makeVariableStatement(name, type, initializer, flags) { - if (flags === void 0) { flags = 2; } - return ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(name, type, initializer)], flags)); + if (flags === void 0) { flags = 2 /* Const */; } + return ts.createVariableStatement(/*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(name, type, initializer)], flags)); } function createRequireCall(moduleSpecifier) { - return ts.createCall(ts.createIdentifier("require"), undefined, [moduleSpecifier]); + return ts.createCall(ts.createIdentifier("require"), /*typeArguments*/ undefined, [moduleSpecifier]); } function addExports(sourceFile, toMove, needExport, useEs6Exports) { return ts.flatMap(toMove, function (statement) { @@ -90885,15 +108363,15 @@ var ts; } function deleteUnusedImports(sourceFile, importDecl, changes, isUnused) { switch (importDecl.kind) { - case 244: + case 244 /* ImportDeclaration */: deleteUnusedImportsInDeclaration(sourceFile, importDecl, changes, isUnused); break; - case 243: + case 243 /* ImportEqualsDeclaration */: if (isUnused(importDecl.name)) { changes.deleteNode(sourceFile, importDecl); } break; - case 232: + case 232 /* VariableDeclaration */: deleteUnusedImportsInVariableDeclaration(sourceFile, importDecl, changes, isUnused); break; default: @@ -90906,7 +108384,7 @@ var ts; var _a = importDecl.importClause, name = _a.name, namedBindings = _a.namedBindings; var defaultUnused = !name || isUnused(name); var namedBindingsUnused = !namedBindings || - (namedBindings.kind === 246 ? isUnused(namedBindings.name) : namedBindings.elements.every(function (e) { return isUnused(e.name); })); + (namedBindings.kind === 246 /* NamespaceImport */ ? isUnused(namedBindings.name) : namedBindings.elements.every(function (e) { return isUnused(e.name); })); if (defaultUnused && namedBindingsUnused) { changes.deleteNode(sourceFile, importDecl); } @@ -90918,7 +108396,7 @@ var ts; if (namedBindingsUnused) { changes.deleteNode(sourceFile, namedBindings); } - else if (namedBindings.kind === 247) { + else if (namedBindings.kind === 247 /* NamedImports */) { for (var _i = 0, _b = namedBindings.elements; _i < _b.length; _i++) { var element = _b[_i]; if (isUnused(element.name)) @@ -90931,14 +108409,14 @@ var ts; function deleteUnusedImportsInVariableDeclaration(sourceFile, varDecl, changes, isUnused) { var name = varDecl.name; switch (name.kind) { - case 71: + case 71 /* Identifier */: if (isUnused(name)) { changes.deleteNode(sourceFile, name); } break; - case 181: + case 181 /* ArrayBindingPattern */: break; - case 180: + case 180 /* ObjectBindingPattern */: if (name.elements.every(function (e) { return ts.isIdentifier(e.name) && isUnused(e.name); })) { changes.deleteNode(sourceFile, ts.isVariableDeclarationList(varDecl.parent) && varDecl.parent.declarations.length === 1 ? varDecl.parent.parent : varDecl); } @@ -90961,9 +108439,10 @@ var ts; ts.append(copiedOldImports, filterImport(i, moduleSpecifierFromImport(i), function (name) { return importsToCopy.has(checker.getSymbolAtLocation(name)); })); }); } + // Also, import things used from the old file, and insert 'export' modifiers as necessary in the old file. var oldFileDefault; var oldFileNamedImports = []; - var markSeenTop = ts.nodeSeenTracker(); + var markSeenTop = ts.nodeSeenTracker(); // Needed because multiple declarations may appear in `const x = 0, y = 1;`. newFileImportsFromOldFile.forEach(function (symbol) { for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var decl = _a[_i]; @@ -90976,7 +108455,7 @@ var ts; if (markSeenTop(top)) { addExportToChanges(oldFile, top, changes, useEs6ModuleSyntax); } - if (ts.hasModifier(decl, 512)) { + if (ts.hasModifier(decl, 512 /* Default */)) { oldFileDefault = name; } else { @@ -90992,7 +108471,7 @@ var ts; for (var i = 1;; i++) { var name = ts.combinePaths(inDirectory, newModuleName + extension); if (!host.fileExists(name)) - return newModuleName; + return newModuleName; // TODO: GH#18217 newModuleName = moduleName + "." + i; } } @@ -91039,15 +108518,16 @@ var ts; } return { movedSymbols: movedSymbols, newFileImportsFromOldFile: newFileImportsFromOldFile, oldFileImportsFromNewFile: oldFileImportsFromNewFile, oldImportsNeededByNewFile: oldImportsNeededByNewFile, unusedImportsFromOldFile: unusedImportsFromOldFile }; } + // Below should all be utilities function isInImport(decl) { switch (decl.kind) { - case 243: - case 248: - case 245: + case 243 /* ImportEqualsDeclaration */: + case 248 /* ImportSpecifier */: + case 245 /* ImportClause */: return true; - case 232: + case 232 /* VariableDeclaration */: return isVariableDeclarationInImport(decl); - case 182: + case 182 /* BindingElement */: return ts.isVariableDeclaration(decl.parent.parent) && isVariableDeclarationInImport(decl.parent.parent); default: return false; @@ -91055,23 +108535,23 @@ var ts; } function isVariableDeclarationInImport(decl) { return ts.isSourceFile(decl.parent.parent.parent) && - decl.initializer && ts.isRequireCall(decl.initializer, true); + decl.initializer && ts.isRequireCall(decl.initializer, /*checkArgumentIsStringLiteralLike*/ true); } function filterImport(i, moduleSpecifier, keep) { switch (i.kind) { - case 244: { + case 244 /* ImportDeclaration */: { var clause = i.importClause; if (!clause) return undefined; var defaultImport = clause.name && keep(clause.name) ? clause.name : undefined; var namedBindings = clause.namedBindings && filterNamedBindings(clause.namedBindings, keep); return defaultImport || namedBindings - ? ts.createImportDeclaration(undefined, undefined, ts.createImportClause(defaultImport, namedBindings), moduleSpecifier) + ? ts.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, ts.createImportClause(defaultImport, namedBindings), moduleSpecifier) : undefined; } - case 243: + case 243 /* ImportEqualsDeclaration */: return keep(i.name) ? i : undefined; - case 232: { + case 232 /* VariableDeclaration */: { var name = filterBindingName(i.name, keep); return name ? makeVariableStatement(name, i.type, createRequireCall(moduleSpecifier), i.parent.flags) : undefined; } @@ -91080,7 +108560,7 @@ var ts; } } function filterNamedBindings(namedBindings, keep) { - if (namedBindings.kind === 246) { + if (namedBindings.kind === 246 /* NamespaceImport */) { return keep(namedBindings.name) ? namedBindings : undefined; } else { @@ -91090,11 +108570,12 @@ var ts; } function filterBindingName(name, keep) { switch (name.kind) { - case 71: + case 71 /* Identifier */: return keep(name) ? name : undefined; - case 181: + case 181 /* ArrayBindingPattern */: return name; - case 180: { + case 180 /* ObjectBindingPattern */: { + // We can't handle nested destructurings or property names well here, so just copy them all. var newElements = name.elements.filter(function (prop) { return prop.propertyName || !ts.isIdentifier(prop.name) || keep(prop.name); }); return newElements.length ? ts.createObjectBindingPattern(newElements) : undefined; } @@ -91112,7 +108593,7 @@ var ts; } }); } - var SymbolSet = (function () { + var SymbolSet = /** @class */ (function () { function SymbolSet() { this.map = ts.createMap(); } @@ -91150,13 +108631,13 @@ var ts; } function isNonVariableTopLevelDeclaration(node) { switch (node.kind) { - case 234: - case 235: - case 239: - case 238: - case 237: - case 236: - case 243: + case 234 /* FunctionDeclaration */: + case 235 /* ClassDeclaration */: + case 239 /* ModuleDeclaration */: + case 238 /* EnumDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 236 /* InterfaceDeclaration */: + case 243 /* ImportEqualsDeclaration */: return true; default: return false; @@ -91164,26 +108645,26 @@ var ts; } function forEachTopLevelDeclaration(statement, cb) { switch (statement.kind) { - case 234: - case 235: - case 239: - case 238: - case 237: - case 236: - case 243: + case 234 /* FunctionDeclaration */: + case 235 /* ClassDeclaration */: + case 239 /* ModuleDeclaration */: + case 238 /* EnumDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 236 /* InterfaceDeclaration */: + case 243 /* ImportEqualsDeclaration */: return cb(statement); - case 214: + case 214 /* VariableStatement */: return ts.forEach(statement.declarationList.declarations, cb); - case 216: { + case 216 /* ExpressionStatement */: { var expression = statement.expression; - return ts.isBinaryExpression(expression) && ts.getSpecialPropertyAssignmentKind(expression) === 1 + return ts.isBinaryExpression(expression) && ts.getSpecialPropertyAssignmentKind(expression) === 1 /* ExportsProperty */ ? cb(statement) : undefined; } } } function nameOfTopLevelDeclaration(d) { - return d.kind === 216 ? d.expression.left.name : ts.tryCast(d.name, ts.isIdentifier); + return d.kind === 216 /* ExpressionStatement */ ? d.expression.left.name : ts.tryCast(d.name, ts.isIdentifier); } function getTopLevelDeclarationStatement(d) { return ts.isVariableDeclaration(d) ? d.parent.parent : d; @@ -91203,7 +108684,7 @@ var ts; } function isExported(sourceFile, decl, useEs6Exports) { if (useEs6Exports) { - return !ts.isExpressionStatement(decl) && ts.hasModifier(decl, 1); + return !ts.isExpressionStatement(decl) && ts.hasModifier(decl, 1 /* Export */); } else { return getNamesToExportInCommonJS(decl).some(function (name) { return sourceFile.symbol.exports.has(ts.escapeLeadingUnderscores(name)); }); @@ -91213,26 +108694,26 @@ var ts; return useEs6Exports ? [addEs6Export(decl)] : addCommonjsExport(decl); } function addEs6Export(d) { - var modifiers = ts.concatenate([ts.createModifier(84)], d.modifiers); + var modifiers = ts.concatenate([ts.createModifier(84 /* ExportKeyword */)], d.modifiers); switch (d.kind) { - case 234: + case 234 /* FunctionDeclaration */: return ts.updateFunctionDeclaration(d, d.decorators, modifiers, d.asteriskToken, d.name, d.typeParameters, d.parameters, d.type, d.body); - case 235: + case 235 /* ClassDeclaration */: return ts.updateClassDeclaration(d, d.decorators, modifiers, d.name, d.typeParameters, d.heritageClauses, d.members); - case 214: + case 214 /* VariableStatement */: return ts.updateVariableStatement(d, modifiers, d.declarationList); - case 239: + case 239 /* ModuleDeclaration */: return ts.updateModuleDeclaration(d, d.decorators, modifiers, d.name, d.body); - case 238: + case 238 /* EnumDeclaration */: return ts.updateEnumDeclaration(d, d.decorators, modifiers, d.name, d.members); - case 237: + case 237 /* TypeAliasDeclaration */: return ts.updateTypeAliasDeclaration(d, d.decorators, modifiers, d.name, d.typeParameters, d.type); - case 236: + case 236 /* InterfaceDeclaration */: return ts.updateInterfaceDeclaration(d, d.decorators, modifiers, d.name, d.typeParameters, d.heritageClauses, d.members); - case 243: + case 243 /* ImportEqualsDeclaration */: return ts.updateImportEqualsDeclaration(d, d.decorators, modifiers, d.name, d.moduleReference); - case 216: - return ts.Debug.fail(); + case 216 /* ExpressionStatement */: + return ts.Debug.fail(); // Shouldn't try to add 'export' keyword to `exports.x = ...` default: return ts.Debug.assertNever(d); } @@ -91242,28 +108723,30 @@ var ts; } function getNamesToExportInCommonJS(decl) { switch (decl.kind) { - case 234: - case 235: - return [decl.name.text]; - case 214: + case 234 /* FunctionDeclaration */: + case 235 /* ClassDeclaration */: + return [decl.name.text]; // TODO: GH#18217 + case 214 /* VariableStatement */: return ts.mapDefined(decl.declarationList.declarations, function (d) { return ts.isIdentifier(d.name) ? d.name.text : undefined; }); - case 239: - case 238: - case 237: - case 236: - case 243: + case 239 /* ModuleDeclaration */: + case 238 /* EnumDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 236 /* InterfaceDeclaration */: + case 243 /* ImportEqualsDeclaration */: return ts.emptyArray; - case 216: - return ts.Debug.fail(); + case 216 /* ExpressionStatement */: + return ts.Debug.fail(); // Shouldn't try to add 'export' keyword to `exports.x = ...` default: return ts.Debug.assertNever(decl); } } + /** Creates `exports.x = x;` */ function createExportAssignment(name) { - return ts.createExpressionStatement(ts.createBinary(ts.createPropertyAccess(ts.createIdentifier("exports"), ts.createIdentifier(name)), 58, ts.createIdentifier(name))); + return ts.createExpressionStatement(ts.createBinary(ts.createPropertyAccess(ts.createIdentifier("exports"), ts.createIdentifier(name)), 58 /* EqualsToken */, ts.createIdentifier(name))); } })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var refactor; @@ -91306,15 +108789,15 @@ var ts; var body; if (actionName === addBracesActionName) { var returnStatement_1 = ts.createReturn(expression); - body = ts.createBlock([returnStatement_1], true); + body = ts.createBlock([returnStatement_1], /* multiLine */ true); ts.suppressLeadingAndTrailingTrivia(body); - ts.copyComments(expression, returnStatement_1, file, 3, true); + ts.copyComments(expression, returnStatement_1, file, 3 /* MultiLineCommentTrivia */, /* hasTrailingNewLine */ true); } else if (actionName === removeBracesActionName && returnStatement) { var actualExpression = expression || ts.createVoidZero(); body = needsParentheses(actualExpression) ? ts.createParen(actualExpression) : actualExpression; ts.suppressLeadingAndTrailingTrivia(body); - ts.copyComments(returnStatement, body, file, 3, false); + ts.copyComments(returnStatement, body, file, 3 /* MultiLineCommentTrivia */, /* hasTrailingNewLine */ false); } else { ts.Debug.fail("invalid action"); @@ -91323,10 +108806,10 @@ var ts; return { renameFilename: undefined, renameLocation: undefined, edits: edits }; } function needsParentheses(expression) { - return ts.isBinaryExpression(expression) && expression.operatorToken.kind === 26 || ts.isObjectLiteralExpression(expression); + return ts.isBinaryExpression(expression) && expression.operatorToken.kind === 26 /* CommaToken */ || ts.isObjectLiteralExpression(expression); } function getConvertibleArrowFunctionAtPosition(file, startPosition) { - var node = ts.getTokenAtPosition(file, startPosition, false); + var node = ts.getTokenAtPosition(file, startPosition, /*includeJsDocComment*/ false); var func = ts.getContainingFunction(node); if (!func || !ts.isArrowFunction(func) || (!ts.rangeContainsRange(func, node) || ts.rangeContainsRange(func.body, node))) return undefined; @@ -91355,25 +108838,27 @@ var ts; })(ts || (ts = {})); var ts; (function (ts) { + /** The version of the language service API */ ts.servicesVersion = "0.8"; function createNode(kind, pos, end, parent) { var node = ts.isNodeKind(kind) ? new NodeObject(kind, pos, end) : - kind === 71 ? new IdentifierObject(71, pos, end) : + kind === 71 /* Identifier */ ? new IdentifierObject(71 /* Identifier */, pos, end) : new TokenObject(kind, pos, end); node.parent = parent; - node.flags = parent.flags & 12679168; + node.flags = parent.flags & 12679168 /* ContextFlags */; return node; } - var NodeObject = (function () { + var NodeObject = /** @class */ (function () { function NodeObject(kind, pos, end) { this.pos = pos; this.end = end; - this.flags = 0; - this.transformFlags = undefined; + this.flags = 0 /* None */; + this.transformFlags = undefined; // TODO: GH#18217 this.parent = undefined; this.kind = kind; } NodeObject.prototype.assertHasRealPosition = function (message) { + // tslint:disable-next-line:debug-assert ts.Debug.assert(!ts.positionIsSynthesized(this.pos) && !ts.positionIsSynthesized(this.end), message || "Node must have a real position for this operation"); }; NodeObject.prototype.getSourceFile = function () { @@ -91430,8 +108915,8 @@ var ts; if (!children.length) { return undefined; } - var child = ts.find(children, function (kid) { return kid.kind < 278 || kid.kind > 299; }); - return child.kind < 146 ? + var child = ts.find(children, function (kid) { return kid.kind < 278 /* FirstJSDocNode */ || kid.kind > 299 /* LastJSDocNode */; }); + return child.kind < 146 /* FirstNode */ ? child : child.getFirstToken(sourceFile); }; @@ -91442,7 +108927,7 @@ var ts; if (!child) { return undefined; } - return child.kind < 146 ? child : child.getLastToken(sourceFile); + return child.kind < 146 /* FirstNode */ ? child : child.getLastToken(sourceFile); }; NodeObject.prototype.forEachChild = function (cbNode, cbNodeArray) { return ts.forEachChild(this, cbNode, cbNodeArray); @@ -91455,6 +108940,7 @@ var ts; } var children = []; if (ts.isJSDocCommentContainingNode(node)) { + /** Don't add trivia for "tokens" since this is in a comment. */ node.forEachChild(function (child) { children.push(child); }); return children; } @@ -91470,7 +108956,11 @@ var ts; children.push(createSyntaxList(nodes, node)); pos = nodes.end; }; + // jsDocComments need to be the first children ts.forEach(node.jsDoc, processNode); + // For syntactic classifications, all trivia are classified together, including jsdoc comments. + // For that to work, the jsdoc comments should still be the leading trivia of the first child. + // Restoring the scanner position ensures that. pos = node.pos; node.forEachChild(processNode, processNodes); addSyntheticNodes(children, pos, node.end, node); @@ -91483,19 +108973,19 @@ var ts; var token = ts.scanner.scan(); var textPos = ts.scanner.getTextPos(); if (textPos <= end) { - if (token === 71) { + if (token === 71 /* Identifier */) { ts.Debug.fail("Did not expect " + ts.Debug.showSyntaxKind(parent) + " to have an Identifier in its trivia"); } nodes.push(createNode(token, pos, textPos, parent)); } pos = textPos; - if (token === 1) { + if (token === 1 /* EndOfFileToken */) { break; } } } function createSyntaxList(nodes, parent) { - var list = createNode(300, nodes.pos, nodes.end, parent); + var list = createNode(300 /* SyntaxList */, nodes.pos, nodes.end, parent); list._children = []; var pos = nodes.pos; for (var _i = 0, nodes_7 = nodes; _i < nodes_7.length; _i++) { @@ -91507,11 +108997,12 @@ var ts; addSyntheticNodes(list._children, pos, nodes.end, parent); return list; } - var TokenOrIdentifierObject = (function () { + var TokenOrIdentifierObject = /** @class */ (function () { function TokenOrIdentifierObject(pos, end) { + // Set properties in same order as NodeObject this.pos = pos; this.end = end; - this.flags = 0; + this.flags = 0 /* None */; this.parent = undefined; } TokenOrIdentifierObject.prototype.getSourceFile = function () { @@ -91548,7 +109039,7 @@ var ts; return 0; }; TokenOrIdentifierObject.prototype.getChildAt = function () { - return undefined; + return undefined; // TODO: GH#18217 }; TokenOrIdentifierObject.prototype.getChildren = function () { return ts.emptyArray; @@ -91564,7 +109055,7 @@ var ts; }; return TokenOrIdentifierObject; }()); - var SymbolObject = (function () { + var SymbolObject = /** @class */ (function () { function SymbolObject(flags, name) { this.flags = flags; this.escapedName = name; @@ -91590,7 +109081,7 @@ var ts; }; SymbolObject.prototype.getDocumentationComment = function (checker) { if (!this.documentationComment) { - this.documentationComment = ts.emptyArray; + this.documentationComment = ts.emptyArray; // Set temporarily to avoid an infinite loop finding inherited docs this.documentationComment = getDocumentationComment(this.declarations, checker); } return this.documentationComment; @@ -91603,7 +109094,7 @@ var ts; }; return SymbolObject; }()); - var TokenObject = (function (_super) { + var TokenObject = /** @class */ (function (_super) { __extends(TokenObject, _super); function TokenObject(kind, pos, end) { var _this = _super.call(this, pos, end) || this; @@ -91612,7 +109103,7 @@ var ts; } return TokenObject; }(TokenOrIdentifierObject)); - var IdentifierObject = (function (_super) { + var IdentifierObject = /** @class */ (function (_super) { __extends(IdentifierObject, _super); function IdentifierObject(_kind, pos, end) { return _super.call(this, pos, end) || this; @@ -91626,8 +109117,8 @@ var ts; }); return IdentifierObject; }(TokenOrIdentifierObject)); - IdentifierObject.prototype.kind = 71; - var TypeObject = (function () { + IdentifierObject.prototype.kind = 71 /* Identifier */; + var TypeObject = /** @class */ (function () { function TypeObject(checker, flags) { this.checker = checker; this.flags = flags; @@ -91648,16 +109139,16 @@ var ts; return this.checker.getAugmentedPropertiesOfType(this); }; TypeObject.prototype.getCallSignatures = function () { - return this.checker.getSignaturesOfType(this, 0); + return this.checker.getSignaturesOfType(this, 0 /* Call */); }; TypeObject.prototype.getConstructSignatures = function () { - return this.checker.getSignaturesOfType(this, 1); + return this.checker.getSignaturesOfType(this, 1 /* Construct */); }; TypeObject.prototype.getStringIndexType = function () { - return this.checker.getIndexTypeOfType(this, 0); + return this.checker.getIndexTypeOfType(this, 0 /* String */); }; TypeObject.prototype.getNumberIndexType = function () { - return this.checker.getIndexTypeOfType(this, 1); + return this.checker.getIndexTypeOfType(this, 1 /* Number */); }; TypeObject.prototype.getBaseTypes = function () { return this.isClassOrInterface() ? this.checker.getBaseTypes(this) : undefined; @@ -91672,35 +109163,35 @@ var ts; return this.checker.getDefaultFromTypeParameter(this); }; TypeObject.prototype.isUnion = function () { - return !!(this.flags & 262144); + return !!(this.flags & 262144 /* Union */); }; TypeObject.prototype.isIntersection = function () { - return !!(this.flags & 524288); + return !!(this.flags & 524288 /* Intersection */); }; TypeObject.prototype.isUnionOrIntersection = function () { - return !!(this.flags & 786432); + return !!(this.flags & 786432 /* UnionOrIntersection */); }; TypeObject.prototype.isLiteral = function () { - return !!(this.flags & 192); + return !!(this.flags & 192 /* StringOrNumberLiteral */); }; TypeObject.prototype.isStringLiteral = function () { - return !!(this.flags & 64); + return !!(this.flags & 64 /* StringLiteral */); }; TypeObject.prototype.isNumberLiteral = function () { - return !!(this.flags & 128); + return !!(this.flags & 128 /* NumberLiteral */); }; TypeObject.prototype.isTypeParameter = function () { - return !!(this.flags & 65536); + return !!(this.flags & 65536 /* TypeParameter */); }; TypeObject.prototype.isClassOrInterface = function () { - return !!(ts.getObjectFlags(this) & 3); + return !!(ts.getObjectFlags(this) & 3 /* ClassOrInterface */); }; TypeObject.prototype.isClass = function () { - return !!(ts.getObjectFlags(this) & 1); + return !!(ts.getObjectFlags(this) & 1 /* Class */); }; return TypeObject; }()); - var SignatureObject = (function () { + var SignatureObject = /** @class */ (function () { function SignatureObject(checker) { this.checker = checker; } @@ -91727,6 +109218,11 @@ var ts; }; return SignatureObject; }()); + /** + * Returns whether or not the given node has a JSDoc "inheritDoc" tag on it. + * @param node the Node in question. + * @returns `true` if `node` has a JSDoc "inheritDoc" tag on it, otherwise `false`. + */ function hasJSDocInheritDocTag(node) { return ts.getJSDocTags(node).some(function (tag) { return tag.tagName.text === "inheritDoc"; }); } @@ -91737,13 +109233,22 @@ var ts; if (doc.length === 0 || declarations.some(hasJSDocInheritDocTag)) { for (var _i = 0, declarations_14 = declarations; _i < declarations_14.length; _i++) { var declaration = declarations_14[_i]; - var inheritedDocs = findInheritedJSDocComments(declaration, declaration.symbol.name, checker); + var inheritedDocs = findInheritedJSDocComments(declaration, declaration.symbol.name, checker); // TODO: GH#18217 + // TODO: GH#16312 Return a ReadonlyArray, avoid copying inheritedDocs if (inheritedDocs) doc = doc.length === 0 ? inheritedDocs.slice() : inheritedDocs.concat(ts.lineBreakPart(), doc); } } return doc; } + /** + * Attempts to find JSDoc comments for possibly-inherited properties. Checks superclasses then traverses + * implemented interfaces until a symbol is found with the same name and with documentation. + * @param declaration The possibly-inherited declaration to find comments for. + * @param propertyName The name of the possibly-inherited property. + * @param typeChecker A TypeChecker, used to find inherited properties. + * @returns A filled array of documentation comments if any were found, otherwise an empty array. + */ function findInheritedJSDocComments(declaration, propertyName, typeChecker) { return ts.firstDefined(declaration.parent ? ts.getAllSuperTypeNodes(declaration.parent) : ts.emptyArray, function (superTypeNode) { var superType = typeChecker.getTypeAtLocation(superTypeNode); @@ -91752,7 +109257,7 @@ var ts; return inheritedDocs && inheritedDocs.length ? inheritedDocs : undefined; }); } - var SourceFileObject = (function (_super) { + var SourceFileObject = /** @class */ (function (_super) { __extends(SourceFileObject, _super); function SourceFileObject(kind, pos, end) { return _super.call(this, kind, pos, end) || this; @@ -91780,6 +109285,7 @@ var ts; lastCharPos = lineStarts[line + 1] - 1; } var fullText = this.getFullText(); + // if the new line is "\r\n", we should return the last non-new-line-character position return fullText[lastCharPos] === "\n" && fullText[lastCharPos - 1] === "\r" ? lastCharPos - 1 : lastCharPos; }; SourceFileObject.prototype.getNamedDeclarations = function () { @@ -91812,16 +109318,19 @@ var ts; } function visit(node) { switch (node.kind) { - case 234: - case 192: - case 154: - case 153: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: var functionDeclaration = node; var declarationName = getDeclarationName(functionDeclaration); if (declarationName) { var declarations = getDeclarations(declarationName); var lastDeclaration = ts.lastOrUndefined(declarations); + // Check whether this declaration belongs to an "overload group". if (lastDeclaration && functionDeclaration.parent === lastDeclaration.parent && functionDeclaration.symbol === lastDeclaration.symbol) { + // Overwrite the last declaration if it was an overload + // and this one is an implementation. if (functionDeclaration.body && !lastDeclaration.body) { declarations[declarations.length - 1] = functionDeclaration; } @@ -91832,29 +109341,31 @@ var ts; } ts.forEachChild(node, visit); break; - case 235: - case 205: - case 236: - case 237: - case 238: - case 239: - case 243: - case 252: - case 248: - case 245: - case 246: - case 156: - case 157: - case 166: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 238 /* EnumDeclaration */: + case 239 /* ModuleDeclaration */: + case 243 /* ImportEqualsDeclaration */: + case 252 /* ExportSpecifier */: + case 248 /* ImportSpecifier */: + case 245 /* ImportClause */: + case 246 /* NamespaceImport */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 166 /* TypeLiteral */: addDeclaration(node); ts.forEachChild(node, visit); break; - case 149: - if (!ts.hasModifier(node, 92)) { + case 149 /* Parameter */: + // Only consider parameter properties + if (!ts.hasModifier(node, 92 /* ParameterPropertyModifier */)) { break; } - case 232: - case 182: { + // falls through + case 232 /* VariableDeclaration */: + case 182 /* BindingElement */: { var decl = node; if (ts.isBindingPattern(decl.name)) { ts.forEachChild(decl.name, visit); @@ -91864,24 +109375,32 @@ var ts; visit(decl.initializer); } } - case 273: - case 152: - case 151: + // falls through + case 273 /* EnumMember */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: addDeclaration(node); break; - case 250: + case 250 /* ExportDeclaration */: + // Handle named exports case e.g.: + // export {a, b as B} from "mod"; if (node.exportClause) { ts.forEach(node.exportClause.elements, visit); } break; - case 244: + case 244 /* ImportDeclaration */: var importClause = node.importClause; if (importClause) { + // Handle default import case e.g.: + // import d from "mod"; if (importClause.name) { addDeclaration(importClause); } + // Handle named bindings in imports e.g.: + // import * as NS from "mod"; + // import {a, b as B} from "mod"; if (importClause.namedBindings) { - if (importClause.namedBindings.kind === 246) { + if (importClause.namedBindings.kind === 246 /* NamespaceImport */) { addDeclaration(importClause.namedBindings); } else { @@ -91890,10 +109409,11 @@ var ts; } } break; - case 200: - if (ts.getSpecialPropertyAssignmentKind(node) !== 0) { + case 200 /* BinaryExpression */: + if (ts.getSpecialPropertyAssignmentKind(node) !== 0 /* None */) { addDeclaration(node); } + // falls through default: ts.forEachChild(node, visit); } @@ -91901,7 +109421,7 @@ var ts; }; return SourceFileObject; }(NodeObject)); - var SourceMapSourceObject = (function () { + var SourceMapSourceObject = /** @class */ (function () { function SourceMapSourceObject(fileName, text, skipTrivia) { this.fileName = fileName; this.text = text; @@ -91956,9 +109476,10 @@ var ts; } ts.displayPartsToString = displayPartsToString; function getDefaultCompilerOptions() { + // Always default to "ScriptTarget.ES5" for the language service return { - target: 1, - jsx: 1 + target: 1 /* ES5 */, + jsx: 1 /* Preserve */ }; } ts.getDefaultCompilerOptions = getDefaultCompilerOptions; @@ -91966,16 +109487,22 @@ var ts; return ts.codefix.getSupportedErrorCodes(); } ts.getSupportedCodeFixes = getSupportedCodeFixes; - var HostCache = (function () { + // Cache host information about script Should be refreshed + // at each language service public entry point, since we don't know when + // the set of scripts handled by the host changes. + var HostCache = /** @class */ (function () { function HostCache(host, getCanonicalFileName) { this.host = host; + // script id => script index this.currentDirectory = host.getCurrentDirectory(); this.fileNameToEntry = ts.createMap(); + // Initialize the list with the root file names var rootFileNames = host.getScriptFileNames(); for (var _i = 0, rootFileNames_1 = rootFileNames; _i < rootFileNames_1.length; _i++) { var fileName = rootFileNames_1[_i]; this.createEntry(fileName, ts.toPath(fileName, this.currentDirectory, getCanonicalFileName)); } + // store the compilation settings this._compilationSettings = host.getCompilationSettings() || getDefaultCompilerOptions(); } HostCache.prototype.compilationSettings = function () { @@ -92010,7 +109537,7 @@ var ts; }; HostCache.prototype.getOrCreateEntryByPath = function (fileName, path) { var info = this.getEntryByPath(path) || this.createEntry(fileName, path); - return ts.isString(info) ? undefined : info; + return ts.isString(info) ? undefined : info; // TODO: GH#18217 }; HostCache.prototype.getRootFileNames = function () { var names = []; @@ -92019,7 +109546,7 @@ var ts; names.push(entry); } else { - if (entry.scriptKind !== 6) { + if (entry.scriptKind !== 6 /* JSON */) { names.push(entry.hostFileName); } } @@ -92028,34 +109555,38 @@ var ts; }; HostCache.prototype.getVersion = function (path) { var file = this.getHostFileInformation(path); - return (file && file.version); + return (file && file.version); // TODO: GH#18217 }; HostCache.prototype.getScriptSnapshot = function (path) { var file = this.getHostFileInformation(path); - return (file && file.scriptSnapshot); + return (file && file.scriptSnapshot); // TODO: GH#18217 }; return HostCache; }()); - var SyntaxTreeCache = (function () { + var SyntaxTreeCache = /** @class */ (function () { function SyntaxTreeCache(host) { this.host = host; } SyntaxTreeCache.prototype.getCurrentSourceFile = function (fileName) { var scriptSnapshot = this.host.getScriptSnapshot(fileName); if (!scriptSnapshot) { + // The host does not know about this file. throw new Error("Could not find file: '" + fileName + "'."); } var scriptKind = ts.getScriptKind(fileName, this.host); var version = this.host.getScriptVersion(fileName); var sourceFile; if (this.currentFileName !== fileName) { - sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, 6, version, true, scriptKind); + // This is a new file, just parse it + sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, 6 /* Latest */, version, /*setNodeParents*/ true, scriptKind); } else if (this.currentFileVersion !== version) { + // This is the same file, just a newer version. Incrementally parse the file. var editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot); sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange); } if (sourceFile) { + // All done, ensure state is up to date this.currentFileVersion = version; this.currentFileName = fileName; this.currentFileScriptSnapshot = scriptSnapshot; @@ -92077,21 +109608,29 @@ var ts; ts.createLanguageServiceSourceFile = createLanguageServiceSourceFile; ts.disableIncrementalParsing = false; function updateLanguageServiceSourceFile(sourceFile, scriptSnapshot, version, textChangeRange, aggressiveChecks) { + // If we were given a text change range, and our version or open-ness changed, then + // incrementally parse this file. if (textChangeRange) { if (version !== sourceFile.version) { + // Once incremental parsing is ready, then just call into this function. if (!ts.disableIncrementalParsing) { var newText = void 0; + // grab the fragment from the beginning of the original text to the beginning of the span var prefix = textChangeRange.span.start !== 0 ? sourceFile.text.substr(0, textChangeRange.span.start) : ""; + // grab the fragment from the end of the span till the end of the original text var suffix = ts.textSpanEnd(textChangeRange.span) !== sourceFile.text.length ? sourceFile.text.substr(ts.textSpanEnd(textChangeRange.span)) : ""; if (textChangeRange.newLength === 0) { + // edit was a deletion - just combine prefix and suffix newText = prefix && suffix ? prefix + suffix : prefix || suffix; } else { + // it was actual edit, fetch the fragment of new text that correspond to new span var changedText = scriptSnapshot.getText(textChangeRange.span.start, textChangeRange.span.start + textChangeRange.newLength); + // combine prefix, changed text and suffix newText = prefix && suffix ? prefix + changedText + suffix : prefix @@ -92100,7 +109639,10 @@ var ts; } var newSourceFile = ts.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); setSourceFileFields(newSourceFile, scriptSnapshot, version); + // after incremental parsing nameTable might not be up-to-date + // drop it so it can be lazily recreated later newSourceFile.nameTable = undefined; + // dispose all resources held by old script snapshot if (sourceFile !== newSourceFile && sourceFile.scriptSnapshot) { if (sourceFile.scriptSnapshot.dispose) { sourceFile.scriptSnapshot.dispose(); @@ -92111,10 +109653,11 @@ var ts; } } } - return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, true, sourceFile.scriptKind); + // Otherwise, just create a new source file. + return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true, sourceFile.scriptKind); } ts.updateLanguageServiceSourceFile = updateLanguageServiceSourceFile; - var CancellationTokenObject = (function () { + var CancellationTokenObject = /** @class */ (function () { function CancellationTokenObject(cancellationToken) { this.cancellationToken = cancellationToken; } @@ -92128,17 +109671,23 @@ var ts; }; return CancellationTokenObject; }()); - var ThrottledCancellationToken = (function () { + /* @internal */ + /** A cancellation that throttles calls to the host */ + var ThrottledCancellationToken = /** @class */ (function () { function ThrottledCancellationToken(hostCancellationToken, throttleWaitMilliseconds) { if (throttleWaitMilliseconds === void 0) { throttleWaitMilliseconds = 20; } this.hostCancellationToken = hostCancellationToken; this.throttleWaitMilliseconds = throttleWaitMilliseconds; + // Store when we last tried to cancel. Checking cancellation can be expensive (as we have + // to marshall over to the host layer). So we only bother actually checking once enough + // time has passed. this.lastCancellationCheckTime = 0; } ThrottledCancellationToken.prototype.isCancellationRequested = function () { var time = ts.timestamp(); var duration = Math.abs(time - this.lastCancellationCheckTime); if (duration >= this.throttleWaitMilliseconds) { + // Check no more than once every throttle wait milliseconds this.lastCancellationCheckTime = time; return this.hostCancellationToken.isCancellationRequested(); } @@ -92162,6 +109711,7 @@ var ts; var lastTypesRootVersion = 0; var cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken()); var currentDirectory = host.getCurrentDirectory(); + // Check if the localized messages json is set, otherwise query the host for it if (!ts.localizedDiagnosticMessages && host.getLocalizedDiagnosticMessages) { ts.localizedDiagnosticMessages = host.getLocalizedDiagnosticMessages(); } @@ -92182,6 +109732,7 @@ var ts; } function synchronizeHostData() { ts.Debug.assert(!syntaxOnly); + // perform fast check if host supports it if (host.getProjectVersion) { var hostProjectVersion = host.getProjectVersion(); if (hostProjectVersion) { @@ -92194,16 +109745,24 @@ var ts; var typeRootsVersion = host.getTypeRootsVersion ? host.getTypeRootsVersion() : 0; if (lastTypesRootVersion !== typeRootsVersion) { log("TypeRoots version has changed; provide new program"); - program = undefined; + program = undefined; // TODO: GH#18217 lastTypesRootVersion = typeRootsVersion; } + // Get a fresh cache of the host information var hostCache = new HostCache(host, getCanonicalFileName); var rootFileNames = hostCache.getRootFileNames(); var hasInvalidatedResolution = host.hasInvalidatedResolution || ts.returnFalse; + // If the program is already up-to-date, we can reuse it if (ts.isProgramUptoDate(program, rootFileNames, hostCache.compilationSettings(), function (path) { return hostCache.getVersion(path); }, fileExists, hasInvalidatedResolution, !!host.hasChangedAutomaticTypeDirectiveNames)) { return; } + // IMPORTANT - It is critical from this moment onward that we do not check + // cancellation tokens. We are about to mutate source files from a previous program + // instance. If we cancel midway through, we may end up in an inconsistent state where + // the program points to old source files that have been invalidated because of + // incremental parsing. var newSettings = hostCache.compilationSettings(); + // Now create a new compiler var compilerHost = { getSourceFile: getOrCreateSourceFile, getSourceFileByPath: getOrCreateSourceFileByPath, @@ -92216,6 +109775,7 @@ var ts; getCurrentDirectory: function () { return currentDirectory; }, fileExists: fileExists, readFile: function (fileName) { + // stub missing host functionality var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); var entry = hostCache.getEntryByPath(path); if (entry) { @@ -92254,8 +109814,15 @@ var ts; projectReferences: hostCache.getProjectReferences() }; program = ts.createProgram(options); + // hostCache is captured in the closure for 'getOrCreateSourceFile' but it should not be used past this point. + // It needs to be cleared to allow all collected snapshots to be released hostCache = undefined; + // We reset this cache on structure invalidation so we don't hold on to outdated files for long; however we can't use the `compilerHost` above, + // Because it only functions until `hostCache` is cleared, while we'll potentially need the functionality to lazily read sourcemap files during + // the course of whatever called `synchronizeHostData` sourcemappedFileCache = ts.createSourceFileLikeCache(host); + // Make sure all the nodes in the program are both bound, and have their parent + // pointers set property. program.getTypeChecker(); return; function fileExists(fileName) { @@ -92265,6 +109832,8 @@ var ts; !ts.isString(entry) : (!!host.fileExists && host.fileExists(fileName)); } + // Release any files we have acquired in the old program but are + // not part of the new program. function onReleaseOldSourceFile(oldSourceFile, oldOptions) { var oldSettingsKey = documentRegistry.getKeyForCompilationSettings(oldOptions); documentRegistry.releaseDocumentWithKey(oldSourceFile.path, oldSettingsKey); @@ -92274,20 +109843,54 @@ var ts; } function getOrCreateSourceFileByPath(fileName, path, _languageVersion, _onError, shouldCreateNewSourceFile) { ts.Debug.assert(hostCache !== undefined); + // The program is asking for this file, check first if the host can locate it. + // If the host can not locate the file, then it does not exist. return undefined + // to the program to allow reporting of errors for missing files. var hostFileInformation = hostCache.getOrCreateEntryByPath(fileName, path); if (!hostFileInformation) { return undefined; } + // Check if the language version has changed since we last created a program; if they are the same, + // it is safe to reuse the sourceFiles; if not, then the shape of the AST can change, and the oldSourceFile + // can not be reused. we have to dump all syntax trees and create new ones. if (!shouldCreateNewSourceFile) { + // Check if the old program had this file already var oldSourceFile = program && program.getSourceFileByPath(path); if (oldSourceFile) { + // We already had a source file for this file name. Go to the registry to + // ensure that we get the right up to date version of it. We need this to + // address the following race-condition. Specifically, say we have the following: + // + // LS1 + // \ + // DocumentRegistry + // / + // LS2 + // + // Each LS has a reference to file 'foo.ts' at version 1. LS2 then updates + // it's version of 'foo.ts' to version 2. This will cause LS2 and the + // DocumentRegistry to have version 2 of the document. HOwever, LS1 will + // have version 1. And *importantly* this source file will be *corrupt*. + // The act of creating version 2 of the file irrevocably damages the version + // 1 file. + // + // So, later when we call into LS1, we need to make sure that it doesn't use + // it's source file any more, and instead defers to DocumentRegistry to get + // either version 1, version 2 (or some other version) depending on what the + // host says should be used. + // We do not support the scenario where a host can modify a registered + // file's script kind, i.e. in one project some file is treated as ".ts" + // and in another as ".js" ts.Debug.assertEqual(hostFileInformation.scriptKind, oldSourceFile.scriptKind, "Registered script kind should match new script kind.", path); return documentRegistry.updateDocumentWithKey(fileName, path, newSettings, documentRegistryBucketKey, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } + // We didn't already have the file. Fall through and acquire it from the registry. } + // Could not find this file in the old program, create a new SourceFile for it. return documentRegistry.acquireDocumentWithKey(fileName, path, newSettings, documentRegistryBucketKey, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } } + // TODO: GH#18217 frequently asserted as defined function getProgram() { if (syntaxOnly) { ts.Debug.assert(program === undefined); @@ -92297,28 +109900,36 @@ var ts; return program; } function cleanupSemanticCache() { - program = undefined; + program = undefined; // TODO: GH#18217 } function dispose() { if (program) { ts.forEach(program.getSourceFiles(), function (f) { return documentRegistry.releaseDocument(f.fileName, program.getCompilerOptions()); }); - program = undefined; + program = undefined; // TODO: GH#18217 } host = undefined; } + /// Diagnostics function getSyntacticDiagnostics(fileName) { synchronizeHostData(); return program.getSyntacticDiagnostics(getValidSourceFile(fileName), cancellationToken).slice(); } + /** + * getSemanticDiagnostics return array of Diagnostics. If '-d' is not enabled, only report semantic errors + * If '-d' enabled, report both semantic and emitter errors + */ function getSemanticDiagnostics(fileName) { synchronizeHostData(); var targetSourceFile = getValidSourceFile(fileName); + // Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file. + // Therefore only get diagnostics for given file. var semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken); if (!program.getCompilerOptions().declaration) { return semanticDiagnostics.slice(); } + // If '-d' is enabled, check for emitter error. One example of emitter error is export class implements non-export interface var declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken); return semanticDiagnostics.concat(declarationDiagnostics); } @@ -92332,6 +109943,7 @@ var ts; } function getCompletionsAtPosition(fileName, position, options) { if (options === void 0) { options = ts.defaultPreferences; } + // Convert from deprecated options names to new names var fullPreferences = __assign({}, ts.identity(options), { includeCompletionsForModuleExports: options.includeCompletionsForModuleExports || options.includeExternalModuleExports, includeCompletionsWithInsertText: options.includeCompletionsWithInsertText || options.includeInsertTextCompletions }); synchronizeHostData(); return ts.Completions.getCompletionsAtPosition(host, program, log, getValidSourceFile(fileName), position, fullPreferences, options.triggerCharacter); @@ -92339,7 +109951,8 @@ var ts; function getCompletionEntryDetails(fileName, position, name, formattingOptions, source, preferences) { if (preferences === void 0) { preferences = ts.defaultPreferences; } synchronizeHostData(); - return ts.Completions.getCompletionEntryDetails(program, log, getValidSourceFile(fileName), position, { name: name, source: source }, host, (formattingOptions && ts.formatting.getFormatContext(formattingOptions)), getCanonicalFileName, preferences, cancellationToken); + return ts.Completions.getCompletionEntryDetails(program, log, getValidSourceFile(fileName), position, { name: name, source: source }, host, (formattingOptions && ts.formatting.getFormatContext(formattingOptions)), // TODO: GH#18217 + getCanonicalFileName, preferences, cancellationToken); } function getCompletionEntrySymbol(fileName, position, name, source) { synchronizeHostData(); @@ -92350,25 +109963,30 @@ var ts; var sourceFile = getValidSourceFile(fileName); var node = ts.getTouchingPropertyName(sourceFile, position); if (node === sourceFile) { + // Avoid giving quickInfo for the sourceFile as a whole. return undefined; } var typeChecker = program.getTypeChecker(); var symbol = getSymbolAtLocationForQuickInfo(node, typeChecker); if (!symbol || typeChecker.isUnknownSymbol(symbol)) { + // Try getting just type at this position and show switch (node.kind) { - case 71: + case 71 /* Identifier */: if (ts.isLabelName(node)) { + // Type here will be 'any', avoid displaying this. return undefined; } - case 185: - case 146: - case 99: - case 174: - case 97: + // falls through + case 185 /* PropertyAccessExpression */: + case 146 /* QualifiedName */: + case 99 /* ThisKeyword */: + case 174 /* ThisType */: + case 97 /* SuperKeyword */: + // For the identifiers/this/super etc get the type at position var type_4 = typeChecker.getTypeAtLocation(node); return type_4 && { - kind: "", - kindModifiers: "", + kind: "" /* unknown */, + kindModifiers: "" /* none */, textSpan: ts.createTextSpanFromNode(node, sourceFile), displayParts: typeChecker.runWithCancellationToken(cancellationToken, function (typeChecker) { return ts.typeToDisplayParts(typeChecker, type_4, ts.getContainerNode(node)); }), documentation: type_4.symbol ? type_4.symbol.getDocumentationComment(typeChecker) : undefined, @@ -92403,9 +110021,10 @@ var ts; } function toLineColumnOffset(fileName, position) { var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); - var file = program.getSourceFile(path) || sourcemappedFileCache.get(path); + var file = program.getSourceFile(path) || sourcemappedFileCache.get(path); // TODO: GH#18217 return file.getLineAndCharacterOfPosition(position); } + // Sometimes tools can sometimes see the following line as a source mapping url comment, so we mangle it a bit (the [M]) var sourceMapCommentRegExp = /^\/\/[@#] source[M]appingURL=(.+)$/gm; var base64UrlRegExp = /^data:(?:application\/json(?:;charset=[uU][tT][fF]-8);base64,([A-Za-z0-9+\/=]+)$)?/; function scanForSourcemapURL(fileName) { @@ -92428,8 +110047,10 @@ var ts; maps = JSON.parse(contents); } catch (_a) { + // swallow error } if (!maps || !maps.sources || !maps.file || !maps.mappings) { + // obviously invalid map return file.sourceMapper = ts.sourcemaps.identitySourceMapper; } return file.sourceMapper = ts.sourcemaps.decode({ @@ -92454,6 +110075,7 @@ var ts; var base64Object = match[1]; return convertDocumentToSourceMapper(file, ts.base64decode(ts.sys, base64Object), fileName); } + // Not a data URL we can parse, skip it mapFileName = undefined; } } @@ -92466,7 +110088,7 @@ var ts; var location = possibleMapLocations_1[_i]; var mapPath = ts.toPath(location, ts.getDirectoryPath(fileName), getCanonicalFileName); if (host.fileExists(mapPath)) { - return convertDocumentToSourceMapper(file, host.readFile(mapPath), mapPath); + return convertDocumentToSourceMapper(file, host.readFile(mapPath), mapPath); // TODO: GH#18217 } } return file.sourceMapper = ts.sourcemaps.identitySourceMapper; @@ -92476,7 +110098,7 @@ var ts; function getTargetOfMappedPosition(input, original) { if (original === void 0) { original = input; } var info = extract(input); - if (ts.endsWith(info.fileName, ".d.ts")) { + if (ts.endsWith(info.fileName, ".d.ts" /* Dts */)) { var file = program.getSourceFile(info.fileName); if (!file) { var path = ts.toPath(info.fileName, currentDirectory, getCanonicalFileName); @@ -92510,6 +110132,7 @@ var ts; function getTargetOfMappedDeclarationFiles(infos) { return ts.map(infos, function (d) { return getTargetOfMappedDeclarationInfo(d); }); } + /// Goto definition function getDefinitionAtPosition(fileName, position) { synchronizeHostData(); return getTargetOfMappedDeclarationFiles(ts.GoToDefinition.getDefinitionAtPosition(program, getValidSourceFile(fileName), position)); @@ -92532,6 +110155,7 @@ var ts; synchronizeHostData(); return getTargetOfMappedDeclarationFiles(ts.GoToDefinition.getTypeDefinitionAtPosition(program.getTypeChecker(), getValidSourceFile(fileName), position)); } + /// Goto implementation var getTargetOfMappedImplementationLocation = makeGetTargetOfMappedPosition(function (info) { return ({ fileName: info.fileName, position: info.textSpan.start }); }, function (newLoc, info) { return ({ fileName: newLoc.fileName, kind: info.kind, @@ -92550,11 +110174,12 @@ var ts; synchronizeHostData(); return getTargetOfMappedImplementationLocations(ts.FindAllReferences.getImplementationsAtPosition(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position)); } + /// References and Occurrences function getOccurrencesAtPosition(fileName, position) { return ts.flatMap(getDocumentHighlights(fileName, position, [fileName]), function (entry) { return entry.highlightSpans.map(function (highlightSpan) { return ({ fileName: entry.fileName, textSpan: highlightSpan.textSpan, - isWriteAccess: highlightSpan.kind === "writtenReference", + isWriteAccess: highlightSpan.kind === "writtenReference" /* writtenReference */, isDefinition: false, isInString: highlightSpan.isInString, }); }); }); @@ -92574,6 +110199,7 @@ var ts; } function getReferences(fileName, position, options) { synchronizeHostData(); + // Exclude default library when renaming as commonly user don't want to change that file. var sourceFiles = options && options.isForRename ? program.getSourceFiles().filter(function (sourceFile) { return !program.isSourceFileDefaultLibrary(sourceFile); }) : program.getSourceFiles(); @@ -92583,6 +110209,7 @@ var ts; synchronizeHostData(); return ts.FindAllReferences.findReferencedSymbols(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position); } + /// NavigateTo function getNavigateToItems(searchValue, maxResultCount, fileName, excludeDtsFiles) { if (excludeDtsFiles === void 0) { excludeDtsFiles = false; } synchronizeHostData(); @@ -92596,56 +110223,71 @@ var ts; var customTransformers = host.getCustomTransformers && host.getCustomTransformers(); return ts.getFileEmitOutput(program, sourceFile, emitOnlyDtsFiles, cancellationToken, customTransformers); } + // Signature help + /** + * This is a semantic operation. + */ function getSignatureHelpItems(fileName, position) { synchronizeHostData(); var sourceFile = getValidSourceFile(fileName); return ts.SignatureHelp.getSignatureHelpItems(program, sourceFile, position, cancellationToken); } + /// Syntactic features function getNonBoundSourceFile(fileName) { return syntaxTreeCache.getCurrentSourceFile(fileName); } function getNameOrDottedNameSpan(fileName, startPos, _endPos) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + // Get node at the location var node = ts.getTouchingPropertyName(sourceFile, startPos); if (node === sourceFile) { return undefined; } switch (node.kind) { - case 185: - case 146: - case 9: - case 86: - case 101: - case 95: - case 97: - case 99: - case 174: - case 71: + case 185 /* PropertyAccessExpression */: + case 146 /* QualifiedName */: + case 9 /* StringLiteral */: + case 86 /* FalseKeyword */: + case 101 /* TrueKeyword */: + case 95 /* NullKeyword */: + case 97 /* SuperKeyword */: + case 99 /* ThisKeyword */: + case 174 /* ThisType */: + case 71 /* Identifier */: break; + // Cant create the text span default: return undefined; } var nodeForStartPos = node; while (true) { if (ts.isRightSideOfPropertyAccess(nodeForStartPos) || ts.isRightSideOfQualifiedName(nodeForStartPos)) { + // If on the span is in right side of the the property or qualified name, return the span from the qualified name pos to end of this node nodeForStartPos = nodeForStartPos.parent; } else if (ts.isNameOfModuleDeclaration(nodeForStartPos)) { - if (nodeForStartPos.parent.parent.kind === 239 && + // If this is name of a module declarations, check if this is right side of dotted module name + // If parent of the module declaration which is parent of this node is module declaration and its body is the module declaration that this node is name of + // Then this name is name from dotted module + if (nodeForStartPos.parent.parent.kind === 239 /* ModuleDeclaration */ && nodeForStartPos.parent.parent.body === nodeForStartPos.parent) { + // Use parent module declarations name for start pos nodeForStartPos = nodeForStartPos.parent.parent.name; } else { + // We have to use this name for start pos break; } } else { + // Is not a member expression so we have found the node for start pos break; } } return ts.createTextSpanFromBounds(nodeForStartPos.getStart(), node.getEnd()); } function getBreakpointStatementAtPosition(fileName, position) { + // doesn't use compiler - no need to synchronize with host var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return ts.BreakpointResolver.spanInSourceFileAtLocation(sourceFile, position); } @@ -92657,10 +110299,11 @@ var ts; } function isTsOrTsxFile(fileName) { var kind = ts.getScriptKind(fileName, host); - return kind === 3 || kind === 4; + return kind === 3 /* TS */ || kind === 4 /* TSX */; } function getSemanticClassifications(fileName, span) { if (!isTsOrTsxFile(fileName)) { + // do not run semantic classification on non-ts-or-tsx files return []; } synchronizeHostData(); @@ -92668,33 +110311,38 @@ var ts; } function getEncodedSemanticClassifications(fileName, span) { if (!isTsOrTsxFile(fileName)) { - return { spans: [], endOfLineState: 0 }; + // do not run semantic classification on non-ts-or-tsx files + return { spans: [], endOfLineState: 0 /* None */ }; } synchronizeHostData(); return ts.getEncodedSemanticClassifications(program.getTypeChecker(), cancellationToken, getValidSourceFile(fileName), program.getClassifiableNames(), span); } function getSyntacticClassifications(fileName, span) { + // doesn't use compiler - no need to synchronize with host return ts.getSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span); } function getEncodedSyntacticClassifications(fileName, span) { + // doesn't use compiler - no need to synchronize with host return ts.getEncodedSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span); } function getOutliningSpans(fileName) { + // doesn't use compiler - no need to synchronize with host var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return ts.OutliningElementsCollector.collectElements(sourceFile, cancellationToken); } var braceMatching = ts.createMapFromTemplate((_a = {}, - _a[17] = 18, - _a[19] = 20, - _a[21] = 22, - _a[29] = 27, + _a[17 /* OpenBraceToken */] = 18 /* CloseBraceToken */, + _a[19 /* OpenParenToken */] = 20 /* CloseParenToken */, + _a[21 /* OpenBracketToken */] = 22 /* CloseBracketToken */, + _a[29 /* GreaterThanToken */] = 27 /* LessThanToken */, _a)); braceMatching.forEach(function (value, key) { return braceMatching.set(value.toString(), Number(key)); }); function getBraceMatchingAtPosition(fileName, position) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - var token = ts.getTouchingToken(sourceFile, position, false); + var token = ts.getTouchingToken(sourceFile, position, /*includeJsDocComment*/ false); var matchKind = token.getStart(sourceFile) === position ? braceMatching.get(token.kind.toString()) : undefined; var match = matchKind && ts.findChildOfKind(token.parent, matchKind, sourceFile); + // We want to order the braces when we return the result. return match ? [ts.createTextSpanFromNode(token, sourceFile), ts.createTextSpanFromNode(match, sourceFile)].sort(function (a, b) { return a.start - b.start; }) : ts.emptyArray; } function getIndentationAtPosition(fileName, position, editorOptions) { @@ -92774,29 +110422,37 @@ var ts; : Promise.reject("Host does not implement `installPackage`"); default: return ts.Debug.fail(); + // TODO: Debug.assertNever(action); will only work if there is more than one type. } } function getDocCommentTemplateAtPosition(fileName, position) { return ts.JsDoc.getDocCommentTemplateAtPosition(ts.getNewLineOrDefaultFromHost(host), syntaxTreeCache.getCurrentSourceFile(fileName), position); } function isValidBraceCompletionAtPosition(fileName, position, openingBrace) { - if (openingBrace === 60) { + // '<' is currently not supported, figuring out if we're in a Generic Type vs. a comparison is too + // expensive to do during typing scenarios + // i.e. whether we're dealing with: + // var x = new foo<| ( with class foo{} ) + // or + // var y = 3 <| + if (openingBrace === 60 /* lessThan */) { return false; } var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + // Check if in a context where we don't want to perform any insertion if (ts.isInString(sourceFile, position)) { return false; } if (ts.isInsideJsxElementOrAttribute(sourceFile, position)) { - return openingBrace === 123; + return openingBrace === 123 /* openBrace */; } if (ts.isInTemplateString(sourceFile, position)) { return false; } switch (openingBrace) { - case 39: - case 34: - case 96: + case 39 /* singleQuote */: + case 34 /* doubleQuote */: + case 96 /* backtick */: return !ts.isInComment(sourceFile, position); } return true; @@ -92806,7 +110462,7 @@ var ts; var token = ts.findPrecedingToken(position, sourceFile); if (!token) return undefined; - var element = token.kind === 29 && ts.isJsxOpeningElement(token.parent) ? token.parent.parent + var element = token.kind === 29 /* GreaterThanToken */ && ts.isJsxOpeningElement(token.parent) ? token.parent.parent : ts.isJsxText(token) ? token.parent : undefined; if (element && !ts.tagNamesAreEquivalent(element.openingElement.tagName, element.closingElement.tagName)) { return { newText: "" }; @@ -92818,20 +110474,46 @@ var ts; return range && ts.createTextSpanFromRange(range); } function getTodoComments(fileName, descriptors) { + // Note: while getting todo comments seems like a syntactic operation, we actually + // treat it as a semantic operation here. This is because we expect our host to call + // this on every single file. If we treat this syntactically, then that will cause + // us to populate and throw away the tree in our syntax tree cache for each file. By + // treating this as a semantic operation, we can access any tree without throwing + // anything away. synchronizeHostData(); var sourceFile = getValidSourceFile(fileName); cancellationToken.throwIfCancellationRequested(); var fileContents = sourceFile.text; var result = []; + // Exclude node_modules files as we don't want to show the todos of external libraries. if (descriptors.length > 0 && !isNodeModulesFile(sourceFile.fileName)) { var regExp = getTodoCommentsRegExp(); var matchArray = void 0; while (matchArray = regExp.exec(fileContents)) { cancellationToken.throwIfCancellationRequested(); + // If we got a match, here is what the match array will look like. Say the source text is: + // + // " // hack 1" + // + // The result array with the regexp: will be: + // + // ["// hack 1", "// ", "hack 1", undefined, "hack"] + // + // Here are the relevant capture groups: + // 0) The full match for the entire regexp. + // 1) The preamble to the message portion. + // 2) The message portion. + // 3...N) The descriptor that was matched - by index. 'undefined' for each + // descriptor that didn't match. an actual value if it did match. + // + // i.e. 'undefined' in position 3 above means TODO(jason) didn't match. + // "hack" in position 4 means HACK did match. var firstDescriptorCaptureIndex = 3; ts.Debug.assert(matchArray.length === descriptors.length + firstDescriptorCaptureIndex); var preamble = matchArray[1]; var matchPosition = matchArray.index + preamble.length; + // OK, we have found a match in the file. This is only an acceptable match if + // it is contained within a comment. if (!ts.isInComment(sourceFile, matchPosition)) { continue; } @@ -92843,6 +110525,8 @@ var ts; } if (descriptor === undefined) return ts.Debug.fail(); + // We don't want to match something like 'TODOBY', so we make sure a non + // letter/digit follows the match. if (isLetterOrDigit(fileContents.charCodeAt(matchPosition + descriptor.text.length))) { continue; } @@ -92855,21 +110539,59 @@ var ts; return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); } function getTodoCommentsRegExp() { + // NOTE: `?:` means 'non-capture group'. It allows us to have groups without having to + // filter them out later in the final result array. + // TODO comments can appear in one of the following forms: + // + // 1) // TODO or /////////// TODO + // + // 2) /* TODO or /********** TODO + // + // 3) /* + // * TODO + // */ + // + // The following three regexps are used to match the start of the text up to the TODO + // comment portion. var singleLineCommentStart = /(?:\/\/+\s*)/.source; var multiLineCommentStart = /(?:\/\*+\s*)/.source; var anyNumberOfSpacesAndAsterisksAtStartOfLine = /(?:^(?:\s|\*)*)/.source; + // Match any of the above three TODO comment start regexps. + // Note that the outermost group *is* a capture group. We want to capture the preamble + // so that we can determine the starting position of the TODO comment match. var preamble = "(" + anyNumberOfSpacesAndAsterisksAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")"; + // Takes the descriptors and forms a regexp that matches them as if they were literals. + // For example, if the descriptors are "TODO(jason)" and "HACK", then this will be: + // + // (?:(TODO\(jason\))|(HACK)) + // + // Note that the outermost group is *not* a capture group, but the innermost groups + // *are* capture groups. By capturing the inner literals we can determine after + // matching which descriptor we are dealing with. var literals = "(?:" + ts.map(descriptors, function (d) { return "(" + escapeRegExp(d.text) + ")"; }).join("|") + ")"; + // After matching a descriptor literal, the following regexp matches the rest of the + // text up to the end of the line (or */). var endOfLineOrEndOfComment = /(?:$|\*\/)/.source; var messageRemainder = /(?:.*?)/.source; + // This is the portion of the match we'll return as part of the TODO comment result. We + // match the literal portion up to the end of the line or end of comment. var messagePortion = "(" + literals + messageRemainder + ")"; var regExpString = preamble + messagePortion + endOfLineOrEndOfComment; + // The final regexp will look like this: + // /((?:\/\/+\s*)|(?:\/\*+\s*)|(?:^(?:\s|\*)*))((?:(TODO\(jason\))|(HACK))(?:.*?))(?:$|\*\/)/gim + // The flags of the regexp are important here. + // 'g' is so that we are doing a global search and can find matches several times + // in the input. + // + // 'i' is for case insensitivity (We do this to match C# TODO comment code). + // + // 'm' is so we can find matches in a multi-line input. return new RegExp(regExpString, "gim"); } function isLetterOrDigit(char) { - return (char >= 97 && char <= 122) || - (char >= 65 && char <= 90) || - (char >= 48 && char <= 57); + return (char >= 97 /* a */ && char <= 122 /* z */) || + (char >= 65 /* A */ && char <= 90 /* Z */) || + (char >= 48 /* _0 */ && char <= 57 /* _9 */); } function isNodeModulesFile(path) { return ts.stringContains(path, "/node_modules/"); @@ -92961,11 +110683,13 @@ var ts; }; } ts.createLanguageService = createLanguageService; + /* @internal */ + /** Names in the name table are escaped, so an identifier `__foo` will have a name table entry `___foo`. */ function getNameTable(sourceFile) { if (!sourceFile.nameTable) { initializeNameTable(sourceFile); } - return sourceFile.nameTable; + return sourceFile.nameTable; // TODO: GH#18217 } ts.getNameTable = getNameTable; function initializeNameTable(sourceFile) { @@ -92984,39 +110708,52 @@ var ts; } }); } + /** + * We want to store any numbers/strings if they were a name that could be + * related to a declaration. So, if we have 'import x = require("something")' + * then we want 'something' to be in the name table. Similarly, if we have + * "a['propname']" then we want to store "propname" in the name table. + */ function literalIsName(node) { return ts.isDeclarationName(node) || - node.parent.kind === 254 || + node.parent.kind === 254 /* ExternalModuleReference */ || isArgumentOfElementAccessExpression(node) || ts.isLiteralComputedPropertyDeclarationName(node); } + /** + * Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 } + */ + /* @internal */ function getContainingObjectLiteralElement(node) { switch (node.kind) { - case 9: - case 8: - if (node.parent.kind === 147) { + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: + if (node.parent.kind === 147 /* ComputedPropertyName */) { return ts.isObjectLiteralElement(node.parent.parent) ? node.parent.parent : undefined; } - case 71: + // falls through + case 71 /* Identifier */: return ts.isObjectLiteralElement(node.parent) && - (node.parent.parent.kind === 184 || node.parent.parent.kind === 263) && + (node.parent.parent.kind === 184 /* ObjectLiteralExpression */ || node.parent.parent.kind === 263 /* JsxAttributes */) && node.parent.name === node ? node.parent : undefined; } return undefined; } ts.getContainingObjectLiteralElement = getContainingObjectLiteralElement; + /* @internal */ function getPropertySymbolsFromContextualType(typeChecker, node) { var objectLiteral = node.parent; - var contextualType = typeChecker.getContextualType(objectLiteral); - return getPropertySymbolsFromType(contextualType, node.name); + var contextualType = typeChecker.getContextualType(objectLiteral); // TODO: GH#18217 + return getPropertySymbolsFromType(contextualType, node.name); // TODO: GH#18217 } ts.getPropertySymbolsFromContextualType = getPropertySymbolsFromContextualType; + /* @internal */ function getPropertySymbolsFromType(type, propName) { var name = ts.unescapeLeadingUnderscores(ts.getTextOfPropertyName(propName)); if (name && type) { var result_7 = []; var symbol = type.getProperty(name); - if (type.flags & 262144) { + if (type.flags & 262144 /* Union */) { ts.forEach(type.types, function (t) { var symbol = t.getProperty(name); if (symbol) { @@ -93036,10 +110773,16 @@ var ts; function isArgumentOfElementAccessExpression(node) { return node && node.parent && - node.parent.kind === 186 && + node.parent.kind === 186 /* ElementAccessExpression */ && node.parent.argumentExpression === node; } + /** + * Get the path of the default library files (lib.d.ts) as distributed with the typescript + * node package. + * The functionality is not supported if the ts module is consumed outside of a node module. + */ function getDefaultLibFilePath(options) { + // Check __dirname is defined and that we are on a node.js system. if (typeof __dirname !== "undefined") { return __dirname + ts.directorySeparator + ts.getDefaultLibFileName(options); } @@ -93048,26 +110791,39 @@ var ts; ts.getDefaultLibFilePath = getDefaultLibFilePath; ts.objectAllocator = getServicesObjectAllocator(); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var BreakpointResolver; (function (BreakpointResolver) { + /** + * Get the breakpoint span in given sourceFile + */ function spanInSourceFileAtLocation(sourceFile, position) { + // Cannot set breakpoint in dts file if (sourceFile.isDeclarationFile) { return undefined; } - var tokenAtLocation = ts.getTokenAtPosition(sourceFile, position, false); + var tokenAtLocation = ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); var lineOfPosition = sourceFile.getLineAndCharacterOfPosition(position).line; if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart(sourceFile)).line > lineOfPosition) { + // Get previous token if the token is returned starts on new line + // eg: let x =10; |--- cursor is here + // let y = 10; + // token at position will return let keyword on second line as the token but we would like to use + // token on same line if trailing trivia (comments or white spaces on same line) part of the last token on that line var preceding = ts.findPrecedingToken(tokenAtLocation.pos, sourceFile); + // It's a blank line if (!preceding || sourceFile.getLineAndCharacterOfPosition(preceding.getEnd()).line !== lineOfPosition) { return undefined; } tokenAtLocation = preceding; } - if (tokenAtLocation.flags & 4194304) { + // Cannot set breakpoint in ambient declarations + if (tokenAtLocation.flags & 4194304 /* Ambient */) { return undefined; } + // Get the span in the node based on its syntax return spanInNode(tokenAtLocation); function textSpan(startNode, endNode) { var start = startNode.decorators ? @@ -93097,229 +110853,292 @@ var ts; if (node) { var parent = node.parent; switch (node.kind) { - case 214: + case 214 /* VariableStatement */: + // Span on first variable declaration return spanInVariableDeclaration(node.declarationList.declarations[0]); - case 232: - case 152: - case 151: + case 232 /* VariableDeclaration */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: return spanInVariableDeclaration(node); - case 149: + case 149 /* Parameter */: return spanInParameterDeclaration(node); - case 234: - case 154: - case 153: - case 156: - case 157: - case 155: - case 192: - case 193: + case 234 /* FunctionDeclaration */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 155 /* Constructor */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: return spanInFunctionDeclaration(node); - case 213: + case 213 /* Block */: if (ts.isFunctionBlock(node)) { return spanInFunctionBlock(node); } - case 240: + // falls through + case 240 /* ModuleBlock */: return spanInBlock(node); - case 269: + case 269 /* CatchClause */: return spanInBlock(node.block); - case 216: + case 216 /* ExpressionStatement */: + // span on the expression return textSpan(node.expression); - case 225: + case 225 /* ReturnStatement */: + // span on return keyword and expression if present return textSpan(node.getChildAt(0), node.expression); - case 219: + case 219 /* WhileStatement */: + // Span on while(...) return textSpanEndingAtNextToken(node, node.expression); - case 218: + case 218 /* DoStatement */: + // span in statement of the do statement return spanInNode(node.statement); - case 231: + case 231 /* DebuggerStatement */: + // span on debugger keyword return textSpan(node.getChildAt(0)); - case 217: + case 217 /* IfStatement */: + // set on if(..) span return textSpanEndingAtNextToken(node, node.expression); - case 228: + case 228 /* LabeledStatement */: + // span in statement return spanInNode(node.statement); - case 224: - case 223: + case 224 /* BreakStatement */: + case 223 /* ContinueStatement */: + // On break or continue keyword and label if present return textSpan(node.getChildAt(0), node.label); - case 220: + case 220 /* ForStatement */: return spanInForStatement(node); - case 221: + case 221 /* ForInStatement */: + // span of for (a in ...) return textSpanEndingAtNextToken(node, node.expression); - case 222: + case 222 /* ForOfStatement */: + // span in initializer return spanInInitializerOfForLike(node); - case 227: + case 227 /* SwitchStatement */: + // span on switch(...) return textSpanEndingAtNextToken(node, node.expression); - case 266: - case 267: + case 266 /* CaseClause */: + case 267 /* DefaultClause */: + // span in first statement of the clause return spanInNode(node.statements[0]); - case 230: + case 230 /* TryStatement */: + // span in try block return spanInBlock(node.tryBlock); - case 229: + case 229 /* ThrowStatement */: + // span in throw ... return textSpan(node, node.expression); - case 249: + case 249 /* ExportAssignment */: + // span on export = id return textSpan(node, node.expression); - case 243: + case 243 /* ImportEqualsDeclaration */: + // import statement without including semicolon return textSpan(node, node.moduleReference); - case 244: + case 244 /* ImportDeclaration */: + // import statement without including semicolon return textSpan(node, node.moduleSpecifier); - case 250: + case 250 /* ExportDeclaration */: + // import statement without including semicolon return textSpan(node, node.moduleSpecifier); - case 239: - if (ts.getModuleInstanceState(node) !== 1) { + case 239 /* ModuleDeclaration */: + // span on complete module if it is instantiated + if (ts.getModuleInstanceState(node) !== 1 /* Instantiated */) { return undefined; } - case 235: - case 238: - case 273: - case 182: + // falls through + case 235 /* ClassDeclaration */: + case 238 /* EnumDeclaration */: + case 273 /* EnumMember */: + case 182 /* BindingElement */: + // span on complete node return textSpan(node); - case 226: + case 226 /* WithStatement */: + // span in statement return spanInNode(node.statement); - case 150: + case 150 /* Decorator */: return spanInNodeArray(parent.decorators); - case 180: - case 181: + case 180 /* ObjectBindingPattern */: + case 181 /* ArrayBindingPattern */: return spanInBindingPattern(node); - case 236: - case 237: + // No breakpoint in interface, type alias + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: return undefined; - case 25: - case 1: + // Tokens: + case 25 /* SemicolonToken */: + case 1 /* EndOfFileToken */: return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile)); - case 26: + case 26 /* CommaToken */: return spanInPreviousNode(node); - case 17: + case 17 /* OpenBraceToken */: return spanInOpenBraceToken(node); - case 18: + case 18 /* CloseBraceToken */: return spanInCloseBraceToken(node); - case 22: + case 22 /* CloseBracketToken */: return spanInCloseBracketToken(node); - case 19: + case 19 /* OpenParenToken */: return spanInOpenParenToken(node); - case 20: + case 20 /* CloseParenToken */: return spanInCloseParenToken(node); - case 56: + case 56 /* ColonToken */: return spanInColonToken(node); - case 29: - case 27: + case 29 /* GreaterThanToken */: + case 27 /* LessThanToken */: return spanInGreaterThanOrLessThanToken(node); - case 106: + // Keywords: + case 106 /* WhileKeyword */: return spanInWhileKeyword(node); - case 82: - case 74: - case 87: + case 82 /* ElseKeyword */: + case 74 /* CatchKeyword */: + case 87 /* FinallyKeyword */: return spanInNextNode(node); - case 145: + case 145 /* OfKeyword */: return spanInOfKeyword(node); default: + // Destructuring pattern in destructuring assignment + // [a, b, c] of + // [a, b, c] = expression if (ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node)) { return spanInArrayLiteralOrObjectLiteralDestructuringPattern(node); } - if ((node.kind === 71 || - node.kind === 204 || - node.kind === 270 || - node.kind === 271) && + // Set breakpoint on identifier element of destructuring pattern + // `a` or `...c` or `d: x` from + // `[a, b, ...c]` or `{ a, b }` or `{ d: x }` from destructuring pattern + if ((node.kind === 71 /* Identifier */ || + node.kind === 204 /* SpreadElement */ || + node.kind === 270 /* PropertyAssignment */ || + node.kind === 271 /* ShorthandPropertyAssignment */) && ts.isArrayLiteralOrObjectLiteralDestructuringPattern(parent)) { return textSpan(node); } - if (node.kind === 200) { + if (node.kind === 200 /* BinaryExpression */) { var _a = node, left = _a.left, operatorToken = _a.operatorToken; + // Set breakpoint in destructuring pattern if its destructuring assignment + // [a, b, c] or {a, b, c} of + // [a, b, c] = expression or + // {a, b, c} = expression if (ts.isArrayLiteralOrObjectLiteralDestructuringPattern(left)) { return spanInArrayLiteralOrObjectLiteralDestructuringPattern(left); } - if (operatorToken.kind === 58 && ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) { + if (operatorToken.kind === 58 /* EqualsToken */ && ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) { + // Set breakpoint on assignment expression element of destructuring pattern + // a = expression of + // [a = expression, b, c] = someExpression or + // { a = expression, b, c } = someExpression return textSpan(node); } - if (operatorToken.kind === 26) { + if (operatorToken.kind === 26 /* CommaToken */) { return spanInNode(left); } } if (ts.isExpressionNode(node)) { switch (parent.kind) { - case 218: + case 218 /* DoStatement */: + // Set span as if on while keyword return spanInPreviousNode(node); - case 150: + case 150 /* Decorator */: + // Set breakpoint on the decorator emit return spanInNode(node.parent); - case 220: - case 222: + case 220 /* ForStatement */: + case 222 /* ForOfStatement */: return textSpan(node); - case 200: - if (node.parent.operatorToken.kind === 26) { + case 200 /* BinaryExpression */: + if (node.parent.operatorToken.kind === 26 /* CommaToken */) { + // If this is a comma expression, the breakpoint is possible in this expression return textSpan(node); } break; - case 193: + case 193 /* ArrowFunction */: if (node.parent.body === node) { + // If this is body of arrow function, it is allowed to have the breakpoint return textSpan(node); } break; } } switch (node.parent.kind) { - case 270: + case 270 /* PropertyAssignment */: + // If this is name of property assignment, set breakpoint in the initializer if (node.parent.name === node && !ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.parent)) { return spanInNode(node.parent.initializer); } break; - case 190: + case 190 /* TypeAssertionExpression */: + // Breakpoint in type assertion goes to its operand if (node.parent.type === node) { return spanInNextNode(node.parent.type); } break; - case 232: - case 149: { + case 232 /* VariableDeclaration */: + case 149 /* Parameter */: { + // initializer of variable/parameter declaration go to previous node var _b = node.parent, initializer = _b.initializer, type = _b.type; if (initializer === node || type === node || ts.isAssignmentOperator(node.kind)) { return spanInPreviousNode(node); } break; } - case 200: { + case 200 /* BinaryExpression */: { var left = node.parent.left; if (ts.isArrayLiteralOrObjectLiteralDestructuringPattern(left) && node !== left) { + // If initializer of destructuring assignment move to previous token return spanInPreviousNode(node); } break; } default: + // return type of function go to previous token if (ts.isFunctionLike(node.parent) && node.parent.type === node) { return spanInPreviousNode(node); } } + // Default go to parent to set the breakpoint return spanInNode(node.parent); } } function textSpanFromVariableDeclaration(variableDeclaration) { if (ts.isVariableDeclarationList(variableDeclaration.parent) && variableDeclaration.parent.declarations[0] === variableDeclaration) { + // First declaration - include let keyword return textSpan(ts.findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent), variableDeclaration); } else { + // Span only on this declaration return textSpan(variableDeclaration); } } function spanInVariableDeclaration(variableDeclaration) { - if (variableDeclaration.parent.parent.kind === 221) { + // If declaration of for in statement, just set the span in parent + if (variableDeclaration.parent.parent.kind === 221 /* ForInStatement */) { return spanInNode(variableDeclaration.parent.parent); } var parent = variableDeclaration.parent; + // If this is a destructuring pattern, set breakpoint in binding pattern if (ts.isBindingPattern(variableDeclaration.name)) { return spanInBindingPattern(variableDeclaration.name); } + // Breakpoint is possible in variableDeclaration only if there is initialization + // or its declaration from 'for of' if (variableDeclaration.initializer || - ts.hasModifier(variableDeclaration, 1) || - parent.parent.kind === 222) { + ts.hasModifier(variableDeclaration, 1 /* Export */) || + parent.parent.kind === 222 /* ForOfStatement */) { return textSpanFromVariableDeclaration(variableDeclaration); } if (ts.isVariableDeclarationList(variableDeclaration.parent) && variableDeclaration.parent.declarations[0] !== variableDeclaration) { + // If we cannot set breakpoint on this declaration, set it on previous one + // Because the variable declaration may be binding pattern and + // we would like to set breakpoint in last binding element if that's the case, + // use preceding token instead return spanInNode(ts.findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent)); } } function canHaveSpanInParameterDeclaration(parameter) { + // Breakpoint is possible on parameter only if it has initializer, is a rest parameter, or has public or private modifier return !!parameter.initializer || parameter.dotDotDotToken !== undefined || - ts.hasModifier(parameter, 4 | 8); + ts.hasModifier(parameter, 4 /* Public */ | 8 /* Private */); } function spanInParameterDeclaration(parameter) { if (ts.isBindingPattern(parameter.name)) { + // Set breakpoint in binding pattern return spanInBindingPattern(parameter.name); } else if (canHaveSpanInParameterDeclaration(parameter)) { @@ -93330,24 +111149,29 @@ var ts; var indexOfParameter = functionDeclaration.parameters.indexOf(parameter); ts.Debug.assert(indexOfParameter !== -1); if (indexOfParameter !== 0) { + // Not a first parameter, go to previous parameter return spanInParameterDeclaration(functionDeclaration.parameters[indexOfParameter - 1]); } else { + // Set breakpoint in the function declaration body return spanInNode(functionDeclaration.body); } } } function canFunctionHaveSpanInWholeDeclaration(functionDeclaration) { - return ts.hasModifier(functionDeclaration, 1) || - (functionDeclaration.parent.kind === 235 && functionDeclaration.kind !== 155); + return ts.hasModifier(functionDeclaration, 1 /* Export */) || + (functionDeclaration.parent.kind === 235 /* ClassDeclaration */ && functionDeclaration.kind !== 155 /* Constructor */); } function spanInFunctionDeclaration(functionDeclaration) { + // No breakpoints in the function signature if (!functionDeclaration.body) { return undefined; } if (canFunctionHaveSpanInWholeDeclaration(functionDeclaration)) { + // Set the span on whole function declaration return textSpan(functionDeclaration); } + // Set span in function body return spanInNode(functionDeclaration.body); } function spanInFunctionBlock(block) { @@ -93359,28 +111183,34 @@ var ts; } function spanInBlock(block) { switch (block.parent.kind) { - case 239: - if (ts.getModuleInstanceState(block.parent) !== 1) { + case 239 /* ModuleDeclaration */: + if (ts.getModuleInstanceState(block.parent) !== 1 /* Instantiated */) { return undefined; } - case 219: - case 217: - case 221: + // falls through + // Set on parent if on same line otherwise on first statement + case 219 /* WhileStatement */: + case 217 /* IfStatement */: + case 221 /* ForInStatement */: return spanInNodeIfStartsOnSameLine(block.parent, block.statements[0]); - case 220: - case 222: + // Set span on previous token if it starts on same line otherwise on the first statement of the block + case 220 /* ForStatement */: + case 222 /* ForOfStatement */: return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(block.pos, sourceFile, block.parent), block.statements[0]); } + // Default action is to set on first statement return spanInNode(block.statements[0]); } function spanInInitializerOfForLike(forLikeStatement) { - if (forLikeStatement.initializer.kind === 233) { + if (forLikeStatement.initializer.kind === 233 /* VariableDeclarationList */) { + // Declaration list - set breakpoint in first declaration var variableDeclarationList = forLikeStatement.initializer; if (variableDeclarationList.declarations.length > 0) { return spanInNode(variableDeclarationList.declarations[0]); } } else { + // Expression - set breakpoint in it return spanInNode(forLikeStatement.initializer); } } @@ -93396,64 +111226,82 @@ var ts; } } function spanInBindingPattern(bindingPattern) { - var firstBindingElement = ts.forEach(bindingPattern.elements, function (element) { return element.kind !== 206 ? element : undefined; }); + // Set breakpoint in first binding element + var firstBindingElement = ts.forEach(bindingPattern.elements, function (element) { return element.kind !== 206 /* OmittedExpression */ ? element : undefined; }); if (firstBindingElement) { return spanInNode(firstBindingElement); } - if (bindingPattern.parent.kind === 182) { + // Empty binding pattern of binding element, set breakpoint on binding element + if (bindingPattern.parent.kind === 182 /* BindingElement */) { return textSpan(bindingPattern.parent); } + // Variable declaration is used as the span return textSpanFromVariableDeclaration(bindingPattern.parent); } function spanInArrayLiteralOrObjectLiteralDestructuringPattern(node) { - ts.Debug.assert(node.kind !== 181 && node.kind !== 180); - var elements = node.kind === 183 ? node.elements : node.properties; - var firstBindingElement = ts.forEach(elements, function (element) { return element.kind !== 206 ? element : undefined; }); + ts.Debug.assert(node.kind !== 181 /* ArrayBindingPattern */ && node.kind !== 180 /* ObjectBindingPattern */); + var elements = node.kind === 183 /* ArrayLiteralExpression */ ? node.elements : node.properties; + var firstBindingElement = ts.forEach(elements, function (element) { return element.kind !== 206 /* OmittedExpression */ ? element : undefined; }); if (firstBindingElement) { return spanInNode(firstBindingElement); } - return textSpan(node.parent.kind === 200 ? node.parent : node); + // Could be ArrayLiteral from destructuring assignment or + // just nested element in another destructuring assignment + // set breakpoint on assignment when parent is destructuring assignment + // Otherwise set breakpoint for this element + return textSpan(node.parent.kind === 200 /* BinaryExpression */ ? node.parent : node); } + // Tokens: function spanInOpenBraceToken(node) { switch (node.parent.kind) { - case 238: + case 238 /* EnumDeclaration */: var enumDeclaration = node.parent; return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile, node.parent), enumDeclaration.members.length ? enumDeclaration.members[0] : enumDeclaration.getLastToken(sourceFile)); - case 235: + case 235 /* ClassDeclaration */: var classDeclaration = node.parent; return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile, node.parent), classDeclaration.members.length ? classDeclaration.members[0] : classDeclaration.getLastToken(sourceFile)); - case 241: + case 241 /* CaseBlock */: return spanInNodeIfStartsOnSameLine(node.parent.parent, node.parent.clauses[0]); } + // Default to parent node return spanInNode(node.parent); } function spanInCloseBraceToken(node) { switch (node.parent.kind) { - case 240: - if (ts.getModuleInstanceState(node.parent.parent) !== 1) { + case 240 /* ModuleBlock */: + // If this is not an instantiated module block, no bp span + if (ts.getModuleInstanceState(node.parent.parent) !== 1 /* Instantiated */) { return undefined; } - case 238: - case 235: + // falls through + case 238 /* EnumDeclaration */: + case 235 /* ClassDeclaration */: + // Span on close brace token return textSpan(node); - case 213: + case 213 /* Block */: if (ts.isFunctionBlock(node.parent)) { + // Span on close brace token return textSpan(node); } - case 269: + // falls through + case 269 /* CatchClause */: return spanInNode(ts.lastOrUndefined(node.parent.statements)); - case 241: + case 241 /* CaseBlock */: + // breakpoint in last statement of the last clause var caseBlock = node.parent; var lastClause = ts.lastOrUndefined(caseBlock.clauses); if (lastClause) { return spanInNode(ts.lastOrUndefined(lastClause.statements)); } return undefined; - case 180: + case 180 /* ObjectBindingPattern */: + // Breakpoint in last binding element or binding pattern if it contains no elements var bindingPattern = node.parent; return spanInNode(ts.lastOrUndefined(bindingPattern.elements) || bindingPattern); + // Default to parent node default: if (ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) { + // Breakpoint in last binding element or binding pattern if it contains no elements var objectLiteral = node.parent; return textSpan(ts.lastOrUndefined(objectLiteral.properties) || objectLiteral); } @@ -93462,74 +111310,85 @@ var ts; } function spanInCloseBracketToken(node) { switch (node.parent.kind) { - case 181: + case 181 /* ArrayBindingPattern */: + // Breakpoint in last binding element or binding pattern if it contains no elements var bindingPattern = node.parent; return textSpan(ts.lastOrUndefined(bindingPattern.elements) || bindingPattern); default: if (ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) { + // Breakpoint in last binding element or binding pattern if it contains no elements var arrayLiteral = node.parent; return textSpan(ts.lastOrUndefined(arrayLiteral.elements) || arrayLiteral); } + // Default to parent node return spanInNode(node.parent); } } function spanInOpenParenToken(node) { - if (node.parent.kind === 218 || - node.parent.kind === 187 || - node.parent.kind === 188) { + if (node.parent.kind === 218 /* DoStatement */ || // Go to while keyword and do action instead + node.parent.kind === 187 /* CallExpression */ || + node.parent.kind === 188 /* NewExpression */) { return spanInPreviousNode(node); } - if (node.parent.kind === 191) { + if (node.parent.kind === 191 /* ParenthesizedExpression */) { return spanInNextNode(node); } + // Default to parent node return spanInNode(node.parent); } function spanInCloseParenToken(node) { + // Is this close paren token of parameter list, set span in previous token switch (node.parent.kind) { - case 192: - case 234: - case 193: - case 154: - case 153: - case 156: - case 157: - case 155: - case 219: - case 218: - case 220: - case 222: - case 187: - case 188: - case 191: + case 192 /* FunctionExpression */: + case 234 /* FunctionDeclaration */: + case 193 /* ArrowFunction */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 155 /* Constructor */: + case 219 /* WhileStatement */: + case 218 /* DoStatement */: + case 220 /* ForStatement */: + case 222 /* ForOfStatement */: + case 187 /* CallExpression */: + case 188 /* NewExpression */: + case 191 /* ParenthesizedExpression */: return spanInPreviousNode(node); + // Default to parent node default: return spanInNode(node.parent); } } function spanInColonToken(node) { + // Is this : specifying return annotation of the function declaration if (ts.isFunctionLike(node.parent) || - node.parent.kind === 270 || - node.parent.kind === 149) { + node.parent.kind === 270 /* PropertyAssignment */ || + node.parent.kind === 149 /* Parameter */) { return spanInPreviousNode(node); } return spanInNode(node.parent); } function spanInGreaterThanOrLessThanToken(node) { - if (node.parent.kind === 190) { + if (node.parent.kind === 190 /* TypeAssertionExpression */) { return spanInNextNode(node); } return spanInNode(node.parent); } function spanInWhileKeyword(node) { - if (node.parent.kind === 218) { + if (node.parent.kind === 218 /* DoStatement */) { + // Set span on while expression return textSpanEndingAtNextToken(node, node.parent.expression); } + // Default to parent node return spanInNode(node.parent); } function spanInOfKeyword(node) { - if (node.parent.kind === 222) { + if (node.parent.kind === 222 /* ForOfStatement */) { + // Set using next token return spanInNextNode(node); } + // Default to parent node return spanInNode(node.parent); } } @@ -93539,17 +111398,42 @@ var ts; })(ts || (ts = {})); var ts; (function (ts) { + /** + * Transform one or more nodes using the supplied transformers. + * @param source A single `Node` or an array of `Node` objects. + * @param transformers An array of `TransformerFactory` callbacks used to process the transformation. + * @param compilerOptions Optional compiler options. + */ function transform(source, transformers, compilerOptions) { var diagnostics = []; - compilerOptions = ts.fixupCompilerOptions(compilerOptions, diagnostics); + compilerOptions = ts.fixupCompilerOptions(compilerOptions, diagnostics); // TODO: GH#18217 var nodes = ts.isArray(source) ? source : [source]; - var result = ts.transformNodes(undefined, undefined, compilerOptions, nodes, transformers, true); + var result = ts.transformNodes(/*resolver*/ undefined, /*emitHost*/ undefined, compilerOptions, nodes, transformers, /*allowDtsFiles*/ true); result.diagnostics = ts.concatenate(result.diagnostics, diagnostics); return result; } ts.transform = transform; })(ts || (ts = {})); +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/* @internal */ var debugObjectHost = (function () { return this; })(); +// We need to use 'null' to interface with the managed side. +/* tslint:disable:no-null-keyword */ +/* tslint:disable:no-in-operator */ +/* @internal */ var ts; (function (ts) { function logInternalError(logger, err) { @@ -93557,7 +111441,7 @@ var ts; logger.log("*INTERNAL ERROR* - Exception in typescript services: " + err.message); } } - var ScriptSnapshotShimAdapter = (function () { + var ScriptSnapshotShimAdapter = /** @class */ (function () { function ScriptSnapshotShimAdapter(scriptSnapshotShim) { this.scriptSnapshotShim = scriptSnapshotShim; } @@ -93571,30 +111455,34 @@ var ts; var oldSnapshotShim = oldSnapshot; var encoded = this.scriptSnapshotShim.getChangeRange(oldSnapshotShim.scriptSnapshotShim); if (encoded === null) { - return null; + return null; // TODO: GH#18217 } - var decoded = JSON.parse(encoded); + var decoded = JSON.parse(encoded); // TODO: GH#18217 return ts.createTextChangeRange(ts.createTextSpan(decoded.span.start, decoded.span.length), decoded.newLength); }; ScriptSnapshotShimAdapter.prototype.dispose = function () { + // if scriptSnapshotShim is a COM object then property check becomes method call with no arguments + // 'in' does not have this effect if ("dispose" in this.scriptSnapshotShim) { - this.scriptSnapshotShim.dispose(); + this.scriptSnapshotShim.dispose(); // TODO: GH#18217 Can we just use `if (this.scriptSnapshotShim.dispose)`? } }; return ScriptSnapshotShimAdapter; }()); - var LanguageServiceShimHostAdapter = (function () { + var LanguageServiceShimHostAdapter = /** @class */ (function () { function LanguageServiceShimHostAdapter(shimHost) { var _this = this; this.shimHost = shimHost; this.loggingEnabled = false; this.tracingEnabled = false; + // if shimHost is a COM object then property check will become method call with no arguments. + // 'in' does not have this effect. if ("getModuleResolutionsForFile" in this.shimHost) { this.resolveModuleNames = function (moduleNames, containingFile) { - var resolutionsInFile = JSON.parse(_this.shimHost.getModuleResolutionsForFile(containingFile)); + var resolutionsInFile = JSON.parse(_this.shimHost.getModuleResolutionsForFile(containingFile)); // TODO: GH#18217 return ts.map(moduleNames, function (name) { var result = ts.getProperty(resolutionsInFile, name); - return result ? { resolvedFileName: result, extension: ts.extensionFromPath(result), isExternalLibraryImport: false } : undefined; + return result ? { resolvedFileName: result, extension: ts.extensionFromPath(result), isExternalLibraryImport: false } : undefined; // TODO: GH#18217 }); }; } @@ -93603,8 +111491,8 @@ var ts; } if ("getTypeReferenceDirectiveResolutionsForFile" in this.shimHost) { this.resolveTypeReferenceDirectives = function (typeDirectiveNames, containingFile) { - var typeDirectivesForFile = JSON.parse(_this.shimHost.getTypeReferenceDirectiveResolutionsForFile(containingFile)); - return ts.map(typeDirectiveNames, function (name) { return ts.getProperty(typeDirectivesForFile, name); }); + var typeDirectivesForFile = JSON.parse(_this.shimHost.getTypeReferenceDirectiveResolutionsForFile(containingFile)); // TODO: GH#18217 + return ts.map(typeDirectiveNames, function (name) { return ts.getProperty(typeDirectivesForFile, name); }); // TODO: GH#18217 }; } } @@ -93623,7 +111511,8 @@ var ts; }; LanguageServiceShimHostAdapter.prototype.getProjectVersion = function () { if (!this.shimHost.getProjectVersion) { - return undefined; + // shimmed host does not support getProjectVersion + return undefined; // TODO: GH#18217 } return this.shimHost.getProjectVersion(); }; @@ -93642,6 +111531,7 @@ var ts; throw Error("LanguageServiceShimHostAdapter.getCompilationSettings: empty compilationSettings"); } var compilerOptions = JSON.parse(settingsJson); + // permit language service to handle all files (filtering should be performed on the host side) compilerOptions.allowNonTsExtensions = true; return compilerOptions; }; @@ -93655,10 +111545,10 @@ var ts; }; LanguageServiceShimHostAdapter.prototype.getScriptKind = function (fileName) { if ("getScriptKind" in this.shimHost) { - return this.shimHost.getScriptKind(fileName); + return this.shimHost.getScriptKind(fileName); // TODO: GH#18217 } else { - return 0; + return 0 /* Unknown */; } }; LanguageServiceShimHostAdapter.prototype.getScriptVersion = function (fileName) { @@ -93691,7 +111581,7 @@ var ts; return this.shimHost.getDefaultLibFileName(JSON.stringify(options)); }; LanguageServiceShimHostAdapter.prototype.readDirectory = function (path, extensions, exclude, include, depth) { - var pattern = ts.getFileMatcherPatterns(path, exclude, include, this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory()); + var pattern = ts.getFileMatcherPatterns(path, exclude, include, this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory()); // TODO: GH#18217 return JSON.parse(this.shimHost.readDirectory(path, JSON.stringify(extensions), JSON.stringify(pattern.basePaths), pattern.excludePattern, pattern.includeFilePattern, pattern.includeDirectoryPattern, depth)); }; LanguageServiceShimHostAdapter.prototype.readFile = function (path, encoding) { @@ -93703,7 +111593,7 @@ var ts; return LanguageServiceShimHostAdapter; }()); ts.LanguageServiceShimHostAdapter = LanguageServiceShimHostAdapter; - var CoreServicesShimHostAdapter = (function () { + var CoreServicesShimHostAdapter = /** @class */ (function () { function CoreServicesShimHostAdapter(shimHost) { var _this = this; this.shimHost = shimHost; @@ -93712,11 +111602,11 @@ var ts; this.directoryExists = function (directoryName) { return _this.shimHost.directoryExists(directoryName); }; } if ("realpath" in this.shimHost) { - this.realpath = function (path) { return _this.shimHost.realpath(path); }; + this.realpath = function (path) { return _this.shimHost.realpath(path); }; // TODO: GH#18217 } } CoreServicesShimHostAdapter.prototype.readDirectory = function (rootDir, extensions, exclude, include, depth) { - var pattern = ts.getFileMatcherPatterns(rootDir, exclude, include, this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory()); + var pattern = ts.getFileMatcherPatterns(rootDir, exclude, include, this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory()); // TODO: GH#18217 return JSON.parse(this.shimHost.readDirectory(rootDir, JSON.stringify(extensions), JSON.stringify(pattern.basePaths), pattern.excludePattern, pattern.includeFilePattern, pattern.includeDirectoryPattern, depth)); }; CoreServicesShimHostAdapter.prototype.fileExists = function (fileName) { @@ -93752,7 +111642,7 @@ var ts; return result; } function forwardJSONCall(logger, actionDescription, action, logPerformance) { - return forwardCall(logger, actionDescription, true, action, logPerformance); + return forwardCall(logger, actionDescription, /*returnJson*/ true, action, logPerformance); } function forwardCall(logger, actionDescription, returnJson, action, logPerformance) { try { @@ -93768,7 +111658,7 @@ var ts; return JSON.stringify({ error: err }); } } - var ShimBase = (function () { + var ShimBase = /** @class */ (function () { function ShimBase(factory) { this.factory = factory; factory.registerShim(this); @@ -93792,7 +111682,7 @@ var ts; reportsUnnecessary: diagnostic.reportsUnnecessary, }; } - var LanguageServiceShimObject = (function (_super) { + var LanguageServiceShimObject = /** @class */ (function (_super) { __extends(LanguageServiceShimObject, _super); function LanguageServiceShimObject(factory, host, languageService) { var _this = _super.call(this, factory) || this; @@ -93805,10 +111695,16 @@ var ts; LanguageServiceShimObject.prototype.forwardJSONCall = function (actionDescription, action) { return forwardJSONCall(this.logger, actionDescription, action, this.logPerformance); }; + /// DISPOSE + /** + * Ensure (almost) deterministic release of internal Javascript resources when + * some external native objects holds onto us (e.g. Com/Interop). + */ LanguageServiceShimObject.prototype.dispose = function (dummy) { this.logger.log("dispose()"); this.languageService.dispose(); this.languageService = null; + // force a GC if (debugObjectHost && debugObjectHost.CollectGarbage) { debugObjectHost.CollectGarbage(); this.logger.log("CollectGarbage()"); @@ -93816,6 +111712,10 @@ var ts; this.logger = null; _super.prototype.dispose.call(this, dummy); }; + /// REFRESH + /** + * Update the list of scripts known to the compiler + */ LanguageServiceShimObject.prototype.refresh = function (throwOnError) { this.forwardJSONCall("refresh(" + throwOnError + ")", function () { return null; }); }; @@ -93840,11 +111740,17 @@ var ts; }; LanguageServiceShimObject.prototype.getEncodedSyntacticClassifications = function (fileName, start, length) { var _this = this; - return this.forwardJSONCall("getEncodedSyntacticClassifications('" + fileName + "', " + start + ", " + length + ")", function () { return convertClassifications(_this.languageService.getEncodedSyntacticClassifications(fileName, ts.createTextSpan(start, length))); }); + return this.forwardJSONCall("getEncodedSyntacticClassifications('" + fileName + "', " + start + ", " + length + ")", + // directly serialize the spans out to a string. This is much faster to decode + // on the managed side versus a full JSON array. + function () { return convertClassifications(_this.languageService.getEncodedSyntacticClassifications(fileName, ts.createTextSpan(start, length))); }); }; LanguageServiceShimObject.prototype.getEncodedSemanticClassifications = function (fileName, start, length) { var _this = this; - return this.forwardJSONCall("getEncodedSemanticClassifications('" + fileName + "', " + start + ", " + length + ")", function () { return convertClassifications(_this.languageService.getEncodedSemanticClassifications(fileName, ts.createTextSpan(start, length))); }); + return this.forwardJSONCall("getEncodedSemanticClassifications('" + fileName + "', " + start + ", " + length + ")", + // directly serialize the spans out to a string. This is much faster to decode + // on the managed side versus a full JSON array. + function () { return convertClassifications(_this.languageService.getEncodedSemanticClassifications(fileName, ts.createTextSpan(start, length))); }); }; LanguageServiceShimObject.prototype.getSyntacticDiagnostics = function (fileName) { var _this = this; @@ -93871,34 +111777,68 @@ var ts; return _this.realizeDiagnostics(diagnostics); }); }; + /// QUICKINFO + /** + * Computes a string representation of the type at the requested position + * in the active file. + */ LanguageServiceShimObject.prototype.getQuickInfoAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getQuickInfoAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getQuickInfoAtPosition(fileName, position); }); }; + /// NAMEORDOTTEDNAMESPAN + /** + * Computes span information of the name or dotted name at the requested position + * in the active file. + */ LanguageServiceShimObject.prototype.getNameOrDottedNameSpan = function (fileName, startPos, endPos) { var _this = this; return this.forwardJSONCall("getNameOrDottedNameSpan('" + fileName + "', " + startPos + ", " + endPos + ")", function () { return _this.languageService.getNameOrDottedNameSpan(fileName, startPos, endPos); }); }; + /** + * STATEMENTSPAN + * Computes span information of statement at the requested position in the active file. + */ LanguageServiceShimObject.prototype.getBreakpointStatementAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getBreakpointStatementAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getBreakpointStatementAtPosition(fileName, position); }); }; + /// SIGNATUREHELP LanguageServiceShimObject.prototype.getSignatureHelpItems = function (fileName, position) { var _this = this; return this.forwardJSONCall("getSignatureHelpItems('" + fileName + "', " + position + ")", function () { return _this.languageService.getSignatureHelpItems(fileName, position); }); }; + /// GOTO DEFINITION + /** + * Computes the definition location and file for the symbol + * at the requested position. + */ LanguageServiceShimObject.prototype.getDefinitionAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getDefinitionAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getDefinitionAtPosition(fileName, position); }); }; + /** + * Computes the definition location and file for the symbol + * at the requested position. + */ LanguageServiceShimObject.prototype.getDefinitionAndBoundSpan = function (fileName, position) { var _this = this; return this.forwardJSONCall("getDefinitionAndBoundSpan('" + fileName + "', " + position + ")", function () { return _this.languageService.getDefinitionAndBoundSpan(fileName, position); }); }; + /// GOTO Type + /** + * Computes the definition location of the type of the symbol + * at the requested position. + */ LanguageServiceShimObject.prototype.getTypeDefinitionAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getTypeDefinitionAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getTypeDefinitionAtPosition(fileName, position); }); }; + /// GOTO Implementation + /** + * Computes the implementation location of the symbol + * at the requested position. + */ LanguageServiceShimObject.prototype.getImplementationAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getImplementationAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getImplementationAtPosition(fileName, position); }); @@ -93911,6 +111851,7 @@ var ts; var _this = this; return this.forwardJSONCall("findRenameLocations('" + fileName + "', " + position + ", " + findInStrings + ", " + findInComments + ")", function () { return _this.languageService.findRenameLocations(fileName, position, findInStrings, findInComments); }); }; + /// GET BRACE MATCHING LanguageServiceShimObject.prototype.getBraceMatchingAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getBraceMatchingAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getBraceMatchingAtPosition(fileName, position); }); @@ -93923,13 +111864,15 @@ var ts; var _this = this; return this.forwardJSONCall("getSpanOfEnclosingComment('" + fileName + "', " + position + ")", function () { return _this.languageService.getSpanOfEnclosingComment(fileName, position, onlyMultiLine); }); }; - LanguageServiceShimObject.prototype.getIndentationAtPosition = function (fileName, position, options) { + /// GET SMART INDENT + LanguageServiceShimObject.prototype.getIndentationAtPosition = function (fileName, position, options /*Services.EditorOptions*/) { var _this = this; return this.forwardJSONCall("getIndentationAtPosition('" + fileName + "', " + position + ")", function () { var localOptions = JSON.parse(options); return _this.languageService.getIndentationAtPosition(fileName, position, localOptions); }); }; + /// GET REFERENCES LanguageServiceShimObject.prototype.getReferencesAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getReferencesAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getReferencesAtPosition(fileName, position); }); @@ -93946,14 +111889,22 @@ var ts; var _this = this; return this.forwardJSONCall("getDocumentHighlights('" + fileName + "', " + position + ")", function () { var results = _this.languageService.getDocumentHighlights(fileName, position, JSON.parse(filesToSearch)); + // workaround for VS document highlighting issue - keep only items from the initial file var normalizedName = ts.normalizeSlashes(fileName).toLowerCase(); return ts.filter(results, function (r) { return ts.normalizeSlashes(r.fileName).toLowerCase() === normalizedName; }); }); }; + /// COMPLETION LISTS + /** + * Get a string based representation of the completions + * to provide at the given source position and providing a member completion + * list if requested. + */ LanguageServiceShimObject.prototype.getCompletionsAtPosition = function (fileName, position, preferences) { var _this = this; return this.forwardJSONCall("getCompletionsAtPosition('" + fileName + "', " + position + ", " + preferences + ")", function () { return _this.languageService.getCompletionsAtPosition(fileName, position, preferences); }); }; + /** Get a string based representation of a completion list entry details */ LanguageServiceShimObject.prototype.getCompletionEntryDetails = function (fileName, position, entryName, formatOptions, source, preferences) { var _this = this; return this.forwardJSONCall("getCompletionEntryDetails('" + fileName + "', " + position + ", '" + entryName + "')", function () { @@ -93961,21 +111912,21 @@ var ts; return _this.languageService.getCompletionEntryDetails(fileName, position, entryName, localOptions, source, preferences); }); }; - LanguageServiceShimObject.prototype.getFormattingEditsForRange = function (fileName, start, end, options) { + LanguageServiceShimObject.prototype.getFormattingEditsForRange = function (fileName, start, end, options /*Services.FormatCodeOptions*/) { var _this = this; return this.forwardJSONCall("getFormattingEditsForRange('" + fileName + "', " + start + ", " + end + ")", function () { var localOptions = JSON.parse(options); return _this.languageService.getFormattingEditsForRange(fileName, start, end, localOptions); }); }; - LanguageServiceShimObject.prototype.getFormattingEditsForDocument = function (fileName, options) { + LanguageServiceShimObject.prototype.getFormattingEditsForDocument = function (fileName, options /*Services.FormatCodeOptions*/) { var _this = this; return this.forwardJSONCall("getFormattingEditsForDocument('" + fileName + "')", function () { var localOptions = JSON.parse(options); return _this.languageService.getFormattingEditsForDocument(fileName, localOptions); }); }; - LanguageServiceShimObject.prototype.getFormattingEditsAfterKeystroke = function (fileName, position, key, options) { + LanguageServiceShimObject.prototype.getFormattingEditsAfterKeystroke = function (fileName, position, key, options /*Services.FormatCodeOptions*/) { var _this = this; return this.forwardJSONCall("getFormattingEditsAfterKeystroke('" + fileName + "', " + position + ", '" + key + "')", function () { var localOptions = JSON.parse(options); @@ -93986,6 +111937,8 @@ var ts; var _this = this; return this.forwardJSONCall("getDocCommentTemplateAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getDocCommentTemplateAtPosition(fileName, position); }); }; + /// NAVIGATE TO + /** Return a list of symbols that are interesting to navigate to */ LanguageServiceShimObject.prototype.getNavigateToItems = function (searchValue, maxResultCount, fileName) { var _this = this; return this.forwardJSONCall("getNavigateToItems('" + searchValue + "', " + maxResultCount + ", " + fileName + ")", function () { return _this.languageService.getNavigateToItems(searchValue, maxResultCount, fileName); }); @@ -94006,20 +111959,22 @@ var ts; var _this = this; return this.forwardJSONCall("getTodoComments('" + fileName + "')", function () { return _this.languageService.getTodoComments(fileName, JSON.parse(descriptors)); }); }; + /// Emit LanguageServiceShimObject.prototype.getEmitOutput = function (fileName) { var _this = this; return this.forwardJSONCall("getEmitOutput('" + fileName + "')", function () { return _this.languageService.getEmitOutput(fileName); }); }; LanguageServiceShimObject.prototype.getEmitOutputObject = function (fileName) { var _this = this; - return forwardCall(this.logger, "getEmitOutput('" + fileName + "')", false, function () { return _this.languageService.getEmitOutput(fileName); }, this.logPerformance); + return forwardCall(this.logger, "getEmitOutput('" + fileName + "')", + /*returnJson*/ false, function () { return _this.languageService.getEmitOutput(fileName); }, this.logPerformance); }; return LanguageServiceShimObject; }(ShimBase)); function convertClassifications(classifications) { return { spans: classifications.spans.join(","), endOfLineState: classifications.endOfLineState }; } - var ClassifierShimObject = (function (_super) { + var ClassifierShimObject = /** @class */ (function (_super) { __extends(ClassifierShimObject, _super); function ClassifierShimObject(factory, logger) { var _this = _super.call(this, factory) || this; @@ -94033,6 +111988,7 @@ var ts; if (syntacticClassifierAbsent === void 0) { syntacticClassifierAbsent = false; } return forwardJSONCall(this.logger, "getEncodedLexicalClassifications", function () { return convertClassifications(_this.classifier.getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent)); }, this.logPerformance); }; + /// COLORIZATION ClassifierShimObject.prototype.getClassificationsForLine = function (text, lexState, classifyKeywordsInGenerics) { if (classifyKeywordsInGenerics === void 0) { classifyKeywordsInGenerics = false; } var classification = this.classifier.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics); @@ -94047,7 +112003,7 @@ var ts; }; return ClassifierShimObject; }(ShimBase)); - var CoreServicesShimObject = (function (_super) { + var CoreServicesShimObject = /** @class */ (function (_super) { __extends(CoreServicesShimObject, _super); function CoreServicesShimObject(factory, logger, host) { var _this = _super.call(this, factory) || this; @@ -94065,7 +112021,7 @@ var ts; var compilerOptions = JSON.parse(compilerOptionsJson); var result = ts.resolveModuleName(moduleName, ts.normalizeSlashes(fileName), compilerOptions, _this.host); var resolvedFileName = result.resolvedModule ? result.resolvedModule.resolvedFileName : undefined; - if (result.resolvedModule && result.resolvedModule.extension !== ".ts" && result.resolvedModule.extension !== ".tsx" && result.resolvedModule.extension !== ".d.ts") { + if (result.resolvedModule && result.resolvedModule.extension !== ".ts" /* Ts */ && result.resolvedModule.extension !== ".tsx" /* Tsx */ && result.resolvedModule.extension !== ".d.ts" /* Dts */) { resolvedFileName = undefined; } return { @@ -94089,7 +112045,8 @@ var ts; CoreServicesShimObject.prototype.getPreProcessedFileInfo = function (fileName, sourceTextSnapshot) { var _this = this; return this.forwardJSONCall("getPreProcessedFileInfo('" + fileName + "')", function () { - var result = ts.preProcessFile(ts.getSnapshotText(sourceTextSnapshot), true, true); + // for now treat files as JavaScript + var result = ts.preProcessFile(ts.getSnapshotText(sourceTextSnapshot), /* readImportFiles */ true, /* detectJavaScriptImports */ true); return { referencedFiles: _this.convertFileReferences(result.referencedFiles), importedFiles: _this.convertFileReferences(result.importedFiles), @@ -94127,7 +112084,7 @@ var ts; return this.forwardJSONCall("getTSConfigFileInfo('" + fileName + "')", function () { var result = ts.parseJsonText(fileName, ts.getSnapshotText(sourceTextSnapshot)); var normalizedFileName = ts.normalizeSlashes(fileName); - var configFile = ts.parseJsonSourceFileConfigFileContent(result, _this.host, ts.getDirectoryPath(normalizedFileName), {}, normalizedFileName); + var configFile = ts.parseJsonSourceFileConfigFileContent(result, _this.host, ts.getDirectoryPath(normalizedFileName), /*existingOptions*/ {}, normalizedFileName); return { options: configFile.options, typeAcquisition: configFile.typeAcquisition, @@ -94142,7 +112099,7 @@ var ts; }; CoreServicesShimObject.prototype.discoverTypings = function (discoverTypingsJson) { var _this = this; - var getCanonicalFileName = ts.createGetCanonicalFileName(false); + var getCanonicalFileName = ts.createGetCanonicalFileName(/*useCaseSensitivefileNames:*/ false); return this.forwardJSONCall("discoverTypings()", function () { var info = JSON.parse(discoverTypingsJson); if (_this.safeList === undefined) { @@ -94153,10 +112110,13 @@ var ts; }; return CoreServicesShimObject; }(ShimBase)); - var TypeScriptServicesFactory = (function () { + var TypeScriptServicesFactory = /** @class */ (function () { function TypeScriptServicesFactory() { this._shims = []; } + /* + * Returns script API version. + */ TypeScriptServicesFactory.prototype.getServicesVersion = function () { return ts.servicesVersion; }; @@ -94166,7 +112126,7 @@ var ts; this.documentRegistry = ts.createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory()); } var hostAdapter = new LanguageServiceShimHostAdapter(host); - var languageService = ts.createLanguageService(hostAdapter, this.documentRegistry, false); + var languageService = ts.createLanguageService(hostAdapter, this.documentRegistry, /*syntaxOnly*/ false); return new LanguageServiceShimObject(this, host, languageService); } catch (err) { @@ -94194,6 +112154,7 @@ var ts; } }; TypeScriptServicesFactory.prototype.close = function () { + // Forget all the registered shims ts.clear(this._shims); this.documentRegistry = undefined; }; @@ -94216,6 +112177,10 @@ var ts; module.exports = ts; } })(ts || (ts = {})); +/* tslint:enable:no-in-operator */ +/* tslint:enable:no-null */ +/// TODO: this is used by VS, clean this up on both sides of the interface +/* @internal */ var TypeScript; (function (TypeScript) { var Services; @@ -94223,6 +112188,8 @@ var TypeScript; Services.TypeScriptServicesFactory = ts.TypeScriptServicesFactory; })(Services = TypeScript.Services || (TypeScript.Services = {})); })(TypeScript || (TypeScript = {})); +// 'toolsVersion' gets consumed by the managed side, so it's not unused. +// TODO: it should be moved into a namespace though. +/* @internal */ var toolsVersion = ts.versionMajorMinor; - -//# sourceMappingURL=typescriptServices.js.map +//# sourceMappingURL=typescriptServices.js.map \ No newline at end of file diff --git a/lib/typescriptServices.d.ts b/lib/typescriptServices.d.ts index c01093525e8..7ad35c1c637 100644 --- a/lib/typescriptServices.d.ts +++ b/lib/typescriptServices.d.ts @@ -16,15 +16,22 @@ and limitations under the License. declare namespace ts { const versionMajorMinor = "3.0"; + /** The version of the TypeScript compiler release */ const version: string; } declare namespace ts { + /** + * Type of objects whose values are all of the same type. + * The `in` and `for-in` operators can *not* be safely used, + * since `Object.prototype` may be modified by outside code. + */ interface MapLike { [index: string]: T; } interface SortedArray extends Array { " __sortedArrayBrand": any; } + /** ES6 Map interface, only read methods included. */ interface ReadonlyMap { get(key: string): T | undefined; has(key: string): boolean; @@ -34,11 +41,13 @@ declare namespace ts { values(): Iterator; entries(): Iterator<[string, T]>; } + /** ES6 Map interface. */ interface Map extends ReadonlyMap { set(key: string, value: T): this; delete(key: string): boolean; clear(): void; } + /** ES6 Iterator type. */ interface Iterator { next(): { value: T; @@ -48,6 +57,7 @@ declare namespace ts { done: true; }; } + /** Array that is only intended to be pushed to, never read. */ interface Push { push(...values: T[]): void; } @@ -452,7 +462,9 @@ declare namespace ts { } enum JsxFlags { None = 0, + /** An element from a named property of the JSX.IntrinsicElements interface */ IntrinsicNamedElement = 1, + /** An element inferred from the string index signature of the JSX.IntrinsicElements interface */ IntrinsicIndexedElement = 2, IntrinsicElement = 3 } @@ -492,6 +504,10 @@ declare namespace ts { type ModifiersArray = NodeArray; interface Identifier extends PrimaryExpression, Declaration { kind: SyntaxKind.Identifier; + /** + * Prefer to use `id.unescapedText`. (Note: This is available only in services, not internally to the TypeScript compiler.) + * Text of identifier, but if the identifier begins with two underscores, this will begin with three. + */ escapedText: __String; originalKeywordKind?: SyntaxKind; isInJSDocNamespace?: boolean; @@ -635,6 +651,14 @@ declare namespace ts { } type BindingPattern = ObjectBindingPattern | ArrayBindingPattern; type ArrayBindingElement = BindingElement | OmittedExpression; + /** + * Several node kinds share function-like features such as a signature, + * a name, and a body. These nodes should extend FunctionLikeDeclarationBase. + * Examples: + * - FunctionDeclaration + * - MethodDeclaration + * - AccessorDeclaration + */ interface FunctionLikeDeclarationBase extends SignatureDeclarationBase { _functionLikeDeclarationBrand: any; asteriskToken?: AsteriskToken; @@ -642,6 +666,7 @@ declare namespace ts { body?: Block | Expression; } type FunctionLikeDeclaration = FunctionDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ConstructorDeclaration | FunctionExpression | ArrowFunction; + /** @deprecated Use SignatureDeclaration */ type FunctionLike = SignatureDeclaration; interface FunctionDeclaration extends FunctionLikeDeclarationBase, DeclarationStatement { kind: SyntaxKind.FunctionDeclaration; @@ -664,6 +689,7 @@ declare namespace ts { parent: ClassLikeDeclaration; body?: FunctionBody; } + /** For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. */ interface SemicolonClassElement extends ClassElement { kind: SyntaxKind.SemicolonClassElement; parent: ClassLikeDeclaration; @@ -803,6 +829,7 @@ declare namespace ts { interface UnaryExpression extends Expression { _unaryExpressionBrand: any; } + /** Deprecated, please use UpdateExpression */ type IncrementExpression = UpdateExpression; interface UpdateExpression extends UnaryExpression { _updateExpressionBrand: any; @@ -984,6 +1011,12 @@ declare namespace ts { parent: ArrayLiteralExpression | CallExpression | NewExpression; expression: Expression; } + /** + * This interface is a base interface for ObjectLiteralExpression and JSXAttributes to extend from. JSXAttributes is similar to + * ObjectLiteralExpression in that it contains array of properties; however, JSXAttributes' properties can only be + * JSXAttribute or JSXSpreadAttribute. ObjectLiteralExpression, on the other hand, can only have properties of type + * ObjectLiteralElement (e.g. PropertyAssignment, ShorthandPropertyAssignment etc.) + */ interface ObjectLiteralExpressionBase extends PrimaryExpression, Declaration { properties: NodeArray; } @@ -1000,6 +1033,7 @@ declare namespace ts { interface SuperPropertyAccessExpression extends PropertyAccessExpression { expression: SuperExpression; } + /** Brand for a PropertyAccessExpression which, like a QualifiedName, consists of a sequence of identifiers separated by dots. */ interface PropertyAccessEntityNameExpression extends PropertyAccessExpression { _propertyAccessExpressionLikeQualifiedNameBrand?: any; expression: EntityNameExpression; @@ -1136,6 +1170,9 @@ declare namespace ts { interface NotEmittedStatement extends Statement { kind: SyntaxKind.NotEmittedStatement; } + /** + * A list of comma-separated expressions. This node is only created by transformations. + */ interface CommaListExpression extends Expression { kind: SyntaxKind.CommaListExpression; elements: NodeArray; @@ -1272,6 +1309,7 @@ declare namespace ts { } interface ClassDeclaration extends ClassLikeDeclarationBase, DeclarationStatement { kind: SyntaxKind.ClassDeclaration; + /** May be undefined in `export default class { ... }`. */ name?: Identifier; } interface ClassExpression extends ClassLikeDeclarationBase, PrimaryExpression { @@ -1341,6 +1379,11 @@ declare namespace ts { statements: NodeArray; } type ModuleReference = EntityName | ExternalModuleReference; + /** + * One of: + * - import x = require("mod"); + * - import x = M.x; + */ interface ImportEqualsDeclaration extends DeclarationStatement, JSDocContainer { kind: SyntaxKind.ImportEqualsDeclaration; parent: SourceFile | ModuleBlock; @@ -1356,6 +1399,7 @@ declare namespace ts { kind: SyntaxKind.ImportDeclaration; parent: SourceFile | ModuleBlock; importClause?: ImportClause; + /** If this is not a StringLiteral it will be a grammar error. */ moduleSpecifier: Expression; } type NamedImportBindings = NamespaceImport | NamedImports; @@ -1377,7 +1421,9 @@ declare namespace ts { interface ExportDeclaration extends DeclarationStatement { kind: SyntaxKind.ExportDeclaration; parent: SourceFile | ModuleBlock; + /** Will not be assigned in the case of `export * from "foo";` */ exportClause?: NamedExports; + /** If this is not a StringLiteral it will be a grammar error. */ moduleSpecifier?: Expression; } interface NamedImports extends Node { @@ -1404,6 +1450,10 @@ declare namespace ts { name: Identifier; } type ImportOrExportSpecifier = ImportSpecifier | ExportSpecifier; + /** + * This is either an `export =` or an `export default` declaration. + * Unless `isExportEquals` is set, this node was parsed as an `export default`. + */ interface ExportAssignment extends DeclarationStatement { kind: SyntaxKind.ExportAssignment; parent: SourceFile; @@ -1474,6 +1524,10 @@ declare namespace ts { interface JSDocUnknownTag extends JSDocTag { kind: SyntaxKind.JSDocTag; } + /** + * Note that `@extends` is a synonym of `@augments`. + * Both tags are represented by this interface. + */ interface JSDocAugmentsTag extends JSDocTag { kind: SyntaxKind.JSDocAugmentsTag; class: ExpressionWithTypeArguments & { @@ -1523,6 +1577,7 @@ declare namespace ts { parent: JSDoc; name: EntityName; typeExpression?: JSDocTypeExpression; + /** Whether the property name came before the type -- non-standard for JSDoc, but Typescript-like */ isNameFirst: boolean; isBracketed: boolean; } @@ -1535,6 +1590,7 @@ declare namespace ts { interface JSDocTypeLiteral extends JSDocType { kind: SyntaxKind.JSDocTypeLiteral; jsDocPropertyTags?: ReadonlyArray; + /** If true, then this type literal represents an *array* of its type. */ isArrayType?: boolean; } enum FlowFlags { @@ -1615,6 +1671,14 @@ declare namespace ts { libReferenceDirectives: ReadonlyArray; languageVariant: LanguageVariant; isDeclarationFile: boolean; + /** + * lib.d.ts should have a reference comment like + * + * /// + * + * 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. + */ hasNoDefaultLib: boolean; languageVersion: ScriptTarget; } @@ -1661,9 +1725,18 @@ declare namespace ts { interface ParseConfigHost { useCaseSensitiveFileNames: boolean; readDirectory(rootDir: string, extensions: ReadonlyArray, excludes: ReadonlyArray | undefined, includes: ReadonlyArray, depth?: number): string[]; + /** + * Gets a value indicating whether the specified path exists and is a file. + * @param path The path to test. + */ fileExists(path: string): boolean; readFile(path: string): string | undefined; } + /** + * Branded string for keeping track of when we've turned an ambiguous path + * specified like "./blah" to an absolute path to an actual + * tsconfig file, e.g. "/root/blah/tsconfig.json" + */ type ResolvedConfigFileName = string & { _isResolvedConfigFileName: never; }; @@ -1672,18 +1745,39 @@ declare namespace ts { } interface CancellationToken { isCancellationRequested(): boolean; + /** @throws OperationCanceledException if isCancellationRequested is true */ throwIfCancellationRequested(): void; } interface Program extends ScriptReferenceHost { + /** + * Get a list of root file names that were passed to a 'createProgram' + */ getRootFileNames(): ReadonlyArray; + /** + * Get a list of files in the program + */ getSourceFiles(): ReadonlyArray; + /** + * Emits the JavaScript and declaration files. If targetSourceFile is not specified, then + * the JavaScript and declaration files will be produced for all the files in this program. + * If targetSourceFile is specified, then only the JavaScript and declaration for that + * specific file will be generated. + * + * If writeFile is not specified then the writeFile callback from the compiler host will be + * used for writing the JavaScript and declaration files. Otherwise, the writeFile parameter + * will be invoked when writing the JavaScript and declaration files. + */ emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult; getOptionsDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray; getGlobalDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray; getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray; + /** The first time this is called, it will return global diagnostics (no location). */ getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray; getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray; getConfigFileParsingDiagnostics(): ReadonlyArray; + /** + * Gets a type checker that can be used to semantically analyze source files in the program. + */ getTypeChecker(): TypeChecker; isSourceFileFromExternalLibrary(file: SourceFile): boolean; getProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined; @@ -1693,16 +1787,25 @@ declare namespace ts { sourceFile: SourceFile; } interface CustomTransformers { + /** Custom transformers to evaluate before built-in .js transformations. */ before?: TransformerFactory[]; + /** Custom transformers to evaluate after built-in .js transformations. */ after?: TransformerFactory[]; + /** Custom transformers to evaluate after built-in .d.ts transformations. */ afterDeclarations?: TransformerFactory[]; } interface SourceMapSpan { + /** Line number in the .js file. */ emittedLine: number; + /** Column number in the .js file. */ emittedColumn: number; + /** Line number in the .ts file. */ sourceLine: number; + /** Column number in the .ts file. */ sourceColumn: number; + /** Optional name (index into names array) associated with this span. */ nameIndex?: number; + /** .ts file (index into sources array) associated with this span */ sourceIndex: number; } interface SourceMapData { @@ -1717,6 +1820,7 @@ declare namespace ts { sourceMapMappings: string; sourceMapDecodedMappings: SourceMapSpan[]; } + /** Return code used by getEmitOutput function to indicate status of the function */ enum ExitStatus { Success = 0, DiagnosticsPresent_OutputsSkipped = 1, @@ -1724,6 +1828,7 @@ declare namespace ts { } interface EmitResult { emitSkipped: boolean; + /** Contains declaration emit diagnostics */ diagnostics: ReadonlyArray; emittedFiles?: string[]; } @@ -1741,21 +1846,41 @@ declare namespace ts { getReturnTypeOfSignature(signature: Signature): Type; getNullableType(type: Type, flags: TypeFlags): Type; getNonNullableType(type: Type): Type; + /** Note that the resulting nodes cannot be checked. */ typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeNode | undefined; + /** Note that the resulting nodes cannot be checked. */ signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): (SignatureDeclaration & { typeArguments?: NodeArray; }) | undefined; + /** Note that the resulting nodes cannot be checked. */ indexInfoToIndexSignatureDeclaration(indexInfo: IndexInfo, kind: IndexKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): IndexSignatureDeclaration | undefined; + /** Note that the resulting nodes cannot be checked. */ symbolToEntityName(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): EntityName | undefined; + /** Note that the resulting nodes cannot be checked. */ symbolToExpression(symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): Expression | undefined; + /** Note that the resulting nodes cannot be checked. */ symbolToTypeParameterDeclarations(symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): NodeArray | undefined; + /** Note that the resulting nodes cannot be checked. */ symbolToParameterDeclaration(symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): ParameterDeclaration | undefined; + /** Note that the resulting nodes cannot be checked. */ typeParameterToDeclaration(parameter: TypeParameter, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeParameterDeclaration | undefined; getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[]; getSymbolAtLocation(node: Node): Symbol | undefined; getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[]; + /** + * The function returns the value (local variable) symbol of an identifier in the short-hand property assignment. + * This is necessary as an identifier in short-hand property assignment can contains two meaning: property name and property value. + */ getShorthandAssignmentValueSymbol(location: Node): Symbol | undefined; getExportSpecifierLocalTargetSymbol(location: ExportSpecifier): Symbol | undefined; + /** + * If a symbol is a local symbol with an associated exported symbol, returns the exported symbol. + * Otherwise returns its input. + * For example, at `export type T = number;`: + * - `getSymbolAtLocation` at the location `T` will return the exported symbol for `T`. + * - But the result of `getSymbolsInScope` will contain the *local* symbol for `T`, not the exported symbol. + * - Calling `getExportSymbolOfSymbol` on that local symbol will return the exported symbol. + */ getExportSymbolOfSymbol(symbol: Symbol): Symbol; getPropertySymbolOfDestructuringAssignment(location: Identifier): Symbol | undefined; getTypeAtLocation(node: Node): Type | undefined; @@ -1764,11 +1889,20 @@ declare namespace ts { typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): string; typePredicateToString(predicate: TypePredicate, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; + /** + * @deprecated Use the createX factory functions or XToY typechecker methods and `createPrinter` or the `xToString` methods instead + * This will be removed in a future version. + */ getSymbolDisplayBuilder(): SymbolDisplayBuilder; getFullyQualifiedName(symbol: Symbol): string; getAugmentedPropertiesOfType(type: Type): Symbol[]; getRootSymbols(symbol: Symbol): Symbol[]; getContextualType(node: Expression): Type | undefined; + /** + * returns unknownSignature in the case of an error. + * returns undefined if the node is not valid. + * @param argumentCount Apparent number of arguments, passed in case of a possibly incomplete call. This should come from an ArgumentListInfo. See `signatureHelp.ts`. + */ getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined; getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature | undefined; isImplementationOfOverload(node: SignatureDeclaration): boolean | undefined; @@ -1777,6 +1911,7 @@ declare namespace ts { isUnknownSymbol(symbol: Symbol): boolean; getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): string | number | undefined; isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName | ImportTypeNode, propertyName: string): boolean; + /** Follow all aliases to get the original symbol. */ getAliasedSymbol(symbol: Symbol): Symbol; getExportsOfModule(moduleSymbol: Symbol): Symbol[]; getAllAttributesTypeFromJsxOpeningLikeElement(elementNode: JsxOpeningLikeElement): Type | undefined; @@ -1790,6 +1925,11 @@ declare namespace ts { getSuggestionForNonexistentModule(node: Identifier, target: Symbol): string | undefined; getBaseConstraintOfType(type: Type): Type | undefined; getDefaultFromTypeParameter(type: Type): Type | undefined; + /** + * Depending on the operation performed, it may be appropriate to throw away the checker + * if the cancellation token is triggered. Typically, if it is used for error checking + * and the operation is cancelled, then it should be discarded, otherwise it is safe to keep. + */ runWithCancellationToken(token: CancellationToken, cb: (checker: TypeChecker) => T): T; } enum NodeBuilderFlags { @@ -1842,7 +1982,7 @@ declare namespace ts { InElementType = 2097152, InFirstTypeArgument = 4194304, InTypeAlias = 8388608, - WriteOwnNameForAnyLike = 0, + /** @deprecated */ WriteOwnNameForAnyLike = 0, NodeBuilderFlagsMask = 9469291 } enum SymbolFormatFlags { @@ -1852,19 +1992,25 @@ declare namespace ts { AllowAnyNodeKind = 4, UseAliasDefinedOutsideCurrentScope = 8 } + /** + * @deprecated + */ interface SymbolDisplayBuilder { - buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void; - buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void; - buildIndexSignatureDisplay(info: IndexInfo, writer: SymbolWriter, kind: IndexKind, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]): void; - buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildTypePredicateDisplay(predicate: TypePredicate, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildDisplayForParametersAndDelimiters(thisParameter: Symbol, parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; - buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void; + /** @deprecated */ buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void; + /** @deprecated */ buildIndexSignatureDisplay(info: IndexInfo, writer: SymbolWriter, kind: IndexKind, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, symbolStack?: Symbol[]): void; + /** @deprecated */ buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildTypePredicateDisplay(predicate: TypePredicate, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildDisplayForParametersAndDelimiters(thisParameter: Symbol, parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + /** @deprecated */ buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; } + /** + * @deprecated Migrate to other methods of generating symbol names, ex symbolToEntityName + a printer or symbolToString + */ interface SymbolWriter extends SymbolTracker { writeKeyword(text: string): void; writeOperator(text: string): void; @@ -1985,11 +2131,20 @@ declare namespace ts { ExportEquals = "export=", Default = "default" } + /** + * This represents a string whose leading underscore have been escaped by adding extra leading underscores. + * The shape of this brand is rather unique compared to others we've used. + * Instead of just an intersection of a string and an object, it is that union-ed + * with an intersection of void and an object. This makes it wholly incompatible + * with a normal string (which is good, it cannot be misused on assignment or on usage), + * while still being comparable with a normal string via === (also good) and castable from a string. + */ type __String = (string & { __escapedIdentifier: void; }) | (void & { __escapedIdentifier: void; }) | InternalSymbolName; + /** ReadonlyMap where keys are `__String`s. */ interface ReadonlyUnderscoreEscapedMap { get(key: __String): T | undefined; has(key: __String): boolean; @@ -1999,11 +2154,13 @@ declare namespace ts { values(): Iterator; entries(): Iterator<[__String, T]>; } + /** Map where keys are `__String`s. */ interface UnderscoreEscapedMap extends ReadonlyUnderscoreEscapedMap { set(key: __String, value: T): this; delete(key: __String): boolean; clear(): void; } + /** SymbolTable based on ES6 Map interface. */ type SymbolTable = UnderscoreEscapedMap; enum TypeFlags { Any = 1, @@ -2095,6 +2252,7 @@ declare namespace ts { interface ObjectType extends Type { objectFlags: ObjectFlags; } + /** Class and interface types (ObjectFlags.Class and ObjectFlags.Interface). */ interface InterfaceType extends ObjectType { typeParameters: TypeParameter[] | undefined; outerTypeParameters: TypeParameter[] | undefined; @@ -2109,6 +2267,16 @@ declare namespace ts { declaredStringIndexInfo?: IndexInfo; declaredNumberIndexInfo?: IndexInfo; } + /** + * Type references (ObjectFlags.Reference). When a class or interface has type parameters or + * a "this" type, references to the class or interface are made using type references. The + * typeArguments property specifies the types to substitute for the type parameters of the + * class or interface and optionally includes an extra element that specifies the type to + * substitute for "this" in the resulting instantiation. When no extra argument is present, + * the type reference itself is substituted for "this". The typeArguments property is undefined + * if the class or interface has no type parameters and the reference isn't specifying an + * explicit "this" argument. + */ interface TypeReference extends ObjectType { target: GenericType; typeArguments?: Type[]; @@ -2193,6 +2361,7 @@ declare namespace ts { AlwaysStrict = 64, PriorityImpliesCombination = 28 } + /** @deprecated Use FileExtensionInfo instead. */ type JsFileExtensionInfo = FileExtensionInfo; interface FileExtensionInfo { extension: string; @@ -2206,6 +2375,12 @@ declare namespace ts { message: string; reportsUnnecessary?: {}; } + /** + * A linked list of formatted diagnostic messages to be used as part of a multiline message. + * It is built from the bottom up, leaving the head to be the "main" diagnostic. + * While it seems that DiagnosticMessageChain is structurally similar to DiagnosticMessage, + * the difference is that messages are all preformatted in DMC. + */ interface DiagnosticMessageChain { messageText: string; category: DiagnosticCategory; @@ -2214,6 +2389,7 @@ declare namespace ts { } interface Diagnostic extends DiagnosticRelatedInformation { category: DiagnosticCategory; + /** May store more in future. For now, this will simply be `true` to indicate when a diagnostic is an unused-identifier diagnostic. */ reportsUnnecessary?: {}; code: number; source?: string; @@ -2244,9 +2420,13 @@ declare namespace ts { name: string; } interface ProjectReference { + /** A normalized path on disk */ path: string; + /** The path as the user originally wrote it */ originalPath?: string; + /** True if the output of this reference should be prepended to the output of this project. Only valid for --outFile compilations */ prepend?: boolean; + /** True if it is intended that this reference form a circularity */ circular?: boolean; } type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike | PluginImport[] | ProjectReference[] | null | undefined; @@ -2323,6 +2503,7 @@ declare namespace ts { traceResolution?: boolean; resolveJsonModule?: boolean; types?: string[]; + /** Paths used to compute primary types search locations */ typeRoots?: string[]; esModuleInterop?: boolean; [option: string]: CompilerOptionsValue | TsConfigSourceFile | undefined; @@ -2354,6 +2535,7 @@ declare namespace ts { LineFeed = 1 } interface LineAndCharacter { + /** 0-based. */ line: number; character: number; } @@ -2365,6 +2547,10 @@ declare namespace ts { TSX = 4, External = 5, JSON = 6, + /** + * Used on extensions that doesn't define the ScriptKind but the content defines it. + * Deferred extensions are going to be included in all project contexts. + */ Deferred = 7 } enum ScriptTarget { @@ -2382,6 +2568,7 @@ declare namespace ts { Standard = 0, JSX = 1 } + /** Either a parsed command line or a parsed tsconfig.json */ interface ParsedCommandLine { options: CompilerOptions; typeAcquisition?: TypeAcquisition; @@ -2422,21 +2609,57 @@ declare namespace ts { readFile(fileName: string): string | undefined; trace?(s: string): void; directoryExists?(directoryName: string): boolean; + /** + * Resolve a symbolic link. + * @see https://nodejs.org/api/fs.html#fs_fs_realpathsync_path_options + */ realpath?(path: string): string; getCurrentDirectory?(): string; getDirectories?(path: string): string[]; } + /** + * Represents the result of module resolution. + * Module resolution will pick up tsx/jsx/js files even if '--jsx' and '--allowJs' are turned off. + * The Program will then filter results based on these flags. + * + * Prefer to return a `ResolvedModuleFull` so that the file type does not have to be inferred. + */ interface ResolvedModule { + /** Path of the file the module was resolved to. */ resolvedFileName: string; + /** True if `resolvedFileName` comes from `node_modules`. */ isExternalLibraryImport?: boolean; } + /** + * ResolvedModule with an explicitly provided `extension` property. + * Prefer this over `ResolvedModule`. + * If changing this, remember to change `moduleResolutionIsEqualTo`. + */ interface ResolvedModuleFull extends ResolvedModule { + /** + * Extension of resolvedFileName. This must match what's at the end of resolvedFileName. + * This is optional for backwards-compatibility, but will be added if not provided. + */ extension: Extension; packageId?: PackageId; } + /** + * Unique identifier with a package name and version. + * If changing this, remember to change `packageIdIsEqual`. + */ interface PackageId { + /** + * Name of the package. + * Should not include `@types`. + * If accessing a non-index file, this should include its name e.g. "foo/bar". + */ name: string; + /** + * Name of a submodule within this package. + * May be "". + */ subModuleName: string; + /** Version of the package, e.g. "1.2.3" */ version: string; } enum Extension { @@ -2473,6 +2696,9 @@ declare namespace ts { getNewLine(): string; readDirectory?(rootDir: string, extensions: ReadonlyArray, excludes: ReadonlyArray | undefined, includes: ReadonlyArray, depth?: number): string[]; resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): (ResolvedModule | undefined)[]; + /** + * This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files + */ resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; getEnvironmentVariable?(name: string): string | undefined; createHash?(data: string): string; @@ -2534,42 +2760,163 @@ declare namespace ts { Unspecified = 4 } interface TransformationContext { + /** Gets the compiler options supplied to the transformer. */ getCompilerOptions(): CompilerOptions; + /** Starts a new lexical environment. */ startLexicalEnvironment(): void; + /** Suspends the current lexical environment, usually after visiting a parameter list. */ suspendLexicalEnvironment(): void; + /** Resumes a suspended lexical environment, usually before visiting a function body. */ resumeLexicalEnvironment(): void; + /** Ends a lexical environment, returning any declarations. */ endLexicalEnvironment(): Statement[] | undefined; + /** Hoists a function declaration to the containing scope. */ hoistFunctionDeclaration(node: FunctionDeclaration): void; + /** Hoists a variable declaration to the containing scope. */ hoistVariableDeclaration(node: Identifier): void; + /** Records a request for a non-scoped emit helper in the current context. */ requestEmitHelper(helper: EmitHelper): void; + /** Gets and resets the requested non-scoped emit helpers. */ readEmitHelpers(): EmitHelper[] | undefined; + /** Enables expression substitutions in the pretty printer for the provided SyntaxKind. */ enableSubstitution(kind: SyntaxKind): void; + /** Determines whether expression substitutions are enabled for the provided node. */ isSubstitutionEnabled(node: Node): boolean; + /** + * Hook used by transformers to substitute expressions just before they + * are emitted by the pretty printer. + * + * NOTE: Transformation hooks should only be modified during `Transformer` initialization, + * before returning the `NodeTransformer` callback. + */ onSubstituteNode: (hint: EmitHint, node: Node) => Node; + /** + * Enables before/after emit notifications in the pretty printer for the provided + * SyntaxKind. + */ enableEmitNotification(kind: SyntaxKind): void; + /** + * Determines whether before/after emit notifications should be raised in the pretty + * printer when it emits a node. + */ isEmitNotificationEnabled(node: Node): boolean; + /** + * Hook used to allow transformers to capture state before or after + * the printer emits a node. + * + * NOTE: Transformation hooks should only be modified during `Transformer` initialization, + * before returning the `NodeTransformer` callback. + */ onEmitNode: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; } interface TransformationResult { + /** Gets the transformed source files. */ transformed: T[]; + /** Gets diagnostics for the transformation. */ diagnostics?: DiagnosticWithLocation[]; + /** + * Gets a substitute for a node, if one is available; otherwise, returns the original node. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to substitute. + */ substituteNode(hint: EmitHint, node: Node): Node; + /** + * Emits a node with possible notification. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emitCallback A callback used to emit the node. + */ emitNodeWithNotification(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void; + /** + * Clean up EmitNode entries on any parse-tree nodes. + */ dispose(): void; } + /** + * A function that is used to initialize and return a `Transformer` callback, which in turn + * will be used to transform one or more nodes. + */ type TransformerFactory = (context: TransformationContext) => Transformer; + /** + * A function that transforms a node. + */ type Transformer = (node: T) => T; + /** + * A function that accepts and possibly transforms a node. + */ type Visitor = (node: Node) => VisitResult; type VisitResult = T | T[] | undefined; interface Printer { + /** + * Print a node and its subtree as-is, without any emit transformations. + * @param hint A value indicating the purpose of a node. This is primarily used to + * distinguish between an `Identifier` used in an expression position, versus an + * `Identifier` used as an `IdentifierName` as part of a declaration. For most nodes you + * should just pass `Unspecified`. + * @param node The node to print. The node and its subtree are printed as-is, without any + * emit transformations. + * @param sourceFile A source file that provides context for the node. The source text of + * the file is used to emit the original source content for literals and identifiers, while + * the identifiers of the source file are used when generating unique names to avoid + * collisions. + */ printNode(hint: EmitHint, node: Node, sourceFile: SourceFile): string; + /** + * Prints a list of nodes using the given format flags + */ printList(format: ListFormat, list: NodeArray, sourceFile: SourceFile): string; + /** + * Prints a source file as-is, without any emit transformations. + */ printFile(sourceFile: SourceFile): string; + /** + * Prints a bundle of source files as-is, without any emit transformations. + */ printBundle(bundle: Bundle): string; } interface PrintHandlers { + /** + * A hook used by the Printer when generating unique names to avoid collisions with + * globally defined names that exist outside of the current source file. + */ hasGlobalName?(name: string): boolean; + /** + * A hook used by the Printer to provide notifications prior to emitting a node. A + * compatible implementation **must** invoke `emitCallback` with the provided `hint` and + * `node` values. + * @param hint A hint indicating the intended purpose of the node. + * @param node The node to emit. + * @param emitCallback A callback that, when invoked, will emit the node. + * @example + * ```ts + * var printer = createPrinter(printerOptions, { + * onEmitNode(hint, node, emitCallback) { + * // set up or track state prior to emitting the node... + * emitCallback(hint, node); + * // restore state after emitting the node... + * } + * }); + * ``` + */ onEmitNode?(hint: EmitHint, node: Node | undefined, emitCallback: (hint: EmitHint, node: Node | undefined) => void): void; + /** + * A hook used by the Printer to perform just-in-time substitution of a node. This is + * primarily used by node transformations that need to substitute one node for another, + * such as replacing `myExportedVar` with `exports.myExportedVar`. + * @param hint A hint indicating the intended purpose of the node. + * @param node The node to emit. + * @example + * ```ts + * var printer = createPrinter(printerOptions, { + * substituteNode(hint, node) { + * // perform substitution if necessary... + * return node; + * } + * }); + * ``` + */ substituteNode?(hint: EmitHint, node: Node): Node; } interface PrinterOptions { @@ -2582,6 +2929,7 @@ declare namespace ts { directoryExists?(directoryName: string): boolean; getCurrentDirectory?(): string; } + /** @deprecated See comment on SymbolWriter */ interface SymbolTracker { trackSymbol?(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void; reportInaccessibleThisError?(): void; @@ -2684,6 +3032,10 @@ declare namespace ts { readFile(path: string, encoding?: string): string | undefined; getFileSize?(path: string): number; writeFile(path: string, data: string, writeByteOrderMark?: boolean): void; + /** + * @pollingInterval - this parameter is used in polling-based watchers and ignored in watchers that + * use native OS file watching + */ watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher; watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher; resolvePath(path: string): string; @@ -2697,7 +3049,11 @@ declare namespace ts { getModifiedTime?(path: string): Date; setModifiedTime?(path: string, time: Date): void; deleteFile?(path: string): void; + /** + * A good implementation is node.js' `crypto.createHash`. (https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm) + */ createHash?(data: string): string; + /** This must be cryptographically secure. Only implement this method using `crypto.createHash("sha256")`. */ createSHA256Hash?(data: string): string; getMemoryUsage?(): number; exit(exitCode?: number): void; @@ -2751,6 +3107,7 @@ declare namespace ts { function getPositionOfLineAndCharacter(sourceFile: SourceFileLike, line: number, character: number): number; function getLineAndCharacterOfPosition(sourceFile: SourceFileLike, position: number): LineAndCharacter; function isWhiteSpaceLike(ch: number): boolean; + /** Does not include line breaks. For that, see isWhiteSpaceLike. */ function isWhiteSpaceSingleLine(ch: number): boolean; function isLineBreak(ch: number): boolean; function couldStartTrivia(text: string, pos: number): boolean; @@ -2762,11 +3119,13 @@ declare namespace ts { function reduceEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U): U | undefined; function getLeadingCommentRanges(text: string, pos: number): CommentRange[] | undefined; function getTrailingCommentRanges(text: string, pos: number): CommentRange[] | undefined; + /** Optionally, get the shebang */ function getShebang(text: string): string | undefined; function isIdentifierStart(ch: number, languageVersion: ScriptTarget | undefined): boolean; function isIdentifierPart(ch: number, languageVersion: ScriptTarget | undefined): boolean; function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, languageVariant?: LanguageVariant, textInitial?: string, onError?: ErrorCallback, start?: number, length?: number): Scanner; } +/** Non-internal stuff goes here */ declare namespace ts { function isExternalModuleNameRelative(moduleName: string): boolean; function sortAndDeduplicateDiagnostics(diagnostics: ReadonlyArray): T[]; @@ -2790,6 +3149,14 @@ declare namespace ts { function textChangeRangeIsUnchanged(range: TextChangeRange): boolean; function createTextChangeRange(span: TextSpan, newLength: number): TextChangeRange; let unchangedTextChangeRange: TextChangeRange; + /** + * Called to merge all the changes that occurred across several versions of a script snapshot + * into a single change. i.e. if a user keeps making successive edits to a script we will + * have a text change from V1 to V2, V2 to V3, ..., Vn. + * + * This function will then merge those changes into a single change range valid between V1 and + * Vn. + */ function collapseTextChangeRangesAcrossMultipleVersions(changes: ReadonlyArray): TextChangeRange; function getTypeParameterOwner(d: Declaration): Declaration | undefined; type ParameterPropertyDeclaration = ParameterDeclaration & { @@ -2801,6 +3168,10 @@ declare namespace ts { function isEmptyBindingElement(node: BindingElement): boolean; function getCombinedModifierFlags(node: Node): ModifierFlags; function getCombinedNodeFlags(node: Node): NodeFlags; + /** + * Checks to see if the locale is in the appropriate format, + * and if it is, attempts to set the appropriate language. + */ function validateLocaleAndSetLanguage(locale: string, sys: { getExecutingFilePath(): string; resolvePath(path: string): string; @@ -2811,26 +3182,100 @@ declare namespace ts { function getOriginalNode(node: Node, nodeTest: (node: Node) => node is T): T; function getOriginalNode(node: Node | undefined): Node | undefined; function getOriginalNode(node: Node | undefined, nodeTest: (node: Node | undefined) => node is T): T | undefined; + /** + * Gets a value indicating whether a node originated in the parse tree. + * + * @param node The node to test. + */ function isParseTreeNode(node: Node): boolean; + /** + * Gets the original parse tree node for a node. + * + * @param node The original node. + * @returns The original parse tree node if found; otherwise, undefined. + */ function getParseTreeNode(node: Node): Node; + /** + * Gets the original parse tree node for a node. + * + * @param node The original node. + * @param nodeTest A callback used to ensure the correct type of parse tree node is returned. + * @returns The original parse tree node if found; otherwise, undefined. + */ function getParseTreeNode(node: Node | undefined, nodeTest?: (node: Node) => node is T): T | undefined; + /** + * Remove extra underscore from escaped identifier text content. + * + * @param identifier The escaped identifier text. + * @returns The unescaped identifier text. + */ function unescapeLeadingUnderscores(identifier: __String): string; function idText(identifier: Identifier): string; function symbolName(symbol: Symbol): string; + /** + * Remove extra underscore from escaped identifier text content. + * @deprecated Use `id.text` for the unescaped text. + * @param identifier The escaped identifier text. + * @returns The unescaped identifier text. + */ function unescapeIdentifier(id: string): string; function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined; function getNameOfDeclaration(declaration: Declaration | Expression): DeclarationName; + /** + * Gets the JSDoc parameter tags for the node if present. + * + * @remarks Returns any JSDoc param tag that matches the provided + * parameter, whether a param tag on a containing function + * expression, or a param tag on a variable declaration whose + * initializer is the containing function. The tags closest to the + * node are returned first, so in the previous example, the param + * tag on the containing function expression would be first. + * + * Does not return tags for binding patterns, because JSDoc matches + * parameters by name and binding patterns do not have a name. + */ function getJSDocParameterTags(param: ParameterDeclaration): ReadonlyArray; + /** + * Return true if the node has JSDoc parameter tags. + * + * @remarks Includes parameter tags that are not directly on the node, + * for example on a variable declaration whose initializer is a function expression. + */ function hasJSDocParameterTags(node: FunctionLikeDeclaration | SignatureDeclaration): boolean; + /** Gets the JSDoc augments tag for the node if present */ function getJSDocAugmentsTag(node: Node): JSDocAugmentsTag | undefined; + /** Gets the JSDoc class tag for the node if present */ function getJSDocClassTag(node: Node): JSDocClassTag | undefined; + /** Gets the JSDoc this tag for the node if present */ function getJSDocThisTag(node: Node): JSDocThisTag | undefined; + /** Gets the JSDoc return tag for the node if present */ function getJSDocReturnTag(node: Node): JSDocReturnTag | undefined; + /** Gets the JSDoc template tag for the node if present */ function getJSDocTemplateTag(node: Node): JSDocTemplateTag | undefined; + /** Gets the JSDoc type tag for the node if present and valid */ function getJSDocTypeTag(node: Node): JSDocTypeTag | undefined; + /** + * Gets the type node for the node if provided via JSDoc. + * + * @remarks The search includes any JSDoc param tag that relates + * to the provided parameter, for example a type tag on the + * parameter itself, or a param tag on a containing function + * expression, or a param tag on a variable declaration whose + * initializer is the containing function. The tags closest to the + * node are examined first, so in the previous example, the type + * tag directly on the node would be returned. + */ function getJSDocType(node: Node): TypeNode | undefined; + /** + * Gets the return type node for the node if provided via JSDoc's return tag. + * + * @remarks `getJSDocReturnTag` just gets the whole JSDoc tag. This function + * gets the type from inside the braces. + */ function getJSDocReturnType(node: Node): TypeNode | undefined; + /** Get all JSDoc tags related to a node, including those on parent nodes. */ function getJSDocTags(node: Node): ReadonlyArray; + /** Gets all JSDoc tags of a specified kind, or undefined if not present. */ function getAllJSDocTagsOfKind(node: Node, kind: SyntaxKind): ReadonlyArray; } declare namespace ts { @@ -3001,6 +3446,11 @@ declare namespace ts { function isJSDocSignature(node: Node): node is JSDocSignature; } declare namespace ts { + /** + * True if node is of some token syntax kind. + * For example, this is true for an IfKeyword but not for an IfStatement. + * Literals are considered tokens, except TemplateLiteral, but does include TemplateHead/Middle/Tail. + */ function isToken(n: Node): boolean; function isLiteralExpression(node: Node): node is LiteralExpression; type TemplateLiteralToken = NoSubstitutionTemplateLiteral | TemplateHead | TemplateMiddle | TemplateTail; @@ -3018,6 +3468,11 @@ declare namespace ts { function isTypeElement(node: Node): node is TypeElement; function isClassOrTypeElement(node: Node): node is ClassElement | TypeElement; function isObjectLiteralElementLike(node: Node): node is ObjectLiteralElementLike; + /** + * Node test that determines whether a node is a valid type node. + * This differs from the `isPartOfTypeNode` function which determines whether a node is *part* + * of a TypeNode. + */ function isTypeNode(node: Node): node is TypeNode; function isFunctionOrConstructorTypeNode(node: Node): node is FunctionTypeNode | ConstructorTypeNode; function isPropertyAccessOrQualifiedName(node: Node): node is PropertyAccessExpression | QualifiedName; @@ -3029,6 +3484,7 @@ declare namespace ts { function isIterationStatement(node: Node, lookInLabeledStatements: boolean): node is IterationStatement | LabeledStatement; function isJsxOpeningLikeElement(node: Node): node is JsxOpeningLikeElement; function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause; + /** True if node is of a kind that may contain comment text. */ function isJSDocCommentContainingNode(node: Node): boolean; function isSetAccessor(node: Node): node is SetAccessorDeclaration; function isGetAccessor(node: Node): node is GetAccessorDeclaration; @@ -3037,9 +3493,27 @@ declare namespace ts { } declare namespace ts { function createNode(kind: SyntaxKind, pos?: number, end?: number): Node; + /** + * Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes + * stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise, + * embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns + * a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned. + * + * @param node a given node to visit its children + * @param cbNode a callback to be invoked for all child nodes + * @param cbNodes a callback to be invoked for embedded array + * + * @remarks `forEachChild` must visit the children of a node in the order + * that they appear in the source code. The language service depends on this property to locate nodes by position. + */ function forEachChild(node: Node, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined; function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile; function parseIsolatedEntityName(text: string, languageVersion: ScriptTarget): EntityName | undefined; + /** + * Parse json text into SyntaxTree and return node and parse errors if any + * @param fileName + * @param sourceText + */ function parseJsonText(fileName: string, sourceText: string): JsonSourceFile; function isExternalModule(file: SourceFile): boolean; function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile; @@ -3047,24 +3521,66 @@ declare namespace ts { declare namespace ts { function parseCommandLine(commandLine: ReadonlyArray, readFile?: (path: string) => string | undefined): ParsedCommandLine; type DiagnosticReporter = (diagnostic: Diagnostic) => void; + /** + * Reports config file diagnostics + */ interface ConfigFileDiagnosticsReporter { + /** + * Reports unrecoverable error when parsing config file + */ onUnRecoverableConfigFileDiagnostic: DiagnosticReporter; } + /** + * Interface extending ParseConfigHost to support ParseConfigFile that reads config file and reports errors + */ interface ParseConfigFileHost extends ParseConfigHost, ConfigFileDiagnosticsReporter { getCurrentDirectory(): string; } + /** + * Reads the config file, reports errors if any and exits if the config file cannot be found + */ function getParsedCommandLineOfConfigFile(configFileName: string, optionsToExtend: CompilerOptions, host: ParseConfigFileHost): ParsedCommandLine | undefined; + /** + * Read tsconfig.json file + * @param fileName The path to the config file + */ function readConfigFile(fileName: string, readFile: (path: string) => string | undefined): { config?: any; error?: Diagnostic; }; + /** + * Parse the text of the tsconfig.json file + * @param fileName The path to the config file + * @param jsonText The text of the config file + */ function parseConfigFileTextToJson(fileName: string, jsonText: string): { config?: any; error?: Diagnostic; }; + /** + * Read tsconfig.json file + * @param fileName The path to the config file + */ function readJsonConfigFile(fileName: string, readFile: (path: string) => string | undefined): TsConfigSourceFile; + /** + * Convert the json syntax tree into the json value + */ function convertToObject(sourceFile: JsonSourceFile, errors: Push): any; + /** + * Parse the contents of a config file (tsconfig.json). + * @param json The contents of the config file to parse + * @param host Instance of ParseConfigHost used to enumerate files in folder. + * @param basePath A root directory to resolve relative path entries in the config + * file to. e.g. outDir + */ function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: ReadonlyArray): ParsedCommandLine; + /** + * Parse the contents of a config file (tsconfig.json). + * @param jsonNode The contents of the config file to parse + * @param host Instance of ParseConfigHost used to enumerate files in folder. + * @param basePath A root directory to resolve relative path entries in the config + * file to. e.g. outDir + */ function parseJsonSourceFileConfigFileContent(sourceFile: TsConfigSourceFile, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: ReadonlyArray): ParsedCommandLine; function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions; @@ -3077,11 +3593,32 @@ declare namespace ts { } declare namespace ts { function getEffectiveTypeRoots(options: CompilerOptions, host: GetEffectiveTypeRootsHost): string[] | undefined; + /** + * @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. + * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups + * is assumed to be the same as root directory of the project. + */ function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost): ResolvedTypeReferenceDirectiveWithFailedLookupLocations; + /** + * Given a set of options, returns the set of type directive names + * that should be included for this program automatically. + * This list could either come from the config file, + * or from enumerating the types root + initial secondary types lookup location. + * More type directives might appear in the program later as a result of loading actual source files; + * this list is only the set of defaults that are implicitly included. + */ function getAutomaticTypeDirectiveNames(options: CompilerOptions, host: ModuleResolutionHost): string[]; + /** + * Cached module resolutions per containing directory. + * This assumes that any module id will have the same resolution for sibling files located in the same folder. + */ interface ModuleResolutionCache extends NonRelativeModuleNameResolutionCache { getOrCreateCacheForDirectory(directoryName: string): Map; } + /** + * Stored map from non-relative module name to a table: directory -> result of module lookup in this directory + * We support only non-relative module names because resolution of relative module names is usually more deterministic and thus less expensive. + */ interface NonRelativeModuleNameResolutionCache { getOrCreateCacheForModuleName(nonRelativeModuleName: string): PerModuleNameCache; } @@ -3097,6 +3634,7 @@ declare namespace ts { } declare namespace ts { function createNodeArray(elements?: ReadonlyArray, hasTrailingComma?: boolean): NodeArray; + /** If a node is passed, creates a string literal whose source text is read from a source node during emit. */ function createLiteral(value: string | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier): StringLiteral; function createLiteral(value: number): NumericLiteral; function createLiteral(value: boolean): BooleanLiteral; @@ -3106,11 +3644,17 @@ declare namespace ts { function createRegularExpressionLiteral(text: string): RegularExpressionLiteral; function createIdentifier(text: string): Identifier; function updateIdentifier(node: Identifier): Identifier; + /** Create a unique temporary variable. */ function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined): Identifier; + /** Create a unique temporary variable for use in a loop. */ function createLoopVariable(): Identifier; + /** Create a unique name based on the supplied text. */ function createUniqueName(text: string): Identifier; + /** Create a unique name based on the supplied text. */ function createOptimisticUniqueName(text: string): Identifier; + /** Create a unique name based on the supplied text. This does not consider names injected by the transformer. */ function createFileLevelUniqueName(text: string): Identifier; + /** Create a unique name generated for a node. */ function getGeneratedNameForNode(node: Node): Identifier; function createToken(token: TKind): Token; function createSuper(): SuperExpression; @@ -3379,8 +3923,25 @@ declare namespace ts { function createEnumMember(name: string | PropertyName, initializer?: Expression): EnumMember; function updateEnumMember(node: EnumMember, name: PropertyName, initializer: Expression | undefined): EnumMember; function updateSourceFileNode(node: SourceFile, statements: ReadonlyArray, isDeclarationFile?: boolean, referencedFiles?: SourceFile["referencedFiles"], typeReferences?: SourceFile["typeReferenceDirectives"], hasNoDefaultLib?: boolean, libReferences?: SourceFile["libReferenceDirectives"]): SourceFile; + /** + * Creates a shallow, memberwise clone of a node for mutation. + */ function getMutableClone(node: T): T; + /** + * Creates a synthetic statement to act as a placeholder for a not-emitted statement in + * order to preserve comments. + * + * @param original The original statement. + */ function createNotEmittedStatement(original: Node): NotEmittedStatement; + /** + * Creates a synthetic expression to act as a placeholder for a not-emitted expression in + * order to preserve comments or sourcemap positions. + * + * @param expression The inner expression to emit. + * @param original The original outer expression. + * @param location The location for the expression. Defaults to the positions from "original" if provided. + */ function createPartiallyEmittedExpression(expression: Expression, original?: Node): PartiallyEmittedExpression; function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression): PartiallyEmittedExpression; function createCommaList(elements: ReadonlyArray): CommaListExpression; @@ -3410,15 +3971,43 @@ declare namespace ts { function createVoidZero(): VoidExpression; function createExportDefault(expression: Expression): ExportAssignment; function createExternalModuleExport(exportName: Identifier): ExportDeclaration; + /** + * Clears any EmitNode entries from parse-tree nodes. + * @param sourceFile A source file. + */ function disposeEmitNodes(sourceFile: SourceFile): void; function setTextRange(range: T, location: TextRange | undefined): T; + /** + * Sets flags that control emit behavior of a node. + */ function setEmitFlags(node: T, emitFlags: EmitFlags): T; + /** + * Gets a custom text range to use when emitting source maps. + */ function getSourceMapRange(node: Node): SourceMapRange; + /** + * Sets a custom text range to use when emitting source maps. + */ function setSourceMapRange(node: T, range: SourceMapRange | undefined): T; + /** + * Create an external source map source file reference + */ function createSourceMapSource(fileName: string, text: string, skipTrivia?: (pos: number) => number): SourceMapSource; + /** + * Gets the TextRange to use for source maps for a token of a node. + */ function getTokenSourceMapRange(node: Node, token: SyntaxKind): SourceMapRange | undefined; + /** + * Sets the TextRange to use for source maps for a token of a node. + */ function setTokenSourceMapRange(node: T, token: SyntaxKind, range: SourceMapRange | undefined): T; + /** + * Gets a custom text range to use when emitting comments. + */ function getCommentRange(node: Node): TextRange; + /** + * Sets a custom text range to use when emitting comments. + */ function setCommentRange(node: T, range: TextRange): T; function getSyntheticLeadingComments(node: Node): SynthesizedComment[] | undefined; function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[] | undefined): T; @@ -3427,26 +4016,115 @@ declare namespace ts { function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[] | undefined): T; function addSyntheticTrailingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean): T; function moveSyntheticComments(node: T, original: Node): T; + /** + * Gets the constant value to emit for an expression. + */ function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression): string | number | undefined; + /** + * Sets the constant value to emit for an expression. + */ function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: string | number): PropertyAccessExpression | ElementAccessExpression; + /** + * Adds an EmitHelper to a node. + */ function addEmitHelper(node: T, helper: EmitHelper): T; + /** + * Add EmitHelpers to a node. + */ function addEmitHelpers(node: T, helpers: EmitHelper[] | undefined): T; + /** + * Removes an EmitHelper from a node. + */ function removeEmitHelper(node: Node, helper: EmitHelper): boolean; + /** + * Gets the EmitHelpers of a node. + */ function getEmitHelpers(node: Node): EmitHelper[] | undefined; + /** + * Moves matching emit helpers from a source node to a target node. + */ function moveEmitHelpers(source: Node, target: Node, predicate: (helper: EmitHelper) => boolean): void; function setOriginalNode(node: T, original: Node | undefined): T; } declare namespace ts { + /** + * Visits a Node using the supplied visitor, possibly returning a new Node in its place. + * + * @param node The Node to visit. + * @param visitor The callback used to visit the Node. + * @param test A callback to execute to verify the Node is valid. + * @param lift An optional callback to execute to lift a NodeArray into a valid Node. + */ function visitNode(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T; + /** + * Visits a Node using the supplied visitor, possibly returning a new Node in its place. + * + * @param node The Node to visit. + * @param visitor The callback used to visit the Node. + * @param test A callback to execute to verify the Node is valid. + * @param lift An optional callback to execute to lift a NodeArray into a valid Node. + */ function visitNode(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T): T | undefined; + /** + * Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place. + * + * @param nodes The NodeArray to visit. + * @param visitor The callback used to visit a Node. + * @param test A node test to execute for each node. + * @param start An optional value indicating the starting offset at which to start visiting. + * @param count An optional value indicating the maximum number of nodes to visit. + */ function visitNodes(nodes: NodeArray | undefined, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray; + /** + * Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place. + * + * @param nodes The NodeArray to visit. + * @param visitor The callback used to visit a Node. + * @param test A node test to execute for each node. + * @param start An optional value indicating the starting offset at which to start visiting. + * @param count An optional value indicating the maximum number of nodes to visit. + */ function visitNodes(nodes: NodeArray | undefined, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray | undefined; + /** + * Starts a new lexical environment and visits a statement list, ending the lexical environment + * and merging hoisted declarations upon completion. + */ function visitLexicalEnvironment(statements: NodeArray, visitor: Visitor, context: TransformationContext, start?: number, ensureUseStrict?: boolean): NodeArray; + /** + * Starts a new lexical environment and visits a parameter list, suspending the lexical + * environment upon completion. + */ function visitParameterList(nodes: NodeArray | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes): NodeArray; + /** + * Resumes a suspended lexical environment and visits a function body, ending the lexical + * environment and merging hoisted declarations upon completion. + */ function visitFunctionBody(node: FunctionBody, visitor: Visitor, context: TransformationContext): FunctionBody; + /** + * Resumes a suspended lexical environment and visits a function body, ending the lexical + * environment and merging hoisted declarations upon completion. + */ function visitFunctionBody(node: FunctionBody | undefined, visitor: Visitor, context: TransformationContext): FunctionBody | undefined; + /** + * Resumes a suspended lexical environment and visits a concise body, ending the lexical + * environment and merging hoisted declarations upon completion. + */ function visitFunctionBody(node: ConciseBody, visitor: Visitor, context: TransformationContext): ConciseBody; + /** + * Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place. + * + * @param node The Node whose children will be visited. + * @param visitor The callback used to visit each child. + * @param context A lexical environment context for the visitor. + */ function visitEachChild(node: T, visitor: Visitor, context: TransformationContext): T; + /** + * Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place. + * + * @param node The Node whose children will be visited. + * @param visitor The callback used to visit each child. + * @param context A lexical environment context for the visitor. + */ function visitEachChild(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes, tokenVisitor?: Visitor): T | undefined; } declare namespace ts { @@ -3467,8 +4145,35 @@ declare namespace ts { function formatDiagnosticsWithColorAndContext(diagnostics: ReadonlyArray, host: FormatDiagnosticsHost): string; function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain | undefined, newLine: string): string; function getConfigFileParsingDiagnostics(configFileParseResult: ParsedCommandLine): ReadonlyArray; + /** + * Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions' + * that represent a compilation unit. + * + * Creating a program proceeds from a set of root files, expanding the set of inputs by following imports and + * triple-slash-reference-path directives transitively. '@types' and triple-slash-reference-types are also pulled in. + * + * @param createProgramOptions - The options for creating a program. + * @returns A 'Program' object. + */ function createProgram(createProgramOptions: CreateProgramOptions): Program; + /** + * Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions' + * that represent a compilation unit. + * + * Creating a program proceeds from a set of root files, expanding the set of inputs by following imports and + * triple-slash-reference-path directives transitively. '@types' and triple-slash-reference-types are also pulled in. + * + * @param rootNames - A set of root files. + * @param options - The compiler options which should be used. + * @param host - The host interacts with the underlying file system. + * @param oldProgram - Reuses an old program structure. + * @param configFileParsingDiagnostics - error during config file parsing + * @returns A 'Program' object. + */ function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program; + /** + * Returns the target config filename of a project reference + */ function resolveProjectReferencePath(host: CompilerHost | UpToDateHost, ref: ProjectReference): ResolvedConfigFileName; } declare namespace ts { @@ -3488,43 +4193,137 @@ declare namespace ts { affected: SourceFile | Program; } | undefined; interface BuilderProgramHost { + /** + * return true if file names are treated with case sensitivity + */ useCaseSensitiveFileNames(): boolean; + /** + * If provided this would be used this hash instead of actual file shape text for detecting changes + */ createHash?: (data: string) => string; + /** + * When emit or emitNextAffectedFile are called without writeFile, + * this callback if present would be used to write files + */ writeFile?: WriteFileCallback; } + /** + * Builder to manage the program state changes + */ interface BuilderProgram { + /** + * Returns current program + */ getProgram(): Program; + /** + * Get compiler options of the program + */ getCompilerOptions(): CompilerOptions; + /** + * Get the source file in the program with file name + */ getSourceFile(fileName: string): SourceFile | undefined; + /** + * Get a list of files in the program + */ getSourceFiles(): ReadonlyArray; + /** + * Get the diagnostics for compiler options + */ getOptionsDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray; + /** + * Get the diagnostics that dont belong to any file + */ getGlobalDiagnostics(cancellationToken?: CancellationToken): ReadonlyArray; + /** + * Get the diagnostics from config file parsing + */ getConfigFileParsingDiagnostics(): ReadonlyArray; + /** + * Get the syntax diagnostics, for all source files if source file is not supplied + */ getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray; + /** + * Get all the dependencies of the file + */ getAllDependencies(sourceFile: SourceFile): ReadonlyArray; + /** + * Gets the semantic diagnostics from the program corresponding to this state of file (if provided) or whole program + * The semantic diagnostics are cached and managed here + * Note that it is assumed that when asked about semantic diagnostics through this API, + * the file has been taken out of affected files so it is safe to use cache or get from program and cache the diagnostics + * In case of SemanticDiagnosticsBuilderProgram if the source file is not provided, + * it will iterate through all the affected files, to ensure that cache stays valid and yet provide a way to get all semantic diagnostics + */ getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): ReadonlyArray; + /** + * Emits the JavaScript and declaration files. + * When targetSource file is specified, emits the files corresponding to that source file, + * otherwise for the whole program. + * In case of EmitAndSemanticDiagnosticsBuilderProgram, when targetSourceFile is specified, + * it is assumed that that file is handled from affected file list. If targetSourceFile is not specified, + * it will only emit all the affected files instead of whole program + * + * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host + * in that order would be used to write the files + */ emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult; + /** + * Get the current directory of the program + */ getCurrentDirectory(): string; } + /** + * The builder that caches the semantic diagnostics for the program and handles the changed files and affected files + */ interface SemanticDiagnosticsBuilderProgram extends BuilderProgram { + /** + * Gets the semantic diagnostics from the program for the next affected file and caches it + * Returns undefined if the iteration is complete + */ getSemanticDiagnosticsOfNextAffectedFile(cancellationToken?: CancellationToken, ignoreSourceFile?: (sourceFile: SourceFile) => boolean): AffectedFileResult>; } + /** + * The builder that can handle the changes in program and iterate through changed file to emit the files + * The semantic diagnostics are cached per file and managed by clearing for the changed/affected files + */ interface EmitAndSemanticDiagnosticsBuilderProgram extends BuilderProgram { + /** + * Emits the next affected file's emit result (EmitResult and sourceFiles emitted) or returns undefined if iteration is complete + * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host + * in that order would be used to write the files + */ emitNextAffectedFile(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): AffectedFileResult; } + /** + * Create the builder to manage semantic diagnostics and cache them + */ function createSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; + /** + * Create the builder that can handle the changes in program and iterate through changed files + * to emit the those files and manage semantic diagnostics cache as well + */ function createEmitAndSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; + /** + * Creates a builder thats just abstraction over program and can be used with watch + */ function createAbstractBuilder(newProgram: Program, host: BuilderProgramHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; function createAbstractBuilder(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; } declare namespace ts { type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void; + /** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */ type CreateProgram = (rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray) => T; interface WatchCompilerHost { + /** + * Used to create the program when need for program creation or recreation detected + */ createProgram: CreateProgram; + /** If provided, callback to invoke after every new program creation */ afterProgramCreate?(program: T): void; + /** If provided, called with Diagnostic message that informs about change in watch status */ onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions): void; useCaseSensitiveFileNames(): boolean; getNewLine(): string; @@ -3532,41 +4331,92 @@ declare namespace ts { getDefaultLibFileName(options: CompilerOptions): string; getDefaultLibLocation?(): string; createHash?(data: string): string; + /** + * Use to check file presence for source files and + * if resolveModuleNames is not provided (complier is in charge of module resolution) then module files as well + */ fileExists(path: string): boolean; + /** + * Use to read file text for source files and + * if resolveModuleNames is not provided (complier is in charge of module resolution) then module files as well + */ readFile(path: string, encoding?: string): string | undefined; + /** If provided, used for module resolution as well as to handle directory structure */ directoryExists?(path: string): boolean; + /** If provided, used in resolutions as well as handling directory structure */ getDirectories?(path: string): string[]; + /** If provided, used to cache and handle directory structure modifications */ readDirectory?(path: string, extensions?: ReadonlyArray, exclude?: ReadonlyArray, include?: ReadonlyArray, depth?: number): string[]; + /** Symbol links resolution */ realpath?(path: string): string; + /** If provided would be used to write log about compilation */ trace?(s: string): void; + /** If provided is used to get the environment variable */ getEnvironmentVariable?(name: string): string | undefined; + /** If provided, used to resolve the module names, otherwise typescript's default module resolution */ resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): ResolvedModule[]; + /** If provided, used to resolve type reference directives, otherwise typescript's default resolution */ resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; + /** Used to watch changes in source files, missing files needed to update the program or config file */ watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher; + /** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */ watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher; + /** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */ setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; + /** If provided, will be used to reset existing delayed compilation */ clearTimeout?(timeoutId: any): void; } + /** + * Host to create watch with root files and options + */ interface WatchCompilerHostOfFilesAndCompilerOptions extends WatchCompilerHost { + /** root files to use to generate program */ rootFiles: string[]; + /** Compiler options */ options: CompilerOptions; } + /** + * Host to create watch with config file + */ interface WatchCompilerHostOfConfigFile extends WatchCompilerHost, ConfigFileDiagnosticsReporter { + /** Name of the config file to compile */ configFileName: string; + /** Options to extend */ optionsToExtend?: CompilerOptions; + /** + * Used to generate source file names from the config file and its include, exclude, files rules + * and also to cache the directory stucture + */ readDirectory(path: string, extensions?: ReadonlyArray, exclude?: ReadonlyArray, include?: ReadonlyArray, depth?: number): string[]; } interface Watch { + /** Synchronize with host and get updated program */ getProgram(): T; } + /** + * Creates the watch what generates program using the config file + */ interface WatchOfConfigFile extends Watch { } + /** + * Creates the watch that generates program using the root files and compiler options + */ interface WatchOfFilesAndCompilerOptions extends Watch { + /** Updates the root files in the program, only if this is not config file compilation */ updateRootFileNames(fileNames: string[]): void; } + /** + * Create the watch compiler host for either configFile or fileNames and its options + */ function createWatchCompilerHost(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfFilesAndCompilerOptions; function createWatchCompilerHost(configFileName: string, optionsToExtend: CompilerOptions | undefined, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfConfigFile; + /** + * Creates the watch from the host for root files and compiler options + */ function createWatchProgram(host: WatchCompilerHostOfFilesAndCompilerOptions): WatchOfFilesAndCompilerOptions; + /** + * Creates the watch from the host for config file + */ function createWatchProgram(host: WatchCompilerHostOfConfigFile): WatchOfConfigFile; } declare namespace ts { @@ -3576,9 +4426,28 @@ declare namespace ts { errorDiagnostic(diag: Diagnostic): void; message(diag: DiagnosticMessage, ...args: string[]): void; } + /** + * A BuildContext tracks what's going on during the course of a build. + * + * Callers may invoke any number of build requests within the same context; + * until the context is reset, each project will only be built at most once. + * + * Example: In a standard setup where project B depends on project A, and both are out of date, + * a failed build of A will result in A remaining out of date. When we try to build + * B, we should immediately bail instead of recomputing A's up-to-date status again. + * + * This also matters for performing fast (i.e. fake) downstream builds of projects + * when their upstream .d.ts files haven't changed content (but have newer timestamps) + */ interface BuildContext { options: BuildOptions; + /** + * Map from output file name to its pre-build timestamp + */ unchangedOutputs: FileMap; + /** + * Map from config file name to up-to-date status + */ projectStatus: FileMap; invalidatedProjects: FileMap; queuedProjects: FileMap; @@ -3597,23 +4466,42 @@ declare namespace ts { enum UpToDateStatusType { Unbuildable = 0, UpToDate = 1, + /** + * The project appears out of date because its upstream inputs are newer than its outputs, + * but all of its outputs are actually newer than the previous identical outputs of its (.d.ts) inputs. + * This means we can Pseudo-build (just touch timestamps), as if we had actually built this project. + */ UpToDateWithUpstreamTypes = 2, OutputMissing = 3, OutOfDateWithSelf = 4, OutOfDateWithUpstream = 5, UpstreamOutOfDate = 6, UpstreamBlocked = 7, + /** + * Projects with no outputs (i.e. "solution" files) + */ ContainerOnly = 8 } type UpToDateStatus = Status.Unbuildable | Status.UpToDate | Status.OutputMissing | Status.OutOfDateWithSelf | Status.OutOfDateWithUpstream | Status.UpstreamOutOfDate | Status.UpstreamBlocked | Status.ContainerOnly; namespace Status { + /** + * The project can't be built at all in its current state. For example, + * its config file cannot be parsed, or it has a syntax error or missing file + */ interface Unbuildable { type: UpToDateStatusType.Unbuildable; reason: string; } + /** + * This project doesn't have any outputs, so "is it up to date" is a meaningless question. + */ interface ContainerOnly { type: UpToDateStatusType.ContainerOnly; } + /** + * The project is up to date with respect to its inputs. + * We track what the newest input file is. + */ interface UpToDate { type: UpToDateStatusType.UpToDate | UpToDateStatusType.UpToDateWithUpstreamTypes; newestInputFileTime: Date; @@ -3623,23 +4511,42 @@ declare namespace ts { newestOutputFileName: string; oldestOutputFileName: string; } + /** + * One or more of the outputs of the project does not exist. + */ interface OutputMissing { type: UpToDateStatusType.OutputMissing; + /** + * The name of the first output file that didn't exist + */ missingOutputFileName: string; } + /** + * One or more of the project's outputs is older than its newest input. + */ interface OutOfDateWithSelf { type: UpToDateStatusType.OutOfDateWithSelf; outOfDateOutputFileName: string; newerInputFileName: string; } + /** + * This project depends on an out-of-date project, so shouldn't be built yet + */ interface UpstreamOutOfDate { type: UpToDateStatusType.UpstreamOutOfDate; upstreamProjectName: string; } + /** + * This project depends an upstream project with build errors + */ interface UpstreamBlocked { type: UpToDateStatusType.UpstreamBlocked; upstreamProjectName: string; } + /** + * One or more of the project's outputs is older than the newest output of + * an upstream project. + */ interface OutOfDateWithUpstream { type: UpToDateStatusType.OutOfDateWithUpstream; outOfDateOutputFileName: string; @@ -3662,6 +4569,10 @@ declare namespace ts { }; function createBuildContext(options: BuildOptions): BuildContext; function performBuild(args: string[], compilerHost: CompilerHost, buildHost: BuildHost, system?: System): number | undefined; + /** + * A SolutionBuilder has an immutable set of rootNames that are the "entry point" projects, but + * can dynamically add/remove other projects based on changes on the rootNames' references + */ function createSolutionBuilder(compilerHost: CompilerHost, buildHost: BuildHost, rootNames: ReadonlyArray, defaultOptions: BuildOptions, system?: System): { buildAllProjects: () => ExitStatus; getUpToDateStatus: (project: ParsedCommandLine | undefined) => UpToDateStatus; @@ -3675,6 +4586,9 @@ declare namespace ts { resolveProjectName: (name: string) => ResolvedConfigFileName | undefined; startWatching: () => void; }; + /** + * Gets the UpToDateStatus for a project + */ function getUpToDateStatus(host: UpToDateHost, project: ParsedCommandLine | undefined): UpToDateStatus; function getAllProjectOutputs(project: ParsedCommandLine): ReadonlyArray; function formatUpToDateStatus(configFileName: string, status: UpToDateStatus, relName: (fileName: string) => string, formatMessage: (message: DiagnosticMessage, ...args: string[]) => T): T | undefined; @@ -3754,10 +4668,25 @@ declare namespace ts { interface SourceMapSource { getLineAndCharacterOfPosition(pos: number): LineAndCharacter; } + /** + * Represents an immutable snapshot of a script at a specified time.Once acquired, the + * snapshot is observably immutable. i.e. the same calls with the same parameters will return + * the same values. + */ interface IScriptSnapshot { + /** Gets a portion of the script snapshot specified by [start, end). */ getText(start: number, end: number): string; + /** Gets the length of this script snapshot. */ getLength(): number; + /** + * Gets the TextChangeRange that describe how the text changed between this text and + * an older version. This information is used by the incremental parser to determine + * what sections of the script need to be re-parsed. 'undefined' can be returned if the + * change range cannot be determined. However, in that case, incremental parsing will + * not happen and the entire document will be re - parsed. + */ getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange | undefined; + /** Releases all resources held by this script snapshot */ dispose?(): void; } namespace ScriptSnapshot { @@ -3804,6 +4733,9 @@ declare namespace ts { getResolvedModuleWithFailedLookupLocationsFromCache?(modulename: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined; resolveTypeReferenceDirectives?(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[]; getDirectories?(directoryName: string): string[]; + /** + * Gets a set of custom transformers to use during emit. + */ getCustomTransformers?(): CustomTransformers | undefined; isKnownTypesPackageName?(name: string): boolean; installPackage?(options: InstallPackageOptions): Promise; @@ -3819,10 +4751,17 @@ declare namespace ts { interface LanguageService { cleanupSemanticCache(): void; getSyntacticDiagnostics(fileName: string): DiagnosticWithLocation[]; + /** The first time this is called, it will return global diagnostics (no location). */ getSemanticDiagnostics(fileName: string): Diagnostic[]; getSuggestionDiagnostics(fileName: string): DiagnosticWithLocation[]; getCompilerOptionsDiagnostics(): Diagnostic[]; + /** + * @deprecated Use getEncodedSyntacticClassifications instead. + */ getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; + /** + * @deprecated Use getEncodedSemanticClassifications instead. + */ getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications; getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications; @@ -3842,6 +4781,7 @@ declare namespace ts { getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined; findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined; getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[] | undefined; + /** @deprecated */ getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined; getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles?: boolean): NavigateToItem[]; getNavigationBarItems(fileName: string): NavigationBarItem[]; @@ -3855,6 +4795,10 @@ declare namespace ts { getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion | undefined; isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean; + /** + * This will return a defined result if the position is after the `>` of the opening tag, or somewhere in the text, of a JSXElement with no closing tag. + * Editors should call this after `>` is typed. + */ getJsxClosingTagAtPosition(fileName: string, position: number): JsxClosingTagInfo | undefined; getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan | undefined; toLineColumnOffset?(fileName: string, position: number): LineAndCharacter; @@ -3863,8 +4807,11 @@ declare namespace ts { applyCodeActionCommand(action: CodeActionCommand): Promise; applyCodeActionCommand(action: CodeActionCommand[]): Promise; applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[]): Promise; + /** @deprecated `fileName` will be ignored */ applyCodeActionCommand(fileName: string, action: CodeActionCommand): Promise; + /** @deprecated `fileName` will be ignored */ applyCodeActionCommand(fileName: string, action: CodeActionCommand[]): Promise; + /** @deprecated `fileName` will be ignored */ applyCodeActionCommand(fileName: string, action: CodeActionCommand | CodeActionCommand[]): Promise; getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined): ApplicableRefactorInfo[]; getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string, preferences: UserPreferences | undefined): RefactorEditInfo | undefined; @@ -3884,8 +4831,11 @@ declare namespace ts { type OrganizeImportsScope = CombinedCodeFixScope; type CompletionsTriggerCharacter = "." | '"' | "'" | "`" | "/" | "@" | "<"; interface GetCompletionsAtPositionOptions extends UserPreferences { + /** If the editor is asking for completions because a certain character was typed, and not because the user explicitly requested them, this should be set. */ triggerCharacter?: CompletionsTriggerCharacter; + /** @deprecated Use includeCompletionsForModuleExports */ includeExternalModuleExports?: boolean; + /** @deprecated Use includeCompletionsWithInsertText */ includeInsertTextCompletions?: boolean; } interface ApplyCodeActionCommandResult { @@ -3899,6 +4849,12 @@ declare namespace ts { textSpan: TextSpan; classificationType: ClassificationTypeNames; } + /** + * Navigation bar interface designed for visual studio's dual-column layout. + * This does not form a proper tree. + * The navbar is returned as a list of top-level items, each of which has a list of child items. + * Child items always have an empty array for their `childItems`. + */ interface NavigationBarItem { text: string; kind: ScriptElementKind; @@ -3909,12 +4865,23 @@ declare namespace ts { bolded: boolean; grayed: boolean; } + /** + * Node in a tree of nested declarations in a file. + * The top node is always a script or module node. + */ interface NavigationTree { + /** Name of the declaration, or a short description, e.g. "". */ text: string; kind: ScriptElementKind; + /** ScriptElementKindModifier separated by commas, e.g. "public,abstract" */ kindModifiers: string; + /** + * Spans of the nodes that generated this declaration. + * There will be more than one if this is the result of merging. + */ spans: TextSpan[]; nameSpan: TextSpan | undefined; + /** Present if non-empty */ childItems?: NavigationTree[]; } interface TodoCommentDescriptor { @@ -3936,12 +4903,23 @@ declare namespace ts { isNewFile?: boolean; } interface CodeAction { + /** Description of the code action to display in the UI of the editor */ description: string; + /** Text changes to apply to each file as part of the code action */ changes: FileTextChanges[]; + /** + * If the user accepts the code fix, the editor should send the action back in a `applyAction` request. + * This allows the language service to have side effects (e.g. installing dependencies) upon a code fix. + */ commands?: CodeActionCommand[]; } interface CodeFixAction extends CodeAction { + /** Short name to identify the fix, for use by telemetry. */ fixName: string; + /** + * If present, one may call 'getCombinedCodeFix' with this fixId. + * This may be omitted to indicate that the code fix can't be applied in a group. + */ fixId?: {}; fixAllDescription?: string; } @@ -3952,16 +4930,49 @@ declare namespace ts { type CodeActionCommand = InstallPackageAction; interface InstallPackageAction { } + /** + * A set of one or more available refactoring actions, grouped under a parent refactoring. + */ interface ApplicableRefactorInfo { + /** + * The programmatic name of the refactoring + */ name: string; + /** + * A description of this refactoring category to show to the user. + * If the refactoring gets inlined (see below), this text will not be visible. + */ description: string; + /** + * Inlineable refactorings can have their actions hoisted out to the top level + * of a context menu. Non-inlineanable refactorings should always be shown inside + * their parent grouping. + * + * If not specified, this value is assumed to be 'true' + */ inlineable?: boolean; actions: RefactorActionInfo[]; } + /** + * Represents a single refactoring action - for example, the "Extract Method..." refactor might + * offer several actions, each corresponding to a surround class or closure to extract into. + */ interface RefactorActionInfo { + /** + * The programmatic name of the refactoring action + */ name: string; + /** + * A description of this refactoring action to show to the user. + * If the parent refactoring is inlined away, this will be the only text shown, + * so this description should make sense by itself if the parent is inlineable=true + */ description: string; } + /** + * A set of edits to make in response to a refactor action, plus an optional + * location where renaming should be invoked from + */ interface RefactorEditInfo { edits: FileTextChanges[]; renameFilename?: string; @@ -3970,11 +4981,16 @@ declare namespace ts { } interface TextInsertion { newText: string; + /** The position in newText the caret should point to after the insertion. */ caretOffset: number; } interface DocumentSpan { textSpan: TextSpan; fileName: string; + /** + * If the span represents a location that was remapped (e.g. via a .d.ts.map file), + * then the original filename and span will be specified here + */ originalTextSpan?: TextSpan; originalFileName?: string; } @@ -4146,6 +5162,13 @@ declare namespace ts { displayParts: SymbolDisplayPart[]; isOptional: boolean; } + /** + * Represents a single signature to show in signature help. + * The id is used for subsequent calls into the language service to ask questions about the + * signature help item in the context of any documents that have been updated. i.e. after + * an edit has happened, while signature help is still active, the host can ask important + * questions like 'what parameter is the user currently contained within?'. + */ interface SignatureHelpItem { isVariadic: boolean; prefixDisplayParts: SymbolDisplayPart[]; @@ -4155,6 +5178,9 @@ declare namespace ts { documentation: SymbolDisplayPart[]; tags: JSDocTagInfo[]; } + /** + * Represents a set of signature help items, and the preferred item that should be selected. + */ interface SignatureHelpItems { items: SignatureHelpItem[]; applicableSpan: TextSpan; @@ -4163,8 +5189,12 @@ declare namespace ts { argumentCount: number; } interface CompletionInfo { + /** Not true for all glboal completions. This will be true if the enclosing scope matches a few syntax kinds. See `isSnippetScope`. */ isGlobalCompletion: boolean; isMemberCompletion: boolean; + /** + * true when the current location also allows for a new identifier + */ isNewIdentifierLocation: boolean; entries: CompletionEntry[]; } @@ -4174,6 +5204,11 @@ declare namespace ts { kindModifiers?: string; sortText: string; insertText?: string; + /** + * An optional span that indicates the text to be replaced by this completion item. + * If present, this span should be used instead of the default one. + * It will be set if the required span differs from the one generated by the default replacement behavior. + */ replacementSpan?: TextSpan; hasAction?: true; source?: string; @@ -4190,16 +5225,30 @@ declare namespace ts { source?: SymbolDisplayPart[]; } interface OutliningSpan { + /** The span of the document to actually collapse. */ textSpan: TextSpan; + /** The span of the document to display when the user hovers over the collapsed span. */ hintSpan: TextSpan; + /** The text to display in the editor for the collapsed region. */ bannerText: string; + /** + * Whether or not this region should be automatically collapsed when + * the 'Collapse to Definitions' command is invoked. + */ autoCollapse: boolean; + /** + * Classification of the contents of the span + */ kind: OutliningSpanKind; } enum OutliningSpanKind { + /** Single or multi-line comments */ Comment = "comment", + /** Sections marked by '// #region' and '// #endregion' comments */ Region = "region", + /** Declarations and expressions */ Code = "code", + /** Contiguous blocks of import declarations */ Imports = "imports" } enum OutputFileType { @@ -4236,33 +5285,82 @@ declare namespace ts { classification: TokenClass; } interface Classifier { + /** + * Gives lexical classifications of tokens on a line without any syntactic context. + * For instance, a token consisting of the text 'string' can be either an identifier + * named 'string' or the keyword 'string', however, because this classifier is not aware, + * it relies on certain heuristics to give acceptable results. For classifications where + * speed trumps accuracy, this function is preferable; however, for true accuracy, the + * syntactic classifier is ideal. In fact, in certain editing scenarios, combining the + * lexical, syntactic, and semantic classifiers may issue the best user experience. + * + * @param text The text of a line to classify. + * @param lexState The state of the lexical classifier at the end of the previous line. + * @param syntacticClassifierAbsent Whether the client is *not* using a syntactic classifier. + * If there is no syntactic classifier (syntacticClassifierAbsent=true), + * certain heuristics may be used in its place; however, if there is a + * syntactic classifier (syntacticClassifierAbsent=false), certain + * classifications which may be incorrectly categorized will be given + * back as Identifiers in order to allow the syntactic classifier to + * subsume the classification. + * @deprecated Use getLexicalClassifications instead. + */ getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent: boolean): ClassificationResult; getEncodedLexicalClassifications(text: string, endOfLineState: EndOfLineState, syntacticClassifierAbsent: boolean): Classifications; } enum ScriptElementKind { unknown = "", warning = "warning", + /** predefined type (void) or keyword (class) */ keyword = "keyword", + /** top level script node */ scriptElement = "script", + /** module foo {} */ moduleElement = "module", + /** class X {} */ classElement = "class", + /** var x = class X {} */ localClassElement = "local class", + /** interface Y {} */ interfaceElement = "interface", + /** type T = ... */ typeElement = "type", + /** enum E */ enumElement = "enum", enumMemberElement = "enum member", + /** + * Inside module and script only + * const v = .. + */ variableElement = "var", + /** Inside function */ localVariableElement = "local var", + /** + * Inside module and script only + * function f() { } + */ functionElement = "function", + /** Inside function */ localFunctionElement = "local function", + /** class X { [public|private]* foo() {} } */ memberFunctionElement = "method", + /** class X { [public|private]* [get|set] foo:number; } */ memberGetAccessorElement = "getter", memberSetAccessorElement = "setter", + /** + * class X { [public|private]* foo:number; } + * interface Y { foo:number; } + */ memberVariableElement = "property", + /** class X { constructor() { } } */ constructorImplementationElement = "constructor", + /** interface Y { ():number; } */ callSignatureElement = "call", + /** interface Y { []:number; } */ indexSignatureElement = "index", + /** interface Y { new():Y; } */ constructSignatureElement = "construct", + /** function foo(*Y*: string) */ parameterElement = "parameter", typeParameterElement = "type parameter", primitiveType = "primitive type", @@ -4272,7 +5370,11 @@ declare namespace ts { letElement = "let", directory = "directory", externalModuleName = "external module name", + /** + * + */ jsxAttribute = "JSX attribute", + /** String literal */ string = "string" } enum ScriptElementKindModifier { @@ -4342,12 +5444,62 @@ declare namespace ts { function createClassifier(): Classifier; } declare namespace ts { + /** + * The document registry represents a store of SourceFile objects that can be shared between + * multiple LanguageService instances. A LanguageService instance holds on the SourceFile (AST) + * of files in the context. + * SourceFile objects account for most of the memory usage by the language service. Sharing + * the same DocumentRegistry instance between different instances of LanguageService allow + * for more efficient memory utilization since all projects will share at least the library + * file (lib.d.ts). + * + * A more advanced use of the document registry is to serialize sourceFile objects to disk + * and re-hydrate them when needed. + * + * To create a default DocumentRegistry, use createDocumentRegistry to create one, and pass it + * to all subsequent createLanguageService calls. + */ interface DocumentRegistry { + /** + * Request a stored SourceFile with a given fileName and compilationSettings. + * The first call to acquire will call createLanguageServiceSourceFile to generate + * the SourceFile if was not found in the registry. + * + * @param fileName The name of the file requested + * @param compilationSettings Some compilation settings like target affects the + * shape of a the resulting SourceFile. This allows the DocumentRegistry to store + * multiple copies of the same file for different compilation settings. + * @param scriptSnapshot Text of the file. Only used if the file was not found + * in the registry and a new one was created. + * @param version Current version of the file. Only used if the file was not found + * in the registry and a new one was created. + */ acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; acquireDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; + /** + * Request an updated version of an already existing SourceFile with a given fileName + * and compilationSettings. The update will in-turn call updateLanguageServiceSourceFile + * to get an updated SourceFile. + * + * @param fileName The name of the file requested + * @param compilationSettings Some compilation settings like target affects the + * shape of a the resulting SourceFile. This allows the DocumentRegistry to store + * multiple copies of the same file for different compilation settings. + * @param scriptSnapshot Text of the file. + * @param version Current version of the file. + */ updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; updateDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey; + /** + * Informs the DocumentRegistry that a file is not needed any longer. + * + * Note: It is not allowed to call release on a SourceFile that was not acquired from + * this registry originally. + * + * @param fileName The name of the file to be released + * @param compilationSettings The compilation settings used to acquire the file + */ releaseDocument(fileName: string, compilationSettings: CompilerOptions): void; releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey): void; reportStats(): string; @@ -4378,6 +5530,7 @@ declare namespace ts { function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[], moduleName?: string): string; } declare namespace ts { + /** The version of the language service API */ const servicesVersion = "0.8"; function toEditorSettings(options: EditorOptions | EditorSettings): EditorSettings; function displayPartsToString(displayParts: SymbolDisplayPart[] | undefined): string; @@ -4387,9 +5540,20 @@ declare namespace ts { let disableIncrementalParsing: boolean; function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange | undefined, aggressiveChecks?: boolean): SourceFile; function createLanguageService(host: LanguageServiceHost, documentRegistry?: DocumentRegistry, syntaxOnly?: boolean): LanguageService; + /** + * Get the path of the default library files (lib.d.ts) as distributed with the typescript + * node package. + * The functionality is not supported if the ts module is consumed outside of a node module. + */ function getDefaultLibFilePath(options: CompilerOptions): string; } declare namespace ts { + /** + * Transform one or more nodes using the supplied transformers. + * @param source A single `Node` or an array of `Node` objects. + * @param transformers An array of `TransformerFactory` callbacks used to process the transformation. + * @param compilerOptions Optional compiler options. + */ function transform(source: T | T[], transformers: TransformerFactory[], compilerOptions?: CompilerOptions): TransformationResult; } //# sourceMappingURL=typescriptServices.d.ts.map \ No newline at end of file diff --git a/lib/typescriptServices.js b/lib/typescriptServices.js index 6794e291e7c..c1ead6a1fac 100644 --- a/lib/typescriptServices.js +++ b/lib/typescriptServices.js @@ -15,22 +15,28 @@ and limitations under the License. "use strict"; -var __assign = (this && this.__assign) || Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); }; var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) { if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } return cooked; }; var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + } return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } @@ -39,10 +45,14 @@ var __extends = (this && this.__extends) || (function () { })(); var ts; (function (ts) { + // WARNING: The script `configureNightly.ts` uses a regexp to parse out these values. + // If changing the text in this section, be sure to test `configureNightly` too. ts.versionMajorMinor = "3.0"; + /** The version of the TypeScript compiler release */ ts.version = ts.versionMajorMinor + ".0-dev"; })(ts || (ts = {})); (function (ts) { + /* @internal */ var Comparison; (function (Comparison) { Comparison[Comparison["LessThan"] = -1] = "LessThan"; @@ -50,13 +60,19 @@ var ts; Comparison[Comparison["GreaterThan"] = 1] = "GreaterThan"; })(Comparison = ts.Comparison || (ts.Comparison = {})); })(ts || (ts = {})); +/* @internal */ (function (ts) { + /** Create a MapLike with good performance. */ function createDictionaryObject() { - var map = Object.create(null); + var map = Object.create(/*prototype*/ null); // tslint:disable-line:no-null-keyword + // Using 'delete' on an object causes V8 to put the object in dictionary mode. + // This disables creation of hidden classes, which are expensive when an object is + // constantly changing shape. map.__ = undefined; delete map.__; return map; } + /** Create a new map. If a template object is provided, the map will copy entries from it. */ function createMap() { return new ts.MapCtr(); } @@ -72,6 +88,8 @@ var ts; ts.createMapFromEntries = createMapFromEntries; function createMapFromTemplate(template) { var map = new ts.MapCtr(); + // Copies keys/values from template. Note that for..in will not throw if + // template is undefined, and instead will just exit the loop. for (var key in template) { if (hasOwnProperty.call(template, key)) { map.set(key, template[key]); @@ -80,9 +98,12 @@ var ts; return map; } ts.createMapFromTemplate = createMapFromTemplate; + // Internet Explorer's Map doesn't support iteration, so don't use it. + // tslint:disable-next-line no-in-operator variable-name ts.MapCtr = typeof Map !== "undefined" && "entries" in Map.prototype ? Map : shimMap(); + // Keep the class inside a function so it doesn't get compiled if it's not used. function shimMap() { - var MapIterator = (function () { + var MapIterator = /** @class */ (function () { function MapIterator(data, selector) { this.index = 0; this.data = data; @@ -99,7 +120,7 @@ var ts; }; return MapIterator; }()); - return (function () { + return /** @class */ (function () { function class_1() { this.data = createDictionaryObject(); this.size = 0; @@ -115,6 +136,7 @@ var ts; return this; }; class_1.prototype.has = function (key) { + // tslint:disable-next-line:no-in-operator return key in this.data; }; class_1.prototype.delete = function (key) { @@ -150,6 +172,11 @@ var ts; return array ? array.length : 0; } ts.length = length; + /** + * Iterates through 'array' by index and performs the callback on each element of array until the callback + * returns a truthy value, then returns that value. + * If no such value is found, the callback is applied to each element of array and undefined is returned. + */ function forEach(array, callback) { if (array) { for (var i = 0; i < array.length; i++) { @@ -162,6 +189,7 @@ var ts; return undefined; } ts.forEach = forEach; + /** Like `forEach`, but suitable for use with numbers and strings (which may be falsy). */ function firstDefined(array, callback) { if (array === undefined) { return undefined; @@ -220,6 +248,11 @@ var ts; return map; } ts.zipToMap = zipToMap; + /** + * Iterates through `array` by index and performs the callback on each element of array until the callback + * returns a falsey value, then returns false. + * If no such value is found, the callback is applied to each element of array and `true` is returned. + */ function every(array, callback) { if (array) { for (var i = 0; i < array.length; i++) { @@ -251,6 +284,7 @@ var ts; return undefined; } ts.findLast = findLast; + /** Works like Array.prototype.findIndex, returning `-1` if no element satisfying the predicate is found. */ function findIndex(array, predicate, startIndex) { for (var i = startIndex || 0; i < array.length; i++) { if (predicate(array[i], i)) { @@ -269,6 +303,10 @@ var ts; return -1; } ts.findLastIndex = findLastIndex; + /** + * Returns the first truthy result of `callback`, or else fails. + * This is like `forEach`, but never returns undefined. + */ function findMap(array, callback) { for (var i = 0; i < array.length; i++) { var result = callback(array[i], i); @@ -599,6 +637,7 @@ var ts; return false; } ts.some = some; + /** Calls the callback with (start, afterEnd) index pairs for each range where 'pred' is true. */ function getRangesWhere(arr, pred, cb) { var start; for (var i = 0; i < arr.length; i++) { @@ -625,6 +664,8 @@ var ts; } ts.concatenate = concatenate; function deduplicateRelational(array, equalityComparer, comparer) { + // Perform a stable sort of the array. This ensures the first entry in a list of + // duplicates remains the first entry in the result. var indices = array.map(function (_, i) { return i; }); stableSortIndices(array, indices, comparer); var last = array[indices[0]]; @@ -637,6 +678,7 @@ var ts; last = item; } } + // restore original order deduplicated.sort(); return deduplicated.map(function (i) { return array[i]; }); } @@ -666,10 +708,13 @@ var ts; for (var i = 1; i < array.length; i++) { var next = array[i]; switch (comparer(next, last)) { + // equality comparison case true: - case 0: + // relational comparison + case 0 /* EqualTo */: continue; - case -1: + case -1 /* LessThan */: + // If `array` is sorted, `next` should **never** be less than `last`. return Debug.fail("Array is unsorted."); } deduplicated.push(last = next); @@ -725,25 +770,41 @@ var ts; return result || array; } ts.compact = compact; + /** + * Gets the relative complement of `arrayA` with respect to `arrayB`, returning the elements that + * are not present in `arrayA` but are present in `arrayB`. Assumes both arrays are sorted + * based on the provided comparer. + */ function relativeComplement(arrayA, arrayB, comparer) { if (!arrayB || !arrayA || arrayB.length === 0 || arrayA.length === 0) return arrayB; var result = []; loopB: for (var offsetA = 0, offsetB = 0; offsetB < arrayB.length; offsetB++) { if (offsetB > 0) { - Debug.assertGreaterThanOrEqual(comparer(arrayB[offsetB], arrayB[offsetB - 1]), 0); + // Ensure `arrayB` is properly sorted. + Debug.assertGreaterThanOrEqual(comparer(arrayB[offsetB], arrayB[offsetB - 1]), 0 /* EqualTo */); } loopA: for (var startA = offsetA; offsetA < arrayA.length; offsetA++) { if (offsetA > startA) { - Debug.assertGreaterThanOrEqual(comparer(arrayA[offsetA], arrayA[offsetA - 1]), 0); + // Ensure `arrayA` is properly sorted. We only need to perform this check if + // `offsetA` has changed since we entered the loop. + Debug.assertGreaterThanOrEqual(comparer(arrayA[offsetA], arrayA[offsetA - 1]), 0 /* EqualTo */); } switch (comparer(arrayB[offsetB], arrayA[offsetA])) { - case -1: + case -1 /* LessThan */: + // If B is less than A, B does not exist in arrayA. Add B to the result and + // move to the next element in arrayB without changing the current position + // in arrayA. result.push(arrayB[offsetB]); continue loopB; - case 0: + case 0 /* EqualTo */: + // If B is equal to A, B exists in arrayA. Move to the next element in + // arrayB without adding B to the result or changing the current position + // in arrayA. continue loopB; - case 1: + case 1 /* GreaterThan */: + // If B is greater than A, we need to keep looking for B in arrayA. Move to + // the next element in arrayA and recheck. continue loopA; } } @@ -769,6 +830,10 @@ var ts; return to; } ts.append = append; + /** + * Gets the actual offset into an array for a relative offset. Negative offsets indicate a + * position offset from the end of the array. + */ function toOffset(array, offset) { return offset < 0 ? array.length + offset : offset; } @@ -787,6 +852,9 @@ var ts; return to; } ts.addRange = addRange; + /** + * @return Whether the value was added. + */ function pushIfUnique(array, toAdd, equalityComparer) { if (contains(array, toAdd, equalityComparer)) { return false; @@ -797,6 +865,9 @@ var ts; } } ts.pushIfUnique = pushIfUnique; + /** + * Unlike `pushIfUnique`, this can take `undefined` as an input, and returns a new array. + */ function appendIfUnique(array, toAdd, equalityComparer) { if (array) { pushIfUnique(array, toAdd, equalityComparer); @@ -808,8 +879,12 @@ var ts; } ts.appendIfUnique = appendIfUnique; function stableSortIndices(array, indices, comparer) { + // sort indices by value then position indices.sort(function (x, y) { return comparer(array[x], array[y]) || compareValues(x, y); }); } + /** + * Returns a new sorted array. + */ function sort(array, comparer) { return array.slice().sort(comparer); } @@ -844,6 +919,9 @@ var ts; } }; } ts.arrayIterator = arrayIterator; + /** + * Stable sort of an array. Elements equal to each other maintain their relative position in the array. + */ function stableSort(array, comparer) { var indices = array.map(function (_, i) { return i; }); stableSortIndices(array, indices, comparer); @@ -860,6 +938,10 @@ var ts; return true; } ts.rangeEquals = rangeEquals; + /** + * Returns the element at a specific offset in an array if non-empty, `undefined` otherwise. + * A negative offset indicates the element should be retrieved from the end of the array. + */ function elementAt(array, offset) { if (array) { offset = toOffset(array, offset); @@ -870,6 +952,9 @@ var ts; return undefined; } ts.elementAt = elementAt; + /** + * Returns the first element of an array if non-empty, `undefined` otherwise. + */ function firstOrUndefined(array) { return array.length === 0 ? undefined : array[0]; } @@ -879,6 +964,9 @@ var ts; return array[0]; } ts.first = first; + /** + * Returns the last element of an array if non-empty, `undefined` otherwise. + */ function lastOrUndefined(array) { return array.length === 0 ? undefined : array[array.length - 1]; } @@ -888,6 +976,9 @@ var ts; return array[array.length - 1]; } ts.last = last; + /** + * Returns the only element of an array if it contains only one element, `undefined` otherwise. + */ function singleOrUndefined(array) { return array && array.length === 1 ? array[0] @@ -906,6 +997,17 @@ var ts; return result; } ts.replaceElement = replaceElement; + /** + * Performs a binary search, finding the index at which `value` occurs in `array`. + * If no such index is found, returns the 2's-complement of first index at which + * `array[index]` exceeds `value`. + * @param array A sorted array whose first element must be no larger than number + * @param value The value to be searched for in the array. + * @param keySelector A callback used to select the search key from `value` and each element of + * `array`. + * @param keyComparer A callback used to compare two keys in a sorted array. + * @param offset An offset into `array` at which to start the search. + */ function binarySearch(array, value, keySelector, keyComparer, offset) { if (!array || array.length === 0) { return -1; @@ -917,12 +1019,12 @@ var ts; var middle = low + ((high - low) >> 1); var midKey = keySelector(array[middle]); switch (keyComparer(midKey, key)) { - case -1: + case -1 /* LessThan */: low = middle + 1; break; - case 0: + case 0 /* EqualTo */: return middle; - case 1: + case 1 /* GreaterThan */: high = middle - 1; break; } @@ -955,14 +1057,29 @@ var ts; } ts.reduceLeft = reduceLeft; var hasOwnProperty = Object.prototype.hasOwnProperty; + /** + * Indicates whether a map-like contains an own property with the specified key. + * + * @param map A map-like. + * @param key A property key. + */ function hasProperty(map, key) { return hasOwnProperty.call(map, key); } ts.hasProperty = hasProperty; + /** + * Gets the value of an owned property in a map-like. + * + * @param map A map-like. + * @param key A property key. + */ function getProperty(map, key) { return hasOwnProperty.call(map, key) ? map[key] : undefined; } ts.getProperty = getProperty; + /** + * Gets the owned, enumerable property keys of a map-like. + */ function getOwnKeys(map) { var keys = []; for (var key in map) { @@ -1001,13 +1118,19 @@ var ts; var arg = args_1[_a]; for (var p in arg) { if (hasProperty(arg, p)) { - t[p] = arg[p]; + t[p] = arg[p]; // TODO: GH#23368 } } } return t; } ts.assign = assign; + /** + * Performs a shallow equality comparison of the contents of two map-likes. + * + * @param left A map-like whose properties should be compared. + * @param right A map-like whose properties should be compared. + */ function equalOwnProperties(left, right, equalityComparer) { if (equalityComparer === void 0) { equalityComparer = equateValues; } if (left === right) @@ -1118,6 +1241,9 @@ var ts; } } } + /** + * Tests whether a value is an array. + */ function isArray(value) { return Array.isArray ? Array.isArray(value) : value instanceof Array; } @@ -1126,6 +1252,9 @@ var ts; return isArray(value) ? value : [value]; } ts.toArray = toArray; + /** + * Tests whether a value is string + */ function isString(text) { return typeof text === "string"; } @@ -1140,16 +1269,22 @@ var ts; return Debug.fail("Invalid cast. The supplied value " + value + " did not pass the test '" + Debug.getFunctionName(test) + "'."); } ts.cast = cast; - function noop(_) { } + /** Does nothing. */ + function noop(_) { } // tslint:disable-line no-empty ts.noop = noop; + /** Do nothing and return false */ function returnFalse() { return false; } ts.returnFalse = returnFalse; + /** Do nothing and return true */ function returnTrue() { return true; } ts.returnTrue = returnTrue; + /** Returns its argument. */ function identity(x) { return x; } ts.identity = identity; + /** Returns lower case string */ function toLowerCase(x) { return x.toLowerCase(); } ts.toLowerCase = toLowerCase; + /** Throws an error because a function is not implemented. */ function notImplemented() { throw new Error("Not implemented"); } @@ -1224,7 +1359,7 @@ var ts; })(AssertionLevel = ts.AssertionLevel || (ts.AssertionLevel = {})); var Debug; (function (Debug) { - Debug.currentAssertionLevel = 0; + Debug.currentAssertionLevel = 0 /* None */; Debug.isDebugging = false; function shouldAssert(level) { return Debug.currentAssertionLevel >= level; @@ -1310,6 +1445,14 @@ var ts; return a === b; } ts.equateValues = equateValues; + /** + * Compare the equality of two strings using a case-sensitive ordinal comparison. + * + * Case-sensitive comparisons compare both strings one code-point at a time using the integer + * value of each code-point after applying `toUpperCase` to each string. We always map both + * strings to their upper-case form as some unicode characters do not properly round-trip to + * lowercase (such as `ẞ` (German sharp capital s)). + */ function equateStringsCaseInsensitive(a, b) { return a === b || a !== undefined @@ -1317,37 +1460,69 @@ var ts; && a.toUpperCase() === b.toUpperCase(); } ts.equateStringsCaseInsensitive = equateStringsCaseInsensitive; + /** + * Compare the equality of two strings using a case-sensitive ordinal comparison. + * + * Case-sensitive comparisons compare both strings one code-point at a time using the + * integer value of each code-point. + */ function equateStringsCaseSensitive(a, b) { return equateValues(a, b); } ts.equateStringsCaseSensitive = equateStringsCaseSensitive; function compareComparableValues(a, b) { - return a === b ? 0 : - a === undefined ? -1 : - b === undefined ? 1 : - a < b ? -1 : - 1; + return a === b ? 0 /* EqualTo */ : + a === undefined ? -1 /* LessThan */ : + b === undefined ? 1 /* GreaterThan */ : + a < b ? -1 /* LessThan */ : + 1 /* GreaterThan */; } + /** + * Compare two numeric values for their order relative to each other. + * To compare strings, use any of the `compareStrings` functions. + */ function compareValues(a, b) { return compareComparableValues(a, b); } ts.compareValues = compareValues; function min(a, b, compare) { - return compare(a, b) === -1 ? a : b; + return compare(a, b) === -1 /* LessThan */ ? a : b; } ts.min = min; + /** + * Compare two strings using a case-insensitive ordinal comparison. + * + * Ordinal comparisons are based on the difference between the unicode code points of both + * strings. Characters with multiple unicode representations are considered unequal. Ordinal + * comparisons provide predictable ordering, but place "a" after "B". + * + * Case-insensitive comparisons compare both strings one code-point at a time using the integer + * value of each code-point after applying `toUpperCase` to each string. We always map both + * strings to their upper-case form as some unicode characters do not properly round-trip to + * lowercase (such as `ẞ` (German sharp capital s)). + */ function compareStringsCaseInsensitive(a, b) { if (a === b) - return 0; + return 0 /* EqualTo */; if (a === undefined) - return -1; + return -1 /* LessThan */; if (b === undefined) - return 1; + return 1 /* GreaterThan */; a = a.toUpperCase(); b = b.toUpperCase(); - return a < b ? -1 : a > b ? 1 : 0; + return a < b ? -1 /* LessThan */ : a > b ? 1 /* GreaterThan */ : 0 /* EqualTo */; } ts.compareStringsCaseInsensitive = compareStringsCaseInsensitive; + /** + * Compare two strings using a case-sensitive ordinal comparison. + * + * Ordinal comparisons are based on the difference between the unicode code points of both + * strings. Characters with multiple unicode representations are considered unequal. Ordinal + * comparisons provide predictable ordering, but place "a" after "B". + * + * Case-sensitive comparisons compare both strings one code-point at a time using the integer + * value of each code-point. + */ function compareStringsCaseSensitive(a, b) { return compareComparableValues(a, b); } @@ -1356,6 +1531,9 @@ var ts; return ignoreCase ? compareStringsCaseInsensitive : compareStringsCaseSensitive; } ts.getStringComparer = getStringComparer; + /** + * Creates a string comparer for use with string collation in the UI. + */ var createUIStringComparer = (function () { var defaultComparer; var enUSComparer; @@ -1363,19 +1541,22 @@ var ts; return createStringComparer; function compareWithCallback(a, b, comparer) { if (a === b) - return 0; + return 0 /* EqualTo */; if (a === undefined) - return -1; + return -1 /* LessThan */; if (b === undefined) - return 1; + return 1 /* GreaterThan */; var value = comparer(a, b); - return value < 0 ? -1 : value > 0 ? 1 : 0; + return value < 0 ? -1 /* LessThan */ : value > 0 ? 1 /* GreaterThan */ : 0 /* EqualTo */; } function createIntlCollatorStringComparer(locale) { + // Intl.Collator.prototype.compare is bound to the collator. See NOTE in + // http://www.ecma-international.org/ecma-402/2.0/#sec-Intl.Collator.prototype.compare var comparer = new Intl.Collator(locale, { usage: "sort", sensitivity: "variant" }).compare; return function (a, b) { return compareWithCallback(a, b, comparer); }; } function createLocaleCompareStringComparer(locale) { + // if the locale is not the default locale (`undefined`), use the fallback comparer. if (locale !== undefined) return createFallbackStringComparer(); return function (a, b) { return compareWithCallback(a, b, compareStrings); }; @@ -1384,26 +1565,39 @@ var ts; } } function createFallbackStringComparer() { + // An ordinal comparison puts "A" after "b", but for the UI we want "A" before "b". + // We first sort case insensitively. So "Aaa" will come before "baa". + // Then we sort case sensitively, so "aaa" will come before "Aaa". + // + // For case insensitive comparisons we always map both strings to their + // upper-case form as some unicode characters do not properly round-trip to + // lowercase (such as `ẞ` (German sharp capital s)). return function (a, b) { return compareWithCallback(a, b, compareDictionaryOrder); }; function compareDictionaryOrder(a, b) { return compareStrings(a.toUpperCase(), b.toUpperCase()) || compareStrings(a, b); } function compareStrings(a, b) { - return a < b ? -1 : a > b ? 1 : 0; + return a < b ? -1 /* LessThan */ : a > b ? 1 /* GreaterThan */ : 0 /* EqualTo */; } } function getStringComparerFactory() { + // If the host supports Intl, we use it for comparisons using the default locale. if (typeof Intl === "object" && typeof Intl.Collator === "function") { return createIntlCollatorStringComparer; } + // If the host does not support Intl, we fall back to localeCompare. + // localeCompare in Node v0.10 is just an ordinal comparison, so don't use it. if (typeof String.prototype.localeCompare === "function" && typeof String.prototype.toLocaleUpperCase === "function" && "a".localeCompare("B") < 0) { return createLocaleCompareStringComparer; } + // Otherwise, fall back to ordinal comparison: return createFallbackStringComparer; } function createStringComparer(locale) { + // Hold onto common string comparers. This avoids constantly reallocating comparers during + // tests. if (locale === undefined) { return defaultComparer || (defaultComparer = stringComparerFactory(locale)); } @@ -1428,25 +1622,50 @@ var ts; } } ts.setUILocale = setUILocale; + /** + * Compare two strings in a using the case-sensitive sort behavior of the UI locale. + * + * Ordering is not predictable between different host locales, but is best for displaying + * ordered data for UI presentation. Characters with multiple unicode representations may + * be considered equal. + * + * Case-sensitive comparisons compare strings that differ in base characters, or + * accents/diacritic marks, or case as unequal. + */ function compareStringsCaseSensitiveUI(a, b) { var comparer = uiComparerCaseSensitive || (uiComparerCaseSensitive = createUIStringComparer(uiLocale)); return comparer(a, b); } ts.compareStringsCaseSensitiveUI = compareStringsCaseSensitiveUI; function compareProperties(a, b, key, comparer) { - return a === b ? 0 : - a === undefined ? -1 : - b === undefined ? 1 : + return a === b ? 0 /* EqualTo */ : + a === undefined ? -1 /* LessThan */ : + b === undefined ? 1 /* GreaterThan */ : comparer(a[key], b[key]); } ts.compareProperties = compareProperties; + /** True is greater than false. */ function compareBooleans(a, b) { return compareValues(a ? 1 : 0, b ? 1 : 0); } ts.compareBooleans = compareBooleans; + /** + * Given a name and a list of names that are *not* equal to the name, return a spelling suggestion if there is one that is close enough. + * Names less than length 3 only check for case-insensitive equality, not Levenshtein distance. + * + * If there is a candidate that's the same except for case, return that. + * If there is a candidate that's within one edit of the name, return that. + * Otherwise, return the candidate with the smallest Levenshtein distance, + * except for candidates: + * * With no name + * * Whose length differs from the target name by more than 0.34 of the length of the name. + * * Whose levenshtein distance is more than 0.4 of the length of the name + * (0.4 allows 1 substitution/transposition for every 5 characters, + * and 1 insertion/deletion at 3 characters) + */ function getSpellingSuggestion(name, candidates, getName) { var maximumLengthDifference = Math.min(2, Math.floor(name.length * 0.34)); - var bestDistance = Math.floor(name.length * 0.4) + 1; + var bestDistance = Math.floor(name.length * 0.4) + 1; // If the best result isn't better than this, don't bother. var bestCandidate; var justCheckExactMatches = false; var nameLowerCase = name.toLowerCase(); @@ -1462,8 +1681,10 @@ var ts; continue; } if (candidateName.length < 3) { + // Don't bother, user would have noticed a 2-character name having an extra character continue; } + // Only care about a result better than the best so far. var distance = levenshteinWithMax(nameLowerCase, candidateNameLowerCase, bestDistance - 1); if (distance === undefined) { continue; @@ -1473,7 +1694,7 @@ var ts; bestCandidate = candidate; } else { - Debug.assert(distance < bestDistance); + Debug.assert(distance < bestDistance); // Else `levenshteinWithMax` should return undefined bestDistance = distance; bestCandidate = candidate; } @@ -1485,6 +1706,7 @@ var ts; function levenshteinWithMax(s1, s2, max) { var previous = new Array(s2.length + 1); var current = new Array(s2.length + 1); + /** Represents any value > max. We don't care about the particular value. */ var big = max + 1; for (var i = 0; i <= s2.length; i++) { previous[i] = i; @@ -1494,6 +1716,7 @@ var ts; var minJ = i > max ? i - max : 1; var maxJ = s2.length > max + i ? max + i : s2.length; current[0] = i; + /** Smallest value of the matrix in the ith column. */ var colMin = i; for (var j = 1; j < minJ; j++) { current[j] = big; @@ -1501,7 +1724,7 @@ var ts; for (var j = minJ; j <= maxJ; j++) { var dist = c1 === s2.charCodeAt(j - 1) ? previous[j - 1] - : Math.min(previous[j] + 1, current[j - 1] + 1, previous[j - 1] + 2); + : Math.min(/*delete*/ previous[j] + 1, /*insert*/ current[j - 1] + 1, /*substitute*/ previous[j - 1] + 2); current[j] = dist; colMin = Math.min(colMin, dist); } @@ -1509,6 +1732,7 @@ var ts; current[j] = big; } if (colMin > max) { + // Give up -- everything in this column is > max and it can't get better in future columns. return undefined; } var temp = previous; @@ -1549,11 +1773,17 @@ var ts; return false; } ts.fileExtensionIsOneOf = fileExtensionIsOneOf; + /** + * Takes a string like "jquery-min.4.2.3" and returns "jquery" + */ function removeMinAndVersionNumbers(fileName) { + // Match a "." or "-" followed by a version number or 'min' at the end of the name var trailingMinOrVersion = /[.-]((min)|(\d+(\.\d+)*))$/; + // The "min" or version may both be present, in either order, so try applying the above twice. return fileName.replace(trailingMinOrVersion, "").replace(trailingMinOrVersion, ""); } ts.removeMinAndVersionNumbers = removeMinAndVersionNumbers; + /** Remove an item from an array, moving everything to its right one space left. */ function orderedRemoveItem(array, item) { for (var i = 0; i < array.length; i++) { if (array[i] === item) { @@ -1564,7 +1794,9 @@ var ts; return false; } ts.orderedRemoveItem = orderedRemoveItem; + /** Remove an item by index from an array, moving everything to its right one space left. */ function orderedRemoveItemAt(array, index) { + // This seems to be faster than either `array.splice(i, 1)` or `array.copyWithin(i, i+ 1)`. for (var i = index; i < array.length - 1; i++) { array[i] = array[i + 1]; } @@ -1572,14 +1804,17 @@ var ts; } ts.orderedRemoveItemAt = orderedRemoveItemAt; function unorderedRemoveItemAt(array, index) { + // Fill in the "hole" left at `index`. array[index] = array[array.length - 1]; array.pop(); } ts.unorderedRemoveItemAt = unorderedRemoveItemAt; + /** Remove the *first* occurrence of `item` from the array. */ function unorderedRemoveItem(array, item) { return unorderedRemoveFirstItemWhere(array, function (element) { return element === item; }); } ts.unorderedRemoveItem = unorderedRemoveItem; + /** Remove the *first* element satisfying `predicate`. */ function unorderedRemoveFirstItemWhere(array, predicate) { for (var i = 0; i < array.length; i++) { if (predicate(array[i])) { @@ -1598,13 +1833,19 @@ var ts; return prefix + "*" + suffix; } ts.patternText = patternText; + /** + * Given that candidate matches pattern, returns the text matching the '*'. + * E.g.: matchedText(tryParsePattern("foo*baz"), "foobarbaz") === "bar" + */ function matchedText(pattern, candidate) { Debug.assert(isPatternMatch(pattern, candidate)); return candidate.substring(pattern.prefix.length, candidate.length - pattern.suffix.length); } ts.matchedText = matchedText; + /** Return the object corresponding to the best pattern to match `candidate`. */ function findBestPatternMatch(values, getPattern, candidate) { var matchedValue; + // use length of prefix as betterness criteria var longestMatchPrefixLength = -1; for (var _i = 0, values_2 = values; _i < values_2.length; _i++) { var v = values_2[_i]; @@ -1643,7 +1884,7 @@ var ts; return function (arg) { return f(arg) || g(arg); }; } ts.or = or; - function assertTypeIsNever(_) { } + function assertTypeIsNever(_) { } // tslint:disable-line no-empty ts.assertTypeIsNever = assertTypeIsNever; function singleElementArray(t) { return t === undefined ? undefined : [t]; @@ -1659,11 +1900,11 @@ var ts; var newItem = newItems[newIndex]; var oldItem = oldItems[oldIndex]; var compareResult = comparer(newItem, oldItem); - if (compareResult === -1) { + if (compareResult === -1 /* LessThan */) { inserted(newItem); newIndex++; } - else if (compareResult === 1) { + else if (compareResult === 1 /* GreaterThan */) { deleted(oldItem); oldIndex++; } @@ -1682,19 +1923,29 @@ var ts; } ts.enumerateInsertsAndDeletes = enumerateInsertsAndDeletes; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { + /** Gets a timestamp with (at least) ms resolution */ ts.timestamp = typeof performance !== "undefined" && performance.now ? function () { return performance.now(); } : Date.now ? Date.now : function () { return +(new Date()); }; })(ts || (ts = {})); +/*@internal*/ +/** Performance measurements for the compiler. */ (function (ts) { var performance; (function (performance) { + // NOTE: cannot use ts.noop as core.ts loads after this var profilerEvent = typeof onProfilerEvent === "function" && onProfilerEvent.profiler === true ? onProfilerEvent : function () { }; var enabled = false; var profilerStart = 0; var counts; var marks; var measures; + /** + * Marks a performance event. + * + * @param markName The name of the mark. + */ function mark(markName) { if (enabled) { marks.set(markName, ts.timestamp()); @@ -1703,6 +1954,15 @@ var ts; } } performance.mark = mark; + /** + * Adds a performance measurement with the specified name. + * + * @param measureName The name of the performance measurement. + * @param startMarkName The name of the starting mark. If not supplied, the point at which the + * profiler was enabled is used. + * @param endMarkName The name of the ending mark. If not supplied, the current timestamp is + * used. + */ function measure(measureName, startMarkName, endMarkName) { if (enabled) { var end = endMarkName && marks.get(endMarkName) || ts.timestamp(); @@ -1711,20 +1971,36 @@ var ts; } } performance.measure = measure; + /** + * Gets the number of times a marker was encountered. + * + * @param markName The name of the mark. + */ function getCount(markName) { return counts && counts.get(markName) || 0; } performance.getCount = getCount; + /** + * Gets the total duration of all measurements with the supplied name. + * + * @param measureName The name of the measure whose durations should be accumulated. + */ function getDuration(measureName) { return measures && measures.get(measureName) || 0; } performance.getDuration = getDuration; + /** + * Iterate over each measure, performing some action + * + * @param cb The action to perform for each measure + */ function forEachMeasure(cb) { measures.forEach(function (measure, key) { cb(key, measure); }); } performance.forEachMeasure = forEachMeasure; + /** Enables (and resets) performance measurements for the compiler. */ function enable() { counts = ts.createMap(); marks = ts.createMap(); @@ -1733,6 +2009,7 @@ var ts; profilerStart = ts.timestamp(); } performance.enable = enable; + /** Disables performance measurements for the compiler. */ function disable() { enabled = false; } @@ -1741,6 +2018,8 @@ var ts; })(ts || (ts = {})); var ts; (function (ts) { + // token > SyntaxKind.Identifier => token is a keyword + // Also, If you add a new SyntaxKind be sure to keep the `Markers` section at the bottom in sync var SyntaxKind; (function (SyntaxKind) { SyntaxKind[SyntaxKind["Unknown"] = 0] = "Unknown"; @@ -1749,17 +2028,23 @@ var ts; SyntaxKind[SyntaxKind["MultiLineCommentTrivia"] = 3] = "MultiLineCommentTrivia"; SyntaxKind[SyntaxKind["NewLineTrivia"] = 4] = "NewLineTrivia"; SyntaxKind[SyntaxKind["WhitespaceTrivia"] = 5] = "WhitespaceTrivia"; + // We detect and preserve #! on the first line SyntaxKind[SyntaxKind["ShebangTrivia"] = 6] = "ShebangTrivia"; + // We detect and provide better error recovery when we encounter a git merge marker. This + // allows us to edit files with git-conflict markers in them in a much more pleasant manner. SyntaxKind[SyntaxKind["ConflictMarkerTrivia"] = 7] = "ConflictMarkerTrivia"; + // Literals SyntaxKind[SyntaxKind["NumericLiteral"] = 8] = "NumericLiteral"; SyntaxKind[SyntaxKind["StringLiteral"] = 9] = "StringLiteral"; SyntaxKind[SyntaxKind["JsxText"] = 10] = "JsxText"; SyntaxKind[SyntaxKind["JsxTextAllWhiteSpaces"] = 11] = "JsxTextAllWhiteSpaces"; SyntaxKind[SyntaxKind["RegularExpressionLiteral"] = 12] = "RegularExpressionLiteral"; SyntaxKind[SyntaxKind["NoSubstitutionTemplateLiteral"] = 13] = "NoSubstitutionTemplateLiteral"; + // Pseudo-literals SyntaxKind[SyntaxKind["TemplateHead"] = 14] = "TemplateHead"; SyntaxKind[SyntaxKind["TemplateMiddle"] = 15] = "TemplateMiddle"; SyntaxKind[SyntaxKind["TemplateTail"] = 16] = "TemplateTail"; + // Punctuation SyntaxKind[SyntaxKind["OpenBraceToken"] = 17] = "OpenBraceToken"; SyntaxKind[SyntaxKind["CloseBraceToken"] = 18] = "CloseBraceToken"; SyntaxKind[SyntaxKind["OpenParenToken"] = 19] = "OpenParenToken"; @@ -1801,6 +2086,7 @@ var ts; SyntaxKind[SyntaxKind["QuestionToken"] = 55] = "QuestionToken"; SyntaxKind[SyntaxKind["ColonToken"] = 56] = "ColonToken"; SyntaxKind[SyntaxKind["AtToken"] = 57] = "AtToken"; + // Assignments SyntaxKind[SyntaxKind["EqualsToken"] = 58] = "EqualsToken"; SyntaxKind[SyntaxKind["PlusEqualsToken"] = 59] = "PlusEqualsToken"; SyntaxKind[SyntaxKind["MinusEqualsToken"] = 60] = "MinusEqualsToken"; @@ -1814,7 +2100,9 @@ var ts; SyntaxKind[SyntaxKind["AmpersandEqualsToken"] = 68] = "AmpersandEqualsToken"; SyntaxKind[SyntaxKind["BarEqualsToken"] = 69] = "BarEqualsToken"; SyntaxKind[SyntaxKind["CaretEqualsToken"] = 70] = "CaretEqualsToken"; + // Identifiers SyntaxKind[SyntaxKind["Identifier"] = 71] = "Identifier"; + // Reserved words SyntaxKind[SyntaxKind["BreakKeyword"] = 72] = "BreakKeyword"; SyntaxKind[SyntaxKind["CaseKeyword"] = 73] = "CaseKeyword"; SyntaxKind[SyntaxKind["CatchKeyword"] = 74] = "CatchKeyword"; @@ -1851,6 +2139,7 @@ var ts; SyntaxKind[SyntaxKind["VoidKeyword"] = 105] = "VoidKeyword"; SyntaxKind[SyntaxKind["WhileKeyword"] = 106] = "WhileKeyword"; SyntaxKind[SyntaxKind["WithKeyword"] = 107] = "WithKeyword"; + // Strict mode reserved words SyntaxKind[SyntaxKind["ImplementsKeyword"] = 108] = "ImplementsKeyword"; SyntaxKind[SyntaxKind["InterfaceKeyword"] = 109] = "InterfaceKeyword"; SyntaxKind[SyntaxKind["LetKeyword"] = 110] = "LetKeyword"; @@ -1860,6 +2149,7 @@ var ts; SyntaxKind[SyntaxKind["PublicKeyword"] = 114] = "PublicKeyword"; SyntaxKind[SyntaxKind["StaticKeyword"] = 115] = "StaticKeyword"; SyntaxKind[SyntaxKind["YieldKeyword"] = 116] = "YieldKeyword"; + // Contextual keywords SyntaxKind[SyntaxKind["AbstractKeyword"] = 117] = "AbstractKeyword"; SyntaxKind[SyntaxKind["AsKeyword"] = 118] = "AsKeyword"; SyntaxKind[SyntaxKind["AnyKeyword"] = 119] = "AnyKeyword"; @@ -1889,11 +2179,15 @@ var ts; SyntaxKind[SyntaxKind["FromKeyword"] = 143] = "FromKeyword"; SyntaxKind[SyntaxKind["GlobalKeyword"] = 144] = "GlobalKeyword"; SyntaxKind[SyntaxKind["OfKeyword"] = 145] = "OfKeyword"; + // Parse tree nodes + // Names SyntaxKind[SyntaxKind["QualifiedName"] = 146] = "QualifiedName"; SyntaxKind[SyntaxKind["ComputedPropertyName"] = 147] = "ComputedPropertyName"; + // Signature elements SyntaxKind[SyntaxKind["TypeParameter"] = 148] = "TypeParameter"; SyntaxKind[SyntaxKind["Parameter"] = 149] = "Parameter"; SyntaxKind[SyntaxKind["Decorator"] = 150] = "Decorator"; + // TypeMember SyntaxKind[SyntaxKind["PropertySignature"] = 151] = "PropertySignature"; SyntaxKind[SyntaxKind["PropertyDeclaration"] = 152] = "PropertyDeclaration"; SyntaxKind[SyntaxKind["MethodSignature"] = 153] = "MethodSignature"; @@ -1904,6 +2198,7 @@ var ts; SyntaxKind[SyntaxKind["CallSignature"] = 158] = "CallSignature"; SyntaxKind[SyntaxKind["ConstructSignature"] = 159] = "ConstructSignature"; SyntaxKind[SyntaxKind["IndexSignature"] = 160] = "IndexSignature"; + // Type SyntaxKind[SyntaxKind["TypePredicate"] = 161] = "TypePredicate"; SyntaxKind[SyntaxKind["TypeReference"] = 162] = "TypeReference"; SyntaxKind[SyntaxKind["FunctionType"] = 163] = "FunctionType"; @@ -1923,9 +2218,11 @@ var ts; SyntaxKind[SyntaxKind["MappedType"] = 177] = "MappedType"; SyntaxKind[SyntaxKind["LiteralType"] = 178] = "LiteralType"; SyntaxKind[SyntaxKind["ImportType"] = 179] = "ImportType"; + // Binding patterns SyntaxKind[SyntaxKind["ObjectBindingPattern"] = 180] = "ObjectBindingPattern"; SyntaxKind[SyntaxKind["ArrayBindingPattern"] = 181] = "ArrayBindingPattern"; SyntaxKind[SyntaxKind["BindingElement"] = 182] = "BindingElement"; + // Expression SyntaxKind[SyntaxKind["ArrayLiteralExpression"] = 183] = "ArrayLiteralExpression"; SyntaxKind[SyntaxKind["ObjectLiteralExpression"] = 184] = "ObjectLiteralExpression"; SyntaxKind[SyntaxKind["PropertyAccessExpression"] = 185] = "PropertyAccessExpression"; @@ -1954,8 +2251,10 @@ var ts; SyntaxKind[SyntaxKind["AsExpression"] = 208] = "AsExpression"; SyntaxKind[SyntaxKind["NonNullExpression"] = 209] = "NonNullExpression"; SyntaxKind[SyntaxKind["MetaProperty"] = 210] = "MetaProperty"; + // Misc SyntaxKind[SyntaxKind["TemplateSpan"] = 211] = "TemplateSpan"; SyntaxKind[SyntaxKind["SemicolonClassElement"] = 212] = "SemicolonClassElement"; + // Element SyntaxKind[SyntaxKind["Block"] = 213] = "Block"; SyntaxKind[SyntaxKind["VariableStatement"] = 214] = "VariableStatement"; SyntaxKind[SyntaxKind["EmptyStatement"] = 215] = "EmptyStatement"; @@ -1997,7 +2296,9 @@ var ts; SyntaxKind[SyntaxKind["NamedExports"] = 251] = "NamedExports"; SyntaxKind[SyntaxKind["ExportSpecifier"] = 252] = "ExportSpecifier"; SyntaxKind[SyntaxKind["MissingDeclaration"] = 253] = "MissingDeclaration"; + // Module references SyntaxKind[SyntaxKind["ExternalModuleReference"] = 254] = "ExternalModuleReference"; + // JSX SyntaxKind[SyntaxKind["JsxElement"] = 255] = "JsxElement"; SyntaxKind[SyntaxKind["JsxSelfClosingElement"] = 256] = "JsxSelfClosingElement"; SyntaxKind[SyntaxKind["JsxOpeningElement"] = 257] = "JsxOpeningElement"; @@ -2009,20 +2310,27 @@ var ts; SyntaxKind[SyntaxKind["JsxAttributes"] = 263] = "JsxAttributes"; SyntaxKind[SyntaxKind["JsxSpreadAttribute"] = 264] = "JsxSpreadAttribute"; SyntaxKind[SyntaxKind["JsxExpression"] = 265] = "JsxExpression"; + // Clauses SyntaxKind[SyntaxKind["CaseClause"] = 266] = "CaseClause"; SyntaxKind[SyntaxKind["DefaultClause"] = 267] = "DefaultClause"; SyntaxKind[SyntaxKind["HeritageClause"] = 268] = "HeritageClause"; SyntaxKind[SyntaxKind["CatchClause"] = 269] = "CatchClause"; + // Property assignments SyntaxKind[SyntaxKind["PropertyAssignment"] = 270] = "PropertyAssignment"; SyntaxKind[SyntaxKind["ShorthandPropertyAssignment"] = 271] = "ShorthandPropertyAssignment"; SyntaxKind[SyntaxKind["SpreadAssignment"] = 272] = "SpreadAssignment"; + // Enum SyntaxKind[SyntaxKind["EnumMember"] = 273] = "EnumMember"; + // Top-level nodes SyntaxKind[SyntaxKind["SourceFile"] = 274] = "SourceFile"; SyntaxKind[SyntaxKind["Bundle"] = 275] = "Bundle"; SyntaxKind[SyntaxKind["UnparsedSource"] = 276] = "UnparsedSource"; SyntaxKind[SyntaxKind["InputFiles"] = 277] = "InputFiles"; + // JSDoc nodes SyntaxKind[SyntaxKind["JSDocTypeExpression"] = 278] = "JSDocTypeExpression"; + // The * type SyntaxKind[SyntaxKind["JSDocAllType"] = 279] = "JSDocAllType"; + // The ? type SyntaxKind[SyntaxKind["JSDocUnknownType"] = 280] = "JSDocUnknownType"; SyntaxKind[SyntaxKind["JSDocNullableType"] = 281] = "JSDocNullableType"; SyntaxKind[SyntaxKind["JSDocNonNullableType"] = 282] = "JSDocNonNullableType"; @@ -2043,13 +2351,17 @@ var ts; SyntaxKind[SyntaxKind["JSDocTemplateTag"] = 297] = "JSDocTemplateTag"; SyntaxKind[SyntaxKind["JSDocTypedefTag"] = 298] = "JSDocTypedefTag"; SyntaxKind[SyntaxKind["JSDocPropertyTag"] = 299] = "JSDocPropertyTag"; + // Synthesized list SyntaxKind[SyntaxKind["SyntaxList"] = 300] = "SyntaxList"; + // Transformation nodes SyntaxKind[SyntaxKind["NotEmittedStatement"] = 301] = "NotEmittedStatement"; SyntaxKind[SyntaxKind["PartiallyEmittedExpression"] = 302] = "PartiallyEmittedExpression"; SyntaxKind[SyntaxKind["CommaListExpression"] = 303] = "CommaListExpression"; SyntaxKind[SyntaxKind["MergeDeclarationMarker"] = 304] = "MergeDeclarationMarker"; SyntaxKind[SyntaxKind["EndOfDeclarationMarker"] = 305] = "EndOfDeclarationMarker"; + // Enum value count SyntaxKind[SyntaxKind["Count"] = 306] = "Count"; + // Markers SyntaxKind[SyntaxKind["FirstAssignment"] = 58] = "FirstAssignment"; SyntaxKind[SyntaxKind["LastAssignment"] = 70] = "LastAssignment"; SyntaxKind[SyntaxKind["FirstCompoundAssignment"] = 59] = "FirstCompoundAssignment"; @@ -2079,8 +2391,8 @@ var ts; SyntaxKind[SyntaxKind["LastJSDocNode"] = 299] = "LastJSDocNode"; SyntaxKind[SyntaxKind["FirstJSDocTagNode"] = 289] = "FirstJSDocTagNode"; SyntaxKind[SyntaxKind["LastJSDocTagNode"] = 299] = "LastJSDocTagNode"; - SyntaxKind[SyntaxKind["FirstContextualKeyword"] = 117] = "FirstContextualKeyword"; - SyntaxKind[SyntaxKind["LastContextualKeyword"] = 145] = "LastContextualKeyword"; + /* @internal */ SyntaxKind[SyntaxKind["FirstContextualKeyword"] = 117] = "FirstContextualKeyword"; + /* @internal */ SyntaxKind[SyntaxKind["LastContextualKeyword"] = 145] = "LastContextualKeyword"; })(SyntaxKind = ts.SyntaxKind || (ts.SyntaxKind = {})); var NodeFlags; (function (NodeFlags) { @@ -2104,18 +2416,32 @@ var ts; NodeFlags[NodeFlags["JavaScriptFile"] = 65536] = "JavaScriptFile"; NodeFlags[NodeFlags["ThisNodeOrAnySubNodesHasError"] = 131072] = "ThisNodeOrAnySubNodesHasError"; NodeFlags[NodeFlags["HasAggregatedChildData"] = 262144] = "HasAggregatedChildData"; - NodeFlags[NodeFlags["PossiblyContainsDynamicImport"] = 524288] = "PossiblyContainsDynamicImport"; - NodeFlags[NodeFlags["PossiblyContainsImportMeta"] = 1048576] = "PossiblyContainsImportMeta"; + // These flags will be set when the parser encounters a dynamic import expression or 'import.meta' to avoid + // walking the tree if the flags are not set. However, these flags are just a approximation + // (hence why it's named "PossiblyContainsDynamicImport") because once set, the flags never get cleared. + // During editing, if a dynamic import is removed, incremental parsing will *NOT* clear this flag. + // This means that the tree will always be traversed during module resolution, or when looking for external module indicators. + // However, the removal operation should not occur often and in the case of the + // removal, it is likely that users will add the import anyway. + // The advantage of this approach is its simplicity. For the case of batch compilation, + // we guarantee that users won't have to pay the price of walking the tree if a dynamic import isn't used. + /* @internal */ NodeFlags[NodeFlags["PossiblyContainsDynamicImport"] = 524288] = "PossiblyContainsDynamicImport"; + /* @internal */ NodeFlags[NodeFlags["PossiblyContainsImportMeta"] = 1048576] = "PossiblyContainsImportMeta"; NodeFlags[NodeFlags["JSDoc"] = 2097152] = "JSDoc"; - NodeFlags[NodeFlags["Ambient"] = 4194304] = "Ambient"; - NodeFlags[NodeFlags["InWithStatement"] = 8388608] = "InWithStatement"; + /* @internal */ NodeFlags[NodeFlags["Ambient"] = 4194304] = "Ambient"; + /* @internal */ NodeFlags[NodeFlags["InWithStatement"] = 8388608] = "InWithStatement"; NodeFlags[NodeFlags["JsonFile"] = 16777216] = "JsonFile"; NodeFlags[NodeFlags["BlockScoped"] = 3] = "BlockScoped"; NodeFlags[NodeFlags["ReachabilityCheckFlags"] = 384] = "ReachabilityCheckFlags"; NodeFlags[NodeFlags["ReachabilityAndEmitFlags"] = 1408] = "ReachabilityAndEmitFlags"; + // Parsing context flags NodeFlags[NodeFlags["ContextFlags"] = 12679168] = "ContextFlags"; + // Exclude these flags when parsing a Type NodeFlags[NodeFlags["TypeExcludesFlags"] = 20480] = "TypeExcludesFlags"; - NodeFlags[NodeFlags["PermanentlySetIncrementalFlags"] = 1572864] = "PermanentlySetIncrementalFlags"; + // Represents all flags that are potentially set once and + // never cleared on SourceFiles which get re-used in between incremental parses. + // See the comment above on `PossiblyContainsDynamicImport` and `PossiblyContainsImportMeta`. + /* @internal */ NodeFlags[NodeFlags["PermanentlySetIncrementalFlags"] = 1572864] = "PermanentlySetIncrementalFlags"; })(NodeFlags = ts.NodeFlags || (ts.NodeFlags = {})); var ModifierFlags; (function (ModifierFlags) { @@ -2133,6 +2459,7 @@ var ts; ModifierFlags[ModifierFlags["Const"] = 2048] = "Const"; ModifierFlags[ModifierFlags["HasComputedFlags"] = 536870912] = "HasComputedFlags"; ModifierFlags[ModifierFlags["AccessibilityModifier"] = 28] = "AccessibilityModifier"; + // Accessibility modifiers and 'readonly' can be attached to a parameter in a constructor to make it a property. ModifierFlags[ModifierFlags["ParameterPropertyModifier"] = 92] = "ParameterPropertyModifier"; ModifierFlags[ModifierFlags["NonPublicAccessibilityModifier"] = 24] = "NonPublicAccessibilityModifier"; ModifierFlags[ModifierFlags["TypeScriptModifier"] = 2270] = "TypeScriptModifier"; @@ -2142,28 +2469,35 @@ var ts; var JsxFlags; (function (JsxFlags) { JsxFlags[JsxFlags["None"] = 0] = "None"; + /** An element from a named property of the JSX.IntrinsicElements interface */ JsxFlags[JsxFlags["IntrinsicNamedElement"] = 1] = "IntrinsicNamedElement"; + /** An element inferred from the string index signature of the JSX.IntrinsicElements interface */ JsxFlags[JsxFlags["IntrinsicIndexedElement"] = 2] = "IntrinsicIndexedElement"; JsxFlags[JsxFlags["IntrinsicElement"] = 3] = "IntrinsicElement"; })(JsxFlags = ts.JsxFlags || (ts.JsxFlags = {})); + /* @internal */ var RelationComparisonResult; (function (RelationComparisonResult) { RelationComparisonResult[RelationComparisonResult["Succeeded"] = 1] = "Succeeded"; RelationComparisonResult[RelationComparisonResult["Failed"] = 2] = "Failed"; RelationComparisonResult[RelationComparisonResult["FailedAndReported"] = 3] = "FailedAndReported"; })(RelationComparisonResult = ts.RelationComparisonResult || (ts.RelationComparisonResult = {})); + /*@internal*/ var GeneratedIdentifierFlags; (function (GeneratedIdentifierFlags) { + // Kinds GeneratedIdentifierFlags[GeneratedIdentifierFlags["None"] = 0] = "None"; GeneratedIdentifierFlags[GeneratedIdentifierFlags["Auto"] = 1] = "Auto"; GeneratedIdentifierFlags[GeneratedIdentifierFlags["Loop"] = 2] = "Loop"; GeneratedIdentifierFlags[GeneratedIdentifierFlags["Unique"] = 3] = "Unique"; GeneratedIdentifierFlags[GeneratedIdentifierFlags["Node"] = 4] = "Node"; GeneratedIdentifierFlags[GeneratedIdentifierFlags["KindMask"] = 7] = "KindMask"; + // Flags GeneratedIdentifierFlags[GeneratedIdentifierFlags["ReservedInNestedScopes"] = 8] = "ReservedInNestedScopes"; GeneratedIdentifierFlags[GeneratedIdentifierFlags["Optimistic"] = 16] = "Optimistic"; GeneratedIdentifierFlags[GeneratedIdentifierFlags["FileLevel"] = 32] = "FileLevel"; })(GeneratedIdentifierFlags = ts.GeneratedIdentifierFlags || (ts.GeneratedIdentifierFlags = {})); + /* @internal */ var TokenFlags; (function (TokenFlags) { TokenFlags[TokenFlags["None"] = 0] = "None"; @@ -2198,24 +2532,32 @@ var ts; FlowFlags[FlowFlags["Label"] = 12] = "Label"; FlowFlags[FlowFlags["Condition"] = 96] = "Condition"; })(FlowFlags = ts.FlowFlags || (ts.FlowFlags = {})); - var OperationCanceledException = (function () { + var OperationCanceledException = /** @class */ (function () { function OperationCanceledException() { } return OperationCanceledException; }()); ts.OperationCanceledException = OperationCanceledException; + /* @internal */ var StructureIsReused; (function (StructureIsReused) { StructureIsReused[StructureIsReused["Not"] = 0] = "Not"; StructureIsReused[StructureIsReused["SafeModules"] = 1] = "SafeModules"; StructureIsReused[StructureIsReused["Completely"] = 2] = "Completely"; })(StructureIsReused = ts.StructureIsReused || (ts.StructureIsReused = {})); + /** Return code used by getEmitOutput function to indicate status of the function */ var ExitStatus; (function (ExitStatus) { + // Compiler ran successfully. Either this was a simple do-nothing compilation (for example, + // when -version or -help was provided, or this was a normal compilation, no diagnostics + // were produced, and all outputs were generated successfully. ExitStatus[ExitStatus["Success"] = 0] = "Success"; + // Diagnostics were produced and because of them no code was generated. ExitStatus[ExitStatus["DiagnosticsPresent_OutputsSkipped"] = 1] = "DiagnosticsPresent_OutputsSkipped"; + // Diagnostics were produced and outputs were generated in spite of them. ExitStatus[ExitStatus["DiagnosticsPresent_OutputsGenerated"] = 2] = "DiagnosticsPresent_OutputsGenerated"; })(ExitStatus = ts.ExitStatus || (ts.ExitStatus = {})); + /* @internal */ var UnionReduction; (function (UnionReduction) { UnionReduction[UnionReduction["None"] = 0] = "None"; @@ -2225,6 +2567,7 @@ var ts; var NodeBuilderFlags; (function (NodeBuilderFlags) { NodeBuilderFlags[NodeBuilderFlags["None"] = 0] = "None"; + // Options NodeBuilderFlags[NodeBuilderFlags["NoTruncation"] = 1] = "NoTruncation"; NodeBuilderFlags[NodeBuilderFlags["WriteArrayAsGenericType"] = 2] = "WriteArrayAsGenericType"; NodeBuilderFlags[NodeBuilderFlags["GenerateNamesForShadowedTypeParams"] = 4] = "GenerateNamesForShadowedTypeParams"; @@ -2240,6 +2583,7 @@ var ts; NodeBuilderFlags[NodeBuilderFlags["UseTypeOfFunction"] = 4096] = "UseTypeOfFunction"; NodeBuilderFlags[NodeBuilderFlags["OmitParameterModifiers"] = 8192] = "OmitParameterModifiers"; NodeBuilderFlags[NodeBuilderFlags["UseAliasDefinedOutsideCurrentScope"] = 16384] = "UseAliasDefinedOutsideCurrentScope"; + // Error handling NodeBuilderFlags[NodeBuilderFlags["AllowThisInObjectLiteral"] = 32768] = "AllowThisInObjectLiteral"; NodeBuilderFlags[NodeBuilderFlags["AllowQualifedNameInPlaceOfIdentifier"] = 65536] = "AllowQualifedNameInPlaceOfIdentifier"; NodeBuilderFlags[NodeBuilderFlags["AllowAnonymousIdentifier"] = 131072] = "AllowAnonymousIdentifier"; @@ -2248,49 +2592,70 @@ var ts; NodeBuilderFlags[NodeBuilderFlags["AllowUniqueESSymbolType"] = 1048576] = "AllowUniqueESSymbolType"; NodeBuilderFlags[NodeBuilderFlags["AllowEmptyIndexInfoType"] = 2097152] = "AllowEmptyIndexInfoType"; NodeBuilderFlags[NodeBuilderFlags["IgnoreErrors"] = 3112960] = "IgnoreErrors"; + // State NodeBuilderFlags[NodeBuilderFlags["InObjectTypeLiteral"] = 4194304] = "InObjectTypeLiteral"; NodeBuilderFlags[NodeBuilderFlags["InTypeAlias"] = 8388608] = "InTypeAlias"; NodeBuilderFlags[NodeBuilderFlags["InInitialEntityName"] = 16777216] = "InInitialEntityName"; NodeBuilderFlags[NodeBuilderFlags["InReverseMappedType"] = 33554432] = "InReverseMappedType"; })(NodeBuilderFlags = ts.NodeBuilderFlags || (ts.NodeBuilderFlags = {})); + // Ensure the shared flags between this and `NodeBuilderFlags` stay in alignment var TypeFormatFlags; (function (TypeFormatFlags) { TypeFormatFlags[TypeFormatFlags["None"] = 0] = "None"; TypeFormatFlags[TypeFormatFlags["NoTruncation"] = 1] = "NoTruncation"; TypeFormatFlags[TypeFormatFlags["WriteArrayAsGenericType"] = 2] = "WriteArrayAsGenericType"; + // hole because there's a hole in node builder flags TypeFormatFlags[TypeFormatFlags["UseStructuralFallback"] = 8] = "UseStructuralFallback"; + // hole because there's a hole in node builder flags TypeFormatFlags[TypeFormatFlags["WriteTypeArgumentsOfSignature"] = 32] = "WriteTypeArgumentsOfSignature"; TypeFormatFlags[TypeFormatFlags["UseFullyQualifiedType"] = 64] = "UseFullyQualifiedType"; + // hole because `UseOnlyExternalAliasing` is here in node builder flags, but functions which take old flags use `SymbolFormatFlags` instead TypeFormatFlags[TypeFormatFlags["SuppressAnyReturnType"] = 256] = "SuppressAnyReturnType"; + // hole because `WriteTypeParametersInQualifiedName` is here in node builder flags, but functions which take old flags use `SymbolFormatFlags` for this instead TypeFormatFlags[TypeFormatFlags["MultilineObjectLiterals"] = 1024] = "MultilineObjectLiterals"; TypeFormatFlags[TypeFormatFlags["WriteClassExpressionAsTypeLiteral"] = 2048] = "WriteClassExpressionAsTypeLiteral"; TypeFormatFlags[TypeFormatFlags["UseTypeOfFunction"] = 4096] = "UseTypeOfFunction"; TypeFormatFlags[TypeFormatFlags["OmitParameterModifiers"] = 8192] = "OmitParameterModifiers"; TypeFormatFlags[TypeFormatFlags["UseAliasDefinedOutsideCurrentScope"] = 16384] = "UseAliasDefinedOutsideCurrentScope"; + // even though `T` can't be accessed in the current scope. + // Error Handling TypeFormatFlags[TypeFormatFlags["AllowUniqueESSymbolType"] = 1048576] = "AllowUniqueESSymbolType"; + // TypeFormatFlags exclusive TypeFormatFlags[TypeFormatFlags["AddUndefined"] = 131072] = "AddUndefined"; TypeFormatFlags[TypeFormatFlags["WriteArrowStyleSignature"] = 262144] = "WriteArrowStyleSignature"; + // State TypeFormatFlags[TypeFormatFlags["InArrayType"] = 524288] = "InArrayType"; TypeFormatFlags[TypeFormatFlags["InElementType"] = 2097152] = "InElementType"; TypeFormatFlags[TypeFormatFlags["InFirstTypeArgument"] = 4194304] = "InFirstTypeArgument"; TypeFormatFlags[TypeFormatFlags["InTypeAlias"] = 8388608] = "InTypeAlias"; - TypeFormatFlags[TypeFormatFlags["WriteOwnNameForAnyLike"] = 0] = "WriteOwnNameForAnyLike"; + /** @deprecated */ TypeFormatFlags[TypeFormatFlags["WriteOwnNameForAnyLike"] = 0] = "WriteOwnNameForAnyLike"; TypeFormatFlags[TypeFormatFlags["NodeBuilderFlagsMask"] = 9469291] = "NodeBuilderFlagsMask"; })(TypeFormatFlags = ts.TypeFormatFlags || (ts.TypeFormatFlags = {})); var SymbolFormatFlags; (function (SymbolFormatFlags) { SymbolFormatFlags[SymbolFormatFlags["None"] = 0] = "None"; + // Write symbols's type argument if it is instantiated symbol + // eg. class C { p: T } <-- Show p as C.p here + // var a: C; + // var p = a.p; <--- Here p is property of C so show it as C.p instead of just C.p SymbolFormatFlags[SymbolFormatFlags["WriteTypeParametersOrArguments"] = 1] = "WriteTypeParametersOrArguments"; + // Use only external alias information to get the symbol name in the given context + // eg. module m { export class c { } } import x = m.c; + // When this flag is specified m.c will be used to refer to the class instead of alias symbol x SymbolFormatFlags[SymbolFormatFlags["UseOnlyExternalAliasing"] = 2] = "UseOnlyExternalAliasing"; + // Build symbol name using any nodes needed, instead of just components of an entity name SymbolFormatFlags[SymbolFormatFlags["AllowAnyNodeKind"] = 4] = "AllowAnyNodeKind"; + // Prefer aliases which are not directly visible SymbolFormatFlags[SymbolFormatFlags["UseAliasDefinedOutsideCurrentScope"] = 8] = "UseAliasDefinedOutsideCurrentScope"; })(SymbolFormatFlags = ts.SymbolFormatFlags || (ts.SymbolFormatFlags = {})); + /* @internal */ var SymbolAccessibility; (function (SymbolAccessibility) { SymbolAccessibility[SymbolAccessibility["Accessible"] = 0] = "Accessible"; SymbolAccessibility[SymbolAccessibility["NotAccessible"] = 1] = "NotAccessible"; SymbolAccessibility[SymbolAccessibility["CannotBeNamed"] = 2] = "CannotBeNamed"; })(SymbolAccessibility = ts.SymbolAccessibility || (ts.SymbolAccessibility = {})); + /* @internal */ var SyntheticSymbolKind; (function (SyntheticSymbolKind) { SyntheticSymbolKind[SyntheticSymbolKind["UnionOrIntersection"] = 0] = "UnionOrIntersection"; @@ -2301,10 +2666,16 @@ var ts; TypePredicateKind[TypePredicateKind["This"] = 0] = "This"; TypePredicateKind[TypePredicateKind["Identifier"] = 1] = "Identifier"; })(TypePredicateKind = ts.TypePredicateKind || (ts.TypePredicateKind = {})); + /** Indicates how to serialize the name for a TypeReferenceNode when emitting decorator metadata */ + /* @internal */ var TypeReferenceSerializationKind; (function (TypeReferenceSerializationKind) { TypeReferenceSerializationKind[TypeReferenceSerializationKind["Unknown"] = 0] = "Unknown"; + // should be emitted using a safe fallback. TypeReferenceSerializationKind[TypeReferenceSerializationKind["TypeWithConstructSignatureAndValue"] = 1] = "TypeWithConstructSignatureAndValue"; + // function that can be reached at runtime (e.g. a `class` + // declaration or a `var` declaration for the static side + // of a type, such as the global `Promise` type in lib.d.ts). TypeReferenceSerializationKind[TypeReferenceSerializationKind["VoidNullableOrNeverType"] = 2] = "VoidNullableOrNeverType"; TypeReferenceSerializationKind[TypeReferenceSerializationKind["NumberLikeType"] = 3] = "NumberLikeType"; TypeReferenceSerializationKind[TypeReferenceSerializationKind["StringLikeType"] = 4] = "StringLikeType"; @@ -2313,6 +2684,7 @@ var ts; TypeReferenceSerializationKind[TypeReferenceSerializationKind["ESSymbolType"] = 7] = "ESSymbolType"; TypeReferenceSerializationKind[TypeReferenceSerializationKind["Promise"] = 8] = "Promise"; TypeReferenceSerializationKind[TypeReferenceSerializationKind["TypeWithCallSignature"] = 9] = "TypeWithCallSignature"; + // with call signatures. TypeReferenceSerializationKind[TypeReferenceSerializationKind["ObjectType"] = 10] = "ObjectType"; })(TypeReferenceSerializationKind = ts.TypeReferenceSerializationKind || (ts.TypeReferenceSerializationKind = {})); var SymbolFlags; @@ -2345,6 +2717,7 @@ var ts; SymbolFlags[SymbolFlags["Optional"] = 16777216] = "Optional"; SymbolFlags[SymbolFlags["Transient"] = 33554432] = "Transient"; SymbolFlags[SymbolFlags["JSContainer"] = 67108864] = "JSContainer"; + /* @internal */ SymbolFlags[SymbolFlags["All"] = 67108863] = "All"; SymbolFlags[SymbolFlags["Enum"] = 384] = "Enum"; SymbolFlags[SymbolFlags["Variable"] = 3] = "Variable"; @@ -2353,7 +2726,11 @@ var ts; SymbolFlags[SymbolFlags["Namespace"] = 1920] = "Namespace"; SymbolFlags[SymbolFlags["Module"] = 1536] = "Module"; SymbolFlags[SymbolFlags["Accessor"] = 98304] = "Accessor"; + // Variables can be redeclared, but can not redeclare a block-scoped declaration with the + // same name, or any other value that is not a variable, e.g. ValueModule or Class SymbolFlags[SymbolFlags["FunctionScopedVariableExcludes"] = 67216318] = "FunctionScopedVariableExcludes"; + // Block-scoped declarations are not allowed to be re-declared + // they can not merge with anything in the value space SymbolFlags[SymbolFlags["BlockScopedVariableExcludes"] = 67216319] = "BlockScopedVariableExcludes"; SymbolFlags[SymbolFlags["ParameterExcludes"] = 67216319] = "ParameterExcludes"; SymbolFlags[SymbolFlags["PropertyExcludes"] = 0] = "PropertyExcludes"; @@ -2378,14 +2755,20 @@ var ts; SymbolFlags[SymbolFlags["BlockScoped"] = 418] = "BlockScoped"; SymbolFlags[SymbolFlags["PropertyOrAccessor"] = 98308] = "PropertyOrAccessor"; SymbolFlags[SymbolFlags["ClassMember"] = 106500] = "ClassMember"; + /* @internal */ + // The set of things we consider semantically classifiable. Used to speed up the LS during + // classification. SymbolFlags[SymbolFlags["Classifiable"] = 2885600] = "Classifiable"; + /* @internal */ SymbolFlags[SymbolFlags["LateBindingContainer"] = 6240] = "LateBindingContainer"; })(SymbolFlags = ts.SymbolFlags || (ts.SymbolFlags = {})); + /* @internal */ var EnumKind; (function (EnumKind) { EnumKind[EnumKind["Numeric"] = 0] = "Numeric"; - EnumKind[EnumKind["Literal"] = 1] = "Literal"; + EnumKind[EnumKind["Literal"] = 1] = "Literal"; // Literal enum (each member has a TypeFlags.EnumLiteral type) })(EnumKind = ts.EnumKind || (ts.EnumKind = {})); + /* @internal */ var CheckFlags; (function (CheckFlags) { CheckFlags[CheckFlags["Instantiated"] = 1] = "Instantiated"; @@ -2421,6 +2804,7 @@ var ts; InternalSymbolName["ExportEquals"] = "export="; InternalSymbolName["Default"] = "default"; })(InternalSymbolName = ts.InternalSymbolName || (ts.InternalSymbolName = {})); + /* @internal */ var NodeCheckFlags; (function (NodeCheckFlags) { NodeCheckFlags[NodeCheckFlags["TypeChecked"] = 1] = "TypeChecked"; @@ -2472,20 +2856,31 @@ var ts; TypeFlags[TypeFlags["Conditional"] = 4194304] = "Conditional"; TypeFlags[TypeFlags["Substitution"] = 8388608] = "Substitution"; TypeFlags[TypeFlags["NonPrimitive"] = 16777216] = "NonPrimitive"; + /* @internal */ TypeFlags[TypeFlags["FreshLiteral"] = 33554432] = "FreshLiteral"; + /* @internal */ TypeFlags[TypeFlags["UnionOfUnitTypes"] = 67108864] = "UnionOfUnitTypes"; + /* @internal */ TypeFlags[TypeFlags["ContainsWideningType"] = 134217728] = "ContainsWideningType"; + /* @internal */ TypeFlags[TypeFlags["ContainsObjectLiteral"] = 268435456] = "ContainsObjectLiteral"; + /* @internal */ TypeFlags[TypeFlags["ContainsAnyFunctionType"] = 536870912] = "ContainsAnyFunctionType"; + /* @internal */ TypeFlags[TypeFlags["AnyOrUnknown"] = 3] = "AnyOrUnknown"; + /* @internal */ TypeFlags[TypeFlags["Nullable"] = 24576] = "Nullable"; TypeFlags[TypeFlags["Literal"] = 448] = "Literal"; TypeFlags[TypeFlags["Unit"] = 27072] = "Unit"; TypeFlags[TypeFlags["StringOrNumberLiteral"] = 192] = "StringOrNumberLiteral"; + /* @internal */ TypeFlags[TypeFlags["StringOrNumberLiteralOrUnique"] = 2240] = "StringOrNumberLiteralOrUnique"; + /* @internal */ TypeFlags[TypeFlags["DefinitelyFalsy"] = 29120] = "DefinitelyFalsy"; TypeFlags[TypeFlags["PossiblyFalsy"] = 29148] = "PossiblyFalsy"; + /* @internal */ TypeFlags[TypeFlags["Intrinsic"] = 16839967] = "Intrinsic"; + /* @internal */ TypeFlags[TypeFlags["Primitive"] = 32764] = "Primitive"; TypeFlags[TypeFlags["StringLike"] = 68] = "StringLike"; TypeFlags[TypeFlags["NumberLike"] = 168] = "NumberLike"; @@ -2493,6 +2888,7 @@ var ts; TypeFlags[TypeFlags["EnumLike"] = 544] = "EnumLike"; TypeFlags[TypeFlags["ESSymbolLike"] = 3072] = "ESSymbolLike"; TypeFlags[TypeFlags["VoidLike"] = 12288] = "VoidLike"; + /* @internal */ TypeFlags[TypeFlags["DisjointDomains"] = 16809468] = "DisjointDomains"; TypeFlags[TypeFlags["UnionOrIntersection"] = 786432] = "UnionOrIntersection"; TypeFlags[TypeFlags["StructuredType"] = 917504] = "StructuredType"; @@ -2501,15 +2897,27 @@ var ts; TypeFlags[TypeFlags["InstantiablePrimitive"] = 1048576] = "InstantiablePrimitive"; TypeFlags[TypeFlags["Instantiable"] = 15794176] = "Instantiable"; TypeFlags[TypeFlags["StructuredOrInstantiable"] = 16711680] = "StructuredOrInstantiable"; + // 'Narrowable' types are types where narrowing actually narrows. + // This *should* be every type other than null, undefined, void, and never TypeFlags[TypeFlags["Narrowable"] = 33492479] = "Narrowable"; TypeFlags[TypeFlags["NotUnionOrUnit"] = 16909315] = "NotUnionOrUnit"; + /* @internal */ TypeFlags[TypeFlags["NotUnit"] = 16749629] = "NotUnit"; + /* @internal */ TypeFlags[TypeFlags["RequiresWidening"] = 402653184] = "RequiresWidening"; + /* @internal */ TypeFlags[TypeFlags["PropagatingFlags"] = 939524096] = "PropagatingFlags"; + // The following flags are used for different purposes during union and intersection type construction + /* @internal */ TypeFlags[TypeFlags["NonWideningType"] = 134217728] = "NonWideningType"; + /* @internal */ TypeFlags[TypeFlags["Wildcard"] = 268435456] = "Wildcard"; + /* @internal */ TypeFlags[TypeFlags["EmptyObject"] = 536870912] = "EmptyObject"; + /* @internal */ TypeFlags[TypeFlags["ConstructionFlags"] = 939524096] = "ConstructionFlags"; + // The following flag is used for different purposes by maybeTypeOfKind + /* @internal */ TypeFlags[TypeFlags["GenericMappedType"] = 134217728] = "GenericMappedType"; })(TypeFlags = ts.TypeFlags || (ts.TypeFlags = {})); var ObjectFlags; @@ -2530,6 +2938,7 @@ var ts; ObjectFlags[ObjectFlags["MarkerType"] = 8192] = "MarkerType"; ObjectFlags[ObjectFlags["ClassOrInterface"] = 3] = "ClassOrInterface"; })(ObjectFlags = ts.ObjectFlags || (ts.ObjectFlags = {})); + /* @internal */ var Variance; (function (Variance) { Variance[Variance["Invariant"] = 0] = "Invariant"; @@ -2559,6 +2968,7 @@ var ts; InferencePriority[InferencePriority["AlwaysStrict"] = 64] = "AlwaysStrict"; InferencePriority[InferencePriority["PriorityImpliesCombination"] = 28] = "PriorityImpliesCombination"; })(InferencePriority = ts.InferencePriority || (ts.InferencePriority = {})); + /* @internal */ var InferenceFlags; (function (InferenceFlags) { InferenceFlags[InferenceFlags["None"] = 0] = "None"; @@ -2566,20 +2976,37 @@ var ts; InferenceFlags[InferenceFlags["NoDefault"] = 2] = "NoDefault"; InferenceFlags[InferenceFlags["AnyDefault"] = 4] = "AnyDefault"; })(InferenceFlags = ts.InferenceFlags || (ts.InferenceFlags = {})); + /** + * Ternary values are defined such that + * x & y is False if either x or y is False. + * x & y is Maybe if either x or y is Maybe, but neither x or y is False. + * x & y is True if both x and y are True. + * x | y is False if both x and y are False. + * x | y is Maybe if either x or y is Maybe, but neither x or y is True. + * x | y is True if either x or y is True. + */ + /* @internal */ var Ternary; (function (Ternary) { Ternary[Ternary["False"] = 0] = "False"; Ternary[Ternary["Maybe"] = 1] = "Maybe"; Ternary[Ternary["True"] = -1] = "True"; })(Ternary = ts.Ternary || (ts.Ternary = {})); + /* @internal */ var SpecialPropertyAssignmentKind; (function (SpecialPropertyAssignmentKind) { SpecialPropertyAssignmentKind[SpecialPropertyAssignmentKind["None"] = 0] = "None"; + /// exports.name = expr SpecialPropertyAssignmentKind[SpecialPropertyAssignmentKind["ExportsProperty"] = 1] = "ExportsProperty"; + /// module.exports = expr SpecialPropertyAssignmentKind[SpecialPropertyAssignmentKind["ModuleExports"] = 2] = "ModuleExports"; + /// className.prototype.name = expr SpecialPropertyAssignmentKind[SpecialPropertyAssignmentKind["PrototypeProperty"] = 3] = "PrototypeProperty"; + /// this.name = expr SpecialPropertyAssignmentKind[SpecialPropertyAssignmentKind["ThisProperty"] = 4] = "ThisProperty"; + // F.name = expr SpecialPropertyAssignmentKind[SpecialPropertyAssignmentKind["Property"] = 5] = "Property"; + // F.prototype = { ... } SpecialPropertyAssignmentKind[SpecialPropertyAssignmentKind["Prototype"] = 6] = "Prototype"; })(SpecialPropertyAssignmentKind = ts.SpecialPropertyAssignmentKind || (ts.SpecialPropertyAssignmentKind = {})); var DiagnosticCategory; @@ -2589,6 +3016,7 @@ var ts; DiagnosticCategory[DiagnosticCategory["Suggestion"] = 2] = "Suggestion"; DiagnosticCategory[DiagnosticCategory["Message"] = 3] = "Message"; })(DiagnosticCategory = ts.DiagnosticCategory || (ts.DiagnosticCategory = {})); + /* @internal */ function diagnosticCategoryName(d, lowerCase) { if (lowerCase === void 0) { lowerCase = true; } var name = DiagnosticCategory[d.category]; @@ -2631,6 +3059,10 @@ var ts; ScriptKind[ScriptKind["TSX"] = 4] = "TSX"; ScriptKind[ScriptKind["External"] = 5] = "External"; ScriptKind[ScriptKind["JSON"] = 6] = "JSON"; + /** + * Used on extensions that doesn't define the ScriptKind but the content defines it. + * Deferred extensions are going to be included in all project contexts. + */ ScriptKind[ScriptKind["Deferred"] = 7] = "Deferred"; })(ScriptKind = ts.ScriptKind || (ts.ScriptKind = {})); var ScriptTarget; @@ -2655,6 +3087,7 @@ var ts; WatchDirectoryFlags[WatchDirectoryFlags["None"] = 0] = "None"; WatchDirectoryFlags[WatchDirectoryFlags["Recursive"] = 1] = "Recursive"; })(WatchDirectoryFlags = ts.WatchDirectoryFlags || (ts.WatchDirectoryFlags = {})); + /* @internal */ var CharacterCodes; (function (CharacterCodes) { CharacterCodes[CharacterCodes["nullCharacter"] = 0] = "nullCharacter"; @@ -2664,6 +3097,7 @@ var ts; CharacterCodes[CharacterCodes["lineSeparator"] = 8232] = "lineSeparator"; CharacterCodes[CharacterCodes["paragraphSeparator"] = 8233] = "paragraphSeparator"; CharacterCodes[CharacterCodes["nextLine"] = 133] = "nextLine"; + // Unicode 3.0 space characters CharacterCodes[CharacterCodes["space"] = 32] = "space"; CharacterCodes[CharacterCodes["nonBreakingSpace"] = 160] = "nonBreakingSpace"; CharacterCodes[CharacterCodes["enQuad"] = 8192] = "enQuad"; @@ -2791,9 +3225,12 @@ var ts; Extension["Jsx"] = ".jsx"; Extension["Json"] = ".json"; })(Extension = ts.Extension || (ts.Extension = {})); + /* @internal */ var TransformFlags; (function (TransformFlags) { TransformFlags[TransformFlags["None"] = 0] = "None"; + // Facts + // - Flags used to indicate that a node or subtree contains syntax that requires transformation. TransformFlags[TransformFlags["TypeScript"] = 1] = "TypeScript"; TransformFlags[TransformFlags["ContainsTypeScript"] = 2] = "ContainsTypeScript"; TransformFlags[TransformFlags["ContainsJsx"] = 4] = "ContainsJsx"; @@ -2806,6 +3243,8 @@ var ts; TransformFlags[TransformFlags["ContainsGenerator"] = 512] = "ContainsGenerator"; TransformFlags[TransformFlags["DestructuringAssignment"] = 1024] = "DestructuringAssignment"; TransformFlags[TransformFlags["ContainsDestructuringAssignment"] = 2048] = "ContainsDestructuringAssignment"; + // Markers + // - Flags used to indicate that a subtree contains a specific transformation. TransformFlags[TransformFlags["ContainsDecorators"] = 4096] = "ContainsDecorators"; TransformFlags[TransformFlags["ContainsPropertyInitializer"] = 8192] = "ContainsPropertyInitializer"; TransformFlags[TransformFlags["ContainsLexicalThis"] = 16384] = "ContainsLexicalThis"; @@ -2825,7 +3264,12 @@ var ts; TransformFlags[TransformFlags["ContainsDynamicImport"] = 67108864] = "ContainsDynamicImport"; TransformFlags[TransformFlags["Super"] = 134217728] = "Super"; TransformFlags[TransformFlags["ContainsSuper"] = 268435456] = "ContainsSuper"; + // Please leave this as 1 << 29. + // It is the maximum bit we can set before we outgrow the size of a v8 small integer (SMI) on an x86 system. + // It is a good reminder of how much room we have left TransformFlags[TransformFlags["HasComputedFlags"] = 536870912] = "HasComputedFlags"; + // Assertions + // - Bitmasks that are used to assert facts about the syntax of a node and its subtree. TransformFlags[TransformFlags["AssertTypeScript"] = 3] = "AssertTypeScript"; TransformFlags[TransformFlags["AssertJsx"] = 4] = "AssertJsx"; TransformFlags[TransformFlags["AssertESNext"] = 8] = "AssertESNext"; @@ -2834,6 +3278,9 @@ var ts; TransformFlags[TransformFlags["AssertES2015"] = 192] = "AssertES2015"; TransformFlags[TransformFlags["AssertGenerator"] = 768] = "AssertGenerator"; TransformFlags[TransformFlags["AssertDestructuringAssignment"] = 3072] = "AssertDestructuringAssignment"; + // Scope Exclusions + // - Bitmasks that exclude flags from propagating out of a specific context + // into the subtree flags of their container. TransformFlags[TransformFlags["OuterExpressionExcludes"] = 536872257] = "OuterExpressionExcludes"; TransformFlags[TransformFlags["PropertyAccessExcludes"] = 671089985] = "PropertyAccessExcludes"; TransformFlags[TransformFlags["NodeExcludes"] = 939525441] = "NodeExcludes"; @@ -2850,6 +3297,8 @@ var ts; TransformFlags[TransformFlags["ParameterExcludes"] = 939525441] = "ParameterExcludes"; TransformFlags[TransformFlags["CatchClauseExcludes"] = 940574017] = "CatchClauseExcludes"; TransformFlags[TransformFlags["BindingPatternExcludes"] = 940049729] = "BindingPatternExcludes"; + // Masks + // - Additional bitmasks TransformFlags[TransformFlags["TypeScriptClassSyntaxMask"] = 274432] = "TypeScriptClassSyntaxMask"; TransformFlags[TransformFlags["ES2015FunctionSyntaxMask"] = 163840] = "ES2015FunctionSyntaxMask"; })(TransformFlags = ts.TransformFlags || (ts.TransformFlags = {})); @@ -2884,9 +3333,14 @@ var ts; EmitFlags[EmitFlags["HasEndOfDeclarationMarker"] = 4194304] = "HasEndOfDeclarationMarker"; EmitFlags[EmitFlags["Iterator"] = 8388608] = "Iterator"; EmitFlags[EmitFlags["NoAsciiEscaping"] = 16777216] = "NoAsciiEscaping"; - EmitFlags[EmitFlags["TypeScriptClassWrapper"] = 33554432] = "TypeScriptClassWrapper"; - EmitFlags[EmitFlags["NeverApplyImportHelper"] = 67108864] = "NeverApplyImportHelper"; + /*@internal*/ EmitFlags[EmitFlags["TypeScriptClassWrapper"] = 33554432] = "TypeScriptClassWrapper"; + /*@internal*/ EmitFlags[EmitFlags["NeverApplyImportHelper"] = 67108864] = "NeverApplyImportHelper"; })(EmitFlags = ts.EmitFlags || (ts.EmitFlags = {})); + /** + * Used by the checker, this enum keeps track of external emit helpers that should be type + * checked. + */ + /* @internal */ var ExternalEmitHelpers; (function (ExternalEmitHelpers) { ExternalEmitHelpers[ExternalEmitHelpers["Extends"] = 1] = "Extends"; @@ -2908,10 +3362,15 @@ var ts; ExternalEmitHelpers[ExternalEmitHelpers["MakeTemplateObject"] = 65536] = "MakeTemplateObject"; ExternalEmitHelpers[ExternalEmitHelpers["FirstEmitHelper"] = 1] = "FirstEmitHelper"; ExternalEmitHelpers[ExternalEmitHelpers["LastEmitHelper"] = 65536] = "LastEmitHelper"; + // Helpers included by ES2015 for..of ExternalEmitHelpers[ExternalEmitHelpers["ForOfIncludes"] = 256] = "ForOfIncludes"; + // Helpers included by ES2017 for..await..of ExternalEmitHelpers[ExternalEmitHelpers["ForAwaitOfIncludes"] = 16384] = "ForAwaitOfIncludes"; + // Helpers included by ES2017 async generators ExternalEmitHelpers[ExternalEmitHelpers["AsyncGeneratorIncludes"] = 6144] = "AsyncGeneratorIncludes"; + // Helpers included by yield* in ES2017 async generators ExternalEmitHelpers[ExternalEmitHelpers["AsyncDelegatorIncludes"] = 26624] = "AsyncDelegatorIncludes"; + // Helpers included by ES2015 spread ExternalEmitHelpers[ExternalEmitHelpers["SpreadIncludes"] = 1536] = "SpreadIncludes"; })(ExternalEmitHelpers = ts.ExternalEmitHelpers || (ts.ExternalEmitHelpers = {})); var EmitHint; @@ -2925,19 +3384,23 @@ var ts; var ListFormat; (function (ListFormat) { ListFormat[ListFormat["None"] = 0] = "None"; + // Line separators ListFormat[ListFormat["SingleLine"] = 0] = "SingleLine"; ListFormat[ListFormat["MultiLine"] = 1] = "MultiLine"; ListFormat[ListFormat["PreserveLines"] = 2] = "PreserveLines"; ListFormat[ListFormat["LinesMask"] = 3] = "LinesMask"; + // Delimiters ListFormat[ListFormat["NotDelimited"] = 0] = "NotDelimited"; ListFormat[ListFormat["BarDelimited"] = 4] = "BarDelimited"; ListFormat[ListFormat["AmpersandDelimited"] = 8] = "AmpersandDelimited"; ListFormat[ListFormat["CommaDelimited"] = 16] = "CommaDelimited"; ListFormat[ListFormat["DelimitersMask"] = 28] = "DelimitersMask"; ListFormat[ListFormat["AllowTrailingComma"] = 32] = "AllowTrailingComma"; + // Whitespace ListFormat[ListFormat["Indented"] = 64] = "Indented"; ListFormat[ListFormat["SpaceBetweenBraces"] = 128] = "SpaceBetweenBraces"; ListFormat[ListFormat["SpaceBetweenSiblings"] = 256] = "SpaceBetweenSiblings"; + // Brackets/Braces ListFormat[ListFormat["Braces"] = 512] = "Braces"; ListFormat[ListFormat["Parenthesis"] = 1024] = "Parenthesis"; ListFormat[ListFormat["AngleBrackets"] = 2048] = "AngleBrackets"; @@ -2946,11 +3409,13 @@ var ts; ListFormat[ListFormat["OptionalIfUndefined"] = 8192] = "OptionalIfUndefined"; ListFormat[ListFormat["OptionalIfEmpty"] = 16384] = "OptionalIfEmpty"; ListFormat[ListFormat["Optional"] = 24576] = "Optional"; + // Other ListFormat[ListFormat["PreferNewLine"] = 32768] = "PreferNewLine"; ListFormat[ListFormat["NoTrailingNewLine"] = 65536] = "NoTrailingNewLine"; ListFormat[ListFormat["NoInterveningComments"] = 131072] = "NoInterveningComments"; ListFormat[ListFormat["NoSpaceIfEmpty"] = 262144] = "NoSpaceIfEmpty"; ListFormat[ListFormat["SingleElement"] = 524288] = "SingleElement"; + // Precomputed Formats ListFormat[ListFormat["Modifiers"] = 131328] = "Modifiers"; ListFormat[ListFormat["HeritageClauses"] = 256] = "HeritageClauses"; ListFormat[ListFormat["SingleLineTypeLiteralMembers"] = 384] = "SingleLineTypeLiteralMembers"; @@ -2988,18 +3453,40 @@ var ts; ListFormat[ListFormat["Parameters"] = 1296] = "Parameters"; ListFormat[ListFormat["IndexSignatureParameters"] = 4432] = "IndexSignatureParameters"; })(ListFormat = ts.ListFormat || (ts.ListFormat = {})); + /* @internal */ var PragmaKindFlags; (function (PragmaKindFlags) { PragmaKindFlags[PragmaKindFlags["None"] = 0] = "None"; + /** + * Triple slash comment of the form + * /// + */ PragmaKindFlags[PragmaKindFlags["TripleSlashXML"] = 1] = "TripleSlashXML"; + /** + * Single line comment of the form + * // @pragma-name argval1 argval2 + * or + * /// @pragma-name argval1 argval2 + */ PragmaKindFlags[PragmaKindFlags["SingleLine"] = 2] = "SingleLine"; + /** + * Multiline non-jsdoc pragma of the form + * /* @pragma-name argval1 argval2 * / + */ PragmaKindFlags[PragmaKindFlags["MultiLine"] = 4] = "MultiLine"; PragmaKindFlags[PragmaKindFlags["All"] = 7] = "All"; PragmaKindFlags[PragmaKindFlags["Default"] = 7] = "Default"; })(PragmaKindFlags = ts.PragmaKindFlags || (ts.PragmaKindFlags = {})); + /** + * This function only exists to cause exact types to be inferred for all the literals within `commentPragmas` + */ + /* @internal */ function _contextuallyTypePragmas(args) { return args; } + // While not strictly a type, this is here because `PragmaMap` needs to be here to be used with `SourceFile`, and we don't + // fancy effectively defining it twice, once in value-space and once in type-space + /* @internal */ ts.commentPragmas = _contextuallyTypePragmas({ "reference": { args: [ @@ -3008,32 +3495,38 @@ var ts; { name: "path", optional: true, captureSpan: true }, { name: "no-default-lib", optional: true } ], - kind: 1 + kind: 1 /* TripleSlashXML */ }, "amd-dependency": { args: [{ name: "path" }, { name: "name", optional: true }], - kind: 1 + kind: 1 /* TripleSlashXML */ }, "amd-module": { args: [{ name: "name" }], - kind: 1 + kind: 1 /* TripleSlashXML */ }, "ts-check": { - kind: 2 + kind: 2 /* SingleLine */ }, "ts-nocheck": { - kind: 2 + kind: 2 /* SingleLine */ }, "jsx": { args: [{ name: "factory" }], - kind: 4 + kind: 4 /* MultiLine */ }, }); })(ts || (ts = {})); var ts; (function (ts) { + /** + * Set a high stack trace limit to provide more information in case of an error. + * Called for command-line and server use cases. + * Not called if TypeScript is used as a library. + */ + /* @internal */ function setStackTraceLimit() { - if (Error.stackTraceLimit < 100) { + if (Error.stackTraceLimit < 100) { // Also tests that we won't set the property if it doesn't exist. Error.stackTraceLimit = 100; } } @@ -3044,6 +3537,7 @@ var ts; FileWatcherEventKind[FileWatcherEventKind["Changed"] = 1] = "Changed"; FileWatcherEventKind[FileWatcherEventKind["Deleted"] = 2] = "Deleted"; })(FileWatcherEventKind = ts.FileWatcherEventKind || (ts.FileWatcherEventKind = {})); + /* @internal */ var PollingInterval; (function (PollingInterval) { PollingInterval[PollingInterval["High"] = 2000] = "High"; @@ -3059,11 +3553,13 @@ var ts; return pollingIntervalsForPriority[watchPriority]; } var pollingIntervalsForPriority = getPriorityValues(250); + /* @internal */ function watchFileUsingPriorityPollingInterval(host, fileName, callback, watchPriority) { return host.watchFile(fileName, callback, pollingInterval(watchPriority)); } ts.watchFileUsingPriorityPollingInterval = watchFileUsingPriorityPollingInterval; - ts.missingFileModifiedTime = new Date(0); + /* @internal */ + ts.missingFileModifiedTime = new Date(0); // Any subsequent modification will occur after this time function createPollingIntervalBasedLevels(levels) { var _a; return _a = {}, @@ -3074,7 +3570,9 @@ var ts; } var defaultChunkLevels = { Low: 32, Medium: 64, High: 256 }; var pollingChunkSize = createPollingIntervalBasedLevels(defaultChunkLevels); + /* @internal */ ts.unchangedPollThresholds = createPollingIntervalBasedLevels(defaultChunkLevels); + /* @internal */ function setCustomPollingValues(system) { if (!system.getEnvironmentVariable) { return; @@ -3118,6 +3616,7 @@ var ts; } } ts.setCustomPollingValues = setCustomPollingValues; + /* @internal */ function createDynamicPriorityPollingWatchFile(host) { var watchedFiles = []; var changedFilesInLastPoll = []; @@ -3137,7 +3636,9 @@ var ts; return { close: function () { file.isClosed = true; + // Remove from watchedFiles ts.unorderedRemoveItem(watchedFiles, file); + // Do not update polling interval queue since that will happen as part of polling } }; } @@ -3150,6 +3651,7 @@ var ts; } function pollPollingIntervalQueue(queue) { queue.pollIndex = pollQueue(queue, queue.pollingInterval, queue.pollIndex, pollingChunkSize[queue.pollingInterval]); + // Set the next polling index and timeout if (queue.length) { scheduleNextPoll(queue.pollingInterval); } @@ -3159,13 +3661,18 @@ var ts; } } function pollLowPollingIntervalQueue(queue) { - pollQueue(changedFilesInLastPoll, PollingInterval.Low, 0, changedFilesInLastPoll.length); + // Always poll complete list of changedFilesInLastPoll + pollQueue(changedFilesInLastPoll, PollingInterval.Low, /*pollIndex*/ 0, changedFilesInLastPoll.length); + // Finally do the actual polling of the queue pollPollingIntervalQueue(queue); + // Schedule poll if there are files in changedFilesInLastPoll but no files in the actual queue + // as pollPollingIntervalQueue wont schedule for next poll if (!queue.pollScheduled && changedFilesInLastPoll.length) { scheduleNextPoll(PollingInterval.Low); } } function pollQueue(queue, pollingInterval, pollIndex, chunkSize) { + // Max visit would be all elements of the queue var needsVisit = queue.length; var definedValueCopyToIndex = pollIndex; for (var polled = 0; polled < chunkSize && needsVisit > 0; nextPollIndex(), needsVisit--) { @@ -3180,10 +3687,12 @@ var ts; polled++; var fileChanged = onWatchedFileStat(watchedFile, getModifiedTime(watchedFile.fileName)); if (watchedFile.isClosed) { + // Closed watcher as part of callback queue[pollIndex] = undefined; } else if (fileChanged) { watchedFile.unchangedPolls = 0; + // Changed files go to changedFilesInLastPoll queue if (queue !== changedFilesInLastPoll) { queue[pollIndex] = undefined; addChangedFileToLowPollingIntervalQueue(watchedFile); @@ -3193,6 +3702,7 @@ var ts; watchedFile.unchangedPolls++; } else if (queue === changedFilesInLastPoll) { + // Restart unchangedPollCount for unchanged file and move to low polling interval queue watchedFile.unchangedPolls = 1; queue[pollIndex] = undefined; addToPollingIntervalQueue(watchedFile, PollingInterval.Low); @@ -3203,6 +3713,7 @@ var ts; addToPollingIntervalQueue(watchedFile, pollingInterval === PollingInterval.Low ? PollingInterval.Medium : PollingInterval.High); } if (queue[pollIndex]) { + // Copy this file to the non hole location if (definedValueCopyToIndex < pollIndex) { queue[definedValueCopyToIndex] = watchedFile; queue[pollIndex] = undefined; @@ -3210,11 +3721,13 @@ var ts; definedValueCopyToIndex++; } } + // Return next poll index return pollIndex; function nextPollIndex() { pollIndex++; if (pollIndex === queue.length) { if (definedValueCopyToIndex < pollIndex) { + // There are holes from nextDefinedValueIndex to end of queue, change queue size queue.length = definedValueCopyToIndex; } pollIndex = 0; @@ -3253,6 +3766,10 @@ var ts; } } ts.createDynamicPriorityPollingWatchFile = createDynamicPriorityPollingWatchFile; + /** + * Returns true if file status changed + */ + /*@internal*/ function onWatchedFileStat(watchedFile, modifiedTime) { var oldTime = watchedFile.mtime.getTime(); var newTime = modifiedTime.getTime(); @@ -3269,11 +3786,22 @@ var ts; return false; } ts.onWatchedFileStat = onWatchedFileStat; + /** + * Watch the directory recursively using host provided method to watch child directories + * that means if this is recursive watcher, watch the children directories as well + * (eg on OS that dont support recursive watch using fs.watch use fs.watchFile) + */ + /*@internal*/ function createRecursiveDirectoryWatcher(host) { return createDirectoryWatcher; + /** + * Create the directory watcher for the dirPath. + */ function createDirectoryWatcher(dirName, callback) { var watcher = host.watchDirectory(dirName, function (fileName) { + // Call the actual callback callback(fileName); + // Iterate through existing children and update the watches if needed updateChildWatches(result, callback); }); var result = { @@ -3289,21 +3817,33 @@ var ts; return result; } function updateChildWatches(watcher, callback) { + // Iterate through existing children and update the watches if needed if (watcher) { watcher.childWatches = watchChildDirectories(watcher.dirName, watcher.childWatches, callback); } } + /** + * Watch the directories in the parentDir + */ function watchChildDirectories(parentDir, existingChildWatches, callback) { var newChildWatches; ts.enumerateInsertsAndDeletes(host.directoryExists(parentDir) ? ts.mapDefined(host.getAccessibleSortedChildDirectories(parentDir), function (child) { var childFullName = ts.getNormalizedAbsolutePath(child, parentDir); - return host.filePathComparer(childFullName, host.realpath(childFullName)) === 0 ? childFullName : undefined; + // Filter our the symbolic link directories since those arent included in recursive watch + // which is same behaviour when recursive: true is passed to fs.watch + return host.filePathComparer(childFullName, host.realpath(childFullName)) === 0 /* EqualTo */ ? childFullName : undefined; }) : ts.emptyArray, existingChildWatches, function (child, childWatcher) { return host.filePathComparer(child, childWatcher.dirName); }, createAndAddChildDirectoryWatcher, ts.closeFileWatcher, addChildDirectoryWatcher); return newChildWatches || ts.emptyArray; + /** + * Create new childDirectoryWatcher and add it to the new ChildDirectoryWatcher list + */ function createAndAddChildDirectoryWatcher(childName) { var result = createDirectoryWatcher(childName, callback); addChildDirectoryWatcher(result); } + /** + * Add child directory watcher to the new ChildDirectoryWatcher list + */ function addChildDirectoryWatcher(childWatcher) { (newChildWatches || (newChildWatches = [])).push(childWatcher); } @@ -3325,12 +3865,17 @@ var ts; return parseInt(version.substring(1, dot)); } ts.getNodeMajorVersion = getNodeMajorVersion; + // TODO: this is used as if it's certainly defined in many places. ts.sys = (function () { + // NodeJS detects "\uFEFF" at the start of the string and *replaces* it with the actual + // byte order mark from the specified encoding. Using any other byte order mark does + // not actually work. var byteOrderMarkIndicator = "\uFEFF"; function getNodeSystem() { var _fs = require("fs"); var _path = require("path"); var _os = require("os"); + // crypto can be absent on reduced node installations var _crypto; try { _crypto = require("crypto"); @@ -3403,7 +3948,7 @@ var ts; return stat.size; } } - catch (_a) { } + catch ( /*ignore*/_a) { /*ignore*/ } return 0; }, exit: function (exitCode) { @@ -3416,6 +3961,7 @@ var ts; require("source-map-support").install(); } catch (_a) { + // Could not enable source maps. } }, setTimeout: setTimeout, @@ -3441,11 +3987,14 @@ var ts; }; return nodeSystem; function isFileSystemCaseSensitive() { + // win32\win64 are case insensitive platforms if (platform === "win32" || platform === "win64") { return false; } + // If this file exists under a different case, we must be case-insensitve. return !fileExists(swapCase(__filename)); } + /** Convert all lowercase chars to uppercase, and vice-versa */ function swapCase(s) { return s.replace(/\w/g, function (ch) { var up = ch.toUpperCase(); @@ -3455,22 +4004,30 @@ var ts; function getWatchFile() { switch (tscWatchFile) { case "PriorityPollingInterval": + // Use polling interval based on priority when create watch using host.watchFile return fsWatchFile; case "DynamicPriorityPolling": + // Use polling interval but change the interval depending on file changes and their default polling interval return createDynamicPriorityPollingWatchFile({ getModifiedTime: getModifiedTime, setTimeout: setTimeout }); case "UseFsEvents": + // Use notifications from FS to watch with falling back to fs.watchFile return watchFileUsingFsWatch; case "UseFsEventsWithFallbackDynamicPolling": + // Use notifications from FS to watch with falling back to dynamic watch file dynamicPollingWatchFile = createDynamicPriorityPollingWatchFile({ getModifiedTime: getModifiedTime, setTimeout: setTimeout }); return createWatchFileUsingDynamicWatchFile(dynamicPollingWatchFile); case "UseFsEventsOnParentDirectory": + // Use notifications from FS to watch with falling back to fs.watchFile return createNonPollingWatchFile(); } return useNonPollingWatchers ? createNonPollingWatchFile() : + // Default to do not use polling interval as it is before this experiment branch function (fileName, callback) { return fsWatchFile(fileName, callback); }; } function getWatchDirectory() { + // Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows + // (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643) var fsSupportsRecursive = isNode4OrLater && (process.platform === "win32" || process.platform === "darwin"); if (fsSupportsRecursive) { return watchDirectoryUsingFsWatch; @@ -3492,10 +4049,11 @@ var ts; return watchDirectoryRecursively(directoryName, callback); } watchDirectory(directoryName, callback); - return undefined; + return undefined; // TODO: GH#18217 }; } function createNonPollingWatchFile() { + // One file can have multiple watchers var fileWatcherCallbacks = ts.createMultiMap(); var dirWatchers = ts.createMap(); var toCanonicalName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); @@ -3521,9 +4079,11 @@ var ts; } function createDirectoryWatcher(dirName, dirPath) { var watcher = fsWatchDirectory(dirName, function (_eventName, relativeFileName) { + // When files are deleted from disk, the triggered "rename" event would have a relativefileName of "undefined" var fileName = !ts.isString(relativeFileName) - ? undefined + ? undefined // TODO: GH#18217 : ts.getNormalizedAbsolutePath(relativeFileName, dirName); + // Some applications save a working file via rename operations var callbacks = fileWatcherCallbacks.get(toCanonicalName(fileName)); if (callbacks) { for (var _i = 0, callbacks_1 = callbacks; _i < callbacks_1.length; _i++) { @@ -3544,9 +4104,12 @@ var ts; close: function () { return _fs.unwatchFile(fileName, fileChanged); } }; function fileChanged(curr, prev) { + // previous event kind check is to ensure we recongnize the file as previously also missing when it is restored or renamed twice (that is it disappears and reappears) + // In such case, prevTime returned is same as prev time of event when file was deleted as per node documentation var isPreviouslyDeleted = +prev.mtime === 0 || eventKind === FileWatcherEventKind.Deleted; if (+curr.mtime === 0) { if (isPreviouslyDeleted) { + // Already deleted file, no need to callback again return; } eventKind = FileWatcherEventKind.Deleted; @@ -3554,10 +4117,12 @@ var ts; else if (isPreviouslyDeleted) { eventKind = FileWatcherEventKind.Created; } + // If there is no change in modified time, ignore the event else if (+curr.mtime === +prev.mtime) { return; } else { + // File changed eventKind = FileWatcherEventKind.Changed; } callback(fileName, eventKind); @@ -3572,36 +4137,55 @@ var ts; callback(fileName, fileExists(fileName) ? FileWatcherEventKind.Created : FileWatcherEventKind.Deleted); } else { + // Change callback(fileName, FileWatcherEventKind.Changed); } }; } function createFsWatchCallbackForDirectoryWatcherCallback(directoryName, callback) { return function (eventName, relativeFileName) { + // In watchDirectory we only care about adding and removing files (when event name is + // "rename"); changes made within files are handled by corresponding fileWatchers (when + // event name is "change") if (eventName === "rename") { + // When deleting a file, the passed baseFileName is null callback(!relativeFileName ? directoryName : ts.normalizePath(ts.combinePaths(directoryName, relativeFileName))); } }; } function fsWatch(fileOrDirectory, entryKind, callback, recursive, fallbackPollingWatchFile, pollingInterval) { var options; + /** Watcher for the file system entry depending on whether it is missing or present */ var watcher = !fileSystemEntryExists(fileOrDirectory, entryKind) ? watchMissingFileSystemEntry() : watchPresentFileSystemEntry(); return { close: function () { + // Close the watcher (either existing file system entry watcher or missing file system entry watcher) watcher.close(); watcher = undefined; } }; + /** + * Invoke the callback with rename and update the watcher if not closed + * @param createWatcher + */ function invokeCallbackAndUpdateWatcher(createWatcher) { + // Call the callback for current directory callback("rename", ""); + // If watcher is not closed, update it if (watcher) { watcher.close(); watcher = createWatcher(); } } + /** + * Watch the file or directory that is currently present + * and when the watched file or directory is deleted, switch to missing file system entry watcher + */ function watchPresentFileSystemEntry() { + // Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows + // (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643) if (options === undefined) { if (isNode4OrLater && (process.platform === "win32" || process.platform === "darwin")) { options = { persistent: true, recursive: !!recursive }; @@ -3612,32 +4196,47 @@ var ts; } try { var presentWatcher = _fs.watch(fileOrDirectory, options, callback); + // Watch the missing file or directory or error presentWatcher.on("error", function () { return invokeCallbackAndUpdateWatcher(watchMissingFileSystemEntry); }); return presentWatcher; } catch (e) { + // Catch the exception and use polling instead + // Eg. on linux the number of watches are limited and one could easily exhaust watches and the exception ENOSPC is thrown when creating watcher at that point + // so instead of throwing error, use fs.watchFile return watchPresentFileSystemEntryWithFsWatchFile(); } } + /** + * Watch the file or directory using fs.watchFile since fs.watch threw exception + * Eg. on linux the number of watches are limited and one could easily exhaust watches and the exception ENOSPC is thrown when creating watcher at that point + */ function watchPresentFileSystemEntryWithFsWatchFile() { return fallbackPollingWatchFile(fileOrDirectory, createFileWatcherCallback(callback), pollingInterval); } + /** + * Watch the file or directory that is missing + * and switch to existing file or directory when the missing filesystem entry is created + */ function watchMissingFileSystemEntry() { return fallbackPollingWatchFile(fileOrDirectory, function (_fileName, eventKind) { if (eventKind === FileWatcherEventKind.Created && fileSystemEntryExists(fileOrDirectory, entryKind)) { + // Call the callback for current file or directory + // For now it could be callback for the inner directory creation, + // but just return current directory, better than current no-op invokeCallbackAndUpdateWatcher(watchPresentFileSystemEntry); } }, pollingInterval); } } function watchFileUsingFsWatch(fileName, callback, pollingInterval) { - return fsWatch(fileName, 0, createFsWatchCallbackForFileWatcherCallback(fileName, callback), false, fsWatchFile, pollingInterval); + return fsWatch(fileName, 0 /* File */, createFsWatchCallbackForFileWatcherCallback(fileName, callback), /*recursive*/ false, fsWatchFile, pollingInterval); } function createWatchFileUsingDynamicWatchFile(watchFile) { - return function (fileName, callback, pollingInterval) { return fsWatch(fileName, 0, createFsWatchCallbackForFileWatcherCallback(fileName, callback), false, watchFile, pollingInterval); }; + return function (fileName, callback, pollingInterval) { return fsWatch(fileName, 0 /* File */, createFsWatchCallbackForFileWatcherCallback(fileName, callback), /*recursive*/ false, watchFile, pollingInterval); }; } function fsWatchDirectory(directoryName, callback, recursive) { - return fsWatch(directoryName, 1, callback, !!recursive, fsWatchFile); + return fsWatch(directoryName, 1 /* Directory */, callback, !!recursive, fsWatchFile); } function watchDirectoryUsingFsWatch(directoryName, callback, recursive) { return fsWatchDirectory(directoryName, createFsWatchCallbackForDirectoryWatcherCallback(directoryName, callback), recursive); @@ -3652,7 +4251,9 @@ var ts; var buffer = _fs.readFileSync(fileName); var len = buffer.length; if (len >= 2 && buffer[0] === 0xFE && buffer[1] === 0xFF) { - len &= ~1; + // Big endian UTF-16 byte order mark detected. Since big endian is not supported by node.js, + // flip all byte pairs and treat as little endian. + len &= ~1; // Round down to a multiple of 2 for (var i = 0; i < len; i += 2) { var temp = buffer[i]; buffer[i] = buffer[i + 1]; @@ -3661,21 +4262,25 @@ var ts; return buffer.toString("utf16le", 2); } if (len >= 2 && buffer[0] === 0xFF && buffer[1] === 0xFE) { + // Little endian UTF-16 byte order mark detected return buffer.toString("utf16le", 2); } if (len >= 3 && buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) { + // UTF-8 byte order mark detected return buffer.toString("utf8", 3); } + // Default is UTF-8 with no byte order mark return buffer.toString("utf8"); } function writeFile(fileName, data, writeByteOrderMark) { + // If a BOM is required, emit one if (writeByteOrderMark) { data = byteOrderMarkIndicator + data; } var fd; try { fd = _fs.openSync(fileName, "w"); - _fs.writeSync(fd, data, undefined, "utf8"); + _fs.writeSync(fd, data, /*position*/ undefined, "utf8"); } finally { if (fd !== undefined) { @@ -3690,6 +4295,8 @@ var ts; var directories = []; for (var _i = 0, entries_2 = entries; _i < entries_2.length; _i++) { var entry = entries_2[_i]; + // This is necessary because on some file system node fails to exclude + // "." and "..". See https://github.com/nodejs/node/issues/4002 if (entry === "." || entry === "..") { continue; } @@ -3721,8 +4328,8 @@ var ts; try { var stat = _fs.statSync(path); switch (entryKind) { - case 0: return stat.isFile(); - case 1: return stat.isDirectory(); + case 0 /* File */: return stat.isFile(); + case 1 /* Directory */: return stat.isDirectory(); default: return false; } } @@ -3731,13 +4338,13 @@ var ts; } } function fileExists(path) { - return fileSystemEntryExists(path, 0); + return fileSystemEntryExists(path, 0 /* File */); } function directoryExists(path) { - return fileSystemEntryExists(path, 1); + return fileSystemEntryExists(path, 1 /* Directory */); } function getDirectories(path) { - return ts.filter(_fs.readdirSync(path), function (dir) { return fileSystemEntryExists(ts.combinePaths(path, dir), 1); }); + return ts.filter(_fs.readdirSync(path), function (dir) { return fileSystemEntryExists(ts.combinePaths(path, dir), 1 /* Directory */); }); } function realpath(path) { try { @@ -3771,6 +4378,10 @@ var ts; return; } } + /** + * djb2 hashing algorithm + * http://www.cse.yorku.ca/~oz/hash.html + */ function generateDjb2Hash(data) { var chars = data.split("").map(function (str) { return str.charCodeAt(0); }); return "" + chars.reduce(function (prev, curr) { return ((prev << 5) + prev) + curr; }, 5381); @@ -3794,9 +4405,11 @@ var ts; useCaseSensitiveFileNames: !!ChakraHost.useCaseSensitiveFileNames, write: ChakraHost.echo, readFile: function (path, _encoding) { + // encoding is automatically handled by the implementation in ChakraHost return ChakraHost.readFile(path); }, writeFile: function (path, data, writeByteOrderMark) { + // If a BOM is required, emit one if (writeByteOrderMark) { data = byteOrderMarkIndicator + data; } @@ -3833,9 +4446,12 @@ var ts; sys = getChakraSystem(); } else if (typeof process !== "undefined" && process.nextTick && !process.browser && typeof require !== "undefined") { + // process and process.nextTick checks if current environment is node-like + // process.browser check excludes webpack and browserify sys = getNodeSystem(); } if (sys) { + // patch writefile to create folder before writing the file var originalWriteFile_1 = sys.writeFile; sys.writeFile = function (path, data, writeBom) { var directoryPath = ts.getDirectoryPath(ts.normalizeSlashes(path)); @@ -3850,18 +4466,22 @@ var ts; if (ts.sys && ts.sys.getEnvironmentVariable) { setCustomPollingValues(ts.sys); ts.Debug.currentAssertionLevel = /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV")) - ? 1 - : 0; + ? 1 /* Normal */ + : 0 /* None */; } if (ts.sys && ts.sys.debugMode) { ts.Debug.isDebugging = true; } })(ts || (ts = {})); +// +// generated from './diagnosticInformationMap.generated.ts' by 'src/compiler' +/* @internal */ var ts; (function (ts) { function diag(code, category, key, message, reportsUnnecessary) { return { code: code, category: category, key: key, message: message, reportsUnnecessary: reportsUnnecessary }; } + // tslint:disable-next-line variable-name ts.Diagnostics = { Unterminated_string_literal: diag(1002, ts.DiagnosticCategory.Error, "Unterminated_string_literal_1002", "Unterminated string literal."), Identifier_expected: diag(1003, ts.DiagnosticCategory.Error, "Identifier_expected_1003", "Identifier expected."), @@ -4424,7 +5044,7 @@ var ts; _0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible: diag(2692, ts.DiagnosticCategory.Error, "_0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible_2692", "'{0}' is a primitive, but '{1}' is a wrapper object. Prefer using '{0}' when possible."), _0_only_refers_to_a_type_but_is_being_used_as_a_value_here: diag(2693, ts.DiagnosticCategory.Error, "_0_only_refers_to_a_type_but_is_being_used_as_a_value_here_2693", "'{0}' only refers to a type, but is being used as a value here."), Namespace_0_has_no_exported_member_1: diag(2694, ts.DiagnosticCategory.Error, "Namespace_0_has_no_exported_member_1_2694", "Namespace '{0}' has no exported member '{1}'."), - Left_side_of_comma_operator_is_unused_and_has_no_side_effects: diag(2695, ts.DiagnosticCategory.Error, "Left_side_of_comma_operator_is_unused_and_has_no_side_effects_2695", "Left side of comma operator is unused and has no side effects.", true), + Left_side_of_comma_operator_is_unused_and_has_no_side_effects: diag(2695, ts.DiagnosticCategory.Error, "Left_side_of_comma_operator_is_unused_and_has_no_side_effects_2695", "Left side of comma operator is unused and has no side effects.", /*reportsUnnecessary*/ true), The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead: diag(2696, ts.DiagnosticCategory.Error, "The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead_2696", "The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead?"), An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option: diag(2697, ts.DiagnosticCategory.Error, "An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_in_2697", "An async function or method must return a 'Promise'. Make sure you have a declaration for 'Promise' or include 'ES2015' in your `--lib` option."), Spread_types_may_only_be_created_from_object_types: diag(2698, ts.DiagnosticCategory.Error, "Spread_types_may_only_be_created_from_object_types_2698", "Spread types may only be created from object types."), @@ -4690,12 +5310,12 @@ var ts; Resolving_real_path_for_0_result_1: diag(6130, ts.DiagnosticCategory.Message, "Resolving_real_path_for_0_result_1_6130", "Resolving real path for '{0}', result '{1}'."), Cannot_compile_modules_using_option_0_unless_the_module_flag_is_amd_or_system: diag(6131, ts.DiagnosticCategory.Error, "Cannot_compile_modules_using_option_0_unless_the_module_flag_is_amd_or_system_6131", "Cannot compile modules using option '{0}' unless the '--module' flag is 'amd' or 'system'."), File_name_0_has_a_1_extension_stripping_it: diag(6132, ts.DiagnosticCategory.Message, "File_name_0_has_a_1_extension_stripping_it_6132", "File name '{0}' has a '{1}' extension - stripping it."), - _0_is_declared_but_its_value_is_never_read: diag(6133, ts.DiagnosticCategory.Error, "_0_is_declared_but_its_value_is_never_read_6133", "'{0}' is declared but its value is never read.", true), + _0_is_declared_but_its_value_is_never_read: diag(6133, ts.DiagnosticCategory.Error, "_0_is_declared_but_its_value_is_never_read_6133", "'{0}' is declared but its value is never read.", /*reportsUnnecessary*/ true), Report_errors_on_unused_locals: diag(6134, ts.DiagnosticCategory.Message, "Report_errors_on_unused_locals_6134", "Report errors on unused locals."), Report_errors_on_unused_parameters: diag(6135, ts.DiagnosticCategory.Message, "Report_errors_on_unused_parameters_6135", "Report errors on unused parameters."), The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files: diag(6136, ts.DiagnosticCategory.Message, "The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files_6136", "The maximum dependency depth to search under node_modules and load JavaScript files."), Cannot_import_type_declaration_files_Consider_importing_0_instead_of_1: diag(6137, ts.DiagnosticCategory.Error, "Cannot_import_type_declaration_files_Consider_importing_0_instead_of_1_6137", "Cannot import type declaration files. Consider importing '{0}' instead of '{1}'."), - Property_0_is_declared_but_its_value_is_never_read: diag(6138, ts.DiagnosticCategory.Error, "Property_0_is_declared_but_its_value_is_never_read_6138", "Property '{0}' is declared but its value is never read.", true), + Property_0_is_declared_but_its_value_is_never_read: diag(6138, ts.DiagnosticCategory.Error, "Property_0_is_declared_but_its_value_is_never_read_6138", "Property '{0}' is declared but its value is never read.", /*reportsUnnecessary*/ true), Import_emit_helpers_from_tslib: diag(6139, ts.DiagnosticCategory.Message, "Import_emit_helpers_from_tslib_6139", "Import emit helpers from 'tslib'."), Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using_cache_location_2: diag(6140, ts.DiagnosticCategory.Error, "Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using__6140", "Auto discovery for typings is enabled in project '{0}'. Running extra resolution pass for module '{1}' using cache location '{2}'."), Parse_in_strict_mode_and_emit_use_strict_for_each_source_file: diag(6141, ts.DiagnosticCategory.Message, "Parse_in_strict_mode_and_emit_use_strict_for_each_source_file_6141", "Parse in strict mode and emit \"use strict\" for each source file."), @@ -4748,14 +5368,14 @@ var ts; Multiple_consecutive_numeric_separators_are_not_permitted: diag(6189, ts.DiagnosticCategory.Error, "Multiple_consecutive_numeric_separators_are_not_permitted_6189", "Multiple consecutive numeric separators are not permitted."), Found_package_json_at_0_Package_ID_is_1: diag(6190, ts.DiagnosticCategory.Message, "Found_package_json_at_0_Package_ID_is_1_6190", "Found 'package.json' at '{0}'. Package ID is '{1}'."), Whether_to_keep_outdated_console_output_in_watch_mode_instead_of_clearing_the_screen: diag(6191, ts.DiagnosticCategory.Message, "Whether_to_keep_outdated_console_output_in_watch_mode_instead_of_clearing_the_screen_6191", "Whether to keep outdated console output in watch mode instead of clearing the screen."), - All_imports_in_import_declaration_are_unused: diag(6192, ts.DiagnosticCategory.Error, "All_imports_in_import_declaration_are_unused_6192", "All imports in import declaration are unused.", true), + All_imports_in_import_declaration_are_unused: diag(6192, ts.DiagnosticCategory.Error, "All_imports_in_import_declaration_are_unused_6192", "All imports in import declaration are unused.", /*reportsUnnecessary*/ true), Found_1_error_Watching_for_file_changes: diag(6193, ts.DiagnosticCategory.Message, "Found_1_error_Watching_for_file_changes_6193", "Found 1 error. Watching for file changes."), Found_0_errors_Watching_for_file_changes: diag(6194, ts.DiagnosticCategory.Message, "Found_0_errors_Watching_for_file_changes_6194", "Found {0} errors. Watching for file changes."), Resolve_keyof_to_string_valued_property_names_only_no_numbers_or_symbols: diag(6195, ts.DiagnosticCategory.Message, "Resolve_keyof_to_string_valued_property_names_only_no_numbers_or_symbols_6195", "Resolve 'keyof' to string valued property names only (no numbers or symbols)."), - _0_is_declared_but_never_used: diag(6196, ts.DiagnosticCategory.Error, "_0_is_declared_but_never_used_6196", "'{0}' is declared but never used.", true), + _0_is_declared_but_never_used: diag(6196, ts.DiagnosticCategory.Error, "_0_is_declared_but_never_used_6196", "'{0}' is declared but never used.", /*reportsUnnecessary*/ true), Include_modules_imported_with_json_extension: diag(6197, ts.DiagnosticCategory.Message, "Include_modules_imported_with_json_extension_6197", "Include modules imported with '.json' extension"), - All_destructured_elements_are_unused: diag(6198, ts.DiagnosticCategory.Error, "All_destructured_elements_are_unused_6198", "All destructured elements are unused.", true), - All_variables_are_unused: diag(6199, ts.DiagnosticCategory.Error, "All_variables_are_unused_6199", "All variables are unused.", true), + All_destructured_elements_are_unused: diag(6198, ts.DiagnosticCategory.Error, "All_destructured_elements_are_unused_6198", "All destructured elements are unused.", /*reportsUnnecessary*/ true), + All_variables_are_unused: diag(6199, ts.DiagnosticCategory.Error, "All_variables_are_unused_6199", "All variables are unused.", /*reportsUnnecessary*/ true), Projects_to_reference: diag(6300, ts.DiagnosticCategory.Message, "Projects_to_reference_6300", "Projects to reference"), Enable_project_compilation: diag(6302, ts.DiagnosticCategory.Message, "Enable_project_compilation_6302", "Enable project compilation"), Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0: diag(6202, ts.DiagnosticCategory.Error, "Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0_6202", "Project references may not form a circular graph. Cycle detected: {0}"), @@ -4805,8 +5425,8 @@ var ts; Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions: diag(7024, ts.DiagnosticCategory.Error, "Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_ref_7024", "Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions."), Generator_implicitly_has_type_0_because_it_does_not_yield_any_values_Consider_supplying_a_return_type: diag(7025, ts.DiagnosticCategory.Error, "Generator_implicitly_has_type_0_because_it_does_not_yield_any_values_Consider_supplying_a_return_typ_7025", "Generator implicitly has type '{0}' because it does not yield any values. Consider supplying a return type."), JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists: diag(7026, ts.DiagnosticCategory.Error, "JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists_7026", "JSX element implicitly has type 'any' because no interface 'JSX.{0}' exists."), - Unreachable_code_detected: diag(7027, ts.DiagnosticCategory.Error, "Unreachable_code_detected_7027", "Unreachable code detected.", true), - Unused_label: diag(7028, ts.DiagnosticCategory.Error, "Unused_label_7028", "Unused label.", true), + Unreachable_code_detected: diag(7027, ts.DiagnosticCategory.Error, "Unreachable_code_detected_7027", "Unreachable code detected.", /*reportsUnnecessary*/ true), + Unused_label: diag(7028, ts.DiagnosticCategory.Error, "Unused_label_7028", "Unused label.", /*reportsUnnecessary*/ true), Fallthrough_case_in_switch: diag(7029, ts.DiagnosticCategory.Error, "Fallthrough_case_in_switch_7029", "Fallthrough case in switch."), Not_all_code_paths_return_a_value: diag(7030, ts.DiagnosticCategory.Error, "Not_all_code_paths_return_a_value_7030", "Not all code paths return a value."), Binding_element_0_implicitly_has_an_1_type: diag(7031, ts.DiagnosticCategory.Error, "Binding_element_0_implicitly_has_an_1_type_7031", "Binding element '{0}' implicitly has an '{1}' type."), @@ -4966,157 +5586,204 @@ var ts; })(ts || (ts = {})); var ts; (function (ts) { + /* @internal */ function tokenIsIdentifierOrKeyword(token) { - return token >= 71; + return token >= 71 /* Identifier */; } ts.tokenIsIdentifierOrKeyword = tokenIsIdentifierOrKeyword; + /* @internal */ function tokenIsIdentifierOrKeywordOrGreaterThan(token) { - return token === 29 || tokenIsIdentifierOrKeyword(token); + return token === 29 /* GreaterThanToken */ || tokenIsIdentifierOrKeyword(token); } ts.tokenIsIdentifierOrKeywordOrGreaterThan = tokenIsIdentifierOrKeywordOrGreaterThan; var textToToken = ts.createMapFromTemplate({ - "abstract": 117, - "any": 119, - "as": 118, - "boolean": 122, - "break": 72, - "case": 73, - "catch": 74, - "class": 75, - "continue": 77, - "const": 76, - "constructor": 123, - "debugger": 78, - "declare": 124, - "default": 79, - "delete": 80, - "do": 81, - "else": 82, - "enum": 83, - "export": 84, - "extends": 85, - "false": 86, - "finally": 87, - "for": 88, - "from": 143, - "function": 89, - "get": 125, - "if": 90, - "implements": 108, - "import": 91, - "in": 92, - "infer": 126, - "instanceof": 93, - "interface": 109, - "is": 127, - "keyof": 128, - "let": 110, - "module": 129, - "namespace": 130, - "never": 131, - "new": 94, - "null": 95, - "number": 134, - "object": 135, - "package": 111, - "private": 112, - "protected": 113, - "public": 114, - "readonly": 132, - "require": 133, - "global": 144, - "return": 96, - "set": 136, - "static": 115, - "string": 137, - "super": 97, - "switch": 98, - "symbol": 138, - "this": 99, - "throw": 100, - "true": 101, - "try": 102, - "type": 139, - "typeof": 103, - "undefined": 140, - "unique": 141, - "unknown": 142, - "var": 104, - "void": 105, - "while": 106, - "with": 107, - "yield": 116, - "async": 120, - "await": 121, - "of": 145, - "{": 17, - "}": 18, - "(": 19, - ")": 20, - "[": 21, - "]": 22, - ".": 23, - "...": 24, - ";": 25, - ",": 26, - "<": 27, - ">": 29, - "<=": 30, - ">=": 31, - "==": 32, - "!=": 33, - "===": 34, - "!==": 35, - "=>": 36, - "+": 37, - "-": 38, - "**": 40, - "*": 39, - "/": 41, - "%": 42, - "++": 43, - "--": 44, - "<<": 45, - ">": 46, - ">>>": 47, - "&": 48, - "|": 49, - "^": 50, - "!": 51, - "~": 52, - "&&": 53, - "||": 54, - "?": 55, - ":": 56, - "=": 58, - "+=": 59, - "-=": 60, - "*=": 61, - "**=": 62, - "/=": 63, - "%=": 64, - "<<=": 65, - ">>=": 66, - ">>>=": 67, - "&=": 68, - "|=": 69, - "^=": 70, - "@": 57, + "abstract": 117 /* AbstractKeyword */, + "any": 119 /* AnyKeyword */, + "as": 118 /* AsKeyword */, + "boolean": 122 /* BooleanKeyword */, + "break": 72 /* BreakKeyword */, + "case": 73 /* CaseKeyword */, + "catch": 74 /* CatchKeyword */, + "class": 75 /* ClassKeyword */, + "continue": 77 /* ContinueKeyword */, + "const": 76 /* ConstKeyword */, + "constructor": 123 /* ConstructorKeyword */, + "debugger": 78 /* DebuggerKeyword */, + "declare": 124 /* DeclareKeyword */, + "default": 79 /* DefaultKeyword */, + "delete": 80 /* DeleteKeyword */, + "do": 81 /* DoKeyword */, + "else": 82 /* ElseKeyword */, + "enum": 83 /* EnumKeyword */, + "export": 84 /* ExportKeyword */, + "extends": 85 /* ExtendsKeyword */, + "false": 86 /* FalseKeyword */, + "finally": 87 /* FinallyKeyword */, + "for": 88 /* ForKeyword */, + "from": 143 /* FromKeyword */, + "function": 89 /* FunctionKeyword */, + "get": 125 /* GetKeyword */, + "if": 90 /* IfKeyword */, + "implements": 108 /* ImplementsKeyword */, + "import": 91 /* ImportKeyword */, + "in": 92 /* InKeyword */, + "infer": 126 /* InferKeyword */, + "instanceof": 93 /* InstanceOfKeyword */, + "interface": 109 /* InterfaceKeyword */, + "is": 127 /* IsKeyword */, + "keyof": 128 /* KeyOfKeyword */, + "let": 110 /* LetKeyword */, + "module": 129 /* ModuleKeyword */, + "namespace": 130 /* NamespaceKeyword */, + "never": 131 /* NeverKeyword */, + "new": 94 /* NewKeyword */, + "null": 95 /* NullKeyword */, + "number": 134 /* NumberKeyword */, + "object": 135 /* ObjectKeyword */, + "package": 111 /* PackageKeyword */, + "private": 112 /* PrivateKeyword */, + "protected": 113 /* ProtectedKeyword */, + "public": 114 /* PublicKeyword */, + "readonly": 132 /* ReadonlyKeyword */, + "require": 133 /* RequireKeyword */, + "global": 144 /* GlobalKeyword */, + "return": 96 /* ReturnKeyword */, + "set": 136 /* SetKeyword */, + "static": 115 /* StaticKeyword */, + "string": 137 /* StringKeyword */, + "super": 97 /* SuperKeyword */, + "switch": 98 /* SwitchKeyword */, + "symbol": 138 /* SymbolKeyword */, + "this": 99 /* ThisKeyword */, + "throw": 100 /* ThrowKeyword */, + "true": 101 /* TrueKeyword */, + "try": 102 /* TryKeyword */, + "type": 139 /* TypeKeyword */, + "typeof": 103 /* TypeOfKeyword */, + "undefined": 140 /* UndefinedKeyword */, + "unique": 141 /* UniqueKeyword */, + "unknown": 142 /* UnknownKeyword */, + "var": 104 /* VarKeyword */, + "void": 105 /* VoidKeyword */, + "while": 106 /* WhileKeyword */, + "with": 107 /* WithKeyword */, + "yield": 116 /* YieldKeyword */, + "async": 120 /* AsyncKeyword */, + "await": 121 /* AwaitKeyword */, + "of": 145 /* OfKeyword */, + "{": 17 /* OpenBraceToken */, + "}": 18 /* CloseBraceToken */, + "(": 19 /* OpenParenToken */, + ")": 20 /* CloseParenToken */, + "[": 21 /* OpenBracketToken */, + "]": 22 /* CloseBracketToken */, + ".": 23 /* DotToken */, + "...": 24 /* DotDotDotToken */, + ";": 25 /* SemicolonToken */, + ",": 26 /* CommaToken */, + "<": 27 /* LessThanToken */, + ">": 29 /* GreaterThanToken */, + "<=": 30 /* LessThanEqualsToken */, + ">=": 31 /* GreaterThanEqualsToken */, + "==": 32 /* EqualsEqualsToken */, + "!=": 33 /* ExclamationEqualsToken */, + "===": 34 /* EqualsEqualsEqualsToken */, + "!==": 35 /* ExclamationEqualsEqualsToken */, + "=>": 36 /* EqualsGreaterThanToken */, + "+": 37 /* PlusToken */, + "-": 38 /* MinusToken */, + "**": 40 /* AsteriskAsteriskToken */, + "*": 39 /* AsteriskToken */, + "/": 41 /* SlashToken */, + "%": 42 /* PercentToken */, + "++": 43 /* PlusPlusToken */, + "--": 44 /* MinusMinusToken */, + "<<": 45 /* LessThanLessThanToken */, + ">": 46 /* GreaterThanGreaterThanToken */, + ">>>": 47 /* GreaterThanGreaterThanGreaterThanToken */, + "&": 48 /* AmpersandToken */, + "|": 49 /* BarToken */, + "^": 50 /* CaretToken */, + "!": 51 /* ExclamationToken */, + "~": 52 /* TildeToken */, + "&&": 53 /* AmpersandAmpersandToken */, + "||": 54 /* BarBarToken */, + "?": 55 /* QuestionToken */, + ":": 56 /* ColonToken */, + "=": 58 /* EqualsToken */, + "+=": 59 /* PlusEqualsToken */, + "-=": 60 /* MinusEqualsToken */, + "*=": 61 /* AsteriskEqualsToken */, + "**=": 62 /* AsteriskAsteriskEqualsToken */, + "/=": 63 /* SlashEqualsToken */, + "%=": 64 /* PercentEqualsToken */, + "<<=": 65 /* LessThanLessThanEqualsToken */, + ">>=": 66 /* GreaterThanGreaterThanEqualsToken */, + ">>>=": 67 /* GreaterThanGreaterThanGreaterThanEqualsToken */, + "&=": 68 /* AmpersandEqualsToken */, + "|=": 69 /* BarEqualsToken */, + "^=": 70 /* CaretEqualsToken */, + "@": 57 /* AtToken */, }); + /* + As per ECMAScript Language Specification 3th Edition, Section 7.6: Identifiers + IdentifierStart :: + Can contain Unicode 3.0.0 categories: + Uppercase letter (Lu), + Lowercase letter (Ll), + Titlecase letter (Lt), + Modifier letter (Lm), + Other letter (Lo), or + Letter number (Nl). + IdentifierPart :: = + Can contain IdentifierStart + Unicode 3.0.0 categories: + Non-spacing mark (Mn), + Combining spacing mark (Mc), + Decimal number (Nd), or + Connector punctuation (Pc). + + Codepoint ranges for ES3 Identifiers are extracted from the Unicode 3.0.0 specification at: + http://www.unicode.org/Public/3.0-Update/UnicodeData-3.0.0.txt + */ var unicodeES3IdentifierStart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, 740, 750, 750, 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1164, 1220, 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1610, 1649, 1747, 1749, 1749, 1765, 1766, 1786, 1788, 1808, 1808, 1810, 1836, 1920, 1957, 2309, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2784, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 2997, 2999, 3001, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3168, 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3294, 3294, 3296, 3297, 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3424, 3425, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805, 3840, 3840, 3904, 3911, 3913, 3946, 3976, 3979, 4096, 4129, 4131, 4135, 4137, 4138, 4176, 4181, 4256, 4293, 4304, 4342, 4352, 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4742, 4744, 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, 6067, 6176, 6263, 6272, 6312, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8319, 8319, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12346, 12353, 12436, 12445, 12446, 12449, 12538, 12540, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65138, 65140, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500,]; var unicodeES3IdentifierPart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, 740, 750, 750, 768, 846, 864, 866, 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1155, 1158, 1164, 1220, 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1441, 1443, 1465, 1467, 1469, 1471, 1471, 1473, 1474, 1476, 1476, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1621, 1632, 1641, 1648, 1747, 1749, 1756, 1759, 1768, 1770, 1773, 1776, 1788, 1808, 1836, 1840, 1866, 1920, 1968, 2305, 2307, 2309, 2361, 2364, 2381, 2384, 2388, 2392, 2403, 2406, 2415, 2433, 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2492, 2494, 2500, 2503, 2504, 2507, 2509, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2562, 2562, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2649, 2652, 2654, 2654, 2662, 2676, 2689, 2691, 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2784, 2790, 2799, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2876, 2883, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2913, 2918, 2927, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 2997, 2999, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3031, 3031, 3047, 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3134, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3168, 3169, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3262, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3297, 3302, 3311, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3390, 3395, 3398, 3400, 3402, 3405, 3415, 3415, 3424, 3425, 3430, 3439, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3805, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3946, 3953, 3972, 3974, 3979, 3984, 3991, 3993, 4028, 4038, 4038, 4096, 4129, 4131, 4135, 4137, 4138, 4140, 4146, 4150, 4153, 4160, 4169, 4176, 4185, 4256, 4293, 4304, 4342, 4352, 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4742, 4744, 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 4969, 4977, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, 6099, 6112, 6121, 6160, 6169, 6176, 6263, 6272, 6313, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8255, 8256, 8319, 8319, 8400, 8412, 8417, 8417, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12335, 12337, 12341, 12344, 12346, 12353, 12436, 12441, 12442, 12445, 12446, 12449, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65056, 65059, 65075, 65076, 65101, 65103, 65136, 65138, 65140, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65381, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500,]; + /* + As per ECMAScript Language Specification 5th Edition, Section 7.6: ISyntaxToken Names and Identifiers + IdentifierStart :: + Can contain Unicode 6.2 categories: + Uppercase letter (Lu), + Lowercase letter (Ll), + Titlecase letter (Lt), + Modifier letter (Lm), + Other letter (Lo), or + Letter number (Nl). + IdentifierPart :: + Can contain IdentifierStart + Unicode 6.2 categories: + Non-spacing mark (Mn), + Combining spacing mark (Mc), + Decimal number (Nd), + Connector punctuation (Pc), + , or + . + + Codepoint ranges for ES5 Identifiers are extracted from the Unicode 6.2 specification at: + http://www.unicode.org/Public/6.2.0/ucd/UnicodeData.txt + */ var unicodeES5IdentifierStart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 880, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1162, 1319, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1568, 1610, 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775, 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957, 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069, 2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2208, 2208, 2210, 2220, 2308, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2423, 2425, 2431, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929, 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261, 3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3807, 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138, 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198, 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000, 6016, 6067, 6103, 6103, 6108, 6108, 6176, 6263, 6272, 6312, 6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516, 6528, 6571, 6593, 6599, 6656, 6678, 6688, 6740, 6823, 6823, 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7098, 7141, 7168, 7203, 7245, 7247, 7258, 7293, 7401, 7404, 7406, 7409, 7413, 7414, 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, 11499, 11502, 11506, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, 19968, 40908, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539, 42560, 42606, 42623, 42647, 42656, 42735, 42775, 42783, 42786, 42888, 42891, 42894, 42896, 42899, 42912, 42922, 43000, 43009, 43011, 43013, 43015, 43018, 43020, 43042, 43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259, 43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442, 43471, 43471, 43520, 43560, 43584, 43586, 43588, 43595, 43616, 43638, 43642, 43642, 43648, 43695, 43697, 43697, 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714, 43739, 43741, 43744, 43754, 43762, 43764, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44002, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500,]; var unicodeES5IdentifierPart = [170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 768, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1155, 1159, 1162, 1319, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1469, 1471, 1471, 1473, 1474, 1476, 1477, 1479, 1479, 1488, 1514, 1520, 1522, 1552, 1562, 1568, 1641, 1646, 1747, 1749, 1756, 1759, 1768, 1770, 1788, 1791, 1791, 1808, 1866, 1869, 1969, 1984, 2037, 2042, 2042, 2048, 2093, 2112, 2139, 2208, 2208, 2210, 2220, 2276, 2302, 2304, 2403, 2406, 2415, 2417, 2423, 2425, 2431, 2433, 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2500, 2503, 2504, 2507, 2510, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2561, 2563, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2641, 2641, 2649, 2652, 2654, 2654, 2662, 2677, 2689, 2691, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2787, 2790, 2799, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2876, 2884, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2915, 2918, 2927, 2929, 2929, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3024, 3024, 3031, 3031, 3046, 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3160, 3161, 3168, 3171, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3260, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3299, 3302, 3311, 3313, 3314, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3396, 3398, 3400, 3402, 3406, 3415, 3415, 3424, 3427, 3430, 3439, 3450, 3455, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3807, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3948, 3953, 3972, 3974, 3991, 3993, 4028, 4038, 4038, 4096, 4169, 4176, 4253, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4957, 4959, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5908, 5920, 5940, 5952, 5971, 5984, 5996, 5998, 6000, 6002, 6003, 6016, 6099, 6103, 6103, 6108, 6109, 6112, 6121, 6155, 6157, 6160, 6169, 6176, 6263, 6272, 6314, 6320, 6389, 6400, 6428, 6432, 6443, 6448, 6459, 6470, 6509, 6512, 6516, 6528, 6571, 6576, 6601, 6608, 6617, 6656, 6683, 6688, 6750, 6752, 6780, 6783, 6793, 6800, 6809, 6823, 6823, 6912, 6987, 6992, 7001, 7019, 7027, 7040, 7155, 7168, 7223, 7232, 7241, 7245, 7293, 7376, 7378, 7380, 7414, 7424, 7654, 7676, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8204, 8205, 8255, 8256, 8276, 8276, 8305, 8305, 8319, 8319, 8336, 8348, 8400, 8412, 8417, 8417, 8421, 8432, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, 11499, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11647, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11744, 11775, 11823, 11823, 12293, 12295, 12321, 12335, 12337, 12341, 12344, 12348, 12353, 12438, 12441, 12442, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, 19968, 40908, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42539, 42560, 42607, 42612, 42621, 42623, 42647, 42655, 42737, 42775, 42783, 42786, 42888, 42891, 42894, 42896, 42899, 42912, 42922, 43000, 43047, 43072, 43123, 43136, 43204, 43216, 43225, 43232, 43255, 43259, 43259, 43264, 43309, 43312, 43347, 43360, 43388, 43392, 43456, 43471, 43481, 43520, 43574, 43584, 43597, 43600, 43609, 43616, 43638, 43642, 43643, 43648, 43714, 43739, 43741, 43744, 43759, 43762, 43766, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44010, 44012, 44013, 44016, 44025, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65024, 65039, 65056, 65062, 65075, 65076, 65101, 65103, 65136, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500,]; function lookupInUnicodeMap(code, map) { + // Bail out quickly if it couldn't possibly be in the map. if (code < map[0]) { return false; } + // Perform binary search in one of the Unicode range maps var lo = 0; var hi = map.length; var mid; while (lo + 1 < hi) { mid = lo + (hi - lo) / 2; + // mid has to be even to catch a range's beginning mid -= mid % 2; if (map[mid] <= code && code <= map[mid + 1]) { return true; @@ -5130,14 +5797,14 @@ var ts; } return false; } - function isUnicodeIdentifierStart(code, languageVersion) { - return languageVersion >= 1 ? + /* @internal */ function isUnicodeIdentifierStart(code, languageVersion) { + return languageVersion >= 1 /* ES5 */ ? lookupInUnicodeMap(code, unicodeES5IdentifierStart) : lookupInUnicodeMap(code, unicodeES3IdentifierStart); } ts.isUnicodeIdentifierStart = isUnicodeIdentifierStart; function isUnicodeIdentifierPart(code, languageVersion) { - return languageVersion >= 1 ? + return languageVersion >= 1 /* ES5 */ ? lookupInUnicodeMap(code, unicodeES5IdentifierPart) : lookupInUnicodeMap(code, unicodeES3IdentifierPart); } @@ -5153,10 +5820,12 @@ var ts; return tokenStrings[t]; } ts.tokenToString = tokenToString; + /* @internal */ function stringToToken(s) { return textToToken.get(s); } ts.stringToToken = stringToToken; + /* @internal */ function computeLineStarts(text) { var result = new Array(); var pos = 0; @@ -5165,16 +5834,17 @@ var ts; var ch = text.charCodeAt(pos); pos++; switch (ch) { - case 13: - if (text.charCodeAt(pos) === 10) { + case 13 /* carriageReturn */: + if (text.charCodeAt(pos) === 10 /* lineFeed */) { pos++; } - case 10: + // falls through + case 10 /* lineFeed */: result.push(lineStart); lineStart = pos; break; default: - if (ch > 127 && isLineBreak(ch)) { + if (ch > 127 /* maxAsciiCharacter */ && isLineBreak(ch)) { result.push(lineStart); lineStart = pos; } @@ -5189,6 +5859,7 @@ var ts; return computePositionOfLineAndCharacter(getLineStarts(sourceFile), line, character, sourceFile.text); } ts.getPositionOfLineAndCharacter = getPositionOfLineAndCharacter; + /* @internal */ function computePositionOfLineAndCharacter(lineStarts, line, character, debugText) { if (line < 0 || line >= lineStarts.length) { ts.Debug.fail("Bad line number. Line: " + line + ", lineStarts.length: " + lineStarts.length + " , line map is correct? " + (debugText !== undefined ? ts.arraysEqual(lineStarts, computeLineStarts(debugText)) : "unknown")); @@ -5198,18 +5869,30 @@ var ts; ts.Debug.assert(res < lineStarts[line + 1]); } else if (debugText !== undefined) { - ts.Debug.assert(res <= debugText.length); + ts.Debug.assert(res <= debugText.length); // Allow single character overflow for trailing newline } return res; } ts.computePositionOfLineAndCharacter = computePositionOfLineAndCharacter; + /* @internal */ function getLineStarts(sourceFile) { return sourceFile.lineMap || (sourceFile.lineMap = computeLineStarts(sourceFile.text)); } ts.getLineStarts = getLineStarts; + /* @internal */ + /** + * We assume the first line starts at position 0 and 'position' is non-negative. + */ function computeLineAndCharacterOfPosition(lineStarts, position) { var lineNumber = ts.binarySearch(lineStarts, position, ts.identity, ts.compareValues); if (lineNumber < 0) { + // If the actual position was not found, + // the binary search returns the 2's-complement of the next line start + // e.g. if the line starts at [5, 10, 23, 80] and the position requested was 20 + // then the search will return -2. + // + // We want the index of the previous line start, so we subtract 1. + // Review 2's-complement if this is confusing. lineNumber = ~lineNumber - 1; ts.Debug.assert(lineNumber !== -1, "position cannot precede the beginning of the file"); } @@ -5227,86 +5910,107 @@ var ts; return isWhiteSpaceSingleLine(ch) || isLineBreak(ch); } ts.isWhiteSpaceLike = isWhiteSpaceLike; + /** Does not include line breaks. For that, see isWhiteSpaceLike. */ function isWhiteSpaceSingleLine(ch) { - return ch === 32 || - ch === 9 || - ch === 11 || - ch === 12 || - ch === 160 || - ch === 133 || - ch === 5760 || - ch >= 8192 && ch <= 8203 || - ch === 8239 || - ch === 8287 || - ch === 12288 || - ch === 65279; + // Note: nextLine is in the Zs space, and should be considered to be a whitespace. + // It is explicitly not a line-break as it isn't in the exact set specified by EcmaScript. + return ch === 32 /* space */ || + ch === 9 /* tab */ || + ch === 11 /* verticalTab */ || + ch === 12 /* formFeed */ || + ch === 160 /* nonBreakingSpace */ || + ch === 133 /* nextLine */ || + ch === 5760 /* ogham */ || + ch >= 8192 /* enQuad */ && ch <= 8203 /* zeroWidthSpace */ || + ch === 8239 /* narrowNoBreakSpace */ || + ch === 8287 /* mathematicalSpace */ || + ch === 12288 /* ideographicSpace */ || + ch === 65279 /* byteOrderMark */; } ts.isWhiteSpaceSingleLine = isWhiteSpaceSingleLine; function isLineBreak(ch) { - return ch === 10 || - ch === 13 || - ch === 8232 || - ch === 8233; + // ES5 7.3: + // The ECMAScript line terminator characters are listed in Table 3. + // Table 3: Line Terminator Characters + // Code Unit Value Name Formal Name + // \u000A Line Feed + // \u000D Carriage Return + // \u2028 Line separator + // \u2029 Paragraph separator + // Only the characters in Table 3 are treated as line terminators. Other new line or line + // breaking characters are treated as white space but not as line terminators. + return ch === 10 /* lineFeed */ || + ch === 13 /* carriageReturn */ || + ch === 8232 /* lineSeparator */ || + ch === 8233 /* paragraphSeparator */; } ts.isLineBreak = isLineBreak; function isDigit(ch) { - return ch >= 48 && ch <= 57; + return ch >= 48 /* _0 */ && ch <= 57 /* _9 */; } + /* @internal */ function isOctalDigit(ch) { - return ch >= 48 && ch <= 55; + return ch >= 48 /* _0 */ && ch <= 55 /* _7 */; } ts.isOctalDigit = isOctalDigit; function couldStartTrivia(text, pos) { + // Keep in sync with skipTrivia var ch = text.charCodeAt(pos); switch (ch) { - case 13: - case 10: - case 9: - case 11: - case 12: - case 32: - case 47: - case 60: - case 124: - case 61: - case 62: + case 13 /* carriageReturn */: + case 10 /* lineFeed */: + case 9 /* tab */: + case 11 /* verticalTab */: + case 12 /* formFeed */: + case 32 /* space */: + case 47 /* slash */: + // starts of normal trivia + case 60 /* lessThan */: + case 124 /* bar */: + case 61 /* equals */: + case 62 /* greaterThan */: + // Starts of conflict marker trivia return true; - case 35: + case 35 /* hash */: + // Only if its the beginning can we have #! trivia return pos === 0; default: - return ch > 127; + return ch > 127 /* maxAsciiCharacter */; } } ts.couldStartTrivia = couldStartTrivia; + /* @internal */ function skipTrivia(text, pos, stopAfterLineBreak, stopAtComments) { if (stopAtComments === void 0) { stopAtComments = false; } if (ts.positionIsSynthesized(pos)) { return pos; } + // Keep in sync with couldStartTrivia while (true) { var ch = text.charCodeAt(pos); switch (ch) { - case 13: - if (text.charCodeAt(pos + 1) === 10) { + case 13 /* carriageReturn */: + if (text.charCodeAt(pos + 1) === 10 /* lineFeed */) { pos++; } - case 10: + // falls through + case 10 /* lineFeed */: pos++; if (stopAfterLineBreak) { return pos; } continue; - case 9: - case 11: - case 12: - case 32: + case 9 /* tab */: + case 11 /* verticalTab */: + case 12 /* formFeed */: + case 32 /* space */: pos++; continue; - case 47: + case 47 /* slash */: if (stopAtComments) { break; } - if (text.charCodeAt(pos + 1) === 47) { + if (text.charCodeAt(pos + 1) === 47 /* slash */) { pos += 2; while (pos < text.length) { if (isLineBreak(text.charCodeAt(pos))) { @@ -5316,10 +6020,10 @@ var ts; } continue; } - if (text.charCodeAt(pos + 1) === 42) { + if (text.charCodeAt(pos + 1) === 42 /* asterisk */) { pos += 2; while (pos < text.length) { - if (text.charCodeAt(pos) === 42 && text.charCodeAt(pos + 1) === 47) { + if (text.charCodeAt(pos) === 42 /* asterisk */ && text.charCodeAt(pos + 1) === 47 /* slash */) { pos += 2; break; } @@ -5328,23 +6032,23 @@ var ts; continue; } break; - case 60: - case 124: - case 61: - case 62: + case 60 /* lessThan */: + case 124 /* bar */: + case 61 /* equals */: + case 62 /* greaterThan */: if (isConflictMarkerTrivia(text, pos)) { pos = scanConflictMarkerTrivia(text, pos); continue; } break; - case 35: + case 35 /* hash */: if (pos === 0 && isShebangTrivia(text, pos)) { pos = scanShebangTrivia(text, pos); continue; } break; default: - if (ch > 127 && (isWhiteSpaceLike(ch))) { + if (ch > 127 /* maxAsciiCharacter */ && (isWhiteSpaceLike(ch))) { pos++; continue; } @@ -5354,9 +6058,12 @@ var ts; } } ts.skipTrivia = skipTrivia; + // All conflict markers consist of the same character repeated seven times. If it is + // a <<<<<<< or >>>>>>> marker then it is also followed by a space. var mergeConflictMarkerLength = "<<<<<<<".length; function isConflictMarkerTrivia(text, pos) { ts.Debug.assert(pos >= 0); + // Conflict markers must be at the start of a line. if (pos === 0 || isLineBreak(text.charCodeAt(pos - 1))) { var ch = text.charCodeAt(pos); if ((pos + mergeConflictMarkerLength) < text.length) { @@ -5365,8 +6072,8 @@ var ts; return false; } } - return ch === 61 || - text.charCodeAt(pos + mergeConflictMarkerLength) === 32; + return ch === 61 /* equals */ || + text.charCodeAt(pos + mergeConflictMarkerLength) === 32 /* space */; } } return false; @@ -5377,16 +6084,18 @@ var ts; } var ch = text.charCodeAt(pos); var len = text.length; - if (ch === 60 || ch === 62) { + if (ch === 60 /* lessThan */ || ch === 62 /* greaterThan */) { while (pos < len && !isLineBreak(text.charCodeAt(pos))) { pos++; } } else { - ts.Debug.assert(ch === 124 || ch === 61); + ts.Debug.assert(ch === 124 /* bar */ || ch === 61 /* equals */); + // Consume everything from the start of a ||||||| or ======= marker to the start + // of the next ======= or >>>>>>> marker. while (pos < len) { var currentChar = text.charCodeAt(pos); - if ((currentChar === 61 || currentChar === 62) && currentChar !== ch && isConflictMarkerTrivia(text, pos)) { + if ((currentChar === 61 /* equals */ || currentChar === 62 /* greaterThan */) && currentChar !== ch && isConflictMarkerTrivia(text, pos)) { break; } pos++; @@ -5396,6 +6105,7 @@ var ts; } var shebangTriviaRegex = /^#!.*/; function isShebangTrivia(text, pos) { + // Shebangs check must only be done at the start of the file ts.Debug.assert(pos === 0); return shebangTriviaRegex.test(text); } @@ -5404,6 +6114,26 @@ var ts; pos = pos + shebang.length; return pos; } + /** + * Invokes a callback for each comment range following the provided position. + * + * Single-line comment ranges include the leading double-slash characters but not the ending + * line break. Multi-line comment ranges include the leading slash-asterisk and trailing + * asterisk-slash characters. + * + * @param reduce If true, accumulates the result of calling the callback in a fashion similar + * to reduceLeft. If false, iteration stops when the callback returns a truthy value. + * @param text The source text to scan. + * @param pos The position at which to start scanning. + * @param trailing If false, whitespace is skipped until the first line break and comments + * between that location and the next token are returned. If true, comments occurring + * between the given position and the next line break are returned. + * @param cb The callback to execute as each comment range is encountered. + * @param state A state value to pass to each iteration of the callback. + * @param initial An initial value to pass when accumulating results (when "reduce" is true). + * @returns If "reduce" is true, the accumulated value. If "reduce" is false, the first truthy + * return value of the callback. + */ function iterateCommentRanges(reduce, text, pos, trailing, cb, state, initial) { var pendingPos; var pendingEnd; @@ -5415,11 +6145,12 @@ var ts; scan: while (pos >= 0 && pos < text.length) { var ch = text.charCodeAt(pos); switch (ch) { - case 13: - if (text.charCodeAt(pos + 1) === 10) { + case 13 /* carriageReturn */: + if (text.charCodeAt(pos + 1) === 10 /* lineFeed */) { pos++; } - case 10: + // falls through + case 10 /* lineFeed */: pos++; if (trailing) { break scan; @@ -5429,20 +6160,20 @@ var ts; pendingHasTrailingNewLine = true; } continue; - case 9: - case 11: - case 12: - case 32: + case 9 /* tab */: + case 11 /* verticalTab */: + case 12 /* formFeed */: + case 32 /* space */: pos++; continue; - case 47: + case 47 /* slash */: var nextChar = text.charCodeAt(pos + 1); var hasTrailingNewLine = false; - if (nextChar === 47 || nextChar === 42) { - var kind = nextChar === 47 ? 2 : 3; + if (nextChar === 47 /* slash */ || nextChar === 42 /* asterisk */) { + var kind = nextChar === 47 /* slash */ ? 2 /* SingleLineCommentTrivia */ : 3 /* MultiLineCommentTrivia */; var startPos = pos; pos += 2; - if (nextChar === 47) { + if (nextChar === 47 /* slash */) { while (pos < text.length) { if (isLineBreak(text.charCodeAt(pos))) { hasTrailingNewLine = true; @@ -5453,7 +6184,7 @@ var ts; } else { while (pos < text.length) { - if (text.charCodeAt(pos) === 42 && text.charCodeAt(pos + 1) === 47) { + if (text.charCodeAt(pos) === 42 /* asterisk */ && text.charCodeAt(pos + 1) === 47 /* slash */) { pos += 2; break; } @@ -5464,6 +6195,7 @@ var ts; if (hasPendingCommentRange) { accumulator = cb(pendingPos, pendingEnd, pendingKind, pendingHasTrailingNewLine, state, accumulator); if (!reduce && accumulator) { + // If we are not reducing and we have a truthy result, return it. return accumulator; } } @@ -5477,7 +6209,7 @@ var ts; } break scan; default: - if (ch > 127 && (isWhiteSpaceLike(ch))) { + if (ch > 127 /* maxAsciiCharacter */ && (isWhiteSpaceLike(ch))) { if (hasPendingCommentRange && isLineBreak(ch)) { pendingHasTrailingNewLine = true; } @@ -5493,19 +6225,19 @@ var ts; return accumulator; } function forEachLeadingCommentRange(text, pos, cb, state) { - return iterateCommentRanges(false, text, pos, false, cb, state); + return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ false, cb, state); } ts.forEachLeadingCommentRange = forEachLeadingCommentRange; function forEachTrailingCommentRange(text, pos, cb, state) { - return iterateCommentRanges(false, text, pos, true, cb, state); + return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ true, cb, state); } ts.forEachTrailingCommentRange = forEachTrailingCommentRange; function reduceEachLeadingCommentRange(text, pos, cb, state, initial) { - return iterateCommentRanges(true, text, pos, false, cb, state, initial); + return iterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ false, cb, state, initial); } ts.reduceEachLeadingCommentRange = reduceEachLeadingCommentRange; function reduceEachTrailingCommentRange(text, pos, cb, state, initial) { - return iterateCommentRanges(true, text, pos, true, cb, state, initial); + return iterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ true, cb, state, initial); } ts.reduceEachTrailingCommentRange = reduceEachTrailingCommentRange; function appendCommentRange(pos, end, kind, hasTrailingNewLine, _state, comments) { @@ -5516,13 +6248,14 @@ var ts; return comments; } function getLeadingCommentRanges(text, pos) { - return reduceEachLeadingCommentRange(text, pos, appendCommentRange, undefined, undefined); + return reduceEachLeadingCommentRange(text, pos, appendCommentRange, /*state*/ undefined, /*initial*/ undefined); } ts.getLeadingCommentRanges = getLeadingCommentRanges; function getTrailingCommentRanges(text, pos) { - return reduceEachTrailingCommentRange(text, pos, appendCommentRange, undefined, undefined); + return reduceEachTrailingCommentRange(text, pos, appendCommentRange, /*state*/ undefined, /*initial*/ undefined); } ts.getTrailingCommentRanges = getTrailingCommentRanges; + /** Optionally, get the shebang */ function getShebang(text) { var match = shebangTriviaRegex.exec(text); if (match) { @@ -5531,17 +6264,18 @@ var ts; } ts.getShebang = getShebang; function isIdentifierStart(ch, languageVersion) { - return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || - ch === 36 || ch === 95 || - ch > 127 && isUnicodeIdentifierStart(ch, languageVersion); + return ch >= 65 /* A */ && ch <= 90 /* Z */ || ch >= 97 /* a */ && ch <= 122 /* z */ || + ch === 36 /* $ */ || ch === 95 /* _ */ || + ch > 127 /* maxAsciiCharacter */ && isUnicodeIdentifierStart(ch, languageVersion); } ts.isIdentifierStart = isIdentifierStart; function isIdentifierPart(ch, languageVersion) { - return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || - ch >= 48 && ch <= 57 || ch === 36 || ch === 95 || - ch > 127 && isUnicodeIdentifierPart(ch, languageVersion); + return ch >= 65 /* A */ && ch <= 90 /* Z */ || ch >= 97 /* a */ && ch <= 122 /* z */ || + ch >= 48 /* _0 */ && ch <= 57 /* _9 */ || ch === 36 /* $ */ || ch === 95 /* _ */ || + ch > 127 /* maxAsciiCharacter */ && isUnicodeIdentifierPart(ch, languageVersion); } ts.isIdentifierPart = isIdentifierPart; + /* @internal */ function isIdentifierText(name, languageVersion) { if (!isIdentifierStart(name.charCodeAt(0), languageVersion)) { return false; @@ -5554,12 +6288,17 @@ var ts; return true; } ts.isIdentifierText = isIdentifierText; + // Creates a scanner over a (possibly unspecified) range of a piece of text. function createScanner(languageVersion, skipTrivia, languageVariant, textInitial, onError, start, length) { - if (languageVariant === void 0) { languageVariant = 0; } + if (languageVariant === void 0) { languageVariant = 0 /* Standard */; } var text = textInitial; + // Current position (end position of text of current token) var pos; + // end of text var end; + // Start position of whitespace before current token var startPos; + // Start position of text of current token var tokenPos; var token; var tokenValue; @@ -5572,11 +6311,11 @@ var ts; getTokenPos: function () { return tokenPos; }, getTokenText: function () { return text.substring(tokenPos, pos); }, getTokenValue: function () { return tokenValue; }, - hasExtendedUnicodeEscape: function () { return (tokenFlags & 8) !== 0; }, - hasPrecedingLineBreak: function () { return (tokenFlags & 1) !== 0; }, - isIdentifier: function () { return token === 71 || token > 107; }, - isReservedWord: function () { return token >= 72 && token <= 107; }, - isUnterminated: function () { return (tokenFlags & 4) !== 0; }, + hasExtendedUnicodeEscape: function () { return (tokenFlags & 8 /* ExtendedUnicodeEscape */) !== 0; }, + hasPrecedingLineBreak: function () { return (tokenFlags & 1 /* PrecedingLineBreak */) !== 0; }, + isIdentifier: function () { return token === 71 /* Identifier */ || token > 107 /* LastReservedWord */; }, + isReservedWord: function () { return token >= 72 /* FirstReservedWord */ && token <= 107 /* LastReservedWord */; }, + isUnterminated: function () { return (tokenFlags & 4 /* Unterminated */) !== 0; }, getTokenFlags: function () { return tokenFlags; }, reScanGreaterToken: reScanGreaterToken, reScanSlashToken: reScanSlashToken, @@ -5613,8 +6352,8 @@ var ts; var result = ""; while (true) { var ch = text.charCodeAt(pos); - if (ch === 95) { - tokenFlags |= 512; + if (ch === 95 /* _ */) { + tokenFlags |= 512 /* ContainsSeparator */; if (allowSeparator) { allowSeparator = false; isPreviousTokenSeparator = true; @@ -5638,7 +6377,7 @@ var ts; } break; } - if (text.charCodeAt(pos - 1) === 95) { + if (text.charCodeAt(pos - 1) === 95 /* _ */) { error(ts.Diagnostics.Numeric_separators_are_not_allowed_here, pos - 1, 1); } return result + text.substring(start, pos); @@ -5648,15 +6387,15 @@ var ts; var mainFragment = scanNumberFragment(); var decimalFragment; var scientificFragment; - if (text.charCodeAt(pos) === 46) { + if (text.charCodeAt(pos) === 46 /* dot */) { pos++; decimalFragment = scanNumberFragment(); } var end = pos; - if (text.charCodeAt(pos) === 69 || text.charCodeAt(pos) === 101) { + if (text.charCodeAt(pos) === 69 /* E */ || text.charCodeAt(pos) === 101 /* e */) { pos++; - tokenFlags |= 16; - if (text.charCodeAt(pos) === 43 || text.charCodeAt(pos) === 45) + tokenFlags |= 16 /* Scientific */; + if (text.charCodeAt(pos) === 43 /* plus */ || text.charCodeAt(pos) === 45 /* minus */) pos++; var preNumericPart = pos; var finalFragment = scanNumberFragment(); @@ -5668,7 +6407,7 @@ var ts; end = pos; } } - if (tokenFlags & 512) { + if (tokenFlags & 512 /* ContainsSeparator */) { var result = mainFragment; if (decimalFragment) { result += "." + decimalFragment; @@ -5679,7 +6418,7 @@ var ts; return "" + +result; } else { - return "" + +(text.substring(start, end)); + return "" + +(text.substring(start, end)); // No need to use all the fragments; no _ removal needed } } function scanOctalDigits() { @@ -5689,11 +6428,19 @@ var ts; } return +(text.substring(start, pos)); } + /** + * Scans the given number of hexadecimal digits in the text, + * returning -1 if the given number is unavailable. + */ function scanExactNumberOfHexDigits(count, canHaveSeparators) { - return scanHexDigits(count, false, canHaveSeparators); + return scanHexDigits(/*minCount*/ count, /*scanAsManyAsPossible*/ false, canHaveSeparators); } + /** + * Scans as many hexadecimal digits as are available in the text, + * returning -1 if the given number of digits was unavailable. + */ function scanMinimumNumberOfHexDigits(count, canHaveSeparators) { - return scanHexDigits(count, true, canHaveSeparators); + return scanHexDigits(/*minCount*/ count, /*scanAsManyAsPossible*/ true, canHaveSeparators); } function scanHexDigits(minCount, scanAsManyAsPossible, canHaveSeparators) { var digits = 0; @@ -5702,8 +6449,8 @@ var ts; var isPreviousTokenSeparator = false; while (digits < minCount || scanAsManyAsPossible) { var ch = text.charCodeAt(pos); - if (canHaveSeparators && ch === 95) { - tokenFlags |= 512; + if (canHaveSeparators && ch === 95 /* _ */) { + tokenFlags |= 512 /* ContainsSeparator */; if (allowSeparator) { allowSeparator = false; isPreviousTokenSeparator = true; @@ -5718,14 +6465,14 @@ var ts; continue; } allowSeparator = canHaveSeparators; - if (ch >= 48 && ch <= 57) { - value = value * 16 + ch - 48; + if (ch >= 48 /* _0 */ && ch <= 57 /* _9 */) { + value = value * 16 + ch - 48 /* _0 */; } - else if (ch >= 65 && ch <= 70) { - value = value * 16 + ch - 65 + 10; + else if (ch >= 65 /* A */ && ch <= 70 /* F */) { + value = value * 16 + ch - 65 /* A */ + 10; } - else if (ch >= 97 && ch <= 102) { - value = value * 16 + ch - 97 + 10; + else if (ch >= 97 /* a */ && ch <= 102 /* f */) { + value = value * 16 + ch - 97 /* a */ + 10; } else { break; @@ -5737,7 +6484,7 @@ var ts; if (digits < minCount) { value = -1; } - if (text.charCodeAt(pos - 1) === 95) { + if (text.charCodeAt(pos - 1) === 95 /* _ */) { error(ts.Diagnostics.Numeric_separators_are_not_allowed_here, pos - 1, 1); } return value; @@ -5751,7 +6498,7 @@ var ts; while (true) { if (pos >= end) { result += text.substring(start, pos); - tokenFlags |= 4; + tokenFlags |= 4 /* Unterminated */; error(ts.Diagnostics.Unterminated_string_literal); break; } @@ -5761,7 +6508,7 @@ var ts; pos++; break; } - if (ch === 92 && !jsxAttributeString) { + if (ch === 92 /* backslash */ && !jsxAttributeString) { result += text.substring(start, pos); result += scanEscapeSequence(); start = pos; @@ -5769,7 +6516,7 @@ var ts; } if (isLineBreak(ch) && !jsxAttributeString) { result += text.substring(start, pos); - tokenFlags |= 4; + tokenFlags |= 4 /* Unterminated */; error(ts.Diagnostics.Unterminated_string_literal); break; } @@ -5777,8 +6524,12 @@ var ts; } return result; } + /** + * Sets the current 'tokenValue' and returns a NoSubstitutionTemplateLiteral or + * a literal component of a TemplateExpression. + */ function scanTemplateAndSetTokenValue() { - var startedWithBacktick = text.charCodeAt(pos) === 96; + var startedWithBacktick = text.charCodeAt(pos) === 96 /* backtick */; pos++; var start = pos; var contents = ""; @@ -5786,34 +6537,39 @@ var ts; while (true) { if (pos >= end) { contents += text.substring(start, pos); - tokenFlags |= 4; + tokenFlags |= 4 /* Unterminated */; error(ts.Diagnostics.Unterminated_template_literal); - resultingToken = startedWithBacktick ? 13 : 16; + resultingToken = startedWithBacktick ? 13 /* NoSubstitutionTemplateLiteral */ : 16 /* TemplateTail */; break; } var currChar = text.charCodeAt(pos); - if (currChar === 96) { + // '`' + if (currChar === 96 /* backtick */) { contents += text.substring(start, pos); pos++; - resultingToken = startedWithBacktick ? 13 : 16; + resultingToken = startedWithBacktick ? 13 /* NoSubstitutionTemplateLiteral */ : 16 /* TemplateTail */; break; } - if (currChar === 36 && pos + 1 < end && text.charCodeAt(pos + 1) === 123) { + // '${' + if (currChar === 36 /* $ */ && pos + 1 < end && text.charCodeAt(pos + 1) === 123 /* openBrace */) { contents += text.substring(start, pos); pos += 2; - resultingToken = startedWithBacktick ? 14 : 15; + resultingToken = startedWithBacktick ? 14 /* TemplateHead */ : 15 /* TemplateMiddle */; break; } - if (currChar === 92) { + // Escape character + if (currChar === 92 /* backslash */) { contents += text.substring(start, pos); contents += scanEscapeSequence(); start = pos; continue; } - if (currChar === 13) { + // Speculated ECMAScript 6 Spec 11.8.6.1: + // and LineTerminatorSequences are normalized to for Template Values + if (currChar === 13 /* carriageReturn */) { contents += text.substring(start, pos); pos++; - if (pos < end && text.charCodeAt(pos) === 10) { + if (pos < end && text.charCodeAt(pos) === 10 /* lineFeed */) { pos++; } contents += "\n"; @@ -5835,47 +6591,53 @@ var ts; var ch = text.charCodeAt(pos); pos++; switch (ch) { - case 48: + case 48 /* _0 */: return "\0"; - case 98: + case 98 /* b */: return "\b"; - case 116: + case 116 /* t */: return "\t"; - case 110: + case 110 /* n */: return "\n"; - case 118: + case 118 /* v */: return "\v"; - case 102: + case 102 /* f */: return "\f"; - case 114: + case 114 /* r */: return "\r"; - case 39: + case 39 /* singleQuote */: return "\'"; - case 34: + case 34 /* doubleQuote */: return "\""; - case 117: - if (pos < end && text.charCodeAt(pos) === 123) { - tokenFlags |= 8; + case 117 /* u */: + // '\u{DDDDDDDD}' + if (pos < end && text.charCodeAt(pos) === 123 /* openBrace */) { + tokenFlags |= 8 /* ExtendedUnicodeEscape */; pos++; return scanExtendedUnicodeEscape(); } - return scanHexadecimalEscape(4); - case 120: - return scanHexadecimalEscape(2); - case 13: - if (pos < end && text.charCodeAt(pos) === 10) { + // '\uDDDD' + return scanHexadecimalEscape(/*numDigits*/ 4); + case 120 /* x */: + // '\xDD' + return scanHexadecimalEscape(/*numDigits*/ 2); + // when encountering a LineContinuation (i.e. a backslash and a line terminator sequence), + // the line terminator is interpreted to be "the empty code unit sequence". + case 13 /* carriageReturn */: + if (pos < end && text.charCodeAt(pos) === 10 /* lineFeed */) { pos++; } - case 10: - case 8232: - case 8233: + // falls through + case 10 /* lineFeed */: + case 8232 /* lineSeparator */: + case 8233 /* paragraphSeparator */: return ""; default: return String.fromCharCode(ch); } } function scanHexadecimalEscape(numDigits) { - var escapedValue = scanExactNumberOfHexDigits(numDigits, false); + var escapedValue = scanExactNumberOfHexDigits(numDigits, /*canHaveSeparators*/ false); if (escapedValue >= 0) { return String.fromCharCode(escapedValue); } @@ -5885,8 +6647,9 @@ var ts; } } function scanExtendedUnicodeEscape() { - var escapedValue = scanMinimumNumberOfHexDigits(1, false); + var escapedValue = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ false); var isInvalidExtendedEscape = false; + // Validate the value of the digit if (escapedValue < 0) { error(ts.Diagnostics.Hexadecimal_digit_expected); isInvalidExtendedEscape = true; @@ -5899,7 +6662,8 @@ var ts; error(ts.Diagnostics.Unexpected_end_of_text); isInvalidExtendedEscape = true; } - else if (text.charCodeAt(pos) === 125) { + else if (text.charCodeAt(pos) === 125 /* closeBrace */) { + // Only swallow the following character up if it's a '}'. pos++; } else { @@ -5911,6 +6675,7 @@ var ts; } return utf16EncodeAsString(escapedValue); } + // Derived from the 10.1.1 UTF16Encoding of the ES6 Spec. function utf16EncodeAsString(codePoint) { ts.Debug.assert(0x0 <= codePoint && codePoint <= 0x10FFFF); if (codePoint <= 65535) { @@ -5920,11 +6685,13 @@ var ts; var codeUnit2 = ((codePoint - 65536) % 1024) + 0xDC00; return String.fromCharCode(codeUnit1, codeUnit2); } + // Current character is known to be a backslash. Check for Unicode escape of the form '\uXXXX' + // and return code point value if valid Unicode escape is found. Otherwise return -1. function peekUnicodeEscape() { - if (pos + 5 < end && text.charCodeAt(pos + 1) === 117) { + if (pos + 5 < end && text.charCodeAt(pos + 1) === 117 /* u */) { var start_1 = pos; pos += 2; - var value = scanExactNumberOfHexDigits(4, false); + var value = scanExactNumberOfHexDigits(4, /*canHaveSeparators*/ false); pos = start_1; return value; } @@ -5938,13 +6705,14 @@ var ts; if (isIdentifierPart(ch, languageVersion)) { pos++; } - else if (ch === 92) { + else if (ch === 92 /* backslash */) { ch = peekUnicodeEscape(); if (!(ch >= 0 && isIdentifierPart(ch, languageVersion))) { break; } result += text.substring(start, pos); result += String.fromCharCode(ch); + // Valid Unicode escape is always six characters pos += 6; start = pos; } @@ -5956,28 +6724,32 @@ var ts; return result; } function getIdentifierToken() { + // Reserved words are between 2 and 11 characters long and start with a lowercase letter var len = tokenValue.length; if (len >= 2 && len <= 11) { var ch = tokenValue.charCodeAt(0); - if (ch >= 97 && ch <= 122) { + if (ch >= 97 /* a */ && ch <= 122 /* z */) { token = textToToken.get(tokenValue); if (token !== undefined) { return token; } } } - return token = 71; + return token = 71 /* Identifier */; } function scanBinaryOrOctalDigits(base) { ts.Debug.assert(base === 2 || base === 8, "Expected either base 2 or base 8"); var value = 0; + // For counting number of digits; Valid binaryIntegerLiteral must have at least one binary digit following B or b. + // Similarly valid octalIntegerLiteral must have at least one octal digit following o or O. var numberOfDigits = 0; var separatorAllowed = false; var isPreviousTokenSeparator = false; while (true) { var ch = text.charCodeAt(pos); - if (ch === 95) { - tokenFlags |= 512; + // Numeric separators are allowed anywhere within a numeric literal, except not at the beginning, or following another separator + if (ch === 95 /* _ */) { + tokenFlags |= 512 /* ContainsSeparator */; if (separatorAllowed) { separatorAllowed = false; isPreviousTokenSeparator = true; @@ -5992,7 +6764,7 @@ var ts; continue; } separatorAllowed = true; - var valueOfCh = ch - 48; + var valueOfCh = ch - 48 /* _0 */; if (!isDigit(ch) || valueOfCh >= base) { break; } @@ -6001,10 +6773,12 @@ var ts; numberOfDigits++; isPreviousTokenSeparator = false; } + // Invalid binaryIntegerLiteral or octalIntegerLiteral if (numberOfDigits === 0) { return -1; } - if (text.charCodeAt(pos - 1) === 95) { + if (text.charCodeAt(pos - 1) === 95 /* _ */) { + // Literal ends with underscore - not allowed error(ts.Diagnostics.Numeric_separators_are_not_allowed_here, pos - 1, 1); return value; } @@ -6016,39 +6790,41 @@ var ts; while (true) { tokenPos = pos; if (pos >= end) { - return token = 1; + return token = 1 /* EndOfFileToken */; } var ch = text.charCodeAt(pos); - if (ch === 35 && pos === 0 && isShebangTrivia(text, pos)) { + // Special handling for shebang + if (ch === 35 /* hash */ && pos === 0 && isShebangTrivia(text, pos)) { pos = scanShebangTrivia(text, pos); if (skipTrivia) { continue; } else { - return token = 6; + return token = 6 /* ShebangTrivia */; } } switch (ch) { - case 10: - case 13: - tokenFlags |= 1; + case 10 /* lineFeed */: + case 13 /* carriageReturn */: + tokenFlags |= 1 /* PrecedingLineBreak */; if (skipTrivia) { pos++; continue; } else { - if (ch === 13 && pos + 1 < end && text.charCodeAt(pos + 1) === 10) { + if (ch === 13 /* carriageReturn */ && pos + 1 < end && text.charCodeAt(pos + 1) === 10 /* lineFeed */) { + // consume both CR and LF pos += 2; } else { pos++; } - return token = 4; + return token = 4 /* NewLineTrivia */; } - case 9: - case 11: - case 12: - case 32: + case 9 /* tab */: + case 11 /* verticalTab */: + case 12 /* formFeed */: + case 32 /* space */: if (skipTrivia) { pos++; continue; @@ -6057,89 +6833,90 @@ var ts; while (pos < end && isWhiteSpaceSingleLine(text.charCodeAt(pos))) { pos++; } - return token = 5; + return token = 5 /* WhitespaceTrivia */; } - case 33: - if (text.charCodeAt(pos + 1) === 61) { - if (text.charCodeAt(pos + 2) === 61) { - return pos += 3, token = 35; + case 33 /* exclamation */: + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + if (text.charCodeAt(pos + 2) === 61 /* equals */) { + return pos += 3, token = 35 /* ExclamationEqualsEqualsToken */; } - return pos += 2, token = 33; + return pos += 2, token = 33 /* ExclamationEqualsToken */; } pos++; - return token = 51; - case 34: - case 39: + return token = 51 /* ExclamationToken */; + case 34 /* doubleQuote */: + case 39 /* singleQuote */: tokenValue = scanString(); - return token = 9; - case 96: + return token = 9 /* StringLiteral */; + case 96 /* backtick */: return token = scanTemplateAndSetTokenValue(); - case 37: - if (text.charCodeAt(pos + 1) === 61) { - return pos += 2, token = 64; + case 37 /* percent */: + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + return pos += 2, token = 64 /* PercentEqualsToken */; } pos++; - return token = 42; - case 38: - if (text.charCodeAt(pos + 1) === 38) { - return pos += 2, token = 53; + return token = 42 /* PercentToken */; + case 38 /* ampersand */: + if (text.charCodeAt(pos + 1) === 38 /* ampersand */) { + return pos += 2, token = 53 /* AmpersandAmpersandToken */; } - if (text.charCodeAt(pos + 1) === 61) { - return pos += 2, token = 68; + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + return pos += 2, token = 68 /* AmpersandEqualsToken */; } pos++; - return token = 48; - case 40: + return token = 48 /* AmpersandToken */; + case 40 /* openParen */: pos++; - return token = 19; - case 41: + return token = 19 /* OpenParenToken */; + case 41 /* closeParen */: pos++; - return token = 20; - case 42: - if (text.charCodeAt(pos + 1) === 61) { - return pos += 2, token = 61; + return token = 20 /* CloseParenToken */; + case 42 /* asterisk */: + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + return pos += 2, token = 61 /* AsteriskEqualsToken */; } - if (text.charCodeAt(pos + 1) === 42) { - if (text.charCodeAt(pos + 2) === 61) { - return pos += 3, token = 62; + if (text.charCodeAt(pos + 1) === 42 /* asterisk */) { + if (text.charCodeAt(pos + 2) === 61 /* equals */) { + return pos += 3, token = 62 /* AsteriskAsteriskEqualsToken */; } - return pos += 2, token = 40; + return pos += 2, token = 40 /* AsteriskAsteriskToken */; } pos++; - return token = 39; - case 43: - if (text.charCodeAt(pos + 1) === 43) { - return pos += 2, token = 43; + return token = 39 /* AsteriskToken */; + case 43 /* plus */: + if (text.charCodeAt(pos + 1) === 43 /* plus */) { + return pos += 2, token = 43 /* PlusPlusToken */; } - if (text.charCodeAt(pos + 1) === 61) { - return pos += 2, token = 59; + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + return pos += 2, token = 59 /* PlusEqualsToken */; } pos++; - return token = 37; - case 44: + return token = 37 /* PlusToken */; + case 44 /* comma */: pos++; - return token = 26; - case 45: - if (text.charCodeAt(pos + 1) === 45) { - return pos += 2, token = 44; + return token = 26 /* CommaToken */; + case 45 /* minus */: + if (text.charCodeAt(pos + 1) === 45 /* minus */) { + return pos += 2, token = 44 /* MinusMinusToken */; } - if (text.charCodeAt(pos + 1) === 61) { - return pos += 2, token = 60; + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + return pos += 2, token = 60 /* MinusEqualsToken */; } pos++; - return token = 38; - case 46: + return token = 38 /* MinusToken */; + case 46 /* dot */: if (isDigit(text.charCodeAt(pos + 1))) { tokenValue = scanNumber(); - return token = 8; + return token = 8 /* NumericLiteral */; } - if (text.charCodeAt(pos + 1) === 46 && text.charCodeAt(pos + 2) === 46) { - return pos += 3, token = 24; + if (text.charCodeAt(pos + 1) === 46 /* dot */ && text.charCodeAt(pos + 2) === 46 /* dot */) { + return pos += 3, token = 24 /* DotDotDotToken */; } pos++; - return token = 23; - case 47: - if (text.charCodeAt(pos + 1) === 47) { + return token = 23 /* DotToken */; + case 47 /* slash */: + // Single-line comment + if (text.charCodeAt(pos + 1) === 47 /* slash */) { pos += 2; while (pos < end) { if (isLineBreak(text.charCodeAt(pos))) { @@ -6151,24 +6928,25 @@ var ts; continue; } else { - return token = 2; + return token = 2 /* SingleLineCommentTrivia */; } } - if (text.charCodeAt(pos + 1) === 42) { + // Multi-line comment + if (text.charCodeAt(pos + 1) === 42 /* asterisk */) { pos += 2; - if (text.charCodeAt(pos) === 42 && text.charCodeAt(pos + 1) !== 47) { - tokenFlags |= 2; + if (text.charCodeAt(pos) === 42 /* asterisk */ && text.charCodeAt(pos + 1) !== 47 /* slash */) { + tokenFlags |= 2 /* PrecedingJSDocComment */; } var commentClosed = false; while (pos < end) { var ch_1 = text.charCodeAt(pos); - if (ch_1 === 42 && text.charCodeAt(pos + 1) === 47) { + if (ch_1 === 42 /* asterisk */ && text.charCodeAt(pos + 1) === 47 /* slash */) { pos += 2; commentClosed = true; break; } if (isLineBreak(ch_1)) { - tokenFlags |= 1; + tokenFlags |= 1 /* PrecedingLineBreak */; } pos++; } @@ -6180,177 +6958,182 @@ var ts; } else { if (!commentClosed) { - tokenFlags |= 4; + tokenFlags |= 4 /* Unterminated */; } - return token = 3; + return token = 3 /* MultiLineCommentTrivia */; } } - if (text.charCodeAt(pos + 1) === 61) { - return pos += 2, token = 63; + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + return pos += 2, token = 63 /* SlashEqualsToken */; } pos++; - return token = 41; - case 48: - if (pos + 2 < end && (text.charCodeAt(pos + 1) === 88 || text.charCodeAt(pos + 1) === 120)) { + return token = 41 /* SlashToken */; + case 48 /* _0 */: + if (pos + 2 < end && (text.charCodeAt(pos + 1) === 88 /* X */ || text.charCodeAt(pos + 1) === 120 /* x */)) { pos += 2; - var value = scanMinimumNumberOfHexDigits(1, true); + var value = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ true); if (value < 0) { error(ts.Diagnostics.Hexadecimal_digit_expected); value = 0; } tokenValue = "" + value; - tokenFlags |= 64; - return token = 8; + tokenFlags |= 64 /* HexSpecifier */; + return token = 8 /* NumericLiteral */; } - else if (pos + 2 < end && (text.charCodeAt(pos + 1) === 66 || text.charCodeAt(pos + 1) === 98)) { + else if (pos + 2 < end && (text.charCodeAt(pos + 1) === 66 /* B */ || text.charCodeAt(pos + 1) === 98 /* b */)) { pos += 2; - var value = scanBinaryOrOctalDigits(2); + var value = scanBinaryOrOctalDigits(/* base */ 2); if (value < 0) { error(ts.Diagnostics.Binary_digit_expected); value = 0; } tokenValue = "" + value; - tokenFlags |= 128; - return token = 8; + tokenFlags |= 128 /* BinarySpecifier */; + return token = 8 /* NumericLiteral */; } - else if (pos + 2 < end && (text.charCodeAt(pos + 1) === 79 || text.charCodeAt(pos + 1) === 111)) { + else if (pos + 2 < end && (text.charCodeAt(pos + 1) === 79 /* O */ || text.charCodeAt(pos + 1) === 111 /* o */)) { pos += 2; - var value = scanBinaryOrOctalDigits(8); + var value = scanBinaryOrOctalDigits(/* base */ 8); if (value < 0) { error(ts.Diagnostics.Octal_digit_expected); value = 0; } tokenValue = "" + value; - tokenFlags |= 256; - return token = 8; + tokenFlags |= 256 /* OctalSpecifier */; + return token = 8 /* NumericLiteral */; } + // Try to parse as an octal if (pos + 1 < end && isOctalDigit(text.charCodeAt(pos + 1))) { tokenValue = "" + scanOctalDigits(); - tokenFlags |= 32; - return token = 8; + tokenFlags |= 32 /* Octal */; + return token = 8 /* NumericLiteral */; } - case 49: - case 50: - case 51: - case 52: - case 53: - case 54: - case 55: - case 56: - case 57: + // This fall-through is a deviation from the EcmaScript grammar. The grammar says that a leading zero + // can only be followed by an octal digit, a dot, or the end of the number literal. However, we are being + // permissive and allowing decimal digits of the form 08* and 09* (which many browsers also do). + // falls through + case 49 /* _1 */: + case 50 /* _2 */: + case 51 /* _3 */: + case 52 /* _4 */: + case 53 /* _5 */: + case 54 /* _6 */: + case 55 /* _7 */: + case 56 /* _8 */: + case 57 /* _9 */: tokenValue = scanNumber(); - return token = 8; - case 58: + return token = 8 /* NumericLiteral */; + case 58 /* colon */: pos++; - return token = 56; - case 59: + return token = 56 /* ColonToken */; + case 59 /* semicolon */: pos++; - return token = 25; - case 60: + return token = 25 /* SemicolonToken */; + case 60 /* lessThan */: if (isConflictMarkerTrivia(text, pos)) { pos = scanConflictMarkerTrivia(text, pos, error); if (skipTrivia) { continue; } else { - return token = 7; + return token = 7 /* ConflictMarkerTrivia */; } } - if (text.charCodeAt(pos + 1) === 60) { - if (text.charCodeAt(pos + 2) === 61) { - return pos += 3, token = 65; + if (text.charCodeAt(pos + 1) === 60 /* lessThan */) { + if (text.charCodeAt(pos + 2) === 61 /* equals */) { + return pos += 3, token = 65 /* LessThanLessThanEqualsToken */; } - return pos += 2, token = 45; + return pos += 2, token = 45 /* LessThanLessThanToken */; } - if (text.charCodeAt(pos + 1) === 61) { - return pos += 2, token = 30; + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + return pos += 2, token = 30 /* LessThanEqualsToken */; } - if (languageVariant === 1 && - text.charCodeAt(pos + 1) === 47 && - text.charCodeAt(pos + 2) !== 42) { - return pos += 2, token = 28; + if (languageVariant === 1 /* JSX */ && + text.charCodeAt(pos + 1) === 47 /* slash */ && + text.charCodeAt(pos + 2) !== 42 /* asterisk */) { + return pos += 2, token = 28 /* LessThanSlashToken */; } pos++; - return token = 27; - case 61: + return token = 27 /* LessThanToken */; + case 61 /* equals */: if (isConflictMarkerTrivia(text, pos)) { pos = scanConflictMarkerTrivia(text, pos, error); if (skipTrivia) { continue; } else { - return token = 7; + return token = 7 /* ConflictMarkerTrivia */; } } - if (text.charCodeAt(pos + 1) === 61) { - if (text.charCodeAt(pos + 2) === 61) { - return pos += 3, token = 34; + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + if (text.charCodeAt(pos + 2) === 61 /* equals */) { + return pos += 3, token = 34 /* EqualsEqualsEqualsToken */; } - return pos += 2, token = 32; + return pos += 2, token = 32 /* EqualsEqualsToken */; } - if (text.charCodeAt(pos + 1) === 62) { - return pos += 2, token = 36; + if (text.charCodeAt(pos + 1) === 62 /* greaterThan */) { + return pos += 2, token = 36 /* EqualsGreaterThanToken */; } pos++; - return token = 58; - case 62: + return token = 58 /* EqualsToken */; + case 62 /* greaterThan */: if (isConflictMarkerTrivia(text, pos)) { pos = scanConflictMarkerTrivia(text, pos, error); if (skipTrivia) { continue; } else { - return token = 7; + return token = 7 /* ConflictMarkerTrivia */; } } pos++; - return token = 29; - case 63: + return token = 29 /* GreaterThanToken */; + case 63 /* question */: pos++; - return token = 55; - case 91: + return token = 55 /* QuestionToken */; + case 91 /* openBracket */: pos++; - return token = 21; - case 93: + return token = 21 /* OpenBracketToken */; + case 93 /* closeBracket */: pos++; - return token = 22; - case 94: - if (text.charCodeAt(pos + 1) === 61) { - return pos += 2, token = 70; + return token = 22 /* CloseBracketToken */; + case 94 /* caret */: + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + return pos += 2, token = 70 /* CaretEqualsToken */; } pos++; - return token = 50; - case 123: + return token = 50 /* CaretToken */; + case 123 /* openBrace */: pos++; - return token = 17; - case 124: + return token = 17 /* OpenBraceToken */; + case 124 /* bar */: if (isConflictMarkerTrivia(text, pos)) { pos = scanConflictMarkerTrivia(text, pos, error); if (skipTrivia) { continue; } else { - return token = 7; + return token = 7 /* ConflictMarkerTrivia */; } } - if (text.charCodeAt(pos + 1) === 124) { - return pos += 2, token = 54; + if (text.charCodeAt(pos + 1) === 124 /* bar */) { + return pos += 2, token = 54 /* BarBarToken */; } - if (text.charCodeAt(pos + 1) === 61) { - return pos += 2, token = 69; + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + return pos += 2, token = 69 /* BarEqualsToken */; } pos++; - return token = 49; - case 125: + return token = 49 /* BarToken */; + case 125 /* closeBrace */: pos++; - return token = 18; - case 126: + return token = 18 /* CloseBraceToken */; + case 126 /* tilde */: pos++; - return token = 52; - case 64: + return token = 52 /* TildeToken */; + case 64 /* at */: pos++; - return token = 57; - case 92: + return token = 57 /* AtToken */; + case 92 /* backslash */: var cookedChar = peekUnicodeEscape(); if (cookedChar >= 0 && isIdentifierStart(cookedChar, languageVersion)) { pos += 6; @@ -6359,14 +7142,14 @@ var ts; } error(ts.Diagnostics.Invalid_character); pos++; - return token = 0; + return token = 0 /* Unknown */; default: if (isIdentifierStart(ch, languageVersion)) { pos++; while (pos < end && isIdentifierPart(ch = text.charCodeAt(pos), languageVersion)) pos++; tokenValue = text.substring(tokenPos, pos); - if (ch === 92) { + if (ch === 92 /* backslash */) { tokenValue += scanIdentifierParts(); } return token = getIdentifierToken(); @@ -6376,69 +7159,75 @@ var ts; continue; } else if (isLineBreak(ch)) { - tokenFlags |= 1; + tokenFlags |= 1 /* PrecedingLineBreak */; pos++; continue; } error(ts.Diagnostics.Invalid_character); pos++; - return token = 0; + return token = 0 /* Unknown */; } } } function reScanGreaterToken() { - if (token === 29) { - if (text.charCodeAt(pos) === 62) { - if (text.charCodeAt(pos + 1) === 62) { - if (text.charCodeAt(pos + 2) === 61) { - return pos += 3, token = 67; + if (token === 29 /* GreaterThanToken */) { + if (text.charCodeAt(pos) === 62 /* greaterThan */) { + if (text.charCodeAt(pos + 1) === 62 /* greaterThan */) { + if (text.charCodeAt(pos + 2) === 61 /* equals */) { + return pos += 3, token = 67 /* GreaterThanGreaterThanGreaterThanEqualsToken */; } - return pos += 2, token = 47; + return pos += 2, token = 47 /* GreaterThanGreaterThanGreaterThanToken */; } - if (text.charCodeAt(pos + 1) === 61) { - return pos += 2, token = 66; + if (text.charCodeAt(pos + 1) === 61 /* equals */) { + return pos += 2, token = 66 /* GreaterThanGreaterThanEqualsToken */; } pos++; - return token = 46; + return token = 46 /* GreaterThanGreaterThanToken */; } - if (text.charCodeAt(pos) === 61) { + if (text.charCodeAt(pos) === 61 /* equals */) { pos++; - return token = 31; + return token = 31 /* GreaterThanEqualsToken */; } } return token; } function reScanSlashToken() { - if (token === 41 || token === 63) { + if (token === 41 /* SlashToken */ || token === 63 /* SlashEqualsToken */) { var p = tokenPos + 1; var inEscape = false; var inCharacterClass = false; while (true) { + // If we reach the end of a file, or hit a newline, then this is an unterminated + // regex. Report error and return what we have so far. if (p >= end) { - tokenFlags |= 4; + tokenFlags |= 4 /* Unterminated */; error(ts.Diagnostics.Unterminated_regular_expression_literal); break; } var ch = text.charCodeAt(p); if (isLineBreak(ch)) { - tokenFlags |= 4; + tokenFlags |= 4 /* Unterminated */; error(ts.Diagnostics.Unterminated_regular_expression_literal); break; } if (inEscape) { + // Parsing an escape character; + // reset the flag and just advance to the next char. inEscape = false; } - else if (ch === 47 && !inCharacterClass) { + else if (ch === 47 /* slash */ && !inCharacterClass) { + // A slash within a character class is permissible, + // but in general it signals the end of the regexp literal. p++; break; } - else if (ch === 91) { + else if (ch === 91 /* openBracket */) { inCharacterClass = true; } - else if (ch === 92) { + else if (ch === 92 /* backslash */) { inEscape = true; } - else if (ch === 93) { + else if (ch === 93 /* closeBracket */) { inCharacterClass = false; } p++; @@ -6448,12 +7237,15 @@ var ts; } pos = p; tokenValue = text.substring(tokenPos, pos); - token = 12; + token = 12 /* RegularExpressionLiteral */; } return token; } + /** + * Unconditionally back up and scan a template expression portion. + */ function reScanTemplateToken() { - ts.Debug.assert(token === 18, "'reScanTemplateToken' should only be called on a '}'"); + ts.Debug.assert(token === 18 /* CloseBraceToken */, "'reScanTemplateToken' should only be called on a '}'"); pos = tokenPos; return token = scanTemplateAndSetTokenValue(); } @@ -6464,34 +7256,43 @@ var ts; function scanJsxToken() { startPos = tokenPos = pos; if (pos >= end) { - return token = 1; + return token = 1 /* EndOfFileToken */; } var char = text.charCodeAt(pos); - if (char === 60) { - if (text.charCodeAt(pos + 1) === 47) { + if (char === 60 /* lessThan */) { + if (text.charCodeAt(pos + 1) === 47 /* slash */) { pos += 2; - return token = 28; + return token = 28 /* LessThanSlashToken */; } pos++; - return token = 27; + return token = 27 /* LessThanToken */; } - if (char === 123) { + if (char === 123 /* openBrace */) { pos++; - return token = 17; + return token = 17 /* OpenBraceToken */; } + // First non-whitespace character on this line. var firstNonWhitespace = 0; + // These initial values are special because the first line is: + // firstNonWhitespace = 0 to indicate that we want leading whitspace, while (pos < end) { char = text.charCodeAt(pos); - if (char === 123) { + if (char === 123 /* openBrace */) { break; } - if (char === 60) { + if (char === 60 /* lessThan */) { if (isConflictMarkerTrivia(text, pos)) { pos = scanConflictMarkerTrivia(text, pos, error); - return token = 7; + return token = 7 /* ConflictMarkerTrivia */; } break; } + // FirstNonWhitespace is 0, then we only see whitespaces so far. If we see a linebreak, we want to ignore that whitespaces. + // i.e (- : whitespace) + //
---- + //
becomes
+ // + //
----
becomes
----
if (isLineBreak(char) && firstNonWhitespace === 0) { firstNonWhitespace = -1; } @@ -6500,14 +7301,16 @@ var ts; } pos++; } - return firstNonWhitespace === -1 ? 11 : 10; + return firstNonWhitespace === -1 ? 11 /* JsxTextAllWhiteSpaces */ : 10 /* JsxText */; } + // Scans a JSX identifier; these differ from normal identifiers in that + // they allow dashes function scanJsxIdentifier() { if (tokenIsIdentifierOrKeyword(token)) { var firstCharPosition = pos; while (pos < end) { var ch = text.charCodeAt(pos); - if (ch === 45 || ((firstCharPosition === pos) ? isIdentifierStart(ch, languageVersion) : isIdentifierPart(ch, languageVersion))) { + if (ch === 45 /* minus */ || ((firstCharPosition === pos) ? isIdentifierStart(ch, languageVersion) : isIdentifierPart(ch, languageVersion))) { pos++; } else { @@ -6521,70 +7324,71 @@ var ts; function scanJsxAttributeValue() { startPos = pos; switch (text.charCodeAt(pos)) { - case 34: - case 39: - tokenValue = scanString(true); - return token = 9; + case 34 /* doubleQuote */: + case 39 /* singleQuote */: + tokenValue = scanString(/*jsxAttributeString*/ true); + return token = 9 /* StringLiteral */; default: + // If this scans anything other than `{`, it's a parse error. return scan(); } } function scanJSDocToken() { startPos = tokenPos = pos; if (pos >= end) { - return token = 1; + return token = 1 /* EndOfFileToken */; } var ch = text.charCodeAt(pos); pos++; switch (ch) { - case 9: - case 11: - case 12: - case 32: + case 9 /* tab */: + case 11 /* verticalTab */: + case 12 /* formFeed */: + case 32 /* space */: while (pos < end && isWhiteSpaceSingleLine(text.charCodeAt(pos))) { pos++; } - return token = 5; - case 64: - return token = 57; - case 10: - case 13: - return token = 4; - case 42: - return token = 39; - case 123: - return token = 17; - case 125: - return token = 18; - case 91: - return token = 21; - case 93: - return token = 22; - case 60: - return token = 27; - case 61: - return token = 58; - case 44: - return token = 26; - case 46: - return token = 23; - case 96: - while (pos < end && text.charCodeAt(pos) !== 96) { + return token = 5 /* WhitespaceTrivia */; + case 64 /* at */: + return token = 57 /* AtToken */; + case 10 /* lineFeed */: + case 13 /* carriageReturn */: + return token = 4 /* NewLineTrivia */; + case 42 /* asterisk */: + return token = 39 /* AsteriskToken */; + case 123 /* openBrace */: + return token = 17 /* OpenBraceToken */; + case 125 /* closeBrace */: + return token = 18 /* CloseBraceToken */; + case 91 /* openBracket */: + return token = 21 /* OpenBracketToken */; + case 93 /* closeBracket */: + return token = 22 /* CloseBracketToken */; + case 60 /* lessThan */: + return token = 27 /* LessThanToken */; + case 61 /* equals */: + return token = 58 /* EqualsToken */; + case 44 /* comma */: + return token = 26 /* CommaToken */; + case 46 /* dot */: + return token = 23 /* DotToken */; + case 96 /* backtick */: + while (pos < end && text.charCodeAt(pos) !== 96 /* backtick */) { pos++; } tokenValue = text.substring(tokenPos + 1, pos); pos++; - return token = 13; + return token = 13 /* NoSubstitutionTemplateLiteral */; } - if (isIdentifierStart(ch, 6)) { - while (isIdentifierPart(text.charCodeAt(pos), 6) && pos < end) { + if (isIdentifierStart(ch, 6 /* Latest */)) { + while (isIdentifierPart(text.charCodeAt(pos), 6 /* Latest */) && pos < end) { pos++; } tokenValue = text.substring(tokenPos, pos); - return token = 71; + return token = 71 /* Identifier */; } else { - return token = 0; + return token = 0 /* Unknown */; } } function speculationHelper(callback, isLookahead) { @@ -6595,6 +7399,8 @@ var ts; var saveTokenValue = tokenValue; var saveTokenFlags = tokenFlags; var result = callback(); + // If our callback returned something 'falsy' or we're just looking ahead, + // then unconditionally restore us to where we were. if (!result || isLookahead) { pos = savePos; startPos = saveStartPos; @@ -6625,10 +7431,10 @@ var ts; return result; } function lookAhead(callback) { - return speculationHelper(callback, true); + return speculationHelper(callback, /*isLookahead*/ true); } function tryScan(callback) { - return speculationHelper(callback, false); + return speculationHelper(callback, /*isLookahead*/ false); } function getText() { return text; @@ -6652,16 +7458,20 @@ var ts; pos = textPos; startPos = textPos; tokenPos = textPos; - token = 0; + token = 0 /* Unknown */; tokenValue = undefined; tokenFlags = 0; } } ts.createScanner = createScanner; })(ts || (ts = {})); +/** Non-internal stuff goes here */ var ts; (function (ts) { function isExternalModuleNameRelative(moduleName) { + // TypeScript 1.0 spec (April 2014): 11.2.1 + // An external module name is "relative" if the first term is "." or "..". + // Update: We also consider a path like `C:\foo.ts` "relative" because we do not search for it in `node_modules` or treat it as an ambient module. return ts.pathIsRelative(moduleName) || ts.isRootedDiskPath(moduleName); } ts.isExternalModuleNameRelative = isExternalModuleNameRelative; @@ -6670,6 +7480,7 @@ var ts; } ts.sortAndDeduplicateDiagnostics = sortAndDeduplicateDiagnostics; })(ts || (ts = {})); +/* @internal */ (function (ts) { ts.emptyArray = []; ts.resolvingEmptyArray = []; @@ -6689,6 +7500,7 @@ var ts; return undefined; } ts.getDeclarationOfKind = getDeclarationOfKind; + /** Create a new escaped identifier map. */ function createUnderscoreEscapedMap() { return new ts.MapCtr(); } @@ -6731,6 +7543,8 @@ var ts; getColumn: function () { return 0; }, getIndent: function () { return 0; }, isAtStartOfLine: function () { return false; }, + // Completely ignore indentation for string writers. And map newlines to + // a single space. writeLine: function () { return str += " "; }, increaseIndent: ts.noop, decreaseIndent: ts.noop, @@ -6892,23 +7706,31 @@ var ts; return false; } ts.hasChangesInResolutions = hasChangesInResolutions; + // Returns true if this node contains a parse error anywhere underneath it. function containsParseError(node) { aggregateChildData(node); - return (node.flags & 131072) !== 0; + return (node.flags & 131072 /* ThisNodeOrAnySubNodesHasError */) !== 0; } ts.containsParseError = containsParseError; function aggregateChildData(node) { - if (!(node.flags & 262144)) { - var thisNodeOrAnySubNodesHasError = ((node.flags & 32768) !== 0) || + if (!(node.flags & 262144 /* HasAggregatedChildData */)) { + // A node is considered to contain a parse error if: + // a) the parser explicitly marked that it had an error + // b) any of it's children reported that it had an error. + var thisNodeOrAnySubNodesHasError = ((node.flags & 32768 /* ThisNodeHasError */) !== 0) || ts.forEachChild(node, containsParseError); + // If so, mark ourselves accordingly. if (thisNodeOrAnySubNodesHasError) { - node.flags |= 131072; + node.flags |= 131072 /* ThisNodeOrAnySubNodesHasError */; } - node.flags |= 262144; + // Also mark that we've propagated the child information to this node. This way we can + // always consult the bit directly on this node without needing to check its children + // again. + node.flags |= 262144 /* HasAggregatedChildData */; } } function getSourceFileOfNode(node) { - while (node && node.kind !== 274) { + while (node && node.kind !== 274 /* SourceFile */) { node = node.parent; } return node; @@ -6916,11 +7738,11 @@ var ts; ts.getSourceFileOfNode = getSourceFileOfNode; function isStatementWithLocals(node) { switch (node.kind) { - case 213: - case 241: - case 220: - case 221: - case 222: + case 213 /* Block */: + case 241 /* CaseBlock */: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: return true; } return false; @@ -6931,6 +7753,7 @@ var ts; return ts.getLineStarts(sourceFile)[line]; } ts.getStartPositionOfLine = getStartPositionOfLine; + // This is a useful function for debugging purposes. function nodePosToString(node) { var file = getSourceFileOfNode(node); var loc = ts.getLineAndCharacterOfPosition(file, node.pos); @@ -6943,12 +7766,19 @@ var ts; var lineIndex = line; var sourceText = sourceFile.text; if (lineIndex + 1 === lineStarts.length) { + // last line - return EOF return sourceText.length - 1; } else { + // current line start var start = lineStarts[lineIndex]; + // take the start position of the next line - 1 = it should be some line break var pos = lineStarts[lineIndex + 1] - 1; ts.Debug.assert(ts.isLineBreak(sourceText.charCodeAt(pos))); + // walk backwards skipping line breaks, stop the the beginning of current line. + // i.e: + // + // $ <- end of line for this position should match the start position while (start <= pos && ts.isLineBreak(sourceText.charCodeAt(pos))) { pos--; } @@ -6956,21 +7786,45 @@ var ts; } } ts.getEndLinePosition = getEndLinePosition; + /** + * Returns a value indicating whether a name is unique globally or within the current file. + * Note: This does not consider whether a name appears as a free identifier or not, so at the expression `x.y` this includes both `x` and `y`. + */ function isFileLevelUniqueName(sourceFile, name, hasGlobalName) { return !(hasGlobalName && hasGlobalName(name)) && !sourceFile.identifiers.has(name); } ts.isFileLevelUniqueName = isFileLevelUniqueName; + // Returns true if this node is missing from the actual source code. A 'missing' node is different + // from 'undefined/defined'. When a node is undefined (which can happen for optional nodes + // in the tree), it is definitely missing. However, a node may be defined, but still be + // missing. This happens whenever the parser knows it needs to parse something, but can't + // get anything in the source code that it expects at that location. For example: + // + // let a: ; + // + // Here, the Type in the Type-Annotation is not-optional (as there is a colon in the source + // code). So the parser will attempt to parse out a type, and will create an actual node. + // However, this node will be 'missing' in the sense that no actual source-code/tokens are + // contained within it. function nodeIsMissing(node) { if (node === undefined) { return true; } - return node.pos === node.end && node.pos >= 0 && node.kind !== 1; + return node.pos === node.end && node.pos >= 0 && node.kind !== 1 /* EndOfFileToken */; } ts.nodeIsMissing = nodeIsMissing; function nodeIsPresent(node) { return !nodeIsMissing(node); } ts.nodeIsPresent = nodeIsPresent; + /** + * Appends a range of value to begin of an array, returning the array. + * + * @param to The array to which `value` is to be appended. If `to` is `undefined`, a new array + * is created if `value` was appended. + * @param from The values to append to the array. If `from` is `undefined`, nothing is + * appended. If an element of `from` is `undefined`, that element is not appended. + */ function prependStatements(to, from) { if (from === undefined || from.length === 0) return to; @@ -6984,10 +7838,17 @@ var ts; return to; } ts.prependStatements = prependStatements; + /** + * Determine if the given comment is a triple-slash + * + * @return true if the comment is a triple-slash comment else false + */ function isRecognizedTripleSlashComment(text, commentPos, commentEnd) { - if (text.charCodeAt(commentPos + 1) === 47 && + // Verify this is /// comment, but do the regexp match only when we first can find /// in the comment text + // so that we don't end up computing comment string and doing match for all // comments + if (text.charCodeAt(commentPos + 1) === 47 /* slash */ && commentPos + 2 < commentEnd && - text.charCodeAt(commentPos + 2) === 47) { + text.charCodeAt(commentPos + 2) === 47 /* slash */) { var textSubStr = text.substring(commentPos, commentEnd); return textSubStr.match(ts.fullTripleSlashReferencePathRegEx) || textSubStr.match(ts.fullTripleSlashAMDReferencePathRegEx) || @@ -6999,21 +7860,27 @@ var ts; } ts.isRecognizedTripleSlashComment = isRecognizedTripleSlashComment; function isPinnedComment(text, start) { - return text.charCodeAt(start + 1) === 42 && - text.charCodeAt(start + 2) === 33; + return text.charCodeAt(start + 1) === 42 /* asterisk */ && + text.charCodeAt(start + 2) === 33 /* exclamation */; } ts.isPinnedComment = isPinnedComment; function getTokenPosOfNode(node, sourceFile, includeJsDoc) { + // With nodes that have no width (i.e. 'Missing' nodes), we actually *don't* + // want to skip trivia because this will launch us forward to the next token. if (nodeIsMissing(node)) { return node.pos; } if (ts.isJSDocNode(node)) { - return ts.skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos, false, true); + return ts.skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); } if (includeJsDoc && ts.hasJSDocNodes(node)) { return getTokenPosOfNode(node.jsDoc[0]); } - if (node.kind === 300 && node._children.length > 0) { + // For a syntax list, it is possible that one of its children has JSDocComment nodes, while + // the syntax list itself considers them as normal trivia. Therefore if we simply skip + // trivia for the list, we may have skipped the JSDocComment as well. So we should process its + // first child to determine the actual position of its first token. + if (node.kind === 300 /* SyntaxList */ && node._children.length > 0) { return getTokenPosOfNode(node._children[0], sourceFile, includeJsDoc); } return ts.skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos); @@ -7047,38 +7914,51 @@ var ts; function getPos(range) { return range.pos; } + /** + * Note: it is expected that the `nodeArray` and the `node` are within the same file. + * For example, searching for a `SourceFile` in a `SourceFile[]` wouldn't work. + */ function indexOfNode(nodeArray, node) { return ts.binarySearch(nodeArray, node, getPos, ts.compareValues); } ts.indexOfNode = indexOfNode; + /** + * Gets flags that control emit behavior of a node. + */ function getEmitFlags(node) { var emitNode = node.emitNode; return emitNode && emitNode.flags || 0; } ts.getEmitFlags = getEmitFlags; function getLiteralText(node, sourceFile) { - if (!nodeIsSynthesized(node) && node.parent && !(ts.isNumericLiteral(node) && node.numericLiteralFlags & 512)) { + // 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 && !(ts.isNumericLiteral(node) && node.numericLiteralFlags & 512 /* ContainsSeparator */)) { return getSourceTextOfNodeFromSourceFile(sourceFile, node); } - var escapeText = getEmitFlags(node) & 16777216 ? escapeString : escapeNonAsciiString; + var escapeText = getEmitFlags(node) & 16777216 /* NoAsciiEscaping */ ? escapeString : escapeNonAsciiString; + // If we can't reach the original source text, use the canonical form if it's a number, + // or a (possibly escaped) quoted form of the original text if it's string-like. switch (node.kind) { - case 9: + case 9 /* StringLiteral */: if (node.singleQuote) { - return "'" + escapeText(node.text, 39) + "'"; + return "'" + escapeText(node.text, 39 /* singleQuote */) + "'"; } else { - return '"' + escapeText(node.text, 34) + '"'; + return '"' + escapeText(node.text, 34 /* doubleQuote */) + '"'; } - case 13: - return "`" + escapeText(node.text, 96) + "`"; - case 14: - return "`" + escapeText(node.text, 96) + "${"; - case 15: - return "}" + escapeText(node.text, 96) + "${"; - case 16: - return "}" + escapeText(node.text, 96) + "`"; - case 8: - case 12: + case 13 /* NoSubstitutionTemplateLiteral */: + return "`" + escapeText(node.text, 96 /* backtick */) + "`"; + case 14 /* TemplateHead */: + // tslint:disable-next-line no-invalid-template-strings + return "`" + escapeText(node.text, 96 /* backtick */) + "${"; + case 15 /* TemplateMiddle */: + // tslint:disable-next-line no-invalid-template-strings + return "}" + escapeText(node.text, 96 /* backtick */) + "${"; + case 16 /* TemplateTail */: + return "}" + escapeText(node.text, 96 /* backtick */) + "`"; + case 8 /* NumericLiteral */: + case 12 /* RegularExpressionLiteral */: return node.text; } return ts.Debug.fail("Literal kind '" + node.kind + "' not accounted for."); @@ -7088,59 +7968,74 @@ var ts; return ts.isString(value) ? '"' + escapeNonAsciiString(value) + '"' : "" + value; } ts.getTextOfConstantValue = getTextOfConstantValue; + // Add an extra underscore to identifiers that start with two underscores to avoid issues with magic names like '__proto__' function escapeLeadingUnderscores(identifier) { - return (identifier.length >= 2 && identifier.charCodeAt(0) === 95 && identifier.charCodeAt(1) === 95 ? "_" + identifier : identifier); + return (identifier.length >= 2 && identifier.charCodeAt(0) === 95 /* _ */ && identifier.charCodeAt(1) === 95 /* _ */ ? "_" + identifier : identifier); } ts.escapeLeadingUnderscores = escapeLeadingUnderscores; + /** + * @deprecated Use `id.escapedText` to get the escaped text of an Identifier. + * @param identifier The identifier to escape + */ function escapeIdentifier(identifier) { return identifier; } ts.escapeIdentifier = escapeIdentifier; + // Make an identifier from an external module name by extracting the string after the last "/" and replacing + // all non-alphanumeric characters with underscores function makeIdentifierFromModuleName(moduleName) { return ts.getBaseFileName(moduleName).replace(/^(\d)/, "_$1").replace(/\W/g, "_"); } ts.makeIdentifierFromModuleName = makeIdentifierFromModuleName; function isBlockOrCatchScoped(declaration) { - return (ts.getCombinedNodeFlags(declaration) & 3) !== 0 || + return (ts.getCombinedNodeFlags(declaration) & 3 /* BlockScoped */) !== 0 || isCatchClauseVariableDeclarationOrBindingElement(declaration); } ts.isBlockOrCatchScoped = isBlockOrCatchScoped; function isCatchClauseVariableDeclarationOrBindingElement(declaration) { var node = getRootDeclaration(declaration); - return node.kind === 232 && node.parent.kind === 269; + return node.kind === 232 /* VariableDeclaration */ && node.parent.kind === 269 /* CatchClause */; } ts.isCatchClauseVariableDeclarationOrBindingElement = isCatchClauseVariableDeclarationOrBindingElement; function isAmbientModule(node) { - return ts.isModuleDeclaration(node) && (node.name.kind === 9 || isGlobalScopeAugmentation(node)); + return ts.isModuleDeclaration(node) && (node.name.kind === 9 /* StringLiteral */ || isGlobalScopeAugmentation(node)); } ts.isAmbientModule = isAmbientModule; function isModuleWithStringLiteralName(node) { - return ts.isModuleDeclaration(node) && node.name.kind === 9; + return ts.isModuleDeclaration(node) && node.name.kind === 9 /* StringLiteral */; } ts.isModuleWithStringLiteralName = isModuleWithStringLiteralName; function isNonGlobalAmbientModule(node) { return ts.isModuleDeclaration(node) && ts.isStringLiteral(node.name); } ts.isNonGlobalAmbientModule = isNonGlobalAmbientModule; + /** + * An effective module (namespace) declaration is either + * 1. An actual declaration: namespace X { ... } + * 2. A Javascript declaration, which is: + * An identifier in a nested property access expression: Y in `X.Y.Z = { ... }` + */ function isEffectiveModuleDeclaration(node) { return ts.isModuleDeclaration(node) || ts.isIdentifier(node); } ts.isEffectiveModuleDeclaration = isEffectiveModuleDeclaration; + /** Given a symbol for a module, checks that it is a shorthand ambient module. */ function isShorthandAmbientModuleSymbol(moduleSymbol) { return isShorthandAmbientModule(moduleSymbol.valueDeclaration); } ts.isShorthandAmbientModuleSymbol = isShorthandAmbientModuleSymbol; function isShorthandAmbientModule(node) { - return node && node.kind === 239 && (!node.body); + // The only kind of module that can be missing a body is a shorthand ambient module. + return node && node.kind === 239 /* ModuleDeclaration */ && (!node.body); } function isBlockScopedContainerTopLevel(node) { - return node.kind === 274 || - node.kind === 239 || + return node.kind === 274 /* SourceFile */ || + node.kind === 239 /* ModuleDeclaration */ || ts.isFunctionLike(node); } ts.isBlockScopedContainerTopLevel = isBlockScopedContainerTopLevel; function isGlobalScopeAugmentation(module) { - return !!(module.flags & 512); + return !!(module.flags & 512 /* GlobalAugmentation */); } ts.isGlobalScopeAugmentation = isGlobalScopeAugmentation; function isExternalModuleAugmentation(node) { @@ -7148,10 +8043,13 @@ var ts; } ts.isExternalModuleAugmentation = isExternalModuleAugmentation; function isModuleAugmentationExternal(node) { + // external module augmentation is a ambient module declaration that is either: + // - defined in the top level scope and source file is an external module + // - defined inside ambient module declaration located in the top level scope and source file not an external module switch (node.parent.kind) { - case 274: + case 274 /* SourceFile */: return ts.isExternalModule(node.parent); - case 240: + case 240 /* ModuleBlock */: return isAmbientModule(node.parent.parent) && ts.isSourceFile(node.parent.parent.parent) && !ts.isExternalModule(node.parent.parent.parent); } return false; @@ -7163,22 +8061,24 @@ var ts; ts.isEffectiveExternalModule = isEffectiveExternalModule; function isBlockScope(node, parentNode) { switch (node.kind) { - case 274: - case 241: - case 269: - case 239: - case 220: - case 221: - case 222: - case 155: - case 154: - case 156: - case 157: - case 234: - case 192: - case 193: + case 274 /* SourceFile */: + case 241 /* CaseBlock */: + case 269 /* CatchClause */: + case 239 /* ModuleDeclaration */: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 155 /* Constructor */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: return true; - case 213: + case 213 /* Block */: + // function block is not considered block-scope container + // see comment in binder.ts: bind(...), case for SyntaxKind.Block return !ts.isFunctionLike(parentNode); } return false; @@ -7186,28 +8086,28 @@ var ts; ts.isBlockScope = isBlockScope; function isDeclarationWithTypeParameters(node) { switch (node.kind) { - case 158: - case 159: - case 153: - case 160: - case 163: - case 164: - case 284: - case 235: - case 205: - case 236: - case 237: - case 297: - case 234: - case 154: - case 155: - case 156: - case 157: - case 192: - case 193: - case 292: - case 298: - case 288: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 153 /* MethodSignature */: + case 160 /* IndexSignature */: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 284 /* JSDocFunctionType */: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 297 /* JSDocTemplateTag */: + case 234 /* FunctionDeclaration */: + case 154 /* MethodDeclaration */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 292 /* JSDocCallbackTag */: + case 298 /* JSDocTypedefTag */: + case 288 /* JSDocSignature */: return true; default: ts.assertTypeIsNever(node); @@ -7217,8 +8117,8 @@ var ts; ts.isDeclarationWithTypeParameters = isDeclarationWithTypeParameters; function isAnyImportSyntax(node) { switch (node.kind) { - case 244: - case 243: + case 244 /* ImportDeclaration */: + case 243 /* ImportEqualsDeclaration */: return true; default: return false; @@ -7227,15 +8127,15 @@ var ts; ts.isAnyImportSyntax = isAnyImportSyntax; function isLateVisibilityPaintedStatement(node) { switch (node.kind) { - case 244: - case 243: - case 214: - case 235: - case 234: - case 239: - case 237: - case 236: - case 238: + case 244 /* ImportDeclaration */: + case 243 /* ImportEqualsDeclaration */: + case 214 /* VariableStatement */: + case 235 /* ClassDeclaration */: + case 234 /* FunctionDeclaration */: + case 239 /* ModuleDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 236 /* InterfaceDeclaration */: + case 238 /* EnumDeclaration */: return true; default: return false; @@ -7246,10 +8146,15 @@ var ts; return isAnyImportSyntax(node) || ts.isExportDeclaration(node); } ts.isAnyImportOrReExport = isAnyImportOrReExport; + // Gets the nearest enclosing block scope container that has the provided node + // as a descendant, that is not the provided node. function getEnclosingBlockScopeContainer(node) { return findAncestor(node.parent, function (current) { return isBlockScope(current, current.parent); }); } ts.getEnclosingBlockScopeContainer = getEnclosingBlockScopeContainer; + // Return display name of an identifier + // Computed property names will just be emitted as "[]", where is the source + // text of the expression in the computed property. function declarationNameToString(name) { return getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name); } @@ -7260,13 +8165,13 @@ var ts; ts.getNameFromIndexInfo = getNameFromIndexInfo; function getTextOfPropertyName(name) { switch (name.kind) { - case 71: + case 71 /* Identifier */: return name.escapedText; - case 9: - case 8: + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: return escapeLeadingUnderscores(name.text); - case 147: - return isStringOrNumericLiteral(name.expression) ? escapeLeadingUnderscores(name.expression.text) : undefined; + case 147 /* ComputedPropertyName */: + return isStringOrNumericLiteral(name.expression) ? escapeLeadingUnderscores(name.expression.text) : undefined; // TODO: GH#18217 Almost all uses of this assume the result to be defined! default: ts.Debug.assertNever(name); } @@ -7274,11 +8179,11 @@ var ts; ts.getTextOfPropertyName = getTextOfPropertyName; function entityNameToString(name) { switch (name.kind) { - case 71: + case 71 /* Identifier */: return getFullWidth(name) === 0 ? ts.idText(name) : getTextOfNode(name); - case 146: + case 146 /* QualifiedName */: return entityNameToString(name.left) + "." + entityNameToString(name.right); - case 185: + case 185 /* PropertyAccessExpression */: return entityNameToString(name.expression) + "." + entityNameToString(name.name); default: throw ts.Debug.assertNever(name); @@ -7315,7 +8220,7 @@ var ts; } ts.createDiagnosticForNodeFromMessageChain = createDiagnosticForNodeFromMessageChain; function getSpanOfTokenAtPosition(sourceFile, pos) { - var scanner = ts.createScanner(sourceFile.languageVersion, true, sourceFile.languageVariant, sourceFile.text, undefined, pos); + var scanner = ts.createScanner(sourceFile.languageVersion, /*skipTrivia*/ true, sourceFile.languageVariant, sourceFile.text, /*onError:*/ undefined, pos); scanner.scan(); var start = scanner.getTokenPos(); return ts.createTextSpanFromBounds(start, scanner.getTextPos()); @@ -7323,10 +8228,12 @@ var ts; ts.getSpanOfTokenAtPosition = getSpanOfTokenAtPosition; function getErrorSpanForArrowFunction(sourceFile, node) { var pos = ts.skipTrivia(sourceFile.text, node.pos); - if (node.body && node.body.kind === 213) { + if (node.body && node.body.kind === 213 /* Block */) { var startLine = ts.getLineAndCharacterOfPosition(sourceFile, node.body.pos).line; var endLine = ts.getLineAndCharacterOfPosition(sourceFile, node.body.end).line; if (startLine < endLine) { + // The arrow function spans multiple lines, + // make the error span be the first line, inclusive. return ts.createTextSpan(pos, getEndLinePosition(startLine, sourceFile) - pos + 1); } } @@ -7335,40 +8242,46 @@ var ts; function getErrorSpanForNode(sourceFile, node) { var errorNode = node; switch (node.kind) { - case 274: - var pos_1 = ts.skipTrivia(sourceFile.text, 0, false); + case 274 /* SourceFile */: + var pos_1 = ts.skipTrivia(sourceFile.text, 0, /*stopAfterLineBreak*/ false); if (pos_1 === sourceFile.text.length) { + // file is empty - return span for the beginning of the file return ts.createTextSpan(0, 0); } return getSpanOfTokenAtPosition(sourceFile, pos_1); - case 232: - case 182: - case 235: - case 205: - case 236: - case 239: - case 238: - case 273: - case 234: - case 192: - case 154: - case 156: - case 157: - case 237: - case 152: - case 151: + // This list is a work in progress. Add missing node kinds to improve their error + // spans. + case 232 /* VariableDeclaration */: + case 182 /* BindingElement */: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 236 /* InterfaceDeclaration */: + case 239 /* ModuleDeclaration */: + case 238 /* EnumDeclaration */: + case 273 /* EnumMember */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 237 /* TypeAliasDeclaration */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: errorNode = node.name; break; - case 193: + case 193 /* ArrowFunction */: return getErrorSpanForArrowFunction(sourceFile, node); } if (errorNode === undefined) { + // If we don't have a better node, then just set the error on the first token of + // construct. return getSpanOfTokenAtPosition(sourceFile, node.pos); } var isMissing = nodeIsMissing(errorNode); var pos = isMissing ? errorNode.pos : ts.skipTrivia(sourceFile.text, errorNode.pos); + // These asserts should all be satisfied for a properly constructed `errorNode`. if (isMissing) { ts.Debug.assert(pos === errorNode.pos, "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809"); ts.Debug.assert(pos === errorNode.end, "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809"); @@ -7385,57 +8298,58 @@ var ts; } ts.isExternalOrCommonJsModule = isExternalOrCommonJsModule; function isJsonSourceFile(file) { - return file.scriptKind === 6; + return file.scriptKind === 6 /* JSON */; } ts.isJsonSourceFile = isJsonSourceFile; function isConstEnumDeclaration(node) { - return node.kind === 238 && isConst(node); + return node.kind === 238 /* EnumDeclaration */ && isConst(node); } ts.isConstEnumDeclaration = isConstEnumDeclaration; function isConst(node) { - return !!(ts.getCombinedNodeFlags(node) & 2) - || !!(ts.getCombinedModifierFlags(node) & 2048); + return !!(ts.getCombinedNodeFlags(node) & 2 /* Const */) + || !!(ts.getCombinedModifierFlags(node) & 2048 /* Const */); } ts.isConst = isConst; function isLet(node) { - return !!(ts.getCombinedNodeFlags(node) & 1); + return !!(ts.getCombinedNodeFlags(node) & 1 /* Let */); } ts.isLet = isLet; function isSuperCall(n) { - return n.kind === 187 && n.expression.kind === 97; + return n.kind === 187 /* CallExpression */ && n.expression.kind === 97 /* SuperKeyword */; } ts.isSuperCall = isSuperCall; function isImportCall(n) { - return n.kind === 187 && n.expression.kind === 91; + return n.kind === 187 /* CallExpression */ && n.expression.kind === 91 /* ImportKeyword */; } ts.isImportCall = isImportCall; function isLiteralImportTypeNode(n) { - return n.kind === 179 && - n.argument.kind === 178 && + return n.kind === 179 /* ImportType */ && + n.argument.kind === 178 /* LiteralType */ && ts.isStringLiteral(n.argument.literal); } ts.isLiteralImportTypeNode = isLiteralImportTypeNode; function isPrologueDirective(node) { - return node.kind === 216 - && node.expression.kind === 9; + return node.kind === 216 /* ExpressionStatement */ + && node.expression.kind === 9 /* StringLiteral */; } ts.isPrologueDirective = isPrologueDirective; function getLeadingCommentRangesOfNode(node, sourceFileOfNode) { - return node.kind !== 10 ? ts.getLeadingCommentRanges(sourceFileOfNode.text, node.pos) : undefined; + return node.kind !== 10 /* JsxText */ ? ts.getLeadingCommentRanges(sourceFileOfNode.text, node.pos) : undefined; } ts.getLeadingCommentRangesOfNode = getLeadingCommentRangesOfNode; function getJSDocCommentRanges(node, text) { - var commentRanges = (node.kind === 149 || - node.kind === 148 || - node.kind === 192 || - node.kind === 193 || - node.kind === 191) ? + var commentRanges = (node.kind === 149 /* Parameter */ || + node.kind === 148 /* TypeParameter */ || + node.kind === 192 /* FunctionExpression */ || + node.kind === 193 /* ArrowFunction */ || + node.kind === 191 /* ParenthesizedExpression */) ? ts.concatenate(ts.getTrailingCommentRanges(text, node.pos), ts.getLeadingCommentRanges(text, node.pos)) : ts.getLeadingCommentRanges(text, node.pos); + // True if the comment starts with '/**' but not if it is '/**/' return ts.filter(commentRanges, function (comment) { - return text.charCodeAt(comment.pos + 1) === 42 && - text.charCodeAt(comment.pos + 2) === 42 && - text.charCodeAt(comment.pos + 3) !== 47; + return text.charCodeAt(comment.pos + 1) === 42 /* asterisk */ && + text.charCodeAt(comment.pos + 2) === 42 /* asterisk */ && + text.charCodeAt(comment.pos + 3) !== 47 /* slash */; }); } ts.getJSDocCommentRanges = getJSDocCommentRanges; @@ -7444,75 +8358,87 @@ var ts; ts.fullTripleSlashAMDReferencePathRegEx = /^(\/\/\/\s*/; var defaultLibReferenceRegEx = /^(\/\/\/\s*/; function isPartOfTypeNode(node) { - if (161 <= node.kind && node.kind <= 179) { + if (161 /* FirstTypeNode */ <= node.kind && node.kind <= 179 /* LastTypeNode */) { return true; } switch (node.kind) { - case 119: - case 142: - case 134: - case 137: - case 122: - case 138: - case 140: - case 131: + case 119 /* AnyKeyword */: + case 142 /* UnknownKeyword */: + case 134 /* NumberKeyword */: + case 137 /* StringKeyword */: + case 122 /* BooleanKeyword */: + case 138 /* SymbolKeyword */: + case 140 /* UndefinedKeyword */: + case 131 /* NeverKeyword */: return true; - case 105: - return node.parent.kind !== 196; - case 207: + case 105 /* VoidKeyword */: + return node.parent.kind !== 196 /* VoidExpression */; + case 207 /* ExpressionWithTypeArguments */: return !isExpressionWithTypeArgumentsInClassExtendsClause(node); - case 148: - return node.parent.kind === 177 || node.parent.kind === 172; - case 71: - if (node.parent.kind === 146 && node.parent.right === node) { + case 148 /* TypeParameter */: + return node.parent.kind === 177 /* MappedType */ || node.parent.kind === 172 /* InferType */; + // Identifiers and qualified names may be type nodes, depending on their context. Climb + // above them to find the lowest container + case 71 /* Identifier */: + // If the identifier is the RHS of a qualified name, then it's a type iff its parent is. + if (node.parent.kind === 146 /* QualifiedName */ && node.parent.right === node) { node = node.parent; } - else if (node.parent.kind === 185 && node.parent.name === node) { + else if (node.parent.kind === 185 /* PropertyAccessExpression */ && node.parent.name === node) { node = node.parent; } - ts.Debug.assert(node.kind === 71 || node.kind === 146 || node.kind === 185, "'node' was expected to be a qualified name, identifier or property access in 'isPartOfTypeNode'."); - case 146: - case 185: - case 99: { + // At this point, node is either a qualified name or an identifier + ts.Debug.assert(node.kind === 71 /* Identifier */ || node.kind === 146 /* QualifiedName */ || node.kind === 185 /* PropertyAccessExpression */, "'node' was expected to be a qualified name, identifier or property access in 'isPartOfTypeNode'."); + // falls through + case 146 /* QualifiedName */: + case 185 /* PropertyAccessExpression */: + case 99 /* ThisKeyword */: { var parent = node.parent; - if (parent.kind === 165) { + if (parent.kind === 165 /* TypeQuery */) { return false; } - if (parent.kind === 179) { + if (parent.kind === 179 /* ImportType */) { return !parent.isTypeOf; } - if (161 <= parent.kind && parent.kind <= 179) { + // Do not recursively call isPartOfTypeNode on the parent. In the example: + // + // let a: A.B.C; + // + // Calling isPartOfTypeNode would consider the qualified name A.B a type node. + // Only C and A.B.C are type nodes. + if (161 /* FirstTypeNode */ <= parent.kind && parent.kind <= 179 /* LastTypeNode */) { return true; } switch (parent.kind) { - case 207: + case 207 /* ExpressionWithTypeArguments */: return !isExpressionWithTypeArgumentsInClassExtendsClause(parent); - case 148: + case 148 /* TypeParameter */: return node === parent.constraint; - case 152: - case 151: - case 149: - case 232: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 149 /* Parameter */: + case 232 /* VariableDeclaration */: return node === parent.type; - case 234: - case 192: - case 193: - case 155: - case 154: - case 153: - case 156: - case 157: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 155 /* Constructor */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return node === parent.type; - case 158: - case 159: - case 160: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 160 /* IndexSignature */: return node === parent.type; - case 190: + case 190 /* TypeAssertionExpression */: return node === parent.type; - case 187: - case 188: + case 187 /* CallExpression */: + case 188 /* NewExpression */: return ts.contains(parent.typeArguments, node); - case 189: + case 189 /* TaggedTemplateExpression */: + // TODO (drosen): TaggedTemplateExpressions may eventually support type arguments. return false; } } @@ -7530,27 +8456,29 @@ var ts; return false; } ts.isChildOfNodeWithKind = isChildOfNodeWithKind; + // Warning: This has the same semantics as the forEach family of functions, + // in that traversal terminates in the event that 'visitor' supplies a truthy value. function forEachReturnStatement(body, visitor) { return traverse(body); function traverse(node) { switch (node.kind) { - case 225: + case 225 /* ReturnStatement */: return visitor(node); - case 241: - case 213: - case 217: - case 218: - case 219: - case 220: - case 221: - case 222: - case 226: - case 227: - case 266: - case 267: - case 228: - case 230: - case 269: + case 241 /* CaseBlock */: + case 213 /* Block */: + case 217 /* IfStatement */: + case 218 /* DoStatement */: + case 219 /* WhileStatement */: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 226 /* WithStatement */: + case 227 /* SwitchStatement */: + case 266 /* CaseClause */: + case 267 /* DefaultClause */: + case 228 /* LabeledStatement */: + case 230 /* TryStatement */: + case 269 /* CatchClause */: return ts.forEachChild(node, traverse); } } @@ -7560,39 +8488,52 @@ var ts; return traverse(body); function traverse(node) { switch (node.kind) { - case 203: + case 203 /* YieldExpression */: visitor(node); var operand = node.expression; if (operand) { traverse(operand); } return; - case 238: - case 236: - case 239: - case 237: - case 235: - case 205: + case 238 /* EnumDeclaration */: + case 236 /* InterfaceDeclaration */: + case 239 /* ModuleDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + // These are not allowed inside a generator now, but eventually they may be allowed + // as local types. Regardless, any yield statements contained within them should be + // skipped in this traversal. return; default: if (ts.isFunctionLike(node)) { - if (node.name && node.name.kind === 147) { + if (node.name && node.name.kind === 147 /* ComputedPropertyName */) { + // Note that we will not include methods/accessors of a class because they would require + // first descending into the class. This is by design. traverse(node.name.expression); return; } } else if (!isPartOfTypeNode(node)) { + // This is the general case, which should include mostly expressions and statements. + // Also includes NodeArrays. ts.forEachChild(node, traverse); } } } } ts.forEachYieldExpression = forEachYieldExpression; + /** + * Gets the most likely element type for a TypeNode. This is not an exhaustive test + * as it assumes a rest argument can only be an array type (either T[], or Array). + * + * @param node The type node. + */ function getRestParameterElementType(node) { - if (node && node.kind === 167) { + if (node && node.kind === 167 /* ArrayType */) { return node.elementType; } - else if (node && node.kind === 162) { + else if (node && node.kind === 162 /* TypeReference */) { return ts.singleOrUndefined(node.typeArguments); } else { @@ -7602,12 +8543,12 @@ var ts; ts.getRestParameterElementType = getRestParameterElementType; function getMembersOfDeclaration(node) { switch (node.kind) { - case 236: - case 235: - case 205: - case 166: + case 236 /* InterfaceDeclaration */: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 166 /* TypeLiteral */: return node.members; - case 184: + case 184 /* ObjectLiteralExpression */: return node.properties; } } @@ -7615,14 +8556,14 @@ var ts; function isVariableLike(node) { if (node) { switch (node.kind) { - case 182: - case 273: - case 149: - case 270: - case 152: - case 151: - case 271: - case 232: + case 182 /* BindingElement */: + case 273 /* EnumMember */: + case 149 /* Parameter */: + case 270 /* PropertyAssignment */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 271 /* ShorthandPropertyAssignment */: + case 232 /* VariableDeclaration */: return true; } } @@ -7634,8 +8575,8 @@ var ts; } ts.isVariableLikeOrAccessor = isVariableLikeOrAccessor; function isVariableDeclarationInVariableStatement(node) { - return node.parent.kind === 233 - && node.parent.parent.kind === 214; + return node.parent.kind === 233 /* VariableDeclarationList */ + && node.parent.parent.kind === 214 /* VariableStatement */; } ts.isVariableDeclarationInVariableStatement = isVariableDeclarationInVariableStatement; function isValidESSymbolDeclaration(node) { @@ -7646,13 +8587,13 @@ var ts; ts.isValidESSymbolDeclaration = isValidESSymbolDeclaration; function introducesArgumentsExoticObject(node) { switch (node.kind) { - case 154: - case 153: - case 155: - case 156: - case 157: - case 234: - case 192: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: return true; } return false; @@ -7663,7 +8604,7 @@ var ts; if (beforeUnwrapLabelCallback) { beforeUnwrapLabelCallback(node); } - if (node.statement.kind !== 228) { + if (node.statement.kind !== 228 /* LabeledStatement */) { return node.statement; } node = node.statement; @@ -7671,30 +8612,30 @@ var ts; } ts.unwrapInnermostStatementOfLabel = unwrapInnermostStatementOfLabel; function isFunctionBlock(node) { - return node && node.kind === 213 && ts.isFunctionLike(node.parent); + return node && node.kind === 213 /* Block */ && ts.isFunctionLike(node.parent); } ts.isFunctionBlock = isFunctionBlock; function isObjectLiteralMethod(node) { - return node && node.kind === 154 && node.parent.kind === 184; + return node && node.kind === 154 /* MethodDeclaration */ && node.parent.kind === 184 /* ObjectLiteralExpression */; } ts.isObjectLiteralMethod = isObjectLiteralMethod; function isObjectLiteralOrClassExpressionMethod(node) { - return node.kind === 154 && - (node.parent.kind === 184 || - node.parent.kind === 205); + return node.kind === 154 /* MethodDeclaration */ && + (node.parent.kind === 184 /* ObjectLiteralExpression */ || + node.parent.kind === 205 /* ClassExpression */); } ts.isObjectLiteralOrClassExpressionMethod = isObjectLiteralOrClassExpressionMethod; function isIdentifierTypePredicate(predicate) { - return predicate && predicate.kind === 1; + return predicate && predicate.kind === 1 /* Identifier */; } ts.isIdentifierTypePredicate = isIdentifierTypePredicate; function isThisTypePredicate(predicate) { - return predicate && predicate.kind === 0; + return predicate && predicate.kind === 0 /* This */; } ts.isThisTypePredicate = isThisTypePredicate; function getPropertyAssignment(objectLiteral, key, key2) { return objectLiteral.properties.filter(function (property) { - if (property.kind === 270) { + if (property.kind === 270 /* PropertyAssignment */) { var propName = getTextOfPropertyName(property.name); return key === propName || (!!key2 && key2 === propName); } @@ -7731,64 +8672,87 @@ var ts; } ts.getContainingClass = getContainingClass; function getThisContainer(node, includeArrowFunctions) { - ts.Debug.assert(node.kind !== 274); + ts.Debug.assert(node.kind !== 274 /* SourceFile */); while (true) { node = node.parent; if (!node) { - return ts.Debug.fail(); + return ts.Debug.fail(); // If we never pass in a SourceFile, this should be unreachable, since we'll stop when we reach that. } switch (node.kind) { - case 147: + case 147 /* ComputedPropertyName */: + // If the grandparent node is an object literal (as opposed to a class), + // then the computed property is not a 'this' container. + // A computed property name in a class needs to be a this container + // so that we can error on it. if (ts.isClassLike(node.parent.parent)) { return node; } + // If this is a computed property, then the parent should not + // make it a this container. The parent might be a property + // in an object literal, like a method or accessor. But in order for + // such a parent to be a this container, the reference must be in + // the *body* of the container. node = node.parent; break; - case 150: - if (node.parent.kind === 149 && ts.isClassElement(node.parent.parent)) { + case 150 /* Decorator */: + // Decorators are always applied outside of the body of a class or method. + if (node.parent.kind === 149 /* Parameter */ && ts.isClassElement(node.parent.parent)) { + // If the decorator's parent is a Parameter, we resolve the this container from + // the grandparent class declaration. node = node.parent.parent; } else if (ts.isClassElement(node.parent)) { + // If the decorator's parent is a class element, we resolve the 'this' container + // from the parent class declaration. node = node.parent; } break; - case 193: + case 193 /* ArrowFunction */: if (!includeArrowFunctions) { continue; } - case 234: - case 192: - case 239: - case 152: - case 151: - case 154: - case 153: - case 155: - case 156: - case 157: - case 158: - case 159: - case 160: - case 238: - case 274: + // falls through + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 239 /* ModuleDeclaration */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 160 /* IndexSignature */: + case 238 /* EnumDeclaration */: + case 274 /* SourceFile */: return node; } } } ts.getThisContainer = getThisContainer; function getNewTargetContainer(node) { - var container = getThisContainer(node, false); + var container = getThisContainer(node, /*includeArrowFunctions*/ false); if (container) { switch (container.kind) { - case 155: - case 234: - case 192: + case 155 /* Constructor */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: return container; } } return undefined; } ts.getNewTargetContainer = getNewTargetContainer; + /** + * Given an super call/property node, returns the closest node where + * - a super call/property access is legal in the node and not legal in the parent node the node. + * i.e. super call is legal in constructor but not legal in the class body. + * - the container is an arrow function (so caller might need to call getSuperContainer again in case it needs to climb higher) + * - a super call/property is definitely illegal in the container (but might be legal in some subnode) + * i.e. super property access is illegal in function declaration but can be legal in the statement list + */ function getSuperContainer(node, stopOnFunctions) { while (true) { node = node.parent; @@ -7796,28 +8760,34 @@ var ts; return node; } switch (node.kind) { - case 147: + case 147 /* ComputedPropertyName */: node = node.parent; break; - case 234: - case 192: - case 193: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: if (!stopOnFunctions) { continue; } - case 152: - case 151: - case 154: - case 153: - case 155: - case 156: - case 157: + // falls through + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return node; - case 150: - if (node.parent.kind === 149 && ts.isClassElement(node.parent.parent)) { + case 150 /* Decorator */: + // Decorators are always applied outside of the body of a class or method. + if (node.parent.kind === 149 /* Parameter */ && ts.isClassElement(node.parent.parent)) { + // If the decorator's parent is a Parameter, we resolve the this container from + // the grandparent class declaration. node = node.parent.parent; } else if (ts.isClassElement(node.parent)) { + // If the decorator's parent is a class element, we resolve the 'this' container + // from the parent class declaration. node = node.parent; } break; @@ -7826,41 +8796,47 @@ var ts; } ts.getSuperContainer = getSuperContainer; function getImmediatelyInvokedFunctionExpression(func) { - if (func.kind === 192 || func.kind === 193) { + if (func.kind === 192 /* FunctionExpression */ || func.kind === 193 /* ArrowFunction */) { var prev = func; var parent = func.parent; - while (parent.kind === 191) { + while (parent.kind === 191 /* ParenthesizedExpression */) { prev = parent; parent = parent.parent; } - if (parent.kind === 187 && parent.expression === prev) { + if (parent.kind === 187 /* CallExpression */ && parent.expression === prev) { return parent; } } } ts.getImmediatelyInvokedFunctionExpression = getImmediatelyInvokedFunctionExpression; + /** + * Determines whether a node is a property or element access expression for `super`. + */ function isSuperProperty(node) { var kind = node.kind; - return (kind === 185 || kind === 186) - && node.expression.kind === 97; + return (kind === 185 /* PropertyAccessExpression */ || kind === 186 /* ElementAccessExpression */) + && node.expression.kind === 97 /* SuperKeyword */; } ts.isSuperProperty = isSuperProperty; + /** + * Determines whether a node is a property or element access expression for `this`. + */ function isThisProperty(node) { var kind = node.kind; - return (kind === 185 || kind === 186) - && node.expression.kind === 99; + return (kind === 185 /* PropertyAccessExpression */ || kind === 186 /* ElementAccessExpression */) + && node.expression.kind === 99 /* ThisKeyword */; } ts.isThisProperty = isThisProperty; function getEntityNameFromTypeNode(node) { switch (node.kind) { - case 162: + case 162 /* TypeReference */: return node.typeName; - case 207: + case 207 /* ExpressionWithTypeArguments */: return isEntityNameExpression(node.expression) ? node.expression : undefined; - case 71: - case 146: + case 71 /* Identifier */: + case 146 /* QualifiedName */: return node; } return undefined; @@ -7868,10 +8844,10 @@ var ts; ts.getEntityNameFromTypeNode = getEntityNameFromTypeNode; function getInvokedExpression(node) { switch (node.kind) { - case 189: + case 189 /* TaggedTemplateExpression */: return node.tag; - case 257: - case 256: + case 257 /* JsxOpeningElement */: + case 256 /* JsxSelfClosingElement */: return node.tagName; default: return node.expression; @@ -7880,41 +8856,45 @@ var ts; ts.getInvokedExpression = getInvokedExpression; function nodeCanBeDecorated(node, parent, grandparent) { switch (node.kind) { - case 235: + case 235 /* ClassDeclaration */: + // classes are valid targets return true; - case 152: - return parent.kind === 235; - case 156: - case 157: - case 154: + case 152 /* PropertyDeclaration */: + // property declarations are valid if their parent is a class declaration. + return parent.kind === 235 /* ClassDeclaration */; + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 154 /* MethodDeclaration */: + // if this method has a body and its parent is a class declaration, this is a valid target. return node.body !== undefined - && parent.kind === 235; - case 149: + && parent.kind === 235 /* ClassDeclaration */; + case 149 /* Parameter */: + // if the parameter's parent has a body and its grandparent is a class declaration, this is a valid target; return parent.body !== undefined - && (parent.kind === 155 - || parent.kind === 154 - || parent.kind === 157) - && grandparent.kind === 235; + && (parent.kind === 155 /* Constructor */ + || parent.kind === 154 /* MethodDeclaration */ + || parent.kind === 157 /* SetAccessor */) + && grandparent.kind === 235 /* ClassDeclaration */; } return false; } ts.nodeCanBeDecorated = nodeCanBeDecorated; function nodeIsDecorated(node, parent, grandparent) { return node.decorators !== undefined - && nodeCanBeDecorated(node, parent, grandparent); + && nodeCanBeDecorated(node, parent, grandparent); // TODO: GH#18217 } ts.nodeIsDecorated = nodeIsDecorated; function nodeOrChildIsDecorated(node, parent, grandparent) { - return nodeIsDecorated(node, parent, grandparent) || childIsDecorated(node, parent); + return nodeIsDecorated(node, parent, grandparent) || childIsDecorated(node, parent); // TODO: GH#18217 } ts.nodeOrChildIsDecorated = nodeOrChildIsDecorated; function childIsDecorated(node, parent) { switch (node.kind) { - case 235: - return ts.some(node.members, function (m) { return nodeOrChildIsDecorated(m, node, parent); }); - case 154: - case 157: - return ts.some(node.parameters, function (p) { return nodeIsDecorated(p, node, parent); }); + case 235 /* ClassDeclaration */: + return ts.some(node.members, function (m) { return nodeOrChildIsDecorated(m, node, parent); }); // TODO: GH#18217 + case 154 /* MethodDeclaration */: + case 157 /* SetAccessor */: + return ts.some(node.parameters, function (p) { return nodeIsDecorated(p, node, parent); }); // TODO: GH#18217 default: return false; } @@ -7922,9 +8902,9 @@ var ts; ts.childIsDecorated = childIsDecorated; function isJSXTagName(node) { var parent = node.parent; - if (parent.kind === 257 || - parent.kind === 256 || - parent.kind === 258) { + if (parent.kind === 257 /* JsxOpeningElement */ || + parent.kind === 256 /* JsxSelfClosingElement */ || + parent.kind === 258 /* JsxClosingElement */) { return parent.tagName === node; } return false; @@ -7932,55 +8912,56 @@ var ts; ts.isJSXTagName = isJSXTagName; function isExpressionNode(node) { switch (node.kind) { - case 97: - case 95: - case 101: - case 86: - case 12: - case 183: - case 184: - case 185: - case 186: - case 187: - case 188: - case 189: - case 208: - case 190: - case 209: - case 191: - case 192: - case 205: - case 193: - case 196: - case 194: - case 195: - case 198: - case 199: - case 200: - case 201: - case 204: - case 202: - case 13: - case 206: - case 255: - case 256: - case 259: - case 203: - case 197: - case 210: + case 97 /* SuperKeyword */: + case 95 /* NullKeyword */: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: + case 12 /* RegularExpressionLiteral */: + case 183 /* ArrayLiteralExpression */: + case 184 /* ObjectLiteralExpression */: + case 185 /* PropertyAccessExpression */: + case 186 /* ElementAccessExpression */: + case 187 /* CallExpression */: + case 188 /* NewExpression */: + case 189 /* TaggedTemplateExpression */: + case 208 /* AsExpression */: + case 190 /* TypeAssertionExpression */: + case 209 /* NonNullExpression */: + case 191 /* ParenthesizedExpression */: + case 192 /* FunctionExpression */: + case 205 /* ClassExpression */: + case 193 /* ArrowFunction */: + case 196 /* VoidExpression */: + case 194 /* DeleteExpression */: + case 195 /* TypeOfExpression */: + case 198 /* PrefixUnaryExpression */: + case 199 /* PostfixUnaryExpression */: + case 200 /* BinaryExpression */: + case 201 /* ConditionalExpression */: + case 204 /* SpreadElement */: + case 202 /* TemplateExpression */: + case 13 /* NoSubstitutionTemplateLiteral */: + case 206 /* OmittedExpression */: + case 255 /* JsxElement */: + case 256 /* JsxSelfClosingElement */: + case 259 /* JsxFragment */: + case 203 /* YieldExpression */: + case 197 /* AwaitExpression */: + case 210 /* MetaProperty */: return true; - case 146: - while (node.parent.kind === 146) { + case 146 /* QualifiedName */: + while (node.parent.kind === 146 /* QualifiedName */) { node = node.parent; } - return node.parent.kind === 165 || isJSXTagName(node); - case 71: - if (node.parent.kind === 165 || isJSXTagName(node)) { + return node.parent.kind === 165 /* TypeQuery */ || isJSXTagName(node); + case 71 /* Identifier */: + if (node.parent.kind === 165 /* TypeQuery */ || isJSXTagName(node)) { return true; } - case 8: - case 9: - case 99: + // falls through + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: + case 99 /* ThisKeyword */: return isInExpressionContext(node); default: return false; @@ -7990,47 +8971,47 @@ var ts; function isInExpressionContext(node) { var parent = node.parent; switch (parent.kind) { - case 232: - case 149: - case 152: - case 151: - case 273: - case 270: - case 182: + case 232 /* VariableDeclaration */: + case 149 /* Parameter */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 273 /* EnumMember */: + case 270 /* PropertyAssignment */: + case 182 /* BindingElement */: return parent.initializer === node; - case 216: - case 217: - case 218: - case 219: - case 225: - case 226: - case 227: - case 266: - case 229: + case 216 /* ExpressionStatement */: + case 217 /* IfStatement */: + case 218 /* DoStatement */: + case 219 /* WhileStatement */: + case 225 /* ReturnStatement */: + case 226 /* WithStatement */: + case 227 /* SwitchStatement */: + case 266 /* CaseClause */: + case 229 /* ThrowStatement */: return parent.expression === node; - case 220: + case 220 /* ForStatement */: var forStatement = parent; - return (forStatement.initializer === node && forStatement.initializer.kind !== 233) || + return (forStatement.initializer === node && forStatement.initializer.kind !== 233 /* VariableDeclarationList */) || forStatement.condition === node || forStatement.incrementor === node; - case 221: - case 222: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: var forInStatement = parent; - return (forInStatement.initializer === node && forInStatement.initializer.kind !== 233) || + return (forInStatement.initializer === node && forInStatement.initializer.kind !== 233 /* VariableDeclarationList */) || forInStatement.expression === node; - case 190: - case 208: + case 190 /* TypeAssertionExpression */: + case 208 /* AsExpression */: return node === parent.expression; - case 211: + case 211 /* TemplateSpan */: return node === parent.expression; - case 147: + case 147 /* ComputedPropertyName */: return node === parent.expression; - case 150: - case 265: - case 264: - case 272: + case 150 /* Decorator */: + case 265 /* JsxExpression */: + case 264 /* JsxSpreadAttribute */: + case 272 /* SpreadAssignment */: return true; - case 207: + case 207 /* ExpressionWithTypeArguments */: return parent.expression === node && isExpressionWithTypeArgumentsInClassExtendsClause(parent); default: return isExpressionNode(parent); @@ -8038,7 +9019,7 @@ var ts; } ts.isInExpressionContext = isInExpressionContext; function isExternalModuleImportEqualsDeclaration(node) { - return node.kind === 243 && node.moduleReference.kind === 254; + return node.kind === 243 /* ImportEqualsDeclaration */ && node.moduleReference.kind === 254 /* ExternalModuleReference */; } ts.isExternalModuleImportEqualsDeclaration = isExternalModuleImportEqualsDeclaration; function getExternalModuleImportEqualsDeclarationExpression(node) { @@ -8047,7 +9028,7 @@ var ts; } ts.getExternalModuleImportEqualsDeclarationExpression = getExternalModuleImportEqualsDeclarationExpression; function isInternalModuleImportEqualsDeclaration(node) { - return node.kind === 243 && node.moduleReference.kind !== 254; + return node.kind === 243 /* ImportEqualsDeclaration */ && node.moduleReference.kind !== 254 /* ExternalModuleReference */; } ts.isInternalModuleImportEqualsDeclaration = isInternalModuleImportEqualsDeclaration; function isSourceFileJavaScript(file) { @@ -8059,15 +9040,15 @@ var ts; } ts.isSourceFileNotJavaScript = isSourceFileNotJavaScript; function isInJavaScriptFile(node) { - return !!node && !!(node.flags & 65536); + return !!node && !!(node.flags & 65536 /* JavaScriptFile */); } ts.isInJavaScriptFile = isInJavaScriptFile; function isInJsonFile(node) { - return !!node && !!(node.flags & 16777216); + return !!node && !!(node.flags & 16777216 /* JsonFile */); } ts.isInJsonFile = isInJsonFile; function isInJSDoc(node) { - return !!node && !!(node.flags & 2097152); + return !!node && !!(node.flags & 2097152 /* JSDoc */); } ts.isInJSDoc = isInJSDoc; function isJSDocIndexSignature(node) { @@ -8075,15 +9056,15 @@ var ts; ts.isIdentifier(node.typeName) && node.typeName.escapedText === "Object" && node.typeArguments && node.typeArguments.length === 2 && - (node.typeArguments[0].kind === 137 || node.typeArguments[0].kind === 134); + (node.typeArguments[0].kind === 137 /* StringKeyword */ || node.typeArguments[0].kind === 134 /* NumberKeyword */); } ts.isJSDocIndexSignature = isJSDocIndexSignature; function isRequireCall(callExpression, checkArgumentIsStringLiteralLike) { - if (callExpression.kind !== 187) { + if (callExpression.kind !== 187 /* CallExpression */) { return false; } var _a = callExpression, expression = _a.expression, args = _a.arguments; - if (expression.kind !== 71 || expression.escapedText !== "require") { + if (expression.kind !== 71 /* Identifier */ || expression.escapedText !== "require") { return false; } if (args.length !== 1) { @@ -8094,11 +9075,11 @@ var ts; } ts.isRequireCall = isRequireCall; function isSingleOrDoubleQuote(charCode) { - return charCode === 39 || charCode === 34; + return charCode === 39 /* singleQuote */ || charCode === 34 /* doubleQuote */; } ts.isSingleOrDoubleQuote = isSingleOrDoubleQuote; function isStringDoubleQuoted(str, sourceFile) { - return getSourceTextOfNodeFromSourceFile(sourceFile, str).charCodeAt(0) === 34; + return getSourceTextOfNodeFromSourceFile(sourceFile, str).charCodeAt(0) === 34 /* doubleQuote */; } ts.isStringDoubleQuoted = isStringDoubleQuoted; function getDeclarationOfJSInitializer(node) { @@ -8111,16 +9092,16 @@ var ts; name = node.parent.name; decl = node.parent; } - else if (ts.isBinaryExpression(node.parent) && node.parent.operatorToken.kind === 58 && node.parent.right === node) { + else if (ts.isBinaryExpression(node.parent) && node.parent.operatorToken.kind === 58 /* EqualsToken */ && node.parent.right === node) { name = node.parent.left; decl = name; } - else if (ts.isBinaryExpression(node.parent) && node.parent.operatorToken.kind === 54) { + else if (ts.isBinaryExpression(node.parent) && node.parent.operatorToken.kind === 54 /* BarBarToken */) { if (ts.isVariableDeclaration(node.parent.parent) && node.parent.parent.initializer === node.parent) { name = node.parent.parent.name; decl = node.parent.parent; } - else if (ts.isBinaryExpression(node.parent.parent) && node.parent.parent.operatorToken.kind === 58 && node.parent.parent.right === node.parent) { + else if (ts.isBinaryExpression(node.parent.parent) && node.parent.parent.operatorToken.kind === 58 /* EqualsToken */ && node.parent.parent.right === node.parent) { name = node.parent.parent.left; decl = name; } @@ -8134,36 +9115,52 @@ var ts; return decl; } ts.getDeclarationOfJSInitializer = getDeclarationOfJSInitializer; + /** Get the initializer, taking into account defaulted Javascript initializers */ function getEffectiveInitializer(node) { if (isInJavaScriptFile(node) && node.initializer && - ts.isBinaryExpression(node.initializer) && node.initializer.operatorToken.kind === 54 && + ts.isBinaryExpression(node.initializer) && node.initializer.operatorToken.kind === 54 /* BarBarToken */ && node.name && isEntityNameExpression(node.name) && isSameEntityName(node.name, node.initializer.left)) { return node.initializer.right; } return node.initializer; } ts.getEffectiveInitializer = getEffectiveInitializer; + /** Get the declaration initializer when it is container-like (See getJavascriptInitializer). */ function getDeclaredJavascriptInitializer(node) { var init = getEffectiveInitializer(node); return init && getJavascriptInitializer(init, isPrototypeAccess(node.name)); } ts.getDeclaredJavascriptInitializer = getDeclaredJavascriptInitializer; + /** + * Get the assignment 'initializer' -- the righthand side-- when the initializer is container-like (See getJavascriptInitializer). + * We treat the right hand side of assignments with container-like initalizers as declarations. + */ function getAssignedJavascriptInitializer(node) { - if (node && node.parent && ts.isBinaryExpression(node.parent) && node.parent.operatorToken.kind === 58) { + if (node && node.parent && ts.isBinaryExpression(node.parent) && node.parent.operatorToken.kind === 58 /* EqualsToken */) { var isPrototypeAssignment = isPrototypeAccess(node.parent.left); return getJavascriptInitializer(node.parent.right, isPrototypeAssignment) || getDefaultedJavascriptInitializer(node.parent.left, node.parent.right, isPrototypeAssignment); } } ts.getAssignedJavascriptInitializer = getAssignedJavascriptInitializer; + /** + * Recognized Javascript container-like initializers are: + * 1. (function() {})() -- IIFEs + * 2. function() { } -- Function expressions + * 3. class { } -- Class expressions + * 4. {} -- Empty object literals + * 5. { ... } -- Non-empty object literals, when used to initialize a prototype, like `C.prototype = { m() { } }` + * + * This function returns the provided initializer, or undefined if it is not valid. + */ function getJavascriptInitializer(initializer, isPrototypeAssignment) { if (ts.isCallExpression(initializer)) { var e = skipParentheses(initializer.expression); - return e.kind === 192 || e.kind === 193 ? initializer : undefined; + return e.kind === 192 /* FunctionExpression */ || e.kind === 193 /* ArrowFunction */ ? initializer : undefined; } - if (initializer.kind === 192 || - initializer.kind === 205 || - initializer.kind === 193) { + if (initializer.kind === 192 /* FunctionExpression */ || + initializer.kind === 205 /* ClassExpression */ || + initializer.kind === 193 /* ArrowFunction */) { return initializer; } if (ts.isObjectLiteralExpression(initializer) && (initializer.properties.length === 0 || isPrototypeAssignment)) { @@ -8171,23 +9168,32 @@ var ts; } } ts.getJavascriptInitializer = getJavascriptInitializer; + /** + * A defaulted Javascript initializer matches the pattern + * `Lhs = Lhs || JavascriptInitializer` + * or `var Lhs = Lhs || JavascriptInitializer` + * + * The second Lhs is required to be the same as the first except that it may be prefixed with + * 'window.', 'global.' or 'self.' The second Lhs is otherwise ignored by the binder and checker. + */ function getDefaultedJavascriptInitializer(name, initializer, isPrototypeAssignment) { - var e = ts.isBinaryExpression(initializer) && initializer.operatorToken.kind === 54 && getJavascriptInitializer(initializer.right, isPrototypeAssignment); + var e = ts.isBinaryExpression(initializer) && initializer.operatorToken.kind === 54 /* BarBarToken */ && getJavascriptInitializer(initializer.right, isPrototypeAssignment); if (e && isSameEntityName(name, initializer.left)) { return e; } } function isDefaultedJavascriptInitializer(node) { var name = ts.isVariableDeclaration(node.parent) ? node.parent.name : - ts.isBinaryExpression(node.parent) && node.parent.operatorToken.kind === 58 ? node.parent.left : + ts.isBinaryExpression(node.parent) && node.parent.operatorToken.kind === 58 /* EqualsToken */ ? node.parent.left : undefined; return name && getJavascriptInitializer(node.right, isPrototypeAccess(name)) && isEntityNameExpression(name) && isSameEntityName(name, node.left); } ts.isDefaultedJavascriptInitializer = isDefaultedJavascriptInitializer; + /** Given a Javascript initializer, return the outer name. That is, the lhs of the assignment or the declaration name. */ function getOuterNameOfJsInitializer(node) { if (ts.isBinaryExpression(node.parent)) { - var parent = (node.parent.operatorToken.kind === 54 && ts.isBinaryExpression(node.parent.parent)) ? node.parent.parent : node.parent; - if (parent.operatorToken.kind === 58 && ts.isIdentifier(parent.left)) { + var parent = (node.parent.operatorToken.kind === 54 /* BarBarToken */ && ts.isBinaryExpression(node.parent.parent)) ? node.parent.parent : node.parent; + if (parent.operatorToken.kind === 58 /* EqualsToken */ && ts.isIdentifier(parent.left)) { return parent.left; } } @@ -8196,12 +9202,21 @@ var ts; } } ts.getOuterNameOfJsInitializer = getOuterNameOfJsInitializer; + /** + * Is the 'declared' name the same as the one in the initializer? + * @return true for identical entity names, as well as ones where the initializer is prefixed with + * 'window', 'self' or 'global'. For example: + * + * var my = my || {} + * var min = window.min || {} + * my.app = self.my.app || class { } + */ function isSameEntityName(name, initializer) { if (ts.isIdentifier(name) && ts.isIdentifier(initializer)) { return name.escapedText === initializer.escapedText; } if (ts.isIdentifier(name) && ts.isPropertyAccessExpression(initializer)) { - return (initializer.expression.kind === 99 || + return (initializer.expression.kind === 99 /* ThisKeyword */ || ts.isIdentifier(initializer.expression) && (initializer.expression.escapedText === "window" || initializer.expression.escapedText === "self" || @@ -8214,7 +9229,7 @@ var ts; return false; } function getRightMostAssignedExpression(node) { - while (isAssignmentExpression(node, true)) { + while (isAssignmentExpression(node, /*excludeCompoundAssignements*/ true)) { node = node.right; } return node; @@ -8228,25 +9243,30 @@ var ts; return ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression) && node.expression.escapedText === "module" && node.name.escapedText === "exports"; } ts.isModuleExportsPropertyAccessExpression = isModuleExportsPropertyAccessExpression; + /// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property + /// assignments we treat as special in the binder function getSpecialPropertyAssignmentKind(expr) { if (!isInJavaScriptFile(expr) || - expr.operatorToken.kind !== 58 || + expr.operatorToken.kind !== 58 /* EqualsToken */ || !ts.isPropertyAccessExpression(expr.left)) { - return 0; + return 0 /* None */; } var lhs = expr.left; - if (lhs.expression.kind === 99) { - return 4; + if (lhs.expression.kind === 99 /* ThisKeyword */) { + return 4 /* ThisProperty */; } else if (ts.isIdentifier(lhs.expression) && lhs.expression.escapedText === "module" && lhs.name.escapedText === "exports") { - return 2; + // module.exports = expr + return 2 /* ModuleExports */; } else if (isEntityNameExpression(lhs.expression)) { if (lhs.name.escapedText === "prototype" && ts.isObjectLiteralExpression(getInitializerOfBinaryExpression(expr))) { - return 6; + // F.prototype = { ... } + return 6 /* Prototype */; } else if (isPrototypeAccess(lhs.expression)) { - return 3; + // F.G....prototype.x = expr + return 3 /* PrototypeProperty */; } var nextToLast = lhs; while (ts.isPropertyAccessExpression(nextToLast.expression)) { @@ -8256,11 +9276,13 @@ var ts; var id = nextToLast.expression; if (id.escapedText === "exports" || id.escapedText === "module" && nextToLast.name.escapedText === "exports") { - return 1; + // exports.name = expr OR module.exports.name = expr + return 1 /* ExportsProperty */; } - return 5; + // F.G...x = expr + return 5 /* Property */; } - return 0; + return 0 /* None */; } ts.getSpecialPropertyAssignmentKind = getSpecialPropertyAssignmentKind; function getInitializerOfBinaryExpression(expr) { @@ -8271,12 +9293,12 @@ var ts; } ts.getInitializerOfBinaryExpression = getInitializerOfBinaryExpression; function isPrototypePropertyAssignment(node) { - return ts.isBinaryExpression(node) && getSpecialPropertyAssignmentKind(node) === 3; + return ts.isBinaryExpression(node) && getSpecialPropertyAssignmentKind(node) === 3 /* PrototypeProperty */; } ts.isPrototypePropertyAssignment = isPrototypePropertyAssignment; function isSpecialPropertyDeclaration(expr) { return isInJavaScriptFile(expr) && - expr.parent && expr.parent.kind === 216 && + expr.parent && expr.parent.kind === 216 /* ExpressionStatement */ && !!ts.getJSDocTypeTag(expr.parent); } ts.isSpecialPropertyDeclaration = isSpecialPropertyDeclaration; @@ -8286,14 +9308,14 @@ var ts; ts.importFromModuleSpecifier = importFromModuleSpecifier; function tryGetImportFromModuleSpecifier(node) { switch (node.parent.kind) { - case 244: - case 250: + case 244 /* ImportDeclaration */: + case 250 /* ExportDeclaration */: return node.parent; - case 254: + case 254 /* ExternalModuleReference */: return node.parent.parent; - case 187: + case 187 /* CallExpression */: return node.parent; - case 178: + case 178 /* LiteralType */: ts.Debug.assert(ts.isStringLiteral(node)); return ts.tryCast(node.parent.parent, ts.isImportTypeNode); default: @@ -8303,12 +9325,12 @@ var ts; ts.tryGetImportFromModuleSpecifier = tryGetImportFromModuleSpecifier; function getExternalModuleName(node) { switch (node.kind) { - case 244: - case 250: + case 244 /* ImportDeclaration */: + case 250 /* ExportDeclaration */: return node.moduleSpecifier; - case 243: - return node.moduleReference.kind === 254 ? node.moduleReference.expression : undefined; - case 179: + case 243 /* ImportEqualsDeclaration */: + return node.moduleReference.kind === 254 /* ExternalModuleReference */ ? node.moduleReference.expression : undefined; + case 179 /* ImportType */: return isLiteralImportTypeNode(node) ? node.argument.literal : undefined; default: return ts.Debug.assertNever(node); @@ -8317,11 +9339,11 @@ var ts; ts.getExternalModuleName = getExternalModuleName; function getNamespaceDeclarationNode(node) { switch (node.kind) { - case 244: + case 244 /* ImportDeclaration */: return node.importClause && ts.tryCast(node.importClause.namedBindings, ts.isNamespaceImport); - case 243: + case 243 /* ImportEqualsDeclaration */: return node; - case 250: + case 250 /* ExportDeclaration */: return undefined; default: return ts.Debug.assertNever(node); @@ -8329,19 +9351,19 @@ var ts; } ts.getNamespaceDeclarationNode = getNamespaceDeclarationNode; function isDefaultImport(node) { - return node.kind === 244 && !!node.importClause && !!node.importClause.name; + return node.kind === 244 /* ImportDeclaration */ && !!node.importClause && !!node.importClause.name; } ts.isDefaultImport = isDefaultImport; function hasQuestionToken(node) { if (node) { switch (node.kind) { - case 149: - case 154: - case 153: - case 271: - case 270: - case 152: - case 151: + case 149 /* Parameter */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 271 /* ShorthandPropertyAssignment */: + case 270 /* PropertyAssignment */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: return node.questionToken !== undefined; } } @@ -8349,14 +9371,14 @@ var ts; } ts.hasQuestionToken = hasQuestionToken; function isJSDocConstructSignature(node) { - return node.kind === 284 && + return node.kind === 284 /* JSDocFunctionType */ && node.parameters.length > 0 && node.parameters[0].name && node.parameters[0].name.escapedText === "new"; } ts.isJSDocConstructSignature = isJSDocConstructSignature; function isJSDocTypeAlias(node) { - return node.kind === 298 || node.kind === 292; + return node.kind === 298 /* JSDocTypedefTag */ || node.kind === 292 /* JSDocCallbackTag */; } ts.isJSDocTypeAlias = isJSDocTypeAlias; function isTypeAlias(node) { @@ -8366,27 +9388,27 @@ var ts; function getSourceOfAssignment(node) { return ts.isExpressionStatement(node) && node.expression && ts.isBinaryExpression(node.expression) && - node.expression.operatorToken.kind === 58 + node.expression.operatorToken.kind === 58 /* EqualsToken */ ? node.expression.right : undefined; } function getSourceOfDefaultedAssignment(node) { return ts.isExpressionStatement(node) && ts.isBinaryExpression(node.expression) && - getSpecialPropertyAssignmentKind(node.expression) !== 0 && + getSpecialPropertyAssignmentKind(node.expression) !== 0 /* None */ && ts.isBinaryExpression(node.expression.right) && - node.expression.right.operatorToken.kind === 54 + node.expression.right.operatorToken.kind === 54 /* BarBarToken */ ? node.expression.right.right : undefined; } function getSingleInitializerOfVariableStatementOrPropertyDeclaration(node) { switch (node.kind) { - case 214: + case 214 /* VariableStatement */: var v = getSingleVariableOfVariableStatement(node); return v && v.initializer; - case 152: + case 152 /* PropertyDeclaration */: return node.initializer; - case 270: + case 270 /* PropertyAssignment */: return node.initializer; } } @@ -8396,7 +9418,7 @@ var ts; function getNestedModuleDeclaration(node) { return ts.isModuleDeclaration(node) && node.body && - node.body.kind === 239 + node.body.kind === 239 /* ModuleDeclaration */ ? node.body : undefined; } @@ -8408,9 +9430,15 @@ var ts; var parent = node.parent; if (!parent) return; - if (parent.kind === 270 || parent.kind === 152 || getNestedModuleDeclaration(parent)) { + if (parent.kind === 270 /* PropertyAssignment */ || parent.kind === 152 /* PropertyDeclaration */ || getNestedModuleDeclaration(parent)) { getJSDocCommentsAndTagsWorker(parent); } + // Try to recognize this pattern when node is initializer of variable declaration and JSDoc comments are on containing variable statement. + // /** + // * @param {number} name + // * @returns {number} + // */ + // var x = function(name) { return name.length; } if (parent.parent && (getSingleVariableOfVariableStatement(parent.parent) === node)) { getJSDocCommentsAndTagsWorker(parent.parent); } @@ -8420,9 +9448,9 @@ var ts; getSourceOfDefaultedAssignment(parent.parent.parent))) { getJSDocCommentsAndTagsWorker(parent.parent.parent); } - if (ts.isBinaryExpression(node) && node.operatorToken.kind === 58 || - ts.isBinaryExpression(parent) && parent.operatorToken.kind === 58 || - node.kind === 185 && node.parent && node.parent.kind === 216) { + if (ts.isBinaryExpression(node) && node.operatorToken.kind === 58 /* EqualsToken */ || + ts.isBinaryExpression(parent) && parent.operatorToken.kind === 58 /* EqualsToken */ || + node.kind === 185 /* PropertyAccessExpression */ && node.parent && node.parent.kind === 216 /* ExpressionStatement */) { if (ts.isBinaryExpression(parent)) { getJSDocCommentsAndTagsWorker(parent.parent); } @@ -8430,7 +9458,8 @@ var ts; getJSDocCommentsAndTagsWorker(parent); } } - if (node.kind === 149) { + // Pull parameter comments from declaring function as well + if (node.kind === 149 /* Parameter */) { result = ts.addRange(result, ts.getJSDocParameterTags(node)); } if (isVariableLike(node) && ts.hasInitializer(node) && node.initializer !== hostNode && ts.hasJSDocNodes(node.initializer)) { @@ -8442,6 +9471,7 @@ var ts; } } ts.getJSDocCommentsAndTags = getJSDocCommentsAndTags; + /** Does the opposite of `getJSDocParameterTags`: given a JSDoc parameter, finds the parameter corresponding to it. */ function getParameterSymbolFromJSDoc(node) { if (node.symbol) { return node.symbol; @@ -8454,7 +9484,7 @@ var ts; if (!decl) { return undefined; } - var parameter = ts.find(decl.parameters, function (p) { return p.name.kind === 71 && p.name.escapedText === name; }); + var parameter = ts.find(decl.parameters, function (p) { return p.name.kind === 71 /* Identifier */ && p.name.escapedText === name; }); return parameter && parameter.symbol; } ts.getParameterSymbolFromJSDoc = getParameterSymbolFromJSDoc; @@ -8489,7 +9519,7 @@ var ts; ts.hasRestParameter = hasRestParameter; function isRestParameter(node) { var type = ts.isJSDocParameterTag(node) ? (node.typeExpression && node.typeExpression.type) : node.type; - return node.dotDotDotToken !== undefined || !!type && type.kind === 285; + return node.dotDotDotToken !== undefined || !!type && type.kind === 285 /* JSDocVariadicType */; } ts.isRestParameter = isRestParameter; var AssignmentKind; @@ -8502,65 +9532,73 @@ var ts; var parent = node.parent; while (true) { switch (parent.kind) { - case 200: + case 200 /* BinaryExpression */: var binaryOperator = parent.operatorToken.kind; return isAssignmentOperator(binaryOperator) && parent.left === node ? - binaryOperator === 58 ? 1 : 2 : - 0; - case 198: - case 199: + binaryOperator === 58 /* EqualsToken */ ? 1 /* Definite */ : 2 /* Compound */ : + 0 /* None */; + case 198 /* PrefixUnaryExpression */: + case 199 /* PostfixUnaryExpression */: var unaryOperator = parent.operator; - return unaryOperator === 43 || unaryOperator === 44 ? 2 : 0; - case 221: - case 222: - return parent.initializer === node ? 1 : 0; - case 191: - case 183: - case 204: - case 209: + return unaryOperator === 43 /* PlusPlusToken */ || unaryOperator === 44 /* MinusMinusToken */ ? 2 /* Compound */ : 0 /* None */; + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + return parent.initializer === node ? 1 /* Definite */ : 0 /* None */; + case 191 /* ParenthesizedExpression */: + case 183 /* ArrayLiteralExpression */: + case 204 /* SpreadElement */: + case 209 /* NonNullExpression */: node = parent; break; - case 271: + case 271 /* ShorthandPropertyAssignment */: if (parent.name !== node) { - return 0; + return 0 /* None */; } node = parent.parent; break; - case 270: + case 270 /* PropertyAssignment */: if (parent.name === node) { - return 0; + return 0 /* None */; } node = parent.parent; break; default: - return 0; + return 0 /* None */; } parent = node.parent; } } ts.getAssignmentTargetKind = getAssignmentTargetKind; + // A node is an assignment target if it is on the left hand side of an '=' token, if it is parented by a property + // assignment in an object literal that is an assignment target, or if it is parented by an array literal that is + // an assignment target. Examples include 'a = xxx', '{ p: a } = xxx', '[{ a }] = xxx'. + // (Note that `p` is not a target in the above examples, only `a`.) function isAssignmentTarget(node) { - return getAssignmentTargetKind(node) !== 0; + return getAssignmentTargetKind(node) !== 0 /* None */; } ts.isAssignmentTarget = isAssignmentTarget; + /** + * Indicates whether a node could contain a `var` VariableDeclarationList that contributes to + * the same `var` declaration scope as the node's parent. + */ function isNodeWithPossibleHoistedDeclaration(node) { switch (node.kind) { - case 213: - case 214: - case 226: - case 217: - case 227: - case 241: - case 266: - case 267: - case 228: - case 220: - case 221: - case 222: - case 218: - case 219: - case 230: - case 269: + case 213 /* Block */: + case 214 /* VariableStatement */: + case 226 /* WithStatement */: + case 217 /* IfStatement */: + case 227 /* SwitchStatement */: + case 241 /* CaseBlock */: + case 266 /* CaseClause */: + case 267 /* DefaultClause */: + case 228 /* LabeledStatement */: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 218 /* DoStatement */: + case 219 /* WhileStatement */: + case 230 /* TryStatement */: + case 269 /* CatchClause */: return true; } return false; @@ -8577,26 +9615,27 @@ var ts; return node; } function walkUpParenthesizedTypes(node) { - return walkUp(node, 173); + return walkUp(node, 173 /* ParenthesizedType */); } ts.walkUpParenthesizedTypes = walkUpParenthesizedTypes; function walkUpParenthesizedExpressions(node) { - return walkUp(node, 191); + return walkUp(node, 191 /* ParenthesizedExpression */); } ts.walkUpParenthesizedExpressions = walkUpParenthesizedExpressions; function skipParentheses(node) { - while (node.kind === 191) { + while (node.kind === 191 /* ParenthesizedExpression */) { node = node.expression; } return node; } ts.skipParentheses = skipParentheses; + // a node is delete target iff. it is PropertyAccessExpression/ElementAccessExpression with parentheses skipped function isDeleteTarget(node) { - if (node.kind !== 185 && node.kind !== 186) { + if (node.kind !== 185 /* PropertyAccessExpression */ && node.kind !== 186 /* ElementAccessExpression */) { return false; } node = walkUpParenthesizedExpressions(node.parent); - return node && node.kind === 194; + return node && node.kind === 194 /* DeleteExpression */; } ts.isDeleteTarget = isDeleteTarget; function isNodeDescendantOf(node, ancestor) { @@ -8608,15 +9647,17 @@ var ts; return false; } ts.isNodeDescendantOf = isNodeDescendantOf; + // True if `name` is the name of a declaration node function isDeclarationName(name) { return !ts.isSourceFile(name) && !ts.isBindingPattern(name) && ts.isDeclaration(name.parent) && name.parent.name === name; } ts.isDeclarationName = isDeclarationName; + // See GH#16030 function isAnyDeclarationName(name) { switch (name.kind) { - case 71: - case 9: - case 8: { + case 71 /* Identifier */: + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: { var parent = name.parent; if (ts.isDeclaration(parent)) { return parent.name === name; @@ -8627,7 +9668,7 @@ var ts; } else { var binExp = name.parent.parent; - return ts.isBinaryExpression(binExp) && getSpecialPropertyAssignmentKind(binExp) !== 0 && ts.getNameOfDeclaration(binExp) === name; + return ts.isBinaryExpression(binExp) && getSpecialPropertyAssignmentKind(binExp) !== 0 /* None */ && ts.getNameOfDeclaration(binExp) === name; } } default: @@ -8636,51 +9677,64 @@ var ts; } ts.isAnyDeclarationName = isAnyDeclarationName; function isLiteralComputedPropertyDeclarationName(node) { - return (node.kind === 9 || node.kind === 8) && - node.parent.kind === 147 && + return (node.kind === 9 /* StringLiteral */ || node.kind === 8 /* NumericLiteral */) && + node.parent.kind === 147 /* ComputedPropertyName */ && ts.isDeclaration(node.parent.parent); } ts.isLiteralComputedPropertyDeclarationName = isLiteralComputedPropertyDeclarationName; + // Return true if the given identifier is classified as an IdentifierName function isIdentifierName(node) { var parent = node.parent; switch (parent.kind) { - case 152: - case 151: - case 154: - case 153: - case 156: - case 157: - case 273: - case 270: - case 185: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 273 /* EnumMember */: + case 270 /* PropertyAssignment */: + case 185 /* PropertyAccessExpression */: + // Name in member declaration or property name in property access return parent.name === node; - case 146: + case 146 /* QualifiedName */: + // Name on right hand side of dot in a type query or type reference if (parent.right === node) { - while (parent.kind === 146) { + while (parent.kind === 146 /* QualifiedName */) { parent = parent.parent; } - return parent.kind === 165 || parent.kind === 162; + return parent.kind === 165 /* TypeQuery */ || parent.kind === 162 /* TypeReference */; } return false; - case 182: - case 248: + case 182 /* BindingElement */: + case 248 /* ImportSpecifier */: + // Property name in binding element or import specifier return parent.propertyName === node; - case 252: - case 262: + case 252 /* ExportSpecifier */: + case 262 /* JsxAttribute */: + // Any name in an export specifier or JSX Attribute return true; } return false; } ts.isIdentifierName = isIdentifierName; + // An alias symbol is created by one of the following declarations: + // import = ... + // import from ... + // import * as from ... + // import { x as } from ... + // export { x as } from ... + // export = + // export default function isAliasSymbolDeclaration(node) { - return node.kind === 243 || - node.kind === 242 || - node.kind === 245 && !!node.name || - node.kind === 246 || - node.kind === 248 || - node.kind === 252 || - node.kind === 249 && exportAssignmentIsAlias(node) || - ts.isBinaryExpression(node) && getSpecialPropertyAssignmentKind(node) === 2; + return node.kind === 243 /* ImportEqualsDeclaration */ || + node.kind === 242 /* NamespaceExportDeclaration */ || + node.kind === 245 /* ImportClause */ && !!node.name || + node.kind === 246 /* NamespaceImport */ || + node.kind === 248 /* ImportSpecifier */ || + node.kind === 252 /* ExportSpecifier */ || + node.kind === 249 /* ExportAssignment */ && exportAssignmentIsAlias(node) || + ts.isBinaryExpression(node) && getSpecialPropertyAssignmentKind(node) === 2 /* ModuleExports */; } ts.isAliasSymbolDeclaration = isAliasSymbolDeclaration; function exportAssignmentIsAlias(node) { @@ -8689,15 +9743,16 @@ var ts; } ts.exportAssignmentIsAlias = exportAssignmentIsAlias; function getClassExtendsHeritageClauseElement(node) { - var heritageClause = getHeritageClause(node.heritageClauses, 85); + var heritageClause = getHeritageClause(node.heritageClauses, 85 /* ExtendsKeyword */); return heritageClause && heritageClause.types.length > 0 ? heritageClause.types[0] : undefined; } ts.getClassExtendsHeritageClauseElement = getClassExtendsHeritageClauseElement; function getClassImplementsHeritageClauseElements(node) { - var heritageClause = getHeritageClause(node.heritageClauses, 108); + var heritageClause = getHeritageClause(node.heritageClauses, 108 /* ImplementsKeyword */); return heritageClause ? heritageClause.types : undefined; } ts.getClassImplementsHeritageClauseElements = getClassImplementsHeritageClauseElements; + /** Returns the node in an `extends` or `implements` clause of a class or interface. */ function getAllSuperTypeNodes(node) { return ts.isInterfaceDeclaration(node) ? getInterfaceBaseTypeNodes(node) || ts.emptyArray : ts.isClassLike(node) ? ts.concatenate(ts.singleElementArray(getClassExtendsHeritageClauseElement(node)), getClassImplementsHeritageClauseElements(node)) || ts.emptyArray @@ -8705,7 +9760,7 @@ var ts; } ts.getAllSuperTypeNodes = getAllSuperTypeNodes; function getInterfaceBaseTypeNodes(node) { - var heritageClause = getHeritageClause(node.heritageClauses, 85); + var heritageClause = getHeritageClause(node.heritageClauses, 85 /* ExtendsKeyword */); return heritageClause ? heritageClause.types : undefined; } ts.getInterfaceBaseTypeNodes = getInterfaceBaseTypeNodes; @@ -8739,11 +9794,11 @@ var ts; } ts.getAncestor = getAncestor; function isKeyword(token) { - return 72 <= token && token <= 145; + return 72 /* FirstKeyword */ <= token && token <= 145 /* LastKeyword */; } ts.isKeyword = isKeyword; function isContextualKeyword(token) { - return 117 <= token && token <= 145; + return 117 /* FirstContextualKeyword */ <= token && token <= 145 /* LastContextualKeyword */; } ts.isContextualKeyword = isContextualKeyword; function isNonContextualKeyword(token) { @@ -8756,7 +9811,7 @@ var ts; } ts.isStringANonContextualKeyword = isStringANonContextualKeyword; function isTrivia(token) { - return 2 <= token && token <= 7; + return 2 /* FirstTriviaToken */ <= token && token <= 7 /* LastTriviaToken */; } ts.isTrivia = isTrivia; var FunctionFlags; @@ -8769,75 +9824,88 @@ var ts; })(FunctionFlags = ts.FunctionFlags || (ts.FunctionFlags = {})); function getFunctionFlags(node) { if (!node) { - return 4; + return 4 /* Invalid */; } - var flags = 0; + var flags = 0 /* Normal */; switch (node.kind) { - case 234: - case 192: - case 154: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 154 /* MethodDeclaration */: if (node.asteriskToken) { - flags |= 1; + flags |= 1 /* Generator */; } - case 193: - if (hasModifier(node, 256)) { - flags |= 2; + // falls through + case 193 /* ArrowFunction */: + if (hasModifier(node, 256 /* Async */)) { + flags |= 2 /* Async */; } break; } if (!node.body) { - flags |= 4; + flags |= 4 /* Invalid */; } return flags; } ts.getFunctionFlags = getFunctionFlags; function isAsyncFunction(node) { switch (node.kind) { - case 234: - case 192: - case 193: - case 154: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 154 /* MethodDeclaration */: return node.body !== undefined && node.asteriskToken === undefined - && hasModifier(node, 256); + && hasModifier(node, 256 /* Async */); } return false; } ts.isAsyncFunction = isAsyncFunction; function isStringOrNumericLiteral(node) { var kind = node.kind; - return kind === 9 - || kind === 8; + return kind === 9 /* StringLiteral */ + || kind === 8 /* NumericLiteral */; } ts.isStringOrNumericLiteral = isStringOrNumericLiteral; + /** + * A declaration has a dynamic name if both of the following are true: + * 1. The declaration has a computed property name + * 2. The computed name is *not* expressed as Symbol., where name + * is a property of the Symbol constructor that denotes a built in + * Symbol. + */ function hasDynamicName(declaration) { var name = ts.getNameOfDeclaration(declaration); return !!name && isDynamicName(name); } ts.hasDynamicName = hasDynamicName; function isDynamicName(name) { - return name.kind === 147 && + return name.kind === 147 /* ComputedPropertyName */ && !isStringOrNumericLiteral(name.expression) && !isWellKnownSymbolSyntactically(name.expression); } ts.isDynamicName = isDynamicName; + /** + * Checks if the expression is of the form: + * Symbol.name + * where Symbol is literally the word "Symbol", and name is any identifierName + */ function isWellKnownSymbolSyntactically(node) { return ts.isPropertyAccessExpression(node) && isESSymbolIdentifier(node.expression); } ts.isWellKnownSymbolSyntactically = isWellKnownSymbolSyntactically; function getPropertyNameForPropertyNameNode(name) { - if (name.kind === 71) { + if (name.kind === 71 /* Identifier */) { return name.escapedText; } - if (name.kind === 9 || name.kind === 8) { + if (name.kind === 9 /* StringLiteral */ || name.kind === 8 /* NumericLiteral */) { return escapeLeadingUnderscores(name.text); } - if (name.kind === 147) { + if (name.kind === 147 /* ComputedPropertyName */) { var nameExpression = name.expression; if (isWellKnownSymbolSyntactically(nameExpression)) { return getPropertyNameForKnownSymbolName(ts.idText(nameExpression.name)); } - else if (nameExpression.kind === 9 || nameExpression.kind === 8) { + else if (nameExpression.kind === 9 /* StringLiteral */ || nameExpression.kind === 8 /* NumericLiteral */) { return escapeLeadingUnderscores(nameExpression.text); } } @@ -8846,10 +9914,10 @@ var ts; ts.getPropertyNameForPropertyNameNode = getPropertyNameForPropertyNameNode; function isPropertyNameLiteral(node) { switch (node.kind) { - case 71: - case 9: - case 13: - case 8: + case 71 /* Identifier */: + case 9 /* StringLiteral */: + case 13 /* NoSubstitutionTemplateLiteral */: + case 8 /* NumericLiteral */: return true; default: return false; @@ -8857,11 +9925,11 @@ var ts; } ts.isPropertyNameLiteral = isPropertyNameLiteral; function getTextOfIdentifierOrLiteral(node) { - return node.kind === 71 ? ts.idText(node) : node.text; + return node.kind === 71 /* Identifier */ ? ts.idText(node) : node.text; } ts.getTextOfIdentifierOrLiteral = getTextOfIdentifierOrLiteral; function getEscapedTextOfIdentifierOrLiteral(node) { - return node.kind === 71 ? node.escapedText : escapeLeadingUnderscores(node.text); + return node.kind === 71 /* Identifier */ ? node.escapedText : escapeLeadingUnderscores(node.text); } ts.getEscapedTextOfIdentifierOrLiteral = getEscapedTextOfIdentifierOrLiteral; function getPropertyNameForKnownSymbolName(symbolName) { @@ -8872,8 +9940,11 @@ var ts; return ts.startsWith(symbol.escapedName, "__@"); } ts.isKnownSymbol = isKnownSymbol; + /** + * Includes the word "Symbol" with unicode escapes + */ function isESSymbolIdentifier(node) { - return node.kind === 71 && node.escapedText === "Symbol"; + return node.kind === 71 /* Identifier */ && node.escapedText === "Symbol"; } ts.isESSymbolIdentifier = isESSymbolIdentifier; function isPushOrUnshiftIdentifier(node) { @@ -8882,11 +9953,11 @@ var ts; ts.isPushOrUnshiftIdentifier = isPushOrUnshiftIdentifier; function isParameterDeclaration(node) { var root = getRootDeclaration(node); - return root.kind === 149; + return root.kind === 149 /* Parameter */; } ts.isParameterDeclaration = isParameterDeclaration; function getRootDeclaration(node) { - while (node.kind === 182) { + while (node.kind === 182 /* BindingElement */) { node = node.parent.parent; } return node; @@ -8894,15 +9965,15 @@ var ts; ts.getRootDeclaration = getRootDeclaration; function nodeStartsNewLexicalEnvironment(node) { var kind = node.kind; - return kind === 155 - || kind === 192 - || kind === 234 - || kind === 193 - || kind === 154 - || kind === 156 - || kind === 157 - || kind === 239 - || kind === 274; + return kind === 155 /* Constructor */ + || kind === 192 /* FunctionExpression */ + || kind === 234 /* FunctionDeclaration */ + || kind === 193 /* ArrowFunction */ + || kind === 154 /* MethodDeclaration */ + || kind === 156 /* GetAccessor */ + || kind === 157 /* SetAccessor */ + || kind === 239 /* ModuleDeclaration */ + || kind === 274 /* SourceFile */; } ts.nodeStartsNewLexicalEnvironment = nodeStartsNewLexicalEnvironment; function nodeIsSynthesized(range) { @@ -8921,55 +9992,55 @@ var ts; })(Associativity = ts.Associativity || (ts.Associativity = {})); function getExpressionAssociativity(expression) { var operator = getOperator(expression); - var hasArguments = expression.kind === 188 && expression.arguments !== undefined; + var hasArguments = expression.kind === 188 /* NewExpression */ && expression.arguments !== undefined; return getOperatorAssociativity(expression.kind, operator, hasArguments); } ts.getExpressionAssociativity = getExpressionAssociativity; function getOperatorAssociativity(kind, operator, hasArguments) { switch (kind) { - case 188: - return hasArguments ? 0 : 1; - case 198: - case 195: - case 196: - case 194: - case 197: - case 201: - case 203: - return 1; - case 200: + case 188 /* NewExpression */: + return hasArguments ? 0 /* Left */ : 1 /* Right */; + case 198 /* PrefixUnaryExpression */: + case 195 /* TypeOfExpression */: + case 196 /* VoidExpression */: + case 194 /* DeleteExpression */: + case 197 /* AwaitExpression */: + case 201 /* ConditionalExpression */: + case 203 /* YieldExpression */: + return 1 /* Right */; + case 200 /* BinaryExpression */: switch (operator) { - case 40: - case 58: - case 59: - case 60: - case 62: - case 61: - case 63: - case 64: - case 65: - case 66: - case 67: - case 68: - case 70: - case 69: - return 1; + case 40 /* AsteriskAsteriskToken */: + case 58 /* EqualsToken */: + case 59 /* PlusEqualsToken */: + case 60 /* MinusEqualsToken */: + case 62 /* AsteriskAsteriskEqualsToken */: + case 61 /* AsteriskEqualsToken */: + case 63 /* SlashEqualsToken */: + case 64 /* PercentEqualsToken */: + case 65 /* LessThanLessThanEqualsToken */: + case 66 /* GreaterThanGreaterThanEqualsToken */: + case 67 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + case 68 /* AmpersandEqualsToken */: + case 70 /* CaretEqualsToken */: + case 69 /* BarEqualsToken */: + return 1 /* Right */; } } - return 0; + return 0 /* Left */; } ts.getOperatorAssociativity = getOperatorAssociativity; function getExpressionPrecedence(expression) { var operator = getOperator(expression); - var hasArguments = expression.kind === 188 && expression.arguments !== undefined; + var hasArguments = expression.kind === 188 /* NewExpression */ && expression.arguments !== undefined; return getOperatorPrecedence(expression.kind, operator, hasArguments); } ts.getExpressionPrecedence = getExpressionPrecedence; function getOperator(expression) { - if (expression.kind === 200) { + if (expression.kind === 200 /* BinaryExpression */) { return expression.operatorToken.kind; } - else if (expression.kind === 198 || expression.kind === 199) { + else if (expression.kind === 198 /* PrefixUnaryExpression */ || expression.kind === 199 /* PostfixUnaryExpression */) { return expression.operator; } else { @@ -8979,122 +10050,125 @@ var ts; ts.getOperator = getOperator; function getOperatorPrecedence(nodeKind, operatorKind, hasArguments) { switch (nodeKind) { - case 303: + case 303 /* CommaListExpression */: return 0; - case 204: + case 204 /* SpreadElement */: return 1; - case 203: + case 203 /* YieldExpression */: return 2; - case 201: + case 201 /* ConditionalExpression */: return 4; - case 200: + case 200 /* BinaryExpression */: switch (operatorKind) { - case 26: + case 26 /* CommaToken */: return 0; - case 58: - case 59: - case 60: - case 62: - case 61: - case 63: - case 64: - case 65: - case 66: - case 67: - case 68: - case 70: - case 69: + case 58 /* EqualsToken */: + case 59 /* PlusEqualsToken */: + case 60 /* MinusEqualsToken */: + case 62 /* AsteriskAsteriskEqualsToken */: + case 61 /* AsteriskEqualsToken */: + case 63 /* SlashEqualsToken */: + case 64 /* PercentEqualsToken */: + case 65 /* LessThanLessThanEqualsToken */: + case 66 /* GreaterThanGreaterThanEqualsToken */: + case 67 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + case 68 /* AmpersandEqualsToken */: + case 70 /* CaretEqualsToken */: + case 69 /* BarEqualsToken */: return 3; default: return getBinaryOperatorPrecedence(operatorKind); } - case 198: - case 195: - case 196: - case 194: - case 197: + case 198 /* PrefixUnaryExpression */: + case 195 /* TypeOfExpression */: + case 196 /* VoidExpression */: + case 194 /* DeleteExpression */: + case 197 /* AwaitExpression */: return 16; - case 199: + case 199 /* PostfixUnaryExpression */: return 17; - case 187: + case 187 /* CallExpression */: return 18; - case 188: + case 188 /* NewExpression */: return hasArguments ? 19 : 18; - case 189: - case 185: - case 186: + case 189 /* TaggedTemplateExpression */: + case 185 /* PropertyAccessExpression */: + case 186 /* ElementAccessExpression */: return 19; - case 99: - case 97: - case 71: - case 95: - case 101: - case 86: - case 8: - case 9: - case 183: - case 184: - case 192: - case 193: - case 205: - case 255: - case 256: - case 259: - case 12: - case 13: - case 202: - case 191: - case 206: + case 99 /* ThisKeyword */: + case 97 /* SuperKeyword */: + case 71 /* Identifier */: + case 95 /* NullKeyword */: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: + case 183 /* ArrayLiteralExpression */: + case 184 /* ObjectLiteralExpression */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 205 /* ClassExpression */: + case 255 /* JsxElement */: + case 256 /* JsxSelfClosingElement */: + case 259 /* JsxFragment */: + case 12 /* RegularExpressionLiteral */: + case 13 /* NoSubstitutionTemplateLiteral */: + case 202 /* TemplateExpression */: + case 191 /* ParenthesizedExpression */: + case 206 /* OmittedExpression */: return 20; default: return -1; } } ts.getOperatorPrecedence = getOperatorPrecedence; + /* @internal */ function getBinaryOperatorPrecedence(kind) { switch (kind) { - case 54: + case 54 /* BarBarToken */: return 5; - case 53: + case 53 /* AmpersandAmpersandToken */: return 6; - case 49: + case 49 /* BarToken */: return 7; - case 50: + case 50 /* CaretToken */: return 8; - case 48: + case 48 /* AmpersandToken */: return 9; - case 32: - case 33: - case 34: - case 35: + case 32 /* EqualsEqualsToken */: + case 33 /* ExclamationEqualsToken */: + case 34 /* EqualsEqualsEqualsToken */: + case 35 /* ExclamationEqualsEqualsToken */: return 10; - case 27: - case 29: - case 30: - case 31: - case 93: - case 92: - case 118: + case 27 /* LessThanToken */: + case 29 /* GreaterThanToken */: + case 30 /* LessThanEqualsToken */: + case 31 /* GreaterThanEqualsToken */: + case 93 /* InstanceOfKeyword */: + case 92 /* InKeyword */: + case 118 /* AsKeyword */: return 11; - case 45: - case 46: - case 47: + case 45 /* LessThanLessThanToken */: + case 46 /* GreaterThanGreaterThanToken */: + case 47 /* GreaterThanGreaterThanGreaterThanToken */: return 12; - case 37: - case 38: + case 37 /* PlusToken */: + case 38 /* MinusToken */: return 13; - case 39: - case 41: - case 42: + case 39 /* AsteriskToken */: + case 41 /* SlashToken */: + case 42 /* PercentToken */: return 14; - case 40: + case 40 /* AsteriskAsteriskToken */: return 15; } + // -1 is lower than all other precedences. Returning it will cause binary expression + // parsing to stop. return -1; } ts.getBinaryOperatorPrecedence = getBinaryOperatorPrecedence; function createDiagnosticCollection() { - var nonFileDiagnostics = []; + var nonFileDiagnostics = []; // See GH#19873 var filesWithDiagnostics = []; var fileDiagnostics = ts.createMap(); var hasReadNonFileDiagnostics = false; @@ -9112,12 +10186,13 @@ var ts; if (diagnostic.file) { diagnostics = fileDiagnostics.get(diagnostic.file.fileName); if (!diagnostics) { - diagnostics = []; + diagnostics = []; // See GH#19873 fileDiagnostics.set(diagnostic.file.fileName, diagnostics); ts.insertSorted(filesWithDiagnostics, diagnostic.file.fileName, ts.compareStringsCaseSensitive); } } else { + // If we've already read the non-file diagnostics, do not modify the existing array. if (hasReadNonFileDiagnostics) { hasReadNonFileDiagnostics = false; nonFileDiagnostics = nonFileDiagnostics.slice(); @@ -9143,6 +10218,11 @@ var ts; } } ts.createDiagnosticCollection = createDiagnosticCollection; + // This consists of the first 19 unprintable ASCII characters, canonical escapes, lineSeparator, + // paragraphSeparator, and nextLine. The latter three are just desirable to suppress new lines in + // the language service. These characters should be escaped when printing, and if any characters are added, + // the map below must be updated. Note that this regexp *does not* include the 'delete' character. + // There is no reason for this other than that JSON.stringify does not handle it either. var doubleQuoteEscapedCharsRegExp = /[\\\"\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g; var singleQuoteEscapedCharsRegExp = /[\\\'\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g; var backtickQuoteEscapedCharsRegExp = /[\\\`\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g; @@ -9159,28 +10239,35 @@ var ts; "\`": "\\\`", "\u2028": "\\u2028", "\u2029": "\\u2029", - "\u0085": "\\u0085" + "\u0085": "\\u0085" // nextLine }); + /** + * Based heavily on the abstract 'Quote'/'QuoteJSONString' operation from ECMA-262 (24.3.2.2), + * but augmented for a few select characters (e.g. lineSeparator, paragraphSeparator, nextLine) + * Note that this doesn't actually wrap the input in double quotes. + */ function escapeString(s, quoteChar) { - var escapedCharsRegExp = quoteChar === 96 ? backtickQuoteEscapedCharsRegExp : - quoteChar === 39 ? singleQuoteEscapedCharsRegExp : + var escapedCharsRegExp = quoteChar === 96 /* backtick */ ? backtickQuoteEscapedCharsRegExp : + quoteChar === 39 /* singleQuote */ ? singleQuoteEscapedCharsRegExp : doubleQuoteEscapedCharsRegExp; return s.replace(escapedCharsRegExp, getReplacement); } ts.escapeString = escapeString; function getReplacement(c, offset, input) { - if (c.charCodeAt(0) === 0) { + if (c.charCodeAt(0) === 0 /* nullCharacter */) { var lookAhead = input.charCodeAt(offset + c.length); - if (lookAhead >= 48 && lookAhead <= 57) { + if (lookAhead >= 48 /* _0 */ && lookAhead <= 57 /* _9 */) { + // If the null character is followed by digits, print as a hex escape to prevent the result from parsing as an octal (which is forbidden in strict mode) return "\\x00"; } + // Otherwise, keep printing a literal \0 for the null character return "\\0"; } return escapedCharsMap.get(c) || get16BitUnicodeEscapeSequence(c.charCodeAt(0)); } function isIntrinsicJsxName(name) { var ch = name.charCodeAt(0); - return (ch >= 97 && ch <= 122) || name.indexOf("-") > -1; + return (ch >= 97 /* a */ && ch <= 122 /* z */) || name.indexOf("-") > -1; } ts.isIntrinsicJsxName = isIntrinsicJsxName; function get16BitUnicodeEscapeSequence(charCode) { @@ -9191,6 +10278,8 @@ var ts; var nonAsciiCharacters = /[^\u0000-\u007F]/g; function escapeNonAsciiString(s, quoteChar) { s = escapeString(s, quoteChar); + // Replace non-ASCII characters with '\uNNNN' escapes if any exist. + // Otherwise just return the original string. return nonAsciiCharacters.test(s) ? s.replace(nonAsciiCharacters, function (c) { return get16BitUnicodeEscapeSequence(c.charCodeAt(0)); }) : s; @@ -9309,11 +10398,14 @@ var ts; return getResolvedExternalModuleName(host, file); } ts.getExternalModuleNameFromDeclaration = getExternalModuleNameFromDeclaration; + /** + * Resolves a local path to a path which is absolute to the base of the emit + */ function getExternalModuleNameFromPath(host, fileName, referencePath) { var getCanonicalFileName = function (f) { return host.getCanonicalFileName(f); }; var dir = toPath(referencePath ? ts.getDirectoryPath(referencePath) : host.getCommonSourceDirectory(), host.getCurrentDirectory(), getCanonicalFileName); var filePath = ts.getNormalizedAbsolutePath(fileName, host.getCurrentDirectory()); - var relativePath = ts.getRelativePathToDirectoryOrUrl(dir, filePath, dir, getCanonicalFileName, false); + var relativePath = ts.getRelativePathToDirectoryOrUrl(dir, filePath, dir, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); var extensionless = ts.removeFileExtension(relativePath); return referencePath ? ts.ensurePathIsNonModuleName(extensionless) : extensionless; } @@ -9332,19 +10424,29 @@ var ts; ts.getOwnEmitOutputFilePath = getOwnEmitOutputFilePath; function getDeclarationEmitOutputFilePath(sourceFile, host) { var options = host.getCompilerOptions(); - var outputDir = options.declarationDir || options.outDir; + var outputDir = options.declarationDir || options.outDir; // Prefer declaration folder if specified var path = outputDir ? getSourceFilePathInNewDir(sourceFile, host, outputDir) : sourceFile.fileName; - return ts.removeFileExtension(path) + ".d.ts"; + return ts.removeFileExtension(path) + ".d.ts" /* Dts */; } ts.getDeclarationEmitOutputFilePath = getDeclarationEmitOutputFilePath; + /** + * Gets the source files that are expected to have an emit output. + * + * Originally part of `forEachExpectedEmitFile`, this functionality was extracted to support + * transformations. + * + * @param host An EmitHost. + * @param targetSourceFile An optional target source file to emit. + */ function getSourceFilesToEmit(host, targetSourceFile) { var options = host.getCompilerOptions(); var isSourceFileFromExternalLibrary = function (file) { return host.isSourceFileFromExternalLibrary(file); }; if (options.outFile || options.out) { var moduleKind = ts.getEmitModuleKind(options); var moduleEmitEnabled_1 = moduleKind === ts.ModuleKind.AMD || moduleKind === ts.ModuleKind.System; + // Can emit only sources that are not declaration file and are either non module code or module with --module or --target es6 specified return ts.filter(host.getSourceFiles(), function (sourceFile) { return (moduleEmitEnabled_1 || !ts.isExternalModule(sourceFile)) && sourceFileMayBeEmitted(sourceFile, options, isSourceFileFromExternalLibrary); }); @@ -9355,6 +10457,7 @@ var ts; } } ts.getSourceFilesToEmit = getSourceFilesToEmit; + /** Don't call this for `--outFile`, just for `--outDir` or plain emit. `--outFile` needs additional checks. */ function sourceFileMayBeEmitted(sourceFile, options, isSourceFileFromExternalLibrary) { return !(options.noEmitForJsFiles && isSourceFileJavaScript(sourceFile)) && !sourceFile.isDeclarationFile && !isSourceFileFromExternalLibrary(sourceFile); } @@ -9391,12 +10494,14 @@ var ts; return accessor.parameters[hasThis ? 1 : 0]; } } + /** Get the type annotation for the value parameter. */ function getSetAccessorTypeAnnotationNode(accessor) { var parameter = getSetAccessorValueParameter(accessor); return parameter && parameter.type; } ts.getSetAccessorTypeAnnotationNode = getSetAccessorTypeAnnotationNode; function getThisParameter(signature) { + // callback tags do not currently support this parameters if (signature.parameters.length && !ts.isJSDocSignature(signature)) { var thisParameter = signature.parameters[0]; if (parameterIsThisKeyword(thisParameter)) { @@ -9410,24 +10515,25 @@ var ts; } ts.parameterIsThisKeyword = parameterIsThisKeyword; function isThisIdentifier(node) { - return !!node && node.kind === 71 && identifierIsThisKeyword(node); + return !!node && node.kind === 71 /* Identifier */ && identifierIsThisKeyword(node); } ts.isThisIdentifier = isThisIdentifier; function identifierIsThisKeyword(id) { - return id.originalKeywordKind === 99; + return id.originalKeywordKind === 99 /* ThisKeyword */; } ts.identifierIsThisKeyword = identifierIsThisKeyword; function getAllAccessorDeclarations(declarations, accessor) { + // TODO: GH#18217 var firstAccessor; var secondAccessor; var getAccessor; var setAccessor; if (hasDynamicName(accessor)) { firstAccessor = accessor; - if (accessor.kind === 156) { + if (accessor.kind === 156 /* GetAccessor */) { getAccessor = accessor; } - else if (accessor.kind === 157) { + else if (accessor.kind === 157 /* SetAccessor */) { setAccessor = accessor; } else { @@ -9436,8 +10542,8 @@ var ts; } else { ts.forEach(declarations, function (member) { - if ((member.kind === 156 || member.kind === 157) - && hasModifier(member, 32) === hasModifier(accessor, 32)) { + if ((member.kind === 156 /* GetAccessor */ || member.kind === 157 /* SetAccessor */) + && hasModifier(member, 32 /* Static */) === hasModifier(accessor, 32 /* Static */)) { var memberName = getPropertyNameForPropertyNameNode(member.name); var accessorName = getPropertyNameForPropertyNameNode(accessor.name); if (memberName === accessorName) { @@ -9447,10 +10553,10 @@ var ts; else if (!secondAccessor) { secondAccessor = member; } - if (member.kind === 156 && !getAccessor) { + if (member.kind === 156 /* GetAccessor */ && !getAccessor) { getAccessor = member; } - if (member.kind === 157 && !setAccessor) { + if (member.kind === 157 /* SetAccessor */ && !setAccessor) { setAccessor = member; } } @@ -9465,6 +10571,10 @@ var ts; }; } ts.getAllAccessorDeclarations = getAllAccessorDeclarations; + /** + * Gets the effective type annotation of a variable, parameter, or property. If the node was + * parsed in a JavaScript file, gets the type annotation from JSDoc. + */ function getEffectiveTypeAnnotationNode(node) { return node.type || (isInJavaScriptFile(node) ? ts.getJSDocType(node) : undefined); } @@ -9473,6 +10583,10 @@ var ts; return node.type; } ts.getTypeAnnotationNode = getTypeAnnotationNode; + /** + * Gets the effective return type annotation of a signature. If the node was parsed in a + * JavaScript file, gets the return type annotation from JSDoc. + */ function getEffectiveReturnTypeNode(node) { if (ts.isJSDocSignature(node)) { return node.type && node.type.typeExpression && node.type.typeExpression.type; @@ -9480,12 +10594,16 @@ var ts; return node.type || (isInJavaScriptFile(node) ? ts.getJSDocReturnType(node) : undefined); } ts.getEffectiveReturnTypeNode = getEffectiveReturnTypeNode; + /** + * Gets the effective type parameters. If the node was parsed in a + * JavaScript file, gets the type parameters from the `@template` tag from JSDoc. + */ function getEffectiveTypeParameterDeclarations(node) { if (ts.isJSDocSignature(node)) { return ts.emptyArray; } if (isJSDocTypeAlias(node)) { - ts.Debug.assert(node.parent.kind === 286); + ts.Debug.assert(node.parent.kind === 286 /* JSDocComment */); return ts.flatMap(node.parent.tags, function (tag) { return ts.isJSDocTemplateTag(tag) ? tag.typeParameters : undefined; }); } return node.typeParameters || (isInJavaScriptFile(node) ? getJSDocTypeParameterDeclarations(node) : ts.emptyArray); @@ -9495,9 +10613,14 @@ var ts; return ts.flatMap(ts.getJSDocTags(node), function (tag) { return isNonTypeAliasTemplate(tag) ? tag.typeParameters : undefined; }); } ts.getJSDocTypeParameterDeclarations = getJSDocTypeParameterDeclarations; + /** template tags are only available when a typedef isn't already using them */ function isNonTypeAliasTemplate(tag) { - return ts.isJSDocTemplateTag(tag) && !(tag.parent.kind === 286 && tag.parent.tags.some(isJSDocTypeAlias)); + return ts.isJSDocTemplateTag(tag) && !(tag.parent.kind === 286 /* JSDocComment */ && tag.parent.tags.some(isJSDocTypeAlias)); } + /** + * Gets the effective type annotation of the value parameter of a set accessor. If the node + * was parsed in a JavaScript file, gets the type annotation from JSDoc. + */ function getEffectiveSetAccessorTypeAnnotationNode(node) { var parameter = getSetAccessorValueParameter(node); return parameter && getEffectiveTypeAnnotationNode(parameter); @@ -9508,6 +10631,7 @@ var ts; } ts.emitNewLineBeforeLeadingComments = emitNewLineBeforeLeadingComments; function emitNewLineBeforeLeadingCommentsOfPosition(lineMap, writer, pos, leadingComments) { + // If the leading comments start on different line than the start of node, write new line if (leadingComments && leadingComments.length && pos !== leadingComments[0].pos && getLineOfLocalPositionFromLineMap(lineMap, pos) !== getLineOfLocalPositionFromLineMap(lineMap, leadingComments[0].pos)) { writer.writeLine(); @@ -9515,6 +10639,7 @@ var ts; } ts.emitNewLineBeforeLeadingCommentsOfPosition = emitNewLineBeforeLeadingCommentsOfPosition; function emitNewLineBeforeLeadingCommentOfPosition(lineMap, writer, pos, commentPos) { + // If the leading comments start on different line than the start of node, write new line if (pos !== commentPos && getLineOfLocalPositionFromLineMap(lineMap, pos) !== getLineOfLocalPositionFromLineMap(lineMap, commentPos)) { writer.writeLine(); @@ -9547,15 +10672,25 @@ var ts; } } ts.emitComments = emitComments; + /** + * Detached comment is a comment at the top of file or function body that is separated from + * the next statement by space. + */ function emitDetachedComments(text, lineMap, writer, writeComment, node, newLine, removeComments) { var leadingComments; var currentDetachedCommentInfo; if (removeComments) { + // removeComments is true, only reserve pinned comment at the top of file + // For example: + // /*! Pinned Comment */ + // + // var x = 10; if (node.pos === 0) { leadingComments = ts.filter(ts.getLeadingCommentRanges(text, node.pos), isPinnedCommentLocal); } } else { + // removeComments is false, just get detached as normal and bypass the process to filter comment leadingComments = ts.getLeadingCommentRanges(text, node.pos); } if (leadingComments) { @@ -9567,6 +10702,9 @@ var ts; var lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, lastComment.end); var commentLine = getLineOfLocalPositionFromLineMap(lineMap, comment.pos); if (commentLine >= lastCommentLine + 2) { + // There was a blank line between the last comment and this comment. This + // comment is not part of the copyright comments. Return what we have so + // far. break; } } @@ -9574,11 +10712,15 @@ var ts; lastComment = comment; } if (detachedComments.length) { + // All comments look like they could have been part of the copyright header. Make + // sure there is at least one blank line between it and the node. If not, it's not + // a copyright header. var lastCommentLine = getLineOfLocalPositionFromLineMap(lineMap, ts.last(detachedComments).end); var nodeLine = getLineOfLocalPositionFromLineMap(lineMap, ts.skipTrivia(text, node.pos)); if (nodeLine >= lastCommentLine + 2) { + // Valid detachedComments emitNewLineBeforeLeadingComments(lineMap, writer, node, leadingComments); - emitComments(text, lineMap, writer, detachedComments, false, true, newLine, writeComment); + emitComments(text, lineMap, writer, detachedComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment); currentDetachedCommentInfo = { nodePos: node.pos, detachedCommentEndPos: ts.last(detachedComments).end }; } } @@ -9590,7 +10732,7 @@ var ts; } ts.emitDetachedComments = emitDetachedComments; function writeCommentRange(text, lineMap, writer, commentPos, commentEnd, newLine) { - if (text.charCodeAt(commentPos + 1) === 42) { + if (text.charCodeAt(commentPos + 1) === 42 /* asterisk */) { var firstCommentLineAndCharacter = ts.computeLineAndCharacterOfPosition(lineMap, commentPos); var lineCount = lineMap.length; var firstCommentLineIndent = void 0; @@ -9599,29 +10741,50 @@ var ts; ? text.length + 1 : lineMap[currentLine + 1]; if (pos !== commentPos) { + // If we are not emitting first line, we need to write the spaces to adjust the alignment if (firstCommentLineIndent === undefined) { firstCommentLineIndent = calculateIndent(text, lineMap[firstCommentLineAndCharacter.line], commentPos); } + // These are number of spaces writer is going to write at current indent var currentWriterIndentSpacing = writer.getIndent() * getIndentSize(); + // Number of spaces we want to be writing + // eg: Assume writer indent + // module m { + // /* starts at character 9 this is line 1 + // * starts at character pos 4 line --1 = 8 - 8 + 3 + // More left indented comment */ --2 = 8 - 8 + 2 + // class c { } + // } + // module m { + // /* this is line 1 -- Assume current writer indent 8 + // * line --3 = 8 - 4 + 5 + // More right indented comment */ --4 = 8 - 4 + 11 + // class c { } + // } var spacesToEmit = currentWriterIndentSpacing - firstCommentLineIndent + calculateIndent(text, pos, nextLineStart); if (spacesToEmit > 0) { var numberOfSingleSpacesToEmit = spacesToEmit % getIndentSize(); var indentSizeSpaceString = getIndentString((spacesToEmit - numberOfSingleSpacesToEmit) / getIndentSize()); + // Write indent size string ( in eg 1: = "", 2: "" , 3: string with 8 spaces 4: string with 12 spaces writer.rawWrite(indentSizeSpaceString); + // Emit the single spaces (in eg: 1: 3 spaces, 2: 2 spaces, 3: 1 space, 4: 3 spaces) while (numberOfSingleSpacesToEmit) { writer.rawWrite(" "); numberOfSingleSpacesToEmit--; } } else { + // No spaces to emit write empty string writer.rawWrite(""); } } + // Write the comment line text writeTrimmedCurrentLine(text, commentEnd, writer, newLine, pos, nextLineStart); pos = nextLineStart; } } else { + // Single line comment of style //.... writer.write(text.substring(commentPos, commentEnd)); } } @@ -9630,29 +10793,33 @@ var ts; var end = Math.min(commentEnd, nextLineStart - 1); var currentLineText = text.substring(pos, end).replace(/^\s+|\s+$/g, ""); if (currentLineText) { + // trimmed forward and ending spaces text writer.write(currentLineText); if (end !== commentEnd) { writer.writeLine(); } } else { + // Empty string - make sure we write empty line writer.writeLiteral(newLine); } } function calculateIndent(text, pos, end) { var currentLineIndent = 0; for (; pos < end && ts.isWhiteSpaceSingleLine(text.charCodeAt(pos)); pos++) { - if (text.charCodeAt(pos) === 9) { + if (text.charCodeAt(pos) === 9 /* tab */) { + // Tabs = TabSize = indent size and go to next tabStop currentLineIndent += getIndentSize() - (currentLineIndent % getIndentSize()); } else { + // Single space currentLineIndent++; } } return currentLineIndent; } function hasModifiers(node) { - return getModifierFlags(node) !== 0; + return getModifierFlags(node) !== 0 /* None */; } ts.hasModifiers = hasModifiers; function hasModifier(node, flags) { @@ -9660,11 +10827,11 @@ var ts; } ts.hasModifier = hasModifier; function hasStaticModifier(node) { - return hasModifier(node, 32); + return hasModifier(node, 32 /* Static */); } ts.hasStaticModifier = hasStaticModifier; function hasReadonlyModifier(node) { - return hasModifier(node, 64); + return hasModifier(node, 64 /* Readonly */); } ts.hasReadonlyModifier = hasReadonlyModifier; function getSelectedModifierFlags(node, flags) { @@ -9672,58 +10839,59 @@ var ts; } ts.getSelectedModifierFlags = getSelectedModifierFlags; function getModifierFlags(node) { - if (node.modifierFlagsCache & 536870912) { - return node.modifierFlagsCache & ~536870912; + if (node.modifierFlagsCache & 536870912 /* HasComputedFlags */) { + return node.modifierFlagsCache & ~536870912 /* HasComputedFlags */; } var flags = getModifierFlagsNoCache(node); - node.modifierFlagsCache = flags | 536870912; + node.modifierFlagsCache = flags | 536870912 /* HasComputedFlags */; return flags; } ts.getModifierFlags = getModifierFlags; function getModifierFlagsNoCache(node) { - var flags = 0; + var flags = 0 /* None */; if (node.modifiers) { for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { var modifier = _a[_i]; flags |= modifierToFlag(modifier.kind); } } - if (node.flags & 4 || (node.kind === 71 && node.isInJSDocNamespace)) { - flags |= 1; + if (node.flags & 4 /* NestedNamespace */ || (node.kind === 71 /* Identifier */ && node.isInJSDocNamespace)) { + flags |= 1 /* Export */; } return flags; } ts.getModifierFlagsNoCache = getModifierFlagsNoCache; function modifierToFlag(token) { switch (token) { - case 115: return 32; - case 114: return 4; - case 113: return 16; - case 112: return 8; - case 117: return 128; - case 84: return 1; - case 124: return 2; - case 76: return 2048; - case 79: return 512; - case 120: return 256; - case 132: return 64; + case 115 /* StaticKeyword */: return 32 /* Static */; + case 114 /* PublicKeyword */: return 4 /* Public */; + case 113 /* ProtectedKeyword */: return 16 /* Protected */; + case 112 /* PrivateKeyword */: return 8 /* Private */; + case 117 /* AbstractKeyword */: return 128 /* Abstract */; + case 84 /* ExportKeyword */: return 1 /* Export */; + case 124 /* DeclareKeyword */: return 2 /* Ambient */; + case 76 /* ConstKeyword */: return 2048 /* Const */; + case 79 /* DefaultKeyword */: return 512 /* Default */; + case 120 /* AsyncKeyword */: return 256 /* Async */; + case 132 /* ReadonlyKeyword */: return 64 /* Readonly */; } - return 0; + return 0 /* None */; } ts.modifierToFlag = modifierToFlag; function isLogicalOperator(token) { - return token === 54 - || token === 53 - || token === 51; + return token === 54 /* BarBarToken */ + || token === 53 /* AmpersandAmpersandToken */ + || token === 51 /* ExclamationToken */; } ts.isLogicalOperator = isLogicalOperator; function isAssignmentOperator(token) { - return token >= 58 && token <= 70; + return token >= 58 /* FirstAssignment */ && token <= 70 /* LastAssignment */; } ts.isAssignmentOperator = isAssignmentOperator; + /** Get `C` given `N` if `N` is in the position `class C extends N` where `N` is an ExpressionWithTypeArguments. */ function tryGetClassExtendingExpressionWithTypeArguments(node) { if (ts.isExpressionWithTypeArguments(node) && - node.parent.token === 85 && + node.parent.token === 85 /* ExtendsKeyword */ && ts.isClassLike(node.parent.parent)) { return node.parent.parent; } @@ -9732,16 +10900,16 @@ var ts; function isAssignmentExpression(node, excludeCompoundAssignment) { return ts.isBinaryExpression(node) && (excludeCompoundAssignment - ? node.operatorToken.kind === 58 + ? node.operatorToken.kind === 58 /* EqualsToken */ : isAssignmentOperator(node.operatorToken.kind)) && ts.isLeftHandSideExpression(node.left); } ts.isAssignmentExpression = isAssignmentExpression; function isDestructuringAssignment(node) { - if (isAssignmentExpression(node, true)) { + if (isAssignmentExpression(node, /*excludeCompoundAssignment*/ true)) { var kind = node.left.kind; - return kind === 184 - || kind === 183; + return kind === 184 /* ObjectLiteralExpression */ + || kind === 183 /* ArrayLiteralExpression */; } return false; } @@ -9751,16 +10919,16 @@ var ts; } ts.isExpressionWithTypeArgumentsInClassExtendsClause = isExpressionWithTypeArgumentsInClassExtendsClause; function isExpressionWithTypeArgumentsInClassImplementsClause(node) { - return node.kind === 207 + return node.kind === 207 /* ExpressionWithTypeArguments */ && isEntityNameExpression(node.expression) && node.parent - && node.parent.token === 108 + && node.parent.token === 108 /* ImplementsKeyword */ && node.parent.parent && ts.isClassLike(node.parent.parent); } ts.isExpressionWithTypeArgumentsInClassImplementsClause = isExpressionWithTypeArgumentsInClassImplementsClause; function isEntityNameExpression(node) { - return node.kind === 71 || isPropertyAccessEntityNameExpression(node); + return node.kind === 71 /* Identifier */ || isPropertyAccessEntityNameExpression(node); } ts.isEntityNameExpression = isEntityNameExpression; function isPropertyAccessEntityNameExpression(node) { @@ -9772,17 +10940,17 @@ var ts; } ts.isPrototypeAccess = isPrototypeAccess; function isRightSideOfQualifiedNameOrPropertyAccess(node) { - return (node.parent.kind === 146 && node.parent.right === node) || - (node.parent.kind === 185 && node.parent.name === node); + return (node.parent.kind === 146 /* QualifiedName */ && node.parent.right === node) || + (node.parent.kind === 185 /* PropertyAccessExpression */ && node.parent.name === node); } ts.isRightSideOfQualifiedNameOrPropertyAccess = isRightSideOfQualifiedNameOrPropertyAccess; function isEmptyObjectLiteral(expression) { - return expression.kind === 184 && + return expression.kind === 184 /* ObjectLiteralExpression */ && expression.properties.length === 0; } ts.isEmptyObjectLiteral = isEmptyObjectLiteral; function isEmptyArrayLiteral(expression) { - return expression.kind === 183 && + return expression.kind === 183 /* ArrayLiteralExpression */ && expression.elements.length === 0; } ts.isEmptyArrayLiteral = isEmptyArrayLiteral; @@ -9791,17 +10959,23 @@ var ts; } ts.getLocalSymbolForExportDefault = getLocalSymbolForExportDefault; function isExportDefaultSymbol(symbol) { - return symbol && ts.length(symbol.declarations) > 0 && hasModifier(symbol.declarations[0], 512); + return symbol && ts.length(symbol.declarations) > 0 && hasModifier(symbol.declarations[0], 512 /* Default */); } + /** Return ".ts", ".d.ts", or ".tsx", if that is the extension. */ function tryExtractTypeScriptExtension(fileName) { return ts.find(ts.supportedTypescriptExtensionsForExtractExtension, function (extension) { return ts.fileExtensionIs(fileName, extension); }); } ts.tryExtractTypeScriptExtension = tryExtractTypeScriptExtension; + /** + * Replace each instance of non-ascii characters by one, two, three, or four escape sequences + * representing the UTF-8 encoding of the character, and return the expanded char code list. + */ function getExpandedCharCodes(input) { var output = []; var length = input.length; for (var i = 0; i < length; i++) { var charCode = input.charCodeAt(i); + // handle utf8 if (charCode < 0x80) { output.push(charCode); } @@ -9827,6 +11001,9 @@ var ts; return output; } var base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + /** + * Converts a string to a base-64 encoded ASCII string. + */ function convertToBase64(input) { var result = ""; var charCodes = getExpandedCharCodes(input); @@ -9834,16 +11011,21 @@ var ts; var length = charCodes.length; var byte1, byte2, byte3, byte4; while (i < length) { + // Convert every 6-bits in the input 3 character points + // into a base64 digit byte1 = charCodes[i] >> 2; byte2 = (charCodes[i] & 3) << 4 | charCodes[i + 1] >> 4; byte3 = (charCodes[i + 1] & 15) << 2 | charCodes[i + 2] >> 6; byte4 = charCodes[i + 2] & 63; + // We are out of characters in the input, set the extra + // digits to 64 (padding character). if (i + 1 >= length) { byte3 = byte4 = 64; } else if (i + 2 >= length) { byte4 = 64; } + // Write to the output result += base64Digits.charAt(byte1) + base64Digits.charAt(byte2) + base64Digits.charAt(byte3) + base64Digits.charAt(byte4); i += 3; } @@ -9869,9 +11051,12 @@ var ts; i++; nextCode = codes[i]; } + // `value` may be greater than 10FFFF (the maximum unicode codepoint) - JS will just make this into an invalid character for us output += String.fromCharCode(value); } else { + // We don't want to kill the process when decoding fails (due to a following char byte not + // following a leading char), so we just print the (bad) value output += String.fromCharCode(charCode); i++; } @@ -9893,9 +11078,11 @@ var ts; var expandedCharCodes = []; var i = 0; while (i < length) { + // Stop decoding once padding characters are present if (input.charCodeAt(i) === base64Digits.charCodeAt(64)) { break; } + // convert 4 input digits into three characters, ignoring padding characters at the end var ch1 = base64Digits.indexOf(input[i]); var ch2 = base64Digits.indexOf(input[i + 1]); var ch3 = base64Digits.indexOf(input[i + 2]); @@ -9903,10 +11090,10 @@ var ts; var code1 = ((ch1 & 63) << 2) | ((ch2 >> 4) & 3); var code2 = ((ch2 & 15) << 4) | ((ch3 >> 2) & 15); var code3 = ((ch3 & 3) << 6) | (ch4 & 63); - if (code2 === 0 && ch3 !== 0) { + if (code2 === 0 && ch3 !== 0) { // code2 decoded to zero, but ch3 was padding - elide code2 and code3 expandedCharCodes.push(code1); } - else if (code3 === 0 && ch4 !== 0) { + else if (code3 === 0 && ch4 !== 0) { // code3 decoded to zero, but ch4 was padding, elide code3 expandedCharCodes.push(code1, code2); } else { @@ -9921,14 +11108,17 @@ var ts; var lineFeed = "\n"; function getNewLineCharacter(options, getNewLine) { switch (options.newLine) { - case 0: + case 0 /* CarriageReturnLineFeed */: return carriageReturnLineFeed; - case 1: + case 1 /* LineFeed */: return lineFeed; } return getNewLine ? getNewLine() : ts.sys ? ts.sys.newLine : carriageReturnLineFeed; } ts.getNewLineCharacter = getNewLineCharacter; + /** + * Formats an enum value as a string for debugging and debug assertions. + */ function formatEnum(value, enumObject, isFlags) { if (value === void 0) { value = 0; } var members = getEnumMembers(enumObject); @@ -9970,61 +11160,96 @@ var ts; return ts.stableSort(result, function (x, y) { return ts.compareValues(x[0], y[0]); }); } function formatSyntaxKind(kind) { - return formatEnum(kind, ts.SyntaxKind, false); + return formatEnum(kind, ts.SyntaxKind, /*isFlags*/ false); } ts.formatSyntaxKind = formatSyntaxKind; function formatModifierFlags(flags) { - return formatEnum(flags, ts.ModifierFlags, true); + return formatEnum(flags, ts.ModifierFlags, /*isFlags*/ true); } ts.formatModifierFlags = formatModifierFlags; function formatTransformFlags(flags) { - return formatEnum(flags, ts.TransformFlags, true); + return formatEnum(flags, ts.TransformFlags, /*isFlags*/ true); } ts.formatTransformFlags = formatTransformFlags; function formatEmitFlags(flags) { - return formatEnum(flags, ts.EmitFlags, true); + return formatEnum(flags, ts.EmitFlags, /*isFlags*/ true); } ts.formatEmitFlags = formatEmitFlags; function formatSymbolFlags(flags) { - return formatEnum(flags, ts.SymbolFlags, true); + return formatEnum(flags, ts.SymbolFlags, /*isFlags*/ true); } ts.formatSymbolFlags = formatSymbolFlags; function formatTypeFlags(flags) { - return formatEnum(flags, ts.TypeFlags, true); + return formatEnum(flags, ts.TypeFlags, /*isFlags*/ true); } ts.formatTypeFlags = formatTypeFlags; function formatObjectFlags(flags) { - return formatEnum(flags, ts.ObjectFlags, true); + return formatEnum(flags, ts.ObjectFlags, /*isFlags*/ true); } ts.formatObjectFlags = formatObjectFlags; + /** + * Creates a new TextRange from the provided pos and end. + * + * @param pos The start position. + * @param end The end position. + */ function createRange(pos, end) { return { pos: pos, end: end }; } ts.createRange = createRange; + /** + * Creates a new TextRange from a provided range with a new end position. + * + * @param range A TextRange. + * @param end The new end position. + */ function moveRangeEnd(range, end) { return createRange(range.pos, end); } ts.moveRangeEnd = moveRangeEnd; + /** + * Creates a new TextRange from a provided range with a new start position. + * + * @param range A TextRange. + * @param pos The new Start position. + */ function moveRangePos(range, pos) { return createRange(pos, range.end); } ts.moveRangePos = moveRangePos; + /** + * Moves the start position of a range past any decorators. + */ function moveRangePastDecorators(node) { return node.decorators && node.decorators.length > 0 ? moveRangePos(node, node.decorators.end) : node; } ts.moveRangePastDecorators = moveRangePastDecorators; + /** + * Moves the start position of a range past any decorators or modifiers. + */ function moveRangePastModifiers(node) { return node.modifiers && node.modifiers.length > 0 ? moveRangePos(node, node.modifiers.end) : moveRangePastDecorators(node); } ts.moveRangePastModifiers = moveRangePastModifiers; + /** + * Determines whether a TextRange has the same start and end positions. + * + * @param range A TextRange. + */ function isCollapsedRange(range) { return range.pos === range.end; } ts.isCollapsedRange = isCollapsedRange; + /** + * Creates a new TextRange for a token at the provides start position. + * + * @param pos The start position. + * @param token The token. + */ function createTokenRange(pos, token) { return createRange(pos, pos + ts.tokenToString(token).length); } @@ -10058,12 +11283,16 @@ var ts; return ts.positionIsSynthesized(range.pos) ? -1 : ts.skipTrivia(sourceFile.text, range.pos); } ts.getStartPositionOfRange = getStartPositionOfRange; + /** + * Determines whether a name was originally the declaration name of an enum or namespace + * declaration. + */ function isDeclarationNameOfEnumOrNamespace(node) { var parseNode = ts.getParseTreeNode(node); if (parseNode) { switch (parseNode.parent.kind) { - case 238: - case 239: + case 238 /* EnumDeclaration */: + case 239 /* ModuleDeclaration */: return parseNode === parseNode.parent.name; } } @@ -10078,6 +11307,7 @@ var ts; return node.initializer !== undefined; } function isWatchSet(options) { + // Firefox has Object.prototype.watch return options.watch && options.hasOwnProperty("watch"); } ts.isWatchSet = isWatchSet; @@ -10086,69 +11316,74 @@ var ts; } ts.closeFileWatcher = closeFileWatcher; function getCheckFlags(symbol) { - return symbol.flags & 33554432 ? symbol.checkFlags : 0; + return symbol.flags & 33554432 /* Transient */ ? symbol.checkFlags : 0; } ts.getCheckFlags = getCheckFlags; function getDeclarationModifierFlagsFromSymbol(s) { if (s.valueDeclaration) { var flags = ts.getCombinedModifierFlags(s.valueDeclaration); - return s.parent && s.parent.flags & 32 ? flags : flags & ~28; + return s.parent && s.parent.flags & 32 /* Class */ ? flags : flags & ~28 /* AccessibilityModifier */; } - if (getCheckFlags(s) & 6) { + if (getCheckFlags(s) & 6 /* Synthetic */) { var checkFlags = s.checkFlags; - var accessModifier = checkFlags & 256 ? 8 : - checkFlags & 64 ? 4 : - 16; - var staticModifier = checkFlags & 512 ? 32 : 0; + var accessModifier = checkFlags & 256 /* ContainsPrivate */ ? 8 /* Private */ : + checkFlags & 64 /* ContainsPublic */ ? 4 /* Public */ : + 16 /* Protected */; + var staticModifier = checkFlags & 512 /* ContainsStatic */ ? 32 /* Static */ : 0; return accessModifier | staticModifier; } - if (s.flags & 4194304) { - return 4 | 32; + if (s.flags & 4194304 /* Prototype */) { + return 4 /* Public */ | 32 /* Static */; } return 0; } ts.getDeclarationModifierFlagsFromSymbol = getDeclarationModifierFlagsFromSymbol; function skipAlias(symbol, checker) { - return symbol.flags & 2097152 ? checker.getAliasedSymbol(symbol) : symbol; + return symbol.flags & 2097152 /* Alias */ ? checker.getAliasedSymbol(symbol) : symbol; } ts.skipAlias = skipAlias; + /** See comment on `declareModuleMember` in `binder.ts`. */ function getCombinedLocalAndExportSymbolFlags(symbol) { return symbol.exportSymbol ? symbol.exportSymbol.flags | symbol.flags : symbol.flags; } ts.getCombinedLocalAndExportSymbolFlags = getCombinedLocalAndExportSymbolFlags; function isWriteOnlyAccess(node) { - return accessKind(node) === 1; + return accessKind(node) === 1 /* Write */; } ts.isWriteOnlyAccess = isWriteOnlyAccess; function isWriteAccess(node) { - return accessKind(node) !== 0; + return accessKind(node) !== 0 /* Read */; } ts.isWriteAccess = isWriteAccess; var AccessKind; (function (AccessKind) { + /** Only reads from a variable. */ AccessKind[AccessKind["Read"] = 0] = "Read"; + /** Only writes to a variable without using the result. E.g.: `x++;`. */ AccessKind[AccessKind["Write"] = 1] = "Write"; + /** Writes to a variable and uses the result as an expression. E.g.: `f(x++);`. */ AccessKind[AccessKind["ReadWrite"] = 2] = "ReadWrite"; })(AccessKind || (AccessKind = {})); function accessKind(node) { var parent = node.parent; if (!parent) - return 0; + return 0 /* Read */; switch (parent.kind) { - case 199: - case 198: + case 199 /* PostfixUnaryExpression */: + case 198 /* PrefixUnaryExpression */: var operator = parent.operator; - return operator === 43 || operator === 44 ? writeOrReadWrite() : 0; - case 200: + return operator === 43 /* PlusPlusToken */ || operator === 44 /* MinusMinusToken */ ? writeOrReadWrite() : 0 /* Read */; + case 200 /* BinaryExpression */: var _a = parent, left = _a.left, operatorToken = _a.operatorToken; - return left === node && isAssignmentOperator(operatorToken.kind) ? writeOrReadWrite() : 0; - case 185: - return parent.name !== node ? 0 : accessKind(parent); + return left === node && isAssignmentOperator(operatorToken.kind) ? writeOrReadWrite() : 0 /* Read */; + case 185 /* PropertyAccessExpression */: + return parent.name !== node ? 0 /* Read */ : accessKind(parent); default: - return 0; + return 0 /* Read */; } function writeOrReadWrite() { - return parent.parent && parent.parent.kind === 216 ? 1 : 2; + // If grandparent is not an ExpressionStatement, this is used as an expression in addition to having a side effect. + return parent.parent && parent.parent.kind === 216 /* ExpressionStatement */ ? 1 /* Write */ : 2 /* ReadWrite */; } } function compareDataObjects(dst, src) { @@ -10170,30 +11405,43 @@ var ts; return true; } ts.compareDataObjects = compareDataObjects; + /** + * clears already present map by calling onDeleteExistingValue callback before deleting that key/value + */ function clearMap(map, onDeleteValue) { + // Remove all map.forEach(onDeleteValue); map.clear(); } ts.clearMap = clearMap; + /** + * Mutates the map with newMap such that keys in map will be same as newMap. + */ function mutateMap(map, newMap, options) { var createNewValue = options.createNewValue, onDeleteValue = options.onDeleteValue, onExistingValue = options.onExistingValue; + // Needs update map.forEach(function (existingValue, key) { var valueInNewMap = newMap.get(key); + // Not present any more in new map, remove it if (valueInNewMap === undefined) { map.delete(key); onDeleteValue(existingValue, key); } + // If present notify about existing values else if (onExistingValue) { onExistingValue(existingValue, valueInNewMap, key); } }); + // Add new values that are not already present newMap.forEach(function (valueInNewMap, key) { if (!map.has(key)) { + // New values map.set(key, createNewValue(key, valueInNewMap)); } }); } ts.mutateMap = mutateMap; + /** Calls `callback` on `directory` and every ancestor directory it has, returning the first defined result. */ function forEachAncestorDirectory(directory, callback) { while (true) { var result = callback(directory); @@ -10208,14 +11456,15 @@ var ts; } } ts.forEachAncestorDirectory = forEachAncestorDirectory; + // Return true if the given type is the constructor type for an abstract class function isAbstractConstructorType(type) { - return !!(getObjectFlags(type) & 16) && !!type.symbol && isAbstractConstructorSymbol(type.symbol); + return !!(getObjectFlags(type) & 16 /* Anonymous */) && !!type.symbol && isAbstractConstructorSymbol(type.symbol); } ts.isAbstractConstructorType = isAbstractConstructorType; function isAbstractConstructorSymbol(symbol) { - if (symbol.flags & 32) { + if (symbol.flags & 32 /* Class */) { var declaration = getClassLikeDeclarationOfSymbol(symbol); - return !!declaration && hasModifier(declaration, 128); + return !!declaration && hasModifier(declaration, 128 /* Abstract */); } return false; } @@ -10225,11 +11474,11 @@ var ts; } ts.getClassLikeDeclarationOfSymbol = getClassLikeDeclarationOfSymbol; function getObjectFlags(type) { - return type.flags & 131072 ? type.objectFlags : 0; + return type.flags & 131072 /* Object */ ? type.objectFlags : 0; } ts.getObjectFlags = getObjectFlags; function typeHasCallOrConstructSignatures(type, checker) { - return checker.getSignaturesOfType(type, 0).length !== 0 || checker.getSignaturesOfType(type, 1).length !== 0; + return checker.getSignaturesOfType(type, 0 /* Call */).length !== 0 || checker.getSignaturesOfType(type, 1 /* Construct */).length !== 0; } ts.typeHasCallOrConstructSignatures = typeHasCallOrConstructSignatures; function forSomeAncestorDirectory(directory, callback) { @@ -10251,6 +11500,7 @@ var ts; if (nodeIsPresent(child)) lastChild = child; }, function (children) { + // As an optimization, jump straight to the end of the list. for (var i = children.length - 1; i >= 0; i--) { if (nodeIsPresent(children[i])) { lastChild = children[i]; @@ -10279,16 +11529,16 @@ var ts; (function (ts) { function getDefaultLibFileName(options) { switch (options.target) { - case 6: + case 6 /* ESNext */: return "lib.esnext.full.d.ts"; - case 5: + case 5 /* ES2018 */: return "lib.es2018.full.d.ts"; - case 4: + case 4 /* ES2017 */: return "lib.es2017.full.d.ts"; - case 3: + case 3 /* ES2016 */: return "lib.es2016.full.d.ts"; - case 2: - return "lib.es6.d.ts"; + case 2 /* ES2015 */: + return "lib.es6.d.ts"; // We don't use lib.es2015.full.d.ts due to breaking change. default: return "lib.d.ts"; } @@ -10306,6 +11556,7 @@ var ts; return position >= span.start && position < textSpanEnd(span); } ts.textSpanContainsPosition = textSpanContainsPosition; + // Returns true if 'span' contains 'other'. function textSpanContainsTextSpan(span, other) { return other.start >= span.start && textSpanEnd(other) <= textSpanEnd(span); } @@ -10353,6 +11604,7 @@ var ts; return { start: start, length: length }; } ts.createTextSpan = createTextSpan; + /* @internal */ function createTextRange(pos, end) { if (end === void 0) { end = pos; } ts.Debug.assert(end >= pos); @@ -10379,6 +11631,14 @@ var ts; } ts.createTextChangeRange = createTextChangeRange; ts.unchangedTextChangeRange = createTextChangeRange(createTextSpan(0, 0), 0); + /** + * Called to merge all the changes that occurred across several versions of a script snapshot + * into a single change. i.e. if a user keeps making successive edits to a script we will + * have a text change from V1 to V2, V2 to V3, ..., Vn. + * + * This function will then merge those changes into a single change range valid between V1 and + * Vn. + */ function collapseTextChangeRangesAcrossMultipleVersions(changes) { if (changes.length === 0) { return ts.unchangedTextChangeRange; @@ -10386,12 +11646,93 @@ var ts; if (changes.length === 1) { return changes[0]; } + // We change from talking about { { oldStart, oldLength }, newLength } to { oldStart, oldEnd, newEnd } + // as it makes things much easier to reason about. var change0 = changes[0]; var oldStartN = change0.span.start; var oldEndN = textSpanEnd(change0.span); var newEndN = oldStartN + change0.newLength; for (var i = 1; i < changes.length; i++) { var nextChange = changes[i]; + // Consider the following case: + // i.e. two edits. The first represents the text change range { { 10, 50 }, 30 }. i.e. The span starting + // at 10, with length 50 is reduced to length 30. The second represents the text change range { { 30, 30 }, 40 }. + // i.e. the span starting at 30 with length 30 is increased to length 40. + // + // 0 10 20 30 40 50 60 70 80 90 100 + // ------------------------------------------------------------------------------------------------------- + // | / + // | /---- + // T1 | /---- + // | /---- + // | /---- + // ------------------------------------------------------------------------------------------------------- + // | \ + // | \ + // T2 | \ + // | \ + // | \ + // ------------------------------------------------------------------------------------------------------- + // + // Merging these turns out to not be too difficult. First, determining the new start of the change is trivial + // it's just the min of the old and new starts. i.e.: + // + // 0 10 20 30 40 50 60 70 80 90 100 + // ------------------------------------------------------------*------------------------------------------ + // | / + // | /---- + // T1 | /---- + // | /---- + // | /---- + // ----------------------------------------$-------------------$------------------------------------------ + // . | \ + // . | \ + // T2 . | \ + // . | \ + // . | \ + // ----------------------------------------------------------------------*-------------------------------- + // + // (Note the dots represent the newly inferred start. + // Determining the new and old end is also pretty simple. Basically it boils down to paying attention to the + // absolute positions at the asterisks, and the relative change between the dollar signs. Basically, we see + // which if the two $'s precedes the other, and we move that one forward until they line up. in this case that + // means: + // + // 0 10 20 30 40 50 60 70 80 90 100 + // --------------------------------------------------------------------------------*---------------------- + // | / + // | /---- + // T1 | /---- + // | /---- + // | /---- + // ------------------------------------------------------------$------------------------------------------ + // . | \ + // . | \ + // T2 . | \ + // . | \ + // . | \ + // ----------------------------------------------------------------------*-------------------------------- + // + // In other words (in this case), we're recognizing that the second edit happened after where the first edit + // ended with a delta of 20 characters (60 - 40). Thus, if we go back in time to where the first edit started + // that's the same as if we started at char 80 instead of 60. + // + // As it so happens, the same logic applies if the second edit precedes the first edit. In that case rather + // than pushing the first edit forward to match the second, we'll push the second edit forward to match the + // first. + // + // In this case that means we have { oldStart: 10, oldEnd: 80, newEnd: 70 } or, in TextChangeRange + // semantics: { { start: 10, length: 70 }, newLength: 60 } + // + // The math then works out as follows. + // If we have { oldStart1, oldEnd1, newEnd1 } and { oldStart2, oldEnd2, newEnd2 } then we can compute the + // final result like so: + // + // { + // oldStart3: Min(oldStart1, oldStart2), + // oldEnd3: Max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1)), + // newEnd3: Max(newEnd2, newEnd2 + (newEnd1 - oldEnd2)) + // } var oldStart1 = oldStartN; var oldEnd1 = oldEndN; var newEnd1 = newEndN; @@ -10402,13 +11743,13 @@ var ts; oldEndN = Math.max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1)); newEndN = Math.max(newEnd2, newEnd2 + (newEnd1 - oldEnd2)); } - return createTextChangeRange(createTextSpanFromBounds(oldStartN, oldEndN), newEndN - oldStartN); + return createTextChangeRange(createTextSpanFromBounds(oldStartN, oldEndN), /*newLength*/ newEndN - oldStartN); } ts.collapseTextChangeRangesAcrossMultipleVersions = collapseTextChangeRangesAcrossMultipleVersions; function getTypeParameterOwner(d) { - if (d && d.kind === 148) { + if (d && d.kind === 148 /* TypeParameter */) { for (var current = d; current; current = current.parent) { - if (ts.isFunctionLike(current) || ts.isClassLike(current) || current.kind === 236) { + if (ts.isFunctionLike(current) || ts.isClassLike(current) || current.kind === 236 /* InterfaceDeclaration */) { return current; } } @@ -10416,7 +11757,7 @@ var ts; } ts.getTypeParameterOwner = getTypeParameterOwner; function isParameterPropertyDeclaration(node) { - return ts.hasModifier(node, 92) && node.parent.kind === 155; + return ts.hasModifier(node, 92 /* ParameterPropertyModifier */) && node.parent.kind === 155 /* Constructor */; } ts.isParameterPropertyDeclaration = isParameterPropertyDeclaration; function isEmptyBindingPattern(node) { @@ -10434,7 +11775,7 @@ var ts; } ts.isEmptyBindingElement = isEmptyBindingElement; function walkUpBindingElementsAndPatterns(node) { - while (node && (node.kind === 182 || ts.isBindingPattern(node))) { + while (node && (node.kind === 182 /* BindingElement */ || ts.isBindingPattern(node))) { node = node.parent; } return node; @@ -10442,35 +11783,46 @@ var ts; function getCombinedModifierFlags(node) { node = walkUpBindingElementsAndPatterns(node); var flags = ts.getModifierFlags(node); - if (node.kind === 232) { + if (node.kind === 232 /* VariableDeclaration */) { node = node.parent; } - if (node && node.kind === 233) { + if (node && node.kind === 233 /* VariableDeclarationList */) { flags |= ts.getModifierFlags(node); node = node.parent; } - if (node && node.kind === 214) { + if (node && node.kind === 214 /* VariableStatement */) { flags |= ts.getModifierFlags(node); } return flags; } ts.getCombinedModifierFlags = getCombinedModifierFlags; + // Returns the node flags for this node and all relevant parent nodes. This is done so that + // nodes like variable declarations and binding elements can returned a view of their flags + // that includes the modifiers from their container. i.e. flags like export/declare aren't + // stored on the variable declaration directly, but on the containing variable statement + // (if it has one). Similarly, flags for let/const are store on the variable declaration + // list. By calling this function, all those flags are combined so that the client can treat + // the node as if it actually had those flags. function getCombinedNodeFlags(node) { node = walkUpBindingElementsAndPatterns(node); var flags = node.flags; - if (node.kind === 232) { + if (node.kind === 232 /* VariableDeclaration */) { node = node.parent; } - if (node && node.kind === 233) { + if (node && node.kind === 233 /* VariableDeclarationList */) { flags |= node.flags; node = node.parent; } - if (node && node.kind === 214) { + if (node && node.kind === 214 /* VariableStatement */) { flags |= node.flags; } return flags; } ts.getCombinedNodeFlags = getCombinedNodeFlags; + /** + * Checks to see if the locale is in the appropriate format, + * and if it is, attempts to set the appropriate language. + */ function validateLocaleAndSetLanguage(locale, sys, errors) { var matchResult = /^([a-z]+)([_\-]([a-z]+))?$/.exec(locale.toLowerCase()); if (!matchResult) { @@ -10481,9 +11833,12 @@ var ts; } var language = matchResult[1]; var territory = matchResult[3]; + // First try the entire locale, then fall back to just language if that's all we have. + // Either ways do not fail, and fallback to the English diagnostic strings. if (!trySetLanguageAndTerritory(language, territory, errors)) { - trySetLanguageAndTerritory(language, undefined, errors); + trySetLanguageAndTerritory(language, /*territory*/ undefined, errors); } + // Set the UI locale for string collation ts.setUILocale(locale); function trySetLanguageAndTerritory(language, territory, errors) { var compilerFilePath = ts.normalizePath(sys.getExecutingFilePath()); @@ -10496,6 +11851,7 @@ var ts; if (!sys.fileExists(filePath)) { return false; } + // TODO: Add codePage support for readFile? var fileContents = ""; try { fileContents = sys.readFile(filePath); @@ -10507,6 +11863,7 @@ var ts; return false; } try { + // tslint:disable-next-line no-unnecessary-qualifier (making clear this is a global mutation!) ts.localizedDiagnosticMessages = JSON.parse(fileContents); } catch (_a) { @@ -10528,8 +11885,13 @@ var ts; return !nodeTest || nodeTest(node) ? node : undefined; } ts.getOriginalNode = getOriginalNode; + /** + * Gets a value indicating whether a node originated in the parse tree. + * + * @param node The node to test. + */ function isParseTreeNode(node) { - return (node.flags & 8) === 0; + return (node.flags & 8 /* Synthesized */) === 0; } ts.isParseTreeNode = isParseTreeNode; function getParseTreeNode(node, nodeTest) { @@ -10543,9 +11905,15 @@ var ts; return undefined; } ts.getParseTreeNode = getParseTreeNode; + /** + * Remove extra underscore from escaped identifier text content. + * + * @param identifier The escaped identifier text. + * @returns The unescaped identifier text. + */ function unescapeLeadingUnderscores(identifier) { var id = identifier; - return id.length >= 3 && id.charCodeAt(0) === 95 && id.charCodeAt(1) === 95 && id.charCodeAt(2) === 95 ? id.substr(1) : id; + return id.length >= 3 && id.charCodeAt(0) === 95 /* _ */ && id.charCodeAt(1) === 95 /* _ */ && id.charCodeAt(2) === 95 /* _ */ ? id.substr(1) : id; } ts.unescapeLeadingUnderscores = unescapeLeadingUnderscores; function idText(identifier) { @@ -10556,42 +11924,55 @@ var ts; return unescapeLeadingUnderscores(symbol.escapedName); } ts.symbolName = symbolName; + /** + * Remove extra underscore from escaped identifier text content. + * @deprecated Use `id.text` for the unescaped text. + * @param identifier The escaped identifier text. + * @returns The unescaped identifier text. + */ function unescapeIdentifier(id) { return id; } ts.unescapeIdentifier = unescapeIdentifier; + /** + * A JSDocTypedef tag has an _optional_ name field - if a name is not directly present, we should + * attempt to draw the name from the node the declaration is on (as that declaration is what its' symbol + * will be merged with) + */ function nameForNamelessJSDocTypedef(declaration) { var hostNode = declaration.parent.parent; if (!hostNode) { return undefined; } + // Covers classes, functions - any named declaration host node if (ts.isDeclaration(hostNode)) { return getDeclarationIdentifier(hostNode); } + // Covers remaining cases switch (hostNode.kind) { - case 214: + case 214 /* VariableStatement */: if (hostNode.declarationList && hostNode.declarationList.declarations[0]) { return getDeclarationIdentifier(hostNode.declarationList.declarations[0]); } return undefined; - case 216: + case 216 /* ExpressionStatement */: var expr = hostNode.expression; switch (expr.kind) { - case 185: + case 185 /* PropertyAccessExpression */: return expr.name; - case 186: + case 186 /* ElementAccessExpression */: var arg = expr.argumentExpression; if (ts.isIdentifier(arg)) { return arg; } } return undefined; - case 1: + case 1 /* EndOfFileToken */: return undefined; - case 191: { + case 191 /* ParenthesizedExpression */: { return getDeclarationIdentifier(hostNode.expression); } - case 228: { + case 228 /* LabeledStatement */: { if (ts.isDeclaration(hostNode.statement) || ts.isExpression(hostNode.statement)) { return getDeclarationIdentifier(hostNode.statement); } @@ -10609,48 +11990,50 @@ var ts; return declaration.name || nameForNamelessJSDocTypedef(declaration); } ts.getNameOfJSDocTypedef = getNameOfJSDocTypedef; + /** @internal */ function isNamedDeclaration(node) { - return !!node.name; + return !!node.name; // A 'name' property should always be a DeclarationName. } ts.isNamedDeclaration = isNamedDeclaration; + // TODO: GH#18217 This is often used as if it returns a defined result function getNameOfDeclaration(declaration) { if (!declaration) { return undefined; } switch (declaration.kind) { - case 205: - case 192: + case 205 /* ClassExpression */: + case 192 /* FunctionExpression */: if (!declaration.name) { return getAssignedName(declaration); } break; - case 71: + case 71 /* Identifier */: return declaration; - case 299: - case 293: { + case 299 /* JSDocPropertyTag */: + case 293 /* JSDocParameterTag */: { var name = declaration.name; - if (name.kind === 146) { + if (name.kind === 146 /* QualifiedName */) { return name.right; } break; } - case 200: { + case 200 /* BinaryExpression */: { var expr = declaration; switch (ts.getSpecialPropertyAssignmentKind(expr)) { - case 1: - case 4: - case 5: - case 3: + case 1 /* ExportsProperty */: + case 4 /* ThisProperty */: + case 5 /* Property */: + case 3 /* PrototypeProperty */: return expr.left.name; default: return undefined; } } - case 292: + case 292 /* JSDocCallbackTag */: return declaration.name; - case 298: + case 298 /* JSDocTypedefTag */: return getNameOfJSDocTypedef(declaration); - case 249: { + case 249 /* ExportAssignment */: { var expression = declaration.expression; return ts.isIdentifier(expression) ? expression : undefined; } @@ -10674,6 +12057,19 @@ var ts; } } } + /** + * Gets the JSDoc parameter tags for the node if present. + * + * @remarks Returns any JSDoc param tag that matches the provided + * parameter, whether a param tag on a containing function + * expression, or a param tag on a variable declaration whose + * initializer is the containing function. The tags closest to the + * node are returned first, so in the previous example, the param + * tag on the containing function expression would be first. + * + * Does not return tags for binding patterns, because JSDoc matches + * parameters by name and binding patterns do not have a name. + */ function getJSDocParameterTags(param) { if (param.name) { if (ts.isIdentifier(param.name)) { @@ -10689,34 +12085,48 @@ var ts; } } } + // return empty array for: out-of-order binding patterns and JSDoc function syntax, which has un-named parameters return ts.emptyArray; } ts.getJSDocParameterTags = getJSDocParameterTags; + /** + * Return true if the node has JSDoc parameter tags. + * + * @remarks Includes parameter tags that are not directly on the node, + * for example on a variable declaration whose initializer is a function expression. + */ function hasJSDocParameterTags(node) { return !!getFirstJSDocTag(node, ts.isJSDocParameterTag); } ts.hasJSDocParameterTags = hasJSDocParameterTags; + /** Gets the JSDoc augments tag for the node if present */ function getJSDocAugmentsTag(node) { return getFirstJSDocTag(node, ts.isJSDocAugmentsTag); } ts.getJSDocAugmentsTag = getJSDocAugmentsTag; + /** Gets the JSDoc class tag for the node if present */ function getJSDocClassTag(node) { return getFirstJSDocTag(node, ts.isJSDocClassTag); } ts.getJSDocClassTag = getJSDocClassTag; + /** Gets the JSDoc this tag for the node if present */ function getJSDocThisTag(node) { return getFirstJSDocTag(node, ts.isJSDocThisTag); } ts.getJSDocThisTag = getJSDocThisTag; + /** Gets the JSDoc return tag for the node if present */ function getJSDocReturnTag(node) { return getFirstJSDocTag(node, ts.isJSDocReturnTag); } ts.getJSDocReturnTag = getJSDocReturnTag; + /** Gets the JSDoc template tag for the node if present */ function getJSDocTemplateTag(node) { return getFirstJSDocTag(node, ts.isJSDocTemplateTag); } ts.getJSDocTemplateTag = getJSDocTemplateTag; + /** Gets the JSDoc type tag for the node if present and valid */ function getJSDocTypeTag(node) { + // We should have already issued an error if there were multiple type jsdocs, so just use the first one. var tag = getFirstJSDocTag(node, ts.isJSDocTypeTag); if (tag && tag.typeExpression && tag.typeExpression.type) { return tag; @@ -10724,6 +12134,17 @@ var ts; return undefined; } ts.getJSDocTypeTag = getJSDocTypeTag; + /** + * Gets the type node for the node if provided via JSDoc. + * + * @remarks The search includes any JSDoc param tag that relates + * to the provided parameter, for example a type tag on the + * parameter itself, or a param tag on a containing function + * expression, or a param tag on a variable declaration whose + * initializer is the containing function. The tags closest to the + * node are examined first, so in the previous example, the type + * tag directly on the node would be returned. + */ function getJSDocType(node) { var tag = getFirstJSDocTag(node, ts.isJSDocTypeTag); if (!tag && ts.isParameter(node)) { @@ -10732,13 +12153,21 @@ var ts; return tag && tag.typeExpression && tag.typeExpression.type; } ts.getJSDocType = getJSDocType; + /** + * Gets the return type node for the node if provided via JSDoc's return tag. + * + * @remarks `getJSDocReturnTag` just gets the whole JSDoc tag. This function + * gets the type from inside the braces. + */ function getJSDocReturnType(node) { var returnTag = getJSDocReturnTag(node); return returnTag && returnTag.typeExpression && returnTag.typeExpression.type; } ts.getJSDocReturnType = getJSDocReturnType; + /** Get all JSDoc tags related to a node, including those on parent nodes. */ function getJSDocTags(node) { var tags = node.jsDocCache; + // If cache is 'null', that means we did the work of searching for JSDoc tags and came up with nothing. if (tags === undefined) { var comments = ts.getJSDocCommentsAndTags(node); ts.Debug.assert(comments.length < 2 || comments[0] !== comments[1]); @@ -10747,710 +12176,749 @@ var ts; return tags; } ts.getJSDocTags = getJSDocTags; + /** Get the first JSDoc tag of a specified kind, or undefined if not present. */ function getFirstJSDocTag(node, predicate) { return ts.find(getJSDocTags(node), predicate); } + /** Gets all JSDoc tags of a specified kind, or undefined if not present. */ function getAllJSDocTagsOfKind(node, kind) { return getJSDocTags(node).filter(function (doc) { return doc.kind === kind; }); } ts.getAllJSDocTagsOfKind = getAllJSDocTagsOfKind; })(ts || (ts = {})); +// Simple node tests of the form `node.kind === SyntaxKind.Foo`. (function (ts) { + // Literals function isNumericLiteral(node) { - return node.kind === 8; + return node.kind === 8 /* NumericLiteral */; } ts.isNumericLiteral = isNumericLiteral; function isStringLiteral(node) { - return node.kind === 9; + return node.kind === 9 /* StringLiteral */; } ts.isStringLiteral = isStringLiteral; function isJsxText(node) { - return node.kind === 10; + return node.kind === 10 /* JsxText */; } ts.isJsxText = isJsxText; function isRegularExpressionLiteral(node) { - return node.kind === 12; + return node.kind === 12 /* RegularExpressionLiteral */; } ts.isRegularExpressionLiteral = isRegularExpressionLiteral; function isNoSubstitutionTemplateLiteral(node) { - return node.kind === 13; + return node.kind === 13 /* NoSubstitutionTemplateLiteral */; } ts.isNoSubstitutionTemplateLiteral = isNoSubstitutionTemplateLiteral; + // Pseudo-literals function isTemplateHead(node) { - return node.kind === 14; + return node.kind === 14 /* TemplateHead */; } ts.isTemplateHead = isTemplateHead; function isTemplateMiddle(node) { - return node.kind === 15; + return node.kind === 15 /* TemplateMiddle */; } ts.isTemplateMiddle = isTemplateMiddle; function isTemplateTail(node) { - return node.kind === 16; + return node.kind === 16 /* TemplateTail */; } ts.isTemplateTail = isTemplateTail; function isIdentifier(node) { - return node.kind === 71; + return node.kind === 71 /* Identifier */; } ts.isIdentifier = isIdentifier; + // Names function isQualifiedName(node) { - return node.kind === 146; + return node.kind === 146 /* QualifiedName */; } ts.isQualifiedName = isQualifiedName; function isComputedPropertyName(node) { - return node.kind === 147; + return node.kind === 147 /* ComputedPropertyName */; } ts.isComputedPropertyName = isComputedPropertyName; + // Signature elements function isTypeParameterDeclaration(node) { - return node.kind === 148; + return node.kind === 148 /* TypeParameter */; } ts.isTypeParameterDeclaration = isTypeParameterDeclaration; function isParameter(node) { - return node.kind === 149; + return node.kind === 149 /* Parameter */; } ts.isParameter = isParameter; function isDecorator(node) { - return node.kind === 150; + return node.kind === 150 /* Decorator */; } ts.isDecorator = isDecorator; + // TypeMember function isPropertySignature(node) { - return node.kind === 151; + return node.kind === 151 /* PropertySignature */; } ts.isPropertySignature = isPropertySignature; function isPropertyDeclaration(node) { - return node.kind === 152; + return node.kind === 152 /* PropertyDeclaration */; } ts.isPropertyDeclaration = isPropertyDeclaration; function isMethodSignature(node) { - return node.kind === 153; + return node.kind === 153 /* MethodSignature */; } ts.isMethodSignature = isMethodSignature; function isMethodDeclaration(node) { - return node.kind === 154; + return node.kind === 154 /* MethodDeclaration */; } ts.isMethodDeclaration = isMethodDeclaration; function isConstructorDeclaration(node) { - return node.kind === 155; + return node.kind === 155 /* Constructor */; } ts.isConstructorDeclaration = isConstructorDeclaration; function isGetAccessorDeclaration(node) { - return node.kind === 156; + return node.kind === 156 /* GetAccessor */; } ts.isGetAccessorDeclaration = isGetAccessorDeclaration; function isSetAccessorDeclaration(node) { - return node.kind === 157; + return node.kind === 157 /* SetAccessor */; } ts.isSetAccessorDeclaration = isSetAccessorDeclaration; function isCallSignatureDeclaration(node) { - return node.kind === 158; + return node.kind === 158 /* CallSignature */; } ts.isCallSignatureDeclaration = isCallSignatureDeclaration; function isConstructSignatureDeclaration(node) { - return node.kind === 159; + return node.kind === 159 /* ConstructSignature */; } ts.isConstructSignatureDeclaration = isConstructSignatureDeclaration; function isIndexSignatureDeclaration(node) { - return node.kind === 160; + return node.kind === 160 /* IndexSignature */; } ts.isIndexSignatureDeclaration = isIndexSignatureDeclaration; + /* @internal */ function isGetOrSetAccessorDeclaration(node) { - return node.kind === 157 || node.kind === 156; + return node.kind === 157 /* SetAccessor */ || node.kind === 156 /* GetAccessor */; } ts.isGetOrSetAccessorDeclaration = isGetOrSetAccessorDeclaration; + // Type function isTypePredicateNode(node) { - return node.kind === 161; + return node.kind === 161 /* TypePredicate */; } ts.isTypePredicateNode = isTypePredicateNode; function isTypeReferenceNode(node) { - return node.kind === 162; + return node.kind === 162 /* TypeReference */; } ts.isTypeReferenceNode = isTypeReferenceNode; function isFunctionTypeNode(node) { - return node.kind === 163; + return node.kind === 163 /* FunctionType */; } ts.isFunctionTypeNode = isFunctionTypeNode; function isConstructorTypeNode(node) { - return node.kind === 164; + return node.kind === 164 /* ConstructorType */; } ts.isConstructorTypeNode = isConstructorTypeNode; function isTypeQueryNode(node) { - return node.kind === 165; + return node.kind === 165 /* TypeQuery */; } ts.isTypeQueryNode = isTypeQueryNode; function isTypeLiteralNode(node) { - return node.kind === 166; + return node.kind === 166 /* TypeLiteral */; } ts.isTypeLiteralNode = isTypeLiteralNode; function isArrayTypeNode(node) { - return node.kind === 167; + return node.kind === 167 /* ArrayType */; } ts.isArrayTypeNode = isArrayTypeNode; function isTupleTypeNode(node) { - return node.kind === 168; + return node.kind === 168 /* TupleType */; } ts.isTupleTypeNode = isTupleTypeNode; function isUnionTypeNode(node) { - return node.kind === 169; + return node.kind === 169 /* UnionType */; } ts.isUnionTypeNode = isUnionTypeNode; function isIntersectionTypeNode(node) { - return node.kind === 170; + return node.kind === 170 /* IntersectionType */; } ts.isIntersectionTypeNode = isIntersectionTypeNode; function isConditionalTypeNode(node) { - return node.kind === 171; + return node.kind === 171 /* ConditionalType */; } ts.isConditionalTypeNode = isConditionalTypeNode; function isInferTypeNode(node) { - return node.kind === 172; + return node.kind === 172 /* InferType */; } ts.isInferTypeNode = isInferTypeNode; function isParenthesizedTypeNode(node) { - return node.kind === 173; + return node.kind === 173 /* ParenthesizedType */; } ts.isParenthesizedTypeNode = isParenthesizedTypeNode; function isThisTypeNode(node) { - return node.kind === 174; + return node.kind === 174 /* ThisType */; } ts.isThisTypeNode = isThisTypeNode; function isTypeOperatorNode(node) { - return node.kind === 175; + return node.kind === 175 /* TypeOperator */; } ts.isTypeOperatorNode = isTypeOperatorNode; function isIndexedAccessTypeNode(node) { - return node.kind === 176; + return node.kind === 176 /* IndexedAccessType */; } ts.isIndexedAccessTypeNode = isIndexedAccessTypeNode; function isMappedTypeNode(node) { - return node.kind === 177; + return node.kind === 177 /* MappedType */; } ts.isMappedTypeNode = isMappedTypeNode; function isLiteralTypeNode(node) { - return node.kind === 178; + return node.kind === 178 /* LiteralType */; } ts.isLiteralTypeNode = isLiteralTypeNode; function isImportTypeNode(node) { - return node.kind === 179; + return node.kind === 179 /* ImportType */; } ts.isImportTypeNode = isImportTypeNode; + // Binding patterns function isObjectBindingPattern(node) { - return node.kind === 180; + return node.kind === 180 /* ObjectBindingPattern */; } ts.isObjectBindingPattern = isObjectBindingPattern; function isArrayBindingPattern(node) { - return node.kind === 181; + return node.kind === 181 /* ArrayBindingPattern */; } ts.isArrayBindingPattern = isArrayBindingPattern; function isBindingElement(node) { - return node.kind === 182; + return node.kind === 182 /* BindingElement */; } ts.isBindingElement = isBindingElement; + // Expression function isArrayLiteralExpression(node) { - return node.kind === 183; + return node.kind === 183 /* ArrayLiteralExpression */; } ts.isArrayLiteralExpression = isArrayLiteralExpression; function isObjectLiteralExpression(node) { - return node.kind === 184; + return node.kind === 184 /* ObjectLiteralExpression */; } ts.isObjectLiteralExpression = isObjectLiteralExpression; function isPropertyAccessExpression(node) { - return node.kind === 185; + return node.kind === 185 /* PropertyAccessExpression */; } ts.isPropertyAccessExpression = isPropertyAccessExpression; function isElementAccessExpression(node) { - return node.kind === 186; + return node.kind === 186 /* ElementAccessExpression */; } ts.isElementAccessExpression = isElementAccessExpression; function isCallExpression(node) { - return node.kind === 187; + return node.kind === 187 /* CallExpression */; } ts.isCallExpression = isCallExpression; function isNewExpression(node) { - return node.kind === 188; + return node.kind === 188 /* NewExpression */; } ts.isNewExpression = isNewExpression; function isTaggedTemplateExpression(node) { - return node.kind === 189; + return node.kind === 189 /* TaggedTemplateExpression */; } ts.isTaggedTemplateExpression = isTaggedTemplateExpression; function isTypeAssertion(node) { - return node.kind === 190; + return node.kind === 190 /* TypeAssertionExpression */; } ts.isTypeAssertion = isTypeAssertion; function isParenthesizedExpression(node) { - return node.kind === 191; + return node.kind === 191 /* ParenthesizedExpression */; } ts.isParenthesizedExpression = isParenthesizedExpression; function skipPartiallyEmittedExpressions(node) { - while (node.kind === 302) { + while (node.kind === 302 /* PartiallyEmittedExpression */) { node = node.expression; } return node; } ts.skipPartiallyEmittedExpressions = skipPartiallyEmittedExpressions; function isFunctionExpression(node) { - return node.kind === 192; + return node.kind === 192 /* FunctionExpression */; } ts.isFunctionExpression = isFunctionExpression; function isArrowFunction(node) { - return node.kind === 193; + return node.kind === 193 /* ArrowFunction */; } ts.isArrowFunction = isArrowFunction; function isDeleteExpression(node) { - return node.kind === 194; + return node.kind === 194 /* DeleteExpression */; } ts.isDeleteExpression = isDeleteExpression; function isTypeOfExpression(node) { - return node.kind === 195; + return node.kind === 195 /* TypeOfExpression */; } ts.isTypeOfExpression = isTypeOfExpression; function isVoidExpression(node) { - return node.kind === 196; + return node.kind === 196 /* VoidExpression */; } ts.isVoidExpression = isVoidExpression; function isAwaitExpression(node) { - return node.kind === 197; + return node.kind === 197 /* AwaitExpression */; } ts.isAwaitExpression = isAwaitExpression; function isPrefixUnaryExpression(node) { - return node.kind === 198; + return node.kind === 198 /* PrefixUnaryExpression */; } ts.isPrefixUnaryExpression = isPrefixUnaryExpression; function isPostfixUnaryExpression(node) { - return node.kind === 199; + return node.kind === 199 /* PostfixUnaryExpression */; } ts.isPostfixUnaryExpression = isPostfixUnaryExpression; function isBinaryExpression(node) { - return node.kind === 200; + return node.kind === 200 /* BinaryExpression */; } ts.isBinaryExpression = isBinaryExpression; function isConditionalExpression(node) { - return node.kind === 201; + return node.kind === 201 /* ConditionalExpression */; } ts.isConditionalExpression = isConditionalExpression; function isTemplateExpression(node) { - return node.kind === 202; + return node.kind === 202 /* TemplateExpression */; } ts.isTemplateExpression = isTemplateExpression; function isYieldExpression(node) { - return node.kind === 203; + return node.kind === 203 /* YieldExpression */; } ts.isYieldExpression = isYieldExpression; function isSpreadElement(node) { - return node.kind === 204; + return node.kind === 204 /* SpreadElement */; } ts.isSpreadElement = isSpreadElement; function isClassExpression(node) { - return node.kind === 205; + return node.kind === 205 /* ClassExpression */; } ts.isClassExpression = isClassExpression; function isOmittedExpression(node) { - return node.kind === 206; + return node.kind === 206 /* OmittedExpression */; } ts.isOmittedExpression = isOmittedExpression; function isExpressionWithTypeArguments(node) { - return node.kind === 207; + return node.kind === 207 /* ExpressionWithTypeArguments */; } ts.isExpressionWithTypeArguments = isExpressionWithTypeArguments; function isAsExpression(node) { - return node.kind === 208; + return node.kind === 208 /* AsExpression */; } ts.isAsExpression = isAsExpression; function isNonNullExpression(node) { - return node.kind === 209; + return node.kind === 209 /* NonNullExpression */; } ts.isNonNullExpression = isNonNullExpression; function isMetaProperty(node) { - return node.kind === 210; + return node.kind === 210 /* MetaProperty */; } ts.isMetaProperty = isMetaProperty; + // Misc function isTemplateSpan(node) { - return node.kind === 211; + return node.kind === 211 /* TemplateSpan */; } ts.isTemplateSpan = isTemplateSpan; function isSemicolonClassElement(node) { - return node.kind === 212; + return node.kind === 212 /* SemicolonClassElement */; } ts.isSemicolonClassElement = isSemicolonClassElement; + // Block function isBlock(node) { - return node.kind === 213; + return node.kind === 213 /* Block */; } ts.isBlock = isBlock; function isVariableStatement(node) { - return node.kind === 214; + return node.kind === 214 /* VariableStatement */; } ts.isVariableStatement = isVariableStatement; function isEmptyStatement(node) { - return node.kind === 215; + return node.kind === 215 /* EmptyStatement */; } ts.isEmptyStatement = isEmptyStatement; function isExpressionStatement(node) { - return node.kind === 216; + return node.kind === 216 /* ExpressionStatement */; } ts.isExpressionStatement = isExpressionStatement; function isIfStatement(node) { - return node.kind === 217; + return node.kind === 217 /* IfStatement */; } ts.isIfStatement = isIfStatement; function isDoStatement(node) { - return node.kind === 218; + return node.kind === 218 /* DoStatement */; } ts.isDoStatement = isDoStatement; function isWhileStatement(node) { - return node.kind === 219; + return node.kind === 219 /* WhileStatement */; } ts.isWhileStatement = isWhileStatement; function isForStatement(node) { - return node.kind === 220; + return node.kind === 220 /* ForStatement */; } ts.isForStatement = isForStatement; function isForInStatement(node) { - return node.kind === 221; + return node.kind === 221 /* ForInStatement */; } ts.isForInStatement = isForInStatement; function isForOfStatement(node) { - return node.kind === 222; + return node.kind === 222 /* ForOfStatement */; } ts.isForOfStatement = isForOfStatement; function isContinueStatement(node) { - return node.kind === 223; + return node.kind === 223 /* ContinueStatement */; } ts.isContinueStatement = isContinueStatement; function isBreakStatement(node) { - return node.kind === 224; + return node.kind === 224 /* BreakStatement */; } ts.isBreakStatement = isBreakStatement; function isBreakOrContinueStatement(node) { - return node.kind === 224 || node.kind === 223; + return node.kind === 224 /* BreakStatement */ || node.kind === 223 /* ContinueStatement */; } ts.isBreakOrContinueStatement = isBreakOrContinueStatement; function isReturnStatement(node) { - return node.kind === 225; + return node.kind === 225 /* ReturnStatement */; } ts.isReturnStatement = isReturnStatement; function isWithStatement(node) { - return node.kind === 226; + return node.kind === 226 /* WithStatement */; } ts.isWithStatement = isWithStatement; function isSwitchStatement(node) { - return node.kind === 227; + return node.kind === 227 /* SwitchStatement */; } ts.isSwitchStatement = isSwitchStatement; function isLabeledStatement(node) { - return node.kind === 228; + return node.kind === 228 /* LabeledStatement */; } ts.isLabeledStatement = isLabeledStatement; function isThrowStatement(node) { - return node.kind === 229; + return node.kind === 229 /* ThrowStatement */; } ts.isThrowStatement = isThrowStatement; function isTryStatement(node) { - return node.kind === 230; + return node.kind === 230 /* TryStatement */; } ts.isTryStatement = isTryStatement; function isDebuggerStatement(node) { - return node.kind === 231; + return node.kind === 231 /* DebuggerStatement */; } ts.isDebuggerStatement = isDebuggerStatement; function isVariableDeclaration(node) { - return node.kind === 232; + return node.kind === 232 /* VariableDeclaration */; } ts.isVariableDeclaration = isVariableDeclaration; function isVariableDeclarationList(node) { - return node.kind === 233; + return node.kind === 233 /* VariableDeclarationList */; } ts.isVariableDeclarationList = isVariableDeclarationList; function isFunctionDeclaration(node) { - return node.kind === 234; + return node.kind === 234 /* FunctionDeclaration */; } ts.isFunctionDeclaration = isFunctionDeclaration; function isClassDeclaration(node) { - return node.kind === 235; + return node.kind === 235 /* ClassDeclaration */; } ts.isClassDeclaration = isClassDeclaration; function isInterfaceDeclaration(node) { - return node.kind === 236; + return node.kind === 236 /* InterfaceDeclaration */; } ts.isInterfaceDeclaration = isInterfaceDeclaration; function isTypeAliasDeclaration(node) { - return node.kind === 237; + return node.kind === 237 /* TypeAliasDeclaration */; } ts.isTypeAliasDeclaration = isTypeAliasDeclaration; function isEnumDeclaration(node) { - return node.kind === 238; + return node.kind === 238 /* EnumDeclaration */; } ts.isEnumDeclaration = isEnumDeclaration; function isModuleDeclaration(node) { - return node.kind === 239; + return node.kind === 239 /* ModuleDeclaration */; } ts.isModuleDeclaration = isModuleDeclaration; function isModuleBlock(node) { - return node.kind === 240; + return node.kind === 240 /* ModuleBlock */; } ts.isModuleBlock = isModuleBlock; function isCaseBlock(node) { - return node.kind === 241; + return node.kind === 241 /* CaseBlock */; } ts.isCaseBlock = isCaseBlock; function isNamespaceExportDeclaration(node) { - return node.kind === 242; + return node.kind === 242 /* NamespaceExportDeclaration */; } ts.isNamespaceExportDeclaration = isNamespaceExportDeclaration; function isImportEqualsDeclaration(node) { - return node.kind === 243; + return node.kind === 243 /* ImportEqualsDeclaration */; } ts.isImportEqualsDeclaration = isImportEqualsDeclaration; function isImportDeclaration(node) { - return node.kind === 244; + return node.kind === 244 /* ImportDeclaration */; } ts.isImportDeclaration = isImportDeclaration; function isImportClause(node) { - return node.kind === 245; + return node.kind === 245 /* ImportClause */; } ts.isImportClause = isImportClause; function isNamespaceImport(node) { - return node.kind === 246; + return node.kind === 246 /* NamespaceImport */; } ts.isNamespaceImport = isNamespaceImport; function isNamedImports(node) { - return node.kind === 247; + return node.kind === 247 /* NamedImports */; } ts.isNamedImports = isNamedImports; function isImportSpecifier(node) { - return node.kind === 248; + return node.kind === 248 /* ImportSpecifier */; } ts.isImportSpecifier = isImportSpecifier; function isExportAssignment(node) { - return node.kind === 249; + return node.kind === 249 /* ExportAssignment */; } ts.isExportAssignment = isExportAssignment; function isExportDeclaration(node) { - return node.kind === 250; + return node.kind === 250 /* ExportDeclaration */; } ts.isExportDeclaration = isExportDeclaration; function isNamedExports(node) { - return node.kind === 251; + return node.kind === 251 /* NamedExports */; } ts.isNamedExports = isNamedExports; function isExportSpecifier(node) { - return node.kind === 252; + return node.kind === 252 /* ExportSpecifier */; } ts.isExportSpecifier = isExportSpecifier; function isMissingDeclaration(node) { - return node.kind === 253; + return node.kind === 253 /* MissingDeclaration */; } ts.isMissingDeclaration = isMissingDeclaration; + // Module References function isExternalModuleReference(node) { - return node.kind === 254; + return node.kind === 254 /* ExternalModuleReference */; } ts.isExternalModuleReference = isExternalModuleReference; + // JSX function isJsxElement(node) { - return node.kind === 255; + return node.kind === 255 /* JsxElement */; } ts.isJsxElement = isJsxElement; function isJsxSelfClosingElement(node) { - return node.kind === 256; + return node.kind === 256 /* JsxSelfClosingElement */; } ts.isJsxSelfClosingElement = isJsxSelfClosingElement; function isJsxOpeningElement(node) { - return node.kind === 257; + return node.kind === 257 /* JsxOpeningElement */; } ts.isJsxOpeningElement = isJsxOpeningElement; function isJsxClosingElement(node) { - return node.kind === 258; + return node.kind === 258 /* JsxClosingElement */; } ts.isJsxClosingElement = isJsxClosingElement; function isJsxFragment(node) { - return node.kind === 259; + return node.kind === 259 /* JsxFragment */; } ts.isJsxFragment = isJsxFragment; function isJsxOpeningFragment(node) { - return node.kind === 260; + return node.kind === 260 /* JsxOpeningFragment */; } ts.isJsxOpeningFragment = isJsxOpeningFragment; function isJsxClosingFragment(node) { - return node.kind === 261; + return node.kind === 261 /* JsxClosingFragment */; } ts.isJsxClosingFragment = isJsxClosingFragment; function isJsxAttribute(node) { - return node.kind === 262; + return node.kind === 262 /* JsxAttribute */; } ts.isJsxAttribute = isJsxAttribute; function isJsxAttributes(node) { - return node.kind === 263; + return node.kind === 263 /* JsxAttributes */; } ts.isJsxAttributes = isJsxAttributes; function isJsxSpreadAttribute(node) { - return node.kind === 264; + return node.kind === 264 /* JsxSpreadAttribute */; } ts.isJsxSpreadAttribute = isJsxSpreadAttribute; function isJsxExpression(node) { - return node.kind === 265; + return node.kind === 265 /* JsxExpression */; } ts.isJsxExpression = isJsxExpression; + // Clauses function isCaseClause(node) { - return node.kind === 266; + return node.kind === 266 /* CaseClause */; } ts.isCaseClause = isCaseClause; function isDefaultClause(node) { - return node.kind === 267; + return node.kind === 267 /* DefaultClause */; } ts.isDefaultClause = isDefaultClause; function isHeritageClause(node) { - return node.kind === 268; + return node.kind === 268 /* HeritageClause */; } ts.isHeritageClause = isHeritageClause; function isCatchClause(node) { - return node.kind === 269; + return node.kind === 269 /* CatchClause */; } ts.isCatchClause = isCatchClause; + // Property assignments function isPropertyAssignment(node) { - return node.kind === 270; + return node.kind === 270 /* PropertyAssignment */; } ts.isPropertyAssignment = isPropertyAssignment; function isShorthandPropertyAssignment(node) { - return node.kind === 271; + return node.kind === 271 /* ShorthandPropertyAssignment */; } ts.isShorthandPropertyAssignment = isShorthandPropertyAssignment; function isSpreadAssignment(node) { - return node.kind === 272; + return node.kind === 272 /* SpreadAssignment */; } ts.isSpreadAssignment = isSpreadAssignment; + // Enum function isEnumMember(node) { - return node.kind === 273; + return node.kind === 273 /* EnumMember */; } ts.isEnumMember = isEnumMember; + // Top-level nodes function isSourceFile(node) { - return node.kind === 274; + return node.kind === 274 /* SourceFile */; } ts.isSourceFile = isSourceFile; function isBundle(node) { - return node.kind === 275; + return node.kind === 275 /* Bundle */; } ts.isBundle = isBundle; function isUnparsedSource(node) { - return node.kind === 276; + return node.kind === 276 /* UnparsedSource */; } ts.isUnparsedSource = isUnparsedSource; + // JSDoc function isJSDocTypeExpression(node) { - return node.kind === 278; + return node.kind === 278 /* JSDocTypeExpression */; } ts.isJSDocTypeExpression = isJSDocTypeExpression; function isJSDocAllType(node) { - return node.kind === 279; + return node.kind === 279 /* JSDocAllType */; } ts.isJSDocAllType = isJSDocAllType; function isJSDocUnknownType(node) { - return node.kind === 280; + return node.kind === 280 /* JSDocUnknownType */; } ts.isJSDocUnknownType = isJSDocUnknownType; function isJSDocNullableType(node) { - return node.kind === 281; + return node.kind === 281 /* JSDocNullableType */; } ts.isJSDocNullableType = isJSDocNullableType; function isJSDocNonNullableType(node) { - return node.kind === 282; + return node.kind === 282 /* JSDocNonNullableType */; } ts.isJSDocNonNullableType = isJSDocNonNullableType; function isJSDocOptionalType(node) { - return node.kind === 283; + return node.kind === 283 /* JSDocOptionalType */; } ts.isJSDocOptionalType = isJSDocOptionalType; function isJSDocFunctionType(node) { - return node.kind === 284; + return node.kind === 284 /* JSDocFunctionType */; } ts.isJSDocFunctionType = isJSDocFunctionType; function isJSDocVariadicType(node) { - return node.kind === 285; + return node.kind === 285 /* JSDocVariadicType */; } ts.isJSDocVariadicType = isJSDocVariadicType; function isJSDoc(node) { - return node.kind === 286; + return node.kind === 286 /* JSDocComment */; } ts.isJSDoc = isJSDoc; function isJSDocAugmentsTag(node) { - return node.kind === 290; + return node.kind === 290 /* JSDocAugmentsTag */; } ts.isJSDocAugmentsTag = isJSDocAugmentsTag; function isJSDocClassTag(node) { - return node.kind === 291; + return node.kind === 291 /* JSDocClassTag */; } ts.isJSDocClassTag = isJSDocClassTag; function isJSDocThisTag(node) { - return node.kind === 295; + return node.kind === 295 /* JSDocThisTag */; } ts.isJSDocThisTag = isJSDocThisTag; function isJSDocParameterTag(node) { - return node.kind === 293; + return node.kind === 293 /* JSDocParameterTag */; } ts.isJSDocParameterTag = isJSDocParameterTag; function isJSDocReturnTag(node) { - return node.kind === 294; + return node.kind === 294 /* JSDocReturnTag */; } ts.isJSDocReturnTag = isJSDocReturnTag; function isJSDocTypeTag(node) { - return node.kind === 296; + return node.kind === 296 /* JSDocTypeTag */; } ts.isJSDocTypeTag = isJSDocTypeTag; function isJSDocTemplateTag(node) { - return node.kind === 297; + return node.kind === 297 /* JSDocTemplateTag */; } ts.isJSDocTemplateTag = isJSDocTemplateTag; function isJSDocTypedefTag(node) { - return node.kind === 298; + return node.kind === 298 /* JSDocTypedefTag */; } ts.isJSDocTypedefTag = isJSDocTypedefTag; function isJSDocPropertyTag(node) { - return node.kind === 299; + return node.kind === 299 /* JSDocPropertyTag */; } ts.isJSDocPropertyTag = isJSDocPropertyTag; function isJSDocPropertyLikeTag(node) { - return node.kind === 299 || node.kind === 293; + return node.kind === 299 /* JSDocPropertyTag */ || node.kind === 293 /* JSDocParameterTag */; } ts.isJSDocPropertyLikeTag = isJSDocPropertyLikeTag; function isJSDocTypeLiteral(node) { - return node.kind === 287; + return node.kind === 287 /* JSDocTypeLiteral */; } ts.isJSDocTypeLiteral = isJSDocTypeLiteral; function isJSDocCallbackTag(node) { - return node.kind === 292; + return node.kind === 292 /* JSDocCallbackTag */; } ts.isJSDocCallbackTag = isJSDocCallbackTag; function isJSDocSignature(node) { - return node.kind === 288; + return node.kind === 288 /* JSDocSignature */; } ts.isJSDocSignature = isJSDocSignature; })(ts || (ts = {})); +// Node tests +// +// All node tests in the following list should *not* reference parent pointers so that +// they may be used with transformations. (function (ts) { + /* @internal */ function isSyntaxList(n) { - return n.kind === 300; + return n.kind === 300 /* SyntaxList */; } ts.isSyntaxList = isSyntaxList; + /* @internal */ function isNode(node) { return isNodeKind(node.kind); } ts.isNode = isNode; + /* @internal */ function isNodeKind(kind) { - return kind >= 146; + return kind >= 146 /* FirstNode */; } ts.isNodeKind = isNodeKind; + /** + * True if node is of some token syntax kind. + * For example, this is true for an IfKeyword but not for an IfStatement. + * Literals are considered tokens, except TemplateLiteral, but does include TemplateHead/Middle/Tail. + */ function isToken(n) { - return n.kind >= 0 && n.kind <= 145; + return n.kind >= 0 /* FirstToken */ && n.kind <= 145 /* LastToken */; } ts.isToken = isToken; + // Node Arrays + /* @internal */ function isNodeArray(array) { return array.hasOwnProperty("pos") && array.hasOwnProperty("end"); } ts.isNodeArray = isNodeArray; + // Literals + /* @internal */ function isLiteralKind(kind) { - return 8 <= kind && kind <= 13; + return 8 /* FirstLiteralToken */ <= kind && kind <= 13 /* LastLiteralToken */; } ts.isLiteralKind = isLiteralKind; function isLiteralExpression(node) { return isLiteralKind(node.kind); } ts.isLiteralExpression = isLiteralExpression; + // Pseudo-literals + /* @internal */ function isTemplateLiteralKind(kind) { - return 13 <= kind && kind <= 16; + return 13 /* FirstTemplateToken */ <= kind && kind <= 16 /* LastTemplateToken */; } ts.isTemplateLiteralKind = isTemplateLiteralKind; function isTemplateLiteralToken(node) { @@ -11459,42 +12927,48 @@ var ts; ts.isTemplateLiteralToken = isTemplateLiteralToken; function isTemplateMiddleOrTemplateTail(node) { var kind = node.kind; - return kind === 15 - || kind === 16; + return kind === 15 /* TemplateMiddle */ + || kind === 16 /* TemplateTail */; } ts.isTemplateMiddleOrTemplateTail = isTemplateMiddleOrTemplateTail; function isStringTextContainingNode(node) { - return node.kind === 9 || isTemplateLiteralKind(node.kind); + return node.kind === 9 /* StringLiteral */ || isTemplateLiteralKind(node.kind); } ts.isStringTextContainingNode = isStringTextContainingNode; + // Identifiers + /* @internal */ function isGeneratedIdentifier(node) { - return ts.isIdentifier(node) && (node.autoGenerateFlags & 7) > 0; + return ts.isIdentifier(node) && (node.autoGenerateFlags & 7 /* KindMask */) > 0 /* None */; } ts.isGeneratedIdentifier = isGeneratedIdentifier; + // Keywords + /* @internal */ function isModifierKind(token) { switch (token) { - case 117: - case 120: - case 76: - case 124: - case 79: - case 84: - case 114: - case 112: - case 113: - case 132: - case 115: + case 117 /* AbstractKeyword */: + case 120 /* AsyncKeyword */: + case 76 /* ConstKeyword */: + case 124 /* DeclareKeyword */: + case 79 /* DefaultKeyword */: + case 84 /* ExportKeyword */: + case 114 /* PublicKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: + case 132 /* ReadonlyKeyword */: + case 115 /* StaticKeyword */: return true; } return false; } ts.isModifierKind = isModifierKind; + /* @internal */ function isParameterPropertyModifier(kind) { - return !!(ts.modifierToFlag(kind) & 92); + return !!(ts.modifierToFlag(kind) & 92 /* ParameterPropertyModifier */); } ts.isParameterPropertyModifier = isParameterPropertyModifier; + /* @internal */ function isClassMemberModifier(idToken) { - return isParameterPropertyModifier(idToken) || idToken === 115; + return isParameterPropertyModifier(idToken) || idToken === 115 /* StaticKeyword */; } ts.isClassMemberModifier = isClassMemberModifier; function isModifier(node) { @@ -11503,104 +12977,111 @@ var ts; ts.isModifier = isModifier; function isEntityName(node) { var kind = node.kind; - return kind === 146 - || kind === 71; + return kind === 146 /* QualifiedName */ + || kind === 71 /* Identifier */; } ts.isEntityName = isEntityName; function isPropertyName(node) { var kind = node.kind; - return kind === 71 - || kind === 9 - || kind === 8 - || kind === 147; + return kind === 71 /* Identifier */ + || kind === 9 /* StringLiteral */ + || kind === 8 /* NumericLiteral */ + || kind === 147 /* ComputedPropertyName */; } ts.isPropertyName = isPropertyName; function isBindingName(node) { var kind = node.kind; - return kind === 71 - || kind === 180 - || kind === 181; + return kind === 71 /* Identifier */ + || kind === 180 /* ObjectBindingPattern */ + || kind === 181 /* ArrayBindingPattern */; } ts.isBindingName = isBindingName; + // Functions function isFunctionLike(node) { return node && isFunctionLikeKind(node.kind); } ts.isFunctionLike = isFunctionLike; + /* @internal */ function isFunctionLikeDeclaration(node) { return node && isFunctionLikeDeclarationKind(node.kind); } ts.isFunctionLikeDeclaration = isFunctionLikeDeclaration; function isFunctionLikeDeclarationKind(kind) { switch (kind) { - case 234: - case 154: - case 155: - case 156: - case 157: - case 192: - case 193: + case 234 /* FunctionDeclaration */: + case 154 /* MethodDeclaration */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: return true; default: return false; } } + /* @internal */ function isFunctionLikeKind(kind) { switch (kind) { - case 153: - case 158: - case 288: - case 159: - case 160: - case 163: - case 284: - case 164: + case 153 /* MethodSignature */: + case 158 /* CallSignature */: + case 288 /* JSDocSignature */: + case 159 /* ConstructSignature */: + case 160 /* IndexSignature */: + case 163 /* FunctionType */: + case 284 /* JSDocFunctionType */: + case 164 /* ConstructorType */: return true; default: return isFunctionLikeDeclarationKind(kind); } } ts.isFunctionLikeKind = isFunctionLikeKind; + /* @internal */ function isFunctionOrModuleBlock(node) { return ts.isSourceFile(node) || ts.isModuleBlock(node) || ts.isBlock(node) && isFunctionLike(node.parent); } ts.isFunctionOrModuleBlock = isFunctionOrModuleBlock; + // Classes function isClassElement(node) { var kind = node.kind; - return kind === 155 - || kind === 152 - || kind === 154 - || kind === 156 - || kind === 157 - || kind === 160 - || kind === 212; + return kind === 155 /* Constructor */ + || kind === 152 /* PropertyDeclaration */ + || kind === 154 /* MethodDeclaration */ + || kind === 156 /* GetAccessor */ + || kind === 157 /* SetAccessor */ + || kind === 160 /* IndexSignature */ + || kind === 212 /* SemicolonClassElement */; } ts.isClassElement = isClassElement; function isClassLike(node) { - return node && (node.kind === 235 || node.kind === 205); + return node && (node.kind === 235 /* ClassDeclaration */ || node.kind === 205 /* ClassExpression */); } ts.isClassLike = isClassLike; function isAccessor(node) { - return node && (node.kind === 156 || node.kind === 157); + return node && (node.kind === 156 /* GetAccessor */ || node.kind === 157 /* SetAccessor */); } ts.isAccessor = isAccessor; + /* @internal */ function isMethodOrAccessor(node) { switch (node.kind) { - case 154: - case 156: - case 157: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return true; default: return false; } } ts.isMethodOrAccessor = isMethodOrAccessor; + // Type members function isTypeElement(node) { var kind = node.kind; - return kind === 159 - || kind === 158 - || kind === 151 - || kind === 153 - || kind === 160; + return kind === 159 /* ConstructSignature */ + || kind === 158 /* CallSignature */ + || kind === 151 /* PropertySignature */ + || kind === 153 /* MethodSignature */ + || kind === 160 /* IndexSignature */; } ts.isTypeElement = isTypeElement; function isClassOrTypeElement(node) { @@ -11609,125 +13090,153 @@ var ts; ts.isClassOrTypeElement = isClassOrTypeElement; function isObjectLiteralElementLike(node) { var kind = node.kind; - return kind === 270 - || kind === 271 - || kind === 272 - || kind === 154 - || kind === 156 - || kind === 157; + return kind === 270 /* PropertyAssignment */ + || kind === 271 /* ShorthandPropertyAssignment */ + || kind === 272 /* SpreadAssignment */ + || kind === 154 /* MethodDeclaration */ + || kind === 156 /* GetAccessor */ + || kind === 157 /* SetAccessor */; } ts.isObjectLiteralElementLike = isObjectLiteralElementLike; + // Type function isTypeNodeKind(kind) { - return (kind >= 161 && kind <= 179) - || kind === 119 - || kind === 142 - || kind === 134 - || kind === 135 - || kind === 122 - || kind === 137 - || kind === 138 - || kind === 99 - || kind === 105 - || kind === 140 - || kind === 95 - || kind === 131 - || kind === 207 - || kind === 279 - || kind === 280 - || kind === 281 - || kind === 282 - || kind === 283 - || kind === 284 - || kind === 285; + return (kind >= 161 /* FirstTypeNode */ && kind <= 179 /* LastTypeNode */) + || kind === 119 /* AnyKeyword */ + || kind === 142 /* UnknownKeyword */ + || kind === 134 /* NumberKeyword */ + || kind === 135 /* ObjectKeyword */ + || kind === 122 /* BooleanKeyword */ + || kind === 137 /* StringKeyword */ + || kind === 138 /* SymbolKeyword */ + || kind === 99 /* ThisKeyword */ + || kind === 105 /* VoidKeyword */ + || kind === 140 /* UndefinedKeyword */ + || kind === 95 /* NullKeyword */ + || kind === 131 /* NeverKeyword */ + || kind === 207 /* ExpressionWithTypeArguments */ + || kind === 279 /* JSDocAllType */ + || kind === 280 /* JSDocUnknownType */ + || kind === 281 /* JSDocNullableType */ + || kind === 282 /* JSDocNonNullableType */ + || kind === 283 /* JSDocOptionalType */ + || kind === 284 /* JSDocFunctionType */ + || kind === 285 /* JSDocVariadicType */; } + /** + * Node test that determines whether a node is a valid type node. + * This differs from the `isPartOfTypeNode` function which determines whether a node is *part* + * of a TypeNode. + */ function isTypeNode(node) { return isTypeNodeKind(node.kind); } ts.isTypeNode = isTypeNode; function isFunctionOrConstructorTypeNode(node) { switch (node.kind) { - case 163: - case 164: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: return true; } return false; } ts.isFunctionOrConstructorTypeNode = isFunctionOrConstructorTypeNode; + // Binding patterns + /* @internal */ function isBindingPattern(node) { if (node) { var kind = node.kind; - return kind === 181 - || kind === 180; + return kind === 181 /* ArrayBindingPattern */ + || kind === 180 /* ObjectBindingPattern */; } return false; } ts.isBindingPattern = isBindingPattern; + /* @internal */ function isAssignmentPattern(node) { var kind = node.kind; - return kind === 183 - || kind === 184; + return kind === 183 /* ArrayLiteralExpression */ + || kind === 184 /* ObjectLiteralExpression */; } ts.isAssignmentPattern = isAssignmentPattern; + /* @internal */ function isArrayBindingElement(node) { var kind = node.kind; - return kind === 182 - || kind === 206; + return kind === 182 /* BindingElement */ + || kind === 206 /* OmittedExpression */; } ts.isArrayBindingElement = isArrayBindingElement; + /** + * Determines whether the BindingOrAssignmentElement is a BindingElement-like declaration + */ + /* @internal */ function isDeclarationBindingElement(bindingElement) { switch (bindingElement.kind) { - case 232: - case 149: - case 182: + case 232 /* VariableDeclaration */: + case 149 /* Parameter */: + case 182 /* BindingElement */: return true; } return false; } ts.isDeclarationBindingElement = isDeclarationBindingElement; + /** + * Determines whether a node is a BindingOrAssignmentPattern + */ + /* @internal */ function isBindingOrAssignmentPattern(node) { return isObjectBindingOrAssignmentPattern(node) || isArrayBindingOrAssignmentPattern(node); } ts.isBindingOrAssignmentPattern = isBindingOrAssignmentPattern; + /** + * Determines whether a node is an ObjectBindingOrAssignmentPattern + */ + /* @internal */ function isObjectBindingOrAssignmentPattern(node) { switch (node.kind) { - case 180: - case 184: + case 180 /* ObjectBindingPattern */: + case 184 /* ObjectLiteralExpression */: return true; } return false; } ts.isObjectBindingOrAssignmentPattern = isObjectBindingOrAssignmentPattern; + /** + * Determines whether a node is an ArrayBindingOrAssignmentPattern + */ + /* @internal */ function isArrayBindingOrAssignmentPattern(node) { switch (node.kind) { - case 181: - case 183: + case 181 /* ArrayBindingPattern */: + case 183 /* ArrayLiteralExpression */: return true; } return false; } ts.isArrayBindingOrAssignmentPattern = isArrayBindingOrAssignmentPattern; + /* @internal */ function isPropertyAccessOrQualifiedNameOrImportTypeNode(node) { var kind = node.kind; - return kind === 185 - || kind === 146 - || kind === 179; + return kind === 185 /* PropertyAccessExpression */ + || kind === 146 /* QualifiedName */ + || kind === 179 /* ImportType */; } ts.isPropertyAccessOrQualifiedNameOrImportTypeNode = isPropertyAccessOrQualifiedNameOrImportTypeNode; + // Expression function isPropertyAccessOrQualifiedName(node) { var kind = node.kind; - return kind === 185 - || kind === 146; + return kind === 185 /* PropertyAccessExpression */ + || kind === 146 /* QualifiedName */; } ts.isPropertyAccessOrQualifiedName = isPropertyAccessOrQualifiedName; function isCallLikeExpression(node) { switch (node.kind) { - case 257: - case 256: - case 187: - case 188: - case 189: - case 150: + case 257 /* JsxOpeningElement */: + case 256 /* JsxSelfClosingElement */: + case 187 /* CallExpression */: + case 188 /* NewExpression */: + case 189 /* TaggedTemplateExpression */: + case 150 /* Decorator */: return true; default: return false; @@ -11735,98 +13244,106 @@ var ts; } ts.isCallLikeExpression = isCallLikeExpression; function isCallOrNewExpression(node) { - return node.kind === 187 || node.kind === 188; + return node.kind === 187 /* CallExpression */ || node.kind === 188 /* NewExpression */; } ts.isCallOrNewExpression = isCallOrNewExpression; function isTemplateLiteral(node) { var kind = node.kind; - return kind === 202 - || kind === 13; + return kind === 202 /* TemplateExpression */ + || kind === 13 /* NoSubstitutionTemplateLiteral */; } ts.isTemplateLiteral = isTemplateLiteral; + /* @internal */ function isLeftHandSideExpression(node) { return isLeftHandSideExpressionKind(ts.skipPartiallyEmittedExpressions(node).kind); } ts.isLeftHandSideExpression = isLeftHandSideExpression; function isLeftHandSideExpressionKind(kind) { switch (kind) { - case 185: - case 186: - case 188: - case 187: - case 255: - case 256: - case 259: - case 189: - case 183: - case 191: - case 184: - case 205: - case 192: - case 71: - case 12: - case 8: - case 9: - case 13: - case 202: - case 86: - case 95: - case 99: - case 101: - case 97: - case 209: - case 210: - case 91: + case 185 /* PropertyAccessExpression */: + case 186 /* ElementAccessExpression */: + case 188 /* NewExpression */: + case 187 /* CallExpression */: + case 255 /* JsxElement */: + case 256 /* JsxSelfClosingElement */: + case 259 /* JsxFragment */: + case 189 /* TaggedTemplateExpression */: + case 183 /* ArrayLiteralExpression */: + case 191 /* ParenthesizedExpression */: + case 184 /* ObjectLiteralExpression */: + case 205 /* ClassExpression */: + case 192 /* FunctionExpression */: + case 71 /* Identifier */: + case 12 /* RegularExpressionLiteral */: + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: + case 13 /* NoSubstitutionTemplateLiteral */: + case 202 /* TemplateExpression */: + case 86 /* FalseKeyword */: + case 95 /* NullKeyword */: + case 99 /* ThisKeyword */: + case 101 /* TrueKeyword */: + case 97 /* SuperKeyword */: + case 209 /* NonNullExpression */: + case 210 /* MetaProperty */: + case 91 /* ImportKeyword */: // technically this is only an Expression if it's in a CallExpression return true; default: return false; } } + /* @internal */ function isUnaryExpression(node) { return isUnaryExpressionKind(ts.skipPartiallyEmittedExpressions(node).kind); } ts.isUnaryExpression = isUnaryExpression; function isUnaryExpressionKind(kind) { switch (kind) { - case 198: - case 199: - case 194: - case 195: - case 196: - case 197: - case 190: + case 198 /* PrefixUnaryExpression */: + case 199 /* PostfixUnaryExpression */: + case 194 /* DeleteExpression */: + case 195 /* TypeOfExpression */: + case 196 /* VoidExpression */: + case 197 /* AwaitExpression */: + case 190 /* TypeAssertionExpression */: return true; default: return isLeftHandSideExpressionKind(kind); } } + /* @internal */ function isUnaryExpressionWithWrite(expr) { switch (expr.kind) { - case 199: + case 199 /* PostfixUnaryExpression */: return true; - case 198: - return expr.operator === 43 || - expr.operator === 44; + case 198 /* PrefixUnaryExpression */: + return expr.operator === 43 /* PlusPlusToken */ || + expr.operator === 44 /* MinusMinusToken */; default: return false; } } ts.isUnaryExpressionWithWrite = isUnaryExpressionWithWrite; + /* @internal */ + /** + * Determines whether a node is an expression based only on its kind. + * Use `isExpressionNode` if not in transforms. + */ function isExpression(node) { return isExpressionKind(ts.skipPartiallyEmittedExpressions(node).kind); } ts.isExpression = isExpression; function isExpressionKind(kind) { switch (kind) { - case 201: - case 203: - case 193: - case 200: - case 204: - case 208: - case 206: - case 303: - case 302: + case 201 /* ConditionalExpression */: + case 203 /* YieldExpression */: + case 193 /* ArrowFunction */: + case 200 /* BinaryExpression */: + case 204 /* SpreadElement */: + case 208 /* AsExpression */: + case 206 /* OmittedExpression */: + case 303 /* CommaListExpression */: + case 302 /* PartiallyEmittedExpression */: return true; default: return isUnaryExpressionKind(kind); @@ -11834,18 +13351,21 @@ var ts; } function isAssertionExpression(node) { var kind = node.kind; - return kind === 190 - || kind === 208; + return kind === 190 /* TypeAssertionExpression */ + || kind === 208 /* AsExpression */; } ts.isAssertionExpression = isAssertionExpression; + /* @internal */ function isPartiallyEmittedExpression(node) { - return node.kind === 302; + return node.kind === 302 /* PartiallyEmittedExpression */; } ts.isPartiallyEmittedExpression = isPartiallyEmittedExpression; + /* @internal */ function isNotEmittedStatement(node) { - return node.kind === 301; + return node.kind === 301 /* NotEmittedStatement */; } ts.isNotEmittedStatement = isNotEmittedStatement; + /* @internal */ function isNotEmittedOrPartiallyEmittedNode(node) { return isNotEmittedStatement(node) || isPartiallyEmittedExpression(node); @@ -11853,152 +13373,169 @@ var ts; ts.isNotEmittedOrPartiallyEmittedNode = isNotEmittedOrPartiallyEmittedNode; function isIterationStatement(node, lookInLabeledStatements) { switch (node.kind) { - case 220: - case 221: - case 222: - case 218: - case 219: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 218 /* DoStatement */: + case 219 /* WhileStatement */: return true; - case 228: + case 228 /* LabeledStatement */: return lookInLabeledStatements && isIterationStatement(node.statement, lookInLabeledStatements); } return false; } ts.isIterationStatement = isIterationStatement; + /* @internal */ function isForInOrOfStatement(node) { - return node.kind === 221 || node.kind === 222; + return node.kind === 221 /* ForInStatement */ || node.kind === 222 /* ForOfStatement */; } ts.isForInOrOfStatement = isForInOrOfStatement; + // Element + /* @internal */ function isConciseBody(node) { return ts.isBlock(node) || isExpression(node); } ts.isConciseBody = isConciseBody; + /* @internal */ function isFunctionBody(node) { return ts.isBlock(node); } ts.isFunctionBody = isFunctionBody; + /* @internal */ function isForInitializer(node) { return ts.isVariableDeclarationList(node) || isExpression(node); } ts.isForInitializer = isForInitializer; + /* @internal */ function isModuleBody(node) { var kind = node.kind; - return kind === 240 - || kind === 239 - || kind === 71; + return kind === 240 /* ModuleBlock */ + || kind === 239 /* ModuleDeclaration */ + || kind === 71 /* Identifier */; } ts.isModuleBody = isModuleBody; + /* @internal */ function isNamespaceBody(node) { var kind = node.kind; - return kind === 240 - || kind === 239; + return kind === 240 /* ModuleBlock */ + || kind === 239 /* ModuleDeclaration */; } ts.isNamespaceBody = isNamespaceBody; + /* @internal */ function isJSDocNamespaceBody(node) { var kind = node.kind; - return kind === 71 - || kind === 239; + return kind === 71 /* Identifier */ + || kind === 239 /* ModuleDeclaration */; } ts.isJSDocNamespaceBody = isJSDocNamespaceBody; + /* @internal */ function isNamedImportBindings(node) { var kind = node.kind; - return kind === 247 - || kind === 246; + return kind === 247 /* NamedImports */ + || kind === 246 /* NamespaceImport */; } ts.isNamedImportBindings = isNamedImportBindings; + /* @internal */ function isModuleOrEnumDeclaration(node) { - return node.kind === 239 || node.kind === 238; + return node.kind === 239 /* ModuleDeclaration */ || node.kind === 238 /* EnumDeclaration */; } ts.isModuleOrEnumDeclaration = isModuleOrEnumDeclaration; function isDeclarationKind(kind) { - return kind === 193 - || kind === 182 - || kind === 235 - || kind === 205 - || kind === 155 - || kind === 238 - || kind === 273 - || kind === 252 - || kind === 234 - || kind === 192 - || kind === 156 - || kind === 245 - || kind === 243 - || kind === 248 - || kind === 236 - || kind === 262 - || kind === 154 - || kind === 153 - || kind === 239 - || kind === 242 - || kind === 246 - || kind === 149 - || kind === 270 - || kind === 152 - || kind === 151 - || kind === 157 - || kind === 271 - || kind === 237 - || kind === 148 - || kind === 232 - || kind === 298 - || kind === 292 - || kind === 299; + return kind === 193 /* ArrowFunction */ + || kind === 182 /* BindingElement */ + || kind === 235 /* ClassDeclaration */ + || kind === 205 /* ClassExpression */ + || kind === 155 /* Constructor */ + || kind === 238 /* EnumDeclaration */ + || kind === 273 /* EnumMember */ + || kind === 252 /* ExportSpecifier */ + || kind === 234 /* FunctionDeclaration */ + || kind === 192 /* FunctionExpression */ + || kind === 156 /* GetAccessor */ + || kind === 245 /* ImportClause */ + || kind === 243 /* ImportEqualsDeclaration */ + || kind === 248 /* ImportSpecifier */ + || kind === 236 /* InterfaceDeclaration */ + || kind === 262 /* JsxAttribute */ + || kind === 154 /* MethodDeclaration */ + || kind === 153 /* MethodSignature */ + || kind === 239 /* ModuleDeclaration */ + || kind === 242 /* NamespaceExportDeclaration */ + || kind === 246 /* NamespaceImport */ + || kind === 149 /* Parameter */ + || kind === 270 /* PropertyAssignment */ + || kind === 152 /* PropertyDeclaration */ + || kind === 151 /* PropertySignature */ + || kind === 157 /* SetAccessor */ + || kind === 271 /* ShorthandPropertyAssignment */ + || kind === 237 /* TypeAliasDeclaration */ + || kind === 148 /* TypeParameter */ + || kind === 232 /* VariableDeclaration */ + || kind === 298 /* JSDocTypedefTag */ + || kind === 292 /* JSDocCallbackTag */ + || kind === 299 /* JSDocPropertyTag */; } function isDeclarationStatementKind(kind) { - return kind === 234 - || kind === 253 - || kind === 235 - || kind === 236 - || kind === 237 - || kind === 238 - || kind === 239 - || kind === 244 - || kind === 243 - || kind === 250 - || kind === 249 - || kind === 242; + return kind === 234 /* FunctionDeclaration */ + || kind === 253 /* MissingDeclaration */ + || kind === 235 /* ClassDeclaration */ + || kind === 236 /* InterfaceDeclaration */ + || kind === 237 /* TypeAliasDeclaration */ + || kind === 238 /* EnumDeclaration */ + || kind === 239 /* ModuleDeclaration */ + || kind === 244 /* ImportDeclaration */ + || kind === 243 /* ImportEqualsDeclaration */ + || kind === 250 /* ExportDeclaration */ + || kind === 249 /* ExportAssignment */ + || kind === 242 /* NamespaceExportDeclaration */; } function isStatementKindButNotDeclarationKind(kind) { - return kind === 224 - || kind === 223 - || kind === 231 - || kind === 218 - || kind === 216 - || kind === 215 - || kind === 221 - || kind === 222 - || kind === 220 - || kind === 217 - || kind === 228 - || kind === 225 - || kind === 227 - || kind === 229 - || kind === 230 - || kind === 214 - || kind === 219 - || kind === 226 - || kind === 301 - || kind === 305 - || kind === 304; + return kind === 224 /* BreakStatement */ + || kind === 223 /* ContinueStatement */ + || kind === 231 /* DebuggerStatement */ + || kind === 218 /* DoStatement */ + || kind === 216 /* ExpressionStatement */ + || kind === 215 /* EmptyStatement */ + || kind === 221 /* ForInStatement */ + || kind === 222 /* ForOfStatement */ + || kind === 220 /* ForStatement */ + || kind === 217 /* IfStatement */ + || kind === 228 /* LabeledStatement */ + || kind === 225 /* ReturnStatement */ + || kind === 227 /* SwitchStatement */ + || kind === 229 /* ThrowStatement */ + || kind === 230 /* TryStatement */ + || kind === 214 /* VariableStatement */ + || kind === 219 /* WhileStatement */ + || kind === 226 /* WithStatement */ + || kind === 301 /* NotEmittedStatement */ + || kind === 305 /* EndOfDeclarationMarker */ + || kind === 304 /* MergeDeclarationMarker */; } + /* @internal */ function isDeclaration(node) { - if (node.kind === 148) { - return node.parent.kind !== 297 || ts.isInJavaScriptFile(node); + if (node.kind === 148 /* TypeParameter */) { + return node.parent.kind !== 297 /* JSDocTemplateTag */ || ts.isInJavaScriptFile(node); } return isDeclarationKind(node.kind); } ts.isDeclaration = isDeclaration; + /* @internal */ function isDeclarationStatement(node) { return isDeclarationStatementKind(node.kind); } ts.isDeclarationStatement = isDeclarationStatement; + /** + * Determines whether the node is a statement that is not also a declaration + */ + /* @internal */ function isStatementButNotDeclaration(node) { return isStatementKindButNotDeclarationKind(node.kind); } ts.isStatementButNotDeclaration = isStatementButNotDeclaration; + /* @internal */ function isStatement(node) { var kind = node.kind; return isStatementKindButNotDeclarationKind(kind) @@ -12007,156 +13544,183 @@ var ts; } ts.isStatement = isStatement; function isBlockStatement(node) { - if (node.kind !== 213) + if (node.kind !== 213 /* Block */) return false; if (node.parent !== undefined) { - if (node.parent.kind === 230 || node.parent.kind === 269) { + if (node.parent.kind === 230 /* TryStatement */ || node.parent.kind === 269 /* CatchClause */) { return false; } } return !ts.isFunctionBlock(node); } + // Module references + /* @internal */ function isModuleReference(node) { var kind = node.kind; - return kind === 254 - || kind === 146 - || kind === 71; + return kind === 254 /* ExternalModuleReference */ + || kind === 146 /* QualifiedName */ + || kind === 71 /* Identifier */; } ts.isModuleReference = isModuleReference; + // JSX + /* @internal */ function isJsxTagNameExpression(node) { var kind = node.kind; - return kind === 99 - || kind === 71 - || kind === 185; + return kind === 99 /* ThisKeyword */ + || kind === 71 /* Identifier */ + || kind === 185 /* PropertyAccessExpression */; } ts.isJsxTagNameExpression = isJsxTagNameExpression; + /* @internal */ function isJsxChild(node) { var kind = node.kind; - return kind === 255 - || kind === 265 - || kind === 256 - || kind === 10 - || kind === 259; + return kind === 255 /* JsxElement */ + || kind === 265 /* JsxExpression */ + || kind === 256 /* JsxSelfClosingElement */ + || kind === 10 /* JsxText */ + || kind === 259 /* JsxFragment */; } ts.isJsxChild = isJsxChild; + /* @internal */ function isJsxAttributeLike(node) { var kind = node.kind; - return kind === 262 - || kind === 264; + return kind === 262 /* JsxAttribute */ + || kind === 264 /* JsxSpreadAttribute */; } ts.isJsxAttributeLike = isJsxAttributeLike; + /* @internal */ function isStringLiteralOrJsxExpression(node) { var kind = node.kind; - return kind === 9 - || kind === 265; + return kind === 9 /* StringLiteral */ + || kind === 265 /* JsxExpression */; } ts.isStringLiteralOrJsxExpression = isStringLiteralOrJsxExpression; function isJsxOpeningLikeElement(node) { var kind = node.kind; - return kind === 257 - || kind === 256; + return kind === 257 /* JsxOpeningElement */ + || kind === 256 /* JsxSelfClosingElement */; } ts.isJsxOpeningLikeElement = isJsxOpeningLikeElement; + // Clauses function isCaseOrDefaultClause(node) { var kind = node.kind; - return kind === 266 - || kind === 267; + return kind === 266 /* CaseClause */ + || kind === 267 /* DefaultClause */; } ts.isCaseOrDefaultClause = isCaseOrDefaultClause; + // JSDoc + /** True if node is of some JSDoc syntax kind. */ + /* @internal */ function isJSDocNode(node) { - return node.kind >= 278 && node.kind <= 299; + return node.kind >= 278 /* FirstJSDocNode */ && node.kind <= 299 /* LastJSDocNode */; } ts.isJSDocNode = isJSDocNode; + /** True if node is of a kind that may contain comment text. */ function isJSDocCommentContainingNode(node) { - return node.kind === 286 || isJSDocTag(node) || ts.isJSDocTypeLiteral(node) || ts.isJSDocSignature(node); + return node.kind === 286 /* JSDocComment */ || isJSDocTag(node) || ts.isJSDocTypeLiteral(node) || ts.isJSDocSignature(node); } ts.isJSDocCommentContainingNode = isJSDocCommentContainingNode; + // TODO: determine what this does before making it public. + /* @internal */ function isJSDocTag(node) { - return node.kind >= 289 && node.kind <= 299; + return node.kind >= 289 /* FirstJSDocTagNode */ && node.kind <= 299 /* LastJSDocTagNode */; } ts.isJSDocTag = isJSDocTag; function isSetAccessor(node) { - return node.kind === 157; + return node.kind === 157 /* SetAccessor */; } ts.isSetAccessor = isSetAccessor; function isGetAccessor(node) { - return node.kind === 156; + return node.kind === 156 /* GetAccessor */; } ts.isGetAccessor = isGetAccessor; + /** True if has jsdoc nodes attached to it. */ + /* @internal */ + // TODO: GH#19856 Would like to return `node is Node & { jsDoc: JSDoc[] }` but it causes long compile times function hasJSDocNodes(node) { var jsDoc = node.jsDoc; return !!jsDoc && jsDoc.length > 0; } ts.hasJSDocNodes = hasJSDocNodes; + /** True if has type node attached to it. */ + /* @internal */ function hasType(node) { return !!node.type; } ts.hasType = hasType; + /* True if the node could have a type node a `.type` */ + /* @internal */ function couldHaveType(node) { switch (node.kind) { - case 149: - case 151: - case 152: - case 153: - case 154: - case 155: - case 156: - case 157: - case 158: - case 159: - case 160: - case 161: - case 163: - case 164: - case 173: - case 175: - case 177: - case 190: - case 192: - case 193: - case 208: - case 232: - case 234: - case 237: - case 278: - case 281: - case 282: - case 283: - case 284: - case 285: + case 149 /* Parameter */: + case 151 /* PropertySignature */: + case 152 /* PropertyDeclaration */: + case 153 /* MethodSignature */: + case 154 /* MethodDeclaration */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 160 /* IndexSignature */: + case 161 /* TypePredicate */: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 173 /* ParenthesizedType */: + case 175 /* TypeOperator */: + case 177 /* MappedType */: + case 190 /* TypeAssertionExpression */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 208 /* AsExpression */: + case 232 /* VariableDeclaration */: + case 234 /* FunctionDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 278 /* JSDocTypeExpression */: + case 281 /* JSDocNullableType */: + case 282 /* JSDocNonNullableType */: + case 283 /* JSDocOptionalType */: + case 284 /* JSDocFunctionType */: + case 285 /* JSDocVariadicType */: return true; } return false; } ts.couldHaveType = couldHaveType; + /** True if has initializer node attached to it. */ + /* @internal */ function hasInitializer(node) { return !!node.initializer; } ts.hasInitializer = hasInitializer; + /** True if has initializer node attached to it. */ + /* @internal */ function hasOnlyExpressionInitializer(node) { return hasInitializer(node) && !ts.isForStatement(node) && !ts.isForInStatement(node) && !ts.isForOfStatement(node) && !ts.isJsxAttribute(node); } ts.hasOnlyExpressionInitializer = hasOnlyExpressionInitializer; function isObjectLiteralElement(node) { switch (node.kind) { - case 262: - case 264: - case 270: - case 271: - case 154: - case 156: - case 157: + case 262 /* JsxAttribute */: + case 264 /* JsxSpreadAttribute */: + case 270 /* PropertyAssignment */: + case 271 /* ShorthandPropertyAssignment */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return true; default: return false; } } ts.isObjectLiteralElement = isObjectLiteralElement; + /* @internal */ function isTypeReferenceType(node) { - return node.kind === 162 || node.kind === 207; + return node.kind === 162 /* TypeReference */ || node.kind === 207 /* ExpressionWithTypeArguments */; } ts.isTypeReferenceType = isTypeReferenceType; var MAX_SMI_X86 = 1073741823; + /* @internal */ function guessIndentation(lines) { var indentation = MAX_SMI_X86; for (var _i = 0, lines_1 = lines; _i < lines_1.length; _i++) { @@ -12181,13 +13745,15 @@ var ts; } ts.guessIndentation = guessIndentation; function isStringLiteralLike(node) { - return node.kind === 9 || node.kind === 13; + return node.kind === 9 /* StringLiteral */ || node.kind === 13 /* NoSubstitutionTemplateLiteral */; } ts.isStringLiteralLike = isStringLiteralLike; })(ts || (ts = {})); +/* @internal */ (function (ts) { + /** @internal */ function isNamedImportsOrExports(node) { - return node.kind === 247 || node.kind === 251; + return node.kind === 247 /* NamedImports */ || node.kind === 251 /* NamedExports */; } ts.isNamedImportsOrExports = isNamedImportsOrExports; function Symbol(flags, name) { @@ -12205,15 +13771,15 @@ var ts; this.checker = checker; } } - function Signature() { } + function Signature() { } // tslint:disable-line no-empty function Node(kind, pos, end) { this.pos = pos; this.end = end; this.kind = kind; this.id = 0; - this.flags = 0; - this.modifierFlagsCache = 0; - this.transformFlags = 0; + this.flags = 0 /* None */; + this.modifierFlagsCache = 0 /* None */; + this.transformFlags = 0 /* None */; this.parent = undefined; this.original = undefined; } @@ -12232,6 +13798,7 @@ var ts; getSignatureConstructor: function () { return Signature; }, getSourceMapSourceConstructor: function () { return SourceMapSource; }, }; + /* @internal */ function formatStringFromArgs(text, args, baseIndex) { if (baseIndex === void 0) { baseIndex = 0; } return text.replace(/{(\d+)}/g, function (_match, index) { return ts.Debug.assertDefined(args[+index + baseIndex]); }); @@ -12263,6 +13830,7 @@ var ts; }; } ts.createFileDiagnostic = createFileDiagnostic; + /* @internal */ function formatMessage(_dummy, message) { var text = getLocaleSpecificMessage(message); if (arguments.length > 2) { @@ -12287,6 +13855,7 @@ var ts; }; } ts.createCompilerDiagnostic = createCompilerDiagnostic; + /* @internal */ function createCompilerDiagnosticFromMessageChain(chain) { return { file: undefined, @@ -12323,19 +13892,21 @@ var ts; function getDiagnosticFilePath(diagnostic) { return diagnostic.file ? diagnostic.file.path : undefined; } + /* @internal */ function compareDiagnostics(d1, d2) { return ts.compareStringsCaseSensitive(getDiagnosticFilePath(d1), getDiagnosticFilePath(d2)) || ts.compareValues(d1.start, d2.start) || ts.compareValues(d1.length, d2.length) || ts.compareValues(d1.code, d2.code) || compareMessageText(d1.messageText, d2.messageText) || - 0; + 0 /* EqualTo */; } ts.compareDiagnostics = compareDiagnostics; function compareMessageText(t1, t2) { var text1 = t1; var text2 = t2; while (text1 && text2) { + // We still have both chains. var string1 = ts.isString(text1) ? text1 : text1.messageText; var string2 = ts.isString(text2) ? text2 : text2.messageText; var res = ts.compareStringsCaseSensitive(string1, string2); @@ -12346,18 +13917,20 @@ var ts; text2 = ts.isString(text2) ? undefined : text2.next; } if (!text1 && !text2) { - return 0; + // if the chains are done, then these messages are the same. + return 0 /* EqualTo */; } - return text1 ? 1 : -1; + // We still have one chain remaining. The shorter chain should come first. + return text1 ? 1 /* GreaterThan */ : -1 /* LessThan */; } function getEmitScriptTarget(compilerOptions) { - return compilerOptions.target || 0; + return compilerOptions.target || 0 /* ES3 */; } ts.getEmitScriptTarget = getEmitScriptTarget; function getEmitModuleKind(compilerOptions) { return typeof compilerOptions.module === "number" ? compilerOptions.module : - getEmitScriptTarget(compilerOptions) >= 2 ? ts.ModuleKind.ES2015 : ts.ModuleKind.CommonJS; + getEmitScriptTarget(compilerOptions) >= 2 /* ES2015 */ ? ts.ModuleKind.ES2015 : ts.ModuleKind.CommonJS; } ts.getEmitModuleKind = getEmitModuleKind; function getEmitModuleResolutionKind(compilerOptions) { @@ -12400,11 +13973,12 @@ var ts; function hasZeroOrOneAsteriskCharacter(str) { var seenAsterisk = false; for (var i = 0; i < str.length; i++) { - if (str.charCodeAt(i) === 42) { + if (str.charCodeAt(i) === 42 /* asterisk */) { if (!seenAsterisk) { seenAsterisk = true; } else { + // have already seen asterisk return false; } } @@ -12412,78 +13986,126 @@ var ts; return true; } ts.hasZeroOrOneAsteriskCharacter = hasZeroOrOneAsteriskCharacter; + /** + * Internally, we represent paths as strings with '/' as the directory separator. + * When we make system calls (eg: LanguageServiceHost.getDirectory()), + * we expect the host to correctly handle paths in our specified format. + */ ts.directorySeparator = "/"; var altDirectorySeparator = "\\"; var urlSchemeSeparator = "://"; var backslashRegExp = /\\/g; + /** + * Normalize path separators. + */ function normalizeSlashes(path) { return path.replace(backslashRegExp, ts.directorySeparator); } ts.normalizeSlashes = normalizeSlashes; function isVolumeCharacter(charCode) { - return (charCode >= 97 && charCode <= 122) || - (charCode >= 65 && charCode <= 90); + return (charCode >= 97 /* a */ && charCode <= 122 /* z */) || + (charCode >= 65 /* A */ && charCode <= 90 /* Z */); } function getFileUrlVolumeSeparatorEnd(url, start) { var ch0 = url.charCodeAt(start); - if (ch0 === 58) + if (ch0 === 58 /* colon */) return start + 1; - if (ch0 === 37 && url.charCodeAt(start + 1) === 51) { + if (ch0 === 37 /* percent */ && url.charCodeAt(start + 1) === 51 /* _3 */) { var ch2 = url.charCodeAt(start + 2); - if (ch2 === 97 || ch2 === 65) + if (ch2 === 97 /* a */ || ch2 === 65 /* A */) return start + 3; } return -1; } + /** + * Returns length of the root part of a path or URL (i.e. length of "/", "x:/", "//server/share/, file:///user/files"). + * If the root is part of a URL, the twos-complement of the root length is returned. + */ function getEncodedRootLength(path) { if (!path) return 0; var ch0 = path.charCodeAt(0); - if (ch0 === 47 || ch0 === 92) { + // POSIX or UNC + if (ch0 === 47 /* slash */ || ch0 === 92 /* backslash */) { if (path.charCodeAt(1) !== ch0) - return 1; - var p1 = path.indexOf(ch0 === 47 ? ts.directorySeparator : altDirectorySeparator, 2); + return 1; // POSIX: "/" (or non-normalized "\") + var p1 = path.indexOf(ch0 === 47 /* slash */ ? ts.directorySeparator : altDirectorySeparator, 2); if (p1 < 0) - return path.length; - return p1 + 1; + return path.length; // UNC: "//server" or "\\server" + return p1 + 1; // UNC: "//server/" or "\\server\" } - if (isVolumeCharacter(ch0) && path.charCodeAt(1) === 58) { + // DOS + if (isVolumeCharacter(ch0) && path.charCodeAt(1) === 58 /* colon */) { var ch2 = path.charCodeAt(2); - if (ch2 === 47 || ch2 === 92) - return 3; + if (ch2 === 47 /* slash */ || ch2 === 92 /* backslash */) + return 3; // DOS: "c:/" or "c:\" if (path.length === 2) - return 2; + return 2; // DOS: "c:" (but not "c:d") } + // URL var schemeEnd = path.indexOf(urlSchemeSeparator); if (schemeEnd !== -1) { var authorityStart = schemeEnd + urlSchemeSeparator.length; var authorityEnd = path.indexOf(ts.directorySeparator, authorityStart); - if (authorityEnd !== -1) { + if (authorityEnd !== -1) { // URL: "file:///", "file://server/", "file://server/path" + // For local "file" URLs, include the leading DOS volume (if present). + // Per https://www.ietf.org/rfc/rfc1738.txt, a host of "" or "localhost" is a + // special case interpreted as "the machine from which the URL is being interpreted". var scheme = path.slice(0, schemeEnd); var authority = path.slice(authorityStart, authorityEnd); if (scheme === "file" && (authority === "" || authority === "localhost") && isVolumeCharacter(path.charCodeAt(authorityEnd + 1))) { var volumeSeparatorEnd = getFileUrlVolumeSeparatorEnd(path, authorityEnd + 2); if (volumeSeparatorEnd !== -1) { - if (path.charCodeAt(volumeSeparatorEnd) === 47) { + if (path.charCodeAt(volumeSeparatorEnd) === 47 /* slash */) { + // URL: "file:///c:/", "file://localhost/c:/", "file:///c%3a/", "file://localhost/c%3a/" return ~(volumeSeparatorEnd + 1); } if (volumeSeparatorEnd === path.length) { + // URL: "file:///c:", "file://localhost/c:", "file:///c$3a", "file://localhost/c%3a" + // but not "file:///c:d" or "file:///c%3ad" return ~volumeSeparatorEnd; } } } - return ~(authorityEnd + 1); + return ~(authorityEnd + 1); // URL: "file://server/", "http://server/" } - return ~path.length; + return ~path.length; // URL: "file://server", "http://server" } + // relative return 0; } + /** + * Returns length of the root part of a path or URL (i.e. length of "/", "x:/", "//server/share/, file:///user/files"). + * + * For example: + * ```ts + * getRootLength("a") === 0 // "" + * getRootLength("/") === 1 // "/" + * getRootLength("c:") === 2 // "c:" + * getRootLength("c:d") === 0 // "" + * getRootLength("c:/") === 3 // "c:/" + * getRootLength("c:\\") === 3 // "c:\\" + * getRootLength("//server") === 7 // "//server" + * getRootLength("//server/share") === 8 // "//server/" + * getRootLength("\\\\server") === 7 // "\\\\server" + * getRootLength("\\\\server\\share") === 8 // "\\\\server\\" + * getRootLength("file:///path") === 8 // "file:///" + * getRootLength("file:///c:") === 10 // "file:///c:" + * getRootLength("file:///c:d") === 8 // "file:///" + * getRootLength("file:///c:/path") === 11 // "file:///c:/" + * getRootLength("file://server") === 13 // "file://server" + * getRootLength("file://server/path") === 14 // "file://server/" + * getRootLength("http://server") === 13 // "http://server" + * getRootLength("http://server/path") === 14 // "http://server/" + * ``` + */ function getRootLength(path) { var rootLength = getEncodedRootLength(path); return rootLength < 0 ? ~rootLength : rootLength; } ts.getRootLength = getRootLength; + // TODO(rbuckton): replace references with `resolvePath` function normalizePath(path) { return ts.resolvePath(path); } @@ -12502,9 +14124,12 @@ var ts; ts.normalizePathAndParts = normalizePathAndParts; function getDirectoryPath(path) { path = normalizeSlashes(path); + // If the path provided is itself the root, then return it. var rootLength = getRootLength(path); if (rootLength === path.length) return path; + // return the leading portion of the path up to the last (non-terminal) directory separator + // but not including any trailing directory separator. path = ts.removeTrailingDirectorySeparator(path); return path.slice(0, Math.max(rootLength, path.lastIndexOf(ts.directorySeparator))); } @@ -12517,19 +14142,27 @@ var ts; return /^\.\.?($|[\\/])/.test(path); } ts.pathIsRelative = pathIsRelative; + /** + * Determines whether a path is an absolute path (e.g. starts with `/`, or a dos path + * like `c:`, `c:\` or `c:/`). + */ function isRootedDiskPath(path) { return getEncodedRootLength(path) > 0; } ts.isRootedDiskPath = isRootedDiskPath; + /** + * Determines whether a path consists only of a path root. + */ function isDiskPathRoot(path) { var rootLength = getEncodedRootLength(path); return rootLength > 0 && rootLength === path.length; } ts.isDiskPathRoot = isDiskPathRoot; + /* @internal */ function convertToRelativePath(absoluteOrRelativePath, basePath, getCanonicalFileName) { return !isRootedDiskPath(absoluteOrRelativePath) ? absoluteOrRelativePath - : ts.getRelativePathToDirectoryOrUrl(basePath, absoluteOrRelativePath, basePath, getCanonicalFileName, false); + : ts.getRelativePathToDirectoryOrUrl(basePath, absoluteOrRelativePath, basePath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); } ts.convertToRelativePath = convertToRelativePath; function pathComponents(path, rootLength) { @@ -12539,6 +14172,12 @@ var ts; rest.pop(); return [root].concat(rest); } + /** + * Parse a path into an array containing a root component (at index 0) and zero or more path + * components (at indices > 0). The result is not normalized. + * If the path is relative, the root component is `""`. + * If the path is absolute, the root component includes the first path separator (`/`). + */ function getPathComponents(path, currentDirectory) { if (currentDirectory === void 0) { currentDirectory = ""; } path = ts.combinePaths(currentDirectory, path); @@ -12546,6 +14185,10 @@ var ts; return pathComponents(path, rootLength); } ts.getPathComponents = getPathComponents; + /** + * Reduce an array of path components to a more simplified path by navigating any + * `"."` or `".."` entries in the path. + */ function reducePathComponents(components) { if (!ts.some(components)) return []; @@ -12571,6 +14214,12 @@ var ts; return reduced; } ts.reducePathComponents = reducePathComponents; + /** + * Parse a path into an array containing a root component (at index 0) and zero or more path + * components (at indices > 0). The result is normalized. + * If the path is relative, the root component is `""`. + * If the path is absolute, the root component includes the first path separator (`/`). + */ function getNormalizedPathComponents(path, currentDirectory) { return reducePathComponents(getPathComponents(path, currentDirectory)); } @@ -12579,6 +14228,10 @@ var ts; return getPathFromPathComponents(getNormalizedPathComponents(fileName, currentDirectory)); } ts.getNormalizedAbsolutePath = getNormalizedAbsolutePath; + /** + * Formats a parsed path consisting of a root component (at index 0) and zero or more path + * segments (at indices > 0). + */ function getPathFromPathComponents(pathComponents) { if (pathComponents.length === 0) return ""; @@ -12589,6 +14242,7 @@ var ts; } ts.getPathFromPathComponents = getPathFromPathComponents; })(ts || (ts = {})); +/* @internal */ (function (ts) { function getPathComponentsRelativeTo(from, to, stringEqualityComparer, getCanonicalFileName) { var fromComponents = ts.reducePathComponents(ts.getPathComponents(from)); @@ -12634,21 +14288,31 @@ var ts; return ts.getPathFromPathComponents(pathComponents); } ts.getRelativePathToDirectoryOrUrl = getRelativePathToDirectoryOrUrl; + /** + * Ensures a path is either absolute (prefixed with `/` or `c:`) or dot-relative (prefixed + * with `./` or `../`) so as not to be confused with an unprefixed module name. + */ function ensurePathIsNonModuleName(path) { return ts.getRootLength(path) === 0 && !ts.pathIsRelative(path) ? "./" + path : path; } ts.ensurePathIsNonModuleName = ensurePathIsNonModuleName; function getBaseFileName(path, extensions, ignoreCase) { path = ts.normalizeSlashes(path); + // if the path provided is itself the root, then it has not file name. var rootLength = ts.getRootLength(path); if (rootLength === path.length) return ""; + // return the trailing portion of the path starting after the last (non-terminal) directory + // separator but not including any trailing directory separator. path = removeTrailingDirectorySeparator(path); var name = path.slice(Math.max(ts.getRootLength(path), path.lastIndexOf(ts.directorySeparator) + 1)); var extension = extensions !== undefined && ignoreCase !== undefined ? getAnyExtensionFromPath(name, extensions, ignoreCase) : undefined; return extension ? name.slice(0, name.length - extension.length) : name; } ts.getBaseFileName = getBaseFileName; + /** + * Combines paths. If a path is absolute, it replaces any previous path. + */ function combinePaths(path) { var paths = []; for (var _i = 1; _i < arguments.length; _i++) { @@ -12671,6 +14335,10 @@ var ts; return path; } ts.combinePaths = combinePaths; + /** + * Combines and resolves paths. If a path is absolute, it replaces any previous path. Any + * `.` and `..` path components are resolved. + */ function resolvePath(path) { var paths = []; for (var _i = 1; _i < arguments.length; _i++) { @@ -12681,11 +14349,14 @@ var ts; return normalized && hasTrailingDirectorySeparator(combined) ? ensureTrailingDirectorySeparator(normalized) : normalized; } ts.resolvePath = resolvePath; + /** + * Determines whether a path has a trailing separator (`/` or `\\`). + */ function hasTrailingDirectorySeparator(path) { if (path.length === 0) return false; var ch = path.charCodeAt(path.length - 1); - return ch === 47 || ch === 92; + return ch === 47 /* slash */ || ch === 92 /* backslash */; } ts.hasTrailingDirectorySeparator = hasTrailingDirectorySeparator; function removeTrailingDirectorySeparator(path) { @@ -12704,27 +14375,33 @@ var ts; ts.ensureTrailingDirectorySeparator = ensureTrailingDirectorySeparator; function comparePathsWorker(a, b, componentComparer) { if (a === b) - return 0; + return 0 /* EqualTo */; if (a === undefined) - return -1; + return -1 /* LessThan */; if (b === undefined) - return 1; + return 1 /* GreaterThan */; var aComponents = ts.reducePathComponents(ts.getPathComponents(a)); var bComponents = ts.reducePathComponents(ts.getPathComponents(b)); var sharedLength = Math.min(aComponents.length, bComponents.length); for (var i = 0; i < sharedLength; i++) { var stringComparer = i === 0 ? ts.compareStringsCaseInsensitive : componentComparer; var result = stringComparer(aComponents[i], bComponents[i]); - if (result !== 0) { + if (result !== 0 /* EqualTo */) { return result; } } return ts.compareValues(aComponents.length, bComponents.length); } + /** + * Performs a case-sensitive comparison of two paths. + */ function comparePathsCaseSensitive(a, b) { return comparePathsWorker(a, b, ts.compareStringsCaseSensitive); } ts.comparePathsCaseSensitive = comparePathsCaseSensitive; + /** + * Performs a case-insensitive comparison of two paths. + */ function comparePathsCaseInsensitive(a, b) { return comparePathsWorker(a, b, ts.compareStringsCaseInsensitive); } @@ -12772,16 +14449,19 @@ var ts; if (a === undefined) return undefined; switch (a.charCodeAt(0)) { - case 47: - case 92: + case 47 /* slash */: + case 92 /* backslash */: return a.slice(1); default: return undefined; } } ts.tryRemoveDirectoryPrefix = tryRemoveDirectoryPrefix; + // Reserved characters, forces escaping of any non-word (or digit), non-whitespace character. + // It may be inefficient (we could just match (/[-[\]{}()*+?.,\\^$|#\s]/g), but this is future + // proof. var reservedCharacterPattern = /[^\w\s\/]/g; - var wildcardCharCodes = [42, 63]; + var wildcardCharCodes = [42 /* asterisk */, 63 /* question */]; function hasExtension(fileName) { return ts.stringContains(getBaseFileName(fileName), "."); } @@ -12789,12 +14469,26 @@ var ts; ts.commonPackageFolders = ["node_modules", "bower_components", "jspm_packages"]; var implicitExcludePathRegexPattern = "(?!(" + ts.commonPackageFolders.join("|") + ")(/|$))"; var filesMatcher = { + /** + * Matches any single directory segment unless it is the last segment and a .min.js file + * Breakdown: + * [^./] # matches everything up to the first . character (excluding directory separators) + * (\\.(?!min\\.js$))? # matches . characters but not if they are part of the .min.js file extension + */ singleAsteriskRegexFragment: "([^./]|(\\.(?!min\\.js$))?)*", + /** + * Regex for the ** wildcard. Matches any number of subdirectories. When used for including + * files or directories, does not match subdirectories that start with a . character + */ doubleAsteriskRegexFragment: "(/" + implicitExcludePathRegexPattern + "[^/.][^/]*)*?", replaceWildcardCharacter: function (match) { return replaceWildcardCharacter(match, filesMatcher.singleAsteriskRegexFragment); } }; var directoriesMatcher = { singleAsteriskRegexFragment: "[^/]*", + /** + * Regex for the ** wildcard. Matches any number of subdirectories. When used for including + * files or directories, does not match subdirectories that start with a . character + */ doubleAsteriskRegexFragment: "(/" + implicitExcludePathRegexPattern + "[^/.][^/]*)*?", replaceWildcardCharacter: function (match) { return replaceWildcardCharacter(match, directoriesMatcher.singleAsteriskRegexFragment); } }; @@ -12814,6 +14508,7 @@ var ts; return undefined; } var pattern = patterns.map(function (pattern) { return "(" + pattern + ")"; }).join("|"); + // If excluding, match "foo/bar/baz...", but if including, only allow "foo". var terminator = usage === "exclude" ? "($|/)" : "$"; return "^(" + pattern + ")" + terminator; } @@ -12826,6 +14521,10 @@ var ts; return spec && getSubPatternFromSpec(spec, basePath, usage, wildcardMatchers[usage]); }); } + /** + * An "includes" path "foo" is implicitly a glob "foo/** /*" (without the space) if its last component has no extension, + * and does not contain any glob characters itself. + */ function isImplicitGlob(lastPathComponent) { return !/[.*?]/.test(lastPathComponent); } @@ -12839,6 +14538,8 @@ var ts; if (usage !== "exclude" && lastComponent === "**") { return undefined; } + // getNormalizedPathComponents includes the separator for the root component. + // We need to remove to create our regex correctly. components[0] = removeTrailingDirectorySeparator(components[0]); if (isImplicitGlob(lastComponent)) { components.push("**", "*"); @@ -12859,15 +14560,24 @@ var ts; } if (usage !== "exclude") { var componentPattern = ""; - if (component.charCodeAt(0) === 42) { + // The * and ? wildcards should not match directories or files that start with . if they + // appear first in a component. Dotted directories and files can be included explicitly + // like so: **/.*/.* + if (component.charCodeAt(0) === 42 /* asterisk */) { componentPattern += "([^./]" + singleAsteriskRegexFragment + ")?"; component = component.substr(1); } - else if (component.charCodeAt(0) === 63) { + else if (component.charCodeAt(0) === 63 /* question */) { componentPattern += "[^./]"; component = component.substr(1); } componentPattern += component.replace(reservedCharacterPattern, replaceWildcardCharacter); + // Patterns should not include subfolders like node_modules unless they are + // explicitly included as part of the path. + // + // As an optimization, if the component pattern is the same as the component, + // then there definitely were no wildcard characters and we do not need to + // add the exclusion pattern. if (componentPattern !== component) { subpattern += implicitExcludePathRegexPattern; } @@ -12888,6 +14598,7 @@ var ts; function replaceWildcardCharacter(match, singleAsteriskRegexFragment) { return match === "*" ? singleAsteriskRegexFragment : match === "?" ? "[^/]" : "\\" + match; } + /** @param path directory of the tsconfig.json */ function getFileMatcherPatterns(path, excludes, includes, useCaseSensitiveFileNames, currentDirectory) { path = ts.normalizePath(path); currentDirectory = ts.normalizePath(currentDirectory); @@ -12905,6 +14616,7 @@ var ts; return new RegExp(pattern, useCaseSensitiveFileNames ? "" : "i"); } ts.getRegexFromPattern = getRegexFromPattern; + /** @param path directory of the tsconfig.json */ function matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, currentDirectory, depth, getFileSystemEntries) { path = ts.normalizePath(path); currentDirectory = ts.normalizePath(currentDirectory); @@ -12912,6 +14624,8 @@ var ts; var includeFileRegexes = patterns.includeFilePatterns && patterns.includeFilePatterns.map(function (pattern) { return getRegexFromPattern(pattern, useCaseSensitiveFileNames); }); var includeDirectoryRegex = patterns.includeDirectoryPattern && getRegexFromPattern(patterns.includeDirectoryPattern, useCaseSensitiveFileNames); var excludeRegex = patterns.excludePattern && getRegexFromPattern(patterns.excludePattern, useCaseSensitiveFileNames); + // Associate an array of results with each include regex. This keeps results in order of the "include" order. + // If there are no "includes", then just put everything in results[0]. var results = includeFileRegexes ? includeFileRegexes.map(function () { return []; }) : [[]]; for (var _i = 0, _a = patterns.basePaths; _i < _a.length; _i++) { var basePath = _a[_i]; @@ -12959,21 +14673,32 @@ var ts; } } ts.matchFiles = matchFiles; + /** + * Computes the unique non-wildcard base paths amongst the provided include patterns. + */ function getBasePaths(path, includes, useCaseSensitiveFileNames) { + // Storage for our results in the form of literal paths (e.g. the paths as written by the user). var basePaths = [path]; if (includes) { + // Storage for literal base paths amongst the include patterns. var includeBasePaths = []; for (var _i = 0, includes_1 = includes; _i < includes_1.length; _i++) { var include = includes_1[_i]; + // We also need to check the relative paths by converting them to absolute and normalizing + // in case they escape the base path (e.g "..\somedirectory") var absolute = ts.isRootedDiskPath(include) ? include : ts.normalizePath(combinePaths(path, include)); + // Append the literal and canonical candidate base paths. includeBasePaths.push(getIncludeBasePath(absolute)); } + // Sort the offsets array using either the literal or canonical path representations. includeBasePaths.sort(ts.getStringComparer(!useCaseSensitiveFileNames)); var _loop_2 = function (includeBasePath) { if (ts.every(basePaths, function (basePath) { return !containsPath(basePath, includeBasePath, path, !useCaseSensitiveFileNames); })) { basePaths.push(includeBasePath); } }; + // Iterate over each include base path and include unique base paths that are not a + // subpath of an existing base path for (var _a = 0, includeBasePaths_1 = includeBasePaths; _a < includeBasePaths_1.length; _a++) { var includeBasePath = includeBasePaths_1[_a]; _loop_2(includeBasePath); @@ -12984,6 +14709,7 @@ var ts; function getIncludeBasePath(absolute) { var wildcardOffset = ts.indexOfAnyCharCode(absolute, wildcardCharCodes); if (wildcardOffset < 0) { + // No "*" or "?" in the path return !hasExtension(absolute) ? absolute : removeTrailingDirectorySeparator(ts.getDirectoryPath(absolute)); @@ -12991,42 +14717,52 @@ var ts; return absolute.substring(0, absolute.lastIndexOf(ts.directorySeparator, wildcardOffset)); } function ensureScriptKind(fileName, scriptKind) { - return scriptKind || getScriptKindFromFileName(fileName) || 3; + // Using scriptKind as a condition handles both: + // - 'scriptKind' is unspecified and thus it is `undefined` + // - 'scriptKind' is set and it is `Unknown` (0) + // If the 'scriptKind' is 'undefined' or 'Unknown' then we attempt + // to get the ScriptKind from the file name. If it cannot be resolved + // from the file name then the default 'TS' script kind is returned. + return scriptKind || getScriptKindFromFileName(fileName) || 3 /* TS */; } ts.ensureScriptKind = ensureScriptKind; function getScriptKindFromFileName(fileName) { var ext = fileName.substr(fileName.lastIndexOf(".")); switch (ext.toLowerCase()) { - case ".js": - return 1; - case ".jsx": - return 2; - case ".ts": - return 3; - case ".tsx": - return 4; - case ".json": - return 6; + case ".js" /* Js */: + return 1 /* JS */; + case ".jsx" /* Jsx */: + return 2 /* JSX */; + case ".ts" /* Ts */: + return 3 /* TS */; + case ".tsx" /* Tsx */: + return 4 /* TSX */; + case ".json" /* Json */: + return 6 /* JSON */; default: - return 0; + return 0 /* Unknown */; } } ts.getScriptKindFromFileName = getScriptKindFromFileName; - ts.supportedTypeScriptExtensions = [".ts", ".tsx", ".d.ts"]; - ts.supportedTypescriptExtensionsForExtractExtension = [".d.ts", ".ts", ".tsx"]; - ts.supportedJavascriptExtensions = [".js", ".jsx"]; + /** + * List of supported extensions in order of file resolution precedence. + */ + ts.supportedTypeScriptExtensions = [".ts" /* Ts */, ".tsx" /* Tsx */, ".d.ts" /* Dts */]; + /** Must have ".d.ts" first because if ".ts" goes first, that will be detected as the extension instead of ".d.ts". */ + ts.supportedTypescriptExtensionsForExtractExtension = [".d.ts" /* Dts */, ".ts" /* Ts */, ".tsx" /* Tsx */]; + ts.supportedJavascriptExtensions = [".js" /* Js */, ".jsx" /* Jsx */]; var allSupportedExtensions = ts.supportedTypeScriptExtensions.concat(ts.supportedJavascriptExtensions); function getSupportedExtensions(options, extraFileExtensions) { var needJsExtensions = options && options.allowJs; if (!extraFileExtensions || extraFileExtensions.length === 0) { return needJsExtensions ? allSupportedExtensions : ts.supportedTypeScriptExtensions; } - var extensions = (needJsExtensions ? allSupportedExtensions : ts.supportedTypeScriptExtensions).concat(ts.mapDefined(extraFileExtensions, function (x) { return x.scriptKind === 7 || needJsExtensions && isJavaScriptLike(x.scriptKind) ? x.extension : undefined; })); + var extensions = (needJsExtensions ? allSupportedExtensions : ts.supportedTypeScriptExtensions).concat(ts.mapDefined(extraFileExtensions, function (x) { return x.scriptKind === 7 /* Deferred */ || needJsExtensions && isJavaScriptLike(x.scriptKind) ? x.extension : undefined; })); return ts.deduplicate(extensions, ts.equateStringsCaseSensitive, ts.compareStringsCaseSensitive); } ts.getSupportedExtensions = getSupportedExtensions; function isJavaScriptLike(scriptKind) { - return scriptKind === 1 || scriptKind === 2; + return scriptKind === 1 /* JS */ || scriptKind === 2 /* JSX */; } function hasJavaScriptFileExtension(fileName) { return ts.some(ts.supportedJavascriptExtensions, function (extension) { return ts.fileExtensionIs(fileName, extension); }); @@ -13049,6 +14785,11 @@ var ts; return false; } ts.isSupportedSourceFileName = isSupportedSourceFileName; + /** + * Extension boundaries by priority. Lower numbers indicate higher priorities, and are + * aligned to the offset of the highest priority extension in the + * allSupportedExtensions array. + */ var ExtensionPriority; (function (ExtensionPriority) { ExtensionPriority[ExtensionPriority["TypeScriptFiles"] = 0] = "TypeScriptFiles"; @@ -13062,31 +14803,39 @@ var ts; return adjustExtensionPriority(i, supportedExtensions); } } - return 0; + // If its not in the list of supported extensions, this is likely a + // TypeScript file with a non-ts extension + return 0 /* Highest */; } ts.getExtensionPriority = getExtensionPriority; + /** + * Adjusts an extension priority to be the highest priority within the same range. + */ function adjustExtensionPriority(extensionPriority, supportedExtensions) { - if (extensionPriority < 2) { - return 0; + if (extensionPriority < 2 /* DeclarationAndJavaScriptFiles */) { + return 0 /* TypeScriptFiles */; } else if (extensionPriority < supportedExtensions.length) { - return 2; + return 2 /* DeclarationAndJavaScriptFiles */; } else { return supportedExtensions.length; } } ts.adjustExtensionPriority = adjustExtensionPriority; + /** + * Gets the next lowest extension priority for a given priority. + */ function getNextLowestExtensionPriority(extensionPriority, supportedExtensions) { - if (extensionPriority < 2) { - return 2; + if (extensionPriority < 2 /* DeclarationAndJavaScriptFiles */) { + return 2 /* DeclarationAndJavaScriptFiles */; } else { return supportedExtensions.length; } } ts.getNextLowestExtensionPriority = getNextLowestExtensionPriority; - var extensionsToRemove = [".d.ts", ".ts", ".js", ".tsx", ".jsx", ".json"]; + var extensionsToRemove = [".d.ts" /* Dts */, ".ts" /* Ts */, ".js" /* Js */, ".tsx" /* Tsx */, ".jsx" /* Jsx */, ".json" /* Json */]; function removeFileExtension(path) { for (var _i = 0, extensionsToRemove_1 = extensionsToRemove; _i < extensionsToRemove_1.length; _i++) { var ext = extensionsToRemove_1[_i]; @@ -13107,7 +14856,7 @@ var ts; } ts.removeExtension = removeExtension; function changeExtension(path, newExtension) { - return changeAnyExtension(path, newExtension, extensionsToRemove, false); + return changeAnyExtension(path, newExtension, extensionsToRemove, /*ignoreCase*/ false); } ts.changeExtension = changeExtension; function changeAnyExtension(path, ext, extensions, ignoreCase) { @@ -13139,6 +14888,7 @@ var ts; Debug.showSyntaxKind = showSyntaxKind; })(Debug = ts.Debug || (ts.Debug = {})); function tryParsePattern(pattern) { + // This should be verified outside of here and a proper error thrown. Debug.assert(ts.hasZeroOrOneAsteriskCharacter(pattern)); var indexOfStar = pattern.indexOf("*"); return indexOfStar === -1 ? undefined : { @@ -13148,17 +14898,24 @@ var ts; } ts.tryParsePattern = tryParsePattern; function positionIsSynthesized(pos) { + // This is a fast way of testing the following conditions: + // pos === undefined || pos === null || isNaN(pos) || pos < 0; return !(pos >= 0); } ts.positionIsSynthesized = positionIsSynthesized; + /** True if an extension is one of the supported TypeScript extensions. */ function extensionIsTypeScript(ext) { - return ext === ".ts" || ext === ".tsx" || ext === ".d.ts"; + return ext === ".ts" /* Ts */ || ext === ".tsx" /* Tsx */ || ext === ".d.ts" /* Dts */; } ts.extensionIsTypeScript = extensionIsTypeScript; function resolutionExtensionIsTypeScriptOrJson(ext) { - return extensionIsTypeScript(ext) || ext === ".json"; + return extensionIsTypeScript(ext) || ext === ".json" /* Json */; } ts.resolutionExtensionIsTypeScriptOrJson = resolutionExtensionIsTypeScriptOrJson; + /** + * Gets the extension from a path. + * Path must have a valid extension. + */ function extensionFromPath(path) { var ext = tryGetExtensionFromPath(path); return ext !== undefined ? ext : Debug.fail("File " + path + " has unknown extension."); @@ -13189,6 +14946,8 @@ var ts; return ""; } function getAnyExtensionFromPath(path, extensions, ignoreCase) { + // Retrieves any string from the final "." onwards from a base file name. + // Unlike extensionFromPath, which throws an exception on unrecognized extensions. if (extensions) { return getAnyExtensionFromPathWorker(path, extensions, ignoreCase ? ts.equateStringsCaseInsensitive : ts.equateStringsCaseSensitive); } @@ -13208,6 +14967,11 @@ var ts; files: ts.emptyArray, directories: ts.emptyArray }; + /** + * patternStrings contains both pattern strings (containing "*") and regular strings. + * Return an exact match if possible, or a pattern match, or undefined. + * (These are verified by verifyCompilerOptions to have 0 or 1 "*" characters.) + */ function matchPatternOrExact(patternStrings, candidate) { var patterns = []; for (var _i = 0, patternStrings_1 = patternStrings; _i < patternStrings_1.length; _i++) { @@ -13217,6 +14981,7 @@ var ts; patterns.push(pattern); } else if (patternString === candidate) { + // pattern was matched as is - no need to search further return patternString; } } @@ -13235,15 +15000,17 @@ var ts; SignatureFlags[SignatureFlags["IgnoreMissingOpenBrace"] = 16] = "IgnoreMissingOpenBrace"; SignatureFlags[SignatureFlags["JSDoc"] = 32] = "JSDoc"; })(SignatureFlags || (SignatureFlags = {})); + // tslint:disable variable-name var NodeConstructor; var TokenConstructor; var IdentifierConstructor; var SourceFileConstructor; + // tslint:enable variable-name function createNode(kind, pos, end) { - if (kind === 274) { + if (kind === 274 /* SourceFile */) { return new (SourceFileConstructor || (SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor()))(kind, pos, end); } - else if (kind === 71) { + else if (kind === 71 /* Identifier */) { return new (IdentifierConstructor || (IdentifierConstructor = ts.objectAllocator.getIdentifierConstructor()))(kind, pos, end); } else if (!ts.isNodeKind(kind)) { @@ -13271,35 +15038,49 @@ var ts; } } } + /*@internal*/ function isJSDocLikeText(text, start) { - return text.charCodeAt(start + 1) === 42 && - text.charCodeAt(start + 2) === 42 && - text.charCodeAt(start + 3) !== 47; + return text.charCodeAt(start + 1) === 42 /* asterisk */ && + text.charCodeAt(start + 2) === 42 /* asterisk */ && + text.charCodeAt(start + 3) !== 47 /* slash */; } ts.isJSDocLikeText = isJSDocLikeText; + /** + * Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes + * stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise, + * embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns + * a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned. + * + * @param node a given node to visit its children + * @param cbNode a callback to be invoked for all child nodes + * @param cbNodes a callback to be invoked for embedded array + * + * @remarks `forEachChild` must visit the children of a node in the order + * that they appear in the source code. The language service depends on this property to locate nodes by position. + */ function forEachChild(node, cbNode, cbNodes) { - if (!node || node.kind <= 145) { + if (!node || node.kind <= 145 /* LastToken */) { return; } switch (node.kind) { - case 146: + case 146 /* QualifiedName */: return visitNode(cbNode, node.left) || visitNode(cbNode, node.right); - case 148: + case 148 /* TypeParameter */: return visitNode(cbNode, node.name) || visitNode(cbNode, node.constraint) || visitNode(cbNode, node.default) || visitNode(cbNode, node.expression); - case 271: + case 271 /* ShorthandPropertyAssignment */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.equalsToken) || visitNode(cbNode, node.objectAssignmentInitializer); - case 272: + case 272 /* SpreadAssignment */: return visitNode(cbNode, node.expression); - case 149: + case 149 /* Parameter */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.dotDotDotToken) || @@ -13307,7 +15088,7 @@ var ts; visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.type) || visitNode(cbNode, node.initializer); - case 152: + case 152 /* PropertyDeclaration */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || @@ -13315,51 +15096,51 @@ var ts; visitNode(cbNode, node.exclamationToken) || visitNode(cbNode, node.type) || visitNode(cbNode, node.initializer); - case 151: + case 151 /* PropertySignature */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.type) || visitNode(cbNode, node.initializer); - case 270: + case 270 /* PropertyAssignment */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.initializer); - case 232: + case 232 /* VariableDeclaration */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.exclamationToken) || visitNode(cbNode, node.type) || visitNode(cbNode, node.initializer); - case 182: + case 182 /* BindingElement */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.dotDotDotToken) || visitNode(cbNode, node.propertyName) || visitNode(cbNode, node.name) || visitNode(cbNode, node.initializer); - case 163: - case 164: - case 158: - case 159: - case 160: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 160 /* IndexSignature */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type); - case 154: - case 153: - case 155: - case 156: - case 157: - case 192: - case 234: - case 193: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 192 /* FunctionExpression */: + case 234 /* FunctionDeclaration */: + case 193 /* ArrowFunction */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.asteriskToken) || @@ -13370,304 +15151,304 @@ var ts; visitNode(cbNode, node.type) || visitNode(cbNode, node.equalsGreaterThanToken) || visitNode(cbNode, node.body); - case 162: + case 162 /* TypeReference */: return visitNode(cbNode, node.typeName) || visitNodes(cbNode, cbNodes, node.typeArguments); - case 161: + case 161 /* TypePredicate */: return visitNode(cbNode, node.parameterName) || visitNode(cbNode, node.type); - case 165: + case 165 /* TypeQuery */: return visitNode(cbNode, node.exprName); - case 166: + case 166 /* TypeLiteral */: return visitNodes(cbNode, cbNodes, node.members); - case 167: + case 167 /* ArrayType */: return visitNode(cbNode, node.elementType); - case 168: + case 168 /* TupleType */: return visitNodes(cbNode, cbNodes, node.elementTypes); - case 169: - case 170: + case 169 /* UnionType */: + case 170 /* IntersectionType */: return visitNodes(cbNode, cbNodes, node.types); - case 171: + case 171 /* ConditionalType */: return visitNode(cbNode, node.checkType) || visitNode(cbNode, node.extendsType) || visitNode(cbNode, node.trueType) || visitNode(cbNode, node.falseType); - case 172: + case 172 /* InferType */: return visitNode(cbNode, node.typeParameter); - case 179: + case 179 /* ImportType */: return visitNode(cbNode, node.argument) || visitNode(cbNode, node.qualifier) || visitNodes(cbNode, cbNodes, node.typeArguments); - case 173: - case 175: + case 173 /* ParenthesizedType */: + case 175 /* TypeOperator */: return visitNode(cbNode, node.type); - case 176: + case 176 /* IndexedAccessType */: return visitNode(cbNode, node.objectType) || visitNode(cbNode, node.indexType); - case 177: + case 177 /* MappedType */: return visitNode(cbNode, node.readonlyToken) || visitNode(cbNode, node.typeParameter) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.type); - case 178: + case 178 /* LiteralType */: return visitNode(cbNode, node.literal); - case 180: - case 181: + case 180 /* ObjectBindingPattern */: + case 181 /* ArrayBindingPattern */: return visitNodes(cbNode, cbNodes, node.elements); - case 183: + case 183 /* ArrayLiteralExpression */: return visitNodes(cbNode, cbNodes, node.elements); - case 184: + case 184 /* ObjectLiteralExpression */: return visitNodes(cbNode, cbNodes, node.properties); - case 185: + case 185 /* PropertyAccessExpression */: return visitNode(cbNode, node.expression) || visitNode(cbNode, node.name); - case 186: + case 186 /* ElementAccessExpression */: return visitNode(cbNode, node.expression) || visitNode(cbNode, node.argumentExpression); - case 187: - case 188: + case 187 /* CallExpression */: + case 188 /* NewExpression */: return visitNode(cbNode, node.expression) || visitNodes(cbNode, cbNodes, node.typeArguments) || visitNodes(cbNode, cbNodes, node.arguments); - case 189: + case 189 /* TaggedTemplateExpression */: return visitNode(cbNode, node.tag) || visitNodes(cbNode, cbNodes, node.typeArguments) || visitNode(cbNode, node.template); - case 190: + case 190 /* TypeAssertionExpression */: return visitNode(cbNode, node.type) || visitNode(cbNode, node.expression); - case 191: + case 191 /* ParenthesizedExpression */: return visitNode(cbNode, node.expression); - case 194: + case 194 /* DeleteExpression */: return visitNode(cbNode, node.expression); - case 195: + case 195 /* TypeOfExpression */: return visitNode(cbNode, node.expression); - case 196: + case 196 /* VoidExpression */: return visitNode(cbNode, node.expression); - case 198: + case 198 /* PrefixUnaryExpression */: return visitNode(cbNode, node.operand); - case 203: + case 203 /* YieldExpression */: return visitNode(cbNode, node.asteriskToken) || visitNode(cbNode, node.expression); - case 197: + case 197 /* AwaitExpression */: return visitNode(cbNode, node.expression); - case 199: + case 199 /* PostfixUnaryExpression */: return visitNode(cbNode, node.operand); - case 200: + case 200 /* BinaryExpression */: return visitNode(cbNode, node.left) || visitNode(cbNode, node.operatorToken) || visitNode(cbNode, node.right); - case 208: + case 208 /* AsExpression */: return visitNode(cbNode, node.expression) || visitNode(cbNode, node.type); - case 209: + case 209 /* NonNullExpression */: return visitNode(cbNode, node.expression); - case 210: + case 210 /* MetaProperty */: return visitNode(cbNode, node.name); - case 201: + case 201 /* ConditionalExpression */: return visitNode(cbNode, node.condition) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.whenTrue) || visitNode(cbNode, node.colonToken) || visitNode(cbNode, node.whenFalse); - case 204: + case 204 /* SpreadElement */: return visitNode(cbNode, node.expression); - case 213: - case 240: + case 213 /* Block */: + case 240 /* ModuleBlock */: return visitNodes(cbNode, cbNodes, node.statements); - case 274: + case 274 /* SourceFile */: return visitNodes(cbNode, cbNodes, node.statements) || visitNode(cbNode, node.endOfFileToken); - case 214: + case 214 /* VariableStatement */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.declarationList); - case 233: + case 233 /* VariableDeclarationList */: return visitNodes(cbNode, cbNodes, node.declarations); - case 216: + case 216 /* ExpressionStatement */: return visitNode(cbNode, node.expression); - case 217: + case 217 /* IfStatement */: return visitNode(cbNode, node.expression) || visitNode(cbNode, node.thenStatement) || visitNode(cbNode, node.elseStatement); - case 218: + case 218 /* DoStatement */: return visitNode(cbNode, node.statement) || visitNode(cbNode, node.expression); - case 219: + case 219 /* WhileStatement */: return visitNode(cbNode, node.expression) || visitNode(cbNode, node.statement); - case 220: + case 220 /* ForStatement */: return visitNode(cbNode, node.initializer) || visitNode(cbNode, node.condition) || visitNode(cbNode, node.incrementor) || visitNode(cbNode, node.statement); - case 221: + case 221 /* ForInStatement */: return visitNode(cbNode, node.initializer) || visitNode(cbNode, node.expression) || visitNode(cbNode, node.statement); - case 222: + case 222 /* ForOfStatement */: return visitNode(cbNode, node.awaitModifier) || visitNode(cbNode, node.initializer) || visitNode(cbNode, node.expression) || visitNode(cbNode, node.statement); - case 223: - case 224: + case 223 /* ContinueStatement */: + case 224 /* BreakStatement */: return visitNode(cbNode, node.label); - case 225: + case 225 /* ReturnStatement */: return visitNode(cbNode, node.expression); - case 226: + case 226 /* WithStatement */: return visitNode(cbNode, node.expression) || visitNode(cbNode, node.statement); - case 227: + case 227 /* SwitchStatement */: return visitNode(cbNode, node.expression) || visitNode(cbNode, node.caseBlock); - case 241: + case 241 /* CaseBlock */: return visitNodes(cbNode, cbNodes, node.clauses); - case 266: + case 266 /* CaseClause */: return visitNode(cbNode, node.expression) || visitNodes(cbNode, cbNodes, node.statements); - case 267: + case 267 /* DefaultClause */: return visitNodes(cbNode, cbNodes, node.statements); - case 228: + case 228 /* LabeledStatement */: return visitNode(cbNode, node.label) || visitNode(cbNode, node.statement); - case 229: + case 229 /* ThrowStatement */: return visitNode(cbNode, node.expression); - case 230: + case 230 /* TryStatement */: return visitNode(cbNode, node.tryBlock) || visitNode(cbNode, node.catchClause) || visitNode(cbNode, node.finallyBlock); - case 269: + case 269 /* CatchClause */: return visitNode(cbNode, node.variableDeclaration) || visitNode(cbNode, node.block); - case 150: + case 150 /* Decorator */: return visitNode(cbNode, node.expression); - case 235: - case 205: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.heritageClauses) || visitNodes(cbNode, cbNodes, node.members); - case 236: + case 236 /* InterfaceDeclaration */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.heritageClauses) || visitNodes(cbNode, cbNodes, node.members); - case 237: + case 237 /* TypeAliasDeclaration */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNode(cbNode, node.type); - case 238: + case 238 /* EnumDeclaration */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.members); - case 273: + case 273 /* EnumMember */: return visitNode(cbNode, node.name) || visitNode(cbNode, node.initializer); - case 239: + case 239 /* ModuleDeclaration */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.body); - case 243: + case 243 /* ImportEqualsDeclaration */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.moduleReference); - case 244: + case 244 /* ImportDeclaration */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.importClause) || visitNode(cbNode, node.moduleSpecifier); - case 245: + case 245 /* ImportClause */: return visitNode(cbNode, node.name) || visitNode(cbNode, node.namedBindings); - case 242: + case 242 /* NamespaceExportDeclaration */: return visitNode(cbNode, node.name); - case 246: + case 246 /* NamespaceImport */: return visitNode(cbNode, node.name); - case 247: - case 251: + case 247 /* NamedImports */: + case 251 /* NamedExports */: return visitNodes(cbNode, cbNodes, node.elements); - case 250: + case 250 /* ExportDeclaration */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.exportClause) || visitNode(cbNode, node.moduleSpecifier); - case 248: - case 252: + case 248 /* ImportSpecifier */: + case 252 /* ExportSpecifier */: return visitNode(cbNode, node.propertyName) || visitNode(cbNode, node.name); - case 249: + case 249 /* ExportAssignment */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.expression); - case 202: + case 202 /* TemplateExpression */: return visitNode(cbNode, node.head) || visitNodes(cbNode, cbNodes, node.templateSpans); - case 211: + case 211 /* TemplateSpan */: return visitNode(cbNode, node.expression) || visitNode(cbNode, node.literal); - case 147: + case 147 /* ComputedPropertyName */: return visitNode(cbNode, node.expression); - case 268: + case 268 /* HeritageClause */: return visitNodes(cbNode, cbNodes, node.types); - case 207: + case 207 /* ExpressionWithTypeArguments */: return visitNode(cbNode, node.expression) || visitNodes(cbNode, cbNodes, node.typeArguments); - case 254: + case 254 /* ExternalModuleReference */: return visitNode(cbNode, node.expression); - case 253: + case 253 /* MissingDeclaration */: return visitNodes(cbNode, cbNodes, node.decorators); - case 303: + case 303 /* CommaListExpression */: return visitNodes(cbNode, cbNodes, node.elements); - case 255: + case 255 /* JsxElement */: return visitNode(cbNode, node.openingElement) || visitNodes(cbNode, cbNodes, node.children) || visitNode(cbNode, node.closingElement); - case 259: + case 259 /* JsxFragment */: return visitNode(cbNode, node.openingFragment) || visitNodes(cbNode, cbNodes, node.children) || visitNode(cbNode, node.closingFragment); - case 256: - case 257: + case 256 /* JsxSelfClosingElement */: + case 257 /* JsxOpeningElement */: return visitNode(cbNode, node.tagName) || visitNodes(cbNode, cbNodes, node.typeArguments) || visitNode(cbNode, node.attributes); - case 263: + case 263 /* JsxAttributes */: return visitNodes(cbNode, cbNodes, node.properties); - case 262: + case 262 /* JsxAttribute */: return visitNode(cbNode, node.name) || visitNode(cbNode, node.initializer); - case 264: + case 264 /* JsxSpreadAttribute */: return visitNode(cbNode, node.expression); - case 265: + case 265 /* JsxExpression */: return visitNode(cbNode, node.dotDotDotToken) || visitNode(cbNode, node.expression); - case 258: + case 258 /* JsxClosingElement */: return visitNode(cbNode, node.tagName); - case 278: + case 278 /* JSDocTypeExpression */: return visitNode(cbNode, node.type); - case 282: + case 282 /* JSDocNonNullableType */: return visitNode(cbNode, node.type); - case 281: + case 281 /* JSDocNullableType */: return visitNode(cbNode, node.type); - case 283: + case 283 /* JSDocOptionalType */: return visitNode(cbNode, node.type); - case 284: + case 284 /* JSDocFunctionType */: return visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type); - case 285: + case 285 /* JSDocVariadicType */: return visitNode(cbNode, node.type); - case 286: + case 286 /* JSDocComment */: return visitNodes(cbNode, cbNodes, node.tags); - case 293: - case 299: + case 293 /* JSDocParameterTag */: + case 299 /* JSDocPropertyTag */: if (node.isNameFirst) { return visitNode(cbNode, node.name) || visitNode(cbNode, node.typeExpression); @@ -13676,17 +15457,17 @@ var ts; return visitNode(cbNode, node.typeExpression) || visitNode(cbNode, node.name); } - case 294: + case 294 /* JSDocReturnTag */: return visitNode(cbNode, node.typeExpression); - case 296: + case 296 /* JSDocTypeTag */: return visitNode(cbNode, node.typeExpression); - case 290: + case 290 /* JSDocAugmentsTag */: return visitNode(cbNode, node.class); - case 297: + case 297 /* JSDocTemplateTag */: return visitNodes(cbNode, cbNodes, node.typeParameters); - case 298: + case 298 /* JSDocTypedefTag */: if (node.typeExpression && - node.typeExpression.kind === 278) { + node.typeExpression.kind === 278 /* JSDocTypeExpression */) { return visitNode(cbNode, node.typeExpression) || visitNode(cbNode, node.fullName); } @@ -13694,18 +15475,18 @@ var ts; return visitNode(cbNode, node.fullName) || visitNode(cbNode, node.typeExpression); } - case 292: + case 292 /* JSDocCallbackTag */: return visitNode(cbNode, node.fullName) || visitNode(cbNode, node.typeExpression); - case 295: + case 295 /* JSDocThisTag */: return visitNode(cbNode, node.typeExpression); - case 288: + case 288 /* JSDocSignature */: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type); - case 287: + case 287 /* JSDocTypeLiteral */: if (node.jsDocPropertyTags) { for (var _i = 0, _a = node.jsDocPropertyTags; _i < _a.length; _i++) { var tag = _a[_i]; @@ -13713,7 +15494,7 @@ var ts; } } return; - case 302: + case 302 /* PartiallyEmittedExpression */: return visitNode(cbNode, node.expression); } } @@ -13722,11 +15503,11 @@ var ts; if (setParentNodes === void 0) { setParentNodes = false; } ts.performance.mark("beforeParse"); var result; - if (languageVersion === 100) { - result = Parser.parseJsonText(fileName, sourceText, languageVersion, undefined, setParentNodes); + if (languageVersion === 100 /* JSON */) { + result = Parser.parseJsonText(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes); } else { - result = Parser.parseSourceFile(fileName, sourceText, languageVersion, undefined, setParentNodes, scriptKind); + result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind); } ts.performance.mark("afterParse"); ts.performance.measure("Parse", "beforeParse", "afterParse"); @@ -13737,41 +15518,71 @@ var ts; return Parser.parseIsolatedEntityName(text, languageVersion); } ts.parseIsolatedEntityName = parseIsolatedEntityName; + /** + * Parse json text into SyntaxTree and return node and parse errors if any + * @param fileName + * @param sourceText + */ function parseJsonText(fileName, sourceText) { return Parser.parseJsonText(fileName, sourceText); } ts.parseJsonText = parseJsonText; + // See also `isExternalOrCommonJsModule` in utilities.ts function isExternalModule(file) { return file.externalModuleIndicator !== undefined; } ts.isExternalModule = isExternalModule; + // Produces a new SourceFile for the 'newText' provided. The 'textChangeRange' parameter + // indicates what changed between the 'text' that this SourceFile has and the 'newText'. + // The SourceFile will be created with the compiler attempting to reuse as many nodes from + // this file as possible. + // + // Note: this function mutates nodes from this SourceFile. That means any existing nodes + // from this SourceFile that are being held onto may change as a result (including + // becoming detached from any SourceFile). It is recommended that this SourceFile not + // be used once 'update' is called on it. function updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks) { if (aggressiveChecks === void 0) { aggressiveChecks = false; } var newSourceFile = IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); - newSourceFile.flags |= (sourceFile.flags & 1572864); + // Because new source file node is created, it may not have the flag PossiblyContainDynamicImport. This is the case if there is no new edit to add dynamic import. + // We will manually port the flag to the new source file. + newSourceFile.flags |= (sourceFile.flags & 1572864 /* PermanentlySetIncrementalFlags */); return newSourceFile; } ts.updateSourceFile = updateSourceFile; + /* @internal */ function parseIsolatedJSDocComment(content, start, length) { var result = Parser.JSDocParser.parseIsolatedJSDocComment(content, start, length); if (result && result.jsDoc) { + // because the jsDocComment was parsed out of the source file, it might + // not be covered by the fixupParentReferences. Parser.fixupParentReferences(result.jsDoc); } return result; } ts.parseIsolatedJSDocComment = parseIsolatedJSDocComment; + /* @internal */ + // Exposed only for testing. function parseJSDocTypeExpressionForTests(content, start, length) { return Parser.JSDocParser.parseJSDocTypeExpressionForTests(content, start, length); } ts.parseJSDocTypeExpressionForTests = parseJSDocTypeExpressionForTests; + // Implement the parser as a singleton module. We do this for perf reasons because creating + // parser instances can actually be expensive enough to impact us on projects with many source + // files. var Parser; (function (Parser) { - var scanner = ts.createScanner(6, true); - var disallowInAndDecoratorContext = 2048 | 8192; + // Share a single scanner across all calls to parse a source file. This helps speed things + // up by avoiding the cost of creating/compiling scanners over and over again. + var scanner = ts.createScanner(6 /* Latest */, /*skipTrivia*/ true); + var disallowInAndDecoratorContext = 2048 /* DisallowInContext */ | 8192 /* DecoratorContext */; + // capture constructors in 'initializeState' to avoid null checks + // tslint:disable variable-name var NodeConstructor; var TokenConstructor; var IdentifierConstructor; var SourceFileConstructor; + // tslint:enable variable-name var sourceFile; var parseDiagnostics; var syntaxCursor; @@ -13781,14 +15592,87 @@ var ts; var identifiers; var identifierCount; var parsingContext; + // Flags that dictate what parsing context we're in. For example: + // Whether or not we are in strict parsing mode. All that changes in strict parsing mode is + // that some tokens that would be considered identifiers may be considered keywords. + // + // When adding more parser context flags, consider which is the more common case that the + // flag will be in. This should be the 'false' state for that flag. The reason for this is + // that we don't store data in our nodes unless the value is in the *non-default* state. So, + // for example, more often than code 'allows-in' (or doesn't 'disallow-in'). We opt for + // 'disallow-in' set to 'false'. Otherwise, if we had 'allowsIn' set to 'true', then almost + // all nodes would need extra state on them to store this info. + // + // Note: 'allowIn' and 'allowYield' track 1:1 with the [in] and [yield] concepts in the ES6 + // grammar specification. + // + // An important thing about these context concepts. By default they are effectively inherited + // while parsing through every grammar production. i.e. if you don't change them, then when + // you parse a sub-production, it will have the same context values as the parent production. + // This is great most of the time. After all, consider all the 'expression' grammar productions + // and how nearly all of them pass along the 'in' and 'yield' context values: + // + // EqualityExpression[In, Yield] : + // RelationalExpression[?In, ?Yield] + // EqualityExpression[?In, ?Yield] == RelationalExpression[?In, ?Yield] + // EqualityExpression[?In, ?Yield] != RelationalExpression[?In, ?Yield] + // EqualityExpression[?In, ?Yield] === RelationalExpression[?In, ?Yield] + // EqualityExpression[?In, ?Yield] !== RelationalExpression[?In, ?Yield] + // + // Where you have to be careful is then understanding what the points are in the grammar + // where the values are *not* passed along. For example: + // + // SingleNameBinding[Yield,GeneratorParameter] + // [+GeneratorParameter]BindingIdentifier[Yield] Initializer[In]opt + // [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt + // + // Here this is saying that if the GeneratorParameter context flag is set, that we should + // explicitly set the 'yield' context flag to false before calling into the BindingIdentifier + // and we should explicitly unset the 'yield' context flag before calling into the Initializer. + // production. Conversely, if the GeneratorParameter context flag is not set, then we + // should leave the 'yield' context flag alone. + // + // Getting this all correct is tricky and requires careful reading of the grammar to + // understand when these values should be changed versus when they should be inherited. + // + // Note: it should not be necessary to save/restore these flags during speculative/lookahead + // parsing. These context flags are naturally stored and restored through normal recursive + // descent parsing and unwinding. var contextFlags; + // Whether or not we've had a parse error since creating the last AST node. If we have + // encountered an error, it will be stored on the next AST node we create. Parse errors + // can be broken down into three categories: + // + // 1) An error that occurred during scanning. For example, an unterminated literal, or a + // character that was completely not understood. + // + // 2) A token was expected, but was not present. This type of error is commonly produced + // by the 'parseExpected' function. + // + // 3) A token was present that no parsing function was able to consume. This type of error + // only occurs in the 'abortParsingListOrMoveToNextToken' function when the parser + // decides to skip the token. + // + // In all of these cases, we want to mark the next node as having had an error before it. + // With this mark, we can know in incremental settings if this node can be reused, or if + // we have to reparse it. If we don't keep this information around, we may just reuse the + // node. in that event we would then not produce the same errors as we did before, causing + // significant confusion problems. + // + // Note: it is necessary that this value be saved/restored during speculative/lookahead + // parsing. During lookahead parsing, we will often create a node. That node will have + // this value attached, and then this value will be set back to 'false'. If we decide to + // rewind, we must get back to the same value we had prior to the lookahead. + // + // Note: any errors at the end of the file that do not precede a regular node, should get + // attached to the EOF token. var parseErrorBeforeNextFinishedNode = false; function parseSourceFile(fileName, sourceText, languageVersion, syntaxCursor, setParentNodes, scriptKind) { if (setParentNodes === void 0) { setParentNodes = false; } scriptKind = ts.ensureScriptKind(fileName, scriptKind); - if (scriptKind === 6) { + if (scriptKind === 6 /* JSON */) { var result_1 = parseJsonText(fileName, sourceText, languageVersion, syntaxCursor, setParentNodes); - ts.convertToObjectWorker(result_1, result_1.parseDiagnostics, false, undefined, undefined); + ts.convertToObjectWorker(result_1, result_1.parseDiagnostics, /*returnValue*/ false, /*knownRootOptions*/ undefined, /*jsonConversionNotifier*/ undefined); result_1.typeReferenceDirectives = ts.emptyArray; result_1.amdDependencies = ts.emptyArray; return result_1; @@ -13800,57 +15684,62 @@ var ts; } Parser.parseSourceFile = parseSourceFile; function parseIsolatedEntityName(content, languageVersion) { - initializeState(content, languageVersion, undefined, 1); + // Choice of `isDeclarationFile` should be arbitrary + initializeState(content, languageVersion, /*syntaxCursor*/ undefined, 1 /* JS */); + // Prime the scanner. nextToken(); - var entityName = parseEntityName(true); - var isInvalid = token() === 1 && !parseDiagnostics.length; + var entityName = parseEntityName(/*allowReservedWords*/ true); + var isInvalid = token() === 1 /* EndOfFileToken */ && !parseDiagnostics.length; clearState(); return isInvalid ? entityName : undefined; } Parser.parseIsolatedEntityName = parseIsolatedEntityName; function parseJsonText(fileName, sourceText, languageVersion, syntaxCursor, setParentNodes) { - if (languageVersion === void 0) { languageVersion = 2; } - initializeState(sourceText, languageVersion, syntaxCursor, 6); - sourceFile = createSourceFile(fileName, 2, 6, false); + if (languageVersion === void 0) { languageVersion = 2 /* ES2015 */; } + initializeState(sourceText, languageVersion, syntaxCursor, 6 /* JSON */); + // Set source file so that errors will be reported with this file name + sourceFile = createSourceFile(fileName, 2 /* ES2015 */, 6 /* JSON */, /*isDeclaration*/ false); sourceFile.flags = contextFlags; + // Prime the scanner. nextToken(); var pos = getNodePos(); - if (token() === 1) { + if (token() === 1 /* EndOfFileToken */) { sourceFile.statements = createNodeArray([], pos, pos); sourceFile.endOfFileToken = parseTokenNode(); } else { - var statement = createNode(216); + var statement = createNode(216 /* ExpressionStatement */); switch (token()) { - case 21: + case 21 /* OpenBracketToken */: statement.expression = parseArrayLiteralExpression(); break; - case 101: - case 86: - case 95: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: + case 95 /* NullKeyword */: statement.expression = parseTokenNode(); break; - case 38: - if (lookAhead(function () { return nextToken() === 8 && nextToken() !== 56; })) { + case 38 /* MinusToken */: + if (lookAhead(function () { return nextToken() === 8 /* NumericLiteral */ && nextToken() !== 56 /* ColonToken */; })) { statement.expression = parsePrefixUnaryExpression(); } else { statement.expression = parseObjectLiteralExpression(); } break; - case 8: - case 9: - if (lookAhead(function () { return nextToken() !== 56; })) { + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: + if (lookAhead(function () { return nextToken() !== 56 /* ColonToken */; })) { statement.expression = parseLiteralNode(); break; } + // falls through default: statement.expression = parseObjectLiteralExpression(); break; } finishNode(statement); sourceFile.statements = createNodeArray([statement], pos); - sourceFile.endOfFileToken = parseExpectedToken(1, ts.Diagnostics.Unexpected_token); + sourceFile.endOfFileToken = parseExpectedToken(1 /* EndOfFileToken */, ts.Diagnostics.Unexpected_token); } if (setParentNodes) { fixupParentReferences(sourceFile); @@ -13862,7 +15751,8 @@ var ts; } Parser.parseJsonText = parseJsonText; function getLanguageVariant(scriptKind) { - return scriptKind === 4 || scriptKind === 2 || scriptKind === 1 || scriptKind === 6 ? 1 : 0; + // .tsx and .jsx files are treated as jsx language variant. + return scriptKind === 4 /* TSX */ || scriptKind === 2 /* JSX */ || scriptKind === 1 /* JS */ || scriptKind === 6 /* JSON */ ? 1 /* JSX */ : 0 /* Standard */; } function initializeState(_sourceText, languageVersion, _syntaxCursor, scriptKind) { NodeConstructor = ts.objectAllocator.getNodeConstructor(); @@ -13877,26 +15767,29 @@ var ts; identifierCount = 0; nodeCount = 0; switch (scriptKind) { - case 1: - case 2: - contextFlags = 65536; + case 1 /* JS */: + case 2 /* JSX */: + contextFlags = 65536 /* JavaScriptFile */; break; - case 6: - contextFlags = 65536 | 16777216; + case 6 /* JSON */: + contextFlags = 65536 /* JavaScriptFile */ | 16777216 /* JsonFile */; break; default: - contextFlags = 0; + contextFlags = 0 /* None */; break; } parseErrorBeforeNextFinishedNode = false; + // Initialize and prime the scanner before parsing the source elements. scanner.setText(sourceText); scanner.setOnError(scanError); scanner.setScriptTarget(languageVersion); scanner.setLanguageVariant(getLanguageVariant(scriptKind)); } function clearState() { + // Clear out the text the scanner is pointing at, so it doesn't keep anything alive unnecessarily. scanner.setText(""); scanner.setOnError(undefined); + // Clear any data. We don't want to accidentally hold onto it for too long. parseDiagnostics = undefined; sourceFile = undefined; identifiers = undefined; @@ -13906,15 +15799,17 @@ var ts; function parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind) { var isDeclarationFile = isDeclarationFileName(fileName); if (isDeclarationFile) { - contextFlags |= 4194304; + contextFlags |= 4194304 /* Ambient */; } sourceFile = createSourceFile(fileName, languageVersion, scriptKind, isDeclarationFile); sourceFile.flags = contextFlags; + // Prime the scanner. nextToken(); + // A member of ReadonlyArray isn't assignable to a member of T[] (and prevents a direct cast) - but this is where we set up those members so they can be readonly in the future processCommentPragmas(sourceFile, sourceText); processPragmasIntoFields(sourceFile, reportPragmaDiagnostic); - sourceFile.statements = parseList(0, parseStatement); - ts.Debug.assert(token() === 1); + sourceFile.statements = parseList(0 /* SourceElements */, parseStatement); + ts.Debug.assert(token() === 1 /* EndOfFileToken */); sourceFile.endOfFileToken = addJSDocComment(parseTokenNode()); setExternalModuleIndicator(sourceFile); sourceFile.nodeCount = nodeCount; @@ -13940,10 +15835,17 @@ var ts; return node; } function fixupParentReferences(rootNode) { + // normally parent references are set during binding. However, for clients that only need + // a syntax tree, and no semantic features, then the binding process is an unnecessary + // overhead. This functions allows us to set all the parents, without all the expense of + // binding. var parent = rootNode; forEachChild(rootNode, visitNode); return; function visitNode(n) { + // walk down setting parents that differ from the parent we think it should be. This + // allows us to quickly bail out of setting parents for subtrees during incremental + // parsing if (n.parent !== parent) { n.parent = parent; var saveParent = parent; @@ -13963,7 +15865,9 @@ var ts; } Parser.fixupParentReferences = fixupParentReferences; function createSourceFile(fileName, languageVersion, scriptKind, isDeclarationFile) { - var sourceFile = new SourceFileConstructor(274, 0, sourceText.length); + // code from createNode is inlined here so createNode won't have to deal with special case of creating source files + // this is quite rare comparing to other nodes and createNode should be as fast as possible + var sourceFile = new SourceFileConstructor(274 /* SourceFile */, /*pos*/ 0, /* end */ sourceText.length); nodeCount++; sourceFile.text = sourceText; sourceFile.bindDiagnostics = []; @@ -13984,81 +15888,102 @@ var ts; } } function setDisallowInContext(val) { - setContextFlag(val, 2048); + setContextFlag(val, 2048 /* DisallowInContext */); } function setYieldContext(val) { - setContextFlag(val, 4096); + setContextFlag(val, 4096 /* YieldContext */); } function setDecoratorContext(val) { - setContextFlag(val, 8192); + setContextFlag(val, 8192 /* DecoratorContext */); } function setAwaitContext(val) { - setContextFlag(val, 16384); + setContextFlag(val, 16384 /* AwaitContext */); } function doOutsideOfContext(context, func) { + // contextFlagsToClear will contain only the context flags that are + // currently set that we need to temporarily clear + // We don't just blindly reset to the previous flags to ensure + // that we do not mutate cached flags for the incremental + // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and + // HasAggregatedChildData). var contextFlagsToClear = context & contextFlags; if (contextFlagsToClear) { - setContextFlag(false, contextFlagsToClear); + // clear the requested context flags + setContextFlag(/*val*/ false, contextFlagsToClear); var result = func(); - setContextFlag(true, contextFlagsToClear); + // restore the context flags we just cleared + setContextFlag(/*val*/ true, contextFlagsToClear); return result; } + // no need to do anything special as we are not in any of the requested contexts return func(); } function doInsideOfContext(context, func) { + // contextFlagsToSet will contain only the context flags that + // are not currently set that we need to temporarily enable. + // We don't just blindly reset to the previous flags to ensure + // that we do not mutate cached flags for the incremental + // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and + // HasAggregatedChildData). var contextFlagsToSet = context & ~contextFlags; if (contextFlagsToSet) { - setContextFlag(true, contextFlagsToSet); + // set the requested context flags + setContextFlag(/*val*/ true, contextFlagsToSet); var result = func(); - setContextFlag(false, contextFlagsToSet); + // reset the context flags we just set + setContextFlag(/*val*/ false, contextFlagsToSet); return result; } + // no need to do anything special as we are already in all of the requested contexts return func(); } function allowInAnd(func) { - return doOutsideOfContext(2048, func); + return doOutsideOfContext(2048 /* DisallowInContext */, func); } function disallowInAnd(func) { - return doInsideOfContext(2048, func); + return doInsideOfContext(2048 /* DisallowInContext */, func); } function doInYieldContext(func) { - return doInsideOfContext(4096, func); + return doInsideOfContext(4096 /* YieldContext */, func); } function doInDecoratorContext(func) { - return doInsideOfContext(8192, func); + return doInsideOfContext(8192 /* DecoratorContext */, func); } function doInAwaitContext(func) { - return doInsideOfContext(16384, func); + return doInsideOfContext(16384 /* AwaitContext */, func); } function doOutsideOfAwaitContext(func) { - return doOutsideOfContext(16384, func); + return doOutsideOfContext(16384 /* AwaitContext */, func); } function doInYieldAndAwaitContext(func) { - return doInsideOfContext(4096 | 16384, func); + return doInsideOfContext(4096 /* YieldContext */ | 16384 /* AwaitContext */, func); } function inContext(flags) { return (contextFlags & flags) !== 0; } function inYieldContext() { - return inContext(4096); + return inContext(4096 /* YieldContext */); } function inDisallowInContext() { - return inContext(2048); + return inContext(2048 /* DisallowInContext */); } function inDecoratorContext() { - return inContext(8192); + return inContext(8192 /* DecoratorContext */); } function inAwaitContext() { - return inContext(16384); + return inContext(16384 /* AwaitContext */); } function parseErrorAtCurrentToken(message, arg0) { parseErrorAt(scanner.getTokenPos(), scanner.getTextPos(), message, arg0); } function parseErrorAtPosition(start, length, message, arg0) { + // Don't report another error if it would just be at the same position as the last error. var lastError = ts.lastOrUndefined(parseDiagnostics); if (!lastError || start !== lastError.start) { parseDiagnostics.push(ts.createFileDiagnostic(sourceFile, start, length, message, arg0)); } + // Mark that we've encountered an error. We'll set an appropriate bit on the next + // node we finish so that it can't be reused incrementally. parseErrorBeforeNextFinishedNode = true; } function parseErrorAt(start, end, message, arg0) { @@ -14073,6 +15998,12 @@ var ts; function getNodePos() { return scanner.getStartPos(); } + // Use this function to access the current token instead of reading the currentToken + // variable. Since function results aren't narrowed in control flow analysis, this ensures + // that the type checker doesn't make wrong assumptions about the type of the current + // token (e.g. a call to nextToken() changes the current token but the checker doesn't + // reason about this side effect). Mainstream VMs inline simple functions like this, so + // there is no performance penalty. function token() { return currentToken; } @@ -14098,14 +16029,25 @@ var ts; return currentToken = scanner.scanJsxAttributeValue(); } function speculationHelper(callback, isLookAhead) { + // Keep track of the state we'll need to rollback to if lookahead fails (or if the + // caller asked us to always reset our state). var saveToken = currentToken; var saveParseDiagnosticsLength = parseDiagnostics.length; var saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode; + // Note: it is not actually necessary to save/restore the context flags here. That's + // because the saving/restoring of these flags happens naturally through the recursive + // descent nature of our parser. However, we still store this here just so we can + // assert that invariant holds. var saveContextFlags = contextFlags; + // If we're only looking ahead, then tell the scanner to only lookahead as well. + // Otherwise, if we're actually speculatively parsing, then tell the scanner to do the + // same. var result = isLookAhead ? scanner.lookAhead(callback) : scanner.tryScan(callback); ts.Debug.assert(saveContextFlags === contextFlags); + // If our callback returned something 'falsy' or we're just looking ahead, + // then unconditionally restore us to where we were. if (!result || isLookAhead) { currentToken = saveToken; parseDiagnostics.length = saveParseDiagnosticsLength; @@ -14113,23 +16055,37 @@ var ts; } return result; } + /** Invokes the provided callback then unconditionally restores the parser to the state it + * was in immediately prior to invoking the callback. The result of invoking the callback + * is returned from this function. + */ function lookAhead(callback) { - return speculationHelper(callback, true); + return speculationHelper(callback, /*isLookAhead*/ true); } + /** Invokes the provided callback. If the callback returns something falsy, then it restores + * the parser to the state it was in immediately prior to invoking the callback. If the + * callback returns something truthy, then the parser state is not rolled back. The result + * of invoking the callback is returned from this function. + */ function tryParse(callback) { - return speculationHelper(callback, false); + return speculationHelper(callback, /*isLookAhead*/ false); } + // Ignore strict mode flag because we will report an error in type checker instead. function isIdentifier() { - if (token() === 71) { + if (token() === 71 /* Identifier */) { return true; } - if (token() === 116 && inYieldContext()) { + // If we have a 'yield' keyword, and we're in the [yield] context, then 'yield' is + // considered a keyword and is not an identifier. + if (token() === 116 /* YieldKeyword */ && inYieldContext()) { return false; } - if (token() === 121 && inAwaitContext()) { + // If we have a 'await' keyword, and we're in the [Await] context, then 'await' is + // considered a keyword and is not an identifier. + if (token() === 121 /* AwaitKeyword */ && inAwaitContext()) { return false; } - return token() > 107; + return token() > 107 /* LastReservedWord */; } function parseExpected(kind, diagnosticMessage, shouldAdvance) { if (shouldAdvance === void 0) { shouldAdvance = true; } @@ -14139,6 +16095,7 @@ var ts; } return true; } + // Report specific message if provided with one. Otherwise, report generic fallback message. if (diagnosticMessage) { parseErrorAtCurrentToken(diagnosticMessage); } @@ -14162,7 +16119,7 @@ var ts; } function parseExpectedToken(t, diagnosticMessage, arg0) { return parseOptionalToken(t) || - createMissingNode(t, false, diagnosticMessage || ts.Diagnostics._0_expected, arg0 || ts.tokenToString(t)); + createMissingNode(t, /*reportAtCurrentPosition*/ false, diagnosticMessage || ts.Diagnostics._0_expected, arg0 || ts.tokenToString(t)); } function parseTokenNode() { var node = createNode(token()); @@ -14170,37 +16127,43 @@ var ts; return finishNode(node); } function canParseSemicolon() { - if (token() === 25) { + // If there's a real semicolon, then we can always parse it out. + if (token() === 25 /* SemicolonToken */) { return true; } - return token() === 18 || token() === 1 || scanner.hasPrecedingLineBreak(); + // We can parse out an optional semicolon in ASI cases in the following cases. + return token() === 18 /* CloseBraceToken */ || token() === 1 /* EndOfFileToken */ || scanner.hasPrecedingLineBreak(); } function parseSemicolon() { if (canParseSemicolon()) { - if (token() === 25) { + if (token() === 25 /* SemicolonToken */) { + // consume the semicolon if it was explicitly provided. nextToken(); } return true; } else { - return parseExpected(25); + return parseExpected(25 /* SemicolonToken */); } } function createNode(kind, pos) { nodeCount++; var p = pos >= 0 ? pos : scanner.getStartPos(); - return ts.isNodeKind(kind) || kind === 0 ? new NodeConstructor(kind, p, p) : - kind === 71 ? new IdentifierConstructor(kind, p, p) : + return ts.isNodeKind(kind) || kind === 0 /* Unknown */ ? new NodeConstructor(kind, p, p) : + kind === 71 /* Identifier */ ? new IdentifierConstructor(kind, p, p) : new TokenConstructor(kind, p, p); } function createNodeWithJSDoc(kind, pos) { var node = createNode(kind, pos); - if (scanner.getTokenFlags() & 2) { + if (scanner.getTokenFlags() & 2 /* PrecedingJSDocComment */) { addJSDocComment(node); } return node; } function createNodeArray(elements, pos, end) { + // Since the element list of a node array is typically created by starting with an empty array and + // repeatedly calling push(), the list may not have the optimal memory layout. We invoke slice() for + // small arrays (1 to 4 elements) to give the VM a chance to allocate an optimal representation. var length = elements.length; var array = (length >= 1 && length <= 4 ? elements.slice() : elements); array.pos = pos; @@ -14212,9 +16175,12 @@ var ts; if (contextFlags) { node.flags |= contextFlags; } + // Keep track on the node if we encountered an error while parsing it. If we did, then + // we cannot reuse the node incrementally. Once we've marked this node, clear out the + // flag so that we don't mark any subsequent nodes. if (parseErrorBeforeNextFinishedNode) { parseErrorBeforeNextFinishedNode = false; - node.flags |= 32768; + node.flags |= 32768 /* ThisNodeHasError */; } return node; } @@ -14226,7 +16192,7 @@ var ts; parseErrorAtCurrentToken(diagnosticMessage, arg0); } var result = createNode(kind); - if (kind === 71) { + if (kind === 71 /* Identifier */) { result.escapedText = ""; } else if (ts.isLiteralKind(kind) || ts.isTemplateLiteralKind(kind)) { @@ -14241,19 +16207,24 @@ var ts; } return identifier; } + // An identifier that starts with two underscores has an extra underscore character prepended to it to avoid issues + // with magic property names like '__proto__'. The 'identifiers' object is used to share a single string instance for + // each identifier in order to reduce memory consumption. function createIdentifier(isIdentifier, diagnosticMessage) { identifierCount++; if (isIdentifier) { - var node = createNode(71); - if (token() !== 71) { + var node = createNode(71 /* Identifier */); + // Store original token kind if it is not just an Identifier so we can report appropriate error later in type checker + if (token() !== 71 /* Identifier */) { node.originalKeywordKind = token(); } node.escapedText = ts.escapeLeadingUnderscores(internIdentifier(scanner.getTokenValue())); nextToken(); return finishNode(node); } - var reportAtCurrentPosition = token() === 1; - return createMissingNode(71, reportAtCurrentPosition, diagnosticMessage || ts.Diagnostics.Identifier_expected); + // Only for end of file because the error gets reported incorrectly on embedded script tags. + var reportAtCurrentPosition = token() === 1 /* EndOfFileToken */; + return createMissingNode(71 /* Identifier */, reportAtCurrentPosition, diagnosticMessage || ts.Diagnostics.Identifier_expected); } function parseIdentifier(diagnosticMessage) { return createIdentifier(isIdentifier(), diagnosticMessage); @@ -14263,28 +16234,34 @@ var ts; } function isLiteralPropertyName() { return ts.tokenIsIdentifierOrKeyword(token()) || - token() === 9 || - token() === 8; + token() === 9 /* StringLiteral */ || + token() === 8 /* NumericLiteral */; } function parsePropertyNameWorker(allowComputedPropertyNames) { - if (token() === 9 || token() === 8) { + if (token() === 9 /* StringLiteral */ || token() === 8 /* NumericLiteral */) { var node = parseLiteralNode(); node.text = internIdentifier(node.text); return node; } - if (allowComputedPropertyNames && token() === 21) { + if (allowComputedPropertyNames && token() === 21 /* OpenBracketToken */) { return parseComputedPropertyName(); } return parseIdentifierName(); } function parsePropertyName() { - return parsePropertyNameWorker(true); + return parsePropertyNameWorker(/*allowComputedPropertyNames*/ true); } function parseComputedPropertyName() { - var node = createNode(147); - parseExpected(21); + // PropertyName [Yield]: + // LiteralPropertyName + // ComputedPropertyName[?Yield] + var node = createNode(147 /* ComputedPropertyName */); + parseExpected(21 /* OpenBracketToken */); + // We parse any expression (including a comma expression). But the grammar + // says that only an assignment expression is allowed, so the grammar checker + // will error if it sees a comma expression. node.expression = allowInAnd(parseExpression); - parseExpected(22); + parseExpected(22 /* CloseBracketToken */); return finishNode(node); } function parseContextualModifier(t) { @@ -14299,19 +16276,20 @@ var ts; } function nextTokenCanFollowModifier() { switch (token()) { - case 76: - return nextToken() === 83; - case 84: + case 76 /* ConstKeyword */: + // 'const' is only a modifier if followed by 'enum'. + return nextToken() === 83 /* EnumKeyword */; + case 84 /* ExportKeyword */: nextToken(); - if (token() === 79) { + if (token() === 79 /* DefaultKeyword */) { return lookAhead(nextTokenCanFollowDefaultKeyword); } - return token() !== 39 && token() !== 118 && token() !== 17 && canFollowModifier(); - case 79: + return token() !== 39 /* AsteriskToken */ && token() !== 118 /* AsKeyword */ && token() !== 17 /* OpenBraceToken */ && canFollowModifier(); + case 79 /* DefaultKeyword */: return nextTokenCanFollowDefaultKeyword(); - case 115: - case 125: - case 136: + case 115 /* StaticKeyword */: + case 125 /* GetKeyword */: + case 136 /* SetKeyword */: nextToken(); return canFollowModifier(); default: @@ -14322,86 +16300,112 @@ var ts; return ts.isModifierKind(token()) && tryParse(nextTokenCanFollowModifier); } function canFollowModifier() { - return token() === 21 - || token() === 17 - || token() === 39 - || token() === 24 + return token() === 21 /* OpenBracketToken */ + || token() === 17 /* OpenBraceToken */ + || token() === 39 /* AsteriskToken */ + || token() === 24 /* DotDotDotToken */ || isLiteralPropertyName(); } function nextTokenCanFollowDefaultKeyword() { nextToken(); - return token() === 75 || token() === 89 || - token() === 109 || - (token() === 117 && lookAhead(nextTokenIsClassKeywordOnSameLine)) || - (token() === 120 && lookAhead(nextTokenIsFunctionKeywordOnSameLine)); + return token() === 75 /* ClassKeyword */ || token() === 89 /* FunctionKeyword */ || + token() === 109 /* InterfaceKeyword */ || + (token() === 117 /* AbstractKeyword */ && lookAhead(nextTokenIsClassKeywordOnSameLine)) || + (token() === 120 /* AsyncKeyword */ && lookAhead(nextTokenIsFunctionKeywordOnSameLine)); } + // True if positioned at the start of a list element function isListElement(parsingContext, inErrorRecovery) { var node = currentNode(parsingContext); if (node) { return true; } switch (parsingContext) { - case 0: - case 1: - case 3: - return !(token() === 25 && inErrorRecovery) && isStartOfStatement(); - case 2: - return token() === 73 || token() === 79; - case 4: + case 0 /* SourceElements */: + case 1 /* BlockStatements */: + case 3 /* SwitchClauseStatements */: + // If we're in error recovery, then we don't want to treat ';' as an empty statement. + // The problem is that ';' can show up in far too many contexts, and if we see one + // and assume it's a statement, then we may bail out inappropriately from whatever + // we're parsing. For example, if we have a semicolon in the middle of a class, then + // we really don't want to assume the class is over and we're on a statement in the + // outer module. We just want to consume and move on. + return !(token() === 25 /* SemicolonToken */ && inErrorRecovery) && isStartOfStatement(); + case 2 /* SwitchClauses */: + return token() === 73 /* CaseKeyword */ || token() === 79 /* DefaultKeyword */; + case 4 /* TypeMembers */: return lookAhead(isTypeMemberStart); - case 5: - return lookAhead(isClassMemberStart) || (token() === 25 && !inErrorRecovery); - case 6: - return token() === 21 || isLiteralPropertyName(); - case 12: - return token() === 21 || token() === 39 || token() === 24 || isLiteralPropertyName(); - case 17: + case 5 /* ClassMembers */: + // We allow semicolons as class elements (as specified by ES6) as long as we're + // not in error recovery. If we're in error recovery, we don't want an errant + // semicolon to be treated as a class member (since they're almost always used + // for statements. + return lookAhead(isClassMemberStart) || (token() === 25 /* SemicolonToken */ && !inErrorRecovery); + case 6 /* EnumMembers */: + // Include open bracket computed properties. This technically also lets in indexers, + // which would be a candidate for improved error reporting. + return token() === 21 /* OpenBracketToken */ || isLiteralPropertyName(); + case 12 /* ObjectLiteralMembers */: + return token() === 21 /* OpenBracketToken */ || token() === 39 /* AsteriskToken */ || token() === 24 /* DotDotDotToken */ || isLiteralPropertyName(); + case 17 /* RestProperties */: return isLiteralPropertyName(); - case 9: - return token() === 21 || token() === 24 || isLiteralPropertyName(); - case 7: - if (token() === 17) { + case 9 /* ObjectBindingElements */: + return token() === 21 /* OpenBracketToken */ || token() === 24 /* DotDotDotToken */ || isLiteralPropertyName(); + case 7 /* HeritageClauseElement */: + // If we see `{ ... }` then only consume it as an expression if it is followed by `,` or `{` + // That way we won't consume the body of a class in its heritage clause. + if (token() === 17 /* OpenBraceToken */) { return lookAhead(isValidHeritageClauseObjectLiteral); } if (!inErrorRecovery) { return isStartOfLeftHandSideExpression() && !isHeritageClauseExtendsOrImplementsKeyword(); } else { + // If we're in error recovery we tighten up what we're willing to match. + // That way we don't treat something like "this" as a valid heritage clause + // element during recovery. return isIdentifier() && !isHeritageClauseExtendsOrImplementsKeyword(); } - case 8: + case 8 /* VariableDeclarations */: return isIdentifierOrPattern(); - case 10: - return token() === 26 || token() === 24 || isIdentifierOrPattern(); - case 18: + case 10 /* ArrayBindingElements */: + return token() === 26 /* CommaToken */ || token() === 24 /* DotDotDotToken */ || isIdentifierOrPattern(); + case 18 /* TypeParameters */: return isIdentifier(); - case 15: - if (token() === 26) { + case 15 /* ArrayLiteralMembers */: + if (token() === 26 /* CommaToken */) { return true; } - case 11: - return token() === 24 || isStartOfExpression(); - case 16: + // falls through + case 11 /* ArgumentExpressions */: + return token() === 24 /* DotDotDotToken */ || isStartOfExpression(); + case 16 /* Parameters */: return isStartOfParameter(); - case 19: - case 20: - return token() === 26 || isStartOfType(); - case 21: + case 19 /* TypeArguments */: + case 20 /* TupleElementTypes */: + return token() === 26 /* CommaToken */ || isStartOfType(); + case 21 /* HeritageClauses */: return isHeritageClause(); - case 22: + case 22 /* ImportOrExportSpecifiers */: return ts.tokenIsIdentifierOrKeyword(token()); - case 13: - return ts.tokenIsIdentifierOrKeyword(token()) || token() === 17; - case 14: + case 13 /* JsxAttributes */: + return ts.tokenIsIdentifierOrKeyword(token()) || token() === 17 /* OpenBraceToken */; + case 14 /* JsxChildren */: return true; } return ts.Debug.fail("Non-exhaustive case in 'isListElement'."); } function isValidHeritageClauseObjectLiteral() { - ts.Debug.assert(token() === 17); - if (nextToken() === 18) { + ts.Debug.assert(token() === 17 /* OpenBraceToken */); + if (nextToken() === 18 /* CloseBraceToken */) { + // if we see "extends {}" then only treat the {} as what we're extending (and not + // the class body) if we have: + // + // extends {} { + // extends {}, + // extends {} extends + // extends {} implements var next = nextToken(); - return next === 26 || next === 17 || next === 85 || next === 108; + return next === 26 /* CommaToken */ || next === 17 /* OpenBraceToken */ || next === 85 /* ExtendsKeyword */ || next === 108 /* ImplementsKeyword */; } return true; } @@ -14418,8 +16422,8 @@ var ts; return ts.tokenIsIdentifierOrKeywordOrGreaterThan(token()); } function isHeritageClauseExtendsOrImplementsKeyword() { - if (token() === 108 || - token() === 85) { + if (token() === 108 /* ImplementsKeyword */ || + token() === 85 /* ExtendsKeyword */) { return lookAhead(nextTokenIsStartOfExpression); } return false; @@ -14432,78 +16436,95 @@ var ts; nextToken(); return isStartOfType(); } + // True if positioned at a list terminator function isListTerminator(kind) { - if (token() === 1) { + if (token() === 1 /* EndOfFileToken */) { + // Being at the end of the file ends all lists. return true; } switch (kind) { - case 1: - case 2: - case 4: - case 5: - case 6: - case 12: - case 9: - case 22: - return token() === 18; - case 3: - return token() === 18 || token() === 73 || token() === 79; - case 7: - return token() === 17 || token() === 85 || token() === 108; - case 8: + case 1 /* BlockStatements */: + case 2 /* SwitchClauses */: + case 4 /* TypeMembers */: + case 5 /* ClassMembers */: + case 6 /* EnumMembers */: + case 12 /* ObjectLiteralMembers */: + case 9 /* ObjectBindingElements */: + case 22 /* ImportOrExportSpecifiers */: + return token() === 18 /* CloseBraceToken */; + case 3 /* SwitchClauseStatements */: + return token() === 18 /* CloseBraceToken */ || token() === 73 /* CaseKeyword */ || token() === 79 /* DefaultKeyword */; + case 7 /* HeritageClauseElement */: + return token() === 17 /* OpenBraceToken */ || token() === 85 /* ExtendsKeyword */ || token() === 108 /* ImplementsKeyword */; + case 8 /* VariableDeclarations */: return isVariableDeclaratorListTerminator(); - case 18: - return token() === 29 || token() === 19 || token() === 17 || token() === 85 || token() === 108; - case 11: - return token() === 20 || token() === 25; - case 15: - case 20: - case 10: - return token() === 22; - case 16: - case 17: - return token() === 20 || token() === 22; - case 19: - return token() !== 26; - case 21: - return token() === 17 || token() === 18; - case 13: - return token() === 29 || token() === 41; - case 14: - return token() === 27 && lookAhead(nextTokenIsSlash); + case 18 /* TypeParameters */: + // Tokens other than '>' are here for better error recovery + return token() === 29 /* GreaterThanToken */ || token() === 19 /* OpenParenToken */ || token() === 17 /* OpenBraceToken */ || token() === 85 /* ExtendsKeyword */ || token() === 108 /* ImplementsKeyword */; + case 11 /* ArgumentExpressions */: + // Tokens other than ')' are here for better error recovery + return token() === 20 /* CloseParenToken */ || token() === 25 /* SemicolonToken */; + case 15 /* ArrayLiteralMembers */: + case 20 /* TupleElementTypes */: + case 10 /* ArrayBindingElements */: + return token() === 22 /* CloseBracketToken */; + case 16 /* Parameters */: + case 17 /* RestProperties */: + // Tokens other than ')' and ']' (the latter for index signatures) are here for better error recovery + return token() === 20 /* CloseParenToken */ || token() === 22 /* CloseBracketToken */ /*|| token === SyntaxKind.OpenBraceToken*/; + case 19 /* TypeArguments */: + // All other tokens should cause the type-argument to terminate except comma token + return token() !== 26 /* CommaToken */; + case 21 /* HeritageClauses */: + return token() === 17 /* OpenBraceToken */ || token() === 18 /* CloseBraceToken */; + case 13 /* JsxAttributes */: + return token() === 29 /* GreaterThanToken */ || token() === 41 /* SlashToken */; + case 14 /* JsxChildren */: + return token() === 27 /* LessThanToken */ && lookAhead(nextTokenIsSlash); default: return false; } } function isVariableDeclaratorListTerminator() { + // If we can consume a semicolon (either explicitly, or with ASI), then consider us done + // with parsing the list of variable declarators. if (canParseSemicolon()) { return true; } + // in the case where we're parsing the variable declarator of a 'for-in' statement, we + // are done if we see an 'in' keyword in front of us. Same with for-of if (isInOrOfKeyword(token())) { return true; } - if (token() === 36) { + // ERROR RECOVERY TWEAK: + // For better error recovery, if we see an '=>' then we just stop immediately. We've got an + // arrow function here and it's going to be very unlikely that we'll resynchronize and get + // another variable declaration. + if (token() === 36 /* EqualsGreaterThanToken */) { return true; } + // Keep trying to parse out variable declarators. return false; } + // True if positioned at element or terminator of the current list or any enclosing list function isInSomeParsingContext() { - for (var kind = 0; kind < 23; kind++) { + for (var kind = 0; kind < 23 /* Count */; kind++) { if (parsingContext & (1 << kind)) { - if (isListElement(kind, true) || isListTerminator(kind)) { + if (isListElement(kind, /*inErrorRecovery*/ true) || isListTerminator(kind)) { return true; } } } return false; } + // Parses a list of elements function parseList(kind, parseElement) { var saveParsingContext = parsingContext; parsingContext |= 1 << kind; var list = []; var listPos = getNodePos(); while (!isListTerminator(kind)) { - if (isListElement(kind, false)) { + if (isListElement(kind, /*inErrorRecovery*/ false)) { var element = parseListElement(kind, parseElement); list.push(element); continue; @@ -14523,85 +16544,145 @@ var ts; return parseElement(); } function currentNode(parsingContext) { + // If there is an outstanding parse error that we've encountered, but not attached to + // some node, then we cannot get a node from the old source tree. This is because we + // want to mark the next node we encounter as being unusable. + // + // Note: This may be too conservative. Perhaps we could reuse the node and set the bit + // on it (or its leftmost child) as having the error. For now though, being conservative + // is nice and likely won't ever affect perf. if (parseErrorBeforeNextFinishedNode) { return undefined; } if (!syntaxCursor) { + // if we don't have a cursor, we could never return a node from the old tree. return undefined; } var node = syntaxCursor.currentNode(scanner.getStartPos()); + // Can't reuse a missing node. if (ts.nodeIsMissing(node)) { return undefined; } + // Can't reuse a node that intersected the change range. if (node.intersectsChange) { return undefined; } + // Can't reuse a node that contains a parse error. This is necessary so that we + // produce the same set of errors again. if (ts.containsParseError(node)) { return undefined; } - var nodeContextFlags = node.flags & 12679168; + // We can only reuse a node if it was parsed under the same strict mode that we're + // currently in. i.e. if we originally parsed a node in non-strict mode, but then + // the user added 'using strict' at the top of the file, then we can't use that node + // again as the presence of strict mode may cause us to parse the tokens in the file + // differently. + // + // Note: we *can* reuse tokens when the strict mode changes. That's because tokens + // are unaffected by strict mode. It's just the parser will decide what to do with it + // differently depending on what mode it is in. + // + // This also applies to all our other context flags as well. + var nodeContextFlags = node.flags & 12679168 /* ContextFlags */; if (nodeContextFlags !== contextFlags) { return undefined; } + // Ok, we have a node that looks like it could be reused. Now verify that it is valid + // in the current list parsing context that we're currently at. if (!canReuseNode(node, parsingContext)) { return undefined; } if (node.jsDocCache) { + // jsDocCache may include tags from parent nodes, which might have been modified. node.jsDocCache = undefined; } return node; } function consumeNode(node) { + // Move the scanner so it is after the node we just consumed. scanner.setTextPos(node.end); nextToken(); return node; } function canReuseNode(node, parsingContext) { switch (parsingContext) { - case 5: + case 5 /* ClassMembers */: return isReusableClassMember(node); - case 2: + case 2 /* SwitchClauses */: return isReusableSwitchClause(node); - case 0: - case 1: - case 3: + case 0 /* SourceElements */: + case 1 /* BlockStatements */: + case 3 /* SwitchClauseStatements */: return isReusableStatement(node); - case 6: + case 6 /* EnumMembers */: return isReusableEnumMember(node); - case 4: + case 4 /* TypeMembers */: return isReusableTypeMember(node); - case 8: + case 8 /* VariableDeclarations */: return isReusableVariableDeclaration(node); - case 16: + case 16 /* Parameters */: return isReusableParameter(node); - case 17: + case 17 /* RestProperties */: return false; - case 21: - case 18: - case 20: - case 19: - case 11: - case 12: - case 7: - case 13: - case 14: + // Any other lists we do not care about reusing nodes in. But feel free to add if + // you can do so safely. Danger areas involve nodes that may involve speculative + // parsing. If speculative parsing is involved with the node, then the range the + // parser reached while looking ahead might be in the edited range (see the example + // in canReuseVariableDeclaratorNode for a good case of this). + case 21 /* HeritageClauses */: + // This would probably be safe to reuse. There is no speculative parsing with + // heritage clauses. + case 18 /* TypeParameters */: + // This would probably be safe to reuse. There is no speculative parsing with + // type parameters. Note that that's because type *parameters* only occur in + // unambiguous *type* contexts. While type *arguments* occur in very ambiguous + // *expression* contexts. + case 20 /* TupleElementTypes */: + // This would probably be safe to reuse. There is no speculative parsing with + // tuple types. + // Technically, type argument list types are probably safe to reuse. While + // speculative parsing is involved with them (since type argument lists are only + // produced from speculative parsing a < as a type argument list), we only have + // the types because speculative parsing succeeded. Thus, the lookahead never + // went past the end of the list and rewound. + case 19 /* TypeArguments */: + // Note: these are almost certainly not safe to ever reuse. Expressions commonly + // need a large amount of lookahead, and we should not reuse them as they may + // have actually intersected the edit. + case 11 /* ArgumentExpressions */: + // This is not safe to reuse for the same reason as the 'AssignmentExpression' + // cases. i.e. a property assignment may end with an expression, and thus might + // have lookahead far beyond it's old node. + case 12 /* ObjectLiteralMembers */: + // This is probably not safe to reuse. There can be speculative parsing with + // type names in a heritage clause. There can be generic names in the type + // name list, and there can be left hand side expressions (which can have type + // arguments.) + case 7 /* HeritageClauseElement */: + // Perhaps safe to reuse, but it's unlikely we'd see more than a dozen attributes + // on any given element. Same for children. + case 13 /* JsxAttributes */: + case 14 /* JsxChildren */: } return false; } function isReusableClassMember(node) { if (node) { switch (node.kind) { - case 155: - case 160: - case 156: - case 157: - case 152: - case 212: + case 155 /* Constructor */: + case 160 /* IndexSignature */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 152 /* PropertyDeclaration */: + case 212 /* SemicolonClassElement */: return true; - case 154: + case 154 /* MethodDeclaration */: + // Method declarations are not necessarily reusable. An object-literal + // may have a method calls "constructor(...)" and we must reparse that + // into an actual .ConstructorDeclaration. var methodDeclaration = node; - var nameIsConstructor = methodDeclaration.name.kind === 71 && - methodDeclaration.name.originalKeywordKind === 123; + var nameIsConstructor = methodDeclaration.name.kind === 71 /* Identifier */ && + methodDeclaration.name.originalKeywordKind === 123 /* ConstructorKeyword */; return !nameIsConstructor; } } @@ -14610,8 +16691,8 @@ var ts; function isReusableSwitchClause(node) { if (node) { switch (node.kind) { - case 266: - case 267: + case 266 /* CaseClause */: + case 267 /* DefaultClause */: return true; } } @@ -14620,70 +16701,86 @@ var ts; function isReusableStatement(node) { if (node) { switch (node.kind) { - case 234: - case 214: - case 213: - case 217: - case 216: - case 229: - case 225: - case 227: - case 224: - case 223: - case 221: - case 222: - case 220: - case 219: - case 226: - case 215: - case 230: - case 228: - case 218: - case 231: - case 244: - case 243: - case 250: - case 249: - case 239: - case 235: - case 236: - case 238: - case 237: + case 234 /* FunctionDeclaration */: + case 214 /* VariableStatement */: + case 213 /* Block */: + case 217 /* IfStatement */: + case 216 /* ExpressionStatement */: + case 229 /* ThrowStatement */: + case 225 /* ReturnStatement */: + case 227 /* SwitchStatement */: + case 224 /* BreakStatement */: + case 223 /* ContinueStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 220 /* ForStatement */: + case 219 /* WhileStatement */: + case 226 /* WithStatement */: + case 215 /* EmptyStatement */: + case 230 /* TryStatement */: + case 228 /* LabeledStatement */: + case 218 /* DoStatement */: + case 231 /* DebuggerStatement */: + case 244 /* ImportDeclaration */: + case 243 /* ImportEqualsDeclaration */: + case 250 /* ExportDeclaration */: + case 249 /* ExportAssignment */: + case 239 /* ModuleDeclaration */: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + case 238 /* EnumDeclaration */: + case 237 /* TypeAliasDeclaration */: return true; } } return false; } function isReusableEnumMember(node) { - return node.kind === 273; + return node.kind === 273 /* EnumMember */; } function isReusableTypeMember(node) { if (node) { switch (node.kind) { - case 159: - case 153: - case 160: - case 151: - case 158: + case 159 /* ConstructSignature */: + case 153 /* MethodSignature */: + case 160 /* IndexSignature */: + case 151 /* PropertySignature */: + case 158 /* CallSignature */: return true; } } return false; } function isReusableVariableDeclaration(node) { - if (node.kind !== 232) { + if (node.kind !== 232 /* VariableDeclaration */) { return false; } + // Very subtle incremental parsing bug. Consider the following code: + // + // let v = new List < A, B + // + // This is actually legal code. It's a list of variable declarators "v = new List() + // + // then we have a problem. "v = new List= 0) { + // Always preserve a trailing comma by marking it on the NodeArray result.hasTrailingComma = true; } return result; @@ -14775,8 +16891,9 @@ var ts; function parseEntityName(allowReservedWords, diagnosticMessage) { var entity = allowReservedWords ? parseIdentifierName(diagnosticMessage) : parseIdentifier(diagnosticMessage); var dotPos = scanner.getStartPos(); - while (parseOptional(23)) { - if (token() === 27) { + while (parseOptional(23 /* DotToken */)) { + if (token() === 27 /* LessThanToken */) { + // the entity is part of a JSDoc-style generic, so record the trailing dot for later error reporting entity.jsdocDotPos = dotPos; break; } @@ -14786,42 +16903,64 @@ var ts; return entity; } function createQualifiedName(entity, name) { - var node = createNode(146, entity.pos); + var node = createNode(146 /* QualifiedName */, entity.pos); node.left = entity; node.right = name; return finishNode(node); } function parseRightSideOfDot(allowIdentifierNames) { + // Technically a keyword is valid here as all identifiers and keywords are identifier names. + // However, often we'll encounter this in error situations when the identifier or keyword + // is actually starting another valid construct. + // + // So, we check for the following specific case: + // + // name. + // identifierOrKeyword identifierNameOrKeyword + // + // Note: the newlines are important here. For example, if that above code + // were rewritten into: + // + // name.identifierOrKeyword + // identifierNameOrKeyword + // + // Then we would consider it valid. That's because ASI would take effect and + // the code would be implicitly: "name.identifierOrKeyword; identifierNameOrKeyword". + // In the first case though, ASI will not take effect because there is not a + // line terminator after the identifier or keyword. if (scanner.hasPrecedingLineBreak() && ts.tokenIsIdentifierOrKeyword(token())) { var matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine); if (matchesPattern) { - return createMissingNode(71, true, ts.Diagnostics.Identifier_expected); + // Report that we need an identifier. However, report it right after the dot, + // and not on the next token. This is because the next token might actually + // be an identifier and the error would be quite confusing. + return createMissingNode(71 /* Identifier */, /*reportAtCurrentPosition*/ true, ts.Diagnostics.Identifier_expected); } } return allowIdentifierNames ? parseIdentifierName() : parseIdentifier(); } function parseTemplateExpression() { - var template = createNode(202); + var template = createNode(202 /* TemplateExpression */); template.head = parseTemplateHead(); - ts.Debug.assert(template.head.kind === 14, "Template head has wrong token kind"); + ts.Debug.assert(template.head.kind === 14 /* TemplateHead */, "Template head has wrong token kind"); var list = []; var listPos = getNodePos(); do { list.push(parseTemplateSpan()); - } while (ts.last(list).literal.kind === 15); + } while (ts.last(list).literal.kind === 15 /* TemplateMiddle */); template.templateSpans = createNodeArray(list, listPos); return finishNode(template); } function parseTemplateSpan() { - var span = createNode(211); + var span = createNode(211 /* TemplateSpan */); span.expression = allowInAnd(parseExpression); var literal; - if (token() === 18) { + if (token() === 18 /* CloseBraceToken */) { reScanTemplateToken(); literal = parseTemplateMiddleOrTemplateTail(); } else { - literal = parseExpectedToken(16, ts.Diagnostics._0_expected, ts.tokenToString(18)); + literal = parseExpectedToken(16 /* TemplateTail */, ts.Diagnostics._0_expected, ts.tokenToString(18 /* CloseBraceToken */)); } span.literal = literal; return finishNode(span); @@ -14831,12 +16970,12 @@ var ts; } function parseTemplateHead() { var fragment = parseLiteralLikeNode(token()); - ts.Debug.assert(fragment.kind === 14, "Template head has wrong token kind"); + ts.Debug.assert(fragment.kind === 14 /* TemplateHead */, "Template head has wrong token kind"); return fragment; } function parseTemplateMiddleOrTemplateTail() { var fragment = parseLiteralLikeNode(token()); - ts.Debug.assert(fragment.kind === 15 || fragment.kind === 16, "Template fragment has wrong token kind"); + ts.Debug.assert(fragment.kind === 15 /* TemplateMiddle */ || fragment.kind === 16 /* TemplateTail */, "Template fragment has wrong token kind"); return fragment; } function parseLiteralLikeNode(kind) { @@ -14849,31 +16988,40 @@ var ts; if (scanner.isUnterminated()) { node.isUnterminated = true; } - if (node.kind === 8) { - node.numericLiteralFlags = scanner.getTokenFlags() & 1008; + // Octal literals are not allowed in strict mode or ES5 + // Note that theoretically the following condition would hold true literals like 009, + // which is not octal.But because of how the scanner separates the tokens, we would + // never get a token like this. Instead, we would get 00 and 9 as two separate tokens. + // We also do not need to check for negatives because any prefix operator would be part of a + // parent unary expression. + if (node.kind === 8 /* NumericLiteral */) { + node.numericLiteralFlags = scanner.getTokenFlags() & 1008 /* NumericLiteralFlags */; } nextToken(); finishNode(node); return node; } + // TYPES function parseTypeReference() { - var node = createNode(162); - node.typeName = parseEntityName(true, ts.Diagnostics.Type_expected); - if (!scanner.hasPrecedingLineBreak() && token() === 27) { - node.typeArguments = parseBracketedList(19, parseType, 27, 29); + var node = createNode(162 /* TypeReference */); + node.typeName = parseEntityName(/*allowReservedWords*/ true, ts.Diagnostics.Type_expected); + if (!scanner.hasPrecedingLineBreak() && token() === 27 /* LessThanToken */) { + node.typeArguments = parseBracketedList(19 /* TypeArguments */, parseType, 27 /* LessThanToken */, 29 /* GreaterThanToken */); } return finishNode(node); } + // If true, we should abort parsing an error function. function typeHasArrowFunctionBlockingParseError(node) { switch (node.kind) { - case 162: + case 162 /* TypeReference */: return ts.nodeIsMissing(node.typeName); - case 163: - case 164: { + case 163 /* FunctionType */: + case 164 /* ConstructorType */: { var _a = node, parameters = _a.parameters, type = _a.type; + // parameters.pos === parameters.end only if we used parseMissingList, else should contain at least `()` return parameters.pos === parameters.end || typeHasArrowFunctionBlockingParseError(type); } - case 173: + case 173 /* ParenthesizedType */: return typeHasArrowFunctionBlockingParseError(node.type); default: return false; @@ -14881,20 +17029,20 @@ var ts; } function parseThisTypePredicate(lhs) { nextToken(); - var node = createNode(161, lhs.pos); + var node = createNode(161 /* TypePredicate */, lhs.pos); node.parameterName = lhs; node.type = parseType(); return finishNode(node); } function parseThisTypeNode() { - var node = createNode(174); + var node = createNode(174 /* ThisType */); nextToken(); return finishNode(node); } function parseJSDocAllType(postFixEquals) { - var result = createNode(279); + var result = createNode(279 /* JSDocAllType */); if (postFixEquals) { - return createJSDocPostfixType(283, result); + return createJSDocPostfixType(283 /* JSDocOptionalType */, result); } else { nextToken(); @@ -14902,127 +17050,162 @@ var ts; return finishNode(result); } function parseJSDocNonNullableType() { - var result = createNode(282); + var result = createNode(282 /* JSDocNonNullableType */); nextToken(); result.type = parseNonArrayType(); return finishNode(result); } function parseJSDocUnknownOrNullableType() { var pos = scanner.getStartPos(); + // skip the ? nextToken(); - if (token() === 26 || - token() === 18 || - token() === 20 || - token() === 29 || - token() === 58 || - token() === 49) { - var result = createNode(280, pos); + // Need to lookahead to decide if this is a nullable or unknown type. + // Here are cases where we'll pick the unknown type: + // + // Foo(?, + // { a: ? } + // Foo(?) + // Foo + // Foo(?= + // (?| + if (token() === 26 /* CommaToken */ || + token() === 18 /* CloseBraceToken */ || + token() === 20 /* CloseParenToken */ || + token() === 29 /* GreaterThanToken */ || + token() === 58 /* EqualsToken */ || + token() === 49 /* BarToken */) { + var result = createNode(280 /* JSDocUnknownType */, pos); return finishNode(result); } else { - var result = createNode(281, pos); + var result = createNode(281 /* JSDocNullableType */, pos); result.type = parseType(); return finishNode(result); } } function parseJSDocFunctionType() { if (lookAhead(nextTokenIsOpenParen)) { - var result = createNodeWithJSDoc(284); + var result = createNodeWithJSDoc(284 /* JSDocFunctionType */); nextToken(); - fillSignature(56, 4 | 32, result); + fillSignature(56 /* ColonToken */, 4 /* Type */ | 32 /* JSDoc */, result); return finishNode(result); } - var node = createNode(162); + var node = createNode(162 /* TypeReference */); node.typeName = parseIdentifierName(); return finishNode(node); } function parseJSDocParameter() { - var parameter = createNode(149); - if (token() === 99 || token() === 94) { + var parameter = createNode(149 /* Parameter */); + if (token() === 99 /* ThisKeyword */ || token() === 94 /* NewKeyword */) { parameter.name = parseIdentifierName(); - parseExpected(56); + parseExpected(56 /* ColonToken */); } parameter.type = parseJSDocType(); return finishNode(parameter); } function parseJSDocType() { - var dotdotdot = parseOptionalToken(24); + var dotdotdot = parseOptionalToken(24 /* DotDotDotToken */); var type = parseType(); if (dotdotdot) { - var variadic = createNode(285, dotdotdot.pos); + var variadic = createNode(285 /* JSDocVariadicType */, dotdotdot.pos); variadic.type = type; type = finishNode(variadic); } - if (token() === 58) { - return createJSDocPostfixType(283, type); + if (token() === 58 /* EqualsToken */) { + return createJSDocPostfixType(283 /* JSDocOptionalType */, type); } return type; } function parseTypeQuery() { - var node = createNode(165); - parseExpected(103); - node.exprName = parseEntityName(true); + var node = createNode(165 /* TypeQuery */); + parseExpected(103 /* TypeOfKeyword */); + node.exprName = parseEntityName(/*allowReservedWords*/ true); return finishNode(node); } function parseTypeParameter() { - var node = createNode(148); + var node = createNode(148 /* TypeParameter */); node.name = parseIdentifier(); - if (parseOptional(85)) { + if (parseOptional(85 /* ExtendsKeyword */)) { + // It's not uncommon for people to write improper constraints to a generic. If the + // user writes a constraint that is an expression and not an actual type, then parse + // it out as an expression (so we can recover well), but report that a type is needed + // instead. if (isStartOfType() || !isStartOfExpression()) { node.constraint = parseType(); } else { + // It was not a type, and it looked like an expression. Parse out an expression + // here so we recover well. Note: it is important that we call parseUnaryExpression + // and not parseExpression here. If the user has: + // + // + // + // We do *not* want to consume the `>` as we're consuming the expression for "". node.expression = parseUnaryExpressionOrHigher(); } } - if (parseOptional(58)) { + if (parseOptional(58 /* EqualsToken */)) { node.default = parseType(); } return finishNode(node); } function parseTypeParameters() { - if (token() === 27) { - return parseBracketedList(18, parseTypeParameter, 27, 29); + if (token() === 27 /* LessThanToken */) { + return parseBracketedList(18 /* TypeParameters */, parseTypeParameter, 27 /* LessThanToken */, 29 /* GreaterThanToken */); } } function parseParameterType() { - if (parseOptional(56)) { + if (parseOptional(56 /* ColonToken */)) { return parseType(); } return undefined; } function isStartOfParameter() { - return token() === 24 || + return token() === 24 /* DotDotDotToken */ || isIdentifierOrPattern() || ts.isModifierKind(token()) || - token() === 57 || - isStartOfType(true); + token() === 57 /* AtToken */ || + isStartOfType(/*inStartOfParameter*/ true); } function parseParameter() { - var node = createNodeWithJSDoc(149); - if (token() === 99) { - node.name = createIdentifier(true); + var node = createNodeWithJSDoc(149 /* Parameter */); + if (token() === 99 /* ThisKeyword */) { + node.name = createIdentifier(/*isIdentifier*/ true); node.type = parseParameterType(); return finishNode(node); } node.decorators = parseDecorators(); node.modifiers = parseModifiers(); - node.dotDotDotToken = parseOptionalToken(24); + node.dotDotDotToken = parseOptionalToken(24 /* DotDotDotToken */); + // FormalParameter [Yield,Await]: + // BindingElement[?Yield,?Await] node.name = parseIdentifierOrPattern(); if (ts.getFullWidth(node.name) === 0 && !ts.hasModifiers(node) && ts.isModifierKind(token())) { + // in cases like + // 'use strict' + // function foo(static) + // isParameter('static') === true, because of isModifier('static') + // however 'static' is not a legal identifier in a strict mode. + // so result of this function will be ParameterDeclaration (flags = 0, name = missing, type = undefined, initializer = undefined) + // and current token will not change => parsing of the enclosing parameter list will last till the end of time (or OOM) + // to avoid this we'll advance cursor to the next token. nextToken(); } - node.questionToken = parseOptionalToken(55); + node.questionToken = parseOptionalToken(55 /* QuestionToken */); node.type = parseParameterType(); node.initializer = parseInitializer(); return finishNode(node); } + /** + * Note: If returnToken is EqualsGreaterThanToken, `signature.type` will always be defined. + * @returns If return type parsing succeeds + */ function fillSignature(returnToken, flags, signature) { - if (!(flags & 32)) { + if (!(flags & 32 /* JSDoc */)) { signature.typeParameters = parseTypeParameters(); } var parametersParsedSuccessfully = parseParameterList(signature, flags); - if (shouldParseReturnType(returnToken, !!(flags & 4))) { + if (shouldParseReturnType(returnToken, !!(flags & 4 /* Type */))) { signature.type = parseTypeOrTypePredicate(); if (typeHasArrowFunctionBlockingParseError(signature.type)) return false; @@ -15030,55 +17213,89 @@ var ts; return parametersParsedSuccessfully; } function shouldParseReturnType(returnToken, isType) { - if (returnToken === 36) { + if (returnToken === 36 /* EqualsGreaterThanToken */) { parseExpected(returnToken); return true; } - else if (parseOptional(56)) { + else if (parseOptional(56 /* ColonToken */)) { return true; } - else if (isType && token() === 36) { - parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(56)); + else if (isType && token() === 36 /* EqualsGreaterThanToken */) { + // This is easy to get backward, especially in type contexts, so parse the type anyway + parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(56 /* ColonToken */)); nextToken(); return true; } return false; } + // Returns true on success. function parseParameterList(signature, flags) { - if (!parseExpected(19)) { + // FormalParameters [Yield,Await]: (modified) + // [empty] + // FormalParameterList[?Yield,Await] + // + // FormalParameter[Yield,Await]: (modified) + // BindingElement[?Yield,Await] + // + // BindingElement [Yield,Await]: (modified) + // SingleNameBinding[?Yield,?Await] + // BindingPattern[?Yield,?Await]Initializer [In, ?Yield,?Await] opt + // + // SingleNameBinding [Yield,Await]: + // BindingIdentifier[?Yield,?Await]Initializer [In, ?Yield,?Await] opt + if (!parseExpected(19 /* OpenParenToken */)) { signature.parameters = createMissingList(); return false; } var savedYieldContext = inYieldContext(); var savedAwaitContext = inAwaitContext(); - setYieldContext(!!(flags & 1)); - setAwaitContext(!!(flags & 2)); - signature.parameters = parseDelimitedList(16, flags & 32 ? parseJSDocParameter : parseParameter); + setYieldContext(!!(flags & 1 /* Yield */)); + setAwaitContext(!!(flags & 2 /* Await */)); + signature.parameters = parseDelimitedList(16 /* Parameters */, flags & 32 /* JSDoc */ ? parseJSDocParameter : parseParameter); setYieldContext(savedYieldContext); setAwaitContext(savedAwaitContext); - return parseExpected(20); + return parseExpected(20 /* CloseParenToken */); } function parseTypeMemberSemicolon() { - if (parseOptional(26)) { + // We allow type members to be separated by commas or (possibly ASI) semicolons. + // First check if it was a comma. If so, we're done with the member. + if (parseOptional(26 /* CommaToken */)) { return; } + // Didn't have a comma. We must have a (possible ASI) semicolon. parseSemicolon(); } function parseSignatureMember(kind) { var node = createNodeWithJSDoc(kind); - if (kind === 159) { - parseExpected(94); + if (kind === 159 /* ConstructSignature */) { + parseExpected(94 /* NewKeyword */); } - fillSignature(56, 4, node); + fillSignature(56 /* ColonToken */, 4 /* Type */, node); parseTypeMemberSemicolon(); return finishNode(node); } function isIndexSignature() { - return token() === 21 && lookAhead(isUnambiguouslyIndexSignature); + return token() === 21 /* OpenBracketToken */ && lookAhead(isUnambiguouslyIndexSignature); } function isUnambiguouslyIndexSignature() { + // The only allowed sequence is: + // + // [id: + // + // However, for error recovery, we also check the following cases: + // + // [... + // [id, + // [id?, + // [id?: + // [id?] + // [public id + // [private id + // [protected id + // [] + // nextToken(); - if (token() === 24 || token() === 22) { + if (token() === 24 /* DotDotDotToken */ || token() === 22 /* CloseBracketToken */) { return true; } if (ts.isModifierKind(token())) { @@ -15091,35 +17308,48 @@ var ts; return false; } else { + // Skip the identifier nextToken(); } - if (token() === 56 || token() === 26) { + // A colon signifies a well formed indexer + // A comma should be a badly formed indexer because comma expressions are not allowed + // in computed properties. + if (token() === 56 /* ColonToken */ || token() === 26 /* CommaToken */) { return true; } - if (token() !== 55) { + // Question mark could be an indexer with an optional property, + // or it could be a conditional expression in a computed property. + if (token() !== 55 /* QuestionToken */) { return false; } + // If any of the following tokens are after the question mark, it cannot + // be a conditional expression, so treat it as an indexer. nextToken(); - return token() === 56 || token() === 26 || token() === 22; + return token() === 56 /* ColonToken */ || token() === 26 /* CommaToken */ || token() === 22 /* CloseBracketToken */; } function parseIndexSignatureDeclaration(node) { - node.kind = 160; - node.parameters = parseBracketedList(16, parseParameter, 21, 22); + node.kind = 160 /* IndexSignature */; + node.parameters = parseBracketedList(16 /* Parameters */, parseParameter, 21 /* OpenBracketToken */, 22 /* CloseBracketToken */); node.type = parseTypeAnnotation(); parseTypeMemberSemicolon(); return finishNode(node); } function parsePropertyOrMethodSignature(node) { node.name = parsePropertyName(); - node.questionToken = parseOptionalToken(55); - if (token() === 19 || token() === 27) { - node.kind = 153; - fillSignature(56, 4, node); + node.questionToken = parseOptionalToken(55 /* QuestionToken */); + if (token() === 19 /* OpenParenToken */ || token() === 27 /* LessThanToken */) { + node.kind = 153 /* MethodSignature */; + // Method signatures don't exist in expression contexts. So they have neither + // [Yield] nor [Await] + fillSignature(56 /* ColonToken */, 4 /* Type */, node); } else { - node.kind = 151; + node.kind = 151 /* PropertySignature */; node.type = parseTypeAnnotation(); - if (token() === 58) { + if (token() === 58 /* EqualsToken */) { + // Although type literal properties cannot not have initializers, we attempt + // to parse an initializer so we can report in the checker that an interface + // property or type literal property cannot have an initializer. node.initializer = parseInitializer(); } } @@ -15127,39 +17357,45 @@ var ts; return finishNode(node); } function isTypeMemberStart() { - if (token() === 19 || token() === 27) { + // Return true if we have the start of a signature member + if (token() === 19 /* OpenParenToken */ || token() === 27 /* LessThanToken */) { return true; } var idToken = false; + // Eat up all modifiers, but hold on to the last one in case it is actually an identifier while (ts.isModifierKind(token())) { idToken = true; nextToken(); } - if (token() === 21) { + // Index signatures and computed property names are type members + if (token() === 21 /* OpenBracketToken */) { return true; } + // Try to get the first property-like token following all modifiers if (isLiteralPropertyName()) { idToken = true; nextToken(); } + // If we were able to get any potential identifier, check that it is + // the start of a member declaration if (idToken) { - return token() === 19 || - token() === 27 || - token() === 55 || - token() === 56 || - token() === 26 || + return token() === 19 /* OpenParenToken */ || + token() === 27 /* LessThanToken */ || + token() === 55 /* QuestionToken */ || + token() === 56 /* ColonToken */ || + token() === 26 /* CommaToken */ || canParseSemicolon(); } return false; } function parseTypeMember() { - if (token() === 19 || token() === 27) { - return parseSignatureMember(158); + if (token() === 19 /* OpenParenToken */ || token() === 27 /* LessThanToken */) { + return parseSignatureMember(158 /* CallSignature */); } - if (token() === 94 && lookAhead(nextTokenIsOpenParenOrLessThan)) { - return parseSignatureMember(159); + if (token() === 94 /* NewKeyword */ && lookAhead(nextTokenIsOpenParenOrLessThan)) { + return parseSignatureMember(159 /* ConstructSignature */); } - var node = createNodeWithJSDoc(0); + var node = createNodeWithJSDoc(0 /* Unknown */); node.modifiers = parseModifiers(); if (isIndexSignature()) { return parseIndexSignatureDeclaration(node); @@ -15168,30 +17404,30 @@ var ts; } function nextTokenIsOpenParenOrLessThan() { nextToken(); - return token() === 19 || token() === 27; + return token() === 19 /* OpenParenToken */ || token() === 27 /* LessThanToken */; } function nextTokenIsDot() { - return nextToken() === 23; + return nextToken() === 23 /* DotToken */; } function nextTokenIsOpenParenOrLessThanOrDot() { switch (nextToken()) { - case 19: - case 27: - case 23: + case 19 /* OpenParenToken */: + case 27 /* LessThanToken */: + case 23 /* DotToken */: return true; } return false; } function parseTypeLiteral() { - var node = createNode(166); + var node = createNode(166 /* TypeLiteral */); node.members = parseObjectTypeMembers(); return finishNode(node); } function parseObjectTypeMembers() { var members; - if (parseExpected(17)) { - members = parseList(4, parseTypeMember); - parseExpected(18); + if (parseExpected(17 /* OpenBraceToken */)) { + members = parseList(4 /* TypeMembers */, parseTypeMember); + parseExpected(18 /* CloseBraceToken */); } else { members = createMissingList(); @@ -15200,76 +17436,76 @@ var ts; } function isStartOfMappedType() { nextToken(); - if (token() === 37 || token() === 38) { - return nextToken() === 132; + if (token() === 37 /* PlusToken */ || token() === 38 /* MinusToken */) { + return nextToken() === 132 /* ReadonlyKeyword */; } - if (token() === 132) { + if (token() === 132 /* ReadonlyKeyword */) { nextToken(); } - return token() === 21 && nextTokenIsIdentifier() && nextToken() === 92; + return token() === 21 /* OpenBracketToken */ && nextTokenIsIdentifier() && nextToken() === 92 /* InKeyword */; } function parseMappedTypeParameter() { - var node = createNode(148); + var node = createNode(148 /* TypeParameter */); node.name = parseIdentifier(); - parseExpected(92); + parseExpected(92 /* InKeyword */); node.constraint = parseType(); return finishNode(node); } function parseMappedType() { - var node = createNode(177); - parseExpected(17); - if (token() === 132 || token() === 37 || token() === 38) { + var node = createNode(177 /* MappedType */); + parseExpected(17 /* OpenBraceToken */); + if (token() === 132 /* ReadonlyKeyword */ || token() === 37 /* PlusToken */ || token() === 38 /* MinusToken */) { node.readonlyToken = parseTokenNode(); - if (node.readonlyToken.kind !== 132) { - parseExpectedToken(132); + if (node.readonlyToken.kind !== 132 /* ReadonlyKeyword */) { + parseExpectedToken(132 /* ReadonlyKeyword */); } } - parseExpected(21); + parseExpected(21 /* OpenBracketToken */); node.typeParameter = parseMappedTypeParameter(); - parseExpected(22); - if (token() === 55 || token() === 37 || token() === 38) { + parseExpected(22 /* CloseBracketToken */); + if (token() === 55 /* QuestionToken */ || token() === 37 /* PlusToken */ || token() === 38 /* MinusToken */) { node.questionToken = parseTokenNode(); - if (node.questionToken.kind !== 55) { - parseExpectedToken(55); + if (node.questionToken.kind !== 55 /* QuestionToken */) { + parseExpectedToken(55 /* QuestionToken */); } } node.type = parseTypeAnnotation(); parseSemicolon(); - parseExpected(18); + parseExpected(18 /* CloseBraceToken */); return finishNode(node); } function parseTupleType() { - var node = createNode(168); - node.elementTypes = parseBracketedList(20, parseType, 21, 22); + var node = createNode(168 /* TupleType */); + node.elementTypes = parseBracketedList(20 /* TupleElementTypes */, parseType, 21 /* OpenBracketToken */, 22 /* CloseBracketToken */); return finishNode(node); } function parseParenthesizedType() { - var node = createNode(173); - parseExpected(19); + var node = createNode(173 /* ParenthesizedType */); + parseExpected(19 /* OpenParenToken */); node.type = parseType(); - parseExpected(20); + parseExpected(20 /* CloseParenToken */); return finishNode(node); } function parseFunctionOrConstructorType() { var pos = getNodePos(); - var kind = parseOptional(94) ? 164 : 163; + var kind = parseOptional(94 /* NewKeyword */) ? 164 /* ConstructorType */ : 163 /* FunctionType */; var node = createNodeWithJSDoc(kind, pos); - fillSignature(36, 4, node); + fillSignature(36 /* EqualsGreaterThanToken */, 4 /* Type */, node); return finishNode(node); } function parseKeywordAndNoDot() { var node = parseTokenNode(); - return token() === 23 ? undefined : node; + return token() === 23 /* DotToken */ ? undefined : node; } function parseLiteralTypeNode(negative) { - var node = createNode(178); + var node = createNode(178 /* LiteralType */); var unaryMinusExpression; if (negative) { - unaryMinusExpression = createNode(198); - unaryMinusExpression.operator = 38; + unaryMinusExpression = createNode(198 /* PrefixUnaryExpression */); + unaryMinusExpression.operator = 38 /* MinusToken */; nextToken(); } - var expression = token() === 101 || token() === 86 + var expression = token() === 101 /* TrueKeyword */ || token() === 86 /* FalseKeyword */ ? parseTokenNode() : parseLiteralLikeNode(token()); if (negative) { @@ -15282,78 +17518,79 @@ var ts; } function isStartOfTypeOfImportType() { nextToken(); - return token() === 91; + return token() === 91 /* ImportKeyword */; } function parseImportType() { - sourceFile.flags |= 524288; - var node = createNode(179); - if (parseOptional(103)) { + sourceFile.flags |= 524288 /* PossiblyContainsDynamicImport */; + var node = createNode(179 /* ImportType */); + if (parseOptional(103 /* TypeOfKeyword */)) { node.isTypeOf = true; } - parseExpected(91); - parseExpected(19); + parseExpected(91 /* ImportKeyword */); + parseExpected(19 /* OpenParenToken */); node.argument = parseType(); - parseExpected(20); - if (parseOptional(23)) { - node.qualifier = parseEntityName(true, ts.Diagnostics.Type_expected); + parseExpected(20 /* CloseParenToken */); + if (parseOptional(23 /* DotToken */)) { + node.qualifier = parseEntityName(/*allowReservedWords*/ true, ts.Diagnostics.Type_expected); } node.typeArguments = tryParseTypeArguments(); return finishNode(node); } function nextTokenIsNumericLiteral() { - return nextToken() === 8; + return nextToken() === 8 /* NumericLiteral */; } function parseNonArrayType() { switch (token()) { - case 119: - case 142: - case 137: - case 134: - case 138: - case 122: - case 140: - case 131: - case 135: + case 119 /* AnyKeyword */: + case 142 /* UnknownKeyword */: + case 137 /* StringKeyword */: + case 134 /* NumberKeyword */: + case 138 /* SymbolKeyword */: + case 122 /* BooleanKeyword */: + case 140 /* UndefinedKeyword */: + case 131 /* NeverKeyword */: + case 135 /* ObjectKeyword */: + // If these are followed by a dot, then parse these out as a dotted type reference instead. return tryParse(parseKeywordAndNoDot) || parseTypeReference(); - case 39: - return parseJSDocAllType(false); - case 61: - return parseJSDocAllType(true); - case 55: + case 39 /* AsteriskToken */: + return parseJSDocAllType(/*postfixEquals*/ false); + case 61 /* AsteriskEqualsToken */: + return parseJSDocAllType(/*postfixEquals*/ true); + case 55 /* QuestionToken */: return parseJSDocUnknownOrNullableType(); - case 89: + case 89 /* FunctionKeyword */: return parseJSDocFunctionType(); - case 51: + case 51 /* ExclamationToken */: return parseJSDocNonNullableType(); - case 13: - case 9: - case 8: - case 101: - case 86: + case 13 /* NoSubstitutionTemplateLiteral */: + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: return parseLiteralTypeNode(); - case 38: - return lookAhead(nextTokenIsNumericLiteral) ? parseLiteralTypeNode(true) : parseTypeReference(); - case 105: - case 95: + case 38 /* MinusToken */: + return lookAhead(nextTokenIsNumericLiteral) ? parseLiteralTypeNode(/*negative*/ true) : parseTypeReference(); + case 105 /* VoidKeyword */: + case 95 /* NullKeyword */: return parseTokenNode(); - case 99: { + case 99 /* ThisKeyword */: { var thisKeyword = parseThisTypeNode(); - if (token() === 127 && !scanner.hasPrecedingLineBreak()) { + if (token() === 127 /* IsKeyword */ && !scanner.hasPrecedingLineBreak()) { return parseThisTypePredicate(thisKeyword); } else { return thisKeyword; } } - case 103: + case 103 /* TypeOfKeyword */: return lookAhead(isStartOfTypeOfImportType) ? parseImportType() : parseTypeQuery(); - case 17: + case 17 /* OpenBraceToken */: return lookAhead(isStartOfMappedType) ? parseMappedType() : parseTypeLiteral(); - case 21: + case 21 /* OpenBracketToken */: return parseTupleType(); - case 19: + case 19 /* OpenParenToken */: return parseParenthesizedType(); - case 91: + case 91 /* ImportKeyword */: return parseImportType(); default: return parseTypeReference(); @@ -15361,40 +17598,42 @@ var ts; } function isStartOfType(inStartOfParameter) { switch (token()) { - case 119: - case 142: - case 137: - case 134: - case 122: - case 138: - case 141: - case 105: - case 140: - case 95: - case 99: - case 103: - case 131: - case 17: - case 21: - case 27: - case 49: - case 48: - case 94: - case 9: - case 8: - case 101: - case 86: - case 135: - case 39: - case 55: - case 51: - case 24: - case 126: - case 91: + case 119 /* AnyKeyword */: + case 142 /* UnknownKeyword */: + case 137 /* StringKeyword */: + case 134 /* NumberKeyword */: + case 122 /* BooleanKeyword */: + case 138 /* SymbolKeyword */: + case 141 /* UniqueKeyword */: + case 105 /* VoidKeyword */: + case 140 /* UndefinedKeyword */: + case 95 /* NullKeyword */: + case 99 /* ThisKeyword */: + case 103 /* TypeOfKeyword */: + case 131 /* NeverKeyword */: + case 17 /* OpenBraceToken */: + case 21 /* OpenBracketToken */: + case 27 /* LessThanToken */: + case 49 /* BarToken */: + case 48 /* AmpersandToken */: + case 94 /* NewKeyword */: + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: + case 135 /* ObjectKeyword */: + case 39 /* AsteriskToken */: + case 55 /* QuestionToken */: + case 51 /* ExclamationToken */: + case 24 /* DotDotDotToken */: + case 126 /* InferKeyword */: + case 91 /* ImportKeyword */: return true; - case 38: + case 38 /* MinusToken */: return !inStartOfParameter && lookAhead(nextTokenIsNumericLiteral); - case 19: + case 19 /* OpenParenToken */: + // Only consider '(' the start of a type if followed by ')', '...', an identifier, a modifier, + // or something that starts a type. We don't want to consider things like '(1)' a type. return !inStartOfParameter && lookAhead(isStartOfParenthesizedOrFunctionType); default: return isIdentifier(); @@ -15402,34 +17641,35 @@ var ts; } function isStartOfParenthesizedOrFunctionType() { nextToken(); - return token() === 20 || isStartOfParameter() || isStartOfType(); + return token() === 20 /* CloseParenToken */ || isStartOfParameter() || isStartOfType(); } function parsePostfixTypeOrHigher() { var type = parseNonArrayType(); while (!scanner.hasPrecedingLineBreak()) { switch (token()) { - case 51: - type = createJSDocPostfixType(282, type); + case 51 /* ExclamationToken */: + type = createJSDocPostfixType(282 /* JSDocNonNullableType */, type); break; - case 55: - if (!(contextFlags & 2097152) && lookAhead(nextTokenIsStartOfType)) { + case 55 /* QuestionToken */: + // If not in JSDoc and next token is start of a type we have a conditional type + if (!(contextFlags & 2097152 /* JSDoc */) && lookAhead(nextTokenIsStartOfType)) { return type; } - type = createJSDocPostfixType(281, type); + type = createJSDocPostfixType(281 /* JSDocNullableType */, type); break; - case 21: - parseExpected(21); + case 21 /* OpenBracketToken */: + parseExpected(21 /* OpenBracketToken */); if (isStartOfType()) { - var node = createNode(176, type.pos); + var node = createNode(176 /* IndexedAccessType */, type.pos); node.objectType = type; node.indexType = parseType(); - parseExpected(22); + parseExpected(22 /* CloseBracketToken */); type = finishNode(node); } else { - var node = createNode(167, type.pos); + var node = createNode(167 /* ArrayType */, type.pos); node.elementType = type; - parseExpected(22); + parseExpected(22 /* CloseBracketToken */); type = finishNode(node); } break; @@ -15446,16 +17686,16 @@ var ts; return finishNode(postfix); } function parseTypeOperator(operator) { - var node = createNode(175); + var node = createNode(175 /* TypeOperator */); parseExpected(operator); node.operator = operator; node.type = parseTypeOperatorOrHigher(); return finishNode(node); } function parseInferType() { - var node = createNode(172); - parseExpected(126); - var typeParameter = createNode(148); + var node = createNode(172 /* InferType */); + parseExpected(126 /* InferKeyword */); + var typeParameter = createNode(148 /* TypeParameter */); typeParameter.name = parseIdentifier(); node.typeParameter = finishNode(typeParameter); return finishNode(node); @@ -15463,10 +17703,10 @@ var ts; function parseTypeOperatorOrHigher() { var operator = token(); switch (operator) { - case 128: - case 141: + case 128 /* KeyOfKeyword */: + case 141 /* UniqueKeyword */: return parseTypeOperator(operator); - case 126: + case 126 /* InferKeyword */: return parseInferType(); } return parsePostfixTypeOrHigher(); @@ -15486,26 +17726,28 @@ var ts; return type; } function parseIntersectionTypeOrHigher() { - return parseUnionOrIntersectionType(170, parseTypeOperatorOrHigher, 48); + return parseUnionOrIntersectionType(170 /* IntersectionType */, parseTypeOperatorOrHigher, 48 /* AmpersandToken */); } function parseUnionTypeOrHigher() { - return parseUnionOrIntersectionType(169, parseIntersectionTypeOrHigher, 49); + return parseUnionOrIntersectionType(169 /* UnionType */, parseIntersectionTypeOrHigher, 49 /* BarToken */); } function isStartOfFunctionType() { - if (token() === 27) { + if (token() === 27 /* LessThanToken */) { return true; } - return token() === 19 && lookAhead(isUnambiguouslyStartOfFunctionType); + return token() === 19 /* OpenParenToken */ && lookAhead(isUnambiguouslyStartOfFunctionType); } function skipParameterStart() { if (ts.isModifierKind(token())) { + // Skip modifiers parseModifiers(); } - if (isIdentifier() || token() === 99) { + if (isIdentifier() || token() === 99 /* ThisKeyword */) { nextToken(); return true; } - if (token() === 21 || token() === 17) { + if (token() === 21 /* OpenBracketToken */ || token() === 17 /* OpenBraceToken */) { + // Return true if we can parse an array or object binding pattern with no errors var previousErrorCount = parseDiagnostics.length; parseIdentifierOrPattern(); return previousErrorCount === parseDiagnostics.length; @@ -15514,17 +17756,26 @@ var ts; } function isUnambiguouslyStartOfFunctionType() { nextToken(); - if (token() === 20 || token() === 24) { + if (token() === 20 /* CloseParenToken */ || token() === 24 /* DotDotDotToken */) { + // ( ) + // ( ... return true; } if (skipParameterStart()) { - if (token() === 56 || token() === 26 || - token() === 55 || token() === 58) { + // We successfully skipped modifiers (if any) and an identifier or binding pattern, + // now see if we have something that indicates a parameter declaration + if (token() === 56 /* ColonToken */ || token() === 26 /* CommaToken */ || + token() === 55 /* QuestionToken */ || token() === 58 /* EqualsToken */) { + // ( xxx : + // ( xxx , + // ( xxx ? + // ( xxx = return true; } - if (token() === 20) { + if (token() === 20 /* CloseParenToken */) { nextToken(); - if (token() === 36) { + if (token() === 36 /* EqualsGreaterThanToken */) { + // ( xxx ) => return true; } } @@ -15535,7 +17786,7 @@ var ts; var typePredicateVariable = isIdentifier() && tryParse(parseTypePredicatePrefix); var type = parseType(); if (typePredicateVariable) { - var node = createNode(161, typePredicateVariable.pos); + var node = createNode(161 /* TypePredicate */, typePredicateVariable.pos); node.parameterName = typePredicateVariable; node.type = type; return finishNode(node); @@ -15546,56 +17797,60 @@ var ts; } function parseTypePredicatePrefix() { var id = parseIdentifier(); - if (token() === 127 && !scanner.hasPrecedingLineBreak()) { + if (token() === 127 /* IsKeyword */ && !scanner.hasPrecedingLineBreak()) { nextToken(); return id; } } function parseType() { - return doOutsideOfContext(20480, parseTypeWorker); + // The rules about 'yield' only apply to actual code/expression contexts. They don't + // apply to 'type' contexts. So we disable these parameters here before moving on. + return doOutsideOfContext(20480 /* TypeExcludesFlags */, parseTypeWorker); } function parseTypeWorker(noConditionalTypes) { - if (isStartOfFunctionType() || token() === 94) { + if (isStartOfFunctionType() || token() === 94 /* NewKeyword */) { return parseFunctionOrConstructorType(); } var type = parseUnionTypeOrHigher(); - if (!noConditionalTypes && !scanner.hasPrecedingLineBreak() && parseOptional(85)) { - var node = createNode(171, type.pos); + if (!noConditionalTypes && !scanner.hasPrecedingLineBreak() && parseOptional(85 /* ExtendsKeyword */)) { + var node = createNode(171 /* ConditionalType */, type.pos); node.checkType = type; - node.extendsType = parseTypeWorker(true); - parseExpected(55); + // The type following 'extends' is not permitted to be another conditional type + node.extendsType = parseTypeWorker(/*noConditionalTypes*/ true); + parseExpected(55 /* QuestionToken */); node.trueType = parseTypeWorker(); - parseExpected(56); + parseExpected(56 /* ColonToken */); node.falseType = parseTypeWorker(); return finishNode(node); } return type; } function parseTypeAnnotation() { - return parseOptional(56) ? parseType() : undefined; + return parseOptional(56 /* ColonToken */) ? parseType() : undefined; } + // EXPRESSIONS function isStartOfLeftHandSideExpression() { switch (token()) { - case 99: - case 97: - case 95: - case 101: - case 86: - case 8: - case 9: - case 13: - case 14: - case 19: - case 21: - case 17: - case 89: - case 75: - case 94: - case 41: - case 63: - case 71: + case 99 /* ThisKeyword */: + case 97 /* SuperKeyword */: + case 95 /* NullKeyword */: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: + case 13 /* NoSubstitutionTemplateLiteral */: + case 14 /* TemplateHead */: + case 19 /* OpenParenToken */: + case 21 /* OpenBracketToken */: + case 17 /* OpenBraceToken */: + case 89 /* FunctionKeyword */: + case 75 /* ClassKeyword */: + case 94 /* NewKeyword */: + case 41 /* SlashToken */: + case 63 /* SlashEqualsToken */: + case 71 /* Identifier */: return true; - case 91: + case 91 /* ImportKeyword */: return lookAhead(nextTokenIsOpenParenOrLessThanOrDot); default: return isIdentifier(); @@ -15606,20 +17861,27 @@ var ts; return true; } switch (token()) { - case 37: - case 38: - case 52: - case 51: - case 80: - case 103: - case 105: - case 43: - case 44: - case 27: - case 121: - case 116: + case 37 /* PlusToken */: + case 38 /* MinusToken */: + case 52 /* TildeToken */: + case 51 /* ExclamationToken */: + case 80 /* DeleteKeyword */: + case 103 /* TypeOfKeyword */: + case 105 /* VoidKeyword */: + case 43 /* PlusPlusToken */: + case 44 /* MinusMinusToken */: + case 27 /* LessThanToken */: + case 121 /* AwaitKeyword */: + case 116 /* YieldKeyword */: + // Yield/await always starts an expression. Either it is an identifier (in which case + // it is definitely an expression). Or it's a keyword (either because we're in + // a generator or async function, or in strict mode (or both)) and it started a yield or await expression. return true; default: + // Error tolerance. If we see the start of some binary operator, we consider + // that the start of an expression. That way we'll parse out a missing identifier, + // give a good message about an identifier being missing, and then consume the + // rest of the binary expression. if (isBinaryOperator()) { return true; } @@ -15627,52 +17889,114 @@ var ts; } } function isStartOfExpressionStatement() { - return token() !== 17 && - token() !== 89 && - token() !== 75 && - token() !== 57 && + // As per the grammar, none of '{' or 'function' or 'class' can start an expression statement. + return token() !== 17 /* OpenBraceToken */ && + token() !== 89 /* FunctionKeyword */ && + token() !== 75 /* ClassKeyword */ && + token() !== 57 /* AtToken */ && isStartOfExpression(); } function parseExpression() { + // Expression[in]: + // AssignmentExpression[in] + // Expression[in] , AssignmentExpression[in] + // clear the decorator context when parsing Expression, as it should be unambiguous when parsing a decorator var saveDecoratorContext = inDecoratorContext(); if (saveDecoratorContext) { - setDecoratorContext(false); + setDecoratorContext(/*val*/ false); } var expr = parseAssignmentExpressionOrHigher(); var operatorToken; - while ((operatorToken = parseOptionalToken(26))) { + while ((operatorToken = parseOptionalToken(26 /* CommaToken */))) { expr = makeBinaryExpression(expr, operatorToken, parseAssignmentExpressionOrHigher()); } if (saveDecoratorContext) { - setDecoratorContext(true); + setDecoratorContext(/*val*/ true); } return expr; } function parseInitializer() { - return parseOptional(58) ? parseAssignmentExpressionOrHigher() : undefined; + return parseOptional(58 /* EqualsToken */) ? parseAssignmentExpressionOrHigher() : undefined; } function parseAssignmentExpressionOrHigher() { + // AssignmentExpression[in,yield]: + // 1) ConditionalExpression[?in,?yield] + // 2) LeftHandSideExpression = AssignmentExpression[?in,?yield] + // 3) LeftHandSideExpression AssignmentOperator AssignmentExpression[?in,?yield] + // 4) ArrowFunctionExpression[?in,?yield] + // 5) AsyncArrowFunctionExpression[in,yield,await] + // 6) [+Yield] YieldExpression[?In] + // + // Note: for ease of implementation we treat productions '2' and '3' as the same thing. + // (i.e. they're both BinaryExpressions with an assignment operator in it). + // First, do the simple check if we have a YieldExpression (production '6'). if (isYieldExpression()) { return parseYieldExpression(); } + // Then, check if we have an arrow function (production '4' and '5') that starts with a parenthesized + // parameter list or is an async arrow function. + // AsyncArrowFunctionExpression: + // 1) async[no LineTerminator here]AsyncArrowBindingIdentifier[?Yield][no LineTerminator here]=>AsyncConciseBody[?In] + // 2) CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await][no LineTerminator here]=>AsyncConciseBody[?In] + // Production (1) of AsyncArrowFunctionExpression is parsed in "tryParseAsyncSimpleArrowFunctionExpression". + // And production (2) is parsed in "tryParseParenthesizedArrowFunctionExpression". + // + // If we do successfully parse arrow-function, we must *not* recurse for productions 1, 2 or 3. An ArrowFunction is + // not a LeftHandSideExpression, nor does it start a ConditionalExpression. So we are done + // with AssignmentExpression if we see one. var arrowExpression = tryParseParenthesizedArrowFunctionExpression() || tryParseAsyncSimpleArrowFunctionExpression(); if (arrowExpression) { return arrowExpression; } - var expr = parseBinaryExpressionOrHigher(0); - if (expr.kind === 71 && token() === 36) { + // Now try to see if we're in production '1', '2' or '3'. A conditional expression can + // start with a LogicalOrExpression, while the assignment productions can only start with + // LeftHandSideExpressions. + // + // So, first, we try to just parse out a BinaryExpression. If we get something that is a + // LeftHandSide or higher, then we can try to parse out the assignment expression part. + // Otherwise, we try to parse out the conditional expression bit. We want to allow any + // binary expression here, so we pass in the 'lowest' precedence here so that it matches + // and consumes anything. + var expr = parseBinaryExpressionOrHigher(/*precedence*/ 0); + // To avoid a look-ahead, we did not handle the case of an arrow function with a single un-parenthesized + // parameter ('x => ...') above. We handle it here by checking if the parsed expression was a single + // identifier and the current token is an arrow. + if (expr.kind === 71 /* Identifier */ && token() === 36 /* EqualsGreaterThanToken */) { return parseSimpleArrowFunctionExpression(expr); } + // Now see if we might be in cases '2' or '3'. + // If the expression was a LHS expression, and we have an assignment operator, then + // we're in '2' or '3'. Consume the assignment and return. + // + // Note: we call reScanGreaterToken so that we get an appropriately merged token + // for cases like `> > =` becoming `>>=` if (ts.isLeftHandSideExpression(expr) && ts.isAssignmentOperator(reScanGreaterToken())) { return makeBinaryExpression(expr, parseTokenNode(), parseAssignmentExpressionOrHigher()); } + // It wasn't an assignment or a lambda. This is a conditional expression: return parseConditionalExpressionRest(expr); } function isYieldExpression() { - if (token() === 116) { + if (token() === 116 /* YieldKeyword */) { + // If we have a 'yield' keyword, and this is a context where yield expressions are + // allowed, then definitely parse out a yield expression. if (inYieldContext()) { return true; } + // We're in a context where 'yield expr' is not allowed. However, if we can + // definitely tell that the user was trying to parse a 'yield expr' and not + // just a normal expr that start with a 'yield' identifier, then parse out + // a 'yield expr'. We can then report an error later that they are only + // allowed in generator expressions. + // + // for example, if we see 'yield(foo)', then we'll have to treat that as an + // invocation expression of something called 'yield'. However, if we have + // 'yield foo' then that is not legal as a normal expression, so we can + // definitely recognize this as a yield expression. + // + // for now we just check if the next token is an identifier. More heuristics + // can be added here later as necessary. We just need to make sure that we + // don't accidentally consume something legal. return lookAhead(nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine); } return false; @@ -15682,213 +18006,302 @@ var ts; return !scanner.hasPrecedingLineBreak() && isIdentifier(); } function parseYieldExpression() { - var node = createNode(203); + var node = createNode(203 /* YieldExpression */); + // YieldExpression[In] : + // yield + // yield [no LineTerminator here] [Lexical goal InputElementRegExp]AssignmentExpression[?In, Yield] + // yield [no LineTerminator here] * [Lexical goal InputElementRegExp]AssignmentExpression[?In, Yield] nextToken(); if (!scanner.hasPrecedingLineBreak() && - (token() === 39 || isStartOfExpression())) { - node.asteriskToken = parseOptionalToken(39); + (token() === 39 /* AsteriskToken */ || isStartOfExpression())) { + node.asteriskToken = parseOptionalToken(39 /* AsteriskToken */); node.expression = parseAssignmentExpressionOrHigher(); return finishNode(node); } else { + // if the next token is not on the same line as yield. or we don't have an '*' or + // the start of an expression, then this is just a simple "yield" expression. return finishNode(node); } } function parseSimpleArrowFunctionExpression(identifier, asyncModifier) { - ts.Debug.assert(token() === 36, "parseSimpleArrowFunctionExpression should only have been called if we had a =>"); + ts.Debug.assert(token() === 36 /* EqualsGreaterThanToken */, "parseSimpleArrowFunctionExpression should only have been called if we had a =>"); var node; if (asyncModifier) { - node = createNode(193, asyncModifier.pos); + node = createNode(193 /* ArrowFunction */, asyncModifier.pos); node.modifiers = asyncModifier; } else { - node = createNode(193, identifier.pos); + node = createNode(193 /* ArrowFunction */, identifier.pos); } - var parameter = createNode(149, identifier.pos); + var parameter = createNode(149 /* Parameter */, identifier.pos); parameter.name = identifier; finishNode(parameter); node.parameters = createNodeArray([parameter], parameter.pos, parameter.end); - node.equalsGreaterThanToken = parseExpectedToken(36); - node.body = parseArrowFunctionExpressionBody(!!asyncModifier); + node.equalsGreaterThanToken = parseExpectedToken(36 /* EqualsGreaterThanToken */); + node.body = parseArrowFunctionExpressionBody(/*isAsync*/ !!asyncModifier); return addJSDocComment(finishNode(node)); } function tryParseParenthesizedArrowFunctionExpression() { var triState = isParenthesizedArrowFunctionExpression(); - if (triState === 0) { + if (triState === 0 /* False */) { + // It's definitely not a parenthesized arrow function expression. return undefined; } - var arrowFunction = triState === 1 - ? parseParenthesizedArrowFunctionExpressionHead(true) + // If we definitely have an arrow function, then we can just parse one, not requiring a + // following => or { token. Otherwise, we *might* have an arrow function. Try to parse + // it out, but don't allow any ambiguity, and return 'undefined' if this could be an + // expression instead. + var arrowFunction = triState === 1 /* True */ + ? parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity*/ true) : tryParse(parsePossibleParenthesizedArrowFunctionExpressionHead); if (!arrowFunction) { + // Didn't appear to actually be a parenthesized arrow function. Just bail out. return undefined; } - var isAsync = ts.hasModifier(arrowFunction, 256); + var isAsync = ts.hasModifier(arrowFunction, 256 /* Async */); + // If we have an arrow, then try to parse the body. Even if not, try to parse if we + // have an opening brace, just in case we're in an error state. var lastToken = token(); - arrowFunction.equalsGreaterThanToken = parseExpectedToken(36); - arrowFunction.body = (lastToken === 36 || lastToken === 17) + arrowFunction.equalsGreaterThanToken = parseExpectedToken(36 /* EqualsGreaterThanToken */); + arrowFunction.body = (lastToken === 36 /* EqualsGreaterThanToken */ || lastToken === 17 /* OpenBraceToken */) ? parseArrowFunctionExpressionBody(isAsync) : parseIdentifier(); return finishNode(arrowFunction); } + // True -> We definitely expect a parenthesized arrow function here. + // False -> There *cannot* be a parenthesized arrow function here. + // Unknown -> There *might* be a parenthesized arrow function here. + // Speculatively look ahead to be sure, and rollback if not. function isParenthesizedArrowFunctionExpression() { - if (token() === 19 || token() === 27 || token() === 120) { + if (token() === 19 /* OpenParenToken */ || token() === 27 /* LessThanToken */ || token() === 120 /* AsyncKeyword */) { return lookAhead(isParenthesizedArrowFunctionExpressionWorker); } - if (token() === 36) { - return 1; + if (token() === 36 /* EqualsGreaterThanToken */) { + // ERROR RECOVERY TWEAK: + // If we see a standalone => try to parse it as an arrow function expression as that's + // likely what the user intended to write. + return 1 /* True */; } - return 0; + // Definitely not a parenthesized arrow function. + return 0 /* False */; } function isParenthesizedArrowFunctionExpressionWorker() { - if (token() === 120) { + if (token() === 120 /* AsyncKeyword */) { nextToken(); if (scanner.hasPrecedingLineBreak()) { - return 0; + return 0 /* False */; } - if (token() !== 19 && token() !== 27) { - return 0; + if (token() !== 19 /* OpenParenToken */ && token() !== 27 /* LessThanToken */) { + return 0 /* False */; } } var first = token(); var second = nextToken(); - if (first === 19) { - if (second === 20) { + if (first === 19 /* OpenParenToken */) { + if (second === 20 /* CloseParenToken */) { + // Simple cases: "() =>", "(): ", and "() {". + // This is an arrow function with no parameters. + // The last one is not actually an arrow function, + // but this is probably what the user intended. var third = nextToken(); switch (third) { - case 36: - case 56: - case 17: - return 1; + case 36 /* EqualsGreaterThanToken */: + case 56 /* ColonToken */: + case 17 /* OpenBraceToken */: + return 1 /* True */; default: - return 0; + return 0 /* False */; } } - if (second === 21 || second === 17) { - return 2; + // If encounter "([" or "({", this could be the start of a binding pattern. + // Examples: + // ([ x ]) => { } + // ({ x }) => { } + // ([ x ]) + // ({ x }) + if (second === 21 /* OpenBracketToken */ || second === 17 /* OpenBraceToken */) { + return 2 /* Unknown */; } - if (second === 24) { - return 1; + // Simple case: "(..." + // This is an arrow function with a rest parameter. + if (second === 24 /* DotDotDotToken */) { + return 1 /* True */; } - if (ts.isModifierKind(second) && second !== 120 && lookAhead(nextTokenIsIdentifier)) { - return 1; + // Check for "(xxx yyy", where xxx is a modifier and yyy is an identifier. This + // isn't actually allowed, but we want to treat it as a lambda so we can provide + // a good error message. + if (ts.isModifierKind(second) && second !== 120 /* AsyncKeyword */ && lookAhead(nextTokenIsIdentifier)) { + return 1 /* True */; } + // If we had "(" followed by something that's not an identifier, + // then this definitely doesn't look like a lambda. if (!isIdentifier()) { - return 0; + return 0 /* False */; } switch (nextToken()) { - case 56: - return 1; - case 55: + case 56 /* ColonToken */: + // If we have something like "(a:", then we must have a + // type-annotated parameter in an arrow function expression. + return 1 /* True */; + case 55 /* QuestionToken */: nextToken(); - if (token() === 56 || token() === 26 || token() === 58 || token() === 20) { - return 1; + // If we have "(a?:" or "(a?," or "(a?=" or "(a?)" then it is definitely a lambda. + if (token() === 56 /* ColonToken */ || token() === 26 /* CommaToken */ || token() === 58 /* EqualsToken */ || token() === 20 /* CloseParenToken */) { + return 1 /* True */; } - return 0; - case 26: - case 58: - case 20: - return 2; + // Otherwise it is definitely not a lambda. + return 0 /* False */; + case 26 /* CommaToken */: + case 58 /* EqualsToken */: + case 20 /* CloseParenToken */: + // If we have "(a," or "(a=" or "(a)" this *could* be an arrow function + return 2 /* Unknown */; } - return 0; + // It is definitely not an arrow function + return 0 /* False */; } else { - ts.Debug.assert(first === 27); + ts.Debug.assert(first === 27 /* LessThanToken */); + // If we have "<" not followed by an identifier, + // then this definitely is not an arrow function. if (!isIdentifier()) { - return 0; + return 0 /* False */; } - if (sourceFile.languageVariant === 1) { + // JSX overrides + if (sourceFile.languageVariant === 1 /* JSX */) { var isArrowFunctionInJsx = lookAhead(function () { var third = nextToken(); - if (third === 85) { + if (third === 85 /* ExtendsKeyword */) { var fourth = nextToken(); switch (fourth) { - case 58: - case 29: + case 58 /* EqualsToken */: + case 29 /* GreaterThanToken */: return false; default: return true; } } - else if (third === 26) { + else if (third === 26 /* CommaToken */) { return true; } return false; }); if (isArrowFunctionInJsx) { - return 1; + return 1 /* True */; } - return 0; + return 0 /* False */; } - return 2; + // This *could* be a parenthesized arrow function. + return 2 /* Unknown */; } } function parsePossibleParenthesizedArrowFunctionExpressionHead() { - return parseParenthesizedArrowFunctionExpressionHead(false); + return parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity*/ false); } function tryParseAsyncSimpleArrowFunctionExpression() { - if (token() === 120) { - if (lookAhead(isUnParenthesizedAsyncArrowFunctionWorker) === 1) { + // We do a check here so that we won't be doing unnecessarily call to "lookAhead" + if (token() === 120 /* AsyncKeyword */) { + if (lookAhead(isUnParenthesizedAsyncArrowFunctionWorker) === 1 /* True */) { var asyncModifier = parseModifiersForArrowFunction(); - var expr = parseBinaryExpressionOrHigher(0); + var expr = parseBinaryExpressionOrHigher(/*precedence*/ 0); return parseSimpleArrowFunctionExpression(expr, asyncModifier); } } return undefined; } function isUnParenthesizedAsyncArrowFunctionWorker() { - if (token() === 120) { + // AsyncArrowFunctionExpression: + // 1) async[no LineTerminator here]AsyncArrowBindingIdentifier[?Yield][no LineTerminator here]=>AsyncConciseBody[?In] + // 2) CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await][no LineTerminator here]=>AsyncConciseBody[?In] + if (token() === 120 /* AsyncKeyword */) { nextToken(); - if (scanner.hasPrecedingLineBreak() || token() === 36) { - return 0; + // If the "async" is followed by "=>" token then it is not a beginning of an async arrow-function + // but instead a simple arrow-function which will be parsed inside "parseAssignmentExpressionOrHigher" + if (scanner.hasPrecedingLineBreak() || token() === 36 /* EqualsGreaterThanToken */) { + return 0 /* False */; } - var expr = parseBinaryExpressionOrHigher(0); - if (!scanner.hasPrecedingLineBreak() && expr.kind === 71 && token() === 36) { - return 1; + // Check for un-parenthesized AsyncArrowFunction + var expr = parseBinaryExpressionOrHigher(/*precedence*/ 0); + if (!scanner.hasPrecedingLineBreak() && expr.kind === 71 /* Identifier */ && token() === 36 /* EqualsGreaterThanToken */) { + return 1 /* True */; } } - return 0; + return 0 /* False */; } function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity) { - var node = createNodeWithJSDoc(193); + var node = createNodeWithJSDoc(193 /* ArrowFunction */); node.modifiers = parseModifiersForArrowFunction(); - var isAsync = ts.hasModifier(node, 256) ? 2 : 0; - if (!fillSignature(56, isAsync, node) && !allowAmbiguity) { + var isAsync = ts.hasModifier(node, 256 /* Async */) ? 2 /* Await */ : 0 /* None */; + // Arrow functions are never generators. + // + // If we're speculatively parsing a signature for a parenthesized arrow function, then + // we have to have a complete parameter list. Otherwise we might see something like + // a => (b => c) + // And think that "(b =>" was actually a parenthesized arrow function with a missing + // close paren. + if (!fillSignature(56 /* ColonToken */, isAsync, node) && !allowAmbiguity) { return undefined; } - if (!allowAmbiguity && token() !== 36 && token() !== 17) { + // Parsing a signature isn't enough. + // Parenthesized arrow signatures often look like other valid expressions. + // For instance: + // - "(x = 10)" is an assignment expression parsed as a signature with a default parameter value. + // - "(x,y)" is a comma expression parsed as a signature with two parameters. + // - "a ? (b): c" will have "(b):" parsed as a signature with a return type annotation. + // + // So we need just a bit of lookahead to ensure that it can only be a signature. + if (!allowAmbiguity && token() !== 36 /* EqualsGreaterThanToken */ && token() !== 17 /* OpenBraceToken */) { + // Returning undefined here will cause our caller to rewind to where we started from. return undefined; } return node; } function parseArrowFunctionExpressionBody(isAsync) { - if (token() === 17) { - return parseFunctionBlock(isAsync ? 2 : 0); + if (token() === 17 /* OpenBraceToken */) { + return parseFunctionBlock(isAsync ? 2 /* Await */ : 0 /* None */); } - if (token() !== 25 && - token() !== 89 && - token() !== 75 && + if (token() !== 25 /* SemicolonToken */ && + token() !== 89 /* FunctionKeyword */ && + token() !== 75 /* ClassKeyword */ && isStartOfStatement() && !isStartOfExpressionStatement()) { - return parseFunctionBlock(16 | (isAsync ? 2 : 0)); + // Check if we got a plain statement (i.e. no expression-statements, no function/class expressions/declarations) + // + // Here we try to recover from a potential error situation in the case where the + // user meant to supply a block. For example, if the user wrote: + // + // a => + // let v = 0; + // } + // + // they may be missing an open brace. Check to see if that's the case so we can + // try to recover better. If we don't do this, then the next close curly we see may end + // up preemptively closing the containing construct. + // + // Note: even when 'IgnoreMissingOpenBrace' is passed, parseBody will still error. + return parseFunctionBlock(16 /* IgnoreMissingOpenBrace */ | (isAsync ? 2 /* Await */ : 0 /* None */)); } return isAsync ? doInAwaitContext(parseAssignmentExpressionOrHigher) : doOutsideOfAwaitContext(parseAssignmentExpressionOrHigher); } function parseConditionalExpressionRest(leftOperand) { - var questionToken = parseOptionalToken(55); + // Note: we are passed in an expression which was produced from parseBinaryExpressionOrHigher. + var questionToken = parseOptionalToken(55 /* QuestionToken */); if (!questionToken) { return leftOperand; } - var node = createNode(201, leftOperand.pos); + // Note: we explicitly 'allowIn' in the whenTrue part of the condition expression, and + // we do not that for the 'whenFalse' part. + var node = createNode(201 /* ConditionalExpression */, leftOperand.pos); node.condition = leftOperand; node.questionToken = questionToken; node.whenTrue = doOutsideOfContext(disallowInAndDecoratorContext, parseAssignmentExpressionOrHigher); - node.colonToken = parseExpectedToken(56); + node.colonToken = parseExpectedToken(56 /* ColonToken */); node.whenFalse = ts.nodeIsPresent(node.colonToken) ? parseAssignmentExpressionOrHigher() - : createMissingNode(71, false, ts.Diagnostics._0_expected, ts.tokenToString(56)); + : createMissingNode(71 /* Identifier */, /*reportAtCurrentPosition*/ false, ts.Diagnostics._0_expected, ts.tokenToString(56 /* ColonToken */)); return finishNode(node); } function parseBinaryExpressionOrHigher(precedence) { @@ -15896,22 +18309,50 @@ var ts; return parseBinaryExpressionRest(precedence, leftOperand); } function isInOrOfKeyword(t) { - return t === 92 || t === 145; + return t === 92 /* InKeyword */ || t === 145 /* OfKeyword */; } function parseBinaryExpressionRest(precedence, leftOperand) { while (true) { + // We either have a binary operator here, or we're finished. We call + // reScanGreaterToken so that we merge token sequences like > and = into >= reScanGreaterToken(); var newPrecedence = ts.getBinaryOperatorPrecedence(token()); - var consumeCurrentOperator = token() === 40 ? + // Check the precedence to see if we should "take" this operator + // - For left associative operator (all operator but **), consume the operator, + // recursively call the function below, and parse binaryExpression as a rightOperand + // of the caller if the new precedence of the operator is greater then or equal to the current precedence. + // For example: + // a - b - c; + // ^token; leftOperand = b. Return b to the caller as a rightOperand + // a * b - c + // ^token; leftOperand = b. Return b to the caller as a rightOperand + // a - b * c; + // ^token; leftOperand = b. Return b * c to the caller as a rightOperand + // - For right associative operator (**), consume the operator, recursively call the function + // and parse binaryExpression as a rightOperand of the caller if the new precedence of + // the operator is strictly grater than the current precedence + // For example: + // a ** b ** c; + // ^^token; leftOperand = b. Return b ** c to the caller as a rightOperand + // a - b ** c; + // ^^token; leftOperand = b. Return b ** c to the caller as a rightOperand + // a ** b - c + // ^token; leftOperand = b. Return b to the caller as a rightOperand + var consumeCurrentOperator = token() === 40 /* AsteriskAsteriskToken */ ? newPrecedence >= precedence : newPrecedence > precedence; if (!consumeCurrentOperator) { break; } - if (token() === 92 && inDisallowInContext()) { + if (token() === 92 /* InKeyword */ && inDisallowInContext()) { break; } - if (token() === 118) { + if (token() === 118 /* AsKeyword */) { + // Make sure we *do* perform ASI for constructs like this: + // var x = foo + // as (Bar) + // This should be parsed as an initialized variable, followed + // by a function call to 'as' with the argument 'Bar' if (scanner.hasPrecedingLineBreak()) { break; } @@ -15927,77 +18368,105 @@ var ts; return leftOperand; } function isBinaryOperator() { - if (inDisallowInContext() && token() === 92) { + if (inDisallowInContext() && token() === 92 /* InKeyword */) { return false; } return ts.getBinaryOperatorPrecedence(token()) > 0; } function makeBinaryExpression(left, operatorToken, right) { - var node = createNode(200, left.pos); + var node = createNode(200 /* BinaryExpression */, left.pos); node.left = left; node.operatorToken = operatorToken; node.right = right; return finishNode(node); } function makeAsExpression(left, right) { - var node = createNode(208, left.pos); + var node = createNode(208 /* AsExpression */, left.pos); node.expression = left; node.type = right; return finishNode(node); } function parsePrefixUnaryExpression() { - var node = createNode(198); + var node = createNode(198 /* PrefixUnaryExpression */); node.operator = token(); nextToken(); node.operand = parseSimpleUnaryExpression(); return finishNode(node); } function parseDeleteExpression() { - var node = createNode(194); + var node = createNode(194 /* DeleteExpression */); nextToken(); node.expression = parseSimpleUnaryExpression(); return finishNode(node); } function parseTypeOfExpression() { - var node = createNode(195); + var node = createNode(195 /* TypeOfExpression */); nextToken(); node.expression = parseSimpleUnaryExpression(); return finishNode(node); } function parseVoidExpression() { - var node = createNode(196); + var node = createNode(196 /* VoidExpression */); nextToken(); node.expression = parseSimpleUnaryExpression(); return finishNode(node); } function isAwaitExpression() { - if (token() === 121) { + if (token() === 121 /* AwaitKeyword */) { if (inAwaitContext()) { return true; } + // here we are using similar heuristics as 'isYieldExpression' return lookAhead(nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine); } return false; } function parseAwaitExpression() { - var node = createNode(197); + var node = createNode(197 /* AwaitExpression */); nextToken(); node.expression = parseSimpleUnaryExpression(); return finishNode(node); } + /** + * Parse ES7 exponential expression and await expression + * + * ES7 ExponentiationExpression: + * 1) UnaryExpression[?Yield] + * 2) UpdateExpression[?Yield] ** ExponentiationExpression[?Yield] + * + */ function parseUnaryExpressionOrHigher() { + /** + * ES7 UpdateExpression: + * 1) LeftHandSideExpression[?Yield] + * 2) LeftHandSideExpression[?Yield][no LineTerminator here]++ + * 3) LeftHandSideExpression[?Yield][no LineTerminator here]-- + * 4) ++UnaryExpression[?Yield] + * 5) --UnaryExpression[?Yield] + */ if (isUpdateExpression()) { var updateExpression = parseUpdateExpression(); - return token() === 40 ? + return token() === 40 /* AsteriskAsteriskToken */ ? parseBinaryExpressionRest(ts.getBinaryOperatorPrecedence(token()), updateExpression) : updateExpression; } + /** + * ES7 UnaryExpression: + * 1) UpdateExpression[?yield] + * 2) delete UpdateExpression[?yield] + * 3) void UpdateExpression[?yield] + * 4) typeof UpdateExpression[?yield] + * 5) + UpdateExpression[?yield] + * 6) - UpdateExpression[?yield] + * 7) ~ UpdateExpression[?yield] + * 8) ! UpdateExpression[?yield] + */ var unaryOperator = token(); var simpleUnaryExpression = parseSimpleUnaryExpression(); - if (token() === 40) { + if (token() === 40 /* AsteriskAsteriskToken */) { var pos = ts.skipTrivia(sourceText, simpleUnaryExpression.pos); var end = simpleUnaryExpression.end; - if (simpleUnaryExpression.kind === 190) { + if (simpleUnaryExpression.kind === 190 /* TypeAssertionExpression */) { parseErrorAt(pos, end, ts.Diagnostics.A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses); } else { @@ -16006,63 +18475,108 @@ var ts; } return simpleUnaryExpression; } + /** + * Parse ES7 simple-unary expression or higher: + * + * ES7 UnaryExpression: + * 1) UpdateExpression[?yield] + * 2) delete UnaryExpression[?yield] + * 3) void UnaryExpression[?yield] + * 4) typeof UnaryExpression[?yield] + * 5) + UnaryExpression[?yield] + * 6) - UnaryExpression[?yield] + * 7) ~ UnaryExpression[?yield] + * 8) ! UnaryExpression[?yield] + * 9) [+Await] await UnaryExpression[?yield] + */ function parseSimpleUnaryExpression() { switch (token()) { - case 37: - case 38: - case 52: - case 51: + case 37 /* PlusToken */: + case 38 /* MinusToken */: + case 52 /* TildeToken */: + case 51 /* ExclamationToken */: return parsePrefixUnaryExpression(); - case 80: + case 80 /* DeleteKeyword */: return parseDeleteExpression(); - case 103: + case 103 /* TypeOfKeyword */: return parseTypeOfExpression(); - case 105: + case 105 /* VoidKeyword */: return parseVoidExpression(); - case 27: + case 27 /* LessThanToken */: + // This is modified UnaryExpression grammar in TypeScript + // UnaryExpression (modified): + // < type > UnaryExpression return parseTypeAssertion(); - case 121: + case 121 /* AwaitKeyword */: if (isAwaitExpression()) { return parseAwaitExpression(); } + // falls through default: return parseUpdateExpression(); } } + /** + * Check if the current token can possibly be an ES7 increment expression. + * + * ES7 UpdateExpression: + * LeftHandSideExpression[?Yield] + * LeftHandSideExpression[?Yield][no LineTerminator here]++ + * LeftHandSideExpression[?Yield][no LineTerminator here]-- + * ++LeftHandSideExpression[?Yield] + * --LeftHandSideExpression[?Yield] + */ function isUpdateExpression() { + // This function is called inside parseUnaryExpression to decide + // whether to call parseSimpleUnaryExpression or call parseUpdateExpression directly switch (token()) { - case 37: - case 38: - case 52: - case 51: - case 80: - case 103: - case 105: - case 121: + case 37 /* PlusToken */: + case 38 /* MinusToken */: + case 52 /* TildeToken */: + case 51 /* ExclamationToken */: + case 80 /* DeleteKeyword */: + case 103 /* TypeOfKeyword */: + case 105 /* VoidKeyword */: + case 121 /* AwaitKeyword */: return false; - case 27: - if (sourceFile.languageVariant !== 1) { + case 27 /* LessThanToken */: + // If we are not in JSX context, we are parsing TypeAssertion which is an UnaryExpression + if (sourceFile.languageVariant !== 1 /* JSX */) { return false; } + // We are in JSX context and the token is part of JSXElement. + // falls through default: return true; } } + /** + * Parse ES7 UpdateExpression. UpdateExpression is used instead of ES6's PostFixExpression. + * + * ES7 UpdateExpression[yield]: + * 1) LeftHandSideExpression[?yield] + * 2) LeftHandSideExpression[?yield] [[no LineTerminator here]]++ + * 3) LeftHandSideExpression[?yield] [[no LineTerminator here]]-- + * 4) ++LeftHandSideExpression[?yield] + * 5) --LeftHandSideExpression[?yield] + * In TypeScript (2), (3) are parsed as PostfixUnaryExpression. (4), (5) are parsed as PrefixUnaryExpression + */ function parseUpdateExpression() { - if (token() === 43 || token() === 44) { - var node = createNode(198); + if (token() === 43 /* PlusPlusToken */ || token() === 44 /* MinusMinusToken */) { + var node = createNode(198 /* PrefixUnaryExpression */); node.operator = token(); nextToken(); node.operand = parseLeftHandSideExpressionOrHigher(); return finishNode(node); } - else if (sourceFile.languageVariant === 1 && token() === 27 && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) { - return parseJsxElementOrSelfClosingElementOrFragment(true); + else if (sourceFile.languageVariant === 1 /* JSX */ && token() === 27 /* LessThanToken */ && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) { + // JSXElement is part of primaryExpression + return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true); } var expression = parseLeftHandSideExpressionOrHigher(); ts.Debug.assert(ts.isLeftHandSideExpression(expression)); - if ((token() === 43 || token() === 44) && !scanner.hasPrecedingLineBreak()) { - var node = createNode(199, expression.pos); + if ((token() === 43 /* PlusPlusToken */ || token() === 44 /* MinusMinusToken */) && !scanner.hasPrecedingLineBreak()) { + var node = createNode(199 /* PostfixUnaryExpression */, expression.pos); node.operand = expression; node.operator = token(); nextToken(); @@ -16071,51 +18585,139 @@ var ts; return expression; } function parseLeftHandSideExpressionOrHigher() { + // Original Ecma: + // LeftHandSideExpression: See 11.2 + // NewExpression + // CallExpression + // + // Our simplification: + // + // LeftHandSideExpression: See 11.2 + // MemberExpression + // CallExpression + // + // See comment in parseMemberExpressionOrHigher on how we replaced NewExpression with + // MemberExpression to make our lives easier. + // + // to best understand the below code, it's important to see how CallExpression expands + // out into its own productions: + // + // CallExpression: + // MemberExpression Arguments + // CallExpression Arguments + // CallExpression[Expression] + // CallExpression.IdentifierName + // import (AssignmentExpression) + // super Arguments + // super.IdentifierName + // + // Because of the recursion in these calls, we need to bottom out first. There are three + // bottom out states we can run into: 1) We see 'super' which must start either of + // the last two CallExpression productions. 2) We see 'import' which must start import call. + // 3)we have a MemberExpression which either completes the LeftHandSideExpression, + // or starts the beginning of the first four CallExpression productions. var expression; - if (token() === 91) { + if (token() === 91 /* ImportKeyword */) { if (lookAhead(nextTokenIsOpenParenOrLessThan)) { - sourceFile.flags |= 524288; + // We don't want to eagerly consume all import keyword as import call expression so we look ahead to find "(" + // For example: + // var foo3 = require("subfolder + // import * as foo1 from "module-from-node + // We want this import to be a statement rather than import call expression + sourceFile.flags |= 524288 /* PossiblyContainsDynamicImport */; expression = parseTokenNode(); } else if (lookAhead(nextTokenIsDot)) { + // This is an 'import.*' metaproperty (i.e. 'import.meta') var fullStart = scanner.getStartPos(); - nextToken(); - nextToken(); - var node = createNode(210, fullStart); - node.keywordToken = 91; + nextToken(); // advance past the 'import' + nextToken(); // advance past the dot + var node = createNode(210 /* MetaProperty */, fullStart); + node.keywordToken = 91 /* ImportKeyword */; node.name = parseIdentifierName(); expression = finishNode(node); - sourceFile.flags |= 1048576; + sourceFile.flags |= 1048576 /* PossiblyContainsImportMeta */; } else { expression = parseMemberExpressionOrHigher(); } } else { - expression = token() === 97 ? parseSuperExpression() : parseMemberExpressionOrHigher(); + expression = token() === 97 /* SuperKeyword */ ? parseSuperExpression() : parseMemberExpressionOrHigher(); } + // Now, we *may* be complete. However, we might have consumed the start of a + // CallExpression. As such, we need to consume the rest of it here to be complete. return parseCallExpressionRest(expression); } function parseMemberExpressionOrHigher() { + // Note: to make our lives simpler, we decompose the NewExpression productions and + // place ObjectCreationExpression and FunctionExpression into PrimaryExpression. + // like so: + // + // PrimaryExpression : See 11.1 + // this + // Identifier + // Literal + // ArrayLiteral + // ObjectLiteral + // (Expression) + // FunctionExpression + // new MemberExpression Arguments? + // + // MemberExpression : See 11.2 + // PrimaryExpression + // MemberExpression[Expression] + // MemberExpression.IdentifierName + // + // CallExpression : See 11.2 + // MemberExpression + // CallExpression Arguments + // CallExpression[Expression] + // CallExpression.IdentifierName + // + // Technically this is ambiguous. i.e. CallExpression defines: + // + // CallExpression: + // CallExpression Arguments + // + // If you see: "new Foo()" + // + // Then that could be treated as a single ObjectCreationExpression, or it could be + // treated as the invocation of "new Foo". We disambiguate that in code (to match + // the original grammar) by making sure that if we see an ObjectCreationExpression + // we always consume arguments if they are there. So we treat "new Foo()" as an + // object creation only, and not at all as an invocation. Another way to think + // about this is that for every "new" that we see, we will consume an argument list if + // it is there as part of the *associated* object creation node. Any additional + // argument lists we see, will become invocation expressions. + // + // Because there are no other places in the grammar now that refer to FunctionExpression + // or ObjectCreationExpression, it is safe to push down into the PrimaryExpression + // production. + // + // Because CallExpression and MemberExpression are left recursive, we need to bottom out + // of the recursion immediately. So we parse out a primary expression to start with. var expression = parsePrimaryExpression(); return parseMemberExpressionRest(expression); } function parseSuperExpression() { var expression = parseTokenNode(); - if (token() === 19 || token() === 23 || token() === 21) { + if (token() === 19 /* OpenParenToken */ || token() === 23 /* DotToken */ || token() === 21 /* OpenBracketToken */) { return expression; } - var node = createNode(185, expression.pos); + // If we have seen "super" it must be followed by '(' or '.'. + // If it wasn't then just try to parse out a '.' and report an error. + var node = createNode(185 /* PropertyAccessExpression */, expression.pos); node.expression = expression; - parseExpectedToken(23, ts.Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access); - node.name = parseRightSideOfDot(true); + parseExpectedToken(23 /* DotToken */, ts.Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access); + node.name = parseRightSideOfDot(/*allowIdentifierNames*/ true); return finishNode(node); } function parseJsxElementOrSelfClosingElementOrFragment(inExpressionContext) { var opening = parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext); var result; - if (opening.kind === 257) { - var node = createNode(255, opening.pos); + if (opening.kind === 257 /* JsxOpeningElement */) { + var node = createNode(255 /* JsxElement */, opening.pos); node.openingElement = opening; node.children = parseJsxChildren(node.openingElement); node.closingElement = parseJsxClosingElement(inExpressionContext); @@ -16124,26 +18726,34 @@ var ts; } result = finishNode(node); } - else if (opening.kind === 260) { - var node = createNode(259, opening.pos); + else if (opening.kind === 260 /* JsxOpeningFragment */) { + var node = createNode(259 /* JsxFragment */, opening.pos); node.openingFragment = opening; node.children = parseJsxChildren(node.openingFragment); node.closingFragment = parseJsxClosingFragment(inExpressionContext); result = finishNode(node); } else { - ts.Debug.assert(opening.kind === 256); + ts.Debug.assert(opening.kind === 256 /* JsxSelfClosingElement */); + // Nothing else to do for self-closing elements result = opening; } - if (inExpressionContext && token() === 27) { - var invalidElement = tryParse(function () { return parseJsxElementOrSelfClosingElementOrFragment(true); }); + // If the user writes the invalid code '
' in an expression context (i.e. not wrapped in + // an enclosing tag), we'll naively try to parse ^ this as a 'less than' operator and the remainder of the tag + // as garbage, which will cause the formatter to badly mangle the JSX. Perform a speculative parse of a JSX + // element if we see a < token so that we can wrap it in a synthetic binary expression so the formatter + // does less damage and we can report a better error. + // Since JSX elements are invalid < operands anyway, this lookahead parse will only occur in error scenarios + // of one sort or another. + if (inExpressionContext && token() === 27 /* LessThanToken */) { + var invalidElement = tryParse(function () { return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true); }); if (invalidElement) { parseErrorAtCurrentToken(ts.Diagnostics.JSX_expressions_must_have_one_parent_element); - var badNode = createNode(200, result.pos); + var badNode = createNode(200 /* BinaryExpression */, result.pos); badNode.end = invalidElement.end; badNode.left = result; badNode.right = invalidElement; - badNode.operatorToken = createMissingNode(26, false, undefined); + badNode.operatorToken = createMissingNode(26 /* CommaToken */, /*reportAtCurrentPosition*/ false, /*diagnosticMessage*/ undefined); // TODO: GH#18217 badNode.operatorToken.pos = badNode.operatorToken.end = badNode.right.pos; return badNode; } @@ -16151,14 +18761,16 @@ var ts; return result; } function parseJsxText() { - var node = createNode(10); - node.containsOnlyWhiteSpaces = currentToken === 11; + var node = createNode(10 /* JsxText */); + node.containsOnlyWhiteSpaces = currentToken === 11 /* JsxTextAllWhiteSpaces */; currentToken = scanner.scanJsxToken(); return finishNode(node); } function parseJsxChild(openingTag, token) { switch (token) { - case 1: + case 1 /* EndOfFileToken */: + // If we hit EOF, issue the error at the tag that lacks the closing element + // rather than at the end of the file (which is useless) if (ts.isJsxOpeningFragment(openingTag)) { parseErrorAtRange(openingTag, ts.Diagnostics.JSX_fragment_has_no_corresponding_closing_tag); } @@ -16166,16 +18778,16 @@ var ts; parseErrorAtRange(openingTag.tagName, ts.Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, ts.getTextOfNodeFromSourceText(sourceText, openingTag.tagName)); } return undefined; - case 28: - case 7: + case 28 /* LessThanSlashToken */: + case 7 /* ConflictMarkerTrivia */: return undefined; - case 10: - case 11: + case 10 /* JsxText */: + case 11 /* JsxTextAllWhiteSpaces */: return parseJsxText(); - case 17: - return parseJsxExpression(false); - case 27: - return parseJsxElementOrSelfClosingElementOrFragment(false); + case 17 /* OpenBraceToken */: + return parseJsxExpression(/*inExpressionContext*/ false); + case 27 /* LessThanToken */: + return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ false); default: return ts.Debug.assertNever(token); } @@ -16184,7 +18796,7 @@ var ts; var list = []; var listPos = getNodePos(); var saveParsingContext = parsingContext; - parsingContext |= 1 << 14; + parsingContext |= 1 << 14 /* JsxChildren */; while (true) { var child = parseJsxChild(openingTag, currentToken = scanner.reScanJsxToken()); if (!child) @@ -16195,15 +18807,16 @@ var ts; return createNodeArray(list, listPos); } function parseJsxAttributes() { - var jsxAttributes = createNode(263); - jsxAttributes.properties = parseList(13, parseJsxAttribute); + var jsxAttributes = createNode(263 /* JsxAttributes */); + jsxAttributes.properties = parseList(13 /* JsxAttributes */, parseJsxAttribute); return finishNode(jsxAttributes); } function parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext) { var fullStart = scanner.getStartPos(); - parseExpected(27); - if (token() === 29) { - var node_1 = createNode(260, fullStart); + parseExpected(27 /* LessThanToken */); + if (token() === 29 /* GreaterThanToken */) { + // See below for explanation of scanJsxText + var node_1 = createNode(260 /* JsxOpeningFragment */, fullStart); scanJsxText(); return finishNode(node_1); } @@ -16211,20 +18824,23 @@ var ts; var typeArguments = tryParseTypeArguments(); var attributes = parseJsxAttributes(); var node; - if (token() === 29) { - node = createNode(257, fullStart); + if (token() === 29 /* GreaterThanToken */) { + // Closing tag, so scan the immediately-following text with the JSX scanning instead + // of regular scanning to avoid treating illegal characters (e.g. '#') as immediate + // scanning errors + node = createNode(257 /* JsxOpeningElement */, fullStart); scanJsxText(); } else { - parseExpected(41); + parseExpected(41 /* SlashToken */); if (inExpressionContext) { - parseExpected(29); + parseExpected(29 /* GreaterThanToken */); } else { - parseExpected(29, undefined, false); + parseExpected(29 /* GreaterThanToken */, /*diagnostic*/ undefined, /*shouldAdvance*/ false); scanJsxText(); } - node = createNode(256, fullStart); + node = createNode(256 /* JsxSelfClosingElement */, fullStart); } node.tagName = tagName; node.typeArguments = typeArguments; @@ -16233,119 +18849,125 @@ var ts; } function parseJsxElementName() { scanJsxIdentifier(); - var expression = token() === 99 ? + // JsxElement can have name in the form of + // propertyAccessExpression + // primaryExpression in the form of an identifier and "this" keyword + // We can't just simply use parseLeftHandSideExpressionOrHigher because then we will start consider class,function etc as a keyword + // We only want to consider "this" as a primaryExpression + var expression = token() === 99 /* ThisKeyword */ ? parseTokenNode() : parseIdentifierName(); - while (parseOptional(23)) { - var propertyAccess = createNode(185, expression.pos); + while (parseOptional(23 /* DotToken */)) { + var propertyAccess = createNode(185 /* PropertyAccessExpression */, expression.pos); propertyAccess.expression = expression; - propertyAccess.name = parseRightSideOfDot(true); + propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true); expression = finishNode(propertyAccess); } return expression; } function parseJsxExpression(inExpressionContext) { - var node = createNode(265); - if (!parseExpected(17)) { + var node = createNode(265 /* JsxExpression */); + if (!parseExpected(17 /* OpenBraceToken */)) { return undefined; } - if (token() !== 18) { - node.dotDotDotToken = parseOptionalToken(24); + if (token() !== 18 /* CloseBraceToken */) { + node.dotDotDotToken = parseOptionalToken(24 /* DotDotDotToken */); node.expression = parseAssignmentExpressionOrHigher(); } if (inExpressionContext) { - parseExpected(18); + parseExpected(18 /* CloseBraceToken */); } else { - parseExpected(18, undefined, false); + parseExpected(18 /* CloseBraceToken */, /*message*/ undefined, /*shouldAdvance*/ false); scanJsxText(); } return finishNode(node); } function parseJsxAttribute() { - if (token() === 17) { + if (token() === 17 /* OpenBraceToken */) { return parseJsxSpreadAttribute(); } scanJsxIdentifier(); - var node = createNode(262); + var node = createNode(262 /* JsxAttribute */); node.name = parseIdentifierName(); - if (token() === 58) { + if (token() === 58 /* EqualsToken */) { switch (scanJsxAttributeValue()) { - case 9: + case 9 /* StringLiteral */: node.initializer = parseLiteralNode(); break; default: - node.initializer = parseJsxExpression(true); + node.initializer = parseJsxExpression(/*inExpressionContext*/ true); break; } } return finishNode(node); } function parseJsxSpreadAttribute() { - var node = createNode(264); - parseExpected(17); - parseExpected(24); + var node = createNode(264 /* JsxSpreadAttribute */); + parseExpected(17 /* OpenBraceToken */); + parseExpected(24 /* DotDotDotToken */); node.expression = parseExpression(); - parseExpected(18); + parseExpected(18 /* CloseBraceToken */); return finishNode(node); } function parseJsxClosingElement(inExpressionContext) { - var node = createNode(258); - parseExpected(28); + var node = createNode(258 /* JsxClosingElement */); + parseExpected(28 /* LessThanSlashToken */); node.tagName = parseJsxElementName(); if (inExpressionContext) { - parseExpected(29); + parseExpected(29 /* GreaterThanToken */); } else { - parseExpected(29, undefined, false); + parseExpected(29 /* GreaterThanToken */, /*diagnostic*/ undefined, /*shouldAdvance*/ false); scanJsxText(); } return finishNode(node); } function parseJsxClosingFragment(inExpressionContext) { - var node = createNode(261); - parseExpected(28); + var node = createNode(261 /* JsxClosingFragment */); + parseExpected(28 /* LessThanSlashToken */); if (ts.tokenIsIdentifierOrKeyword(token())) { parseErrorAtRange(parseJsxElementName(), ts.Diagnostics.Expected_corresponding_closing_tag_for_JSX_fragment); } if (inExpressionContext) { - parseExpected(29); + parseExpected(29 /* GreaterThanToken */); } else { - parseExpected(29, undefined, false); + parseExpected(29 /* GreaterThanToken */, /*diagnostic*/ undefined, /*shouldAdvance*/ false); scanJsxText(); } return finishNode(node); } function parseTypeAssertion() { - var node = createNode(190); - parseExpected(27); + var node = createNode(190 /* TypeAssertionExpression */); + parseExpected(27 /* LessThanToken */); node.type = parseType(); - parseExpected(29); + parseExpected(29 /* GreaterThanToken */); node.expression = parseSimpleUnaryExpression(); return finishNode(node); } function parseMemberExpressionRest(expression) { while (true) { - var dotToken = parseOptionalToken(23); + var dotToken = parseOptionalToken(23 /* DotToken */); if (dotToken) { - var propertyAccess = createNode(185, expression.pos); + var propertyAccess = createNode(185 /* PropertyAccessExpression */, expression.pos); propertyAccess.expression = expression; - propertyAccess.name = parseRightSideOfDot(true); + propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true); expression = finishNode(propertyAccess); continue; } - if (token() === 51 && !scanner.hasPrecedingLineBreak()) { + if (token() === 51 /* ExclamationToken */ && !scanner.hasPrecedingLineBreak()) { nextToken(); - var nonNullExpression = createNode(209, expression.pos); + var nonNullExpression = createNode(209 /* NonNullExpression */, expression.pos); nonNullExpression.expression = expression; expression = finishNode(nonNullExpression); continue; } - if (!inDecoratorContext() && parseOptional(21)) { - var indexedAccess = createNode(186, expression.pos); + // when in the [Decorator] context, we do not parse ElementAccess as it could be part of a ComputedPropertyName + if (!inDecoratorContext() && parseOptional(21 /* OpenBracketToken */)) { + var indexedAccess = createNode(186 /* ElementAccessExpression */, expression.pos); indexedAccess.expression = expression; - if (token() === 22) { - indexedAccess.argumentExpression = createMissingNode(71, true, ts.Diagnostics.An_element_access_expression_should_take_an_argument); + if (token() === 22 /* CloseBracketToken */) { + indexedAccess.argumentExpression = createMissingNode(71 /* Identifier */, /*reportAtCurrentPosition*/ true, ts.Diagnostics.An_element_access_expression_should_take_an_argument); } else { var argument = allowInAnd(parseExpression); @@ -16354,25 +18976,25 @@ var ts; } indexedAccess.argumentExpression = argument; } - parseExpected(22); + parseExpected(22 /* CloseBracketToken */); expression = finishNode(indexedAccess); continue; } if (isTemplateStartOfTaggedTemplate()) { - expression = parseTaggedTemplateRest(expression, undefined); + expression = parseTaggedTemplateRest(expression, /*typeArguments*/ undefined); continue; } return expression; } } function isTemplateStartOfTaggedTemplate() { - return token() === 13 || token() === 14; + return token() === 13 /* NoSubstitutionTemplateLiteral */ || token() === 14 /* TemplateHead */; } function parseTaggedTemplateRest(tag, typeArguments) { - var tagExpression = createNode(189, tag.pos); + var tagExpression = createNode(189 /* TaggedTemplateExpression */, tag.pos); tagExpression.tag = tag; tagExpression.typeArguments = typeArguments; - tagExpression.template = token() === 13 + tagExpression.template = token() === 13 /* NoSubstitutionTemplateLiteral */ ? parseLiteralNode() : parseTemplateExpression(); return finishNode(tagExpression); @@ -16380,7 +19002,11 @@ var ts; function parseCallExpressionRest(expression) { while (true) { expression = parseMemberExpressionRest(expression); - if (token() === 27) { + if (token() === 27 /* LessThanToken */) { + // See if this is the start of a generic invocation. If so, consume it and + // keep checking for postfix expressions. Otherwise, it's just a '<' that's + // part of an arithmetic expression. Break out so we consume it higher in the + // stack. var typeArguments = tryParse(parseTypeArgumentsInExpression); if (!typeArguments) { return expression; @@ -16389,15 +19015,15 @@ var ts; expression = parseTaggedTemplateRest(expression, typeArguments); continue; } - var callExpr = createNode(187, expression.pos); + var callExpr = createNode(187 /* CallExpression */, expression.pos); callExpr.expression = expression; callExpr.typeArguments = typeArguments; callExpr.arguments = parseArgumentList(); expression = finishNode(callExpr); continue; } - else if (token() === 19) { - var callExpr = createNode(187, expression.pos); + else if (token() === 19 /* OpenParenToken */) { + var callExpr = createNode(187 /* CallExpression */, expression.pos); callExpr.expression = expression; callExpr.arguments = parseArgumentList(); expression = finishNode(callExpr); @@ -16407,191 +19033,217 @@ var ts; } } function parseArgumentList() { - parseExpected(19); - var result = parseDelimitedList(11, parseArgumentExpression); - parseExpected(20); + parseExpected(19 /* OpenParenToken */); + var result = parseDelimitedList(11 /* ArgumentExpressions */, parseArgumentExpression); + parseExpected(20 /* CloseParenToken */); return result; } function parseTypeArgumentsInExpression() { - if (!parseOptional(27)) { + if (!parseOptional(27 /* LessThanToken */)) { return undefined; } - var typeArguments = parseDelimitedList(19, parseType); - if (!parseExpected(29)) { + var typeArguments = parseDelimitedList(19 /* TypeArguments */, parseType); + if (!parseExpected(29 /* GreaterThanToken */)) { + // If it doesn't have the closing `>` then it's definitely not an type argument list. return undefined; } + // If we have a '<', then only parse this as a argument list if the type arguments + // are complete and we have an open paren. if we don't, rewind and return nothing. return typeArguments && canFollowTypeArgumentsInExpression() ? typeArguments : undefined; } function canFollowTypeArgumentsInExpression() { switch (token()) { - case 19: - case 13: - case 14: - case 23: - case 20: - case 22: - case 56: - case 25: - case 55: - case 32: - case 34: - case 33: - case 35: - case 53: - case 54: - case 50: - case 48: - case 49: - case 18: - case 1: + case 19 /* OpenParenToken */: // foo( + case 13 /* NoSubstitutionTemplateLiteral */: // foo `...` + case 14 /* TemplateHead */: // foo `...${100}...` + // these are the only tokens can legally follow a type argument + // list. So we definitely want to treat them as type arg lists. + case 23 /* DotToken */: // foo. + case 20 /* CloseParenToken */: // foo) + case 22 /* CloseBracketToken */: // foo] + case 56 /* ColonToken */: // foo: + case 25 /* SemicolonToken */: // foo; + case 55 /* QuestionToken */: // foo? + case 32 /* EqualsEqualsToken */: // foo == + case 34 /* EqualsEqualsEqualsToken */: // foo === + case 33 /* ExclamationEqualsToken */: // foo != + case 35 /* ExclamationEqualsEqualsToken */: // foo !== + case 53 /* AmpersandAmpersandToken */: // foo && + case 54 /* BarBarToken */: // foo || + case 50 /* CaretToken */: // foo ^ + case 48 /* AmpersandToken */: // foo & + case 49 /* BarToken */: // foo | + case 18 /* CloseBraceToken */: // foo } + case 1 /* EndOfFileToken */: // foo + // these cases can't legally follow a type arg list. However, they're not legal + // expressions either. The user is probably in the middle of a generic type. So + // treat it as such. return true; - case 26: - case 17: + case 26 /* CommaToken */: // foo, + case 17 /* OpenBraceToken */: // foo { + // We don't want to treat these as type arguments. Otherwise we'll parse this + // as an invocation expression. Instead, we want to parse out the expression + // in isolation from the type arguments. default: + // Anything else treat as an expression. return false; } } function parsePrimaryExpression() { switch (token()) { - case 8: - case 9: - case 13: + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: + case 13 /* NoSubstitutionTemplateLiteral */: return parseLiteralNode(); - case 99: - case 97: - case 95: - case 101: - case 86: + case 99 /* ThisKeyword */: + case 97 /* SuperKeyword */: + case 95 /* NullKeyword */: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: return parseTokenNode(); - case 19: + case 19 /* OpenParenToken */: return parseParenthesizedExpression(); - case 21: + case 21 /* OpenBracketToken */: return parseArrayLiteralExpression(); - case 17: + case 17 /* OpenBraceToken */: return parseObjectLiteralExpression(); - case 120: + case 120 /* AsyncKeyword */: + // Async arrow functions are parsed earlier in parseAssignmentExpressionOrHigher. + // If we encounter `async [no LineTerminator here] function` then this is an async + // function; otherwise, its an identifier. if (!lookAhead(nextTokenIsFunctionKeywordOnSameLine)) { break; } return parseFunctionExpression(); - case 75: + case 75 /* ClassKeyword */: return parseClassExpression(); - case 89: + case 89 /* FunctionKeyword */: return parseFunctionExpression(); - case 94: + case 94 /* NewKeyword */: return parseNewExpressionOrNewDotTarget(); - case 41: - case 63: - if (reScanSlashToken() === 12) { + case 41 /* SlashToken */: + case 63 /* SlashEqualsToken */: + if (reScanSlashToken() === 12 /* RegularExpressionLiteral */) { return parseLiteralNode(); } break; - case 14: + case 14 /* TemplateHead */: return parseTemplateExpression(); } return parseIdentifier(ts.Diagnostics.Expression_expected); } function parseParenthesizedExpression() { - var node = createNodeWithJSDoc(191); - parseExpected(19); + var node = createNodeWithJSDoc(191 /* ParenthesizedExpression */); + parseExpected(19 /* OpenParenToken */); node.expression = allowInAnd(parseExpression); - parseExpected(20); + parseExpected(20 /* CloseParenToken */); return finishNode(node); } function parseSpreadElement() { - var node = createNode(204); - parseExpected(24); + var node = createNode(204 /* SpreadElement */); + parseExpected(24 /* DotDotDotToken */); node.expression = parseAssignmentExpressionOrHigher(); return finishNode(node); } function parseArgumentOrArrayLiteralElement() { - return token() === 24 ? parseSpreadElement() : - token() === 26 ? createNode(206) : + return token() === 24 /* DotDotDotToken */ ? parseSpreadElement() : + token() === 26 /* CommaToken */ ? createNode(206 /* OmittedExpression */) : parseAssignmentExpressionOrHigher(); } function parseArgumentExpression() { return doOutsideOfContext(disallowInAndDecoratorContext, parseArgumentOrArrayLiteralElement); } function parseArrayLiteralExpression() { - var node = createNode(183); - parseExpected(21); + var node = createNode(183 /* ArrayLiteralExpression */); + parseExpected(21 /* OpenBracketToken */); if (scanner.hasPrecedingLineBreak()) { node.multiLine = true; } - node.elements = parseDelimitedList(15, parseArgumentOrArrayLiteralElement); - parseExpected(22); + node.elements = parseDelimitedList(15 /* ArrayLiteralMembers */, parseArgumentOrArrayLiteralElement); + parseExpected(22 /* CloseBracketToken */); return finishNode(node); } function parseObjectLiteralElement() { - var node = createNodeWithJSDoc(0); - if (parseOptionalToken(24)) { - node.kind = 272; + var node = createNodeWithJSDoc(0 /* Unknown */); + if (parseOptionalToken(24 /* DotDotDotToken */)) { + node.kind = 272 /* SpreadAssignment */; node.expression = parseAssignmentExpressionOrHigher(); return finishNode(node); } node.decorators = parseDecorators(); node.modifiers = parseModifiers(); - if (parseContextualModifier(125)) { - return parseAccessorDeclaration(node, 156); + if (parseContextualModifier(125 /* GetKeyword */)) { + return parseAccessorDeclaration(node, 156 /* GetAccessor */); } - if (parseContextualModifier(136)) { - return parseAccessorDeclaration(node, 157); + if (parseContextualModifier(136 /* SetKeyword */)) { + return parseAccessorDeclaration(node, 157 /* SetAccessor */); } - var asteriskToken = parseOptionalToken(39); + var asteriskToken = parseOptionalToken(39 /* AsteriskToken */); var tokenIsIdentifier = isIdentifier(); node.name = parsePropertyName(); - node.questionToken = parseOptionalToken(55); - if (asteriskToken || token() === 19 || token() === 27) { + // Disallowing of optional property assignments happens in the grammar checker. + node.questionToken = parseOptionalToken(55 /* QuestionToken */); + if (asteriskToken || token() === 19 /* OpenParenToken */ || token() === 27 /* LessThanToken */) { return parseMethodDeclaration(node, asteriskToken); } - var isShorthandPropertyAssignment = tokenIsIdentifier && (token() === 26 || token() === 18 || token() === 58); + // check if it is short-hand property assignment or normal property assignment + // NOTE: if token is EqualsToken it is interpreted as CoverInitializedName production + // CoverInitializedName[Yield] : + // IdentifierReference[?Yield] Initializer[In, ?Yield] + // this is necessary because ObjectLiteral productions are also used to cover grammar for ObjectAssignmentPattern + var isShorthandPropertyAssignment = tokenIsIdentifier && (token() === 26 /* CommaToken */ || token() === 18 /* CloseBraceToken */ || token() === 58 /* EqualsToken */); if (isShorthandPropertyAssignment) { - node.kind = 271; - var equalsToken = parseOptionalToken(58); + node.kind = 271 /* ShorthandPropertyAssignment */; + var equalsToken = parseOptionalToken(58 /* EqualsToken */); if (equalsToken) { node.equalsToken = equalsToken; node.objectAssignmentInitializer = allowInAnd(parseAssignmentExpressionOrHigher); } } else { - node.kind = 270; - parseExpected(56); + node.kind = 270 /* PropertyAssignment */; + parseExpected(56 /* ColonToken */); node.initializer = allowInAnd(parseAssignmentExpressionOrHigher); } return finishNode(node); } function parseObjectLiteralExpression() { - var node = createNode(184); - parseExpected(17); + var node = createNode(184 /* ObjectLiteralExpression */); + parseExpected(17 /* OpenBraceToken */); if (scanner.hasPrecedingLineBreak()) { node.multiLine = true; } - node.properties = parseDelimitedList(12, parseObjectLiteralElement, true); - parseExpected(18); + node.properties = parseDelimitedList(12 /* ObjectLiteralMembers */, parseObjectLiteralElement, /*considerSemicolonAsDelimiter*/ true); + parseExpected(18 /* CloseBraceToken */); return finishNode(node); } function parseFunctionExpression() { + // GeneratorExpression: + // function* BindingIdentifier [Yield][opt](FormalParameters[Yield]){ GeneratorBody } + // + // FunctionExpression: + // function BindingIdentifier[opt](FormalParameters){ FunctionBody } var saveDecoratorContext = inDecoratorContext(); if (saveDecoratorContext) { - setDecoratorContext(false); + setDecoratorContext(/*val*/ false); } - var node = createNodeWithJSDoc(192); + var node = createNodeWithJSDoc(192 /* FunctionExpression */); node.modifiers = parseModifiers(); - parseExpected(89); - node.asteriskToken = parseOptionalToken(39); - var isGenerator = node.asteriskToken ? 1 : 0; - var isAsync = ts.hasModifier(node, 256) ? 2 : 0; + parseExpected(89 /* FunctionKeyword */); + node.asteriskToken = parseOptionalToken(39 /* AsteriskToken */); + var isGenerator = node.asteriskToken ? 1 /* Yield */ : 0 /* None */; + var isAsync = ts.hasModifier(node, 256 /* Async */) ? 2 /* Await */ : 0 /* None */; node.name = isGenerator && isAsync ? doInYieldAndAwaitContext(parseOptionalIdentifier) : isGenerator ? doInYieldContext(parseOptionalIdentifier) : isAsync ? doInAwaitContext(parseOptionalIdentifier) : parseOptionalIdentifier(); - fillSignature(56, isGenerator | isAsync, node); + fillSignature(56 /* ColonToken */, isGenerator | isAsync, node); node.body = parseFunctionBlock(isGenerator | isAsync); if (saveDecoratorContext) { - setDecoratorContext(true); + setDecoratorContext(/*val*/ true); } return finishNode(node); } @@ -16600,10 +19252,10 @@ var ts; } function parseNewExpressionOrNewDotTarget() { var fullStart = scanner.getStartPos(); - parseExpected(94); - if (parseOptional(23)) { - var node_2 = createNode(210, fullStart); - node_2.keywordToken = 94; + parseExpected(94 /* NewKeyword */); + if (parseOptional(23 /* DotToken */)) { + var node_2 = createNode(210 /* MetaProperty */, fullStart); + node_2.keywordToken = 94 /* NewKeyword */; node_2.name = parseIdentifierName(); return finishNode(node_2); } @@ -16619,22 +19271,23 @@ var ts; } break; } - var node = createNode(188, fullStart); + var node = createNode(188 /* NewExpression */, fullStart); node.expression = expression; node.typeArguments = typeArguments; - if (node.typeArguments || token() === 19) { + if (node.typeArguments || token() === 19 /* OpenParenToken */) { node.arguments = parseArgumentList(); } return finishNode(node); } + // STATEMENTS function parseBlock(ignoreMissingOpenBrace, diagnosticMessage) { - var node = createNode(213); - if (parseExpected(17, diagnosticMessage) || ignoreMissingOpenBrace) { + var node = createNode(213 /* Block */); + if (parseExpected(17 /* OpenBraceToken */, diagnosticMessage) || ignoreMissingOpenBrace) { if (scanner.hasPrecedingLineBreak()) { node.multiLine = true; } - node.statements = parseList(1, parseStatement); - parseExpected(18); + node.statements = parseList(1 /* BlockStatements */, parseStatement); + parseExpected(18 /* CloseBraceToken */); } else { node.statements = createMissingList(); @@ -16643,98 +19296,104 @@ var ts; } function parseFunctionBlock(flags, diagnosticMessage) { var savedYieldContext = inYieldContext(); - setYieldContext(!!(flags & 1)); + setYieldContext(!!(flags & 1 /* Yield */)); var savedAwaitContext = inAwaitContext(); - setAwaitContext(!!(flags & 2)); + setAwaitContext(!!(flags & 2 /* Await */)); + // We may be in a [Decorator] context when parsing a function expression or + // arrow function. The body of the function is not in [Decorator] context. var saveDecoratorContext = inDecoratorContext(); if (saveDecoratorContext) { - setDecoratorContext(false); + setDecoratorContext(/*val*/ false); } - var block = parseBlock(!!(flags & 16), diagnosticMessage); + var block = parseBlock(!!(flags & 16 /* IgnoreMissingOpenBrace */), diagnosticMessage); if (saveDecoratorContext) { - setDecoratorContext(true); + setDecoratorContext(/*val*/ true); } setYieldContext(savedYieldContext); setAwaitContext(savedAwaitContext); return block; } function parseEmptyStatement() { - var node = createNode(215); - parseExpected(25); + var node = createNode(215 /* EmptyStatement */); + parseExpected(25 /* SemicolonToken */); return finishNode(node); } function parseIfStatement() { - var node = createNode(217); - parseExpected(90); - parseExpected(19); + var node = createNode(217 /* IfStatement */); + parseExpected(90 /* IfKeyword */); + parseExpected(19 /* OpenParenToken */); node.expression = allowInAnd(parseExpression); - parseExpected(20); + parseExpected(20 /* CloseParenToken */); node.thenStatement = parseStatement(); - node.elseStatement = parseOptional(82) ? parseStatement() : undefined; + node.elseStatement = parseOptional(82 /* ElseKeyword */) ? parseStatement() : undefined; return finishNode(node); } function parseDoStatement() { - var node = createNode(218); - parseExpected(81); + var node = createNode(218 /* DoStatement */); + parseExpected(81 /* DoKeyword */); node.statement = parseStatement(); - parseExpected(106); - parseExpected(19); + parseExpected(106 /* WhileKeyword */); + parseExpected(19 /* OpenParenToken */); node.expression = allowInAnd(parseExpression); - parseExpected(20); - parseOptional(25); + parseExpected(20 /* CloseParenToken */); + // From: https://mail.mozilla.org/pipermail/es-discuss/2011-August/016188.html + // 157 min --- All allen at wirfs-brock.com CONF --- "do{;}while(false)false" prohibited in + // spec but allowed in consensus reality. Approved -- this is the de-facto standard whereby + // do;while(0)x will have a semicolon inserted before x. + parseOptional(25 /* SemicolonToken */); return finishNode(node); } function parseWhileStatement() { - var node = createNode(219); - parseExpected(106); - parseExpected(19); + var node = createNode(219 /* WhileStatement */); + parseExpected(106 /* WhileKeyword */); + parseExpected(19 /* OpenParenToken */); node.expression = allowInAnd(parseExpression); - parseExpected(20); + parseExpected(20 /* CloseParenToken */); node.statement = parseStatement(); return finishNode(node); } function parseForOrForInOrForOfStatement() { var pos = getNodePos(); - parseExpected(88); - var awaitToken = parseOptionalToken(121); - parseExpected(19); + parseExpected(88 /* ForKeyword */); + var awaitToken = parseOptionalToken(121 /* AwaitKeyword */); + parseExpected(19 /* OpenParenToken */); var initializer; - if (token() !== 25) { - if (token() === 104 || token() === 110 || token() === 76) { - initializer = parseVariableDeclarationList(true); + if (token() !== 25 /* SemicolonToken */) { + if (token() === 104 /* VarKeyword */ || token() === 110 /* LetKeyword */ || token() === 76 /* ConstKeyword */) { + initializer = parseVariableDeclarationList(/*inForStatementInitializer*/ true); } else { initializer = disallowInAnd(parseExpression); } } var forOrForInOrForOfStatement; - if (awaitToken ? parseExpected(145) : parseOptional(145)) { - var forOfStatement = createNode(222, pos); + if (awaitToken ? parseExpected(145 /* OfKeyword */) : parseOptional(145 /* OfKeyword */)) { + var forOfStatement = createNode(222 /* ForOfStatement */, pos); forOfStatement.awaitModifier = awaitToken; forOfStatement.initializer = initializer; forOfStatement.expression = allowInAnd(parseAssignmentExpressionOrHigher); - parseExpected(20); + parseExpected(20 /* CloseParenToken */); forOrForInOrForOfStatement = forOfStatement; } - else if (parseOptional(92)) { - var forInStatement = createNode(221, pos); + else if (parseOptional(92 /* InKeyword */)) { + var forInStatement = createNode(221 /* ForInStatement */, pos); forInStatement.initializer = initializer; forInStatement.expression = allowInAnd(parseExpression); - parseExpected(20); + parseExpected(20 /* CloseParenToken */); forOrForInOrForOfStatement = forInStatement; } else { - var forStatement = createNode(220, pos); + var forStatement = createNode(220 /* ForStatement */, pos); forStatement.initializer = initializer; - parseExpected(25); - if (token() !== 25 && token() !== 20) { + parseExpected(25 /* SemicolonToken */); + if (token() !== 25 /* SemicolonToken */ && token() !== 20 /* CloseParenToken */) { forStatement.condition = allowInAnd(parseExpression); } - parseExpected(25); - if (token() !== 20) { + parseExpected(25 /* SemicolonToken */); + if (token() !== 20 /* CloseParenToken */) { forStatement.incrementor = allowInAnd(parseExpression); } - parseExpected(20); + parseExpected(20 /* CloseParenToken */); forOrForInOrForOfStatement = forStatement; } forOrForInOrForOfStatement.statement = parseStatement(); @@ -16742,7 +19401,7 @@ var ts; } function parseBreakOrContinueStatement(kind) { var node = createNode(kind); - parseExpected(kind === 224 ? 72 : 77); + parseExpected(kind === 224 /* BreakStatement */ ? 72 /* BreakKeyword */ : 77 /* ContinueKeyword */); if (!canParseSemicolon()) { node.label = parseIdentifier(); } @@ -16750,8 +19409,8 @@ var ts; return finishNode(node); } function parseReturnStatement() { - var node = createNode(225); - parseExpected(96); + var node = createNode(225 /* ReturnStatement */); + parseExpected(96 /* ReturnKeyword */); if (!canParseSemicolon()) { node.expression = allowInAnd(parseExpression); } @@ -16759,92 +19418,106 @@ var ts; return finishNode(node); } function parseWithStatement() { - var node = createNode(226); - parseExpected(107); - parseExpected(19); + var node = createNode(226 /* WithStatement */); + parseExpected(107 /* WithKeyword */); + parseExpected(19 /* OpenParenToken */); node.expression = allowInAnd(parseExpression); - parseExpected(20); - node.statement = doInsideOfContext(8388608, parseStatement); + parseExpected(20 /* CloseParenToken */); + node.statement = doInsideOfContext(8388608 /* InWithStatement */, parseStatement); return finishNode(node); } function parseCaseClause() { - var node = createNode(266); - parseExpected(73); + var node = createNode(266 /* CaseClause */); + parseExpected(73 /* CaseKeyword */); node.expression = allowInAnd(parseExpression); - parseExpected(56); - node.statements = parseList(3, parseStatement); + parseExpected(56 /* ColonToken */); + node.statements = parseList(3 /* SwitchClauseStatements */, parseStatement); return finishNode(node); } function parseDefaultClause() { - var node = createNode(267); - parseExpected(79); - parseExpected(56); - node.statements = parseList(3, parseStatement); + var node = createNode(267 /* DefaultClause */); + parseExpected(79 /* DefaultKeyword */); + parseExpected(56 /* ColonToken */); + node.statements = parseList(3 /* SwitchClauseStatements */, parseStatement); return finishNode(node); } function parseCaseOrDefaultClause() { - return token() === 73 ? parseCaseClause() : parseDefaultClause(); + return token() === 73 /* CaseKeyword */ ? parseCaseClause() : parseDefaultClause(); } function parseSwitchStatement() { - var node = createNode(227); - parseExpected(98); - parseExpected(19); + var node = createNode(227 /* SwitchStatement */); + parseExpected(98 /* SwitchKeyword */); + parseExpected(19 /* OpenParenToken */); node.expression = allowInAnd(parseExpression); - parseExpected(20); - var caseBlock = createNode(241); - parseExpected(17); - caseBlock.clauses = parseList(2, parseCaseOrDefaultClause); - parseExpected(18); + parseExpected(20 /* CloseParenToken */); + var caseBlock = createNode(241 /* CaseBlock */); + parseExpected(17 /* OpenBraceToken */); + caseBlock.clauses = parseList(2 /* SwitchClauses */, parseCaseOrDefaultClause); + parseExpected(18 /* CloseBraceToken */); node.caseBlock = finishNode(caseBlock); return finishNode(node); } function parseThrowStatement() { - var node = createNode(229); - parseExpected(100); + // ThrowStatement[Yield] : + // throw [no LineTerminator here]Expression[In, ?Yield]; + // Because of automatic semicolon insertion, we need to report error if this + // throw could be terminated with a semicolon. Note: we can't call 'parseExpression' + // directly as that might consume an expression on the following line. + // We just return 'undefined' in that case. The actual error will be reported in the + // grammar walker. + var node = createNode(229 /* ThrowStatement */); + parseExpected(100 /* ThrowKeyword */); node.expression = scanner.hasPrecedingLineBreak() ? undefined : allowInAnd(parseExpression); parseSemicolon(); return finishNode(node); } + // TODO: Review for error recovery function parseTryStatement() { - var node = createNode(230); - parseExpected(102); - node.tryBlock = parseBlock(false); - node.catchClause = token() === 74 ? parseCatchClause() : undefined; - if (!node.catchClause || token() === 87) { - parseExpected(87); - node.finallyBlock = parseBlock(false); + var node = createNode(230 /* TryStatement */); + parseExpected(102 /* TryKeyword */); + node.tryBlock = parseBlock(/*ignoreMissingOpenBrace*/ false); + node.catchClause = token() === 74 /* CatchKeyword */ ? parseCatchClause() : undefined; + // If we don't have a catch clause, then we must have a finally clause. Try to parse + // one out no matter what. + if (!node.catchClause || token() === 87 /* FinallyKeyword */) { + parseExpected(87 /* FinallyKeyword */); + node.finallyBlock = parseBlock(/*ignoreMissingOpenBrace*/ false); } return finishNode(node); } function parseCatchClause() { - var result = createNode(269); - parseExpected(74); - if (parseOptional(19)) { + var result = createNode(269 /* CatchClause */); + parseExpected(74 /* CatchKeyword */); + if (parseOptional(19 /* OpenParenToken */)) { result.variableDeclaration = parseVariableDeclaration(); - parseExpected(20); + parseExpected(20 /* CloseParenToken */); } else { + // Keep shape of node to avoid degrading performance. result.variableDeclaration = undefined; } - result.block = parseBlock(false); + result.block = parseBlock(/*ignoreMissingOpenBrace*/ false); return finishNode(result); } function parseDebuggerStatement() { - var node = createNode(231); - parseExpected(78); + var node = createNode(231 /* DebuggerStatement */); + parseExpected(78 /* DebuggerKeyword */); parseSemicolon(); return finishNode(node); } function parseExpressionOrLabeledStatement() { - var node = createNodeWithJSDoc(0); + // Avoiding having to do the lookahead for a labeled statement by just trying to parse + // out an expression, seeing if it is identifier and then seeing if it is followed by + // a colon. + var node = createNodeWithJSDoc(0 /* Unknown */); var expression = allowInAnd(parseExpression); - if (expression.kind === 71 && parseOptional(56)) { - node.kind = 228; + if (expression.kind === 71 /* Identifier */ && parseOptional(56 /* ColonToken */)) { + node.kind = 228 /* LabeledStatement */; node.label = expression; node.statement = parseStatement(); } else { - node.kind = 216; + node.kind = 216 /* ExpressionStatement */; node.expression = expression; parseSemicolon(); } @@ -16856,60 +19529,82 @@ var ts; } function nextTokenIsClassKeywordOnSameLine() { nextToken(); - return token() === 75 && !scanner.hasPrecedingLineBreak(); + return token() === 75 /* ClassKeyword */ && !scanner.hasPrecedingLineBreak(); } function nextTokenIsFunctionKeywordOnSameLine() { nextToken(); - return token() === 89 && !scanner.hasPrecedingLineBreak(); + return token() === 89 /* FunctionKeyword */ && !scanner.hasPrecedingLineBreak(); } function nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine() { nextToken(); - return (ts.tokenIsIdentifierOrKeyword(token()) || token() === 8 || token() === 9) && !scanner.hasPrecedingLineBreak(); + return (ts.tokenIsIdentifierOrKeyword(token()) || token() === 8 /* NumericLiteral */ || token() === 9 /* StringLiteral */) && !scanner.hasPrecedingLineBreak(); } function isDeclaration() { while (true) { switch (token()) { - case 104: - case 110: - case 76: - case 89: - case 75: - case 83: + case 104 /* VarKeyword */: + case 110 /* LetKeyword */: + case 76 /* ConstKeyword */: + case 89 /* FunctionKeyword */: + case 75 /* ClassKeyword */: + case 83 /* EnumKeyword */: return true; - case 109: - case 139: + // 'declare', 'module', 'namespace', 'interface'* and 'type' are all legal JavaScript identifiers; + // however, an identifier cannot be followed by another identifier on the same line. This is what we + // count on to parse out the respective declarations. For instance, we exploit this to say that + // + // namespace n + // + // can be none other than the beginning of a namespace declaration, but need to respect that JavaScript sees + // + // namespace + // n + // + // as the identifier 'namespace' on one line followed by the identifier 'n' on another. + // We need to look one token ahead to see if it permissible to try parsing a declaration. + // + // *Note*: 'interface' is actually a strict mode reserved word. So while + // + // "use strict" + // interface + // I {} + // + // could be legal, it would add complexity for very little gain. + case 109 /* InterfaceKeyword */: + case 139 /* TypeKeyword */: return nextTokenIsIdentifierOnSameLine(); - case 129: - case 130: + case 129 /* ModuleKeyword */: + case 130 /* NamespaceKeyword */: return nextTokenIsIdentifierOrStringLiteralOnSameLine(); - case 117: - case 120: - case 124: - case 112: - case 113: - case 114: - case 132: + case 117 /* AbstractKeyword */: + case 120 /* AsyncKeyword */: + case 124 /* DeclareKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: + case 114 /* PublicKeyword */: + case 132 /* ReadonlyKeyword */: nextToken(); + // ASI takes effect for this modifier. if (scanner.hasPrecedingLineBreak()) { return false; } continue; - case 144: + case 144 /* GlobalKeyword */: nextToken(); - return token() === 17 || token() === 71 || token() === 84; - case 91: + return token() === 17 /* OpenBraceToken */ || token() === 71 /* Identifier */ || token() === 84 /* ExportKeyword */; + case 91 /* ImportKeyword */: nextToken(); - return token() === 9 || token() === 39 || - token() === 17 || ts.tokenIsIdentifierOrKeyword(token()); - case 84: + return token() === 9 /* StringLiteral */ || token() === 39 /* AsteriskToken */ || + token() === 17 /* OpenBraceToken */ || ts.tokenIsIdentifierOrKeyword(token()); + case 84 /* ExportKeyword */: nextToken(); - if (token() === 58 || token() === 39 || - token() === 17 || token() === 79 || - token() === 118) { + if (token() === 58 /* EqualsToken */ || token() === 39 /* AsteriskToken */ || + token() === 17 /* OpenBraceToken */ || token() === 79 /* DefaultKeyword */ || + token() === 118 /* AsKeyword */) { return true; } continue; - case 115: + case 115 /* StaticKeyword */: nextToken(); continue; default: @@ -16922,47 +19617,52 @@ var ts; } function isStartOfStatement() { switch (token()) { - case 57: - case 25: - case 17: - case 104: - case 110: - case 89: - case 75: - case 83: - case 90: - case 81: - case 106: - case 88: - case 77: - case 72: - case 96: - case 107: - case 98: - case 100: - case 102: - case 78: - case 74: - case 87: + case 57 /* AtToken */: + case 25 /* SemicolonToken */: + case 17 /* OpenBraceToken */: + case 104 /* VarKeyword */: + case 110 /* LetKeyword */: + case 89 /* FunctionKeyword */: + case 75 /* ClassKeyword */: + case 83 /* EnumKeyword */: + case 90 /* IfKeyword */: + case 81 /* DoKeyword */: + case 106 /* WhileKeyword */: + case 88 /* ForKeyword */: + case 77 /* ContinueKeyword */: + case 72 /* BreakKeyword */: + case 96 /* ReturnKeyword */: + case 107 /* WithKeyword */: + case 98 /* SwitchKeyword */: + case 100 /* ThrowKeyword */: + case 102 /* TryKeyword */: + case 78 /* DebuggerKeyword */: + // 'catch' and 'finally' do not actually indicate that the code is part of a statement, + // however, we say they are here so that we may gracefully parse them and error later. + case 74 /* CatchKeyword */: + case 87 /* FinallyKeyword */: return true; - case 91: + case 91 /* ImportKeyword */: return isStartOfDeclaration() || lookAhead(nextTokenIsOpenParenOrLessThanOrDot); - case 76: - case 84: + case 76 /* ConstKeyword */: + case 84 /* ExportKeyword */: return isStartOfDeclaration(); - case 120: - case 124: - case 109: - case 129: - case 130: - case 139: - case 144: + case 120 /* AsyncKeyword */: + case 124 /* DeclareKeyword */: + case 109 /* InterfaceKeyword */: + case 129 /* ModuleKeyword */: + case 130 /* NamespaceKeyword */: + case 139 /* TypeKeyword */: + case 144 /* GlobalKeyword */: + // When these don't start a declaration, they're an identifier in an expression statement return true; - case 114: - case 112: - case 113: - case 115: - case 132: + case 114 /* PublicKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: + case 115 /* StaticKeyword */: + case 132 /* ReadonlyKeyword */: + // When these don't start a declaration, they may be the start of a class member if an identifier + // immediately follows. Otherwise they're an identifier in an expression statement. return isStartOfDeclaration() || !lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine); default: return isStartOfExpression(); @@ -16970,73 +19670,76 @@ var ts; } function nextTokenIsIdentifierOrStartOfDestructuring() { nextToken(); - return isIdentifier() || token() === 17 || token() === 21; + return isIdentifier() || token() === 17 /* OpenBraceToken */ || token() === 21 /* OpenBracketToken */; } function isLetDeclaration() { + // In ES6 'let' always starts a lexical declaration if followed by an identifier or { + // or [. return lookAhead(nextTokenIsIdentifierOrStartOfDestructuring); } function parseStatement() { switch (token()) { - case 25: + case 25 /* SemicolonToken */: return parseEmptyStatement(); - case 17: - return parseBlock(false); - case 104: - return parseVariableStatement(createNodeWithJSDoc(232)); - case 110: + case 17 /* OpenBraceToken */: + return parseBlock(/*ignoreMissingOpenBrace*/ false); + case 104 /* VarKeyword */: + return parseVariableStatement(createNodeWithJSDoc(232 /* VariableDeclaration */)); + case 110 /* LetKeyword */: if (isLetDeclaration()) { - return parseVariableStatement(createNodeWithJSDoc(232)); + return parseVariableStatement(createNodeWithJSDoc(232 /* VariableDeclaration */)); } break; - case 89: - return parseFunctionDeclaration(createNodeWithJSDoc(234)); - case 75: - return parseClassDeclaration(createNodeWithJSDoc(235)); - case 90: + case 89 /* FunctionKeyword */: + return parseFunctionDeclaration(createNodeWithJSDoc(234 /* FunctionDeclaration */)); + case 75 /* ClassKeyword */: + return parseClassDeclaration(createNodeWithJSDoc(235 /* ClassDeclaration */)); + case 90 /* IfKeyword */: return parseIfStatement(); - case 81: + case 81 /* DoKeyword */: return parseDoStatement(); - case 106: + case 106 /* WhileKeyword */: return parseWhileStatement(); - case 88: + case 88 /* ForKeyword */: return parseForOrForInOrForOfStatement(); - case 77: - return parseBreakOrContinueStatement(223); - case 72: - return parseBreakOrContinueStatement(224); - case 96: + case 77 /* ContinueKeyword */: + return parseBreakOrContinueStatement(223 /* ContinueStatement */); + case 72 /* BreakKeyword */: + return parseBreakOrContinueStatement(224 /* BreakStatement */); + case 96 /* ReturnKeyword */: return parseReturnStatement(); - case 107: + case 107 /* WithKeyword */: return parseWithStatement(); - case 98: + case 98 /* SwitchKeyword */: return parseSwitchStatement(); - case 100: + case 100 /* ThrowKeyword */: return parseThrowStatement(); - case 102: - case 74: - case 87: + case 102 /* TryKeyword */: + // Include 'catch' and 'finally' for error recovery. + case 74 /* CatchKeyword */: + case 87 /* FinallyKeyword */: return parseTryStatement(); - case 78: + case 78 /* DebuggerKeyword */: return parseDebuggerStatement(); - case 57: + case 57 /* AtToken */: return parseDeclaration(); - case 120: - case 109: - case 139: - case 129: - case 130: - case 124: - case 76: - case 83: - case 84: - case 91: - case 112: - case 113: - case 114: - case 117: - case 115: - case 132: - case 144: + case 120 /* AsyncKeyword */: + case 109 /* InterfaceKeyword */: + case 139 /* TypeKeyword */: + case 129 /* ModuleKeyword */: + case 130 /* NamespaceKeyword */: + case 124 /* DeclareKeyword */: + case 76 /* ConstKeyword */: + case 83 /* EnumKeyword */: + case 84 /* ExportKeyword */: + case 91 /* ImportKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: + case 114 /* PublicKeyword */: + case 117 /* AbstractKeyword */: + case 115 /* StaticKeyword */: + case 132 /* ReadonlyKeyword */: + case 144 /* GlobalKeyword */: if (isStartOfDeclaration()) { return parseDeclaration(); } @@ -17045,18 +19748,18 @@ var ts; return parseExpressionOrLabeledStatement(); } function isDeclareModifier(modifier) { - return modifier.kind === 124; + return modifier.kind === 124 /* DeclareKeyword */; } function parseDeclaration() { - var node = createNodeWithJSDoc(0); + var node = createNodeWithJSDoc(0 /* Unknown */); node.decorators = parseDecorators(); node.modifiers = parseModifiers(); if (ts.some(node.modifiers, isDeclareModifier)) { for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { var m = _a[_i]; - m.flags |= 4194304; + m.flags |= 4194304 /* Ambient */; } - return doInsideOfContext(4194304, function () { return parseDeclarationWorker(node); }); + return doInsideOfContext(4194304 /* Ambient */, function () { return parseDeclarationWorker(node); }); } else { return parseDeclarationWorker(node); @@ -17064,79 +19767,82 @@ var ts; } function parseDeclarationWorker(node) { switch (token()) { - case 104: - case 110: - case 76: + case 104 /* VarKeyword */: + case 110 /* LetKeyword */: + case 76 /* ConstKeyword */: return parseVariableStatement(node); - case 89: + case 89 /* FunctionKeyword */: return parseFunctionDeclaration(node); - case 75: + case 75 /* ClassKeyword */: return parseClassDeclaration(node); - case 109: + case 109 /* InterfaceKeyword */: return parseInterfaceDeclaration(node); - case 139: + case 139 /* TypeKeyword */: return parseTypeAliasDeclaration(node); - case 83: + case 83 /* EnumKeyword */: return parseEnumDeclaration(node); - case 144: - case 129: - case 130: + case 144 /* GlobalKeyword */: + case 129 /* ModuleKeyword */: + case 130 /* NamespaceKeyword */: return parseModuleDeclaration(node); - case 91: + case 91 /* ImportKeyword */: return parseImportDeclarationOrImportEqualsDeclaration(node); - case 84: + case 84 /* ExportKeyword */: nextToken(); switch (token()) { - case 79: - case 58: + case 79 /* DefaultKeyword */: + case 58 /* EqualsToken */: return parseExportAssignment(node); - case 118: + case 118 /* AsKeyword */: return parseNamespaceExportDeclaration(node); default: return parseExportDeclaration(node); } default: if (node.decorators || node.modifiers) { - var missing = createMissingNode(253, true, ts.Diagnostics.Declaration_expected); + // We reached this point because we encountered decorators and/or modifiers and assumed a declaration + // would follow. For recovery and error reporting purposes, return an incomplete declaration. + var missing = createMissingNode(253 /* MissingDeclaration */, /*reportAtCurrentPosition*/ true, ts.Diagnostics.Declaration_expected); missing.pos = node.pos; missing.decorators = node.decorators; missing.modifiers = node.modifiers; return finishNode(missing); } - return undefined; + return undefined; // TODO: GH#18217 } } function nextTokenIsIdentifierOrStringLiteralOnSameLine() { nextToken(); - return !scanner.hasPrecedingLineBreak() && (isIdentifier() || token() === 9); + return !scanner.hasPrecedingLineBreak() && (isIdentifier() || token() === 9 /* StringLiteral */); } function parseFunctionBlockOrSemicolon(flags, diagnosticMessage) { - if (token() !== 17 && canParseSemicolon()) { + if (token() !== 17 /* OpenBraceToken */ && canParseSemicolon()) { parseSemicolon(); return; } return parseFunctionBlock(flags, diagnosticMessage); } + // DECLARATIONS function parseArrayBindingElement() { - if (token() === 26) { - return createNode(206); + if (token() === 26 /* CommaToken */) { + return createNode(206 /* OmittedExpression */); } - var node = createNode(182); - node.dotDotDotToken = parseOptionalToken(24); + var node = createNode(182 /* BindingElement */); + node.dotDotDotToken = parseOptionalToken(24 /* DotDotDotToken */); node.name = parseIdentifierOrPattern(); node.initializer = parseInitializer(); return finishNode(node); } function parseObjectBindingElement() { - var node = createNode(182); - node.dotDotDotToken = parseOptionalToken(24); + var node = createNode(182 /* BindingElement */); + node.dotDotDotToken = parseOptionalToken(24 /* DotDotDotToken */); var tokenIsIdentifier = isIdentifier(); var propertyName = parsePropertyName(); - if (tokenIsIdentifier && token() !== 56) { + if (tokenIsIdentifier && token() !== 56 /* ColonToken */) { node.name = propertyName; } else { - parseExpected(56); + parseExpected(56 /* ColonToken */); node.propertyName = propertyName; node.name = parseIdentifierOrPattern(); } @@ -17144,39 +19850,39 @@ var ts; return finishNode(node); } function parseObjectBindingPattern() { - var node = createNode(180); - parseExpected(17); - node.elements = parseDelimitedList(9, parseObjectBindingElement); - parseExpected(18); + var node = createNode(180 /* ObjectBindingPattern */); + parseExpected(17 /* OpenBraceToken */); + node.elements = parseDelimitedList(9 /* ObjectBindingElements */, parseObjectBindingElement); + parseExpected(18 /* CloseBraceToken */); return finishNode(node); } function parseArrayBindingPattern() { - var node = createNode(181); - parseExpected(21); - node.elements = parseDelimitedList(10, parseArrayBindingElement); - parseExpected(22); + var node = createNode(181 /* ArrayBindingPattern */); + parseExpected(21 /* OpenBracketToken */); + node.elements = parseDelimitedList(10 /* ArrayBindingElements */, parseArrayBindingElement); + parseExpected(22 /* CloseBracketToken */); return finishNode(node); } function isIdentifierOrPattern() { - return token() === 17 || token() === 21 || isIdentifier(); + return token() === 17 /* OpenBraceToken */ || token() === 21 /* OpenBracketToken */ || isIdentifier(); } function parseIdentifierOrPattern() { - if (token() === 21) { + if (token() === 21 /* OpenBracketToken */) { return parseArrayBindingPattern(); } - if (token() === 17) { + if (token() === 17 /* OpenBraceToken */) { return parseObjectBindingPattern(); } return parseIdentifier(); } function parseVariableDeclarationAllowExclamation() { - return parseVariableDeclaration(true); + return parseVariableDeclaration(/*allowExclamation*/ true); } function parseVariableDeclaration(allowExclamation) { - var node = createNode(232); + var node = createNode(232 /* VariableDeclaration */); node.name = parseIdentifierOrPattern(); - if (allowExclamation && node.name.kind === 71 && - token() === 51 && !scanner.hasPrecedingLineBreak()) { + if (allowExclamation && node.name.kind === 71 /* Identifier */ && + token() === 51 /* ExclamationToken */ && !scanner.hasPrecedingLineBreak()) { node.exclamationToken = parseTokenNode(); } node.type = parseTypeAnnotation(); @@ -17186,84 +19892,104 @@ var ts; return finishNode(node); } function parseVariableDeclarationList(inForStatementInitializer) { - var node = createNode(233); + var node = createNode(233 /* VariableDeclarationList */); switch (token()) { - case 104: + case 104 /* VarKeyword */: break; - case 110: - node.flags |= 1; + case 110 /* LetKeyword */: + node.flags |= 1 /* Let */; break; - case 76: - node.flags |= 2; + case 76 /* ConstKeyword */: + node.flags |= 2 /* Const */; break; default: ts.Debug.fail(); } nextToken(); - if (token() === 145 && lookAhead(canFollowContextualOfKeyword)) { + // The user may have written the following: + // + // for (let of X) { } + // + // In this case, we want to parse an empty declaration list, and then parse 'of' + // as a keyword. The reason this is not automatic is that 'of' is a valid identifier. + // So we need to look ahead to determine if 'of' should be treated as a keyword in + // this context. + // The checker will then give an error that there is an empty declaration list. + if (token() === 145 /* OfKeyword */ && lookAhead(canFollowContextualOfKeyword)) { node.declarations = createMissingList(); } else { var savedDisallowIn = inDisallowInContext(); setDisallowInContext(inForStatementInitializer); - node.declarations = parseDelimitedList(8, inForStatementInitializer ? parseVariableDeclaration : parseVariableDeclarationAllowExclamation); + node.declarations = parseDelimitedList(8 /* VariableDeclarations */, inForStatementInitializer ? parseVariableDeclaration : parseVariableDeclarationAllowExclamation); setDisallowInContext(savedDisallowIn); } return finishNode(node); } function canFollowContextualOfKeyword() { - return nextTokenIsIdentifier() && nextToken() === 20; + return nextTokenIsIdentifier() && nextToken() === 20 /* CloseParenToken */; } function parseVariableStatement(node) { - node.kind = 214; - node.declarationList = parseVariableDeclarationList(false); + node.kind = 214 /* VariableStatement */; + node.declarationList = parseVariableDeclarationList(/*inForStatementInitializer*/ false); parseSemicolon(); return finishNode(node); } function parseFunctionDeclaration(node) { - node.kind = 234; - parseExpected(89); - node.asteriskToken = parseOptionalToken(39); - node.name = ts.hasModifier(node, 512) ? parseOptionalIdentifier() : parseIdentifier(); - var isGenerator = node.asteriskToken ? 1 : 0; - var isAsync = ts.hasModifier(node, 256) ? 2 : 0; - fillSignature(56, isGenerator | isAsync, node); + node.kind = 234 /* FunctionDeclaration */; + parseExpected(89 /* FunctionKeyword */); + node.asteriskToken = parseOptionalToken(39 /* AsteriskToken */); + node.name = ts.hasModifier(node, 512 /* Default */) ? parseOptionalIdentifier() : parseIdentifier(); + var isGenerator = node.asteriskToken ? 1 /* Yield */ : 0 /* None */; + var isAsync = ts.hasModifier(node, 256 /* Async */) ? 2 /* Await */ : 0 /* None */; + fillSignature(56 /* ColonToken */, isGenerator | isAsync, node); node.body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, ts.Diagnostics.or_expected); return finishNode(node); } function parseConstructorDeclaration(node) { - node.kind = 155; - parseExpected(123); - fillSignature(56, 0, node); - node.body = parseFunctionBlockOrSemicolon(0, ts.Diagnostics.or_expected); + node.kind = 155 /* Constructor */; + parseExpected(123 /* ConstructorKeyword */); + fillSignature(56 /* ColonToken */, 0 /* None */, node); + node.body = parseFunctionBlockOrSemicolon(0 /* None */, ts.Diagnostics.or_expected); return finishNode(node); } function parseMethodDeclaration(node, asteriskToken, diagnosticMessage) { - node.kind = 154; + node.kind = 154 /* MethodDeclaration */; node.asteriskToken = asteriskToken; - var isGenerator = asteriskToken ? 1 : 0; - var isAsync = ts.hasModifier(node, 256) ? 2 : 0; - fillSignature(56, isGenerator | isAsync, node); + var isGenerator = asteriskToken ? 1 /* Yield */ : 0 /* None */; + var isAsync = ts.hasModifier(node, 256 /* Async */) ? 2 /* Await */ : 0 /* None */; + fillSignature(56 /* ColonToken */, isGenerator | isAsync, node); node.body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, diagnosticMessage); return finishNode(node); } function parsePropertyDeclaration(node) { - node.kind = 152; - if (!node.questionToken && token() === 51 && !scanner.hasPrecedingLineBreak()) { + node.kind = 152 /* PropertyDeclaration */; + if (!node.questionToken && token() === 51 /* ExclamationToken */ && !scanner.hasPrecedingLineBreak()) { node.exclamationToken = parseTokenNode(); } node.type = parseTypeAnnotation(); - node.initializer = ts.hasModifier(node, 32) + // For instance properties specifically, since they are evaluated inside the constructor, + // we do *not * want to parse yield expressions, so we specifically turn the yield context + // off. The grammar would look something like this: + // + // MemberVariableDeclaration[Yield]: + // AccessibilityModifier_opt PropertyName TypeAnnotation_opt Initializer_opt[In]; + // AccessibilityModifier_opt static_opt PropertyName TypeAnnotation_opt Initializer_opt[In, ?Yield]; + // + // The checker may still error in the static case to explicitly disallow the yield expression. + node.initializer = ts.hasModifier(node, 32 /* Static */) ? allowInAnd(parseInitializer) - : doOutsideOfContext(4096 | 2048, parseInitializer); + : doOutsideOfContext(4096 /* YieldContext */ | 2048 /* DisallowInContext */, parseInitializer); parseSemicolon(); return finishNode(node); } function parsePropertyOrMethodDeclaration(node) { - var asteriskToken = parseOptionalToken(39); + var asteriskToken = parseOptionalToken(39 /* AsteriskToken */); node.name = parsePropertyName(); - node.questionToken = parseOptionalToken(55); - if (asteriskToken || token() === 19 || token() === 27) { + // Note: this is not legal as per the grammar. But we allow it in the parser and + // report an error in the grammar checker. + node.questionToken = parseOptionalToken(55 /* QuestionToken */); + if (asteriskToken || token() === 19 /* OpenParenToken */ || token() === 27 /* LessThanToken */) { return parseMethodDeclaration(node, asteriskToken, ts.Diagnostics.or_expected); } return parsePropertyDeclaration(node); @@ -17271,45 +19997,64 @@ var ts; function parseAccessorDeclaration(node, kind) { node.kind = kind; node.name = parsePropertyName(); - fillSignature(56, 0, node); - node.body = parseFunctionBlockOrSemicolon(0); + fillSignature(56 /* ColonToken */, 0 /* None */, node); + node.body = parseFunctionBlockOrSemicolon(0 /* None */); return finishNode(node); } function isClassMemberStart() { var idToken; - if (token() === 57) { + if (token() === 57 /* AtToken */) { return true; } + // Eat up all modifiers, but hold on to the last one in case it is actually an identifier. while (ts.isModifierKind(token())) { idToken = token(); + // If the idToken is a class modifier (protected, private, public, and static), it is + // certain that we are starting to parse class member. This allows better error recovery + // Example: + // public foo() ... // true + // public @dec blah ... // true; we will then report an error later + // export public ... // true; we will then report an error later if (ts.isClassMemberModifier(idToken)) { return true; } nextToken(); } - if (token() === 39) { + if (token() === 39 /* AsteriskToken */) { return true; } + // Try to get the first property-like token following all modifiers. + // This can either be an identifier or the 'get' or 'set' keywords. if (isLiteralPropertyName()) { idToken = token(); nextToken(); } - if (token() === 21) { + // Index signatures and computed properties are class members; we can parse. + if (token() === 21 /* OpenBracketToken */) { return true; } + // If we were able to get any potential identifier... if (idToken !== undefined) { - if (!ts.isKeyword(idToken) || idToken === 136 || idToken === 125) { + // If we have a non-keyword identifier, or if we have an accessor, then it's safe to parse. + if (!ts.isKeyword(idToken) || idToken === 136 /* SetKeyword */ || idToken === 125 /* GetKeyword */) { return true; } + // If it *is* a keyword, but not an accessor, check a little farther along + // to see if it should actually be parsed as a class member. switch (token()) { - case 19: - case 27: - case 51: - case 56: - case 58: - case 55: + case 19 /* OpenParenToken */: // Method declaration + case 27 /* LessThanToken */: // Generic Method declaration + case 51 /* ExclamationToken */: // Non-null assertion on property name + case 56 /* ColonToken */: // Type Annotation for declaration + case 58 /* EqualsToken */: // Initializer for declaration + case 55 /* QuestionToken */: // Not valid, but permitted so that it gets caught later on. return true; default: + // Covers + // - Semicolons (declaration termination) + // - Closing braces (end-of-class, must be declaration) + // - End-of-files (not valid, but permitted so that it gets caught later on) + // - Line-breaks (enabling *automatic semicolon insertion*) return canParseSemicolon(); } } @@ -17320,23 +20065,32 @@ var ts; var listPos = getNodePos(); while (true) { var decoratorStart = getNodePos(); - if (!parseOptional(57)) { + if (!parseOptional(57 /* AtToken */)) { break; } - var decorator = createNode(150, decoratorStart); + var decorator = createNode(150 /* Decorator */, decoratorStart); decorator.expression = doInDecoratorContext(parseLeftHandSideExpressionOrHigher); finishNode(decorator); (list || (list = [])).push(decorator); } return list && createNodeArray(list, listPos); } + /* + * There are situations in which a modifier like 'const' will appear unexpectedly, such as on a class member. + * In those situations, if we are entirely sure that 'const' is not valid on its own (such as when ASI takes effect + * and turns it into a standalone declaration), then it is better to parse it and report an error later. + * + * In such situations, 'permitInvalidConstAsModifier' should be set to true. + */ function parseModifiers(permitInvalidConstAsModifier) { var list; var listPos = getNodePos(); while (true) { var modifierStart = scanner.getStartPos(); var modifierKind = token(); - if (token() === 76 && permitInvalidConstAsModifier) { + if (token() === 76 /* ConstKeyword */ && permitInvalidConstAsModifier) { + // We need to ensure that any subsequent modifiers appear on the same line + // so that when 'const' is a standalone declaration, we don't issue an error. if (!tryParse(nextTokenIsOnSameLineAndCanFollowModifier)) { break; } @@ -17353,7 +20107,7 @@ var ts; } function parseModifiersForArrowFunction() { var modifiers; - if (token() === 120) { + if (token() === 120 /* AsyncKeyword */) { var modifierStart = scanner.getStartPos(); var modifierKind = token(); nextToken(); @@ -17363,54 +20117,60 @@ var ts; return modifiers; } function parseClassElement() { - if (token() === 25) { - var result = createNode(212); + if (token() === 25 /* SemicolonToken */) { + var result = createNode(212 /* SemicolonClassElement */); nextToken(); return finishNode(result); } - var node = createNodeWithJSDoc(0); + var node = createNodeWithJSDoc(0 /* Unknown */); node.decorators = parseDecorators(); - node.modifiers = parseModifiers(true); - if (parseContextualModifier(125)) { - return parseAccessorDeclaration(node, 156); + node.modifiers = parseModifiers(/*permitInvalidConstAsModifier*/ true); + if (parseContextualModifier(125 /* GetKeyword */)) { + return parseAccessorDeclaration(node, 156 /* GetAccessor */); } - if (parseContextualModifier(136)) { - return parseAccessorDeclaration(node, 157); + if (parseContextualModifier(136 /* SetKeyword */)) { + return parseAccessorDeclaration(node, 157 /* SetAccessor */); } - if (token() === 123) { + if (token() === 123 /* ConstructorKeyword */) { return parseConstructorDeclaration(node); } if (isIndexSignature()) { return parseIndexSignatureDeclaration(node); } + // It is very important that we check this *after* checking indexers because + // the [ token can start an index signature or a computed property name if (ts.tokenIsIdentifierOrKeyword(token()) || - token() === 9 || - token() === 8 || - token() === 39 || - token() === 21) { + token() === 9 /* StringLiteral */ || + token() === 8 /* NumericLiteral */ || + token() === 39 /* AsteriskToken */ || + token() === 21 /* OpenBracketToken */) { return parsePropertyOrMethodDeclaration(node); } if (node.decorators || node.modifiers) { - node.name = createMissingNode(71, true, ts.Diagnostics.Declaration_expected); + // treat this as a property declaration with a missing name. + node.name = createMissingNode(71 /* Identifier */, /*reportAtCurrentPosition*/ true, ts.Diagnostics.Declaration_expected); return parsePropertyDeclaration(node); } + // 'isClassMemberStart' should have hinted not to attempt parsing. return ts.Debug.fail("Should not have attempted to parse class member declaration."); } function parseClassExpression() { - return parseClassDeclarationOrExpression(createNodeWithJSDoc(0), 205); + return parseClassDeclarationOrExpression(createNodeWithJSDoc(0 /* Unknown */), 205 /* ClassExpression */); } function parseClassDeclaration(node) { - return parseClassDeclarationOrExpression(node, 235); + return parseClassDeclarationOrExpression(node, 235 /* ClassDeclaration */); } function parseClassDeclarationOrExpression(node, kind) { node.kind = kind; - parseExpected(75); + parseExpected(75 /* ClassKeyword */); node.name = parseNameOfClassDeclarationOrExpression(); node.typeParameters = parseTypeParameters(); node.heritageClauses = parseHeritageClauses(); - if (parseExpected(17)) { + if (parseExpected(17 /* OpenBraceToken */)) { + // ClassTail[Yield,Await] : (Modified) See 14.5 + // ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt } node.members = parseClassMembers(); - parseExpected(18); + parseExpected(18 /* CloseBraceToken */); } else { node.members = createMissingList(); @@ -17418,48 +20178,55 @@ var ts; return finishNode(node); } function parseNameOfClassDeclarationOrExpression() { + // implements is a future reserved word so + // 'class implements' might mean either + // - class expression with omitted name, 'implements' starts heritage clause + // - class with name 'implements' + // 'isImplementsClause' helps to disambiguate between these two cases return isIdentifier() && !isImplementsClause() ? parseIdentifier() : undefined; } function isImplementsClause() { - return token() === 108 && lookAhead(nextTokenIsIdentifierOrKeyword); + return token() === 108 /* ImplementsKeyword */ && lookAhead(nextTokenIsIdentifierOrKeyword); } function parseHeritageClauses() { + // ClassTail[Yield,Await] : (Modified) See 14.5 + // ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt } if (isHeritageClause()) { - return parseList(21, parseHeritageClause); + return parseList(21 /* HeritageClauses */, parseHeritageClause); } return undefined; } function parseHeritageClause() { var tok = token(); - ts.Debug.assert(tok === 85 || tok === 108); - var node = createNode(268); + ts.Debug.assert(tok === 85 /* ExtendsKeyword */ || tok === 108 /* ImplementsKeyword */); // isListElement() should ensure this. + var node = createNode(268 /* HeritageClause */); node.token = tok; nextToken(); - node.types = parseDelimitedList(7, parseExpressionWithTypeArguments); + node.types = parseDelimitedList(7 /* HeritageClauseElement */, parseExpressionWithTypeArguments); return finishNode(node); } function parseExpressionWithTypeArguments() { - var node = createNode(207); + var node = createNode(207 /* ExpressionWithTypeArguments */); node.expression = parseLeftHandSideExpressionOrHigher(); node.typeArguments = tryParseTypeArguments(); return finishNode(node); } function tryParseTypeArguments() { - return token() === 27 - ? parseBracketedList(19, parseType, 27, 29) + return token() === 27 /* LessThanToken */ + ? parseBracketedList(19 /* TypeArguments */, parseType, 27 /* LessThanToken */, 29 /* GreaterThanToken */) : undefined; } function isHeritageClause() { - return token() === 85 || token() === 108; + return token() === 85 /* ExtendsKeyword */ || token() === 108 /* ImplementsKeyword */; } function parseClassMembers() { - return parseList(5, parseClassElement); + return parseList(5 /* ClassMembers */, parseClassElement); } function parseInterfaceDeclaration(node) { - node.kind = 236; - parseExpected(109); + node.kind = 236 /* InterfaceDeclaration */; + parseExpected(109 /* InterfaceKeyword */); node.name = parseIdentifier(); node.typeParameters = parseTypeParameters(); node.heritageClauses = parseHeritageClauses(); @@ -17467,28 +20234,32 @@ var ts; return finishNode(node); } function parseTypeAliasDeclaration(node) { - node.kind = 237; - parseExpected(139); + node.kind = 237 /* TypeAliasDeclaration */; + parseExpected(139 /* TypeKeyword */); node.name = parseIdentifier(); node.typeParameters = parseTypeParameters(); - parseExpected(58); + parseExpected(58 /* EqualsToken */); node.type = parseType(); parseSemicolon(); return finishNode(node); } + // In an ambient declaration, the grammar only allows integer literals as initializers. + // In a non-ambient declaration, the grammar allows uninitialized members only in a + // ConstantEnumMemberSection, which starts at the beginning of an enum declaration + // or any time an integer literal initializer is encountered. function parseEnumMember() { - var node = createNodeWithJSDoc(273); + var node = createNodeWithJSDoc(273 /* EnumMember */); node.name = parsePropertyName(); node.initializer = allowInAnd(parseInitializer); return finishNode(node); } function parseEnumDeclaration(node) { - node.kind = 238; - parseExpected(83); + node.kind = 238 /* EnumDeclaration */; + parseExpected(83 /* EnumKeyword */); node.name = parseIdentifier(); - if (parseExpected(17)) { - node.members = parseDelimitedList(6, parseEnumMember); - parseExpected(18); + if (parseExpected(17 /* OpenBraceToken */)) { + node.members = parseDelimitedList(6 /* EnumMembers */, parseEnumMember); + parseExpected(18 /* CloseBraceToken */); } else { node.members = createMissingList(); @@ -17496,10 +20267,10 @@ var ts; return finishNode(node); } function parseModuleBlock() { - var node = createNode(240); - if (parseExpected(17)) { - node.statements = parseList(1, parseStatement); - parseExpected(18); + var node = createNode(240 /* ModuleBlock */); + if (parseExpected(17 /* OpenBraceToken */)) { + node.statements = parseList(1 /* BlockStatements */, parseStatement); + parseExpected(18 /* CloseBraceToken */); } else { node.statements = createMissingList(); @@ -17507,26 +20278,29 @@ var ts; return finishNode(node); } function parseModuleOrNamespaceDeclaration(node, flags) { - node.kind = 239; - var namespaceFlag = flags & 16; + node.kind = 239 /* ModuleDeclaration */; + // If we are parsing a dotted namespace name, we want to + // propagate the 'Namespace' flag across the names if set. + var namespaceFlag = flags & 16 /* Namespace */; node.flags |= flags; node.name = parseIdentifier(); - node.body = parseOptional(23) - ? parseModuleOrNamespaceDeclaration(createNode(0), 4 | namespaceFlag) + node.body = parseOptional(23 /* DotToken */) + ? parseModuleOrNamespaceDeclaration(createNode(0 /* Unknown */), 4 /* NestedNamespace */ | namespaceFlag) : parseModuleBlock(); return finishNode(node); } function parseAmbientExternalModuleDeclaration(node) { - node.kind = 239; - if (token() === 144) { + node.kind = 239 /* ModuleDeclaration */; + if (token() === 144 /* GlobalKeyword */) { + // parse 'global' as name of global scope augmentation node.name = parseIdentifier(); - node.flags |= 512; + node.flags |= 512 /* GlobalAugmentation */; } else { node.name = parseLiteralNode(); node.name.text = internIdentifier(node.name.text); } - if (token() === 17) { + if (token() === 17 /* OpenBraceToken */) { node.body = parseModuleBlock(); } else { @@ -17536,128 +20310,161 @@ var ts; } function parseModuleDeclaration(node) { var flags = 0; - if (token() === 144) { + if (token() === 144 /* GlobalKeyword */) { + // global augmentation return parseAmbientExternalModuleDeclaration(node); } - else if (parseOptional(130)) { - flags |= 16; + else if (parseOptional(130 /* NamespaceKeyword */)) { + flags |= 16 /* Namespace */; } else { - parseExpected(129); - if (token() === 9) { + parseExpected(129 /* ModuleKeyword */); + if (token() === 9 /* StringLiteral */) { return parseAmbientExternalModuleDeclaration(node); } } return parseModuleOrNamespaceDeclaration(node, flags); } function isExternalModuleReference() { - return token() === 133 && + return token() === 133 /* RequireKeyword */ && lookAhead(nextTokenIsOpenParen); } function nextTokenIsOpenParen() { - return nextToken() === 19; + return nextToken() === 19 /* OpenParenToken */; } function nextTokenIsSlash() { - return nextToken() === 41; + return nextToken() === 41 /* SlashToken */; } function parseNamespaceExportDeclaration(node) { - node.kind = 242; - parseExpected(118); - parseExpected(130); + node.kind = 242 /* NamespaceExportDeclaration */; + parseExpected(118 /* AsKeyword */); + parseExpected(130 /* NamespaceKeyword */); node.name = parseIdentifier(); parseSemicolon(); return finishNode(node); } function parseImportDeclarationOrImportEqualsDeclaration(node) { - parseExpected(91); + parseExpected(91 /* ImportKeyword */); var afterImportPos = scanner.getStartPos(); var identifier; if (isIdentifier()) { identifier = parseIdentifier(); - if (token() !== 26 && token() !== 143) { + if (token() !== 26 /* CommaToken */ && token() !== 143 /* FromKeyword */) { return parseImportEqualsDeclaration(node, identifier); } } - node.kind = 244; - if (identifier || - token() === 39 || - token() === 17) { + // Import statement + node.kind = 244 /* ImportDeclaration */; + // ImportDeclaration: + // import ImportClause from ModuleSpecifier ; + // import ModuleSpecifier; + if (identifier || // import id + token() === 39 /* AsteriskToken */ || // import * + token() === 17 /* OpenBraceToken */) { // import { node.importClause = parseImportClause(identifier, afterImportPos); - parseExpected(143); + parseExpected(143 /* FromKeyword */); } node.moduleSpecifier = parseModuleSpecifier(); parseSemicolon(); return finishNode(node); } function parseImportEqualsDeclaration(node, identifier) { - node.kind = 243; + node.kind = 243 /* ImportEqualsDeclaration */; node.name = identifier; - parseExpected(58); + parseExpected(58 /* EqualsToken */); node.moduleReference = parseModuleReference(); parseSemicolon(); return finishNode(node); } function parseImportClause(identifier, fullStart) { - var importClause = createNode(245, fullStart); + // ImportClause: + // ImportedDefaultBinding + // NameSpaceImport + // NamedImports + // ImportedDefaultBinding, NameSpaceImport + // ImportedDefaultBinding, NamedImports + var importClause = createNode(245 /* ImportClause */, fullStart); if (identifier) { + // ImportedDefaultBinding: + // ImportedBinding importClause.name = identifier; } + // If there was no default import or if there is comma token after default import + // parse namespace or named imports if (!importClause.name || - parseOptional(26)) { - importClause.namedBindings = token() === 39 ? parseNamespaceImport() : parseNamedImportsOrExports(247); + parseOptional(26 /* CommaToken */)) { + importClause.namedBindings = token() === 39 /* AsteriskToken */ ? parseNamespaceImport() : parseNamedImportsOrExports(247 /* NamedImports */); } return finishNode(importClause); } function parseModuleReference() { return isExternalModuleReference() ? parseExternalModuleReference() - : parseEntityName(false); + : parseEntityName(/*allowReservedWords*/ false); } function parseExternalModuleReference() { - var node = createNode(254); - parseExpected(133); - parseExpected(19); + var node = createNode(254 /* ExternalModuleReference */); + parseExpected(133 /* RequireKeyword */); + parseExpected(19 /* OpenParenToken */); node.expression = parseModuleSpecifier(); - parseExpected(20); + parseExpected(20 /* CloseParenToken */); return finishNode(node); } function parseModuleSpecifier() { - if (token() === 9) { + if (token() === 9 /* StringLiteral */) { var result = parseLiteralNode(); result.text = internIdentifier(result.text); return result; } else { + // We allow arbitrary expressions here, even though the grammar only allows string + // literals. We check to ensure that it is only a string literal later in the grammar + // check pass. return parseExpression(); } } function parseNamespaceImport() { - var namespaceImport = createNode(246); - parseExpected(39); - parseExpected(118); + // NameSpaceImport: + // * as ImportedBinding + var namespaceImport = createNode(246 /* NamespaceImport */); + parseExpected(39 /* AsteriskToken */); + parseExpected(118 /* AsKeyword */); namespaceImport.name = parseIdentifier(); return finishNode(namespaceImport); } function parseNamedImportsOrExports(kind) { var node = createNode(kind); - node.elements = parseBracketedList(22, kind === 247 ? parseImportSpecifier : parseExportSpecifier, 17, 18); + // NamedImports: + // { } + // { ImportsList } + // { ImportsList, } + // ImportsList: + // ImportSpecifier + // ImportsList, ImportSpecifier + node.elements = parseBracketedList(22 /* ImportOrExportSpecifiers */, kind === 247 /* NamedImports */ ? parseImportSpecifier : parseExportSpecifier, 17 /* OpenBraceToken */, 18 /* CloseBraceToken */); return finishNode(node); } function parseExportSpecifier() { - return parseImportOrExportSpecifier(252); + return parseImportOrExportSpecifier(252 /* ExportSpecifier */); } function parseImportSpecifier() { - return parseImportOrExportSpecifier(248); + return parseImportOrExportSpecifier(248 /* ImportSpecifier */); } function parseImportOrExportSpecifier(kind) { var node = createNode(kind); + // ImportSpecifier: + // BindingIdentifier + // IdentifierName as BindingIdentifier + // ExportSpecifier: + // IdentifierName + // IdentifierName as IdentifierName var checkIdentifierIsKeyword = ts.isKeyword(token()) && !isIdentifier(); var checkIdentifierStart = scanner.getTokenPos(); var checkIdentifierEnd = scanner.getTextPos(); var identifierName = parseIdentifierName(); - if (token() === 118) { + if (token() === 118 /* AsKeyword */) { node.propertyName = identifierName; - parseExpected(118); + parseExpected(118 /* AsKeyword */); checkIdentifierIsKeyword = ts.isKeyword(token()) && !isIdentifier(); checkIdentifierStart = scanner.getTokenPos(); checkIdentifierEnd = scanner.getTextPos(); @@ -17666,21 +20473,24 @@ var ts; else { node.name = identifierName; } - if (kind === 248 && checkIdentifierIsKeyword) { + if (kind === 248 /* ImportSpecifier */ && checkIdentifierIsKeyword) { parseErrorAt(checkIdentifierStart, checkIdentifierEnd, ts.Diagnostics.Identifier_expected); } return finishNode(node); } function parseExportDeclaration(node) { - node.kind = 250; - if (parseOptional(39)) { - parseExpected(143); + node.kind = 250 /* ExportDeclaration */; + if (parseOptional(39 /* AsteriskToken */)) { + parseExpected(143 /* FromKeyword */); node.moduleSpecifier = parseModuleSpecifier(); } else { - node.exportClause = parseNamedImportsOrExports(251); - if (token() === 143 || (token() === 9 && !scanner.hasPrecedingLineBreak())) { - parseExpected(143); + node.exportClause = parseNamedImportsOrExports(251 /* NamedExports */); + // It is not uncommon to accidentally omit the 'from' keyword. Additionally, in editing scenarios, + // the 'from' keyword can be parsed as a named export when the export clause is unterminated (i.e. `export { from "moduleName";`) + // If we don't have a 'from' keyword, see if we have a string literal such that ASI won't take effect. + if (token() === 143 /* FromKeyword */ || (token() === 9 /* StringLiteral */ && !scanner.hasPrecedingLineBreak())) { + parseExpected(143 /* FromKeyword */); node.moduleSpecifier = parseModuleSpecifier(); } } @@ -17688,33 +20498,35 @@ var ts; return finishNode(node); } function parseExportAssignment(node) { - node.kind = 249; - if (parseOptional(58)) { + node.kind = 249 /* ExportAssignment */; + if (parseOptional(58 /* EqualsToken */)) { node.isExportEquals = true; } else { - parseExpected(79); + parseExpected(79 /* DefaultKeyword */); } node.expression = parseAssignmentExpressionOrHigher(); parseSemicolon(); return finishNode(node); } function setExternalModuleIndicator(sourceFile) { + // Try to use the first top-level import/export when available, then + // fall back to looking for an 'import.meta' somewhere in the tree if necessary. sourceFile.externalModuleIndicator = ts.forEach(sourceFile.statements, isAnExternalModuleIndicatorNode) || getImportMetaIfNecessary(sourceFile); } function isAnExternalModuleIndicatorNode(node) { - return ts.hasModifier(node, 1) - || node.kind === 243 && node.moduleReference.kind === 254 - || node.kind === 244 - || node.kind === 249 - || node.kind === 250 + return ts.hasModifier(node, 1 /* Export */) + || node.kind === 243 /* ImportEqualsDeclaration */ && node.moduleReference.kind === 254 /* ExternalModuleReference */ + || node.kind === 244 /* ImportDeclaration */ + || node.kind === 249 /* ExportAssignment */ + || node.kind === 250 /* ExportDeclaration */ ? node : undefined; } function getImportMetaIfNecessary(sourceFile) { - return sourceFile.flags & 1048576 ? + return sourceFile.flags & 1048576 /* PossiblyContainsImportMeta */ ? walkTreeForExternalModuleIndicators(sourceFile) : undefined; } @@ -17722,7 +20534,7 @@ var ts; return isImportMeta(node) ? node : forEachChild(node, walkTreeForExternalModuleIndicators); } function isImportMeta(node) { - return ts.isMetaProperty(node) && node.keywordToken === 91 && node.name.escapedText === "meta"; + return ts.isMetaProperty(node) && node.keywordToken === 91 /* ImportKeyword */ && node.name.escapedText === "meta"; } var ParsingContext; (function (ParsingContext) { @@ -17749,7 +20561,7 @@ var ts; ParsingContext[ParsingContext["TupleElementTypes"] = 20] = "TupleElementTypes"; ParsingContext[ParsingContext["HeritageClauses"] = 21] = "HeritageClauses"; ParsingContext[ParsingContext["ImportOrExportSpecifiers"] = 22] = "ImportOrExportSpecifiers"; - ParsingContext[ParsingContext["Count"] = 23] = "Count"; + ParsingContext[ParsingContext["Count"] = 23] = "Count"; // Number of parsing contexts })(ParsingContext || (ParsingContext = {})); var Tristate; (function (Tristate) { @@ -17760,8 +20572,8 @@ var ts; var JSDocParser; (function (JSDocParser) { function parseJSDocTypeExpressionForTests(content, start, length) { - initializeState(content, 6, undefined, 1); - sourceFile = createSourceFile("file.js", 6, 1, false); + initializeState(content, 6 /* Latest */, /*_syntaxCursor:*/ undefined, 1 /* JS */); + sourceFile = createSourceFile("file.js", 6 /* Latest */, 1 /* JS */, /*isDeclarationFile*/ false); scanner.setText(content, start, length); currentToken = scanner.scan(); var jsDocTypeExpression = parseJSDocTypeExpression(); @@ -17770,20 +20582,21 @@ var ts; return jsDocTypeExpression ? { jsDocTypeExpression: jsDocTypeExpression, diagnostics: diagnostics } : undefined; } JSDocParser.parseJSDocTypeExpressionForTests = parseJSDocTypeExpressionForTests; + // Parses out a JSDoc type expression. function parseJSDocTypeExpression(mayOmitBraces) { - var result = createNode(278, scanner.getTokenPos()); - var hasBrace = (mayOmitBraces ? parseOptional : parseExpected)(17); - result.type = doInsideOfContext(2097152, parseJSDocType); + var result = createNode(278 /* JSDocTypeExpression */, scanner.getTokenPos()); + var hasBrace = (mayOmitBraces ? parseOptional : parseExpected)(17 /* OpenBraceToken */); + result.type = doInsideOfContext(2097152 /* JSDoc */, parseJSDocType); if (!mayOmitBraces || hasBrace) { - parseExpected(18); + parseExpected(18 /* CloseBraceToken */); } fixupParentReferences(result); return finishNode(result); } JSDocParser.parseJSDocTypeExpression = parseJSDocTypeExpression; function parseIsolatedJSDocComment(content, start, length) { - initializeState(content, 6, undefined, 1); - sourceFile = { languageVariant: 0, text: content }; + initializeState(content, 6 /* Latest */, /*_syntaxCursor:*/ undefined, 1 /* JS */); + sourceFile = { languageVariant: 0 /* Standard */, text: content }; // tslint:disable-line no-object-literal-type-assertion var jsDoc = parseJSDocCommentWorker(start, length); var diagnostics = parseDiagnostics; clearState(); @@ -17799,7 +20612,7 @@ var ts; if (comment) { comment.parent = parent; } - if (contextFlags & 65536) { + if (contextFlags & 65536 /* JavaScriptFile */) { if (!sourceFile.jsDocDiagnostics) { sourceFile.jsDocDiagnostics = []; } @@ -17836,12 +20649,17 @@ var ts; var tagsEnd; var comments = []; var result; + // Check for /** (JSDoc opening part) if (!isJSDocLikeText(content, start)) { return result; } + // + 3 for leading /**, - 5 in total for /** */ scanner.scanRange(start + 3, length - 5, function () { - var state = 1; + // Initially we can parse out a tag. We also have seen a starting asterisk. + // This is so that /** * @type */ doesn't parse. + var state = 1 /* SawAsterisk */; var margin; + // + 4 for leading '/** ' var indent = start - Math.max(content.lastIndexOf("\n", start), 0) + 4; function pushComment(text) { if (!margin) { @@ -17851,19 +20669,22 @@ var ts; indent += text.length; } nextJSDocToken(); - while (parseOptionalJsdoc(5)) + while (parseOptionalJsdoc(5 /* WhitespaceTrivia */)) ; - if (parseOptionalJsdoc(4)) { - state = 0; + if (parseOptionalJsdoc(4 /* NewLineTrivia */)) { + state = 0 /* BeginningOfLine */; indent = 0; } loop: while (true) { switch (token()) { - case 57: - if (state === 0 || state === 1) { + case 57 /* AtToken */: + if (state === 0 /* BeginningOfLine */ || state === 1 /* SawAsterisk */) { removeTrailingNewlines(comments); addTag(parseTag(indent)); - state = 0; + // NOTE: According to usejsdoc.org, a tag goes to end of line, except the last tag. + // Real-world comments may break this rule, so "BeginningOfLine" will not be a real line beginning + // for malformed examples like `/** @param {string} x @returns {number} the length */` + state = 0 /* BeginningOfLine */; margin = undefined; indent++; } @@ -17871,29 +20692,35 @@ var ts; pushComment(scanner.getTokenText()); } break; - case 4: + case 4 /* NewLineTrivia */: comments.push(scanner.getTokenText()); - state = 0; + state = 0 /* BeginningOfLine */; indent = 0; break; - case 39: + case 39 /* AsteriskToken */: var asterisk = scanner.getTokenText(); - if (state === 1 || state === 2) { - state = 2; + if (state === 1 /* SawAsterisk */ || state === 2 /* SavingComments */) { + // If we've already seen an asterisk, then we can no longer parse a tag on this line + state = 2 /* SavingComments */; pushComment(asterisk); } else { - state = 1; + // Ignore the first asterisk on a line + state = 1 /* SawAsterisk */; indent += asterisk.length; } break; - case 71: + case 71 /* Identifier */: + // Anything else is doc comment text. We just save it. Because it + // wasn't a tag, we can no longer parse a tag on this line until we hit the next + // line break. pushComment(scanner.getTokenText()); - state = 2; + state = 2 /* SavingComments */; break; - case 5: + case 5 /* WhitespaceTrivia */: + // only collect whitespace if we're already saving comments or have just crossed the comment indent margin var whitespace = scanner.getTokenText(); - if (state === 2) { + if (state === 2 /* SavingComments */) { comments.push(whitespace); } else if (margin !== undefined && indent + whitespace.length > margin) { @@ -17901,10 +20728,11 @@ var ts; } indent += whitespace.length; break; - case 1: + case 1 /* EndOfFileToken */: break loop; default: - state = 2; + // anything other than whitespace or asterisk at the beginning of the line starts the comment text + state = 2 /* SavingComments */; pushComment(scanner.getTokenText()); break; } @@ -17926,35 +20754,36 @@ var ts; } } function createJSDocComment() { - var result = createNode(286, start); + var result = createNode(286 /* JSDocComment */, start); result.tags = tags && createNodeArray(tags, tagsPos, tagsEnd); result.comment = comments.length ? comments.join("") : undefined; return finishNode(result, end); } function isNextNonwhitespaceTokenEndOfFile() { + // We must use infinite lookahead, as there could be any number of newlines :( while (true) { nextJSDocToken(); - if (token() === 1) { + if (token() === 1 /* EndOfFileToken */) { return true; } - if (!(token() === 5 || token() === 4)) { + if (!(token() === 5 /* WhitespaceTrivia */ || token() === 4 /* NewLineTrivia */)) { return false; } } } function skipWhitespace() { - if (token() === 5 || token() === 4) { + if (token() === 5 /* WhitespaceTrivia */ || token() === 4 /* NewLineTrivia */) { if (lookAhead(isNextNonwhitespaceTokenEndOfFile)) { - return; + return; // Don't skip whitespace prior to EoF (or end of comment) - that shouldn't be included in any node's range } } - while (token() === 5 || token() === 4) { + while (token() === 5 /* WhitespaceTrivia */ || token() === 4 /* NewLineTrivia */) { nextJSDocToken(); } } function parseTag(indent) { - ts.Debug.assert(token() === 57); - var atToken = createNode(57, scanner.getTokenPos()); + ts.Debug.assert(token() === 57 /* AtToken */); + var atToken = createNode(57 /* AtToken */, scanner.getTokenPos()); atToken.end = scanner.getTextPos(); nextJSDocToken(); var tagName = parseJSDocIdentifierName(); @@ -17975,7 +20804,7 @@ var ts; case "arg": case "argument": case "param": - return parseParameterOrPropertyTag(atToken, tagName, 2, indent); + return parseParameterOrPropertyTag(atToken, tagName, 2 /* Parameter */, indent); case "return": case "returns": tag = parseReturnTag(atToken, tagName); @@ -17997,13 +20826,14 @@ var ts; break; } if (!tag.comment) { + // some tags, like typedef and callback, have already parsed their comments earlier tag.comment = parseTagComments(indent + tag.end - tag.pos); } return tag; } function parseTagComments(indent) { var comments = []; - var state = 0; + var state = 0 /* BeginningOfLine */; var margin; function pushComment(text) { if (!margin) { @@ -18015,37 +20845,43 @@ var ts; var tok = token(); loop: while (true) { switch (tok) { - case 4: - if (state >= 1) { - state = 0; + case 4 /* NewLineTrivia */: + if (state >= 1 /* SawAsterisk */) { + state = 0 /* BeginningOfLine */; comments.push(scanner.getTokenText()); } indent = 0; break; - case 57: + case 57 /* AtToken */: scanner.setTextPos(scanner.getTextPos() - 1); - case 1: + // falls through + case 1 /* EndOfFileToken */: + // Done break loop; - case 5: - if (state === 2) { + case 5 /* WhitespaceTrivia */: + if (state === 2 /* SavingComments */) { pushComment(scanner.getTokenText()); } else { var whitespace = scanner.getTokenText(); + // if the whitespace crosses the margin, take only the whitespace that passes the margin if (margin !== undefined && indent + whitespace.length > margin) { comments.push(whitespace.slice(margin - indent - 1)); } indent += whitespace.length; } break; - case 39: - if (state === 0) { - state = 1; + case 39 /* AsteriskToken */: + if (state === 0 /* BeginningOfLine */) { + // leading asterisks start recording on the *next* (non-whitespace) token + state = 1 /* SawAsterisk */; indent += 1; break; } + // record the * as a comment + // falls through default: - state = 2; + state = 2 /* SavingComments */; // leading identifiers start recording as well pushComment(scanner.getTokenText()); break; } @@ -18056,7 +20892,7 @@ var ts; return comments.length === 0 ? undefined : comments.join(""); } function parseUnknownTag(atToken, tagName) { - var result = createNode(289, atToken.pos); + var result = createNode(289 /* JSDocTag */, atToken.pos); result.atToken = atToken; result.tagName = tagName; return finishNode(result); @@ -18076,28 +20912,31 @@ var ts; } function tryParseTypeExpression() { skipWhitespace(); - return token() === 17 ? parseJSDocTypeExpression() : undefined; + return token() === 17 /* OpenBraceToken */ ? parseJSDocTypeExpression() : undefined; } function parseBracketNameInPropertyAndParamTag() { - if (token() === 13) { - return { name: createIdentifier(true), isBracketed: false }; + if (token() === 13 /* NoSubstitutionTemplateLiteral */) { + // a markdown-quoted name: `arg` is not legal jsdoc, but occurs in the wild + return { name: createIdentifier(/*isIdentifier*/ true), isBracketed: false }; } - var isBracketed = parseOptional(21); + // Looking for something like '[foo]', 'foo', '[foo.bar]' or 'foo.bar' + var isBracketed = parseOptional(21 /* OpenBracketToken */); var name = parseJSDocEntityName(); if (isBracketed) { skipWhitespace(); - if (parseOptionalToken(58)) { + // May have an optional default, e.g. '[foo = 42]' + if (parseOptionalToken(58 /* EqualsToken */)) { parseExpression(); } - parseExpected(22); + parseExpected(22 /* CloseBracketToken */); } return { name: name, isBracketed: isBracketed }; } function isObjectOrObjectArrayTypeReference(node) { switch (node.kind) { - case 135: + case 135 /* ObjectKeyword */: return true; - case 167: + case 167 /* ArrayType */: return isObjectOrObjectArrayTypeReference(node.elementType); default: return ts.isTypeReferenceNode(node) && ts.isIdentifier(node.typeName) && node.typeName.escapedText === "Object"; @@ -18112,13 +20951,13 @@ var ts; if (isNameFirst) { typeExpression = tryParseTypeExpression(); } - var result = target === 1 ? - createNode(299, atToken.pos) : - createNode(293, atToken.pos); + var result = target === 1 /* Property */ ? + createNode(299 /* JSDocPropertyTag */, atToken.pos) : + createNode(293 /* JSDocParameterTag */, atToken.pos); var comment; if (indent !== undefined) comment = parseTagComments(indent + scanner.getStartPos() - atToken.pos); - var nestedTypeLiteral = target !== 4 && parseNestedTypeLiteral(typeExpression, name, target); + var nestedTypeLiteral = target !== 4 /* CallbackParameter */ && parseNestedTypeLiteral(typeExpression, name, target); if (nestedTypeLiteral) { typeExpression = nestedTypeLiteral; isNameFirst = true; @@ -18134,20 +20973,20 @@ var ts; } function parseNestedTypeLiteral(typeExpression, name, target) { if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.type)) { - var typeLiteralExpression = createNode(278, scanner.getTokenPos()); + var typeLiteralExpression = createNode(278 /* JSDocTypeExpression */, scanner.getTokenPos()); var child = void 0; var jsdocTypeLiteral = void 0; var start_2 = scanner.getStartPos(); var children = void 0; while (child = tryParse(function () { return parseChildParameterOrPropertyTag(target, name); })) { - if (child.kind === 293 || child.kind === 299) { + if (child.kind === 293 /* JSDocParameterTag */ || child.kind === 299 /* JSDocPropertyTag */) { children = ts.append(children, child); } } if (children) { - jsdocTypeLiteral = createNode(287, start_2); + jsdocTypeLiteral = createNode(287 /* JSDocTypeLiteral */, start_2); jsdocTypeLiteral.jsDocPropertyTags = children; - if (typeExpression.type.kind === 167) { + if (typeExpression.type.kind === 167 /* ArrayType */) { jsdocTypeLiteral.isArrayType = true; } typeLiteralExpression.type = finishNode(jsdocTypeLiteral); @@ -18156,47 +20995,47 @@ var ts; } } function parseReturnTag(atToken, tagName) { - if (ts.forEach(tags, function (t) { return t.kind === 294; })) { + if (ts.forEach(tags, function (t) { return t.kind === 294 /* JSDocReturnTag */; })) { parseErrorAt(tagName.pos, scanner.getTokenPos(), ts.Diagnostics._0_tag_already_specified, tagName.escapedText); } - var result = createNode(294, atToken.pos); + var result = createNode(294 /* JSDocReturnTag */, atToken.pos); result.atToken = atToken; result.tagName = tagName; result.typeExpression = tryParseTypeExpression(); return finishNode(result); } function parseTypeTag(atToken, tagName) { - if (ts.forEach(tags, function (t) { return t.kind === 296; })) { + if (ts.forEach(tags, function (t) { return t.kind === 296 /* JSDocTypeTag */; })) { parseErrorAt(tagName.pos, scanner.getTokenPos(), ts.Diagnostics._0_tag_already_specified, tagName.escapedText); } - var result = createNode(296, atToken.pos); + var result = createNode(296 /* JSDocTypeTag */, atToken.pos); result.atToken = atToken; result.tagName = tagName; - result.typeExpression = parseJSDocTypeExpression(true); + result.typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); return finishNode(result); } function parseAugmentsTag(atToken, tagName) { - var result = createNode(290, atToken.pos); + var result = createNode(290 /* JSDocAugmentsTag */, atToken.pos); result.atToken = atToken; result.tagName = tagName; result.class = parseExpressionWithTypeArgumentsForAugments(); return finishNode(result); } function parseExpressionWithTypeArgumentsForAugments() { - var usedBrace = parseOptional(17); - var node = createNode(207); + var usedBrace = parseOptional(17 /* OpenBraceToken */); + var node = createNode(207 /* ExpressionWithTypeArguments */); node.expression = parsePropertyAccessEntityNameExpression(); node.typeArguments = tryParseTypeArguments(); var res = finishNode(node); if (usedBrace) { - parseExpected(18); + parseExpected(18 /* CloseBraceToken */); } return res; } function parsePropertyAccessEntityNameExpression() { var node = parseJSDocIdentifierName(); - while (parseOptional(23)) { - var prop = createNode(185, node.pos); + while (parseOptional(23 /* DotToken */)) { + var prop = createNode(185 /* PropertyAccessExpression */, node.pos); prop.expression = node; prop.name = parseJSDocIdentifierName(); node = finishNode(prop); @@ -18204,23 +21043,23 @@ var ts; return node; } function parseClassTag(atToken, tagName) { - var tag = createNode(291, atToken.pos); + var tag = createNode(291 /* JSDocClassTag */, atToken.pos); tag.atToken = atToken; tag.tagName = tagName; return finishNode(tag); } function parseThisTag(atToken, tagName) { - var tag = createNode(295, atToken.pos); + var tag = createNode(295 /* JSDocThisTag */, atToken.pos); tag.atToken = atToken; tag.tagName = tagName; - tag.typeExpression = parseJSDocTypeExpression(true); + tag.typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); skipWhitespace(); return finishNode(tag); } function parseTypedefTag(atToken, tagName, indent) { var typeExpression = tryParseTypeExpression(); skipWhitespace(); - var typedefTag = createNode(298, atToken.pos); + var typedefTag = createNode(298 /* JSDocTypedefTag */, atToken.pos); typedefTag.atToken = atToken; typedefTag.tagName = tagName; typedefTag.fullName = parseJSDocTypeNameWithNamespace(); @@ -18236,9 +21075,9 @@ var ts; var start_3 = scanner.getStartPos(); while (child = tryParse(function () { return parseChildPropertyTag(); })) { if (!jsdocTypeLiteral) { - jsdocTypeLiteral = createNode(287, start_3); + jsdocTypeLiteral = createNode(287 /* JSDocTypeLiteral */, start_3); } - if (child.kind === 296) { + if (child.kind === 296 /* JSDocTypeTag */) { if (childTypeTag) { break; } @@ -18251,7 +21090,7 @@ var ts; } } if (jsdocTypeLiteral) { - if (typeExpression && typeExpression.type.kind === 167) { + if (typeExpression && typeExpression.type.kind === 167 /* ArrayType */) { jsdocTypeLiteral.isArrayType = true; } typedefTag.typeExpression = childTypeTag && childTypeTag.typeExpression && !isObjectOrObjectArrayTypeReference(childTypeTag.typeExpression.type) ? @@ -18260,6 +21099,7 @@ var ts; end = typedefTag.typeExpression.end; } } + // Only include the characters between the name end and the next token if a comment was actually parsed out - otherwise it's just whitespace return finishNode(typedefTag, end || typedefTag.comment !== undefined ? scanner.getStartPos() : (typedefTag.fullName || typedefTag.typeExpression || typedefTag.tagName).end); } function parseJSDocTypeNameWithNamespace(nested) { @@ -18268,13 +21108,13 @@ var ts; return undefined; } var typeNameOrNamespaceName = parseJSDocIdentifierName(); - if (parseOptional(23)) { - var jsDocNamespaceNode = createNode(239, pos); + if (parseOptional(23 /* DotToken */)) { + var jsDocNamespaceNode = createNode(239 /* ModuleDeclaration */, pos); if (nested) { - jsDocNamespaceNode.flags |= 4; + jsDocNamespaceNode.flags |= 4 /* NestedNamespace */; } jsDocNamespaceNode.name = typeNameOrNamespaceName; - jsDocNamespaceNode.body = parseJSDocTypeNameWithNamespace(true); + jsDocNamespaceNode.body = parseJSDocTypeNameWithNamespace(/*nested*/ true); return finishNode(jsDocNamespaceNode); } if (nested) { @@ -18283,7 +21123,7 @@ var ts; return typeNameOrNamespaceName; } function parseCallbackTag(atToken, tagName, indent) { - var callbackTag = createNode(292, atToken.pos); + var callbackTag = createNode(292 /* JSDocCallbackTag */, atToken.pos); callbackTag.atToken = atToken; callbackTag.tagName = tagName; callbackTag.fullName = parseJSDocTypeNameWithNamespace(); @@ -18292,15 +21132,15 @@ var ts; callbackTag.comment = parseTagComments(indent); var child; var start = scanner.getStartPos(); - var jsdocSignature = createNode(288, start); + var jsdocSignature = createNode(288 /* JSDocSignature */, start); jsdocSignature.parameters = []; - while (child = tryParse(function () { return parseChildParameterOrPropertyTag(4); })) { + while (child = tryParse(function () { return parseChildParameterOrPropertyTag(4 /* CallbackParameter */); })) { jsdocSignature.parameters = ts.append(jsdocSignature.parameters, child); } var returnTag = tryParse(function () { - if (parseOptionalJsdoc(57)) { + if (parseOptionalJsdoc(57 /* AtToken */)) { var tag = parseTag(indent); - if (tag && tag.kind === 294) { + if (tag && tag.kind === 294 /* JSDocReturnTag */) { return tag; } } @@ -18335,46 +21175,46 @@ var ts; return a.escapedText === b.escapedText; } function parseChildPropertyTag() { - return parseChildParameterOrPropertyTag(1); + return parseChildParameterOrPropertyTag(1 /* Property */); } function parseChildParameterOrPropertyTag(target, name) { var canParseTag = true; var seenAsterisk = false; while (true) { switch (nextJSDocToken()) { - case 57: + case 57 /* AtToken */: if (canParseTag) { var child = tryParseChildTag(target); - if (child && child.kind === 293 && - target !== 4 && - (ts.isIdentifier(child.name) || !escapedTextsEqual(name, child.name.left))) { + if (child && child.kind === 293 /* JSDocParameterTag */ && + target !== 4 /* CallbackParameter */ && + (ts.isIdentifier(child.name) || !escapedTextsEqual(name, child.name.left))) { // TODO: GH#18217 return false; } return child; } seenAsterisk = false; break; - case 4: + case 4 /* NewLineTrivia */: canParseTag = true; seenAsterisk = false; break; - case 39: + case 39 /* AsteriskToken */: if (seenAsterisk) { canParseTag = false; } seenAsterisk = true; break; - case 71: + case 71 /* Identifier */: canParseTag = false; break; - case 1: + case 1 /* EndOfFileToken */: return false; } } } function tryParseChildTag(target) { - ts.Debug.assert(token() === 57); - var atToken = createNode(57); + ts.Debug.assert(token() === 57 /* AtToken */); + var atToken = createNode(57 /* AtToken */); atToken.end = scanner.getTextPos(); nextJSDocToken(); var tagName = parseJSDocIdentifierName(); @@ -18382,15 +21222,15 @@ var ts; var t; switch (tagName.escapedText) { case "type": - return target === 1 && parseTypeTag(atToken, tagName); + return target === 1 /* Property */ && parseTypeTag(atToken, tagName); case "prop": case "property": - t = 1; + t = 1 /* Property */; break; case "arg": case "argument": case "param": - t = 2 | 4; + t = 2 /* Parameter */ | 4 /* CallbackParameter */; break; default: return false; @@ -18398,29 +21238,30 @@ var ts; if (!(target & t)) { return false; } - var tag = parseParameterOrPropertyTag(atToken, tagName, target, undefined); + var tag = parseParameterOrPropertyTag(atToken, tagName, target, /*indent*/ undefined); tag.comment = parseTagComments(tag.end - tag.pos); return tag; } function parseTemplateTag(atToken, tagName) { + // the template tag looks like '@template {Constraint} T,U,V' var constraint; - if (token() === 17) { + if (token() === 17 /* OpenBraceToken */) { constraint = parseJSDocTypeExpression(); } var typeParameters = []; var typeParametersPos = getNodePos(); do { skipWhitespace(); - var typeParameter = createNode(148); + var typeParameter = createNode(148 /* TypeParameter */); typeParameter.name = parseJSDocIdentifierName(ts.Diagnostics.Unexpected_token_A_type_parameter_name_was_expected_without_curly_braces); skipWhitespace(); finishNode(typeParameter); typeParameters.push(typeParameter); - } while (parseOptionalJsdoc(26)); + } while (parseOptionalJsdoc(26 /* CommaToken */)); if (constraint) { ts.first(typeParameters).constraint = constraint.type; } - var result = createNode(297, atToken.pos); + var result = createNode(297 /* JSDocTemplateTag */, atToken.pos); result.atToken = atToken; result.tagName = tagName; result.typeParameters = createNodeArray(typeParameters, typeParametersPos); @@ -18439,13 +21280,16 @@ var ts; } function parseJSDocEntityName() { var entity = parseJSDocIdentifierName(); - if (parseOptional(21)) { - parseExpected(22); + if (parseOptional(21 /* OpenBracketToken */)) { + parseExpected(22 /* CloseBracketToken */); + // Note that y[] is accepted as an entity name, but the postfix brackets are not saved for checking. + // Technically usejsdoc.org requires them for specifying a property of a type equivalent to Array<{ x: ...}> + // but it's not worth it to enforce that restriction. } - while (parseOptional(23)) { + while (parseOptional(23 /* DotToken */)) { var name = parseJSDocIdentifierName(); - if (parseOptional(21)) { - parseExpected(22); + if (parseOptional(21 /* OpenBracketToken */)) { + parseExpected(22 /* CloseBracketToken */); } entity = createQualifiedName(entity, name); } @@ -18453,11 +21297,11 @@ var ts; } function parseJSDocIdentifierName(message) { if (!ts.tokenIsIdentifierOrKeyword(token())) { - return createMissingNode(71, !message, message || ts.Diagnostics.Identifier_expected); + return createMissingNode(71 /* Identifier */, /*reportAtCurrentPosition*/ !message, message || ts.Diagnostics.Identifier_expected); } var pos = scanner.getTokenPos(); var end = scanner.getTextPos(); - var result = createNode(71, pos); + var result = createNode(71 /* Identifier */, pos); result.escapedText = ts.escapeLeadingUnderscores(scanner.getTokenText()); finishNode(result, end); nextJSDocToken(); @@ -18470,27 +21314,72 @@ var ts; var IncrementalParser; (function (IncrementalParser) { function updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks) { - aggressiveChecks = aggressiveChecks || ts.Debug.shouldAssert(2); + aggressiveChecks = aggressiveChecks || ts.Debug.shouldAssert(2 /* Aggressive */); checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks); if (ts.textChangeRangeIsUnchanged(textChangeRange)) { + // if the text didn't change, then we can just return our current source file as-is. return sourceFile; } if (sourceFile.statements.length === 0) { - return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, undefined, true, sourceFile.scriptKind); + // If we don't have any statements in the current source file, then there's no real + // way to incrementally parse. So just do a full parse instead. + return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true, sourceFile.scriptKind); } + // Make sure we're not trying to incrementally update a source file more than once. Once + // we do an update the original source file is considered unusable from that point onwards. + // + // This is because we do incremental parsing in-place. i.e. we take nodes from the old + // tree and give them new positions and parents. From that point on, trusting the old + // tree at all is not possible as far too much of it may violate invariants. var incrementalSourceFile = sourceFile; ts.Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed); incrementalSourceFile.hasBeenIncrementallyParsed = true; var oldText = sourceFile.text; var syntaxCursor = createSyntaxCursor(sourceFile); + // Make the actual change larger so that we know to reparse anything whose lookahead + // might have intersected the change. var changeRange = extendToAffectedRange(sourceFile, textChangeRange); checkChangeRange(sourceFile, newText, changeRange, aggressiveChecks); + // Ensure that extending the affected range only moved the start of the change range + // earlier in the file. ts.Debug.assert(changeRange.span.start <= textChangeRange.span.start); ts.Debug.assert(ts.textSpanEnd(changeRange.span) === ts.textSpanEnd(textChangeRange.span)); ts.Debug.assert(ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)) === ts.textSpanEnd(ts.textChangeRangeNewSpan(textChangeRange))); + // The is the amount the nodes after the edit range need to be adjusted. It can be + // positive (if the edit added characters), negative (if the edit deleted characters) + // or zero (if this was a pure overwrite with nothing added/removed). var delta = ts.textChangeRangeNewSpan(changeRange).length - changeRange.span.length; + // If we added or removed characters during the edit, then we need to go and adjust all + // the nodes after the edit. Those nodes may move forward (if we inserted chars) or they + // may move backward (if we deleted chars). + // + // Doing this helps us out in two ways. First, it means that any nodes/tokens we want + // to reuse are already at the appropriate position in the new text. That way when we + // reuse them, we don't have to figure out if they need to be adjusted. Second, it makes + // it very easy to determine if we can reuse a node. If the node's position is at where + // we are in the text, then we can reuse it. Otherwise we can't. If the node's position + // is ahead of us, then we'll need to rescan tokens. If the node's position is behind + // us, then we'll need to skip it or crumble it as appropriate + // + // We will also adjust the positions of nodes that intersect the change range as well. + // By doing this, we ensure that all the positions in the old tree are consistent, not + // just the positions of nodes entirely before/after the change range. By being + // consistent, we can then easily map from positions to nodes in the old tree easily. + // + // Also, mark any syntax elements that intersect the changed span. We know, up front, + // that we cannot reuse these elements. updateTokenPositionsAndMarkElements(incrementalSourceFile, changeRange.span.start, ts.textSpanEnd(changeRange.span), ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks); - var result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, true, sourceFile.scriptKind); + // Now that we've set up our internal incremental state just proceed and parse the + // source file in the normal fashion. When possible the parser will retrieve and + // reuse nodes from the old tree. + // + // Note: passing in 'true' for setNodeParents is very important. When incrementally + // parsing, we will be reusing nodes from the old tree, and placing it into new + // parents. If we don't set the parents now, we'll end up with an observably + // inconsistent tree. Setting the parents on the new tree should be very fast. We + // will immediately bail out of walking any subtrees when we can see that their parents + // are already correct. + var result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true, sourceFile.scriptKind); return result; } IncrementalParser.updateSourceFile = updateSourceFile; @@ -18507,6 +21396,8 @@ var ts; if (aggressiveChecks && shouldCheckNode(node)) { text = oldText.substring(node.pos, node.end); } + // Ditch any existing LS children we may have created. This way we can avoid + // moving them forward. if (node._children) { node._children = undefined; } @@ -18536,9 +21427,9 @@ var ts; } function shouldCheckNode(node) { switch (node.kind) { - case 9: - case 8: - case 71: + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: + case 71 /* Identifier */: return true; } return false; @@ -18547,11 +21438,63 @@ var ts; ts.Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range"); ts.Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range"); ts.Debug.assert(element.pos <= element.end); + // We have an element that intersects the change range in some way. It may have its + // start, or its end (or both) in the changed range. We want to adjust any part + // that intersects such that the final tree is in a consistent state. i.e. all + // children have spans within the span of their parent, and all siblings are ordered + // properly. + // We may need to update both the 'pos' and the 'end' of the element. + // If the 'pos' is before the start of the change, then we don't need to touch it. + // If it isn't, then the 'pos' must be inside the change. How we update it will + // depend if delta is positive or negative. If delta is positive then we have + // something like: + // + // -------------------AAA----------------- + // -------------------BBBCCCCCCC----------------- + // + // In this case, we consider any node that started in the change range to still be + // starting at the same position. + // + // however, if the delta is negative, then we instead have something like this: + // + // -------------------XXXYYYYYYY----------------- + // -------------------ZZZ----------------- + // + // In this case, any element that started in the 'X' range will keep its position. + // However any element that started after that will have their pos adjusted to be + // at the end of the new range. i.e. any node that started in the 'Y' range will + // be adjusted to have their start at the end of the 'Z' range. + // + // The element will keep its position if possible. Or Move backward to the new-end + // if it's in the 'Y' range. element.pos = Math.min(element.pos, changeRangeNewEnd); + // If the 'end' is after the change range, then we always adjust it by the delta + // amount. However, if the end is in the change range, then how we adjust it + // will depend on if delta is positive or negative. If delta is positive then we + // have something like: + // + // -------------------AAA----------------- + // -------------------BBBCCCCCCC----------------- + // + // In this case, we consider any node that ended inside the change range to keep its + // end position. + // + // however, if the delta is negative, then we instead have something like this: + // + // -------------------XXXYYYYYYY----------------- + // -------------------ZZZ----------------- + // + // In this case, any element that ended in the 'X' range will keep its position. + // However any element that ended after that will have their pos adjusted to be + // at the end of the new range. i.e. any node that ended in the 'Y' range will + // be adjusted to have their end at the end of the 'Z' range. if (element.end >= changeRangeOldEnd) { + // Element ends after the change range. Always adjust the end pos. element.end += delta; } else { + // Element ends in the change range. The element will keep its position if + // possible. Or Move backward to the new-end if it's in the 'Y' range. element.end = Math.min(element.end, changeRangeNewEnd); } ts.Debug.assert(element.pos <= element.end); @@ -18583,13 +21526,19 @@ var ts; function visitNode(child) { ts.Debug.assert(child.pos <= child.end); if (child.pos > changeRangeOldEnd) { - moveElementEntirelyPastChangeRange(child, false, delta, oldText, newText, aggressiveChecks); + // Node is entirely past the change range. We need to move both its pos and + // end, forward or backward appropriately. + moveElementEntirelyPastChangeRange(child, /*isArray*/ false, delta, oldText, newText, aggressiveChecks); return; } + // Check if the element intersects the change range. If it does, then it is not + // reusable. Also, we'll need to recurse to see what constituent portions we may + // be able to use. var fullEnd = child.end; if (fullEnd >= changeStart) { child.intersectsChange = true; child._children = undefined; + // Adjust the pos or end (or both) of the intersecting element accordingly. adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); forEachChild(child, visitNode, visitArray); if (ts.hasJSDocNodes(child)) { @@ -18601,18 +21550,25 @@ var ts; checkNodePositions(child, aggressiveChecks); return; } + // Otherwise, the node is entirely before the change range. No need to do anything with it. ts.Debug.assert(fullEnd < changeStart); } function visitArray(array) { ts.Debug.assert(array.pos <= array.end); if (array.pos > changeRangeOldEnd) { - moveElementEntirelyPastChangeRange(array, true, delta, oldText, newText, aggressiveChecks); + // Array is entirely after the change range. We need to move it, and move any of + // its children. + moveElementEntirelyPastChangeRange(array, /*isArray*/ true, delta, oldText, newText, aggressiveChecks); return; } + // Check if the element intersects the change range. If it does, then it is not + // reusable. Also, we'll need to recurse to see what constituent portions we may + // be able to use. var fullEnd = array.end; if (fullEnd >= changeStart) { array.intersectsChange = true; array._children = undefined; + // Adjust the pos or end (or both) of the intersecting array accordingly. adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); for (var _i = 0, array_9 = array; _i < array_9.length; _i++) { var node = array_9[_i]; @@ -18620,12 +21576,26 @@ var ts; } return; } + // Otherwise, the array is entirely before the change range. No need to do anything with it. ts.Debug.assert(fullEnd < changeStart); } } function extendToAffectedRange(sourceFile, changeRange) { + // Consider the following code: + // void foo() { /; } + // + // If the text changes with an insertion of / just before the semicolon then we end up with: + // void foo() { //; } + // + // If we were to just use the changeRange a is, then we would not rescan the { token + // (as it does not intersect the actual original change range). Because an edit may + // change the token touching it, we actually need to look back *at least* one token so + // that the prior token sees that change. var maxLookahead = 1; var start = changeRange.span.start; + // the first iteration aligns us with the change start. subsequent iteration move us to + // the left by maxLookahead tokens. We only need to do this as long as we're not at the + // start of the tree. for (var i = 0; start > 0 && i <= maxLookahead; i++) { var nearestNode = findNearestNodeStartingBeforeOrAtPosition(sourceFile, start); ts.Debug.assert(nearestNode.pos <= start); @@ -18660,23 +21630,54 @@ var ts; } function visit(child) { if (ts.nodeIsMissing(child)) { + // Missing nodes are effectively invisible to us. We never even consider them + // When trying to find the nearest node before us. return; } + // If the child intersects this position, then this node is currently the nearest + // node that starts before the position. if (child.pos <= position) { if (child.pos >= bestResult.pos) { + // This node starts before the position, and is closer to the position than + // the previous best node we found. It is now the new best node. bestResult = child; } + // Now, the node may overlap the position, or it may end entirely before the + // position. If it overlaps with the position, then either it, or one of its + // children must be the nearest node before the position. So we can just + // recurse into this child to see if we can find something better. if (position < child.end) { + // The nearest node is either this child, or one of the children inside + // of it. We've already marked this child as the best so far. Recurse + // in case one of the children is better. forEachChild(child, visit); + // Once we look at the children of this node, then there's no need to + // continue any further. return true; } else { ts.Debug.assert(child.end <= position); + // The child ends entirely before this position. Say you have the following + // (where $ is the position) + // + // ? $ : <...> <...> + // + // We would want to find the nearest preceding node in "complex expr 2". + // To support that, we keep track of this node, and once we're done searching + // for a best node, we recurse down this node to see if we can find a good + // result in it. + // + // This approach allows us to quickly skip over nodes that are entirely + // before the position, while still allowing us to find any nodes in the + // last one that might be what we want. lastNodeEntirelyBeforePosition = child; } } else { ts.Debug.assert(child.pos > position); + // We're now at a node that is entirely past the position we're searching for. + // This node (and all following nodes) could never contribute to the result, + // so just skip them by returning 'true' here. return true; } } @@ -18685,7 +21686,7 @@ var ts; var oldText = sourceFile.text; if (textChangeRange) { ts.Debug.assert((oldText.length - textChangeRange.span.length + textChangeRange.newLength) === newText.length); - if (aggressiveChecks || ts.Debug.shouldAssert(3)) { + if (aggressiveChecks || ts.Debug.shouldAssert(3 /* VeryAggressive */)) { var oldTextPrefix = oldText.substr(0, textChangeRange.span.start); var newTextPrefix = newText.substr(0, textChangeRange.span.start); ts.Debug.assert(oldTextPrefix === newTextPrefix); @@ -18700,42 +21701,68 @@ var ts; var currentArrayIndex = 0; ts.Debug.assert(currentArrayIndex < currentArray.length); var current = currentArray[currentArrayIndex]; - var lastQueriedPosition = -1; + var lastQueriedPosition = -1 /* Value */; return { currentNode: function (position) { + // Only compute the current node if the position is different than the last time + // we were asked. The parser commonly asks for the node at the same position + // twice. Once to know if can read an appropriate list element at a certain point, + // and then to actually read and consume the node. if (position !== lastQueriedPosition) { + // Much of the time the parser will need the very next node in the array that + // we just returned a node from.So just simply check for that case and move + // forward in the array instead of searching for the node again. if (current && current.end === position && currentArrayIndex < (currentArray.length - 1)) { currentArrayIndex++; current = currentArray[currentArrayIndex]; } + // If we don't have a node, or the node we have isn't in the right position, + // then try to find a viable node at the position requested. if (!current || current.pos !== position) { findHighestListElementThatStartsAtPosition(position); } } + // Cache this query so that we don't do any extra work if the parser calls back + // into us. Note: this is very common as the parser will make pairs of calls like + // 'isListElement -> parseListElement'. If we were unable to find a node when + // called with 'isListElement', we don't want to redo the work when parseListElement + // is called immediately after. lastQueriedPosition = position; + // Either we don'd have a node, or we have a node at the position being asked for. ts.Debug.assert(!current || current.pos === position); return current; } }; + // Finds the highest element in the tree we can find that starts at the provided position. + // The element must be a direct child of some node list in the tree. This way after we + // return it, we can easily return its next sibling in the list. function findHighestListElementThatStartsAtPosition(position) { + // Clear out any cached state about the last node we found. currentArray = undefined; - currentArrayIndex = -1; + currentArrayIndex = -1 /* Value */; current = undefined; + // Recurse into the source file to find the highest node at this position. forEachChild(sourceFile, visitNode, visitArray); return; function visitNode(node) { if (position >= node.pos && position < node.end) { + // Position was within this node. Keep searching deeper to find the node. forEachChild(node, visitNode, visitArray); + // don't proceed any further in the search. return true; } + // position wasn't in this node, have to keep searching. return false; } function visitArray(array) { if (position >= array.pos && position < array.end) { + // position was in this array. Search through this array to see if we find a + // viable element. for (var i = 0; i < array.length; i++) { var child = array[i]; if (child) { if (child.pos === position) { + // Found the right node. We're done. currentArray = array; currentArrayIndex = i; current = child; @@ -18743,6 +21770,8 @@ var ts; } else { if (child.pos < position && position < child.end) { + // Position in somewhere within this child. Search in it and + // stop searching in this array. forEachChild(child, visitNode, visitArray); return true; } @@ -18750,6 +21779,7 @@ var ts; } } } + // position wasn't in this array, have to keep searching. return false; } } @@ -18760,11 +21790,15 @@ var ts; })(InvalidPosition || (InvalidPosition = {})); })(IncrementalParser || (IncrementalParser = {})); function isDeclarationFileName(fileName) { - return ts.fileExtensionIs(fileName, ".d.ts"); + return ts.fileExtensionIs(fileName, ".d.ts" /* Dts */); } + /*@internal*/ function processCommentPragmas(context, sourceText) { - var triviaScanner = ts.createScanner(context.languageVersion, false, 0, sourceText); + var triviaScanner = ts.createScanner(context.languageVersion, /*skipTrivia*/ false, 0 /* Standard */, sourceText); var pragmas = []; + // Keep scanning all the leading trivia in the file until we get to something that + // isn't trivia. Any single line comment will be analyzed to see if it is a + // reference comment. while (true) { var kind = triviaScanner.scan(); if (!ts.isTrivia(kind)) { @@ -18781,7 +21815,7 @@ var ts; context.pragmas = ts.createMap(); for (var _i = 0, pragmas_1 = pragmas; _i < pragmas_1.length; _i++) { var pragma = pragmas_1[_i]; - if (context.pragmas.has(pragma.name)) { + if (context.pragmas.has(pragma.name)) { // TODO: GH#18217 var currentValue = context.pragmas.get(pragma.name); if (currentValue instanceof Array) { currentValue.push(pragma.args); @@ -18795,6 +21829,7 @@ var ts; } } ts.processCommentPragmas = processCommentPragmas; + /*@internal*/ function processPragmasIntoFields(context, reportDiagnostic) { context.checkJsDirective = undefined; context.referencedFiles = []; @@ -18803,12 +21838,15 @@ var ts; context.amdDependencies = []; context.hasNoDefaultLib = false; context.pragmas.forEach(function (entryOrList, key) { + // TODO: The below should be strongly type-guarded and not need casts/explicit annotations, since entryOrList is related to + // key and key is constrained to a union; but it's not (see GH#21483 for at least partial fix) :( switch (key) { case "reference": { var referencedFiles_1 = context.referencedFiles; var typeReferenceDirectives_1 = context.typeReferenceDirectives; var libReferenceDirectives_1 = context.libReferenceDirectives; ts.forEach(ts.toArray(entryOrList), function (arg) { + // TODO: GH#18217 if (arg.arguments["no-default-lib"]) { context.hasNoDefaultLib = true; } @@ -18828,7 +21866,7 @@ var ts; break; } case "amd-dependency": { - context.amdDependencies = ts.map(ts.toArray(entryOrList), function (x) { return ({ name: x.arguments.name, path: x.arguments.path }); }); + context.amdDependencies = ts.map(ts.toArray(entryOrList), function (x) { return ({ name: x.arguments.name, path: x.arguments.path }); }); // TODO: GH#18217 break; } case "amd-module": { @@ -18836,6 +21874,7 @@ var ts; for (var _i = 0, entryOrList_1 = entryOrList; _i < entryOrList_1.length; _i++) { var entry = entryOrList_1[_i]; if (context.moduleName) { + // TODO: It's probably fine to issue this diagnostic on all instances of the pragma reportDiagnostic(entry.range.pos, entry.range.end - entry.range.pos, ts.Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments); } context.moduleName = entry.arguments.name; @@ -18848,8 +21887,9 @@ var ts; } case "ts-nocheck": case "ts-check": { + // _last_ of either nocheck or check in a file is the "winner" ts.forEach(ts.toArray(entryOrList), function (entry) { - if (!context.checkJsDirective || entry.range.pos > context.checkJsDirective.pos) { + if (!context.checkJsDirective || entry.range.pos > context.checkJsDirective.pos) { // TODO: GH#18217 context.checkJsDirective = { enabled: key === "ts-check", end: entry.range.end, @@ -18859,8 +21899,8 @@ var ts; }); break; } - case "jsx": return; - default: ts.Debug.fail("Unhandled pragma kind"); + case "jsx": return; // Accessed directly + default: ts.Debug.fail("Unhandled pragma kind"); // Can this be made into an assertNever in the future? } }); } @@ -18877,11 +21917,11 @@ var ts; var tripleSlashXMLCommentStartRegEx = /^\/\/\/\s*<(\S+)\s.*?\/>/im; var singleLinePragmaRegEx = /^\/\/\/?\s*@(\S+)\s*(.*)\s*$/im; function extractPragmas(pragmas, range, text) { - var tripleSlash = range.kind === 2 && tripleSlashXMLCommentStartRegEx.exec(text); + var tripleSlash = range.kind === 2 /* SingleLineCommentTrivia */ && tripleSlashXMLCommentStartRegEx.exec(text); if (tripleSlash) { - var name = tripleSlash[1].toLowerCase(); + var name = tripleSlash[1].toLowerCase(); // Technically unsafe cast, but we do it so the below check to make it safe typechecks var pragma = ts.commentPragmas[name]; - if (!pragma || !(pragma.kind & 1)) { + if (!pragma || !(pragma.kind & 1 /* TripleSlashXML */)) { return; } if (pragma.args) { @@ -18891,7 +21931,7 @@ var ts; var matcher = getNamedArgRegEx(arg.name); var matchResult = matcher.exec(text); if (!matchResult && !arg.optional) { - return; + return; // Missing required argument, don't parse } else if (matchResult) { if (arg.captureSpan) { @@ -18914,30 +21954,30 @@ var ts; } return; } - var singleLine = range.kind === 2 && singleLinePragmaRegEx.exec(text); + var singleLine = range.kind === 2 /* SingleLineCommentTrivia */ && singleLinePragmaRegEx.exec(text); if (singleLine) { - return addPragmaForMatch(pragmas, range, 2, singleLine); + return addPragmaForMatch(pragmas, range, 2 /* SingleLine */, singleLine); } - if (range.kind === 3) { - var multiLinePragmaRegEx = /\s*@(\S+)\s*(.*)\s*$/gim; + if (range.kind === 3 /* MultiLineCommentTrivia */) { + var multiLinePragmaRegEx = /\s*@(\S+)\s*(.*)\s*$/gim; // Defined inline since it uses the "g" flag, which keeps a persistent index (for iterating) var multiLineMatch = void 0; while (multiLineMatch = multiLinePragmaRegEx.exec(text)) { - addPragmaForMatch(pragmas, range, 4, multiLineMatch); + addPragmaForMatch(pragmas, range, 4 /* MultiLine */, multiLineMatch); } } } function addPragmaForMatch(pragmas, range, kind, match) { if (!match) return; - var name = match[1].toLowerCase(); + var name = match[1].toLowerCase(); // Technically unsafe cast, but we do it so they below check to make it safe typechecks var pragma = ts.commentPragmas[name]; if (!pragma || !(pragma.kind & kind)) { return; } - var args = match[2]; + var args = match[2]; // Split on spaces and match up positionally with definition var argument = getNamedPragmaArguments(pragma, args); if (argument === "fail") - return; + return; // Missing required argument, fail to parse it pragmas.push({ name: name, args: { arguments: argument, range: range } }); return; } @@ -18960,16 +22000,20 @@ var ts; } return argMap; } + /** @internal */ function tagNamesAreEquivalent(lhs, rhs) { if (lhs.kind !== rhs.kind) { return false; } - if (lhs.kind === 71) { + if (lhs.kind === 71 /* Identifier */) { return lhs.escapedText === rhs.escapedText; } - if (lhs.kind === 99) { + if (lhs.kind === 99 /* ThisKeyword */) { return true; } + // If we are at this statement then we must have PropertyAccessExpression and because tag name in Jsx element can only + // take forms of JsxTagNameExpression which includes an identifier, "this" expression, or another propertyAccessExpression + // it is safe to case the expression property as such. See parseJsxElementName for how we parse tag name in Jsx element return lhs.name.escapedText === rhs.name.escapedText && tagNamesAreEquivalent(lhs.expression, rhs.expression); } @@ -18977,8 +22021,14 @@ var ts; })(ts || (ts = {})); var ts; (function (ts) { + /* @internal */ ts.compileOnSaveCommandLineOption = { name: "compileOnSave", type: "boolean" }; + // NOTE: The order here is important to default lib ordering as entries will have the same + // order in the generated program (see `getDefaultLibPriority` in program.ts). This + // order also affects overload resolution when a type declared in one lib is + // augmented in another lib. var libEntries = [ + // JavaScript only ["es5", "lib.es5.d.ts"], ["es6", "lib.es2015.d.ts"], ["es2015", "lib.es2015.d.ts"], @@ -18987,11 +22037,13 @@ var ts; ["es2017", "lib.es2017.d.ts"], ["es2018", "lib.es2018.d.ts"], ["esnext", "lib.esnext.d.ts"], + // Host only ["dom", "lib.dom.d.ts"], ["dom.iterable", "lib.dom.iterable.d.ts"], ["webworker", "lib.webworker.d.ts"], ["webworker.importscripts", "lib.webworker.importscripts.d.ts"], ["scripthost", "lib.scripthost.d.ts"], + // ES2015 Or ESNext By-feature options ["es2015.core", "lib.es2015.core.d.ts"], ["es2015.collection", "lib.es2015.collection.d.ts"], ["es2015.generator", "lib.es2015.generator.d.ts"], @@ -19014,9 +22066,22 @@ var ts; ["esnext.symbol", "lib.esnext.symbol.d.ts"], ["esnext.asynciterable", "lib.esnext.asynciterable.d.ts"], ]; + /** + * An array of supported "lib" reference file names used to determine the order for inclusion + * when referenced, as well as for spelling suggestions. This ensures the correct ordering for + * overload resolution when a type declared in one lib is extended by another. + */ + /* @internal */ ts.libs = libEntries.map(function (entry) { return entry[0]; }); + /** + * A map of lib names to lib files. This map is used both for parsing the "lib" command line + * option as well as for resolving lib reference directives. + */ + /* @internal */ ts.libMap = ts.createMapFromEntries(libEntries); + /* @internal */ ts.optionDeclarations = [ + // CommandLine only options { name: "help", shortName: "h", @@ -19092,18 +22157,19 @@ var ts; category: ts.Diagnostics.Command_line_Options, description: ts.Diagnostics.Watch_input_files, }, + // Basic { name: "target", shortName: "t", type: ts.createMapFromTemplate({ - es3: 0, - es5: 1, - es6: 2, - es2015: 2, - es2016: 3, - es2017: 4, - es2018: 5, - esnext: 6, + es3: 0 /* ES3 */, + es5: 1 /* ES5 */, + es6: 2 /* ES2015 */, + es2015: 2 /* ES2015 */, + es2016: 3 /* ES2016 */, + es2017: 4 /* ES2017 */, + es2018: 5 /* ES2018 */, + esnext: 6 /* ESNext */, }), paramType: ts.Diagnostics.VERSION, showInSimplifiedHelpView: true, @@ -19155,9 +22221,9 @@ var ts; { name: "jsx", type: ts.createMapFromTemplate({ - "preserve": 1, - "react-native": 3, - "react": 2 + "preserve": 1 /* Preserve */, + "react-native": 3 /* ReactNative */, + "react": 2 /* React */ }), paramType: ts.Diagnostics.KIND, showInSimplifiedHelpView: true, @@ -19257,6 +22323,7 @@ var ts; category: ts.Diagnostics.Basic_Options, description: ts.Diagnostics.Transpile_each_file_as_a_separate_module_similar_to_ts_transpileModule }, + // Strict Type Checks { name: "strict", type: "boolean", @@ -19306,6 +22373,7 @@ var ts; category: ts.Diagnostics.Strict_Type_Checking_Options, description: ts.Diagnostics.Parse_in_strict_mode_and_emit_use_strict_for_each_source_file }, + // Additional Checks { name: "noUnusedLocals", type: "boolean", @@ -19334,6 +22402,7 @@ var ts; category: ts.Diagnostics.Additional_Checks, description: ts.Diagnostics.Report_errors_for_fallthrough_cases_in_switch_statement }, + // Module Resolution { name: "moduleResolution", type: ts.createMapFromTemplate({ @@ -19352,6 +22421,8 @@ var ts; description: ts.Diagnostics.Base_directory_to_resolve_non_absolute_module_names }, { + // this option can only be specified in tsconfig.json + // use type = object to copy the value as-is name: "paths", type: "object", isTSConfigOnly: true, @@ -19359,6 +22430,8 @@ var ts; description: ts.Diagnostics.A_series_of_entries_which_re_map_imports_to_lookup_locations_relative_to_the_baseUrl }, { + // this option can only be specified in tsconfig.json + // use type = object to copy the value as-is name: "rootDirs", type: "list", isTSConfigOnly: true, @@ -19411,6 +22484,7 @@ var ts; category: ts.Diagnostics.Module_Resolution_Options, description: ts.Diagnostics.Do_not_resolve_the_real_path_of_symlinks, }, + // Source Maps { name: "sourceRoot", type: "string", @@ -19437,6 +22511,7 @@ var ts; category: ts.Diagnostics.Source_Map_Options, description: ts.Diagnostics.Emit_the_source_alongside_the_sourcemaps_within_a_single_file_requires_inlineSourceMap_or_sourceMap_to_be_set }, + // Experimental { name: "experimentalDecorators", type: "boolean", @@ -19449,6 +22524,7 @@ var ts; category: ts.Diagnostics.Experimental_Options, description: ts.Diagnostics.Enables_experimental_support_for_emitting_type_metadata_for_decorators }, + // Advanced { name: "jsxFactory", type: "string", @@ -19495,6 +22571,7 @@ var ts; name: "out", type: "string", isFilePath: false, + // for correct behaviour, please use outFile category: ts.Diagnostics.Advanced_Options, paramType: ts.Diagnostics.FILE, description: ts.Diagnostics.Deprecated_Use_outFile_instead_Concatenate_and_emit_output_to_single_file, @@ -19532,8 +22609,8 @@ var ts; { name: "newLine", type: ts.createMapFromTemplate({ - crlf: 0, - lf: 1 + crlf: 0 /* CarriageReturnLineFeed */, + lf: 1 /* LineFeed */ }), paramType: ts.Diagnostics.NEWLINE, category: ts.Diagnostics.Advanced_Options, @@ -19656,6 +22733,7 @@ var ts; description: ts.Diagnostics.Resolve_keyof_to_string_valued_property_names_only_no_numbers_or_symbols, }, { + // A list of plugins to load in the language service name: "plugins", type: "list", isTSConfigOnly: true, @@ -19666,8 +22744,12 @@ var ts; description: ts.Diagnostics.List_of_language_service_plugins } ]; + /* @internal */ ts.typeAcquisitionDeclarations = [ { + /* @deprecated typingOptions.enableAutoDiscovery + * Use typeAcquisition.enable instead. + */ name: "enableAutoDiscovery", type: "boolean", }, @@ -19692,14 +22774,17 @@ var ts; } } ]; + /* @internal */ ts.defaultInitCompilerOptions = { module: ts.ModuleKind.CommonJS, - target: 1, + target: 1 /* ES5 */, strict: true, esModuleInterop: true }; var optionNameMapCache; + /* @internal */ function convertEnableAutoDiscoveryToEnable(typeAcquisition) { + // Convert deprecated typingOptions.enableAutoDiscovery to typeAcquisition.enable if (typeAcquisition && typeAcquisition.enableAutoDiscovery !== undefined && typeAcquisition.enable === undefined) { return { enable: typeAcquisition.enableAutoDiscovery, @@ -19725,6 +22810,7 @@ var ts; optionNameMapCache = { optionNameMap: optionNameMap, shortOptionNames: shortOptionNames }; return optionNameMapCache; } + /* @internal */ function createCompilerDiagnosticForInvalidCustomType(opt) { return createDiagnosticForInvalidCustomType(opt, ts.createCompilerDiagnostic); } @@ -19733,10 +22819,12 @@ var ts; var namesOfType = ts.arrayFrom(opt.type.keys()).map(function (key) { return "'" + key + "'"; }).join(", "); return createDiagnostic(ts.Diagnostics.Argument_for_0_option_must_be_Colon_1, "--" + opt.name, namesOfType); } + /* @internal */ function parseCustomTypeOption(opt, value, errors) { return convertJsonOptionOfCustomType(opt, trimString(value || ""), errors); } ts.parseCustomTypeOption = parseCustomTypeOption; + /* @internal */ function parseListTypeOption(opt, value, errors) { if (value === void 0) { value = ""; } value = trimString(value); @@ -19774,16 +22862,17 @@ var ts; while (i < args.length) { var s = args[i]; i++; - if (s.charCodeAt(0) === 64) { + if (s.charCodeAt(0) === 64 /* at */) { parseResponseFile(s.slice(1)); } - else if (s.charCodeAt(0) === 45) { - var opt = getOptionFromName(s.slice(s.charCodeAt(1) === 45 ? 2 : 1), true); + else if (s.charCodeAt(0) === 45 /* minus */) { + var opt = getOptionFromName(s.slice(s.charCodeAt(1) === 45 /* minus */ ? 2 : 1), /*allowShort*/ true); if (opt) { if (opt.isTSConfigOnly) { errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file, opt.name)); } else { + // Check to see if no argument was provided (e.g. "--locale" is the last command-line argument). if (!args[i] && opt.type !== "boolean") { errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Compiler_option_0_expects_an_argument, opt.name)); } @@ -19793,8 +22882,10 @@ var ts; i++; break; case "boolean": + // boolean flag has optional value true, false, others var optValue = args[i]; options[opt.name] = optValue !== "false"; + // consume next argument as boolean flag value if (optValue === "false" || optValue === "true") { i++; } @@ -19810,6 +22901,7 @@ var ts; i++; } break; + // If not a primitive, the possible types are specified in what is effectively a map of options. default: options[opt.name] = parseCustomTypeOption(opt, args[i], errors); i++; @@ -19835,14 +22927,14 @@ var ts; var args = []; var pos = 0; while (true) { - while (pos < text.length && text.charCodeAt(pos) <= 32) + while (pos < text.length && text.charCodeAt(pos) <= 32 /* space */) pos++; if (pos >= text.length) break; var start = pos; - if (text.charCodeAt(start) === 34) { + if (text.charCodeAt(start) === 34 /* doubleQuote */) { pos++; - while (pos < text.length && text.charCodeAt(pos) !== 34) + while (pos < text.length && text.charCodeAt(pos) !== 34 /* doubleQuote */) pos++; if (pos < text.length) { args.push(text.substring(start + 1, pos)); @@ -19853,7 +22945,7 @@ var ts; } } else { - while (text.charCodeAt(pos) > 32) + while (text.charCodeAt(pos) > 32 /* space */) pos++; args.push(text.substring(start, pos)); } @@ -19862,10 +22954,12 @@ var ts; } } ts.parseCommandLine = parseCommandLine; + /** @internal */ function getOptionFromName(optionName, allowShort) { if (allowShort === void 0) { allowShort = false; } optionName = optionName.toLowerCase(); var _a = getOptionNameMap(), optionNameMap = _a.optionNameMap, shortOptionNames = _a.shortOptionNames; + // Try to translate short option names to their full equivalents. if (allowShort) { var short = shortOptionNames.get(optionName); if (short !== undefined) { @@ -19883,20 +22977,25 @@ var ts; var diagnostic = ts.createCompilerDiagnostic.apply(undefined, arguments); return diagnostic.messageText; } + /* @internal */ function printVersion() { ts.sys.write(getDiagnosticText(ts.Diagnostics.Version_0, ts.version) + ts.sys.newLine); } ts.printVersion = printVersion; + /* @internal */ function printHelp(optionsList, syntaxPrefix) { if (syntaxPrefix === void 0) { syntaxPrefix = ""; } var output = []; + // We want to align our "syntax" and "examples" commands to a certain margin. var syntaxLength = getDiagnosticText(ts.Diagnostics.Syntax_Colon_0, "").length; var examplesLength = getDiagnosticText(ts.Diagnostics.Examples_Colon_0, "").length; var marginLength = Math.max(syntaxLength, examplesLength); + // Build up the syntactic skeleton. var syntax = makePadding(marginLength - syntaxLength); syntax += "tsc " + syntaxPrefix + "[" + getDiagnosticText(ts.Diagnostics.options) + "] [" + getDiagnosticText(ts.Diagnostics.file) + "...]"; output.push(getDiagnosticText(ts.Diagnostics.Syntax_Colon_0, syntax)); output.push(ts.sys.newLine + ts.sys.newLine); + // Build up the list of examples. var padding = makePadding(marginLength); output.push(getDiagnosticText(ts.Diagnostics.Examples_Colon_0, makePadding(marginLength - examplesLength) + "tsc hello.ts") + ts.sys.newLine); output.push(padding + "tsc --outFile file.js file.ts" + ts.sys.newLine); @@ -19904,12 +23003,16 @@ var ts; output.push(padding + "tsc --build tsconfig.json" + ts.sys.newLine); output.push(ts.sys.newLine); output.push(getDiagnosticText(ts.Diagnostics.Options_Colon) + ts.sys.newLine); + // We want our descriptions to align at the same column in our output, + // so we keep track of the longest option usage string. marginLength = 0; - var usageColumn = []; + var usageColumn = []; // Things like "-d, --declaration" go in here. var descriptionColumn = []; - var optionsDescriptionMap = ts.createMap(); + var optionsDescriptionMap = ts.createMap(); // Map between option.description and list of option.type if it is a kind for (var _i = 0, optionsList_1 = optionsList; _i < optionsList_1.length; _i++) { var option = optionsList_1[_i]; + // If an option lacks a description, + // it is not officially supported. if (!option.description) { continue; } @@ -19933,12 +23036,15 @@ var ts; description = getDiagnosticText(option.description); } descriptionColumn.push(description); + // Set the new margin for the description column if necessary. marginLength = Math.max(usageText_1.length, marginLength); } + // Special case that can't fit in the loop. var usageText = " @<" + getDiagnosticText(ts.Diagnostics.file) + ">"; usageColumn.push(usageText); descriptionColumn.push(getDiagnosticText(ts.Diagnostics.Insert_command_line_options_and_files_from_a_file)); marginLength = Math.max(usageText.length, marginLength); + // Print out each row, aligning all the descriptions on the same column. for (var i = 0; i < usageColumn.length; i++) { var usage = usageColumn[i]; var description = descriptionColumn[i]; @@ -19969,6 +23075,9 @@ var ts; } } ts.printHelp = printHelp; + /** + * Reads the config file, reports errors if any and exits if the config file cannot be found + */ function getParsedCommandLineOfConfigFile(configFileName, optionsToExtend, host) { var configFileText; try { @@ -19989,11 +23098,20 @@ var ts; return parseJsonSourceFileConfigFileContent(result, host, ts.getNormalizedAbsolutePath(ts.getDirectoryPath(configFileName), cwd), optionsToExtend, ts.getNormalizedAbsolutePath(configFileName, cwd)); } ts.getParsedCommandLineOfConfigFile = getParsedCommandLineOfConfigFile; + /** + * Read tsconfig.json file + * @param fileName The path to the config file + */ function readConfigFile(fileName, readFile) { var textOrDiagnostic = tryReadFile(fileName, readFile); return ts.isString(textOrDiagnostic) ? parseConfigFileTextToJson(fileName, textOrDiagnostic) : { config: {}, error: textOrDiagnostic }; } ts.readConfigFile = readConfigFile; + /** + * Parse the text of the tsconfig.json file + * @param fileName The path to the config file + * @param jsonText The text of the config file + */ function parseConfigFileTextToJson(fileName, jsonText) { var jsonSourceFile = ts.parseJsonText(fileName, jsonText); return { @@ -20002,6 +23120,10 @@ var ts; }; } ts.parseConfigFileTextToJson = parseConfigFileTextToJson; + /** + * Read tsconfig.json file + * @param fileName The path to the config file + */ function readJsonConfigFile(fileName, readFile) { var textOrDiagnostic = tryReadFile(fileName, readFile); return ts.isString(textOrDiagnostic) ? ts.parseJsonText(fileName, textOrDiagnostic) : { parseDiagnostics: [textOrDiagnostic] }; @@ -20087,10 +23209,19 @@ var ts; } return _tsconfigRootOptions; } + /** + * Convert the json syntax tree into the json value + */ function convertToObject(sourceFile, errors) { - return convertToObjectWorker(sourceFile, errors, true, undefined, undefined); + return convertToObjectWorker(sourceFile, errors, /*returnValue*/ true, /*knownRootOptions*/ undefined, /*jsonConversionNotifier*/ undefined); } ts.convertToObject = convertToObject; + /** + * Convert the json syntax tree into the json value and report errors + * This returns the json value (apart from checking errors) only if returnValue provided is true. + * Otherwise it just checks the errors and returns undefined + */ + /*@internal*/ function convertToObjectWorker(sourceFile, errors, returnValue, knownRootOptions, jsonConversionNotifier) { if (!sourceFile.statements.length) { return returnValue ? {} : undefined; @@ -20103,7 +23234,7 @@ var ts; var result = returnValue ? {} : undefined; for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { var element = _a[_i]; - if (element.kind !== 270) { + if (element.kind !== 270 /* PropertyAssignment */) { errors.push(ts.createDiagnosticForNodeInSourceFile(sourceFile, element, ts.Diagnostics.Property_assignment_expected)); continue; } @@ -20123,19 +23254,24 @@ var ts; if (returnValue) { result[keyText] = value; } + // Notify key value set, if user asked for it if (jsonConversionNotifier && + // Current callbacks are only on known parent option or if we are setting values in the root (parentOption || isRootOptionMap(knownOptions))) { var isValidOptionValue = isCompilerOptionsValue(option, value); if (parentOption) { if (isValidOptionValue) { + // Notify option set in the parent if its a valid option value jsonConversionNotifier.onSetValidOptionKeyValueInParent(parentOption, option, value); } } else if (isRootOptionMap(knownOptions)) { if (isValidOptionValue) { + // Notify about the valid root key value being set jsonConversionNotifier.onSetValidOptionKeyValueInRoot(keyText, element.name, value, element.initializer); } else if (!option) { + // Notify about the unknown root key value being set jsonConversionNotifier.onSetUnknownOptionKeyValueInRoot(keyText, element.name, value, element.initializer); } } @@ -20149,16 +23285,16 @@ var ts; } function convertPropertyValueToJson(valueExpression, option) { switch (valueExpression.kind) { - case 101: + case 101 /* TrueKeyword */: reportInvalidOptionValue(option && option.type !== "boolean"); return true; - case 86: + case 86 /* FalseKeyword */: reportInvalidOptionValue(option && option.type !== "boolean"); return false; - case 95: - reportInvalidOptionValue(option && option.name === "extends"); - return null; - case 9: + case 95 /* NullKeyword */: + reportInvalidOptionValue(option && option.name === "extends"); // "extends" is the only option we don't allow null/undefined for + return null; // tslint:disable-line:no-null-keyword + case 9 /* StringLiteral */: if (!isDoubleQuotedString(valueExpression)) { errors.push(ts.createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, ts.Diagnostics.String_literal_with_double_quotes_expected)); } @@ -20166,36 +23302,45 @@ var ts; var text = valueExpression.text; if (option && !ts.isString(option.type)) { var customOption = option; + // Validate custom option type if (!customOption.type.has(text.toLowerCase())) { errors.push(createDiagnosticForInvalidCustomType(customOption, function (message, arg0, arg1) { return ts.createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, message, arg0, arg1); })); } } return text; - case 8: + case 8 /* NumericLiteral */: reportInvalidOptionValue(option && option.type !== "number"); return Number(valueExpression.text); - case 198: - if (valueExpression.operator !== 38 || valueExpression.operand.kind !== 8) { - break; + case 198 /* PrefixUnaryExpression */: + if (valueExpression.operator !== 38 /* MinusToken */ || valueExpression.operand.kind !== 8 /* NumericLiteral */) { + break; // not valid JSON syntax } reportInvalidOptionValue(option && option.type !== "number"); return -Number(valueExpression.operand.text); - case 184: + case 184 /* ObjectLiteralExpression */: reportInvalidOptionValue(option && option.type !== "object"); var objectLiteralExpression = valueExpression; + // Currently having element option declaration in the tsconfig with type "object" + // determines if it needs onSetValidOptionKeyValueInParent callback or not + // At moment there are only "compilerOptions", "typeAcquisition" and "typingOptions" + // that satifies it and need it to modify options set in them (for normalizing file paths) + // vs what we set in the json + // If need arises, we can modify this interface and callbacks as needed if (option) { var _a = option, elementOptions = _a.elementOptions, extraKeyDiagnosticMessage = _a.extraKeyDiagnosticMessage, optionName = _a.name; return convertObjectLiteralExpressionToJson(objectLiteralExpression, elementOptions, extraKeyDiagnosticMessage, optionName); } else { - return convertObjectLiteralExpressionToJson(objectLiteralExpression, undefined, undefined, undefined); + return convertObjectLiteralExpressionToJson(objectLiteralExpression, /* knownOptions*/ undefined, + /*extraKeyDiagnosticMessage */ undefined, /*parentOption*/ undefined); } - case 183: + case 183 /* ArrayLiteralExpression */: reportInvalidOptionValue(option && option.type !== "list"); return convertArrayLiteralExpressionToJson(valueExpression.elements, option && option.element); } + // Not in expected format if (option) { - reportInvalidOptionValue(true); + reportInvalidOptionValue(/*isError*/ true); } else { errors.push(ts.createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, ts.Diagnostics.Property_value_can_only_be_string_literal_numeric_literal_true_false_null_object_literal_or_array_literal)); @@ -20220,7 +23365,7 @@ var ts; function isCompilerOptionsValue(option, value) { if (option) { if (isNullOrUndefined(value)) - return true; + return true; // All options are undefinable/nullable if (option.type === "list") { return ts.isArray(value); } @@ -20229,12 +23374,19 @@ var ts; } return false; } + /** + * Generate tsconfig configuration when running command line "--init" + * @param options commandlineOptions to be generated into tsconfig.json + * @param fileNames array of filenames to be generated into tsconfig.json + */ + /* @internal */ function generateTSConfig(options, fileNames, newLine) { var compilerOptions = ts.extend(options, ts.defaultInitCompilerOptions); var compilerOptionsMap = serializeCompilerOptions(compilerOptions); return writeConfigurations(); function getCustomTypeMapOfCommandLineOption(optionDefinition) { if (optionDefinition.type === "string" || optionDefinition.type === "number" || optionDefinition.type === "boolean") { + // this is of a type CommandLineOptionOfPrimitiveType return undefined; } else if (optionDefinition.type === "list") { @@ -20245,6 +23397,7 @@ var ts; } } function getNameOfCompilerOptionValue(value, customTypeMap) { + // There is a typeMap associated with this command-line option so use it to map value back to its name return ts.forEachEntry(customTypeMap, function (mapValue, key) { if (mapValue === value) { return key; @@ -20256,6 +23409,8 @@ var ts; var optionsNameMap = getOptionNameMap().optionNameMap; var _loop_3 = function (name) { if (ts.hasProperty(options, name)) { + // tsconfig only options cannot be specified via command line, + // so we can assume that only types that can appear here string | number | boolean if (optionsNameMap.has(name) && optionsNameMap.get(name).category === ts.Diagnostics.Command_line_Options) { return "continue"; } @@ -20264,13 +23419,16 @@ var ts; if (optionDefinition) { var customTypeMap_1 = getCustomTypeMapOfCommandLineOption(optionDefinition); if (!customTypeMap_1) { + // There is no map associated with this compiler option then use the value as-is + // This is the case if the value is expect to be string, number, boolean or list of string result.set(name, value); } else { if (optionDefinition.type === "list") { - result.set(name, value.map(function (element) { return getNameOfCompilerOptionValue(element, customTypeMap_1); })); + result.set(name, value.map(function (element) { return getNameOfCompilerOptionValue(element, customTypeMap_1); })); // TODO: GH#18217 } else { + // There is a typeMap associated with this command-line option so use it to map value back to its name result.set(name, getNameOfCompilerOptionValue(value, customTypeMap_1)); } } @@ -20303,11 +23461,14 @@ var ts; } function isAllowedOption(_a) { var category = _a.category, name = _a.name; + // Skip options which do not have a category or have category `Command_line_Options` + // Exclude all possible `Advanced_Options` in tsconfig.json which were NOT defined in command line return category !== undefined && category !== ts.Diagnostics.Command_line_Options && (category !== ts.Diagnostics.Advanced_Options || compilerOptionsMap.has(name)); } function writeConfigurations() { + // Filter applicable options to place in the file var categorizedOptions = ts.createMultiMap(); for (var _i = 0, optionDeclarations_1 = ts.optionDeclarations; _i < optionDeclarations_1.length; _i++) { var option = optionDeclarations_1[_i]; @@ -20316,6 +23477,7 @@ var ts; categorizedOptions.add(ts.getLocaleSpecificMessage(category), option); } } + // Serialize all options and their descriptions var marginLength = 0; var seenKnownKeys = 0; var nameColumn = []; @@ -20341,10 +23503,12 @@ var ts; marginLength = Math.max(optionName.length, marginLength); } }); + // Write the output var tab = makePadding(2); var result = []; result.push("{"); result.push(tab + "\"compilerOptions\": {"); + // Print out each row, aligning all the descriptions on the same column. for (var i = 0; i < nameColumn.length; i++) { var optionName = nameColumn[i]; var description = descriptionColumn[i]; @@ -20366,14 +23530,29 @@ var ts; } } ts.generateTSConfig = generateTSConfig; + /** + * Parse the contents of a config file (tsconfig.json). + * @param json The contents of the config file to parse + * @param host Instance of ParseConfigHost used to enumerate files in folder. + * @param basePath A root directory to resolve relative path entries in the config + * file to. e.g. outDir + */ function parseJsonConfigFileContent(json, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions) { - return parseJsonConfigFileContentWorker(json, undefined, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions); + return parseJsonConfigFileContentWorker(json, /*sourceFile*/ undefined, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions); } ts.parseJsonConfigFileContent = parseJsonConfigFileContent; + /** + * Parse the contents of a config file (tsconfig.json). + * @param jsonNode The contents of the config file to parse + * @param host Instance of ParseConfigHost used to enumerate files in folder. + * @param basePath A root directory to resolve relative path entries in the config + * file to. e.g. outDir + */ function parseJsonSourceFileConfigFileContent(sourceFile, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions) { - return parseJsonConfigFileContentWorker(undefined, sourceFile, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions); + return parseJsonConfigFileContentWorker(/*json*/ undefined, sourceFile, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions); } ts.parseJsonSourceFileConfigFileContent = parseJsonSourceFileConfigFileContent; + /*@internal*/ function setConfigFileInOptions(options, configFile) { if (configFile) { Object.defineProperty(options, "configFile", { enumerable: false, writable: false, value: configFile }); @@ -20381,11 +23560,23 @@ var ts; } ts.setConfigFileInOptions = setConfigFileInOptions; function isNullOrUndefined(x) { + // tslint:disable-next-line:no-null-keyword return x === undefined || x === null; } function directoryOfCombinedPath(fileName, basePath) { + // Use the `getNormalizedAbsolutePath` function to avoid canonicalizing the path, as it must remain noncanonical + // until consistient casing errors are reported return ts.getDirectoryPath(ts.getNormalizedAbsolutePath(fileName, basePath)); } + /** + * Parse the contents of a config file from json or json source file (tsconfig.json). + * @param json The contents of the config file to parse + * @param sourceFile sourceFile corresponding to the Json + * @param host Instance of ParseConfigHost used to enumerate files in folder. + * @param basePath A root directory to resolve relative path entries in the config + * file to. e.g. outDir + * @param resolutionStack Only present for backwards-compatibility. Should be empty. + */ function parseJsonConfigFileContentWorker(json, sourceFile, host, basePath, existingOptions, configFileName, resolutionStack, extraFileExtensions) { if (existingOptions === void 0) { existingOptions = {}; } if (resolutionStack === void 0) { resolutionStack = []; } @@ -20485,10 +23676,12 @@ var ts; } } } + /*@internal*/ function isErrorNoInputFiles(error) { return error.code === ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code; } ts.isErrorNoInputFiles = isErrorNoInputFiles; + /*@internal*/ function getErrorForNoInputFiles(_a, configFileName) { var includeSpecs = _a.includeSpecs, excludeSpecs = _a.excludeSpecs; return ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, configFileName || "tsconfig.json", JSON.stringify(includeSpecs || []), JSON.stringify(excludeSpecs || [])); @@ -20497,6 +23690,10 @@ var ts; function isSuccessfulParsedTsconfig(value) { return !!value.options; } + /** + * This *just* extracts options/include/exclude/files out of a config file. + * It does *not* resolve the included files. + */ function parseConfig(json, sourceFile, host, basePath, configFileName, resolutionStack, errors) { basePath = ts.normalizeSlashes(basePath); var resolvedPath = ts.getNormalizedAbsolutePath(configFileName || "", basePath); @@ -20508,6 +23705,7 @@ var ts; parseOwnConfigOfJson(json, host, basePath, configFileName, errors) : parseOwnConfigOfJsonSourceFile(sourceFile, host, basePath, configFileName, errors); if (ownConfig.extendedConfigPath) { + // copy the resolution stack so it is never reused between branches in potential diamond-problem scenarios. resolutionStack = resolutionStack.concat([resolvedPath]); var extendedConfig = getExtendedConfig(sourceFile, ownConfig.extendedConfigPath, host, basePath, resolutionStack, errors); if (extendedConfig && isSuccessfulParsedTsconfig(extendedConfig)) { @@ -20526,6 +23724,7 @@ var ts; raw_1.compileOnSave = baseRaw_1.compileOnSave; } ownConfig.options = ts.assign({}, extendedConfig.options, ownConfig.options); + // TODO extend type typeAcquisition } } return ownConfig; @@ -20535,6 +23734,8 @@ var ts; errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unknown_option_excludes_Did_you_mean_exclude)); } var options = convertCompilerOptionsFromJsonWorker(json.compilerOptions, basePath, errors, configFileName); + // typingOptions has been deprecated and is only supported for backward compatibility purposes. + // It should be removed in future releases - use typeAcquisition instead. var typeAcquisition = convertTypeAcquisitionFromJsonWorker(json.typeAcquisition || json.typingOptions, basePath, errors, configFileName); json.compileOnSave = convertCompileOnSaveOptionFromJson(json, basePath, errors); var extendedConfigPath; @@ -20584,7 +23785,7 @@ var ts; } } }; - var json = convertToObjectWorker(sourceFile, errors, true, getTsconfigRootOptionsMap(), optionsIterator); + var json = convertToObjectWorker(sourceFile, errors, /*returnValue*/ true, getTsconfigRootOptionsMap(), optionsIterator); if (!typeAcquisition) { if (typingOptionstypeAcquisition) { typeAcquisition = (typingOptionstypeAcquisition.enableAutoDiscovery !== undefined) ? @@ -20603,12 +23804,13 @@ var ts; } function getExtendsConfigPath(extendedConfig, host, basePath, errors, createDiagnostic) { extendedConfig = ts.normalizeSlashes(extendedConfig); + // If the path isn't a rooted or relative path, don't try to resolve it (we reserve the right to special case module-id like paths in the future) if (!(ts.isRootedDiskPath(extendedConfig) || ts.startsWith(extendedConfig, "./") || ts.startsWith(extendedConfig, "../"))) { errors.push(createDiagnostic(ts.Diagnostics.A_path_in_an_extends_option_must_be_relative_or_rooted_but_0_is_not, extendedConfig)); return undefined; } var extendedConfigPath = ts.getNormalizedAbsolutePath(extendedConfig, basePath); - if (!host.fileExists(extendedConfigPath) && !ts.endsWith(extendedConfigPath, ".json")) { + if (!host.fileExists(extendedConfigPath) && !ts.endsWith(extendedConfigPath, ".json" /* Json */)) { extendedConfigPath = extendedConfigPath + ".json"; if (!host.fileExists(extendedConfigPath)) { errors.push(createDiagnostic(ts.Diagnostics.File_0_does_not_exist, extendedConfig)); @@ -20628,11 +23830,12 @@ var ts; return undefined; } var extendedDirname = ts.getDirectoryPath(extendedConfigPath); - var extendedConfig = parseConfig(undefined, extendedResult, host, extendedDirname, ts.getBaseFileName(extendedConfigPath), resolutionStack, errors); + var extendedConfig = parseConfig(/*json*/ undefined, extendedResult, host, extendedDirname, ts.getBaseFileName(extendedConfigPath), resolutionStack, errors); if (sourceFile) { (_a = sourceFile.extendedSourceFiles).push.apply(_a, extendedResult.extendedSourceFiles); } if (isSuccessfulParsedTsconfig(extendedConfig)) { + // Update the paths to reflect base path var relativeDifference_1 = ts.convertToRelativePath(extendedDirname, basePath, ts.identity); var updatePath_1 = function (path) { return ts.isRootedDiskPath(path) ? path : ts.combinePaths(relativeDifference_1, path); }; var mapPropertiesInRawIfNotUndefined = function (propertyName) { @@ -20761,31 +23964,118 @@ var ts; function trimString(s) { return typeof s.trim === "function" ? s.trim() : s.replace(/^[\s]+|[\s]+$/g, ""); } + /** + * Tests for a path that ends in a recursive directory wildcard. + * Matches **, \**, **\, and \**\, but not a**b. + * + * NOTE: used \ in place of / above to avoid issues with multiline comments. + * + * Breakdown: + * (^|\/) # matches either the beginning of the string or a directory separator. + * \*\* # matches the recursive directory wildcard "**". + * \/?$ # matches an optional trailing directory separator at the end of the string. + */ var invalidTrailingRecursionPattern = /(^|\/)\*\*\/?$/; + /** + * Tests for a path where .. appears after a recursive directory wildcard. + * Matches **\..\*, **\a\..\*, and **\.., but not ..\**\* + * + * NOTE: used \ in place of / above to avoid issues with multiline comments. + * + * Breakdown: + * (^|\/) # matches either the beginning of the string or a directory separator. + * \*\*\/ # matches a recursive directory wildcard "**" followed by a directory separator. + * (.*\/)? # optionally matches any number of characters followed by a directory separator. + * \.\. # matches a parent directory path component ".." + * ($|\/) # matches either the end of the string or a directory separator. + */ var invalidDotDotAfterRecursiveWildcardPattern = /(^|\/)\*\*\/(.*\/)?\.\.($|\/)/; + /** + * Tests for a path containing a wildcard character in a directory component of the path. + * Matches \*\, \?\, and \a*b\, but not \a\ or \a\*. + * + * NOTE: used \ in place of / above to avoid issues with multiline comments. + * + * Breakdown: + * \/ # matches a directory separator. + * [^/]*? # matches any number of characters excluding directory separators (non-greedy). + * [*?] # matches either a wildcard character (* or ?) + * [^/]* # matches any number of characters excluding directory separators (greedy). + * \/ # matches a directory separator. + */ var watchRecursivePattern = /\/[^/]*?[*?][^/]*\//; + /** + * Matches the portion of a wildcard path that does not contain wildcards. + * Matches \a of \a\*, or \a\b\c of \a\b\c\?\d. + * + * NOTE: used \ in place of / above to avoid issues with multiline comments. + * + * Breakdown: + * ^ # matches the beginning of the string + * [^*?]* # matches any number of non-wildcard characters + * (?=\/[^/]*[*?]) # lookahead that matches a directory separator followed by + * # a path component that contains at least one wildcard character (* or ?). + */ var wildcardDirectoryPattern = /^[^*?]*(?=\/[^/]*[*?])/; + /** + * Expands an array of file specifications. + * + * @param filesSpecs The literal file names to include. + * @param includeSpecs The wildcard file specifications to include. + * @param excludeSpecs The wildcard file specifications to exclude. + * @param basePath The base path for any relative file specifications. + * @param options Compiler options. + * @param host The host used to resolve files and directories. + * @param errors An array for diagnostic reporting. + */ function matchFileNames(filesSpecs, includeSpecs, excludeSpecs, basePath, options, host, errors, extraFileExtensions, jsonSourceFile) { basePath = ts.normalizePath(basePath); var validatedIncludeSpecs, validatedExcludeSpecs; + // The exclude spec list is converted into a regular expression, which allows us to quickly + // test whether a file or directory should be excluded before recursively traversing the + // file system. if (includeSpecs) { - validatedIncludeSpecs = validateSpecs(includeSpecs, errors, false, jsonSourceFile, "include"); + validatedIncludeSpecs = validateSpecs(includeSpecs, errors, /*allowTrailingRecursion*/ false, jsonSourceFile, "include"); } if (excludeSpecs) { - validatedExcludeSpecs = validateSpecs(excludeSpecs, errors, true, jsonSourceFile, "exclude"); + validatedExcludeSpecs = validateSpecs(excludeSpecs, errors, /*allowTrailingRecursion*/ true, jsonSourceFile, "exclude"); } + // Wildcard directories (provided as part of a wildcard path) are stored in a + // file map that marks whether it was a regular wildcard match (with a `*` or `?` token), + // or a recursive directory. This information is used by filesystem watchers to monitor for + // new entries in these paths. var wildcardDirectories = getWildcardDirectories(validatedIncludeSpecs, validatedExcludeSpecs, basePath, host.useCaseSensitiveFileNames); var spec = { filesSpecs: filesSpecs, referencesSpecs: undefined, includeSpecs: includeSpecs, excludeSpecs: excludeSpecs, validatedIncludeSpecs: validatedIncludeSpecs, validatedExcludeSpecs: validatedExcludeSpecs, wildcardDirectories: wildcardDirectories }; return getFileNamesFromConfigSpecs(spec, basePath, options, host, extraFileExtensions); } + /** + * Gets the file names from the provided config file specs that contain, files, include, exclude and + * other properties needed to resolve the file names + * @param spec The config file specs extracted with file names to include, wildcards to include/exclude and other details + * @param basePath The base path for any relative file specifications. + * @param options Compiler options. + * @param host The host used to resolve files and directories. + * @param extraFileExtensions optionaly file extra file extension information from host + */ + /* @internal */ function getFileNamesFromConfigSpecs(spec, basePath, options, host, extraFileExtensions) { if (extraFileExtensions === void 0) { extraFileExtensions = []; } basePath = ts.normalizePath(basePath); var keyMapper = host.useCaseSensitiveFileNames ? ts.identity : ts.toLowerCase; + // Literal file names (provided via the "files" array in tsconfig.json) are stored in a + // file map with a possibly case insensitive key. We use this map later when when including + // wildcard paths. var literalFileMap = ts.createMap(); + // Wildcard paths (provided via the "includes" array in tsconfig.json) are stored in a + // file map with a possibly case insensitive key. We use this map to store paths matched + // via wildcard, and to handle extension priority. var wildcardFileMap = ts.createMap(); var filesSpecs = spec.filesSpecs, validatedIncludeSpecs = spec.validatedIncludeSpecs, validatedExcludeSpecs = spec.validatedExcludeSpecs, wildcardDirectories = spec.wildcardDirectories; + // Rather than requery this for each file and filespec, we query the supported extensions + // once and store it on the expansion context. var supportedExtensions = ts.getSupportedExtensions(options, extraFileExtensions); + // Literal files are always included verbatim. An "include" or "exclude" specification cannot + // remove a literal file. if (filesSpecs) { for (var _i = 0, filesSpecs_1 = filesSpecs; _i < filesSpecs_1.length; _i++) { var fileName = filesSpecs_1[_i]; @@ -20794,11 +24084,21 @@ var ts; } } if (validatedIncludeSpecs && validatedIncludeSpecs.length > 0) { - for (var _a = 0, _b = host.readDirectory(basePath, supportedExtensions, validatedExcludeSpecs, validatedIncludeSpecs, undefined); _a < _b.length; _a++) { + for (var _a = 0, _b = host.readDirectory(basePath, supportedExtensions, validatedExcludeSpecs, validatedIncludeSpecs, /*depth*/ undefined); _a < _b.length; _a++) { var file = _b[_a]; + // If we have already included a literal or wildcard path with a + // higher priority extension, we should skip this file. + // + // This handles cases where we may encounter both .ts and + // .d.ts (or .js if "allowJs" is enabled) in the same + // directory when they are compilation outputs. if (hasFileWithHigherPriorityExtension(file, literalFileMap, wildcardFileMap, supportedExtensions, keyMapper)) { continue; } + // We may have included a wildcard path with a lower priority + // extension due to the user-defined order of entries in the + // "include" array. If there is a lower priority extension in the + // same directory, we should remove it. removeWildcardFilesWithLowerPriorityExtension(file, wildcardFileMap, supportedExtensions, keyMapper); var key = keyMapper(file); if (!literalFileMap.has(key) && !wildcardFileMap.has(key)) { @@ -20842,7 +24142,22 @@ var ts; return ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0; } } + /** + * Gets directories in a set of include patterns that should be watched for changes. + */ function getWildcardDirectories(include, exclude, path, useCaseSensitiveFileNames) { + // We watch a directory recursively if it contains a wildcard anywhere in a directory segment + // of the pattern: + // + // /a/b/**/d - Watch /a/b recursively to catch changes to any d in any subfolder recursively + // /a/b/*/d - Watch /a/b recursively to catch any d in any immediate subfolder, even if a new subfolder is added + // /a/b - Watch /a/b recursively to catch changes to anything in any recursive subfoler + // + // We watch a directory without recursion if it contains a wildcard in the file segment of + // the pattern: + // + // /a/b/* - Watch /a/b directly to catch any new file + // /a/b/a?z - Watch /a/b directly to catch any new file matching a?z var rawExcludeRegex = ts.getRegularExpressionForWildcard(exclude, path, "exclude"); var excludeRegex = rawExcludeRegex && new RegExp(rawExcludeRegex, useCaseSensitiveFileNames ? "" : "i"); var wildcardDirectories = {}; @@ -20860,12 +24175,13 @@ var ts; var existingFlags = wildcardDirectories[key]; if (existingFlags === undefined || existingFlags < flags) { wildcardDirectories[key] = flags; - if (flags === 1) { + if (flags === 1 /* Recursive */) { recursiveKeys.push(key); } } } } + // Remove any subpaths under an existing recursively watched directory. for (var key in wildcardDirectories) { if (ts.hasProperty(wildcardDirectories, key)) { for (var _a = 0, recursiveKeys_1 = recursiveKeys; _a < recursiveKeys_1.length; _a++) { @@ -20884,18 +24200,26 @@ var ts; if (match) { return { key: useCaseSensitiveFileNames ? match[0] : match[0].toLowerCase(), - flags: watchRecursivePattern.test(spec) ? 1 : 0 + flags: watchRecursivePattern.test(spec) ? 1 /* Recursive */ : 0 /* None */ }; } if (ts.isImplicitGlob(spec)) { - return { key: spec, flags: 1 }; + return { key: spec, flags: 1 /* Recursive */ }; } return undefined; } + /** + * Determines whether a literal or wildcard file has already been included that has a higher + * extension priority. + * + * @param file The path to the file. + * @param extensionPriority The priority of the extension. + * @param context The expansion context. + */ function hasFileWithHigherPriorityExtension(file, literalFiles, wildcardFiles, extensions, keyMapper) { var extensionPriority = ts.getExtensionPriority(file, extensions); var adjustedExtensionPriority = ts.adjustExtensionPriority(extensionPriority, extensions); - for (var i = 0; i < adjustedExtensionPriority; i++) { + for (var i = 0 /* Highest */; i < adjustedExtensionPriority; i++) { var higherPriorityExtension = extensions[i]; var higherPriorityPath = keyMapper(ts.changeExtension(file, higherPriorityExtension)); if (literalFiles.has(higherPriorityPath) || wildcardFiles.has(higherPriorityPath)) { @@ -20904,6 +24228,14 @@ var ts; } return false; } + /** + * Removes files included via wildcard expansion with a lower extension priority that have + * already been included. + * + * @param file The path to the file. + * @param extensionPriority The priority of the extension. + * @param context The expansion context. + */ function removeWildcardFilesWithLowerPriorityExtension(file, wildcardFiles, extensions, keyMapper) { var extensionPriority = ts.getExtensionPriority(file, extensions); var nextExtensionPriority = ts.getNextLowestExtensionPriority(extensionPriority, extensions); @@ -20913,12 +24245,17 @@ var ts; wildcardFiles.delete(lowerPriorityPath); } } + /** + * Produces a cleaned version of compiler options with personally identifiying info (aka, paths) removed. + * Also converts enum values back to strings. + */ + /* @internal */ function convertCompilerOptionsForTelemetry(opts) { var out = {}; for (var key in opts) { if (opts.hasOwnProperty(key)) { var type = getOptionFromName(key); - if (type !== undefined) { + if (type !== undefined) { // Ignore unknown options out[key] = getOptionValueWithEmptyStrings(opts[key], type); } } @@ -20928,11 +24265,11 @@ var ts; ts.convertCompilerOptionsForTelemetry = convertCompilerOptionsForTelemetry; function getOptionValueWithEmptyStrings(value, option) { switch (option.type) { - case "object": + case "object": // "paths". Can't get any useful information from the value since we blank out strings, so just return "". return ""; - case "string": + case "string": // Could be any arbitrary string -- use empty string instead. return ""; - case "number": + case "number": // Allow numbers, but be sure to check it's actually a number. return typeof value === "number" ? value : ""; case "boolean": return typeof value === "boolean" ? value : ""; @@ -20944,7 +24281,7 @@ var ts; if (optionEnumValue === value) { return optionStringValue; } - }); + }); // TODO: GH#18217 } } })(ts || (ts = {})); @@ -20954,6 +24291,7 @@ var ts; host.trace(ts.formatMessage.apply(undefined, arguments)); } ts.trace = trace; + /* @internal */ function isTraceEnabled(compilerOptions, host) { return !!compilerOptions.traceResolution && host.trace !== undefined; } @@ -20962,15 +24300,20 @@ var ts; return r && { path: r.path, extension: r.ext, packageId: packageId }; } function noPackageId(r) { - return withPackageId(undefined, r); + return withPackageId(/*packageId*/ undefined, r); } + /** + * Kinds of file that we are currently looking for. + * Typically there is one pass with Extensions.TypeScript, then a second pass with Extensions.JavaScript. + */ var Extensions; (function (Extensions) { Extensions[Extensions["TypeScript"] = 0] = "TypeScript"; Extensions[Extensions["JavaScript"] = 1] = "JavaScript"; Extensions[Extensions["Json"] = 2] = "Json"; - Extensions[Extensions["DtsOnly"] = 3] = "DtsOnly"; + Extensions[Extensions["DtsOnly"] = 3] = "DtsOnly"; /** Only '.d.ts' */ })(Extensions || (Extensions = {})); + /** Used with `Extensions.DtsOnly` to extract the path from TypeScript results. */ function resolvedTypeScriptOnly(resolved) { if (!resolved) { return undefined; @@ -20984,6 +24327,7 @@ var ts; failedLookupLocations: failedLookupLocations }; } + /** Reads from "main" or "types"/"typings" depending on `extensions`. */ function tryReadPackageJsonFields(readTypes, jsonContent, baseDirectory, state) { return readTypes ? tryReadFromField("typings") || tryReadFromField("types") : tryReadFromField("main"); function tryReadFromField(fieldName) { @@ -21007,6 +24351,7 @@ var ts; return path; } } + /* @internal */ function readJson(path, host) { try { var jsonText = host.readFile(path); @@ -21019,6 +24364,7 @@ var ts; return result.config; } catch (e) { + // gracefully handle if readFile fails or returns not JSON return {}; } } @@ -21039,9 +24385,14 @@ var ts; } } ts.getEffectiveTypeRoots = getEffectiveTypeRoots; + /** + * Returns the path to every node_modules/@types directory from some ancestor directory. + * Returns undefined if there are none. + */ function getDefaultTypeRoots(currentDirectory, host) { if (!host.directoryExists) { return [ts.combinePaths(currentDirectory, nodeModulesAtTypes)]; + // And if it doesn't exist, tough. } var typeRoots; ts.forEachAncestorDirectory(ts.normalizePath(currentDirectory), function (directory) { @@ -21054,6 +24405,11 @@ var ts; return typeRoots; } var nodeModulesAtTypes = ts.combinePaths("node_modules", "@types"); + /** + * @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. + * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups + * is assumed to be the same as root directory of the project. + */ function resolveTypeReferenceDirective(typeReferenceDirectiveName, containingFile, options, host) { var traceEnabled = isTraceEnabled(options, host); var moduleResolutionState = { compilerOptions: options, host: host, traceEnabled: traceEnabled }; @@ -21095,6 +24451,7 @@ var ts; } return { resolvedTypeReferenceDirective: resolvedTypeReferenceDirective, failedLookupLocations: failedLookupLocations }; function primaryLookup() { + // Check primary library paths if (typeRoots && typeRoots.length) { if (traceEnabled) { trace(host, ts.Diagnostics.Resolving_with_primary_search_path_0, typeRoots.join(", ")); @@ -21118,10 +24475,11 @@ var ts; function secondaryLookup() { var initialLocationForSecondaryLookup = containingFile && ts.getDirectoryPath(containingFile); if (initialLocationForSecondaryLookup !== undefined) { + // check secondary locations if (traceEnabled) { trace(host, ts.Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, initialLocationForSecondaryLookup); } - var result = loadModuleFromNodeModules(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, failedLookupLocations, moduleResolutionState, undefined); + var result = loadModuleFromNodeModules(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, failedLookupLocations, moduleResolutionState, /*cache*/ undefined); var resolvedFile = resolvedTypeScriptOnly(result && result.value); if (!resolvedFile && traceEnabled) { trace(host, ts.Diagnostics.Type_reference_directive_0_was_not_resolved, typeReferenceDirectiveName); @@ -21136,10 +24494,20 @@ var ts; } } ts.resolveTypeReferenceDirective = resolveTypeReferenceDirective; + /** + * Given a set of options, returns the set of type directive names + * that should be included for this program automatically. + * This list could either come from the config file, + * or from enumerating the types root + initial secondary types lookup location. + * More type directives might appear in the program later as a result of loading actual source files; + * this list is only the set of defaults that are implicitly included. + */ function getAutomaticTypeDirectiveNames(options, host) { + // Use explicit type list from tsconfig.json if (options.types) { return options.types; } + // Walk the primary type lookup locations var result = []; if (host.directoryExists && host.getDirectories) { var typeRoots = getEffectiveTypeRoots(options, host); @@ -21151,8 +24519,12 @@ var ts; var typeDirectivePath = _b[_a]; var normalized = ts.normalizePath(typeDirectivePath); var packageJsonPath = pathToPackageJson(ts.combinePaths(root, normalized)); + // `types-publisher` sometimes creates packages with `"typings": null` for packages that don't provide their own types. + // See `createNotNeededPackageJSON` in the types-publisher` repo. + // tslint:disable-next-line:no-null-keyword var isNotNeededPackage = host.fileExists(packageJsonPath) && readJson(packageJsonPath, host).typings === null; if (!isNotNeededPackage) { + // Return just the type directive names result.push(ts.getBaseFileName(normalized)); } } @@ -21167,6 +24539,7 @@ var ts; return createModuleResolutionCacheWithMaps(ts.createMap(), ts.createMap(), currentDirectory, getCanonicalFileName); } ts.createModuleResolutionCache = createModuleResolutionCache; + /*@internal*/ function createModuleResolutionCacheWithMaps(directoryToModuleNameMap, moduleNameToDirectoryMap, currentDirectory, getCanonicalFileName) { return { getOrCreateCacheForDirectory: getOrCreateCacheForDirectory, getOrCreateCacheForModuleName: getOrCreateCacheForModuleName }; function getOrCreateCacheForDirectory(directoryName) { @@ -21180,7 +24553,7 @@ var ts; } function getOrCreateCacheForModuleName(nonRelativeModuleName) { if (ts.isExternalModuleNameRelative(nonRelativeModuleName)) { - return undefined; + return undefined; // TODO: GH#18217 } var perModuleNameCache = moduleNameToDirectoryMap.get(nonRelativeModuleName); if (!perModuleNameCache) { @@ -21195,13 +24568,29 @@ var ts; function get(directory) { return directoryPathMap.get(ts.toPath(directory, currentDirectory, getCanonicalFileName)); } + /** + * At first this function add entry directory -> module resolution result to the table. + * Then it computes the set of parent folders for 'directory' that should have the same module resolution result + * and for every parent folder in set it adds entry: parent -> module resolution. . + * Lets say we first directory name: /a/b/c/d/e and resolution result is: /a/b/bar.ts. + * Set of parent folders that should have the same result will be: + * [ + * /a/b/c/d, /a/b/c, /a/b + * ] + * this means that request for module resolution from file in any of these folder will be immediately found in cache. + */ function set(directory, result) { var path = ts.toPath(directory, currentDirectory, getCanonicalFileName); + // if entry is already in cache do nothing if (directoryPathMap.has(path)) { return; } directoryPathMap.set(path, result); var resolvedFileName = result.resolvedModule && result.resolvedModule.resolvedFileName; + // find common prefix between directory and resolved file name + // this common prefix should be the shorted path that has the same resolution + // directory: /a/b/c/d/e + // resolvedFileName: /a/b/foo.d.ts var commonPrefix = getCommonPrefix(path, resolvedFileName); var current = path; while (true) { @@ -21221,10 +24610,12 @@ var ts; return undefined; } var resolutionDirectory = ts.toPath(ts.getDirectoryPath(resolution), currentDirectory, getCanonicalFileName); + // find first position where directory and resolution differs var i = 0; while (i < Math.min(directory.length, resolutionDirectory.length) && directory.charCodeAt(i) === resolutionDirectory.charCodeAt(i)) { i++; } + // find last directory separator before position i var sep = directory.lastIndexOf(ts.directorySeparator, i); if (sep < 0) { return undefined; @@ -21278,6 +24669,7 @@ var ts; } if (perFolderCache) { perFolderCache.set(moduleName, result); + // put result in per-module name cache var perModuleNameCache = cache.getOrCreateCacheForModuleName(moduleName); if (perModuleNameCache) { perModuleNameCache.set(containingDirectory, result); @@ -21295,6 +24687,66 @@ var ts; return result; } ts.resolveModuleName = resolveModuleName; + /** + * Any module resolution kind can be augmented with optional settings: 'baseUrl', 'paths' and 'rootDirs' - they are used to + * mitigate differences between design time structure of the project and its runtime counterpart so the same import name + * can be resolved successfully by TypeScript compiler and runtime module loader. + * If these settings are set then loading procedure will try to use them to resolve module name and it can of failure it will + * fallback to standard resolution routine. + * + * - baseUrl - this setting controls how non-relative module names are resolved. If this setting is specified then non-relative + * names will be resolved relative to baseUrl: i.e. if baseUrl is '/a/b' then candidate location to resolve module name 'c/d' will + * be '/a/b/c/d' + * - paths - this setting can only be used when baseUrl is specified. allows to tune how non-relative module names + * will be resolved based on the content of the module name. + * Structure of 'paths' compiler options + * 'paths': { + * pattern-1: [...substitutions], + * pattern-2: [...substitutions], + * ... + * pattern-n: [...substitutions] + * } + * Pattern here is a string that can contain zero or one '*' character. During module resolution module name will be matched against + * all patterns in the list. Matching for patterns that don't contain '*' means that module name must be equal to pattern respecting the case. + * If pattern contains '*' then to match pattern "*" module name must start with the and end with . + * denotes part of the module name between and . + * If module name can be matches with multiple patterns then pattern with the longest prefix will be picked. + * After selecting pattern we'll use list of substitutions to get candidate locations of the module and the try to load module + * from the candidate location. + * Substitution is a string that can contain zero or one '*'. To get candidate location from substitution we'll pick every + * substitution in the list and replace '*' with string. If candidate location is not rooted it + * will be converted to absolute using baseUrl. + * For example: + * baseUrl: /a/b/c + * "paths": { + * // match all module names + * "*": [ + * "*", // use matched name as is, + * // will be looked as /a/b/c/ + * + * "folder1/*" // substitution will convert matched name to 'folder1/', + * // since it is not rooted then final candidate location will be /a/b/c/folder1/ + * ], + * // match module names that start with 'components/' + * "components/*": [ "/root/components/*" ] // substitution will convert /components/folder1/ to '/root/components/folder1/', + * // it is rooted so it will be final candidate location + * } + * + * 'rootDirs' allows the project to be spreaded across multiple locations and resolve modules with relative names as if + * they were in the same location. For example lets say there are two files + * '/local/src/content/file1.ts' + * '/shared/components/contracts/src/content/protocols/file2.ts' + * After bundling content of '/shared/components/contracts/src' will be merged with '/local/src' so + * if file1 has the following import 'import {x} from "./protocols/file2"' it will be resolved successfully in runtime. + * 'rootDirs' provides the way to tell compiler that in order to get the whole project it should behave as if content of all + * root dirs were merged together. + * I.e. for the example above 'rootDirs' will have two entries: [ '/local/src', '/shared/components/contracts/src' ]. + * Compiler will first convert './protocols/file2' into absolute path relative to the location of containing file: + * '/local/src/content/protocols/file2' and try to load it - failure. + * Then it will search 'rootDirs' looking for a longest matching prefix of this absolute path and if such prefix is found - absolute path will + * be converted to a path relative to found rootDir entry './content/protocols/file2' (*). As a last step compiler will check all remaining + * entries in 'rootDirs', use them to build absolute path out of (*) and try to resolve module from this location. + */ function tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, loader, failedLookupLocations, state) { if (!ts.isExternalModuleNameRelative(moduleName)) { return tryLoadModuleUsingBaseUrl(extensions, moduleName, loader, failedLookupLocations, state); @@ -21315,6 +24767,9 @@ var ts; var matchedNormalizedPrefix; for (var _i = 0, _a = state.compilerOptions.rootDirs; _i < _a.length; _i++) { var rootDir = _a[_i]; + // rootDirs are expected to be absolute + // in case of tsconfig.json this will happen automatically - compiler will expand relative names + // using location of tsconfig.json as base location var normalizedRoot = ts.normalizePath(rootDir); if (!ts.endsWith(normalizedRoot, ts.directorySeparator)) { normalizedRoot += ts.directorySeparator; @@ -21334,6 +24789,7 @@ var ts; trace(state.host, ts.Diagnostics.Longest_matching_prefix_for_0_is_1, candidate, matchedNormalizedPrefix); } var suffix = candidate.substr(matchedNormalizedPrefix.length); + // first - try to load from a initial location if (state.traceEnabled) { trace(state.host, ts.Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, matchedNormalizedPrefix, candidate); } @@ -21344,9 +24800,11 @@ var ts; if (state.traceEnabled) { trace(state.host, ts.Diagnostics.Trying_other_entries_in_rootDirs); } + // then try to resolve using remaining entries in rootDirs for (var _b = 0, _c = state.compilerOptions.rootDirs; _b < _c.length; _b++) { var rootDir = _c[_b]; if (rootDir === matchedRootDir) { + // skip the initially matched entry continue; } var candidate_1 = ts.combinePaths(ts.normalizePath(rootDir), suffix); @@ -21372,6 +24830,7 @@ var ts; if (state.traceEnabled) { trace(state.host, ts.Diagnostics.baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1, state.compilerOptions.baseUrl, moduleName); } + // string is for exact match var matchedPattern; if (state.compilerOptions.paths) { if (state.traceEnabled) { @@ -21391,9 +24850,10 @@ var ts; if (state.traceEnabled) { trace(state.host, ts.Diagnostics.Trying_substitution_0_candidate_module_location_Colon_1, subst, path); } + // A path mapping may have an extension, in contrast to an import, which should omit it. var extension = ts.tryGetExtensionFromPath(candidate); if (extension !== undefined) { - var path_1 = tryFile(candidate, failedLookupLocations, false, state); + var path_1 = tryFile(candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state); if (path_1 !== undefined) { return noPackageId({ path: path_1, ext: extension }); } @@ -21410,11 +24870,17 @@ var ts; } } function nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host, cache) { - return nodeModuleNameResolverWorker(moduleName, ts.getDirectoryPath(containingFile), compilerOptions, host, cache, false); + return nodeModuleNameResolverWorker(moduleName, ts.getDirectoryPath(containingFile), compilerOptions, host, cache, /*jsOnly*/ false); } ts.nodeModuleNameResolver = nodeModuleNameResolver; + /** + * Expose resolution logic to allow us to use Node module resolution logic from arbitrary locations. + * No way to do this with `require()`: https://github.com/nodejs/node/issues/5963 + * Throws an error if the module can't be resolved. + */ + /* @internal */ function resolveJavaScriptModule(moduleName, initialDir, host) { - var _a = nodeModuleNameResolverWorker(moduleName, initialDir, { moduleResolution: ts.ModuleResolutionKind.NodeJs, allowJs: true }, host, undefined, true), resolvedModule = _a.resolvedModule, failedLookupLocations = _a.failedLookupLocations; + var _a = nodeModuleNameResolverWorker(moduleName, initialDir, { moduleResolution: ts.ModuleResolutionKind.NodeJs, allowJs: true }, host, /*cache*/ undefined, /*jsOnly*/ true), resolvedModule = _a.resolvedModule, failedLookupLocations = _a.failedLookupLocations; if (!resolvedModule) { throw new Error("Could not resolve JS module '" + moduleName + "' starting at '" + initialDir + "'. Looked in: " + failedLookupLocations.join(", ")); } @@ -21436,7 +24902,7 @@ var ts; } return { resolvedModule: undefined, failedLookupLocations: failedLookupLocations }; function tryResolve(extensions) { - var loader = function (extensions, candidate, failedLookupLocations, onlyRecordFailures, state) { return nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, onlyRecordFailures, state, true); }; + var loader = function (extensions, candidate, failedLookupLocations, onlyRecordFailures, state) { return nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, onlyRecordFailures, state, /*considerPackageJson*/ true); }; var resolved = tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, loader, failedLookupLocations, state); if (resolved) { return toSearchResult({ resolved: resolved, isExternalLibraryImport: false }); @@ -21458,11 +24924,13 @@ var ts; } resolvedValue = __assign({}, resolvedValue, { path: path }); } + // For node_modules lookups, get the real path so that multiple accesses to an `npm link`-ed module do not create duplicate files. return { value: resolvedValue && { resolved: resolvedValue, originalPath: originalPath, isExternalLibraryImport: true } }; } else { var _a = ts.normalizePathAndParts(ts.combinePaths(containingDirectory, moduleName)), candidate = _a.path, parts = _a.parts; - var resolved_2 = nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, false, state, true); + var resolved_2 = nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state, /*considerPackageJson*/ true); + // Treat explicit "node_modules" import as an external library import. return resolved_2 && toSearchResult({ resolved: resolved_2, isExternalLibraryImport: ts.contains(parts, "node_modules") }); } } @@ -21475,7 +24943,7 @@ var ts; if (traceEnabled) { trace(host, ts.Diagnostics.Resolving_real_path_for_0_result_1, path, real); } - ts.Debug.assert(host.fileExists(real), path + " linked to nonexistent file " + real); + ts.Debug.assert(host.fileExists(real), path + " linked to nonexistent file " + real); // tslint:disable-line return real; } function nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, onlyRecordFailures, state, considerPackageJson) { @@ -21495,7 +24963,7 @@ var ts; var resolvedFromFile = loadModuleFromFile(extensions, candidate, failedLookupLocations, onlyRecordFailures, state); if (resolvedFromFile) { var nm = considerPackageJson ? parseNodeModuleFromPath(resolvedFromFile) : undefined; - var packageId = nm && getPackageJsonInfo(nm.packageDirectory, nm.subModuleName, failedLookupLocations, false, state).packageId; + var packageId = nm && getPackageJsonInfo(nm.packageDirectory, nm.subModuleName, failedLookupLocations, /*onlyRecordFailures*/ false, state).packageId; return withPackageId(packageId, resolvedFromFile); } } @@ -21511,6 +24979,17 @@ var ts; return loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocations, onlyRecordFailures, state, considerPackageJson); } var nodeModulesPathPart = "/node_modules/"; + /** + * This will be called on the successfully resolved path from `loadModuleFromFile`. + * (Not neeeded for `loadModuleFromNodeModules` as that looks up the `package.json` as part of resolution.) + * + * packageDirectory is the directory of the package itself. + * subModuleName is the path within the package. + * For `blah/node_modules/foo/index.d.ts` this is { packageDirectory: "foo", subModuleName: "index.d.ts" }. (Part before "/node_modules/" is ignored.) + * For `/node_modules/foo/bar.d.ts` this is { packageDirectory: "foo", subModuleName": "bar/index.d.ts" }. + * For `/node_modules/@types/foo/bar/index.d.ts` this is { packageDirectory: "@types/foo", subModuleName: "bar/index.d.ts" }. + * For `/node_modules/foo/bar/index.d.ts` this is { packageDirectory: "foo", subModuleName": "bar/index.d.ts" }. + */ function parseNodeModuleFromPath(resolved) { var path = ts.normalizePath(resolved.path); var idx = path.lastIndexOf(nodeModulesPathPart); @@ -21519,11 +24998,11 @@ var ts; } var indexAfterNodeModules = idx + nodeModulesPathPart.length; var indexAfterPackageName = moveToNextDirectorySeparatorIfAvailable(path, indexAfterNodeModules); - if (path.charCodeAt(indexAfterNodeModules) === 64) { + if (path.charCodeAt(indexAfterNodeModules) === 64 /* at */) { indexAfterPackageName = moveToNextDirectorySeparatorIfAvailable(path, indexAfterPackageName); } var packageDirectory = path.slice(0, indexAfterPackageName); - var subModuleName = ts.removeExtension(path.slice(indexAfterPackageName + 1), resolved.ext) + ".d.ts"; + var subModuleName = ts.removeExtension(path.slice(indexAfterPackageName + 1), resolved.ext) + ".d.ts" /* Dts */; return { packageDirectory: packageDirectory, subModuleName: subModuleName }; } function moveToNextDirectorySeparatorIfAvailable(path, prevSeparatorIndex) { @@ -21542,22 +25021,31 @@ var ts; } return path + "/index.d.ts"; } + /* @internal */ function directoryProbablyExists(directoryName, host) { + // if host does not support 'directoryExists' assume that directory will exist return !host.directoryExists || host.directoryExists(directoryName); } ts.directoryProbablyExists = directoryProbablyExists; function loadModuleFromFileNoPackageId(extensions, candidate, failedLookupLocations, onlyRecordFailures, state) { return noPackageId(loadModuleFromFile(extensions, candidate, failedLookupLocations, onlyRecordFailures, state)); } + /** + * @param {boolean} onlyRecordFailures - if true then function won't try to actually load files but instead record all attempts as failures. This flag is necessary + * in cases when we know upfront that all load attempts will fail (because containing folder does not exists) however we still need to record all failed lookup locations. + */ function loadModuleFromFile(extensions, candidate, failedLookupLocations, onlyRecordFailures, state) { if (extensions === Extensions.Json) { - var extensionLess = ts.tryRemoveExtension(candidate, ".json"); + var extensionLess = ts.tryRemoveExtension(candidate, ".json" /* Json */); return extensionLess === undefined ? undefined : tryAddingExtensions(extensionLess, extensions, failedLookupLocations, onlyRecordFailures, state); } + // First, try adding an extension. An import of "foo" could be matched by a file "foo.ts", or "foo.js" by "foo.js.ts" var resolvedByAddingExtension = tryAddingExtensions(candidate, extensions, failedLookupLocations, onlyRecordFailures, state); if (resolvedByAddingExtension) { return resolvedByAddingExtension; } + // If that didn't work, try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one; + // e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts" if (ts.hasJavaScriptFileExtension(candidate)) { var extensionless = ts.removeFileExtension(candidate); if (state.traceEnabled) { @@ -21567,8 +25055,10 @@ var ts; return tryAddingExtensions(extensionless, extensions, failedLookupLocations, onlyRecordFailures, state); } } + /** Try to return an existing file that adds one of the `extensions` to `candidate`. */ function tryAddingExtensions(candidate, extensions, failedLookupLocations, onlyRecordFailures, state) { if (!onlyRecordFailures) { + // check if containing folder exists - if it doesn't then just record failures for all supported extensions without disk probing var directory = ts.getDirectoryPath(candidate); if (directory) { onlyRecordFailures = !directoryProbablyExists(directory, state.host); @@ -21576,19 +25066,20 @@ var ts; } switch (extensions) { case Extensions.DtsOnly: - return tryExtension(".d.ts"); + return tryExtension(".d.ts" /* Dts */); case Extensions.TypeScript: - return tryExtension(".ts") || tryExtension(".tsx") || tryExtension(".d.ts"); + return tryExtension(".ts" /* Ts */) || tryExtension(".tsx" /* Tsx */) || tryExtension(".d.ts" /* Dts */); case Extensions.JavaScript: - return tryExtension(".js") || tryExtension(".jsx"); + return tryExtension(".js" /* Js */) || tryExtension(".jsx" /* Jsx */); case Extensions.Json: - return tryExtension(".json"); + return tryExtension(".json" /* Json */); } function tryExtension(ext) { var path = tryFile(candidate + ext, failedLookupLocations, onlyRecordFailures, state); return path === undefined ? undefined : { path: path, ext: ext }; } } + /** Return the file if it exists. */ function tryFile(fileName, failedLookupLocations, onlyRecordFailures, state) { if (!onlyRecordFailures) { if (state.host.fileExists(fileName)) { @@ -21627,25 +25118,25 @@ var ts; var packageJsonPath = pathToPackageJson(nodeModuleDirectory); if (directoryExists && host.fileExists(packageJsonPath)) { var packageJsonContent = readJson(packageJsonPath, host); - if (subModuleName === "") { - var path = tryReadPackageJsonFields(true, packageJsonContent, nodeModuleDirectory, state); + if (subModuleName === "") { // looking up the root - need to handle types/typings/main redirects for subModuleName + var path = tryReadPackageJsonFields(/*readTypes*/ true, packageJsonContent, nodeModuleDirectory, state); if (typeof path === "string") { subModuleName = addExtensionAndIndex(path.substring(nodeModuleDirectory.length + 1)); } else { - var jsPath = tryReadPackageJsonFields(false, packageJsonContent, nodeModuleDirectory, state); + var jsPath = tryReadPackageJsonFields(/*readTypes*/ false, packageJsonContent, nodeModuleDirectory, state); if (typeof jsPath === "string" && jsPath.length > nodeModuleDirectory.length) { var potentialSubModule_1 = jsPath.substring(nodeModuleDirectory.length + 1); subModuleName = (ts.forEach(ts.supportedJavascriptExtensions, function (extension) { return ts.tryRemoveExtension(potentialSubModule_1, extension); - }) || potentialSubModule_1) + ".d.ts"; + }) || potentialSubModule_1) + ".d.ts" /* Dts */; } else { subModuleName = "index.d.ts"; } } } - if (!ts.endsWith(subModuleName, ".d.ts")) { + if (!ts.endsWith(subModuleName, ".d.ts" /* Dts */)) { subModuleName = addExtensionAndIndex(subModuleName); } var packageId = typeof packageJsonContent.name === "string" && typeof packageJsonContent.version === "string" @@ -21665,6 +25156,7 @@ var ts; if (directoryExists && traceEnabled) { trace(host, ts.Diagnostics.File_0_does_not_exist, packageJsonPath); } + // record package json as one of failed lookup locations - in the future if this file will appear it will invalidate resolution results failedLookupLocations.push(packageJsonPath); return { found: false, packageJsonContent: undefined, packageId: undefined }; } @@ -21673,7 +25165,8 @@ var ts; var file = tryReadPackageJsonFields(extensions !== Extensions.JavaScript && extensions !== Extensions.Json, jsonContent, candidate, state); if (!file) { if (extensions === Extensions.TypeScript) { - file = tryReadPackageJsonFields(false, jsonContent, candidate, state); + // When resolving typescript modules, try resolving using main field as well + file = tryReadPackageJsonFields(/*readTypes*/ false, jsonContent, candidate, state); if (!file) { return undefined; } @@ -21693,27 +25186,32 @@ var ts; trace(state.host, ts.Diagnostics.File_0_has_an_unsupported_extension_so_skipping_it, fromFile); } } + // Even if extensions is DtsOnly, we can still look up a .ts file as a result of package.json "types" var nextExtensions = extensions === Extensions.DtsOnly ? Extensions.TypeScript : extensions; - var result = nodeLoadModuleByRelativeName(nextExtensions, file, failedLookupLocations, onlyRecordFailures, state, false); + // Don't do package.json lookup recursively, because Node.js' package lookup doesn't. + var result = nodeLoadModuleByRelativeName(nextExtensions, file, failedLookupLocations, onlyRecordFailures, state, /*considerPackageJson*/ false); if (result) { + // It won't have a `packageId` set, because we disabled `considerPackageJson`. ts.Debug.assert(result.packageId === undefined); return { path: result.path, ext: result.extension }; } } + /** Resolve from an arbitrarily specified file. Return `undefined` if it has an unsupported extension. */ function resolvedIfExtensionMatches(extensions, path) { var ext = ts.tryGetExtensionFromPath(path); return ext !== undefined && extensionIsOk(extensions, ext) ? { path: path, ext: ext } : undefined; } + /** True if `extension` is one of the supported `extensions`. */ function extensionIsOk(extensions, extension) { switch (extensions) { case Extensions.JavaScript: - return extension === ".js" || extension === ".jsx"; + return extension === ".js" /* Js */ || extension === ".jsx" /* Jsx */; case Extensions.Json: - return extension === ".json"; + return extension === ".json" /* Json */; case Extensions.TypeScript: - return extension === ".ts" || extension === ".tsx" || extension === ".d.ts"; + return extension === ".ts" /* Ts */ || extension === ".tsx" /* Tsx */ || extension === ".d.ts" /* Dts */; case Extensions.DtsOnly: - return extension === ".d.ts"; + return extension === ".d.ts" /* Dts */; } } function pathToPackageJson(directory) { @@ -21721,16 +25219,18 @@ var ts; } function loadModuleFromNodeModulesFolder(extensions, moduleName, nodeModulesFolder, nodeModulesFolderExists, failedLookupLocations, state) { var candidate = ts.normalizePath(ts.combinePaths(nodeModulesFolder, moduleName)); + // First look for a nested package.json, as in `node_modules/foo/bar/package.json`. var packageJsonContent; var packageId; - var packageInfo = getPackageJsonInfo(candidate, "", failedLookupLocations, !nodeModulesFolderExists, state); + var packageInfo = getPackageJsonInfo(candidate, "", failedLookupLocations, /*onlyRecordFailures*/ !nodeModulesFolderExists, state); if (packageInfo.found) { (packageJsonContent = packageInfo.packageJsonContent, packageId = packageInfo.packageId); } else { var _a = getPackageName(moduleName), packageName = _a.packageName, rest = _a.rest; - if (rest !== "") { + if (rest !== "") { // If "rest" is empty, we just did this search above. var packageRootPath = ts.combinePaths(nodeModulesFolder, packageName); + // Don't use a "types" or "main" from here because we're not loading the root, but a subdirectory -- just here for the packageId. packageId = getPackageJsonInfo(packageRootPath, rest, failedLookupLocations, !nodeModulesFolderExists, state).packageId; } } @@ -21738,6 +25238,7 @@ var ts; loadNodeModuleFromDirectoryWorker(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state, packageJsonContent); return withPackageId(packageId, pathAndExtension); } + /* @internal */ function getPackageName(moduleName) { var idx = moduleName.indexOf(ts.directorySeparator); if (moduleName[0] === "@") { @@ -21747,10 +25248,11 @@ var ts; } ts.getPackageName = getPackageName; function loadModuleFromNodeModules(extensions, moduleName, directory, failedLookupLocations, state, cache) { - return loadModuleFromNodeModulesWorker(extensions, moduleName, directory, failedLookupLocations, state, false, cache); + return loadModuleFromNodeModulesWorker(extensions, moduleName, directory, failedLookupLocations, state, /*typesOnly*/ false, cache); } function loadModuleFromNodeModulesAtTypes(moduleName, directory, failedLookupLocations, state) { - return loadModuleFromNodeModulesWorker(Extensions.DtsOnly, moduleName, directory, failedLookupLocations, state, true, undefined); + // Extensions parameter here doesn't actually matter, because typesOnly ensures we're just doing @types lookup, which is always DtsOnly. + return loadModuleFromNodeModulesWorker(Extensions.DtsOnly, moduleName, directory, failedLookupLocations, state, /*typesOnly*/ true, /*cache*/ undefined); } function loadModuleFromNodeModulesWorker(extensions, moduleName, directory, failedLookupLocations, state, typesOnly, cache) { var perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName); @@ -21764,6 +25266,7 @@ var ts; } }); } + /** Load a module from a single node_modules directory, but not from any ancestors' node_modules directories. */ function loadModuleFromNodeModulesOneLevel(extensions, moduleName, directory, failedLookupLocations, state, typesOnly) { if (typesOnly === void 0) { typesOnly = false; } var nodeModulesFolder = ts.combinePaths(directory, "node_modules"); @@ -21787,7 +25290,9 @@ var ts; return loadModuleFromNodeModulesFolder(Extensions.DtsOnly, mangleScopedPackage(moduleName, state), nodeModulesAtTypes_1, nodeModulesAtTypesExists, failedLookupLocations, state); } } + /** Double underscores are used in DefinitelyTyped to delimit scoped packages. */ var mangledScopedPackageSeparator = "__"; + /** For a scoped package, we must look in `@types/foo__bar` instead of `@types/@foo/bar`. */ function mangleScopedPackage(packageName, state) { var mangled = getMangledNameForScopedPackage(packageName); if (state.traceEnabled && mangled !== packageName) { @@ -21795,20 +25300,23 @@ var ts; } return mangled; } + /* @internal */ function getTypesPackageName(packageName) { return "@types/" + getMangledNameForScopedPackage(packageName); } ts.getTypesPackageName = getTypesPackageName; + /* @internal */ function getMangledNameForScopedPackage(packageName) { if (ts.startsWith(packageName, "@")) { var replaceSlash = packageName.replace(ts.directorySeparator, mangledScopedPackageSeparator); if (replaceSlash !== packageName) { - return replaceSlash.slice(1); + return replaceSlash.slice(1); // Take off the "@" } } return packageName; } ts.getMangledNameForScopedPackage = getMangledNameForScopedPackage; + /* @internal */ function getPackageNameFromAtTypesDirectory(mangledName) { var withoutAtTypePrefix = ts.removePrefix(mangledName, "@types/"); if (withoutAtTypePrefix !== mangledName) { @@ -21817,6 +25325,7 @@ var ts; return mangledName; } ts.getPackageNameFromAtTypesDirectory = getPackageNameFromAtTypesDirectory; + /* @internal */ function getUnmangledNameForScopedPackage(typesPackageName) { return ts.stringContains(typesPackageName, mangledScopedPackageSeparator) ? "@" + typesPackageName.replace(mangledScopedPackageSeparator, ts.directorySeparator) : @@ -21839,7 +25348,8 @@ var ts; var failedLookupLocations = []; var containingDirectory = ts.getDirectoryPath(containingFile); var resolved = tryResolve(Extensions.TypeScript) || tryResolve(Extensions.JavaScript); - return createResolvedModuleWithFailedLookupLocations(resolved && resolved.value, undefined, false, failedLookupLocations); + // No originalPath because classic resolution doesn't resolve realPath + return createResolvedModuleWithFailedLookupLocations(resolved && resolved.value, /*originalPath*/ undefined, /*isExternalLibraryImport*/ false, failedLookupLocations); function tryResolve(extensions) { var resolvedUsingSettings = tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, loadModuleFromFileNoPackageId, failedLookupLocations, state); if (resolvedUsingSettings) { @@ -21847,28 +25357,35 @@ var ts; } var perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName); if (!ts.isExternalModuleNameRelative(moduleName)) { + // Climb up parent directories looking for a module. var resolved_3 = ts.forEachAncestorDirectory(containingDirectory, function (directory) { var resolutionFromCache = tryFindNonRelativeModuleNameInCache(perModuleNameCache, moduleName, directory, traceEnabled, host, failedLookupLocations); if (resolutionFromCache) { return resolutionFromCache; } var searchName = ts.normalizePath(ts.combinePaths(directory, moduleName)); - return toSearchResult(loadModuleFromFileNoPackageId(extensions, searchName, failedLookupLocations, false, state)); + return toSearchResult(loadModuleFromFileNoPackageId(extensions, searchName, failedLookupLocations, /*onlyRecordFailures*/ false, state)); }); if (resolved_3) { return resolved_3; } if (extensions === Extensions.TypeScript) { + // If we didn't find the file normally, look it up in @types. return loadModuleFromNodeModulesAtTypes(moduleName, containingDirectory, failedLookupLocations, state); } } else { var candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); - return toSearchResult(loadModuleFromFileNoPackageId(extensions, candidate, failedLookupLocations, false, state)); + return toSearchResult(loadModuleFromFileNoPackageId(extensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state)); } } } ts.classicNameResolver = classicNameResolver; + /** + * LSHost may load a module from a global cache of typings. + * This is the minumum code needed to expose that functionality; the rest is in LSHost. + */ + /* @internal */ function loadModuleFromGlobalCache(moduleName, projectName, compilerOptions, host, globalCache) { var traceEnabled = isTraceEnabled(compilerOptions, host); if (traceEnabled) { @@ -21877,13 +25394,18 @@ var ts; var state = { compilerOptions: compilerOptions, host: host, traceEnabled: traceEnabled }; var failedLookupLocations = []; var resolved = loadModuleFromNodeModulesOneLevel(Extensions.DtsOnly, moduleName, globalCache, failedLookupLocations, state); - return createResolvedModuleWithFailedLookupLocations(resolved, undefined, true, failedLookupLocations); + return createResolvedModuleWithFailedLookupLocations(resolved, /*originalPath*/ undefined, /*isExternalLibraryImport*/ true, failedLookupLocations); } ts.loadModuleFromGlobalCache = loadModuleFromGlobalCache; + /** + * Wraps value to SearchResult. + * @returns undefined if value is undefined or { value } otherwise + */ function toSearchResult(value) { return value !== undefined ? { value: value } : undefined; } })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var ModuleInstanceState; @@ -21893,37 +25415,45 @@ var ts; ModuleInstanceState[ModuleInstanceState["ConstEnumOnly"] = 2] = "ConstEnumOnly"; })(ModuleInstanceState = ts.ModuleInstanceState || (ts.ModuleInstanceState = {})); function getModuleInstanceState(node) { - return node.body ? getModuleInstanceStateWorker(node.body) : 1; + return node.body ? getModuleInstanceStateWorker(node.body) : 1 /* Instantiated */; } ts.getModuleInstanceState = getModuleInstanceState; function getModuleInstanceStateWorker(node) { + // A module is uninstantiated if it contains only switch (node.kind) { - case 236: - case 237: - return 0; - case 238: + // 1. interface declarations, type alias declarations + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: + return 0 /* NonInstantiated */; + // 2. const enum declarations + case 238 /* EnumDeclaration */: if (ts.isConst(node)) { - return 2; + return 2 /* ConstEnumOnly */; } break; - case 244: - case 243: - if (!(ts.hasModifier(node, 1))) { - return 0; + // 3. non-exported import declarations + case 244 /* ImportDeclaration */: + case 243 /* ImportEqualsDeclaration */: + if (!(ts.hasModifier(node, 1 /* Export */))) { + return 0 /* NonInstantiated */; } break; - case 240: { - var state_1 = 0; + // 4. other uninstantiated module declarations. + case 240 /* ModuleBlock */: { + var state_1 = 0 /* NonInstantiated */; ts.forEachChild(node, function (n) { var childState = getModuleInstanceStateWorker(n); switch (childState) { - case 0: + case 0 /* NonInstantiated */: + // child is non-instantiated - continue searching return; - case 2: - state_1 = 2; + case 2 /* ConstEnumOnly */: + // child is const enum only - record state and continue searching + state_1 = 2 /* ConstEnumOnly */; return; - case 1: - state_1 = 1; + case 1 /* Instantiated */: + // child is instantiated - record state and stop + state_1 = 1 /* Instantiated */; return true; default: ts.Debug.assertNever(childState); @@ -21931,20 +25461,34 @@ var ts; }); return state_1; } - case 239: + case 239 /* ModuleDeclaration */: return getModuleInstanceState(node); - case 71: + case 71 /* Identifier */: + // Only jsdoc typedef definition can exist in jsdoc namespace, and it should + // be considered the same as type alias if (node.isInJSDocNamespace) { - return 0; + return 0 /* NonInstantiated */; } } - return 1; + return 1 /* Instantiated */; } var ContainerFlags; (function (ContainerFlags) { + // The current node is not a container, and no container manipulation should happen before + // recursing into it. ContainerFlags[ContainerFlags["None"] = 0] = "None"; + // The current node is a container. It should be set as the current container (and block- + // container) before recursing into it. The current node does not have locals. Examples: + // + // Classes, ObjectLiterals, TypeLiterals, Interfaces... ContainerFlags[ContainerFlags["IsContainer"] = 1] = "IsContainer"; + // The current node is a block-scoped-container. It should be set as the current block- + // container before recursing into it. Examples: + // + // Blocks (when not parented by functions), Catch clauses, For/For-in/For-of statements... ContainerFlags[ContainerFlags["IsBlockScopedContainer"] = 2] = "IsBlockScopedContainer"; + // The current node is the container of a control flow path. The current control flow should + // be saved and restored, and a new control flow initialized within the container. ContainerFlags[ContainerFlags["IsControlFlowContainer"] = 4] = "IsControlFlowContainer"; ContainerFlags[ContainerFlags["IsFunctionLike"] = 8] = "IsFunctionLike"; ContainerFlags[ContainerFlags["IsFunctionExpression"] = 16] = "IsFunctionExpression"; @@ -21966,11 +25510,12 @@ var ts; var languageVersion; var parent; var container; - var thisParentContainer; + var thisParentContainer; // Container one level up var blockScopeContainer; var lastContainer; var delayedTypeAliases; var seenThisKeyword; + // state used by control flow analysis var currentFlow; var currentBreakTarget; var currentContinueTarget; @@ -21980,15 +25525,26 @@ var ts; var preSwitchCaseFlow; var activeLabels; var hasExplicitReturn; + // state used for emit helpers var emitFlags; + // If this file is an external module, then it is automatically in strict-mode according to + // ES6. If it is not an external module, then we'll determine if it is in strict mode or + // not depending on if we see "use strict" in certain places or if we hit a class/namespace + // or if compiler options contain alwaysStrict. var inStrictMode; var symbolCount = 0; - var Symbol; + var Symbol; // tslint:disable-line variable-name var classifiableNames; - var unreachableFlow = { flags: 1 }; - var reportedUnreachableFlow = { flags: 1 }; - var subtreeTransformFlags = 0; + var unreachableFlow = { flags: 1 /* Unreachable */ }; + var reportedUnreachableFlow = { flags: 1 /* Unreachable */ }; + // state used to aggregate transform flags during bind. + var subtreeTransformFlags = 0 /* None */; var skipTransformFlagAggregation; + /** + * Inside the binder, we may create a diagnostic for an as-yet unbound node (with potentially no parent pointers, implying no accessible source file) + * If so, the node _must_ be in the current file (as that's the only way anything could have traversed to it to yield it as the error node) + * This version of `createDiagnosticForNode` uses the binder's context to account for this, and always yields correct diagnostics even in these situations. + */ function createDiagnosticForNode(node, message, arg0, arg1, arg2) { return ts.createDiagnosticForNodeInSourceFile(ts.getSourceFileOfNode(node) || file, node, message, arg0, arg1, arg2); } @@ -22025,12 +25581,13 @@ var ts; currentFalseTarget = undefined; activeLabels = undefined; hasExplicitReturn = false; - emitFlags = 0; - subtreeTransformFlags = 0; + emitFlags = 0 /* None */; + subtreeTransformFlags = 0 /* None */; } return bindSourceFile; function bindInStrictMode(file, opts) { if (ts.getStrictOptionValue(opts, "alwaysStrict") && !file.isDeclarationFile) { + // bind in strict mode source files with alwaysStrict option return true; } else { @@ -22045,23 +25602,26 @@ var ts; symbol.flags |= symbolFlags; node.symbol = symbol; symbol.declarations = ts.append(symbol.declarations, node); - if (symbolFlags & 1955 && !symbol.exports) { + if (symbolFlags & 1955 /* HasExports */ && !symbol.exports) { symbol.exports = ts.createSymbolTable(); } - if (symbolFlags & 6240 && !symbol.members) { + if (symbolFlags & 6240 /* HasMembers */ && !symbol.members) { symbol.members = ts.createSymbolTable(); } - if (symbolFlags & 67216319) { + if (symbolFlags & 67216319 /* Value */) { var valueDeclaration = symbol.valueDeclaration; if (!valueDeclaration || (valueDeclaration.kind !== node.kind && ts.isEffectiveModuleDeclaration(valueDeclaration))) { + // other kinds of value declarations take precedence over modules symbol.valueDeclaration = node; } } } + // Should not be called on a declaration with a computed property name, + // unless it is a well known Symbol. function getDeclarationName(node) { - if (node.kind === 249) { - return node.isExportEquals ? "export=" : "default"; + if (node.kind === 249 /* ExportAssignment */) { + return node.isExportEquals ? "export=" /* ExportEquals */ : "default" /* Default */; } var name = ts.getNameOfDeclaration(node); if (name) { @@ -22069,8 +25629,9 @@ var ts; var moduleName = ts.getTextOfIdentifierOrLiteral(name); return (ts.isGlobalScopeAugmentation(node) ? "__global" : "\"" + moduleName + "\""); } - if (name.kind === 147) { + if (name.kind === 147 /* ComputedPropertyName */) { var nameExpression = name.expression; + // treat computed property names where expression is string/numeric literal as just string/numeric literal if (ts.isStringOrNumericLiteral(nameExpression)) { return ts.escapeLeadingUnderscores(nameExpression.text); } @@ -22080,81 +25641,130 @@ var ts; return ts.isPropertyNameLiteral(name) ? ts.getEscapedTextOfIdentifierOrLiteral(name) : undefined; } switch (node.kind) { - case 155: - return "__constructor"; - case 163: - case 158: - case 288: - return "__call"; - case 164: - case 159: - return "__new"; - case 160: - return "__index"; - case 250: - return "__export"; - case 274: - return "export="; - case 200: - if (ts.getSpecialPropertyAssignmentKind(node) === 2) { - return "export="; + case 155 /* Constructor */: + return "__constructor" /* Constructor */; + case 163 /* FunctionType */: + case 158 /* CallSignature */: + case 288 /* JSDocSignature */: + return "__call" /* Call */; + case 164 /* ConstructorType */: + case 159 /* ConstructSignature */: + return "__new" /* New */; + case 160 /* IndexSignature */: + return "__index" /* Index */; + case 250 /* ExportDeclaration */: + return "__export" /* ExportStar */; + case 274 /* SourceFile */: + // json file should behave as + // module.exports = ... + return "export=" /* ExportEquals */; + case 200 /* BinaryExpression */: + if (ts.getSpecialPropertyAssignmentKind(node) === 2 /* ModuleExports */) { + // module.exports = ... + return "export=" /* ExportEquals */; } ts.Debug.fail("Unknown binary declaration kind"); break; - case 284: - return (ts.isJSDocConstructSignature(node) ? "__new" : "__call"); - case 149: - ts.Debug.assert(node.parent.kind === 284, "Impossible parameter parent kind", function () { return "parent is: " + (ts.SyntaxKind ? ts.SyntaxKind[node.parent.kind] : node.parent.kind) + ", expected JSDocFunctionType"; }); + case 284 /* JSDocFunctionType */: + return (ts.isJSDocConstructSignature(node) ? "__new" /* New */ : "__call" /* Call */); + case 149 /* Parameter */: + // Parameters with names are handled at the top of this function. Parameters + // without names can only come from JSDocFunctionTypes. + ts.Debug.assert(node.parent.kind === 284 /* JSDocFunctionType */, "Impossible parameter parent kind", function () { return "parent is: " + (ts.SyntaxKind ? ts.SyntaxKind[node.parent.kind] : node.parent.kind) + ", expected JSDocFunctionType"; }); var functionType = node.parent; var index = functionType.parameters.indexOf(node); return "arg" + index; } } function getDisplayName(node) { - return ts.isNamedDeclaration(node) ? ts.declarationNameToString(node.name) : ts.unescapeLeadingUnderscores(getDeclarationName(node)); + return ts.isNamedDeclaration(node) ? ts.declarationNameToString(node.name) : ts.unescapeLeadingUnderscores(getDeclarationName(node)); // TODO: GH#18217 } + /** + * Declares a Symbol for the node and adds it to symbols. Reports errors for conflicting identifier names. + * @param symbolTable - The symbol table which node will be added to. + * @param parent - node's parent declaration. + * @param node - The declaration to be added to the symbol table + * @param includes - The SymbolFlags that node has in addition to its declaration type (eg: export, ambient, etc.) + * @param excludes - The flags which node cannot be declared alongside in a symbol table. Used to report forbidden declarations. + */ function declareSymbol(symbolTable, parent, node, includes, excludes, isReplaceableByMethod) { ts.Debug.assert(!ts.hasDynamicName(node)); - var isDefaultExport = ts.hasModifier(node, 512); - var name = isDefaultExport && parent ? "default" : getDeclarationName(node); + var isDefaultExport = ts.hasModifier(node, 512 /* Default */); + // The exported symbol for an export default function/class node is always named "default" + var name = isDefaultExport && parent ? "default" /* Default */ : getDeclarationName(node); var symbol; if (name === undefined) { - symbol = createSymbol(0, "__missing"); + symbol = createSymbol(0 /* None */, "__missing" /* Missing */); } else { + // Check and see if the symbol table already has a symbol with this name. If not, + // create a new symbol with this name and add it to the table. Note that we don't + // give the new symbol any flags *yet*. This ensures that it will not conflict + // with the 'excludes' flags we pass in. + // + // If we do get an existing symbol, see if it conflicts with the new symbol we're + // creating. For example, a 'var' symbol and a 'class' symbol will conflict within + // the same symbol table. If we have a conflict, report the issue on each + // declaration we have for this symbol, and then create a new symbol for this + // declaration. + // + // Note that when properties declared in Javascript constructors + // (marked by isReplaceableByMethod) conflict with another symbol, the property loses. + // Always. This allows the common Javascript pattern of overwriting a prototype method + // with an bound instance method of the same type: `this.method = this.method.bind(this)` + // + // If we created a new symbol, either because we didn't have a symbol with this name + // in the symbol table, or we conflicted with an existing symbol, then just add this + // node as the sole declaration of the new symbol. + // + // Otherwise, we'll be merging into a compatible existing symbol (for example when + // you have multiple 'vars' with the same name in the same container). In this case + // just add this node into the declarations list of the symbol. symbol = symbolTable.get(name); - if (includes & 2885600) { + if (includes & 2885600 /* Classifiable */) { classifiableNames.set(name, true); } if (!symbol) { - symbolTable.set(name, symbol = createSymbol(0, name)); + symbolTable.set(name, symbol = createSymbol(0 /* None */, name)); if (isReplaceableByMethod) symbol.isReplaceableByMethod = true; } else if (isReplaceableByMethod && !symbol.isReplaceableByMethod) { + // A symbol already exists, so don't add this as a declaration. return symbol; } else if (symbol.flags & excludes) { if (symbol.isReplaceableByMethod) { - symbolTable.set(name, symbol = createSymbol(0, name)); + // Javascript constructor-declared symbols can be discarded in favor of + // prototype symbols like methods. + symbolTable.set(name, symbol = createSymbol(0 /* None */, name)); } else { if (ts.isNamedDeclaration(node)) { node.name.parent = node; } - var message_1 = symbol.flags & 2 + // Report errors every position with duplicate declaration + // Report errors on previous encountered declarations + var message_1 = symbol.flags & 2 /* BlockScopedVariable */ ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 : ts.Diagnostics.Duplicate_identifier_0; - if (symbol.flags & 384 || includes & 384) { + if (symbol.flags & 384 /* Enum */ || includes & 384 /* Enum */) { message_1 = ts.Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations; } if (symbol.declarations && symbol.declarations.length) { + // If the current node is a default export of some sort, then check if + // there are any other default exports that we need to error on. + // We'll know whether we have other default exports depending on if `symbol` already has a declaration list set. if (isDefaultExport) { message_1 = ts.Diagnostics.A_module_cannot_have_multiple_default_exports; } else { + // This is to properly report an error in the case "export default { }" is after export default of class declaration or function declaration. + // Error on multiple export default in the following case: + // 1. multiple export default of class declaration or function declaration by checking NodeFlags.Default + // 2. multiple export default of export assignment. This one doesn't have NodeFlags.Default on (as export default doesn't considered as modifiers) if (symbol.declarations && symbol.declarations.length && - (node.kind === 249 && !node.isExportEquals)) { + (node.kind === 249 /* ExportAssignment */ && !node.isExportEquals)) { message_1 = ts.Diagnostics.A_module_cannot_have_multiple_default_exports; } } @@ -22163,7 +25773,7 @@ var ts; file.bindDiagnostics.push(createDiagnosticForNode(ts.getNameOfDeclaration(declaration) || declaration, message_1, getDisplayName(declaration))); }); file.bindDiagnostics.push(createDiagnosticForNode(ts.getNameOfDeclaration(node) || node, message_1, getDisplayName(node))); - symbol = createSymbol(0, name); + symbol = createSymbol(0 /* None */, name); } } } @@ -22177,85 +25787,127 @@ var ts; return symbol; } function declareModuleMember(node, symbolFlags, symbolExcludes) { - var hasExportModifier = ts.getCombinedModifierFlags(node) & 1; - if (symbolFlags & 2097152) { - if (node.kind === 252 || (node.kind === 243 && hasExportModifier)) { + var hasExportModifier = ts.getCombinedModifierFlags(node) & 1 /* Export */; + if (symbolFlags & 2097152 /* Alias */) { + if (node.kind === 252 /* ExportSpecifier */ || (node.kind === 243 /* ImportEqualsDeclaration */ && hasExportModifier)) { return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); } else { - return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); + return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); } } else { + // Exported module members are given 2 symbols: A local symbol that is classified with an ExportValue flag, + // and an associated export symbol with all the correct flags set on it. There are 2 main reasons: + // + // 1. We treat locals and exports of the same name as mutually exclusive within a container. + // That means the binder will issue a Duplicate Identifier error if you mix locals and exports + // with the same name in the same container. + // TODO: Make this a more specific error and decouple it from the exclusion logic. + // 2. When we checkIdentifier in the checker, we set its resolved symbol to the local symbol, + // but return the export symbol (by calling getExportSymbolOfValueSymbolIfExported). That way + // when the emitter comes back to it, it knows not to qualify the name if it was found in a containing scope. + // NOTE: Nested ambient modules always should go to to 'locals' table to prevent their automatic merge + // during global merging in the checker. Why? The only case when ambient module is permitted inside another module is module augmentation + // and this case is specially handled. Module augmentations should only be merged with original module definition + // and should never be merged directly with other augmentation, and the latter case would be possible if automatic merge is allowed. if (ts.isJSDocTypeAlias(node)) - ts.Debug.assert(ts.isInJavaScriptFile(node)); - if ((!ts.isAmbientModule(node) && (hasExportModifier || container.flags & 32)) || ts.isJSDocTypeAlias(node)) { - if (ts.hasModifier(node, 512) && !getDeclarationName(node)) { - return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); + ts.Debug.assert(ts.isInJavaScriptFile(node)); // We shouldn't add symbols for JSDoc nodes if not in a JS file. + if ((!ts.isAmbientModule(node) && (hasExportModifier || container.flags & 32 /* ExportContext */)) || ts.isJSDocTypeAlias(node)) { + if (ts.hasModifier(node, 512 /* Default */) && !getDeclarationName(node)) { + return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); // No local symbol for an unnamed default! } - var exportKind = symbolFlags & 67216319 ? 1048576 : 0; - var local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes); + var exportKind = symbolFlags & 67216319 /* Value */ ? 1048576 /* ExportValue */ : 0; + var local = declareSymbol(container.locals, /*parent*/ undefined, node, exportKind, symbolExcludes); local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); node.localSymbol = local; return local; } else { - return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); + return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); } } } + // All container nodes are kept on a linked list in declaration order. This list is used by + // the getLocalNameOfContainer function in the type checker to validate that the local name + // used for a container is unique. function bindContainer(node, containerFlags) { + // Before we recurse into a node's children, we first save the existing parent, container + // and block-container. Then after we pop out of processing the children, we restore + // these saved values. var saveContainer = container; var saveThisParentContainer = thisParentContainer; var savedBlockScopeContainer = blockScopeContainer; - if (containerFlags & 1) { - if (node.kind !== 193) { + // Depending on what kind of node this is, we may have to adjust the current container + // and block-container. If the current node is a container, then it is automatically + // considered the current block-container as well. Also, for containers that we know + // may contain locals, we eagerly initialize the .locals field. We do this because + // it's highly likely that the .locals will be needed to place some child in (for example, + // a parameter, or variable declaration). + // + // However, we do not proactively create the .locals for block-containers because it's + // totally normal and common for block-containers to never actually have a block-scoped + // variable in them. We don't want to end up allocating an object for every 'block' we + // run into when most of them won't be necessary. + // + // Finally, if this is a block-container, then we clear out any existing .locals object + // it may contain within it. This happens in incremental scenarios. Because we can be + // reusing a node from a previous compilation, that node may have had 'locals' created + // for it. We must clear this so we don't accidentally move any stale data forward from + // a previous compilation. + if (containerFlags & 1 /* IsContainer */) { + if (node.kind !== 193 /* ArrowFunction */) { thisParentContainer = container; } container = blockScopeContainer = node; - if (containerFlags & 32) { + if (containerFlags & 32 /* HasLocals */) { container.locals = ts.createSymbolTable(); } addToContainerChain(container); } - else if (containerFlags & 2) { + else if (containerFlags & 2 /* IsBlockScopedContainer */) { blockScopeContainer = node; blockScopeContainer.locals = undefined; } - if (containerFlags & 4) { + if (containerFlags & 4 /* IsControlFlowContainer */) { var saveCurrentFlow = currentFlow; var saveBreakTarget = currentBreakTarget; var saveContinueTarget = currentContinueTarget; var saveReturnTarget = currentReturnTarget; var saveActiveLabels = activeLabels; var saveHasExplicitReturn = hasExplicitReturn; - var isIIFE = containerFlags & 16 && !ts.hasModifier(node, 256) && + var isIIFE = containerFlags & 16 /* IsFunctionExpression */ && !ts.hasModifier(node, 256 /* Async */) && !node.asteriskToken && !!ts.getImmediatelyInvokedFunctionExpression(node); + // A non-async, non-generator IIFE is considered part of the containing control flow. Return statements behave + // similarly to break statements that exit to a label just past the statement body. if (!isIIFE) { - currentFlow = { flags: 2 }; - if (containerFlags & (16 | 128)) { + currentFlow = { flags: 2 /* Start */ }; + if (containerFlags & (16 /* IsFunctionExpression */ | 128 /* IsObjectLiteralOrClassExpressionMethod */)) { currentFlow.container = node; } } - currentReturnTarget = isIIFE || node.kind === 155 ? createBranchLabel() : undefined; + // We create a return control flow graph for IIFEs and constructors. For constructors + // we use the return control flow graph in strict property intialization checks. + currentReturnTarget = isIIFE || node.kind === 155 /* Constructor */ ? createBranchLabel() : undefined; currentBreakTarget = undefined; currentContinueTarget = undefined; activeLabels = undefined; hasExplicitReturn = false; bindChildren(node); - node.flags &= ~1408; - if (!(currentFlow.flags & 1) && containerFlags & 8 && ts.nodeIsPresent(node.body)) { - node.flags |= 128; + // Reset all reachability check related flags on node (for incremental scenarios) + node.flags &= ~1408 /* ReachabilityAndEmitFlags */; + if (!(currentFlow.flags & 1 /* Unreachable */) && containerFlags & 8 /* IsFunctionLike */ && ts.nodeIsPresent(node.body)) { + node.flags |= 128 /* HasImplicitReturn */; if (hasExplicitReturn) - node.flags |= 256; + node.flags |= 256 /* HasExplicitReturn */; } - if (node.kind === 274) { + if (node.kind === 274 /* SourceFile */) { node.flags |= emitFlags; } if (currentReturnTarget) { addAntecedent(currentReturnTarget, currentFlow); currentFlow = finishFlowLabel(currentReturnTarget); - if (node.kind === 155) { + if (node.kind === 155 /* Constructor */) { node.returnFlowNode = currentFlow; } } @@ -22268,10 +25920,10 @@ var ts; activeLabels = saveActiveLabels; hasExplicitReturn = saveHasExplicitReturn; } - else if (containerFlags & 64) { + else if (containerFlags & 64 /* IsInterface */) { seenThisKeyword = false; bindChildren(node); - node.flags = seenThisKeyword ? node.flags | 64 : node.flags & ~64; + node.flags = seenThisKeyword ? node.flags | 64 /* ContainsThis */ : node.flags & ~64 /* ContainsThis */; } else { bindChildren(node); @@ -22284,7 +25936,7 @@ var ts; if (skipTransformFlagAggregation) { bindChildrenWorker(node); } - else if (node.transformFlags & 536870912) { + else if (node.transformFlags & 536870912 /* HasComputedFlags */) { skipTransformFlagAggregation = true; bindChildrenWorker(node); skipTransformFlagAggregation = false; @@ -22298,8 +25950,8 @@ var ts; } } function bindEachFunctionsFirst(nodes) { - bindEach(nodes, function (n) { return n.kind === 234 ? bind(n) : undefined; }); - bindEach(nodes, function (n) { return n.kind !== 234 ? bind(n) : undefined; }); + bindEach(nodes, function (n) { return n.kind === 234 /* FunctionDeclaration */ ? bind(n) : undefined; }); + bindEach(nodes, function (n) { return n.kind !== 234 /* FunctionDeclaration */ ? bind(n) : undefined; }); } function bindEach(nodes, bindFunction) { if (bindFunction === void 0) { bindFunction = bind; } @@ -22311,14 +25963,14 @@ var ts; } else { var savedSubtreeTransformFlags = subtreeTransformFlags; - subtreeTransformFlags = 0; - var nodeArrayFlags = 0; + subtreeTransformFlags = 0 /* None */; + var nodeArrayFlags = 0 /* None */; for (var _i = 0, nodes_2 = nodes; _i < nodes_2.length; _i++) { var node = nodes_2[_i]; bindFunction(node); - nodeArrayFlags |= node.transformFlags & ~536870912; + nodeArrayFlags |= node.transformFlags & ~536870912 /* HasComputedFlags */; } - nodes.transformFlags = nodeArrayFlags | 536870912; + nodes.transformFlags = nodeArrayFlags | 536870912 /* HasComputedFlags */; subtreeTransformFlags |= savedSubtreeTransformFlags; } } @@ -22331,76 +25983,77 @@ var ts; return; } switch (node.kind) { - case 219: + case 219 /* WhileStatement */: bindWhileStatement(node); break; - case 218: + case 218 /* DoStatement */: bindDoStatement(node); break; - case 220: + case 220 /* ForStatement */: bindForStatement(node); break; - case 221: - case 222: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: bindForInOrForOfStatement(node); break; - case 217: + case 217 /* IfStatement */: bindIfStatement(node); break; - case 225: - case 229: + case 225 /* ReturnStatement */: + case 229 /* ThrowStatement */: bindReturnOrThrow(node); break; - case 224: - case 223: + case 224 /* BreakStatement */: + case 223 /* ContinueStatement */: bindBreakOrContinueStatement(node); break; - case 230: + case 230 /* TryStatement */: bindTryStatement(node); break; - case 227: + case 227 /* SwitchStatement */: bindSwitchStatement(node); break; - case 241: + case 241 /* CaseBlock */: bindCaseBlock(node); break; - case 266: + case 266 /* CaseClause */: bindCaseClause(node); break; - case 228: + case 228 /* LabeledStatement */: bindLabeledStatement(node); break; - case 198: + case 198 /* PrefixUnaryExpression */: bindPrefixUnaryExpressionFlow(node); break; - case 199: + case 199 /* PostfixUnaryExpression */: bindPostfixUnaryExpressionFlow(node); break; - case 200: + case 200 /* BinaryExpression */: bindBinaryExpressionFlow(node); break; - case 194: + case 194 /* DeleteExpression */: bindDeleteExpressionFlow(node); break; - case 201: + case 201 /* ConditionalExpression */: bindConditionalExpressionFlow(node); break; - case 232: + case 232 /* VariableDeclaration */: bindVariableDeclarationFlow(node); break; - case 187: + case 187 /* CallExpression */: bindCallExpressionFlow(node); break; - case 298: - case 292: + case 298 /* JSDocTypedefTag */: + case 292 /* JSDocCallbackTag */: bindJSDocTypeAlias(node); break; - case 274: + // In source files and blocks, bind functions first to match hoisting that occurs at runtime + case 274 /* SourceFile */: bindEachFunctionsFirst(node.statements); bind(node.endOfFileToken); break; - case 213: - case 240: + case 213 /* Block */: + case 240 /* ModuleBlock */: bindEachFunctionsFirst(node.statements); break; default: @@ -22411,26 +26064,26 @@ var ts; } function isNarrowingExpression(expr) { switch (expr.kind) { - case 71: - case 99: - case 185: + case 71 /* Identifier */: + case 99 /* ThisKeyword */: + case 185 /* PropertyAccessExpression */: return isNarrowableReference(expr); - case 187: + case 187 /* CallExpression */: return hasNarrowableArgument(expr); - case 191: + case 191 /* ParenthesizedExpression */: return isNarrowingExpression(expr.expression); - case 200: + case 200 /* BinaryExpression */: return isNarrowingBinaryExpression(expr); - case 198: - return expr.operator === 51 && isNarrowingExpression(expr.operand); + case 198 /* PrefixUnaryExpression */: + return expr.operator === 51 /* ExclamationToken */ && isNarrowingExpression(expr.operand); } return false; } function isNarrowableReference(expr) { - return expr.kind === 71 || - expr.kind === 99 || - expr.kind === 97 || - expr.kind === 185 && isNarrowableReference(expr.expression); + return expr.kind === 71 /* Identifier */ || + expr.kind === 99 /* ThisKeyword */ || + expr.kind === 97 /* SuperKeyword */ || + expr.kind === 185 /* PropertyAccessExpression */ && isNarrowableReference(expr.expression); } function hasNarrowableArgument(expr) { if (expr.arguments) { @@ -22441,7 +26094,7 @@ var ts; } } } - if (expr.expression.kind === 185 && + if (expr.expression.kind === 185 /* PropertyAccessExpression */ && isNarrowableReference(expr.expression.expression)) { return true; } @@ -22455,32 +26108,32 @@ var ts; } function isNarrowingBinaryExpression(expr) { switch (expr.operatorToken.kind) { - case 58: + case 58 /* EqualsToken */: return isNarrowableReference(expr.left); - case 32: - case 33: - case 34: - case 35: + case 32 /* EqualsEqualsToken */: + case 33 /* ExclamationEqualsToken */: + case 34 /* EqualsEqualsEqualsToken */: + case 35 /* ExclamationEqualsEqualsToken */: return isNarrowableOperand(expr.left) || isNarrowableOperand(expr.right) || isNarrowingTypeofOperands(expr.right, expr.left) || isNarrowingTypeofOperands(expr.left, expr.right); - case 93: + case 93 /* InstanceOfKeyword */: return isNarrowableOperand(expr.left); - case 92: + case 92 /* InKeyword */: return isNarrowableInOperands(expr.left, expr.right); - case 26: + case 26 /* CommaToken */: return isNarrowingExpression(expr.right); } return false; } function isNarrowableOperand(expr) { switch (expr.kind) { - case 191: + case 191 /* ParenthesizedExpression */: return isNarrowableOperand(expr.expression); - case 200: + case 200 /* BinaryExpression */: switch (expr.operatorToken.kind) { - case 58: + case 58 /* EqualsToken */: return isNarrowableOperand(expr.left); - case 26: + case 26 /* CommaToken */: return isNarrowableOperand(expr.right); } } @@ -22488,34 +26141,35 @@ var ts; } function createBranchLabel() { return { - flags: 4, + flags: 4 /* BranchLabel */, antecedents: undefined }; } function createLoopLabel() { return { - flags: 8, + flags: 8 /* LoopLabel */, antecedents: undefined }; } function setFlowNodeReferenced(flow) { - flow.flags |= flow.flags & 512 ? 1024 : 512; + // On first reference we set the Referenced flag, thereafter we set the Shared flag + flow.flags |= flow.flags & 512 /* Referenced */ ? 1024 /* Shared */ : 512 /* Referenced */; } function addAntecedent(label, antecedent) { - if (!(antecedent.flags & 1) && !ts.contains(label.antecedents, antecedent)) { + if (!(antecedent.flags & 1 /* Unreachable */) && !ts.contains(label.antecedents, antecedent)) { (label.antecedents || (label.antecedents = [])).push(antecedent); setFlowNodeReferenced(antecedent); } } function createFlowCondition(flags, antecedent, expression) { - if (antecedent.flags & 1) { + if (antecedent.flags & 1 /* Unreachable */) { return antecedent; } if (!expression) { - return flags & 32 ? antecedent : unreachableFlow; + return flags & 32 /* TrueCondition */ ? antecedent : unreachableFlow; } - if (expression.kind === 101 && flags & 64 || - expression.kind === 86 && flags & 32) { + if (expression.kind === 101 /* TrueKeyword */ && flags & 64 /* FalseCondition */ || + expression.kind === 86 /* FalseKeyword */ && flags & 32 /* TrueCondition */) { return unreachableFlow; } if (!isNarrowingExpression(expression)) { @@ -22529,15 +26183,15 @@ var ts; return antecedent; } setFlowNodeReferenced(antecedent); - return { flags: 128, switchStatement: switchStatement, clauseStart: clauseStart, clauseEnd: clauseEnd, antecedent: antecedent }; + return { flags: 128 /* SwitchClause */, switchStatement: switchStatement, clauseStart: clauseStart, clauseEnd: clauseEnd, antecedent: antecedent }; } function createFlowAssignment(antecedent, node) { setFlowNodeReferenced(antecedent); - return { flags: 16, antecedent: antecedent, node: node }; + return { flags: 16 /* Assignment */, antecedent: antecedent, node: node }; } function createFlowArrayMutation(antecedent, node) { setFlowNodeReferenced(antecedent); - var res = { flags: 256, antecedent: antecedent, node: node }; + var res = { flags: 256 /* ArrayMutation */, antecedent: antecedent, node: node }; return res; } function finishFlowLabel(flow) { @@ -22553,34 +26207,34 @@ var ts; function isStatementCondition(node) { var parent = node.parent; switch (parent.kind) { - case 217: - case 219: - case 218: + case 217 /* IfStatement */: + case 219 /* WhileStatement */: + case 218 /* DoStatement */: return parent.expression === node; - case 220: - case 201: + case 220 /* ForStatement */: + case 201 /* ConditionalExpression */: return parent.condition === node; } return false; } function isLogicalExpression(node) { while (true) { - if (node.kind === 191) { + if (node.kind === 191 /* ParenthesizedExpression */) { node = node.expression; } - else if (node.kind === 198 && node.operator === 51) { + else if (node.kind === 198 /* PrefixUnaryExpression */ && node.operator === 51 /* ExclamationToken */) { node = node.operand; } else { - return node.kind === 200 && (node.operatorToken.kind === 53 || - node.operatorToken.kind === 54); + return node.kind === 200 /* BinaryExpression */ && (node.operatorToken.kind === 53 /* AmpersandAmpersandToken */ || + node.operatorToken.kind === 54 /* BarBarToken */); } } } function isTopLevelLogicalExpression(node) { - while (node.parent.kind === 191 || - node.parent.kind === 198 && - node.parent.operator === 51) { + while (node.parent.kind === 191 /* ParenthesizedExpression */ || + node.parent.kind === 198 /* PrefixUnaryExpression */ && + node.parent.operator === 51 /* ExclamationToken */) { node = node.parent; } return !isStatementCondition(node) && !isLogicalExpression(node.parent); @@ -22594,8 +26248,8 @@ var ts; currentTrueTarget = saveTrueTarget; currentFalseTarget = saveFalseTarget; if (!node || !isLogicalExpression(node)) { - addAntecedent(trueTarget, createFlowCondition(32, currentFlow, node)); - addAntecedent(falseTarget, createFlowCondition(64, currentFlow, node)); + addAntecedent(trueTarget, createFlowCondition(32 /* TrueCondition */, currentFlow, node)); + addAntecedent(falseTarget, createFlowCondition(64 /* FalseCondition */, currentFlow, node)); } } function bindIterativeStatement(node, breakTarget, continueTarget) { @@ -22621,9 +26275,11 @@ var ts; } function bindDoStatement(node) { var preDoLabel = createLoopLabel(); - var enclosingLabeledStatement = node.parent.kind === 228 + var enclosingLabeledStatement = node.parent.kind === 228 /* LabeledStatement */ ? ts.lastOrUndefined(activeLabels) : undefined; + // if do statement is wrapped in labeled statement then target labels for break/continue with or without + // label should be the same var preConditionLabel = enclosingLabeledStatement ? enclosingLabeledStatement.continueTarget : createBranchLabel(); var postDoLabel = enclosingLabeledStatement ? enclosingLabeledStatement.breakTarget : createBranchLabel(); addAntecedent(preDoLabel, currentFlow); @@ -22653,13 +26309,13 @@ var ts; var postLoopLabel = createBranchLabel(); addAntecedent(preLoopLabel, currentFlow); currentFlow = preLoopLabel; - if (node.kind === 222) { + if (node.kind === 222 /* ForOfStatement */) { bind(node.awaitModifier); } bind(node.expression); addAntecedent(postLoopLabel, currentFlow); bind(node.initializer); - if (node.initializer.kind !== 233) { + if (node.initializer.kind !== 233 /* VariableDeclarationList */) { bindAssignmentTargetFlow(node.initializer); } bindIterativeStatement(node.statement, postLoopLabel, preLoopLabel); @@ -22681,7 +26337,7 @@ var ts; } function bindReturnOrThrow(node) { bind(node.expression); - if (node.kind === 225) { + if (node.kind === 225 /* ReturnStatement */) { hasExplicitReturn = true; if (currentReturnTarget) { addAntecedent(currentReturnTarget, currentFlow); @@ -22701,7 +26357,7 @@ var ts; return undefined; } function bindBreakOrContinueFlow(node, breakTarget, continueTarget) { - var flowLabel = node.kind === 224 ? breakTarget : continueTarget; + var flowLabel = node.kind === 224 /* BreakStatement */ ? breakTarget : continueTarget; if (flowLabel) { addAntecedent(flowLabel, currentFlow); currentFlow = unreachableFlow; @@ -22723,6 +26379,7 @@ var ts; function bindTryStatement(node) { var preFinallyLabel = createBranchLabel(); var preTryFlow = currentFlow; + // TODO: Every statement in try block is potentially an exit point! bind(node.tryBlock); addAntecedent(preFinallyLabel, currentFlow); var flowAfterTry = currentFlow; @@ -22734,19 +26391,51 @@ var ts; flowAfterCatch = currentFlow; } if (node.finallyBlock) { - var preFinallyFlow = { flags: 2048, antecedent: preTryFlow, lock: {} }; + // in finally flow is combined from pre-try/flow from try/flow from catch + // pre-flow is necessary to make sure that finally is reachable even if finally flows in both try and finally blocks are unreachable + // also for finally blocks we inject two extra edges into the flow graph. + // first -> edge that connects pre-try flow with the label at the beginning of the finally block, it has lock associated with it + // second -> edge that represents post-finally flow. + // these edges are used in following scenario: + // let a; (1) + // try { a = someOperation(); (2)} + // finally { (3) console.log(a) } (4) + // (5) a + // flow graph for this case looks roughly like this (arrows show ): + // (1-pre-try-flow) <--.. <-- (2-post-try-flow) + // ^ ^ + // |*****(3-pre-finally-label) -----| + // ^ + // |-- ... <-- (4-post-finally-label) <--- (5) + // In case when we walk the flow starting from inside the finally block we want to take edge '*****' into account + // since it ensures that finally is always reachable. However when we start outside the finally block and go through label (5) + // then edge '*****' should be discarded because label 4 is only reachable if post-finally label-4 is reachable + // Simply speaking code inside finally block is treated as reachable as pre-try-flow + // since we conservatively assume that any line in try block can throw or return in which case we'll enter finally. + // However code after finally is reachable only if control flow was not abrupted in try/catch or finally blocks - it should be composed from + // final flows of these blocks without taking pre-try flow into account. + // + // extra edges that we inject allows to control this behavior + // if when walking the flow we step on post-finally edge - we can mark matching pre-finally edge as locked so it will be skipped. + var preFinallyFlow = { flags: 2048 /* PreFinally */, antecedent: preTryFlow, lock: {} }; addAntecedent(preFinallyLabel, preFinallyFlow); currentFlow = finishFlowLabel(preFinallyLabel); bind(node.finallyBlock); - if (!(currentFlow.flags & 1)) { - if ((flowAfterTry.flags & 1) && (flowAfterCatch.flags & 1)) { + // if flow after finally is unreachable - keep it + // otherwise check if flows after try and after catch are unreachable + // if yes - convert current flow to unreachable + // i.e. + // try { return "1" } finally { console.log(1); } + // console.log(2); // this line should be unreachable even if flow falls out of finally block + if (!(currentFlow.flags & 1 /* Unreachable */)) { + if ((flowAfterTry.flags & 1 /* Unreachable */) && (flowAfterCatch.flags & 1 /* Unreachable */)) { currentFlow = flowAfterTry === reportedUnreachableFlow || flowAfterCatch === reportedUnreachableFlow ? reportedUnreachableFlow : unreachableFlow; } } - if (!(currentFlow.flags & 1)) { - var afterFinallyFlow = { flags: 4096, antecedent: currentFlow }; + if (!(currentFlow.flags & 1 /* Unreachable */)) { + var afterFinallyFlow = { flags: 4096 /* AfterFinally */, antecedent: currentFlow }; preFinallyFlow.lock = afterFinallyFlow; currentFlow = afterFinallyFlow; } @@ -22764,7 +26453,9 @@ var ts; preSwitchCaseFlow = currentFlow; bind(node.caseBlock); addAntecedent(postSwitchLabel, currentFlow); - var hasDefault = ts.forEach(node.caseBlock.clauses, function (c) { return c.kind === 267; }); + var hasDefault = ts.forEach(node.caseBlock.clauses, function (c) { return c.kind === 267 /* DefaultClause */; }); + // We mark a switch statement as possibly exhaustive if it has no default clause and if all + // case clauses have unreachable end points (e.g. they all return). node.possiblyExhaustive = !hasDefault && !postSwitchLabel.antecedents; if (!hasDefault) { addAntecedent(postSwitchLabel, createFlowSwitchClause(preSwitchCaseFlow, node, 0, 0)); @@ -22792,11 +26483,11 @@ var ts; var clause = clauses[i]; bind(clause); fallthroughFlow = currentFlow; - if (!(currentFlow.flags & 1) && i !== clauses.length - 1 && options.noFallthroughCasesInSwitch) { + if (!(currentFlow.flags & 1 /* Unreachable */) && i !== clauses.length - 1 && options.noFallthroughCasesInSwitch) { errorOnFirstToken(clause, ts.Diagnostics.Fallthrough_case_in_switch); } } - clauses.transformFlags = subtreeTransformFlags | 536870912; + clauses.transformFlags = subtreeTransformFlags | 536870912 /* HasComputedFlags */; subtreeTransformFlags |= savedSubtreeTransformFlags; } function bindCaseClause(node) { @@ -22830,13 +26521,14 @@ var ts; if (!activeLabel.referenced && !options.allowUnusedLabels) { errorOrSuggestionOnFirstToken(ts.unusedLabelIsError(options), node, ts.Diagnostics.Unused_label); } - if (!node.statement || node.statement.kind !== 218) { + if (!node.statement || node.statement.kind !== 218 /* DoStatement */) { + // do statement sets current flow inside bindDoStatement addAntecedent(postStatementLabel, currentFlow); currentFlow = finishFlowLabel(postStatementLabel); } } function bindDestructuringTargetFlow(node) { - if (node.kind === 200 && node.operatorToken.kind === 58) { + if (node.kind === 200 /* BinaryExpression */ && node.operatorToken.kind === 58 /* EqualsToken */) { bindAssignmentTargetFlow(node.left); } else { @@ -22847,10 +26539,10 @@ var ts; if (isNarrowableReference(node)) { currentFlow = createFlowAssignment(currentFlow, node); } - else if (node.kind === 183) { + else if (node.kind === 183 /* ArrayLiteralExpression */) { for (var _i = 0, _a = node.elements; _i < _a.length; _i++) { var e = _a[_i]; - if (e.kind === 204) { + if (e.kind === 204 /* SpreadElement */) { bindAssignmentTargetFlow(e.expression); } else { @@ -22858,16 +26550,16 @@ var ts; } } } - else if (node.kind === 184) { + else if (node.kind === 184 /* ObjectLiteralExpression */) { for (var _b = 0, _c = node.properties; _b < _c.length; _b++) { var p = _c[_b]; - if (p.kind === 270) { + if (p.kind === 270 /* PropertyAssignment */) { bindDestructuringTargetFlow(p.initializer); } - else if (p.kind === 271) { + else if (p.kind === 271 /* ShorthandPropertyAssignment */) { bindAssignmentTargetFlow(p.name); } - else if (p.kind === 272) { + else if (p.kind === 272 /* SpreadAssignment */) { bindAssignmentTargetFlow(p.expression); } } @@ -22875,7 +26567,7 @@ var ts; } function bindLogicalExpression(node, trueTarget, falseTarget) { var preRightLabel = createBranchLabel(); - if (node.operatorToken.kind === 53) { + if (node.operatorToken.kind === 53 /* AmpersandAmpersandToken */) { bindCondition(node.left, preRightLabel, falseTarget); } else { @@ -22886,7 +26578,7 @@ var ts; bindCondition(node.right, trueTarget, falseTarget); } function bindPrefixUnaryExpressionFlow(node) { - if (node.operator === 51) { + if (node.operator === 51 /* ExclamationToken */) { var saveTrueTarget = currentTrueTarget; currentTrueTarget = currentFalseTarget; currentFalseTarget = saveTrueTarget; @@ -22896,20 +26588,20 @@ var ts; } else { bindEachChild(node); - if (node.operator === 43 || node.operator === 44) { + if (node.operator === 43 /* PlusPlusToken */ || node.operator === 44 /* MinusMinusToken */) { bindAssignmentTargetFlow(node.operand); } } } function bindPostfixUnaryExpressionFlow(node) { bindEachChild(node); - if (node.operator === 43 || node.operator === 44) { + if (node.operator === 43 /* PlusPlusToken */ || node.operator === 44 /* MinusMinusToken */) { bindAssignmentTargetFlow(node.operand); } } function bindBinaryExpressionFlow(node) { var operator = node.operatorToken.kind; - if (operator === 53 || operator === 54) { + if (operator === 53 /* AmpersandAmpersandToken */ || operator === 54 /* BarBarToken */) { if (isTopLevelLogicalExpression(node)) { var postExpressionLabel = createBranchLabel(); bindLogicalExpression(node, postExpressionLabel, postExpressionLabel); @@ -22923,7 +26615,7 @@ var ts; bindEachChild(node); if (ts.isAssignmentOperator(operator) && !ts.isAssignmentTarget(node)) { bindAssignmentTargetFlow(node.left); - if (operator === 58 && node.left.kind === 186) { + if (operator === 58 /* EqualsToken */ && node.left.kind === 186 /* ElementAccessExpression */) { var elementAccess = node.left; if (isNarrowableOperand(elementAccess.expression)) { currentFlow = createFlowArrayMutation(currentFlow, node); @@ -22934,7 +26626,7 @@ var ts; } function bindDeleteExpressionFlow(node) { bindEachChild(node); - if (node.expression.kind === 185) { + if (node.expression.kind === 185 /* PropertyAccessExpression */) { bindAssignmentTargetFlow(node.expression); } } @@ -22977,11 +26669,14 @@ var ts; } } function bindCallExpressionFlow(node) { + // If the target of the call expression is a function expression or arrow function we have + // an immediately invoked function expression (IIFE). Initialize the flowNode property to + // the current control flow (which includes evaluation of the IIFE arguments). var expr = node.expression; - while (expr.kind === 191) { + while (expr.kind === 191 /* ParenthesizedExpression */) { expr = expr.expression; } - if (expr.kind === 192 || expr.kind === 193) { + if (expr.kind === 192 /* FunctionExpression */ || expr.kind === 193 /* ArrowFunction */) { bindEach(node.typeArguments); bindEach(node.arguments); bind(node.expression); @@ -22989,7 +26684,7 @@ var ts; else { bindEachChild(node); } - if (node.expression.kind === 185) { + if (node.expression.kind === 185 /* PropertyAccessExpression */) { var propertyAccess = node.expression; if (isNarrowableOperand(propertyAccess.expression) && ts.isPushOrUnshiftIdentifier(propertyAccess.name)) { currentFlow = createFlowArrayMutation(currentFlow, node); @@ -22998,56 +26693,73 @@ var ts; } function getContainerFlags(node) { switch (node.kind) { - case 205: - case 235: - case 238: - case 184: - case 166: - case 287: - case 263: - return 1; - case 236: - return 1 | 64; - case 239: - case 237: - case 177: - return 1 | 32; - case 274: - return 1 | 4 | 32; - case 154: + case 205 /* ClassExpression */: + case 235 /* ClassDeclaration */: + case 238 /* EnumDeclaration */: + case 184 /* ObjectLiteralExpression */: + case 166 /* TypeLiteral */: + case 287 /* JSDocTypeLiteral */: + case 263 /* JsxAttributes */: + return 1 /* IsContainer */; + case 236 /* InterfaceDeclaration */: + return 1 /* IsContainer */ | 64 /* IsInterface */; + case 239 /* ModuleDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 177 /* MappedType */: + return 1 /* IsContainer */ | 32 /* HasLocals */; + case 274 /* SourceFile */: + return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */; + case 154 /* MethodDeclaration */: if (ts.isObjectLiteralOrClassExpressionMethod(node)) { - return 1 | 4 | 32 | 8 | 128; + return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */ | 8 /* IsFunctionLike */ | 128 /* IsObjectLiteralOrClassExpressionMethod */; } - case 155: - case 234: - case 153: - case 156: - case 157: - case 158: - case 288: - case 284: - case 163: - case 159: - case 160: - case 164: - return 1 | 4 | 32 | 8; - case 192: - case 193: - return 1 | 4 | 32 | 8 | 16; - case 240: - return 4; - case 152: - return node.initializer ? 4 : 0; - case 269: - case 220: - case 221: - case 222: - case 241: - return 2; - case 213: - return ts.isFunctionLike(node.parent) ? 0 : 2; + // falls through + case 155 /* Constructor */: + case 234 /* FunctionDeclaration */: + case 153 /* MethodSignature */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 158 /* CallSignature */: + case 288 /* JSDocSignature */: + case 284 /* JSDocFunctionType */: + case 163 /* FunctionType */: + case 159 /* ConstructSignature */: + case 160 /* IndexSignature */: + case 164 /* ConstructorType */: + return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */ | 8 /* IsFunctionLike */; + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */ | 8 /* IsFunctionLike */ | 16 /* IsFunctionExpression */; + case 240 /* ModuleBlock */: + return 4 /* IsControlFlowContainer */; + case 152 /* PropertyDeclaration */: + return node.initializer ? 4 /* IsControlFlowContainer */ : 0; + case 269 /* CatchClause */: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 241 /* CaseBlock */: + return 2 /* IsBlockScopedContainer */; + case 213 /* Block */: + // do not treat blocks directly inside a function as a block-scoped-container. + // Locals that reside in this block should go to the function locals. Otherwise 'x' + // would not appear to be a redeclaration of a block scoped local in the following + // example: + // + // function foo() { + // var x; + // let x; + // } + // + // If we placed 'var x' into the function locals and 'let x' into the locals of + // the block, then there would be no collision. + // + // By not creating a new block-scoped-container here, we ensure that both 'var x' + // and 'let x' go into the Function-container's locals, and we do get a collision + // conflict. + return ts.isFunctionLike(node.parent) ? 0 /* None */ : 2 /* IsBlockScopedContainer */; } - return 0; + return 0 /* None */; } function addToContainerChain(next) { if (lastContainer) { @@ -23057,59 +26769,74 @@ var ts; } function declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes) { switch (container.kind) { - case 239: + // Modules, source files, and classes need specialized handling for how their + // members are declared (for example, a member of a class will go into a specific + // symbol table depending on if it is static or not). We defer to specialized + // handlers to take care of declaring these child members. + case 239 /* ModuleDeclaration */: return declareModuleMember(node, symbolFlags, symbolExcludes); - case 274: + case 274 /* SourceFile */: return declareSourceFileMember(node, symbolFlags, symbolExcludes); - case 205: - case 235: + case 205 /* ClassExpression */: + case 235 /* ClassDeclaration */: return declareClassMember(node, symbolFlags, symbolExcludes); - case 238: + case 238 /* EnumDeclaration */: return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes); - case 166: - case 287: - case 184: - case 236: - case 263: + case 166 /* TypeLiteral */: + case 287 /* JSDocTypeLiteral */: + case 184 /* ObjectLiteralExpression */: + case 236 /* InterfaceDeclaration */: + case 263 /* JsxAttributes */: + // Interface/Object-types always have their children added to the 'members' of + // their container. They are only accessible through an instance of their + // container, and are never in scope otherwise (even inside the body of the + // object / type / interface declaring them). An exception is type parameters, + // which are in scope without qualification (similar to 'locals'). return declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); - case 163: - case 164: - case 158: - case 159: - case 288: - case 160: - case 154: - case 153: - case 155: - case 156: - case 157: - case 234: - case 192: - case 193: - case 284: - case 298: - case 292: - case 237: - case 177: - return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes); + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 288 /* JSDocSignature */: + case 160 /* IndexSignature */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 284 /* JSDocFunctionType */: + case 298 /* JSDocTypedefTag */: + case 292 /* JSDocCallbackTag */: + case 237 /* TypeAliasDeclaration */: + case 177 /* MappedType */: + // All the children of these container types are never visible through another + // symbol (i.e. through another symbol's 'exports' or 'members'). Instead, + // they're only accessed 'lexically' (i.e. from code that exists underneath + // their container in the tree). To accomplish this, we simply add their declared + // symbol to the 'locals' of the container. These symbols can then be found as + // the type checker walks up the containers, checking them for matching names. + return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); } } function declareClassMember(node, symbolFlags, symbolExcludes) { - return ts.hasModifier(node, 32) + return ts.hasModifier(node, 32 /* Static */) ? declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes) : declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes); } function declareSourceFileMember(node, symbolFlags, symbolExcludes) { return ts.isExternalModule(file) ? declareModuleMember(node, symbolFlags, symbolExcludes) - : declareSymbol(file.locals, undefined, node, symbolFlags, symbolExcludes); + : declareSymbol(file.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); } function hasExportDeclarations(node) { - var body = node.kind === 274 ? node : node.body; - if (body && (body.kind === 274 || body.kind === 240)) { + var body = node.kind === 274 /* SourceFile */ ? node : node.body; + if (body && (body.kind === 274 /* SourceFile */ || body.kind === 240 /* ModuleBlock */)) { for (var _i = 0, _a = body.statements; _i < _a.length; _i++) { var stat = _a[_i]; - if (stat.kind === 250 || stat.kind === 249) { + if (stat.kind === 250 /* ExportDeclaration */ || stat.kind === 249 /* ExportAssignment */) { return true; } } @@ -23117,17 +26844,19 @@ var ts; return false; } function setExportContextFlag(node) { - if (node.flags & 4194304 && !hasExportDeclarations(node)) { - node.flags |= 32; + // A declaration source file or ambient module declaration that contains no export declarations (but possibly regular + // declarations with export modifiers) is an export context in which declarations are implicitly exported. + if (node.flags & 4194304 /* Ambient */ && !hasExportDeclarations(node)) { + node.flags |= 32 /* ExportContext */; } else { - node.flags &= ~32; + node.flags &= ~32 /* ExportContext */; } } function bindModuleDeclaration(node) { setExportContextFlag(node); if (ts.isAmbientModule(node)) { - if (ts.hasModifier(node, 1)) { + if (ts.hasModifier(node, 1 /* Export */)) { errorOnFirstToken(node, ts.Diagnostics.export_modifier_cannot_be_applied_to_ambient_modules_and_module_augmentations_since_they_are_always_visible); } if (ts.isModuleAugmentationExternal(node)) { @@ -23135,7 +26864,7 @@ var ts; } else { var pattern = void 0; - if (node.name.kind === 9) { + if (node.name.kind === 9 /* StringLiteral */) { var text = node.name.text; if (ts.hasZeroOrOneAsteriskCharacter(text)) { pattern = ts.tryParsePattern(text); @@ -23144,31 +26873,40 @@ var ts; errorOnFirstToken(node.name, ts.Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, text); } } - var symbol = declareSymbolAndAddToSymbolTable(node, 512, 67215503); + var symbol = declareSymbolAndAddToSymbolTable(node, 512 /* ValueModule */, 67215503 /* ValueModuleExcludes */); file.patternAmbientModules = ts.append(file.patternAmbientModules, pattern && { pattern: pattern, symbol: symbol }); } } else { var state = declareModuleSymbol(node); - if (state !== 0) { + if (state !== 0 /* NonInstantiated */) { var symbol = node.symbol; - symbol.constEnumOnlyModule = (!(symbol.flags & (16 | 32 | 256))) - && state === 2 + // if module was already merged with some function, class or non-const enum, treat it as non-const-enum-only + symbol.constEnumOnlyModule = (!(symbol.flags & (16 /* Function */ | 32 /* Class */ | 256 /* RegularEnum */))) + // Current must be `const enum` only + && state === 2 /* ConstEnumOnly */ + // Can't have been set to 'false' in a previous merged symbol. ('undefined' OK) && symbol.constEnumOnlyModule !== false; } } } function declareModuleSymbol(node) { var state = getModuleInstanceState(node); - var instantiated = state !== 0; - declareSymbolAndAddToSymbolTable(node, instantiated ? 512 : 1024, instantiated ? 67215503 : 0); + var instantiated = state !== 0 /* NonInstantiated */; + declareSymbolAndAddToSymbolTable(node, instantiated ? 512 /* ValueModule */ : 1024 /* NamespaceModule */, instantiated ? 67215503 /* ValueModuleExcludes */ : 0 /* NamespaceModuleExcludes */); return state; } function bindFunctionOrConstructorType(node) { - var symbol = createSymbol(131072, getDeclarationName(node)); - addDeclarationToSymbol(symbol, node, 131072); - var typeLiteralSymbol = createSymbol(2048, "__type"); - addDeclarationToSymbol(typeLiteralSymbol, node, 2048); + // For a given function symbol "<...>(...) => T" we want to generate a symbol identical + // to the one we would get for: { <...>(...): T } + // + // We do that by making an anonymous type literal symbol, and then setting the function + // symbol as its sole member. To the rest of the system, this symbol will be indistinguishable + // from an actual type literal symbol you would have gotten had you used the long form. + var symbol = createSymbol(131072 /* Signature */, getDeclarationName(node)); // TODO: GH#18217 + addDeclarationToSymbol(symbol, node, 131072 /* Signature */); + var typeLiteralSymbol = createSymbol(2048 /* TypeLiteral */, "__type" /* Type */); + addDeclarationToSymbol(typeLiteralSymbol, node, 2048 /* TypeLiteral */); typeLiteralSymbol.members = ts.createSymbolTable(); typeLiteralSymbol.members.set(symbol.escapedName, symbol); } @@ -23182,35 +26920,43 @@ var ts; var seen = ts.createUnderscoreEscapedMap(); for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { var prop = _a[_i]; - if (prop.kind === 272 || prop.name.kind !== 71) { + if (prop.kind === 272 /* SpreadAssignment */ || prop.name.kind !== 71 /* Identifier */) { continue; } var identifier = prop.name; - var currentKind = prop.kind === 270 || prop.kind === 271 || prop.kind === 154 - ? 1 - : 2; + // ECMA-262 11.1.5 Object Initializer + // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true + // a.This production is contained in strict code and IsDataDescriptor(previous) is true and + // IsDataDescriptor(propId.descriptor) is true. + // b.IsDataDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true. + // c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(propId.descriptor) is true. + // d.IsAccessorDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true + // and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields + var currentKind = prop.kind === 270 /* PropertyAssignment */ || prop.kind === 271 /* ShorthandPropertyAssignment */ || prop.kind === 154 /* MethodDeclaration */ + ? 1 /* Property */ + : 2 /* Accessor */; var existingKind = seen.get(identifier.escapedText); if (!existingKind) { seen.set(identifier.escapedText, currentKind); continue; } - if (currentKind === 1 && existingKind === 1) { + if (currentKind === 1 /* Property */ && existingKind === 1 /* Property */) { var span = ts.getErrorSpanForNode(file, identifier); file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode)); } } } - return bindAnonymousDeclaration(node, 4096, "__object"); + return bindAnonymousDeclaration(node, 4096 /* ObjectLiteral */, "__object" /* Object */); } function bindJsxAttributes(node) { - return bindAnonymousDeclaration(node, 4096, "__jsxAttributes"); + return bindAnonymousDeclaration(node, 4096 /* ObjectLiteral */, "__jsxAttributes" /* JSXAttributes */); } function bindJsxAttribute(node, symbolFlags, symbolExcludes) { return declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); } function bindAnonymousDeclaration(node, symbolFlags, name) { var symbol = createSymbol(symbolFlags, name); - if (symbolFlags & (8 | 106500)) { + if (symbolFlags & (8 /* EnumMember */ | 106500 /* ClassMember */)) { symbol.parent = container.symbol; } addDeclarationToSymbol(symbol, node, symbolFlags); @@ -23218,24 +26964,25 @@ var ts; } function bindBlockScopedDeclaration(node, symbolFlags, symbolExcludes) { switch (blockScopeContainer.kind) { - case 239: + case 239 /* ModuleDeclaration */: declareModuleMember(node, symbolFlags, symbolExcludes); break; - case 274: + case 274 /* SourceFile */: if (ts.isExternalOrCommonJsModule(container)) { declareModuleMember(node, symbolFlags, symbolExcludes); break; } + // falls through default: if (!blockScopeContainer.locals) { blockScopeContainer.locals = ts.createSymbolTable(); addToContainerChain(blockScopeContainer); } - declareSymbol(blockScopeContainer.locals, undefined, node, symbolFlags, symbolExcludes); + declareSymbol(blockScopeContainer.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); } } function bindBlockScopedVariableDeclaration(node) { - bindBlockScopedDeclaration(node, 2, 67216319); + bindBlockScopedDeclaration(node, 2 /* BlockScopedVariable */, 67216319 /* BlockScopedVariableExcludes */); } function delayedBindJSDocTypedefTag() { if (!delayedTypeAliases) { @@ -23249,14 +26996,14 @@ var ts; for (var _i = 0, delayedTypeAliases_1 = delayedTypeAliases; _i < delayedTypeAliases_1.length; _i++) { var typeAlias = delayedTypeAliases_1[_i]; var host = ts.getJSDocHost(typeAlias); - container = ts.findAncestor(host.parent, function (n) { return !!(getContainerFlags(n) & 1); }) || file; + container = ts.findAncestor(host.parent, function (n) { return !!(getContainerFlags(n) & 1 /* IsContainer */); }) || file; blockScopeContainer = ts.getEnclosingBlockScopeContainer(host) || file; - currentFlow = { flags: 2 }; + currentFlow = { flags: 2 /* Start */ }; parent = typeAlias; bind(typeAlias.typeExpression); - if (!typeAlias.fullName || typeAlias.fullName.kind === 71) { + if (!typeAlias.fullName || typeAlias.fullName.kind === 71 /* Identifier */) { parent = typeAlias.parent; - bindBlockScopedDeclaration(typeAlias, 524288, 67901928); + bindBlockScopedDeclaration(typeAlias, 524288 /* TypeAlias */, 67901928 /* TypeAliasExcludes */); } else { bind(typeAlias.fullName); @@ -23268,18 +27015,23 @@ var ts; parent = saveParent; currentFlow = saveCurrentFlow; } + // The binder visits every node in the syntax tree so it is a convenient place to perform a single localized + // check for reserved words used as identifiers in strict mode code. function checkStrictModeIdentifier(node) { if (inStrictMode && - node.originalKeywordKind >= 108 && - node.originalKeywordKind <= 116 && + node.originalKeywordKind >= 108 /* FirstFutureReservedWord */ && + node.originalKeywordKind <= 116 /* LastFutureReservedWord */ && !ts.isIdentifierName(node) && - !(node.flags & 4194304)) { + !(node.flags & 4194304 /* Ambient */)) { + // Report error only if there are no parse errors in file if (!file.parseDiagnostics.length) { file.bindDiagnostics.push(createDiagnosticForNode(node, getStrictModeIdentifierMessage(node), ts.declarationNameToString(node))); } } } function getStrictModeIdentifierMessage(node) { + // Provide specialized messages to help the user understand why we think they're in + // strict mode. if (ts.getContainingClass(node)) { return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode; } @@ -23290,16 +27042,23 @@ var ts; } function checkStrictModeBinaryExpression(node) { if (inStrictMode && ts.isLeftHandSideExpression(node.left) && ts.isAssignmentOperator(node.operatorToken.kind)) { + // ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an + // Assignment operator(11.13) or of a PostfixExpression(11.3) checkStrictModeEvalOrArguments(node, node.left); } } function checkStrictModeCatchClause(node) { + // It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the + // Catch production is eval or arguments if (inStrictMode && node.variableDeclaration) { checkStrictModeEvalOrArguments(node, node.variableDeclaration.name); } } function checkStrictModeDeleteExpression(node) { - if (inStrictMode && node.expression.kind === 71) { + // Grammar checking + if (inStrictMode && node.expression.kind === 71 /* Identifier */) { + // When a delete operator occurs within strict mode code, a SyntaxError is thrown if its + // UnaryExpression is a direct reference to a variable, function argument, or function name var span = ts.getErrorSpanForNode(file, node.expression); file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode)); } @@ -23308,15 +27067,19 @@ var ts; return ts.isIdentifier(node) && (node.escapedText === "eval" || node.escapedText === "arguments"); } function checkStrictModeEvalOrArguments(contextNode, name) { - if (name && name.kind === 71) { + if (name && name.kind === 71 /* Identifier */) { var identifier = name; if (isEvalOrArgumentsIdentifier(identifier)) { + // We check first if the name is inside class declaration or class expression; if so give explicit message + // otherwise report generic error message. var span = ts.getErrorSpanForNode(file, name); file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, getStrictModeEvalOrArgumentsMessage(contextNode), ts.idText(identifier))); } } } function getStrictModeEvalOrArgumentsMessage(node) { + // Provide specialized messages to help the user understand why we think they're in + // strict mode. if (ts.getContainingClass(node)) { return ts.Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode; } @@ -23327,10 +27090,13 @@ var ts; } function checkStrictModeFunctionName(node) { if (inStrictMode) { + // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a strict mode FunctionDeclaration or FunctionExpression (13.1)) checkStrictModeEvalOrArguments(node, node.name); } } function getStrictModeBlockScopeFunctionDeclarationMessage(node) { + // Provide specialized messages to help the user understand why we think they're in + // strict mode. if (ts.getContainingClass(node)) { return ts.Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Class_definitions_are_automatically_in_strict_mode; } @@ -23340,33 +27106,42 @@ var ts; return ts.Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5; } function checkStrictModeFunctionDeclaration(node) { - if (languageVersion < 2) { - if (blockScopeContainer.kind !== 274 && - blockScopeContainer.kind !== 239 && + if (languageVersion < 2 /* ES2015 */) { + // Report error if function is not top level function declaration + if (blockScopeContainer.kind !== 274 /* SourceFile */ && + blockScopeContainer.kind !== 239 /* ModuleDeclaration */ && !ts.isFunctionLike(blockScopeContainer)) { + // We check first if the name is inside class declaration or class expression; if so give explicit message + // otherwise report generic error message. var errorSpan = ts.getErrorSpanForNode(file, node); file.bindDiagnostics.push(ts.createFileDiagnostic(file, errorSpan.start, errorSpan.length, getStrictModeBlockScopeFunctionDeclarationMessage(node))); } } } function checkStrictModeNumericLiteral(node) { - if (inStrictMode && node.numericLiteralFlags & 32) { + if (inStrictMode && node.numericLiteralFlags & 32 /* Octal */) { file.bindDiagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.Octal_literals_are_not_allowed_in_strict_mode)); } } function checkStrictModePostfixUnaryExpression(node) { + // Grammar checking + // The identifier eval or arguments may not appear as the LeftHandSideExpression of an + // Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression + // operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator. if (inStrictMode) { checkStrictModeEvalOrArguments(node, node.operand); } } function checkStrictModePrefixUnaryExpression(node) { + // Grammar checking if (inStrictMode) { - if (node.operator === 43 || node.operator === 44) { + if (node.operator === 43 /* PlusPlusToken */ || node.operator === 44 /* MinusMinusToken */) { checkStrictModeEvalOrArguments(node, node.operand); } } } function checkStrictModeWithStatement(node) { + // Grammar checking for withStatement if (inStrictMode) { errorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_strict_mode); } @@ -23391,12 +27166,36 @@ var ts; } node.parent = parent; var saveInStrictMode = inStrictMode; + // Even though in the AST the jsdoc @typedef node belongs to the current node, + // its symbol might be in the same scope with the current node's symbol. Consider: + // + // /** @typedef {string | number} MyType */ + // function foo(); + // + // Here the current node is "foo", which is a container, but the scope of "MyType" should + // not be inside "foo". Therefore we always bind @typedef before bind the parent node, + // and skip binding this tag later when binding all the other jsdoc tags. + // First we bind declaration nodes to a symbol if possible. We'll both create a symbol + // and then potentially add the symbol to an appropriate symbol table. Possible + // destination symbol tables are: + // + // 1) The 'exports' table of the current container's symbol. + // 2) The 'members' table of the current container's symbol. + // 3) The 'locals' table of the current container. + // + // 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); - if (node.kind > 145) { + // 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 + // a local should go into for example. Since terminal nodes are known not to have + // children, as an optimization we don't process those. + if (node.kind > 145 /* LastToken */) { var saveParent = parent; parent = node; var containerFlags = getContainerFlags(node); - if (containerFlags === 0) { + if (containerFlags === 0 /* None */) { bindChildren(node); } else { @@ -23404,7 +27203,7 @@ var ts; } parent = saveParent; } - else if (!skipTransformFlagAggregation && (node.transformFlags & 536870912) === 0) { + else if (!skipTransformFlagAggregation && (node.transformFlags & 536870912 /* HasComputedFlags */) === 0) { subtreeTransformFlags |= computeTransformFlagsForNode(node, 0); bindJSDoc(node); } @@ -23440,27 +27239,35 @@ var ts; } } } + /// Should be called only on prologue directives (isPrologueDirective(node) should be true) function isUseStrictPrologueDirective(node) { var nodeText = ts.getSourceTextOfNodeFromSourceFile(file, node.expression); + // Note: the node text must be exactly "use strict" or 'use strict'. It is not ok for the + // string to contain unicode escapes (as per ES5). return nodeText === '"use strict"' || nodeText === "'use strict'"; } function bindWorker(node) { switch (node.kind) { - case 71: + /* Strict mode checks */ + case 71 /* Identifier */: + // for typedef type names with namespaces, bind the new jsdoc type symbol here + // because it requires all containing namespaces to be in effect, namely the + // current "blockScopeContainer" needs to be set to its immediate namespace parent. if (node.isInJSDocNamespace) { var parentNode = node.parent; while (parentNode && !ts.isJSDocTypeAlias(parentNode)) { parentNode = parentNode.parent; } - bindBlockScopedDeclaration(parentNode, 524288, 67901928); + bindBlockScopedDeclaration(parentNode, 524288 /* TypeAlias */, 67901928 /* TypeAliasExcludes */); break; } - case 99: - if (currentFlow && (ts.isExpression(node) || parent.kind === 271)) { + // falls through + case 99 /* ThisKeyword */: + if (currentFlow && (ts.isExpression(node) || parent.kind === 271 /* ShorthandPropertyAssignment */)) { node.flowNode = currentFlow; } return checkStrictModeIdentifier(node); - case 185: + case 185 /* PropertyAccessExpression */: if (currentFlow && isNarrowableReference(node)) { node.flowNode = currentFlow; } @@ -23468,162 +27275,173 @@ var ts; bindSpecialPropertyDeclaration(node); } break; - case 200: + case 200 /* BinaryExpression */: var specialKind = ts.getSpecialPropertyAssignmentKind(node); switch (specialKind) { - case 1: + case 1 /* ExportsProperty */: bindExportsPropertyAssignment(node); break; - case 2: + case 2 /* ModuleExports */: bindModuleExportsAssignment(node); break; - case 3: + case 3 /* PrototypeProperty */: bindPrototypePropertyAssignment(node.left, node); break; - case 6: + case 6 /* Prototype */: bindPrototypeAssignment(node); break; - case 4: + case 4 /* ThisProperty */: bindThisPropertyAssignment(node); break; - case 5: + case 5 /* Property */: bindSpecialPropertyAssignment(node); break; - case 0: + case 0 /* None */: + // Nothing to do break; default: ts.Debug.fail("Unknown special property assignment kind"); } return checkStrictModeBinaryExpression(node); - case 269: + case 269 /* CatchClause */: return checkStrictModeCatchClause(node); - case 194: + case 194 /* DeleteExpression */: return checkStrictModeDeleteExpression(node); - case 8: + case 8 /* NumericLiteral */: return checkStrictModeNumericLiteral(node); - case 199: + case 199 /* PostfixUnaryExpression */: return checkStrictModePostfixUnaryExpression(node); - case 198: + case 198 /* PrefixUnaryExpression */: return checkStrictModePrefixUnaryExpression(node); - case 226: + case 226 /* WithStatement */: return checkStrictModeWithStatement(node); - case 174: + case 174 /* ThisType */: seenThisKeyword = true; return; - case 161: - break; - case 148: + case 161 /* TypePredicate */: + break; // Binding the children will handle everything + case 148 /* TypeParameter */: return bindTypeParameter(node); - case 149: + case 149 /* Parameter */: return bindParameter(node); - case 232: + case 232 /* VariableDeclaration */: return bindVariableDeclarationOrBindingElement(node); - case 182: + case 182 /* BindingElement */: node.flowNode = currentFlow; return bindVariableDeclarationOrBindingElement(node); - case 152: - case 151: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: return bindPropertyWorker(node); - case 270: - case 271: - return bindPropertyOrMethodOrAccessor(node, 4, 0); - case 273: - return bindPropertyOrMethodOrAccessor(node, 8, 68008959); - case 158: - case 159: - case 160: - return declareSymbolAndAddToSymbolTable(node, 131072, 0); - case 154: - case 153: - return bindPropertyOrMethodOrAccessor(node, 8192 | (node.questionToken ? 16777216 : 0), ts.isObjectLiteralMethod(node) ? 0 : 67208127); - case 234: + case 270 /* PropertyAssignment */: + case 271 /* ShorthandPropertyAssignment */: + return bindPropertyOrMethodOrAccessor(node, 4 /* Property */, 0 /* PropertyExcludes */); + case 273 /* EnumMember */: + return bindPropertyOrMethodOrAccessor(node, 8 /* EnumMember */, 68008959 /* EnumMemberExcludes */); + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 160 /* IndexSignature */: + return declareSymbolAndAddToSymbolTable(node, 131072 /* Signature */, 0 /* None */); + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + // If this is an ObjectLiteralExpression method, then it sits in the same space + // as other properties in the object literal. So we use SymbolFlags.PropertyExcludes + // so that it will conflict with any other object literal members with the same + // name. + return bindPropertyOrMethodOrAccessor(node, 8192 /* Method */ | (node.questionToken ? 16777216 /* Optional */ : 0 /* None */), ts.isObjectLiteralMethod(node) ? 0 /* PropertyExcludes */ : 67208127 /* MethodExcludes */); + case 234 /* FunctionDeclaration */: return bindFunctionDeclaration(node); - case 155: - return declareSymbolAndAddToSymbolTable(node, 16384, 0); - case 156: - return bindPropertyOrMethodOrAccessor(node, 32768, 67150783); - case 157: - return bindPropertyOrMethodOrAccessor(node, 65536, 67183551); - case 163: - case 284: - case 288: - case 164: + case 155 /* Constructor */: + return declareSymbolAndAddToSymbolTable(node, 16384 /* Constructor */, /*symbolExcludes:*/ 0 /* None */); + case 156 /* GetAccessor */: + return bindPropertyOrMethodOrAccessor(node, 32768 /* GetAccessor */, 67150783 /* GetAccessorExcludes */); + case 157 /* SetAccessor */: + return bindPropertyOrMethodOrAccessor(node, 65536 /* SetAccessor */, 67183551 /* SetAccessorExcludes */); + case 163 /* FunctionType */: + case 284 /* JSDocFunctionType */: + case 288 /* JSDocSignature */: + case 164 /* ConstructorType */: return bindFunctionOrConstructorType(node); - case 166: - case 287: - case 177: + case 166 /* TypeLiteral */: + case 287 /* JSDocTypeLiteral */: + case 177 /* MappedType */: return bindAnonymousTypeWorker(node); - case 184: + case 184 /* ObjectLiteralExpression */: return bindObjectLiteralExpression(node); - case 192: - case 193: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: return bindFunctionExpression(node); - case 187: + case 187 /* CallExpression */: if (ts.isInJavaScriptFile(node)) { bindCallExpression(node); } break; - case 205: - case 235: + // Members of classes, interfaces, and modules + case 205 /* ClassExpression */: + case 235 /* ClassDeclaration */: + // All classes are automatically in strict mode in ES6. inStrictMode = true; return bindClassLikeDeclaration(node); - case 236: - return bindBlockScopedDeclaration(node, 64, 67901832); - case 237: - return bindBlockScopedDeclaration(node, 524288, 67901928); - case 238: + case 236 /* InterfaceDeclaration */: + return bindBlockScopedDeclaration(node, 64 /* Interface */, 67901832 /* InterfaceExcludes */); + case 237 /* TypeAliasDeclaration */: + return bindBlockScopedDeclaration(node, 524288 /* TypeAlias */, 67901928 /* TypeAliasExcludes */); + case 238 /* EnumDeclaration */: return bindEnumDeclaration(node); - case 239: + case 239 /* ModuleDeclaration */: return bindModuleDeclaration(node); - case 263: + // Jsx-attributes + case 263 /* JsxAttributes */: return bindJsxAttributes(node); - case 262: - return bindJsxAttribute(node, 4, 0); - case 243: - case 246: - case 248: - case 252: - return declareSymbolAndAddToSymbolTable(node, 2097152, 2097152); - case 242: + case 262 /* JsxAttribute */: + return bindJsxAttribute(node, 4 /* Property */, 0 /* PropertyExcludes */); + // Imports and exports + case 243 /* ImportEqualsDeclaration */: + case 246 /* NamespaceImport */: + case 248 /* ImportSpecifier */: + case 252 /* ExportSpecifier */: + return declareSymbolAndAddToSymbolTable(node, 2097152 /* Alias */, 2097152 /* AliasExcludes */); + case 242 /* NamespaceExportDeclaration */: return bindNamespaceExportDeclaration(node); - case 245: + case 245 /* ImportClause */: return bindImportClause(node); - case 250: + case 250 /* ExportDeclaration */: return bindExportDeclaration(node); - case 249: + case 249 /* ExportAssignment */: return bindExportAssignment(node); - case 274: + case 274 /* SourceFile */: updateStrictModeStatementList(node.statements); return bindSourceFileIfExternalModule(); - case 213: + case 213 /* Block */: if (!ts.isFunctionLike(node.parent)) { return; } - case 240: + // falls through + case 240 /* ModuleBlock */: return updateStrictModeStatementList(node.statements); - case 293: - if (node.parent.kind === 288) { + case 293 /* JSDocParameterTag */: + if (node.parent.kind === 288 /* JSDocSignature */) { return bindParameter(node); } - if (node.parent.kind !== 287) { + if (node.parent.kind !== 287 /* JSDocTypeLiteral */) { break; } - case 299: + // falls through + case 299 /* JSDocPropertyTag */: var propTag = node; - var flags = propTag.isBracketed || propTag.typeExpression && propTag.typeExpression.type.kind === 283 ? - 4 | 16777216 : - 4; - return declareSymbolAndAddToSymbolTable(propTag, flags, 0); - case 298: - case 292: + var flags = propTag.isBracketed || propTag.typeExpression && propTag.typeExpression.type.kind === 283 /* JSDocOptionalType */ ? + 4 /* Property */ | 16777216 /* Optional */ : + 4 /* Property */; + return declareSymbolAndAddToSymbolTable(propTag, flags, 0 /* PropertyExcludes */); + case 298 /* JSDocTypedefTag */: + case 292 /* JSDocCallbackTag */: return (delayedTypeAliases || (delayedTypeAliases = [])).push(node); } } function bindPropertyWorker(node) { - return bindPropertyOrMethodOrAccessor(node, 4 | (node.questionToken ? 16777216 : 0), 0); + return bindPropertyOrMethodOrAccessor(node, 4 /* Property */ | (node.questionToken ? 16777216 /* Optional */ : 0 /* None */), 0 /* PropertyExcludes */); } function bindAnonymousTypeWorker(node) { - return bindAnonymousDeclaration(node, 2048, "__type"); + return bindAnonymousDeclaration(node, 2048 /* TypeLiteral */, "__type" /* Type */); } function bindSourceFileIfExternalModule() { setExportContextFlag(file); @@ -23632,30 +27450,36 @@ var ts; } else if (ts.isJsonSourceFile(file)) { bindSourceFileAsExternalModule(); + // Create symbol equivalent for the module.exports = {} var originalSymbol = file.symbol; - declareSymbol(file.symbol.exports, file.symbol, file, 4, 67108863); + declareSymbol(file.symbol.exports, file.symbol, file, 4 /* Property */, 67108863 /* All */); file.symbol = originalSymbol; } } function bindSourceFileAsExternalModule() { - bindAnonymousDeclaration(file, 512, "\"" + ts.removeFileExtension(file.fileName) + "\""); + bindAnonymousDeclaration(file, 512 /* ValueModule */, "\"" + ts.removeFileExtension(file.fileName) + "\""); } function bindExportAssignment(node) { if (!container.symbol || !container.symbol.exports) { - bindAnonymousDeclaration(node, 2097152, getDeclarationName(node)); + // Export assignment in some sort of block construct + bindAnonymousDeclaration(node, 2097152 /* Alias */, getDeclarationName(node)); } else { - var flags = node.kind === 249 && ts.exportAssignmentIsAlias(node) - ? 2097152 - : 4; - declareSymbol(container.symbol.exports, container.symbol, node, flags, 67108863); + var flags = node.kind === 249 /* ExportAssignment */ && ts.exportAssignmentIsAlias(node) + // An export default clause with an EntityNameExpression or a class expression exports all meanings of that identifier or expression; + ? 2097152 /* Alias */ + // An export default clause with any other expression exports a value + : 4 /* Property */; + // If there is an `export default x;` alias declaration, can't `export default` anything else. + // (In contrast, you can still have `export default function f() {}` and `export default interface I {}`.) + declareSymbol(container.symbol.exports, container.symbol, node, flags, 67108863 /* All */); } } function bindNamespaceExportDeclaration(node) { if (node.modifiers && node.modifiers.length) { file.bindDiagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.Modifiers_cannot_appear_here)); } - if (node.parent.kind !== 274) { + if (node.parent.kind !== 274 /* SourceFile */) { file.bindDiagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.Global_module_exports_may_only_appear_at_top_level)); return; } @@ -23671,19 +27495,21 @@ var ts; } } file.symbol.globalExports = file.symbol.globalExports || ts.createSymbolTable(); - declareSymbol(file.symbol.globalExports, file.symbol, node, 2097152, 2097152); + declareSymbol(file.symbol.globalExports, file.symbol, node, 2097152 /* Alias */, 2097152 /* AliasExcludes */); } function bindExportDeclaration(node) { if (!container.symbol || !container.symbol.exports) { - bindAnonymousDeclaration(node, 8388608, getDeclarationName(node)); + // Export * in some sort of block construct + bindAnonymousDeclaration(node, 8388608 /* ExportStar */, getDeclarationName(node)); } else if (!node.exportClause) { - declareSymbol(container.symbol.exports, container.symbol, node, 8388608, 0); + // All export * declarations are collected in an __export symbol + declareSymbol(container.symbol.exports, container.symbol, node, 8388608 /* ExportStar */, 0 /* None */); } } function bindImportClause(node) { if (node.name) { - declareSymbolAndAddToSymbolTable(node, 2097152, 2097152); + declareSymbolAndAddToSymbolTable(node, 2097152 /* Alias */, 2097152 /* AliasExcludes */); } } function setCommonJsModuleIndicator(node) { @@ -23697,24 +27523,30 @@ var ts; return true; } function bindExportsPropertyAssignment(node) { + // When we create a property via 'exports.foo = bar', the 'exports.foo' property access + // expression is the declaration if (!setCommonJsModuleIndicator(node)) { return; } var lhs = node.left; - var symbol = forEachIdentifierInEntityName(lhs.expression, undefined, function (id, symbol) { + var symbol = forEachIdentifierInEntityName(lhs.expression, /*parent*/ undefined, function (id, symbol) { if (symbol) { - addDeclarationToSymbol(symbol, id, 1536 | 67108864); + addDeclarationToSymbol(symbol, id, 1536 /* Module */ | 67108864 /* JSContainer */); } return symbol; }); if (symbol) { var flags = ts.isClassExpression(node.right) ? - 4 | 1048576 | 32 : - 4 | 1048576; - declareSymbol(symbol.exports, symbol, lhs, flags, 0); + 4 /* Property */ | 1048576 /* ExportValue */ | 32 /* Class */ : + 4 /* Property */ | 1048576 /* ExportValue */; + declareSymbol(symbol.exports, symbol, lhs, flags, 0 /* None */); } } function bindModuleExportsAssignment(node) { + // A common practice in node modules is to set 'export = module.exports = {}', this ensures that 'exports' + // is still pointing to 'module.exports'. + // We do not want to consider this as 'export=' since a module can have only one of these. + // Similarly we do not want to treat 'module.exports = exports' as an 'export='. if (!setCommonJsModuleIndicator(node)) { return; } @@ -23722,49 +27554,57 @@ var ts; if (ts.isEmptyObjectLiteral(assignedExpression) || container === file && isExportsOrModuleExportsOrAlias(file, assignedExpression)) { return; } + // 'module.exports = expr' assignment var flags = ts.exportAssignmentIsAlias(node) - ? 2097152 - : 4 | 1048576 | 512; - declareSymbol(file.symbol.exports, file.symbol, node, flags, 0); + ? 2097152 /* Alias */ + : 4 /* Property */ | 1048576 /* ExportValue */ | 512 /* ValueModule */; + declareSymbol(file.symbol.exports, file.symbol, node, flags, 0 /* None */); } function bindThisPropertyAssignment(node) { ts.Debug.assert(ts.isInJavaScriptFile(node)); - var thisContainer = ts.getThisContainer(node, false); + var thisContainer = ts.getThisContainer(node, /*includeArrowFunctions*/ false); switch (thisContainer.kind) { - case 234: - case 192: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: var constructorSymbol = thisContainer.symbol; - if (ts.isBinaryExpression(thisContainer.parent) && thisContainer.parent.operatorToken.kind === 58) { + // For `f.prototype.m = function() { this.x = 0; }`, `this.x = 0` should modify `f`'s members, not the function expression. + if (ts.isBinaryExpression(thisContainer.parent) && thisContainer.parent.operatorToken.kind === 58 /* EqualsToken */) { var l = thisContainer.parent.left; if (ts.isPropertyAccessEntityNameExpression(l) && ts.isPrototypeAccess(l.expression)) { constructorSymbol = lookupSymbolForPropertyAccess(l.expression.expression, thisParentContainer); } } if (constructorSymbol) { + // Declare a 'member' if the container is an ES5 class or ES6 constructor constructorSymbol.members = constructorSymbol.members || ts.createSymbolTable(); - declareSymbol(constructorSymbol.members, constructorSymbol, node, 4, 0 & ~4); + // It's acceptable for multiple 'this' assignments of the same identifier to occur + declareSymbol(constructorSymbol.members, constructorSymbol, node, 4 /* Property */, 0 /* PropertyExcludes */ & ~4 /* Property */); } break; - case 155: - case 152: - case 154: - case 156: - case 157: + case 155 /* Constructor */: + case 152 /* PropertyDeclaration */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + // this.foo assignment in a JavaScript class + // Bind this property to the containing class var containingClass = thisContainer.parent; - var symbolTable = ts.hasModifier(thisContainer, 32) ? containingClass.symbol.exports : containingClass.symbol.members; - declareSymbol(symbolTable, containingClass.symbol, node, 4, 0, true); + var symbolTable = ts.hasModifier(thisContainer, 32 /* Static */) ? containingClass.symbol.exports : containingClass.symbol.members; + declareSymbol(symbolTable, containingClass.symbol, node, 4 /* Property */, 0 /* None */, /*isReplaceableByMethod*/ true); break; - case 274: + case 274 /* SourceFile */: + // this.foo assignment in a source file + // Do not bind. It would be nice to support this someday though. break; default: ts.Debug.fail(ts.Debug.showSyntaxKind(thisContainer)); } } function bindSpecialPropertyDeclaration(node) { - if (node.expression.kind === 99) { + if (node.expression.kind === 99 /* ThisKeyword */) { bindThisPropertyAssignment(node); } - else if (ts.isPropertyAccessEntityNameExpression(node) && node.parent.parent.kind === 274) { + else if (ts.isPropertyAccessEntityNameExpression(node) && node.parent.parent.kind === 274 /* SourceFile */) { if (ts.isPrototypeAccess(node.expression)) { bindPrototypePropertyAssignment(node, node.parent); } @@ -23773,44 +27613,61 @@ var ts; } } } + /** For `x.prototype = { p, ... }`, declare members p,... if `x` is function/class/{}, or not declared. */ function bindPrototypeAssignment(node) { node.left.parent = node; node.right.parent = node; var lhs = node.left; - bindPropertyAssignment(lhs, lhs, false); + bindPropertyAssignment(lhs, lhs, /*isPrototypeProperty*/ false); } + /** + * For `x.prototype.y = z`, declare a member `y` on `x` if `x` is a function or class, or not declared. + * Note that jsdoc preceding an ExpressionStatement like `x.prototype.y;` is also treated as a declaration. + */ function bindPrototypePropertyAssignment(lhs, parent) { + // Look up the function in the local scope, since prototype assignments should + // follow the function declaration var classPrototype = lhs.expression; var constructorFunction = classPrototype.expression; + // Fix up parent pointers since we're going to use these nodes before we bind into them lhs.parent = parent; constructorFunction.parent = classPrototype; classPrototype.parent = lhs; - bindPropertyAssignment(constructorFunction, lhs, true); + bindPropertyAssignment(constructorFunction, lhs, /*isPrototypeProperty*/ true); } function bindSpecialPropertyAssignment(node) { var lhs = node.left; + // Fix up parent pointers since we're going to use these nodes before we bind into them node.left.parent = node; node.right.parent = node; if (ts.isIdentifier(lhs.expression) && container === file && isNameOfExportsOrModuleExportsAliasDeclaration(file, lhs.expression)) { + // This can be an alias for the 'exports' or 'module.exports' names, e.g. + // var util = module.exports; + // util.property = function ... bindExportsPropertyAssignment(node); } else { bindStaticPropertyAssignment(lhs); } } + /** + * For nodes like `x.y = z`, declare a member 'y' on 'x' if x is a function (or IIFE) or class or {}, or not declared. + * Also works for expression statements preceded by JSDoc, like / ** @type number * / x.y; + */ function bindStaticPropertyAssignment(node) { node.expression.parent = node; - bindPropertyAssignment(node.expression, node, false); + bindPropertyAssignment(node.expression, node, /*isPrototypeProperty*/ false); } function bindPropertyAssignment(name, propertyAccess, isPrototypeProperty) { var namespaceSymbol = lookupSymbolForPropertyAccess(name); var isToplevelNamespaceableInitializer = ts.isBinaryExpression(propertyAccess.parent) - ? getParentOfBinaryExpression(propertyAccess.parent).parent.kind === 274 && + ? getParentOfBinaryExpression(propertyAccess.parent).parent.kind === 274 /* SourceFile */ && !!ts.getJavascriptInitializer(ts.getInitializerOfBinaryExpression(propertyAccess.parent), ts.isPrototypeAccess(propertyAccess.parent.left)) - : propertyAccess.parent.parent.kind === 274; - if (!isPrototypeProperty && (!namespaceSymbol || !(namespaceSymbol.flags & 1920)) && isToplevelNamespaceableInitializer) { - var flags_1 = 1536 | 67108864; - var excludeFlags_1 = 67215503 & ~67108864; + : propertyAccess.parent.parent.kind === 274 /* SourceFile */; + if (!isPrototypeProperty && (!namespaceSymbol || !(namespaceSymbol.flags & 1920 /* Namespace */)) && isToplevelNamespaceableInitializer) { + // make symbols or add declarations for intermediate containers + var flags_1 = 1536 /* Module */ | 67108864 /* JSContainer */; + var excludeFlags_1 = 67215503 /* ValueModuleExcludes */ & ~67108864 /* JSContainer */; namespaceSymbol = forEachIdentifierInEntityName(propertyAccess.expression, namespaceSymbol, function (id, symbol, parent) { if (symbol) { addDeclarationToSymbol(symbol, id, flags_1); @@ -23824,17 +27681,29 @@ var ts; if (!namespaceSymbol || !isJavascriptContainer(namespaceSymbol)) { return; } + // Set up the members collection if it doesn't exist already var symbolTable = isPrototypeProperty ? (namespaceSymbol.members || (namespaceSymbol.members = ts.createSymbolTable())) : (namespaceSymbol.exports || (namespaceSymbol.exports = ts.createSymbolTable())); - var jsContainerFlag = isToplevelNamespaceableInitializer ? 67108864 : 0; + // Declare the method/property + var jsContainerFlag = isToplevelNamespaceableInitializer ? 67108864 /* JSContainer */ : 0; var isMethod = ts.isFunctionLikeDeclaration(ts.getAssignedJavascriptInitializer(propertyAccess)); - var symbolFlags = (isMethod ? 8192 : 4) | jsContainerFlag; - var symbolExcludes = (isMethod ? 67208127 : 0) & ~jsContainerFlag; + var symbolFlags = (isMethod ? 8192 /* Method */ : 4 /* Property */) | jsContainerFlag; + var symbolExcludes = (isMethod ? 67208127 /* MethodExcludes */ : 0 /* PropertyExcludes */) & ~jsContainerFlag; declareSymbol(symbolTable, namespaceSymbol, propertyAccess, symbolFlags, symbolExcludes); } + /** + * Javascript containers are: + * - Functions + * - classes + * - namespaces + * - variables initialized with function expressions + * - with class expressions + * - with empty object literals + * - with non-empty object literals if assigned to the prototype property + */ function isJavascriptContainer(symbol) { - if (symbol.flags & (16 | 32 | 1024)) { + if (symbol.flags & (16 /* Function */ | 32 /* Class */ | 1024 /* NamespaceModule */)) { return true; } var node = symbol.valueDeclaration; @@ -23846,7 +27715,7 @@ var ts; init = init && ts.getRightMostAssignedExpression(init); if (init) { var isPrototypeAssignment = ts.isPrototypeAccess(ts.isVariableDeclaration(node) ? node.name : ts.isBinaryExpression(node) ? node.left : node); - return !!ts.getJavascriptInitializer(ts.isBinaryExpression(init) && init.operatorToken.kind === 54 ? init.right : init, isPrototypeAssignment); + return !!ts.getJavascriptInitializer(ts.isBinaryExpression(init) && init.operatorToken.kind === 54 /* BarBarToken */ ? init.right : init, isPrototypeAssignment); } return false; } @@ -23881,23 +27750,35 @@ var ts; } } function bindCallExpression(node) { - if (!file.commonJsModuleIndicator && ts.isRequireCall(node, false)) { + // We're only inspecting call expressions to detect CommonJS modules, so we can skip + // this check if we've already seen the module indicator + if (!file.commonJsModuleIndicator && ts.isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ false)) { setCommonJsModuleIndicator(node); } } function bindClassLikeDeclaration(node) { - if (node.kind === 235) { - bindBlockScopedDeclaration(node, 32, 68008383); + if (node.kind === 235 /* ClassDeclaration */) { + bindBlockScopedDeclaration(node, 32 /* Class */, 68008383 /* ClassExcludes */); } else { - var bindingName = node.name ? node.name.escapedText : "__class"; - bindAnonymousDeclaration(node, 32, bindingName); + var bindingName = node.name ? node.name.escapedText : "__class" /* Class */; + bindAnonymousDeclaration(node, 32 /* Class */, bindingName); + // Add name of class expression into the map for semantic classifier if (node.name) { classifiableNames.set(node.name.escapedText, true); } } var symbol = node.symbol; - var prototypeSymbol = createSymbol(4 | 4194304, "prototype"); + // TypeScript 1.0 spec (April 2014): 8.4 + // Every class automatically contains a static property member named 'prototype', the + // type of which is an instantiation of the class type with type Any supplied as a type + // argument for each type parameter. It is an error to explicitly declare a static + // property member with the name 'prototype'. + // + // Note: we check for this here because this class may be merging into a module. The + // module might have an exported variable called 'prototype'. We can't allow that as + // that would clash with the built-in 'prototype' for the class. + var prototypeSymbol = createSymbol(4 /* Property */ | 4194304 /* Prototype */, "prototype"); var symbolExport = symbol.exports.get(prototypeSymbol.escapedName); if (symbolExport) { if (node.name) { @@ -23910,8 +27791,8 @@ var ts; } function bindEnumDeclaration(node) { return ts.isConst(node) - ? bindBlockScopedDeclaration(node, 128, 68008831) - : bindBlockScopedDeclaration(node, 256, 68008191); + ? bindBlockScopedDeclaration(node, 128 /* ConstEnum */, 68008831 /* ConstEnumExcludes */) + : bindBlockScopedDeclaration(node, 256 /* RegularEnum */, 68008191 /* RegularEnumExcludes */); } function bindVariableDeclarationOrBindingElement(node) { if (inStrictMode) { @@ -23922,68 +27803,81 @@ var ts; bindBlockScopedVariableDeclaration(node); } else if (ts.isParameterDeclaration(node)) { - declareSymbolAndAddToSymbolTable(node, 1, 67216319); + // It is safe to walk up parent chain to find whether the node is a destructuring parameter declaration + // because its parent chain has already been set up, since parents are set before descending into children. + // + // If node is a binding element in parameter declaration, we need to use ParameterExcludes. + // Using ParameterExcludes flag allows the compiler to report an error on duplicate identifiers in Parameter Declaration + // For example: + // function foo([a,a]) {} // Duplicate Identifier error + // function bar(a,a) {} // Duplicate Identifier error, parameter declaration in this case is handled in bindParameter + // // which correctly set excluded symbols + declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 67216319 /* ParameterExcludes */); } else { - declareSymbolAndAddToSymbolTable(node, 1, 67216318); + declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 67216318 /* FunctionScopedVariableExcludes */); } } } function bindParameter(node) { - if (node.kind === 293 && container.kind !== 288) { + if (node.kind === 293 /* JSDocParameterTag */ && container.kind !== 288 /* JSDocSignature */) { return; } - if (inStrictMode && !(node.flags & 4194304)) { + if (inStrictMode && !(node.flags & 4194304 /* Ambient */)) { + // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a + // strict mode FunctionLikeDeclaration or FunctionExpression(13.1) checkStrictModeEvalOrArguments(node, node.name); } if (ts.isBindingPattern(node.name)) { - bindAnonymousDeclaration(node, 1, "__" + node.parent.parameters.indexOf(node)); + bindAnonymousDeclaration(node, 1 /* FunctionScopedVariable */, "__" + node.parent.parameters.indexOf(node)); } else { - declareSymbolAndAddToSymbolTable(node, 1, 67216319); + declareSymbolAndAddToSymbolTable(node, 1 /* FunctionScopedVariable */, 67216319 /* ParameterExcludes */); } + // If this is a property-parameter, then also declare the property symbol into the + // containing class. if (ts.isParameterPropertyDeclaration(node)) { var classDeclaration = node.parent.parent; - declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, 4 | (node.questionToken ? 16777216 : 0), 0); + declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, 4 /* Property */ | (node.questionToken ? 16777216 /* Optional */ : 0 /* None */), 0 /* PropertyExcludes */); } } function bindFunctionDeclaration(node) { - if (!file.isDeclarationFile && !(node.flags & 4194304)) { + if (!file.isDeclarationFile && !(node.flags & 4194304 /* Ambient */)) { if (ts.isAsyncFunction(node)) { - emitFlags |= 1024; + emitFlags |= 1024 /* HasAsyncFunctions */; } } checkStrictModeFunctionName(node); if (inStrictMode) { checkStrictModeFunctionDeclaration(node); - bindBlockScopedDeclaration(node, 16, 67215791); + bindBlockScopedDeclaration(node, 16 /* Function */, 67215791 /* FunctionExcludes */); } else { - declareSymbolAndAddToSymbolTable(node, 16, 67215791); + declareSymbolAndAddToSymbolTable(node, 16 /* Function */, 67215791 /* FunctionExcludes */); } } function bindFunctionExpression(node) { - if (!file.isDeclarationFile && !(node.flags & 4194304)) { + if (!file.isDeclarationFile && !(node.flags & 4194304 /* Ambient */)) { if (ts.isAsyncFunction(node)) { - emitFlags |= 1024; + emitFlags |= 1024 /* HasAsyncFunctions */; } } if (currentFlow) { node.flowNode = currentFlow; } checkStrictModeFunctionName(node); - var bindingName = node.name ? node.name.escapedText : "__function"; - return bindAnonymousDeclaration(node, 16, bindingName); + var bindingName = node.name ? node.name.escapedText : "__function" /* Function */; + return bindAnonymousDeclaration(node, 16 /* Function */, bindingName); } function bindPropertyOrMethodOrAccessor(node, symbolFlags, symbolExcludes) { - if (!file.isDeclarationFile && !(node.flags & 4194304) && ts.isAsyncFunction(node)) { - emitFlags |= 1024; + if (!file.isDeclarationFile && !(node.flags & 4194304 /* Ambient */) && ts.isAsyncFunction(node)) { + emitFlags |= 1024 /* HasAsyncFunctions */; } if (currentFlow && ts.isObjectLiteralOrClassExpressionMethod(node)) { node.flowNode = currentFlow; } return ts.hasDynamicName(node) - ? bindAnonymousDeclaration(node, symbolFlags, "__computed") + ? bindAnonymousDeclaration(node, symbolFlags, "__computed" /* Computed */) : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); } function getInferTypeContainer(node) { @@ -23992,53 +27886,68 @@ var ts; } function bindTypeParameter(node) { if (ts.isJSDocTemplateTag(node.parent)) { - var container_1 = ts.find(node.parent.parent.tags, ts.isJSDocTypeAlias) || ts.getHostSignatureFromJSDoc(node.parent); + var container_1 = ts.find(node.parent.parent.tags, ts.isJSDocTypeAlias) || ts.getHostSignatureFromJSDoc(node.parent); // TODO: GH#18217 if (container_1) { if (!container_1.locals) { container_1.locals = ts.createSymbolTable(); } - declareSymbol(container_1.locals, undefined, node, 262144, 67639784); + declareSymbol(container_1.locals, /*parent*/ undefined, node, 262144 /* TypeParameter */, 67639784 /* TypeParameterExcludes */); } else { - declareSymbolAndAddToSymbolTable(node, 262144, 67639784); + declareSymbolAndAddToSymbolTable(node, 262144 /* TypeParameter */, 67639784 /* TypeParameterExcludes */); } } - else if (node.parent.kind === 172) { + else if (node.parent.kind === 172 /* InferType */) { var container_2 = getInferTypeContainer(node.parent); if (container_2) { if (!container_2.locals) { container_2.locals = ts.createSymbolTable(); } - declareSymbol(container_2.locals, undefined, node, 262144, 67639784); + declareSymbol(container_2.locals, /*parent*/ undefined, node, 262144 /* TypeParameter */, 67639784 /* TypeParameterExcludes */); } else { - bindAnonymousDeclaration(node, 262144, getDeclarationName(node)); + bindAnonymousDeclaration(node, 262144 /* TypeParameter */, getDeclarationName(node)); // TODO: GH#18217 } } else { - declareSymbolAndAddToSymbolTable(node, 262144, 67639784); + declareSymbolAndAddToSymbolTable(node, 262144 /* TypeParameter */, 67639784 /* TypeParameterExcludes */); } } + // reachability checks function shouldReportErrorOnModuleDeclaration(node) { var instanceState = getModuleInstanceState(node); - return instanceState === 1 || (instanceState === 2 && !!options.preserveConstEnums); + return instanceState === 1 /* Instantiated */ || (instanceState === 2 /* ConstEnumOnly */ && !!options.preserveConstEnums); } function checkUnreachable(node) { - if (!(currentFlow.flags & 1)) { + if (!(currentFlow.flags & 1 /* Unreachable */)) { return false; } if (currentFlow === unreachableFlow) { - var reportError = (ts.isStatementButNotDeclaration(node) && node.kind !== 215) || - node.kind === 235 || - (node.kind === 239 && shouldReportErrorOnModuleDeclaration(node)) || - (node.kind === 238 && (!ts.isConstEnumDeclaration(node) || options.preserveConstEnums)); + var reportError = + // report error on all statements except empty ones + (ts.isStatementButNotDeclaration(node) && node.kind !== 215 /* EmptyStatement */) || + // report error on class declarations + node.kind === 235 /* ClassDeclaration */ || + // report error on instantiated modules or const-enums only modules if preserveConstEnums is set + (node.kind === 239 /* ModuleDeclaration */ && shouldReportErrorOnModuleDeclaration(node)) || + // report error on regular enums and const enums if preserveConstEnums is set + (node.kind === 238 /* EnumDeclaration */ && (!ts.isConstEnumDeclaration(node) || options.preserveConstEnums)); if (reportError) { currentFlow = reportedUnreachableFlow; if (!options.allowUnreachableCode) { + // unreachable code is reported if + // - user has explicitly asked about it AND + // - statement is in not ambient context (statements in ambient context is already an error + // so we should not report extras) AND + // - node is not variable statement OR + // - node is block scoped variable statement OR + // - node is not block scoped variable statement and at least one variable declaration has initializer + // Rationale: we don't want to report errors on non-initialized var's since they are hoisted + // On the other side we do want to report errors on non-initialized 'lets' because of TDZ var isError = ts.unreachableCodeIsError(options) && - !(node.flags & 4194304) && + !(node.flags & 4194304 /* Ambient */) && (!ts.isVariableStatement(node) || - !!(ts.getCombinedNodeFlags(node.declarationList) & 3) || + !!(ts.getCombinedNodeFlags(node.declarationList) & 3 /* BlockScoped */) || node.declarationList.declarations.some(function (d) { return !!d.initializer; })); errorOrSuggestionOnFirstToken(isError, node, ts.Diagnostics.Unreachable_code_detected); } @@ -24047,6 +27956,7 @@ var ts; return true; } } + /* @internal */ function isExportsOrModuleExportsOrAlias(sourceFile, node) { return ts.isExportsIdentifier(node) || ts.isModuleExportsPropertyAccessExpression(node) || @@ -24060,7 +27970,7 @@ var ts; } function isExportsOrModuleExportsOrAliasOrAssignment(sourceFile, node) { return isExportsOrModuleExportsOrAlias(sourceFile, node) || - (ts.isAssignmentExpression(node, true) && (isExportsOrModuleExportsOrAliasOrAssignment(sourceFile, node.left) || isExportsOrModuleExportsOrAliasOrAssignment(sourceFile, node.right))); + (ts.isAssignmentExpression(node, /*excludeCompoundAssignment*/ true) && (isExportsOrModuleExportsOrAliasOrAssignment(sourceFile, node.left) || isExportsOrModuleExportsOrAliasOrAssignment(sourceFile, node.right))); } function lookupSymbolForNameWorker(container, name) { var local = container.locals && container.locals.get(name); @@ -24069,61 +27979,67 @@ var ts; } return container.symbol && container.symbol.exports && container.symbol.exports.get(name); } + /** + * 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 + */ function computeTransformFlagsForNode(node, subtreeFlags) { var kind = node.kind; switch (kind) { - case 187: + case 187 /* CallExpression */: return computeCallExpression(node, subtreeFlags); - case 188: + case 188 /* NewExpression */: return computeNewExpression(node, subtreeFlags); - case 239: + case 239 /* ModuleDeclaration */: return computeModuleDeclaration(node, subtreeFlags); - case 191: + case 191 /* ParenthesizedExpression */: return computeParenthesizedExpression(node, subtreeFlags); - case 200: + case 200 /* BinaryExpression */: return computeBinaryExpression(node, subtreeFlags); - case 216: + case 216 /* ExpressionStatement */: return computeExpressionStatement(node, subtreeFlags); - case 149: + case 149 /* Parameter */: return computeParameter(node, subtreeFlags); - case 193: + case 193 /* ArrowFunction */: return computeArrowFunction(node, subtreeFlags); - case 192: + case 192 /* FunctionExpression */: return computeFunctionExpression(node, subtreeFlags); - case 234: + case 234 /* FunctionDeclaration */: return computeFunctionDeclaration(node, subtreeFlags); - case 232: + case 232 /* VariableDeclaration */: return computeVariableDeclaration(node, subtreeFlags); - case 233: + case 233 /* VariableDeclarationList */: return computeVariableDeclarationList(node, subtreeFlags); - case 214: + case 214 /* VariableStatement */: return computeVariableStatement(node, subtreeFlags); - case 228: + case 228 /* LabeledStatement */: return computeLabeledStatement(node, subtreeFlags); - case 235: + case 235 /* ClassDeclaration */: return computeClassDeclaration(node, subtreeFlags); - case 205: + case 205 /* ClassExpression */: return computeClassExpression(node, subtreeFlags); - case 268: + case 268 /* HeritageClause */: return computeHeritageClause(node, subtreeFlags); - case 269: + case 269 /* CatchClause */: return computeCatchClause(node, subtreeFlags); - case 207: + case 207 /* ExpressionWithTypeArguments */: return computeExpressionWithTypeArguments(node, subtreeFlags); - case 155: + case 155 /* Constructor */: return computeConstructor(node, subtreeFlags); - case 152: + case 152 /* PropertyDeclaration */: return computePropertyDeclaration(node, subtreeFlags); - case 154: + case 154 /* MethodDeclaration */: return computeMethod(node, subtreeFlags); - case 156: - case 157: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return computeAccessor(node, subtreeFlags); - case 243: + case 243 /* ImportEqualsDeclaration */: return computeImportEquals(node, subtreeFlags); - case 185: + case 185 /* PropertyAccessExpression */: return computePropertyAccess(node, subtreeFlags); - case 186: + case 186 /* ElementAccessExpression */: return computeElementAccess(node, subtreeFlags); default: return computeOther(node, kind, subtreeFlags); @@ -24134,645 +28050,790 @@ var ts; var transformFlags = subtreeFlags; var expression = node.expression; if (node.typeArguments) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (subtreeFlags & 524288 - || (expression.transformFlags & (134217728 | 268435456))) { - transformFlags |= 192; - if (expression.transformFlags & 268435456) { - transformFlags |= 16384; + if (subtreeFlags & 524288 /* ContainsSpread */ + || (expression.transformFlags & (134217728 /* Super */ | 268435456 /* ContainsSuper */))) { + // If the this node contains a SpreadExpression, or is a super call, then it is an ES6 + // node. + transformFlags |= 192 /* AssertES2015 */; + // super property or element accesses could be inside lambdas, etc, and need a captured `this`, + // while super keyword for super calls (indicated by TransformFlags.Super) does not (since it can only be top-level in a constructor) + if (expression.transformFlags & 268435456 /* ContainsSuper */) { + transformFlags |= 16384 /* ContainsLexicalThis */; } } - if (expression.kind === 91) { - transformFlags |= 67108864; - if (subtreeFlags & 16384) { - transformFlags |= 32768; + if (expression.kind === 91 /* ImportKeyword */) { + transformFlags |= 67108864 /* ContainsDynamicImport */; + // A dynamic 'import()' call that contains a lexical 'this' will + // require a captured 'this' when emitting down-level. + if (subtreeFlags & 16384 /* ContainsLexicalThis */) { + transformFlags |= 32768 /* ContainsCapturedLexicalThis */; } } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~940049729; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~940049729 /* ArrayLiteralOrCallOrNewExcludes */; } function computeNewExpression(node, subtreeFlags) { var transformFlags = subtreeFlags; if (node.typeArguments) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (subtreeFlags & 524288) { - transformFlags |= 192; + if (subtreeFlags & 524288 /* ContainsSpread */) { + // If the this node contains a SpreadElementExpression then it is an ES6 + // node. + transformFlags |= 192 /* AssertES2015 */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~940049729; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~940049729 /* ArrayLiteralOrCallOrNewExcludes */; } function computeBinaryExpression(node, subtreeFlags) { var transformFlags = subtreeFlags; var operatorTokenKind = node.operatorToken.kind; var leftKind = node.left.kind; - if (operatorTokenKind === 58 && leftKind === 184) { - transformFlags |= 8 | 192 | 3072; + if (operatorTokenKind === 58 /* EqualsToken */ && leftKind === 184 /* ObjectLiteralExpression */) { + // Destructuring object assignments with are ES2015 syntax + // and possibly ESNext if they contain rest + transformFlags |= 8 /* AssertESNext */ | 192 /* AssertES2015 */ | 3072 /* AssertDestructuringAssignment */; } - else if (operatorTokenKind === 58 && leftKind === 183) { - transformFlags |= 192 | 3072; + else if (operatorTokenKind === 58 /* EqualsToken */ && leftKind === 183 /* ArrayLiteralExpression */) { + // Destructuring assignments are ES2015 syntax. + transformFlags |= 192 /* AssertES2015 */ | 3072 /* AssertDestructuringAssignment */; } - else if (operatorTokenKind === 40 - || operatorTokenKind === 62) { - transformFlags |= 32; + else if (operatorTokenKind === 40 /* AsteriskAsteriskToken */ + || operatorTokenKind === 62 /* AsteriskAsteriskEqualsToken */) { + // Exponentiation is ES2016 syntax. + transformFlags |= 32 /* AssertES2016 */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~939525441; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~939525441 /* NodeExcludes */; } function computeParameter(node, subtreeFlags) { var transformFlags = subtreeFlags; var name = node.name; var initializer = node.initializer; var dotDotDotToken = node.dotDotDotToken; + // The '?' token, type annotations, decorators, and 'this' parameters are TypeSCript + // syntax. if (node.questionToken || node.type - || subtreeFlags & 4096 + || subtreeFlags & 4096 /* ContainsDecorators */ || ts.isThisIdentifier(name)) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (ts.hasModifier(node, 92)) { - transformFlags |= 3 | 262144; + // If a parameter has an accessibility modifier, then it is TypeScript syntax. + if (ts.hasModifier(node, 92 /* ParameterPropertyModifier */)) { + transformFlags |= 3 /* AssertTypeScript */ | 262144 /* ContainsParameterPropertyAssignments */; } - if (subtreeFlags & 1048576) { - transformFlags |= 8; + // parameters with object rest destructuring are ES Next syntax + if (subtreeFlags & 1048576 /* ContainsObjectRest */) { + transformFlags |= 8 /* AssertESNext */; } - if (subtreeFlags & 8388608 || initializer || dotDotDotToken) { - transformFlags |= 192 | 131072; + // If a parameter has an initializer, a binding pattern or a dotDotDot token, then + // it is ES6 syntax and its container must emit default value assignments or parameter destructuring downlevel. + if (subtreeFlags & 8388608 /* ContainsBindingPattern */ || initializer || dotDotDotToken) { + transformFlags |= 192 /* AssertES2015 */ | 131072 /* ContainsDefaultValueAssignments */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~939525441; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~939525441 /* ParameterExcludes */; } function computeParenthesizedExpression(node, subtreeFlags) { var transformFlags = subtreeFlags; var expression = node.expression; var expressionKind = expression.kind; var expressionTransformFlags = expression.transformFlags; - if (expressionKind === 208 - || expressionKind === 190) { - transformFlags |= 3; + // If the node is synthesized, it means the emitter put the parentheses there, + // not the user. If we didn't want them, the emitter would not have put them + // there. + if (expressionKind === 208 /* AsExpression */ + || expressionKind === 190 /* TypeAssertionExpression */) { + transformFlags |= 3 /* AssertTypeScript */; } - if (expressionTransformFlags & 1024) { - transformFlags |= 1024; + // If the expression of a ParenthesizedExpression is a destructuring assignment, + // then the ParenthesizedExpression is a destructuring assignment. + if (expressionTransformFlags & 1024 /* DestructuringAssignment */) { + transformFlags |= 1024 /* DestructuringAssignment */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~536872257; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~536872257 /* OuterExpressionExcludes */; } function computeClassDeclaration(node, subtreeFlags) { var transformFlags; - if (ts.hasModifier(node, 2)) { - transformFlags = 3; + if (ts.hasModifier(node, 2 /* Ambient */)) { + // An ambient declaration is TypeScript syntax. + transformFlags = 3 /* AssertTypeScript */; } else { - transformFlags = subtreeFlags | 192; - if ((subtreeFlags & 274432) + // A ClassDeclaration is ES6 syntax. + transformFlags = subtreeFlags | 192 /* AssertES2015 */; + // A class with a parameter property assignment, property initializer, computed property name, or decorator is + // TypeScript syntax. + // An exported declaration may be TypeScript syntax, but is handled by the visitor + // for a namespace declaration. + if ((subtreeFlags & 274432 /* TypeScriptClassSyntaxMask */) || node.typeParameters) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (subtreeFlags & 65536) { - transformFlags |= 16384; + if (subtreeFlags & 65536 /* ContainsLexicalThisInComputedPropertyName */) { + // A computed property name containing `this` might need to be rewritten, + // so propagate the ContainsLexicalThis flag upward. + transformFlags |= 16384 /* ContainsLexicalThis */; } } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~942011713; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~942011713 /* ClassExcludes */; } function computeClassExpression(node, subtreeFlags) { - var transformFlags = subtreeFlags | 192; - if (subtreeFlags & 274432 + // A ClassExpression is ES6 syntax. + var transformFlags = subtreeFlags | 192 /* AssertES2015 */; + // A class with a parameter property assignment, property initializer, or decorator is + // TypeScript syntax. + if (subtreeFlags & 274432 /* TypeScriptClassSyntaxMask */ || node.typeParameters) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (subtreeFlags & 65536) { - transformFlags |= 16384; + if (subtreeFlags & 65536 /* ContainsLexicalThisInComputedPropertyName */) { + // A computed property name containing `this` might need to be rewritten, + // so propagate the ContainsLexicalThis flag upward. + transformFlags |= 16384 /* ContainsLexicalThis */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~942011713; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~942011713 /* ClassExcludes */; } function computeHeritageClause(node, subtreeFlags) { var transformFlags = subtreeFlags; switch (node.token) { - case 85: - transformFlags |= 192; + case 85 /* ExtendsKeyword */: + // An `extends` HeritageClause is ES6 syntax. + transformFlags |= 192 /* AssertES2015 */; break; - case 108: - transformFlags |= 3; + case 108 /* ImplementsKeyword */: + // An `implements` HeritageClause is TypeScript syntax. + transformFlags |= 3 /* AssertTypeScript */; break; default: ts.Debug.fail("Unexpected token for heritage clause"); break; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~939525441; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~939525441 /* NodeExcludes */; } function computeCatchClause(node, subtreeFlags) { var transformFlags = subtreeFlags; if (!node.variableDeclaration) { - transformFlags |= 8; + transformFlags |= 8 /* AssertESNext */; } else if (ts.isBindingPattern(node.variableDeclaration.name)) { - transformFlags |= 192; + transformFlags |= 192 /* AssertES2015 */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~940574017; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~940574017 /* CatchClauseExcludes */; } function computeExpressionWithTypeArguments(node, subtreeFlags) { - var transformFlags = subtreeFlags | 192; + // An ExpressionWithTypeArguments is ES6 syntax, as it is used in the + // extends clause of a class. + var transformFlags = subtreeFlags | 192 /* AssertES2015 */; + // If an ExpressionWithTypeArguments contains type arguments, then it + // is TypeScript syntax. if (node.typeArguments) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~939525441; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~939525441 /* NodeExcludes */; } function computeConstructor(node, subtreeFlags) { var transformFlags = subtreeFlags; - if (ts.hasModifier(node, 2270) + // TypeScript-specific modifiers and overloads are TypeScript syntax + if (ts.hasModifier(node, 2270 /* TypeScriptModifier */) || !node.body) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (subtreeFlags & 1048576) { - transformFlags |= 8; + // function declarations with object rest destructuring are ES Next syntax + if (subtreeFlags & 1048576 /* ContainsObjectRest */) { + transformFlags |= 8 /* AssertESNext */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~1003668801; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~1003668801 /* ConstructorExcludes */; } function computeMethod(node, subtreeFlags) { - var transformFlags = subtreeFlags | 192; + // A MethodDeclaration is ES6 syntax. + var transformFlags = subtreeFlags | 192 /* AssertES2015 */; + // Decorators, TypeScript-specific modifiers, type parameters, type annotations, and + // overloads are TypeScript syntax. if (node.decorators - || ts.hasModifier(node, 2270) + || ts.hasModifier(node, 2270 /* TypeScriptModifier */) || node.typeParameters || node.type - || (node.name && ts.isComputedPropertyName(node.name)) + || (node.name && ts.isComputedPropertyName(node.name)) // While computed method names aren't typescript, the TS transform must visit them to emit property declarations correctly || !node.body) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (subtreeFlags & 1048576) { - transformFlags |= 8; + // function declarations with object rest destructuring are ES Next syntax + if (subtreeFlags & 1048576 /* ContainsObjectRest */) { + transformFlags |= 8 /* AssertESNext */; } - if (ts.hasModifier(node, 256)) { - transformFlags |= node.asteriskToken ? 8 : 16; + // An async method declaration is ES2017 syntax. + if (ts.hasModifier(node, 256 /* Async */)) { + transformFlags |= node.asteriskToken ? 8 /* AssertESNext */ : 16 /* AssertES2017 */; } if (node.asteriskToken) { - transformFlags |= 768; + transformFlags |= 768 /* AssertGenerator */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~1003668801; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~1003668801 /* MethodOrAccessorExcludes */; } function computeAccessor(node, subtreeFlags) { var transformFlags = subtreeFlags; + // Decorators, TypeScript-specific modifiers, type annotations, and overloads are + // TypeScript syntax. if (node.decorators - || ts.hasModifier(node, 2270) + || ts.hasModifier(node, 2270 /* TypeScriptModifier */) || node.type - || (node.name && ts.isComputedPropertyName(node.name)) + || (node.name && ts.isComputedPropertyName(node.name)) // While computed accessor names aren't typescript, the TS transform must visit them to emit property declarations correctly || !node.body) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (subtreeFlags & 1048576) { - transformFlags |= 8; + // function declarations with object rest destructuring are ES Next syntax + if (subtreeFlags & 1048576 /* ContainsObjectRest */) { + transformFlags |= 8 /* AssertESNext */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~1003668801; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~1003668801 /* MethodOrAccessorExcludes */; } function computePropertyDeclaration(node, subtreeFlags) { - var transformFlags = subtreeFlags | 3; + // A PropertyDeclaration is TypeScript syntax. + var transformFlags = subtreeFlags | 3 /* AssertTypeScript */; + // If the PropertyDeclaration has an initializer or a computed name, we need to inform its ancestor + // so that it handle the transformation. if (node.initializer || ts.isComputedPropertyName(node.name)) { - transformFlags |= 8192; + transformFlags |= 8192 /* ContainsPropertyInitializer */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~939525441; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~939525441 /* NodeExcludes */; } function computeFunctionDeclaration(node, subtreeFlags) { var transformFlags; var modifierFlags = ts.getModifierFlags(node); var body = node.body; - if (!body || (modifierFlags & 2)) { - transformFlags = 3; + if (!body || (modifierFlags & 2 /* Ambient */)) { + // An ambient declaration is TypeScript syntax. + // A FunctionDeclaration without a body is an overload and is TypeScript syntax. + transformFlags = 3 /* AssertTypeScript */; } else { - transformFlags = subtreeFlags | 33554432; - if (modifierFlags & 2270 + transformFlags = subtreeFlags | 33554432 /* ContainsHoistedDeclarationOrCompletion */; + // TypeScript-specific modifiers, type parameters, and type annotations are TypeScript + // syntax. + if (modifierFlags & 2270 /* TypeScriptModifier */ || node.typeParameters || node.type) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (modifierFlags & 256) { - transformFlags |= node.asteriskToken ? 8 : 16; + // An async function declaration is ES2017 syntax. + if (modifierFlags & 256 /* Async */) { + transformFlags |= node.asteriskToken ? 8 /* AssertESNext */ : 16 /* AssertES2017 */; } - if (subtreeFlags & 1048576) { - transformFlags |= 8; + // function declarations with object rest destructuring are ES Next syntax + if (subtreeFlags & 1048576 /* ContainsObjectRest */) { + transformFlags |= 8 /* AssertESNext */; } - if (subtreeFlags & 163840) { - transformFlags |= 192; + // If a FunctionDeclaration's subtree has marked the container as needing to capture the + // lexical this, or the function contains parameters with initializers, then this node is + // ES6 syntax. + if (subtreeFlags & 163840 /* ES2015FunctionSyntaxMask */) { + transformFlags |= 192 /* AssertES2015 */; } + // If a FunctionDeclaration is generator function and is the body of a + // transformed async function, then this node can be transformed to a + // down-level generator. + // Currently we do not support transforming any other generator fucntions + // down level. if (node.asteriskToken) { - transformFlags |= 768; + transformFlags |= 768 /* AssertGenerator */; } } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~1003935041; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~1003935041 /* FunctionExcludes */; } function computeFunctionExpression(node, subtreeFlags) { var transformFlags = subtreeFlags; - if (ts.hasModifier(node, 2270) + // TypeScript-specific modifiers, type parameters, and type annotations are TypeScript + // syntax. + if (ts.hasModifier(node, 2270 /* TypeScriptModifier */) || node.typeParameters || node.type) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (ts.hasModifier(node, 256)) { - transformFlags |= node.asteriskToken ? 8 : 16; + // An async function expression is ES2017 syntax. + if (ts.hasModifier(node, 256 /* Async */)) { + transformFlags |= node.asteriskToken ? 8 /* AssertESNext */ : 16 /* AssertES2017 */; } - if (subtreeFlags & 1048576) { - transformFlags |= 8; + // function expressions with object rest destructuring are ES Next syntax + if (subtreeFlags & 1048576 /* ContainsObjectRest */) { + transformFlags |= 8 /* AssertESNext */; } - if (subtreeFlags & 163840) { - transformFlags |= 192; + // If a FunctionExpression's subtree has marked the container as needing to capture the + // lexical this, or the function contains parameters with initializers, then this node is + // ES6 syntax. + if (subtreeFlags & 163840 /* ES2015FunctionSyntaxMask */) { + transformFlags |= 192 /* AssertES2015 */; } + // If a FunctionExpression is generator function and is the body of a + // transformed async function, then this node can be transformed to a + // down-level generator. if (node.asteriskToken) { - transformFlags |= 768; + transformFlags |= 768 /* AssertGenerator */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~1003935041; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~1003935041 /* FunctionExcludes */; } function computeArrowFunction(node, subtreeFlags) { - var transformFlags = subtreeFlags | 192; - if (ts.hasModifier(node, 2270) + // An ArrowFunction is ES6 syntax, and excludes markers that should not escape the scope of an ArrowFunction. + var transformFlags = subtreeFlags | 192 /* AssertES2015 */; + // TypeScript-specific modifiers, type parameters, and type annotations are TypeScript + // syntax. + if (ts.hasModifier(node, 2270 /* TypeScriptModifier */) || node.typeParameters || node.type) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - if (ts.hasModifier(node, 256)) { - transformFlags |= 16; + // An async arrow function is ES2017 syntax. + if (ts.hasModifier(node, 256 /* Async */)) { + transformFlags |= 16 /* AssertES2017 */; } - if (subtreeFlags & 1048576) { - transformFlags |= 8; + // arrow functions with object rest destructuring are ES Next syntax + if (subtreeFlags & 1048576 /* ContainsObjectRest */) { + transformFlags |= 8 /* AssertESNext */; } - if (subtreeFlags & 16384) { - transformFlags |= 32768; + // If an ArrowFunction contains a lexical this, its container must capture the lexical this. + if (subtreeFlags & 16384 /* ContainsLexicalThis */) { + transformFlags |= 32768 /* ContainsCapturedLexicalThis */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~1003902273; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~1003902273 /* ArrowFunctionExcludes */; } function computePropertyAccess(node, subtreeFlags) { var transformFlags = subtreeFlags; - if (transformFlags & 134217728) { - transformFlags ^= 134217728; - transformFlags |= 268435456; + // If a PropertyAccessExpression starts with a super keyword, then it is + // ES6 syntax, and requires a lexical `this` binding. + if (transformFlags & 134217728 /* Super */) { + transformFlags ^= 134217728 /* Super */; + transformFlags |= 268435456 /* ContainsSuper */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~671089985; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~671089985 /* PropertyAccessExcludes */; } function computeElementAccess(node, subtreeFlags) { var transformFlags = subtreeFlags; var expression = node.expression; - var expressionFlags = expression.transformFlags; - if (expressionFlags & 134217728) { - transformFlags &= ~134217728; - transformFlags |= 268435456; + var expressionFlags = expression.transformFlags; // We do not want to aggregate flags from the argument expression for super/this capturing + // If an ElementAccessExpression starts with a super keyword, then it is + // ES6 syntax, and requires a lexical `this` binding. + if (expressionFlags & 134217728 /* Super */) { + transformFlags &= ~134217728 /* Super */; + transformFlags |= 268435456 /* ContainsSuper */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~671089985; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~671089985 /* PropertyAccessExcludes */; } function computeVariableDeclaration(node, subtreeFlags) { var transformFlags = subtreeFlags; - transformFlags |= 192 | 8388608; - if (subtreeFlags & 1048576) { - transformFlags |= 8; + transformFlags |= 192 /* AssertES2015 */ | 8388608 /* ContainsBindingPattern */; + // A VariableDeclaration containing ObjectRest is ESNext syntax + if (subtreeFlags & 1048576 /* ContainsObjectRest */) { + transformFlags |= 8 /* AssertESNext */; } + // Type annotations are TypeScript syntax. if (node.type) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~939525441; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~939525441 /* NodeExcludes */; } function computeVariableStatement(node, subtreeFlags) { var transformFlags; var declarationListTransformFlags = node.declarationList.transformFlags; - if (ts.hasModifier(node, 2)) { - transformFlags = 3; + // An ambient declaration is TypeScript syntax. + if (ts.hasModifier(node, 2 /* Ambient */)) { + transformFlags = 3 /* AssertTypeScript */; } else { transformFlags = subtreeFlags; - if (declarationListTransformFlags & 8388608) { - transformFlags |= 192; + if (declarationListTransformFlags & 8388608 /* ContainsBindingPattern */) { + transformFlags |= 192 /* AssertES2015 */; } } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~939525441; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~939525441 /* NodeExcludes */; } function computeLabeledStatement(node, subtreeFlags) { var transformFlags = subtreeFlags; - if (subtreeFlags & 4194304 - && ts.isIterationStatement(node, true)) { - transformFlags |= 192; + // A labeled statement containing a block scoped binding *may* need to be transformed from ES6. + if (subtreeFlags & 4194304 /* ContainsBlockScopedBinding */ + && ts.isIterationStatement(node, /*lookInLabeledStatements*/ true)) { + transformFlags |= 192 /* AssertES2015 */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~939525441; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~939525441 /* NodeExcludes */; } function computeImportEquals(node, subtreeFlags) { var transformFlags = subtreeFlags; + // An ImportEqualsDeclaration with a namespace reference is TypeScript. if (!ts.isExternalModuleImportEqualsDeclaration(node)) { - transformFlags |= 3; + transformFlags |= 3 /* AssertTypeScript */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~939525441; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~939525441 /* NodeExcludes */; } function computeExpressionStatement(node, subtreeFlags) { var transformFlags = subtreeFlags; - if (node.expression.transformFlags & 1024) { - transformFlags |= 192; + // If the expression of an expression statement is a destructuring assignment, + // then we treat the statement as ES6 so that we can indicate that we do not + // need to hold on to the right-hand side. + if (node.expression.transformFlags & 1024 /* DestructuringAssignment */) { + transformFlags |= 192 /* AssertES2015 */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~939525441; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~939525441 /* NodeExcludes */; } function computeModuleDeclaration(node, subtreeFlags) { - var transformFlags = 3; + var transformFlags = 3 /* AssertTypeScript */; var modifierFlags = ts.getModifierFlags(node); - if ((modifierFlags & 2) === 0) { + if ((modifierFlags & 2 /* Ambient */) === 0) { transformFlags |= subtreeFlags; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~977327425; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~977327425 /* ModuleExcludes */; } function computeVariableDeclarationList(node, subtreeFlags) { - var transformFlags = subtreeFlags | 33554432; - if (subtreeFlags & 8388608) { - transformFlags |= 192; + var transformFlags = subtreeFlags | 33554432 /* ContainsHoistedDeclarationOrCompletion */; + if (subtreeFlags & 8388608 /* ContainsBindingPattern */) { + transformFlags |= 192 /* AssertES2015 */; } - if (node.flags & 3) { - transformFlags |= 192 | 4194304; + // If a VariableDeclarationList is `let` or `const`, then it is ES6 syntax. + if (node.flags & 3 /* BlockScoped */) { + transformFlags |= 192 /* AssertES2015 */ | 4194304 /* ContainsBlockScopedBinding */; } - node.transformFlags = transformFlags | 536870912; - return transformFlags & ~948962625; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; + return transformFlags & ~948962625 /* VariableDeclarationListExcludes */; } function computeOther(node, kind, subtreeFlags) { + // Mark transformations needed for each node var transformFlags = subtreeFlags; - var excludeFlags = 939525441; + var excludeFlags = 939525441 /* NodeExcludes */; switch (kind) { - case 120: - case 197: - transformFlags |= 8 | 16; + case 120 /* AsyncKeyword */: + case 197 /* AwaitExpression */: + // async/await is ES2017 syntax, but may be ESNext syntax (for async generators) + transformFlags |= 8 /* AssertESNext */ | 16 /* AssertES2017 */; break; - case 190: - case 208: - case 302: - transformFlags |= 3; - excludeFlags = 536872257; + case 190 /* TypeAssertionExpression */: + case 208 /* AsExpression */: + case 302 /* PartiallyEmittedExpression */: + // These nodes are TypeScript syntax. + transformFlags |= 3 /* AssertTypeScript */; + excludeFlags = 536872257 /* OuterExpressionExcludes */; break; - case 114: - case 112: - case 113: - case 117: - case 124: - case 76: - case 238: - case 273: - case 209: - case 132: - transformFlags |= 3; + case 114 /* PublicKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: + case 117 /* AbstractKeyword */: + case 124 /* DeclareKeyword */: + case 76 /* ConstKeyword */: + case 238 /* EnumDeclaration */: + case 273 /* EnumMember */: + case 209 /* NonNullExpression */: + case 132 /* ReadonlyKeyword */: + // These nodes are TypeScript syntax. + transformFlags |= 3 /* AssertTypeScript */; break; - case 255: - case 256: - case 257: - case 10: - case 258: - case 259: - case 260: - case 261: - case 262: - case 263: - case 264: - case 265: - transformFlags |= 4; + case 255 /* JsxElement */: + case 256 /* JsxSelfClosingElement */: + case 257 /* JsxOpeningElement */: + case 10 /* JsxText */: + case 258 /* JsxClosingElement */: + case 259 /* JsxFragment */: + case 260 /* JsxOpeningFragment */: + case 261 /* JsxClosingFragment */: + case 262 /* JsxAttribute */: + case 263 /* JsxAttributes */: + case 264 /* JsxSpreadAttribute */: + case 265 /* JsxExpression */: + // These nodes are Jsx syntax. + transformFlags |= 4 /* AssertJsx */; break; - case 13: - case 14: - case 15: - case 16: - case 202: - case 189: - case 271: - case 115: - case 210: - transformFlags |= 192; + case 13 /* NoSubstitutionTemplateLiteral */: + case 14 /* TemplateHead */: + case 15 /* TemplateMiddle */: + case 16 /* TemplateTail */: + case 202 /* TemplateExpression */: + case 189 /* TaggedTemplateExpression */: + case 271 /* ShorthandPropertyAssignment */: + case 115 /* StaticKeyword */: + case 210 /* MetaProperty */: + // These nodes are ES6 syntax. + transformFlags |= 192 /* AssertES2015 */; break; - case 9: + case 9 /* StringLiteral */: if (node.hasExtendedUnicodeEscape) { - transformFlags |= 192; + transformFlags |= 192 /* AssertES2015 */; } break; - case 8: - if (node.numericLiteralFlags & 384) { - transformFlags |= 192; + case 8 /* NumericLiteral */: + if (node.numericLiteralFlags & 384 /* BinaryOrOctalSpecifier */) { + transformFlags |= 192 /* AssertES2015 */; } break; - case 222: + case 222 /* ForOfStatement */: + // This node is either ES2015 syntax or ES2017 syntax (if it is a for-await-of). if (node.awaitModifier) { - transformFlags |= 8; + transformFlags |= 8 /* AssertESNext */; } - transformFlags |= 192; + transformFlags |= 192 /* AssertES2015 */; break; - case 203: - transformFlags |= 8 | 192 | 16777216; + case 203 /* YieldExpression */: + // This node is either ES2015 syntax (in a generator) or ES2017 syntax (in an async + // generator). + transformFlags |= 8 /* AssertESNext */ | 192 /* AssertES2015 */ | 16777216 /* ContainsYield */; break; - case 119: - case 134: - case 131: - case 135: - case 137: - case 122: - case 138: - case 105: - case 148: - case 151: - case 153: - case 158: - case 159: - case 160: - case 161: - case 162: - case 163: - case 164: - case 165: - case 166: - case 167: - case 168: - case 169: - case 170: - case 171: - case 172: - case 173: - case 236: - case 237: - case 174: - case 175: - case 176: - case 177: - case 178: - case 242: - transformFlags = 3; - excludeFlags = -3; + case 119 /* AnyKeyword */: + case 134 /* NumberKeyword */: + case 131 /* NeverKeyword */: + case 135 /* ObjectKeyword */: + case 137 /* StringKeyword */: + case 122 /* BooleanKeyword */: + case 138 /* SymbolKeyword */: + case 105 /* VoidKeyword */: + case 148 /* TypeParameter */: + case 151 /* PropertySignature */: + case 153 /* MethodSignature */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 160 /* IndexSignature */: + case 161 /* TypePredicate */: + case 162 /* TypeReference */: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 165 /* TypeQuery */: + case 166 /* TypeLiteral */: + case 167 /* ArrayType */: + case 168 /* TupleType */: + case 169 /* UnionType */: + case 170 /* IntersectionType */: + case 171 /* ConditionalType */: + case 172 /* InferType */: + case 173 /* ParenthesizedType */: + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 174 /* ThisType */: + case 175 /* TypeOperator */: + case 176 /* IndexedAccessType */: + case 177 /* MappedType */: + case 178 /* LiteralType */: + case 242 /* NamespaceExportDeclaration */: + // Types and signatures are TypeScript syntax, and exclude all other facts. + transformFlags = 3 /* AssertTypeScript */; + excludeFlags = -3 /* TypeExcludes */; break; - case 147: - transformFlags |= 2097152; - if (subtreeFlags & 16384) { - transformFlags |= 65536; + case 147 /* 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 |= 2097152 /* ContainsComputedPropertyName */; + if (subtreeFlags & 16384 /* ContainsLexicalThis */) { + // A computed method name like `[this.getName()](x: string) { ... }` needs to + // distinguish itself from the normal case of a method body containing `this`: + // `this` inside a method doesn't need to be rewritten (the method provides `this`), + // whereas `this` inside a computed name *might* need to be rewritten if the class/object + // is inside an arrow function: + // `_this = this; () => class K { [_this.getName()]() { ... } }` + // To make this distinction, use ContainsLexicalThisInComputedPropertyName + // instead of ContainsLexicalThis for computed property names + transformFlags |= 65536 /* ContainsLexicalThisInComputedPropertyName */; } break; - case 204: - transformFlags |= 192 | 524288; + case 204 /* SpreadElement */: + transformFlags |= 192 /* AssertES2015 */ | 524288 /* ContainsSpread */; break; - case 272: - transformFlags |= 8 | 1048576; + case 272 /* SpreadAssignment */: + transformFlags |= 8 /* AssertESNext */ | 1048576 /* ContainsObjectSpread */; break; - case 97: - transformFlags |= 192 | 134217728; - excludeFlags = 536872257; + case 97 /* SuperKeyword */: + // This node is ES6 syntax. + transformFlags |= 192 /* AssertES2015 */ | 134217728 /* Super */; + excludeFlags = 536872257 /* OuterExpressionExcludes */; // must be set to persist `Super` break; - case 99: - transformFlags |= 16384; + case 99 /* ThisKeyword */: + // Mark this node and its ancestors as containing a lexical `this` keyword. + transformFlags |= 16384 /* ContainsLexicalThis */; break; - case 180: - transformFlags |= 192 | 8388608; - if (subtreeFlags & 524288) { - transformFlags |= 8 | 1048576; + case 180 /* ObjectBindingPattern */: + transformFlags |= 192 /* AssertES2015 */ | 8388608 /* ContainsBindingPattern */; + if (subtreeFlags & 524288 /* ContainsRest */) { + transformFlags |= 8 /* AssertESNext */ | 1048576 /* ContainsObjectRest */; } - excludeFlags = 940049729; + excludeFlags = 940049729 /* BindingPatternExcludes */; break; - case 181: - transformFlags |= 192 | 8388608; - excludeFlags = 940049729; + case 181 /* ArrayBindingPattern */: + transformFlags |= 192 /* AssertES2015 */ | 8388608 /* ContainsBindingPattern */; + excludeFlags = 940049729 /* BindingPatternExcludes */; break; - case 182: - transformFlags |= 192; + case 182 /* BindingElement */: + transformFlags |= 192 /* AssertES2015 */; if (node.dotDotDotToken) { - transformFlags |= 524288; + transformFlags |= 524288 /* ContainsRest */; } break; - case 150: - transformFlags |= 3 | 4096; + case 150 /* Decorator */: + // This node is TypeScript syntax, and marks its container as also being TypeScript syntax. + transformFlags |= 3 /* AssertTypeScript */ | 4096 /* ContainsDecorators */; break; - case 184: - excludeFlags = 942740801; - if (subtreeFlags & 2097152) { - transformFlags |= 192; + case 184 /* ObjectLiteralExpression */: + excludeFlags = 942740801 /* ObjectLiteralExcludes */; + if (subtreeFlags & 2097152 /* ContainsComputedPropertyName */) { + // If an ObjectLiteralExpression contains a ComputedPropertyName, then it + // is an ES6 node. + transformFlags |= 192 /* AssertES2015 */; } - if (subtreeFlags & 65536) { - transformFlags |= 16384; + if (subtreeFlags & 65536 /* ContainsLexicalThisInComputedPropertyName */) { + // A computed property name containing `this` might need to be rewritten, + // so propagate the ContainsLexicalThis flag upward. + transformFlags |= 16384 /* ContainsLexicalThis */; } - if (subtreeFlags & 1048576) { - transformFlags |= 8; + if (subtreeFlags & 1048576 /* ContainsObjectSpread */) { + // If an ObjectLiteralExpression contains a spread element, then it + // is an ES next node. + transformFlags |= 8 /* AssertESNext */; } break; - case 183: - case 188: - excludeFlags = 940049729; - if (subtreeFlags & 524288) { - transformFlags |= 192; + case 183 /* ArrayLiteralExpression */: + case 188 /* NewExpression */: + excludeFlags = 940049729 /* ArrayLiteralOrCallOrNewExcludes */; + if (subtreeFlags & 524288 /* ContainsSpread */) { + // If the this node contains a SpreadExpression, then it is an ES6 + // node. + transformFlags |= 192 /* AssertES2015 */; } break; - case 218: - case 219: - case 220: - case 221: - if (subtreeFlags & 4194304) { - transformFlags |= 192; + case 218 /* DoStatement */: + case 219 /* WhileStatement */: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + // A loop containing a block scoped binding *may* need to be transformed from ES6. + if (subtreeFlags & 4194304 /* ContainsBlockScopedBinding */) { + transformFlags |= 192 /* AssertES2015 */; } break; - case 274: - if (subtreeFlags & 32768) { - transformFlags |= 192; + case 274 /* SourceFile */: + if (subtreeFlags & 32768 /* ContainsCapturedLexicalThis */) { + transformFlags |= 192 /* AssertES2015 */; } break; - case 225: - transformFlags |= 33554432 | 8; + case 225 /* ReturnStatement */: + // Return statements may require an `await` in ESNext. + transformFlags |= 33554432 /* ContainsHoistedDeclarationOrCompletion */ | 8 /* AssertESNext */; break; - case 223: - case 224: - transformFlags |= 33554432; + case 223 /* ContinueStatement */: + case 224 /* BreakStatement */: + transformFlags |= 33554432 /* ContainsHoistedDeclarationOrCompletion */; break; } - node.transformFlags = transformFlags | 536870912; + node.transformFlags = transformFlags | 536870912 /* HasComputedFlags */; return transformFlags & ~excludeFlags; } + /** + * Gets the transform flags to exclude when unioning the transform flags of a subtree. + * + * NOTE: This needs to be kept up-to-date with the exclusions used in `computeTransformFlagsForNode`. + * For performance reasons, `computeTransformFlagsForNode` uses local constant values rather + * than calling this function. + */ + /* @internal */ function getTransformFlagsSubtreeExclusions(kind) { - if (kind >= 161 && kind <= 179) { - return -3; + if (kind >= 161 /* FirstTypeNode */ && kind <= 179 /* LastTypeNode */) { + return -3 /* TypeExcludes */; } switch (kind) { - case 187: - case 188: - case 183: - return 940049729; - case 239: - return 977327425; - case 149: - return 939525441; - case 193: - return 1003902273; - case 192: - case 234: - return 1003935041; - case 233: - return 948962625; - case 235: - case 205: - return 942011713; - case 155: - return 1003668801; - case 154: - case 156: - case 157: - return 1003668801; - case 119: - case 134: - case 131: - case 137: - case 135: - case 122: - case 138: - case 105: - case 148: - case 151: - case 153: - case 158: - case 159: - case 160: - case 236: - case 237: - return -3; - case 184: - return 942740801; - case 269: - return 940574017; - case 180: - case 181: - return 940049729; - case 190: - case 208: - case 302: - case 191: - case 97: - return 536872257; - case 185: - case 186: - return 671089985; + case 187 /* CallExpression */: + case 188 /* NewExpression */: + case 183 /* ArrayLiteralExpression */: + return 940049729 /* ArrayLiteralOrCallOrNewExcludes */; + case 239 /* ModuleDeclaration */: + return 977327425 /* ModuleExcludes */; + case 149 /* Parameter */: + return 939525441 /* ParameterExcludes */; + case 193 /* ArrowFunction */: + return 1003902273 /* ArrowFunctionExcludes */; + case 192 /* FunctionExpression */: + case 234 /* FunctionDeclaration */: + return 1003935041 /* FunctionExcludes */; + case 233 /* VariableDeclarationList */: + return 948962625 /* VariableDeclarationListExcludes */; + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + return 942011713 /* ClassExcludes */; + case 155 /* Constructor */: + return 1003668801 /* ConstructorExcludes */; + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + return 1003668801 /* MethodOrAccessorExcludes */; + case 119 /* AnyKeyword */: + case 134 /* NumberKeyword */: + case 131 /* NeverKeyword */: + case 137 /* StringKeyword */: + case 135 /* ObjectKeyword */: + case 122 /* BooleanKeyword */: + case 138 /* SymbolKeyword */: + case 105 /* VoidKeyword */: + case 148 /* TypeParameter */: + case 151 /* PropertySignature */: + case 153 /* MethodSignature */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 160 /* IndexSignature */: + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: + return -3 /* TypeExcludes */; + case 184 /* ObjectLiteralExpression */: + return 942740801 /* ObjectLiteralExcludes */; + case 269 /* CatchClause */: + return 940574017 /* CatchClauseExcludes */; + case 180 /* ObjectBindingPattern */: + case 181 /* ArrayBindingPattern */: + return 940049729 /* BindingPatternExcludes */; + case 190 /* TypeAssertionExpression */: + case 208 /* AsExpression */: + case 302 /* PartiallyEmittedExpression */: + case 191 /* ParenthesizedExpression */: + case 97 /* SuperKeyword */: + return 536872257 /* OuterExpressionExcludes */; + case 185 /* PropertyAccessExpression */: + case 186 /* ElementAccessExpression */: + return 671089985 /* PropertyAccessExcludes */; default: - return 939525441; + return 939525441 /* NodeExcludes */; } } ts.getTransformFlagsSubtreeExclusions = getTransformFlagsSubtreeExclusions; + /** + * "Binds" JSDoc nodes in TypeScript code. + * Since we will never create symbols for JSDoc, we just set parent pointers instead. + */ function setParentPointers(parent, child) { child.parent = parent; ts.forEachChild(child, function (grandchild) { return setParentPointers(child, grandchild); }); } })(ts || (ts = {})); +/** @internal */ var ts; (function (ts) { function createGetSymbolWalker(getRestTypeOfSignature, getTypePredicateOfSignature, getReturnTypeOfSignature, getBaseTypes, resolveStructuredTypeMembers, getTypeOfSymbol, getResolvedSymbol, getIndexTypeOfStructuredType, getConstraintFromTypeParameter, getFirstIdentifier) { return getSymbolWalker; function getSymbolWalker(accept) { if (accept === void 0) { accept = function () { return true; }; } - var visitedTypes = []; - var visitedSymbols = []; + var visitedTypes = []; // Sparse array from id to type + var visitedSymbols = []; // Sparse array from id to symbol return { walkType: function (type) { try { @@ -24803,35 +28864,38 @@ var ts; return; } visitedTypes[type.id] = type; + // Reuse visitSymbol to visit the type's symbol, + // but be sure to bail on recuring into the type if accept declines the symbol. var shouldBail = visitSymbol(type.symbol); if (shouldBail) return; - if (type.flags & 131072) { + // Visit the type's related types, if any + if (type.flags & 131072 /* Object */) { var objectType = type; var objectFlags = objectType.objectFlags; - if (objectFlags & 4) { + if (objectFlags & 4 /* Reference */) { visitTypeReference(type); } - if (objectFlags & 32) { + if (objectFlags & 32 /* Mapped */) { visitMappedType(type); } - if (objectFlags & (1 | 2)) { + if (objectFlags & (1 /* Class */ | 2 /* Interface */)) { visitInterfaceType(type); } - if (objectFlags & (8 | 16)) { + if (objectFlags & (8 /* Tuple */ | 16 /* Anonymous */)) { visitObjectType(objectType); } } - if (type.flags & 65536) { + if (type.flags & 65536 /* TypeParameter */) { visitTypeParameter(type); } - if (type.flags & 786432) { + if (type.flags & 786432 /* UnionOrIntersection */) { visitUnionOrIntersectionType(type); } - if (type.flags & 1048576) { + if (type.flags & 1048576 /* Index */) { visitIndexType(type); } - if (type.flags & 2097152) { + if (type.flags & 2097152 /* IndexedAccess */) { visitIndexedAccessType(type); } } @@ -24879,10 +28943,11 @@ var ts; visitType(interfaceT.thisType); } function visitObjectType(type) { - var stringIndexType = getIndexTypeOfStructuredType(type, 0); + var stringIndexType = getIndexTypeOfStructuredType(type, 0 /* String */); visitType(stringIndexType); - var numberIndexType = getIndexTypeOfStructuredType(type, 1); + var numberIndexType = getIndexTypeOfStructuredType(type, 1 /* Number */); visitType(numberIndexType); + // The two checks above *should* have already resolved the type (if needed), so this should be cached var resolved = resolveStructuredTypeMembers(type); for (var _i = 0, _a = resolved.callSignatures; _i < _a.length; _i++) { var signature = _a[_i]; @@ -24910,12 +28975,16 @@ var ts; return true; } var t = getTypeOfSymbol(symbol); - visitType(t); - if (symbol.flags & 1955) { + visitType(t); // Should handle members on classes and such + if (symbol.flags & 1955 /* HasExports */) { symbol.exports.forEach(visitSymbol); } ts.forEach(symbol.declarations, function (d) { - if (d.type && d.type.kind === 165) { + // Type queries are too far resolved when we just visit the symbol's type + // (their type resolved directly to the member deeply referenced) + // So to get the intervening symbols, we need to check if there's a type + // query node on any of the symbol's declarations and get symbols there + if (d.type && d.type.kind === 165 /* TypeQuery */) { var query = d.type; var entity = getResolvedSymbol(getFirstIdentifier(query.exprName)); visitSymbol(entity); @@ -24927,6 +28996,7 @@ var ts; } ts.createGetSymbolWalker = createGetSymbolWalker; })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var ambientModuleSymbolRegex = /^".+"$/; @@ -24952,17 +29022,28 @@ var ts; ts.getSymbolId = getSymbolId; function isInstantiatedModule(node, preserveConstEnums) { var moduleState = ts.getModuleInstanceState(node); - return moduleState === 1 || - (preserveConstEnums && moduleState === 2); + return moduleState === 1 /* Instantiated */ || + (preserveConstEnums && moduleState === 2 /* ConstEnumOnly */); } ts.isInstantiatedModule = isInstantiatedModule; function createTypeChecker(host, produceDiagnostics) { + // Cancellation that controls whether or not we can cancel in the middle of type checking. + // In general cancelling is *not* safe for the type checker. We might be in the middle of + // computing something, and we will leave our internals in an inconsistent state. Callers + // who set the cancellation token should catch if a cancellation exception occurs, and + // should throw away and create a new TypeChecker. + // + // Currently we only support setting the cancellation token when getting diagnostics. This + // is because diagnostics can be quite expensive, and we want to allow hosts to bail out if + // they no longer need the information (for example, if the user started editing again). var cancellationToken; var requestedExternalEmitHelpers; var externalHelpersModule; + // tslint:disable variable-name var Symbol = ts.objectAllocator.getSymbolConstructor(); var Type = ts.objectAllocator.getTypeConstructor(); var Signature = ts.objectAllocator.getSignatureConstructor(); + // tslint:enable variable-name var typeCount = 0; var symbolCount = 0; var enumCount = 0; @@ -24981,12 +29062,18 @@ var ts; var keyofStringsOnly = !!compilerOptions.keyofStringsOnly; var emitResolver = createResolver(); var nodeBuilder = createNodeBuilder(); - var undefinedSymbol = createSymbol(4, "undefined"); + var undefinedSymbol = createSymbol(4 /* Property */, "undefined"); undefinedSymbol.declarations = []; - var argumentsSymbol = createSymbol(4, "arguments"); - var requireSymbol = createSymbol(4, "require"); - var moduleSymbol = createSymbol(4, "module"); + var argumentsSymbol = createSymbol(4 /* Property */, "arguments"); + var requireSymbol = createSymbol(4 /* Property */, "require"); + var moduleSymbol = createSymbol(4 /* Property */, "module"); + /** This will be set during calls to `getResolvedSignature` where services determines an apparent number of arguments greater than what is actually provided. */ var apparentArgumentCount; + // for public members that accept a Node or one of its subtypes, we must guard against + // synthetic nodes created during transformations by calling `getParseTreeNode`. + // for most of these, we perform the guard only on `checker` to avoid any possible + // extra cost of calling `getParseTreeNode` when calling these functions from inside the + // checker. var checker = { getNodeCount: function () { return ts.sum(host.getSourceFiles(), "nodeCount"); }, getIdentifierCount: function () { return ts.sum(host.getSourceFiles(), "identifierCount"); }, @@ -25129,13 +29216,13 @@ var ts; return parsed ? isImplementationOfOverload(parsed) : undefined; }, getImmediateAliasedSymbol: function (symbol) { - ts.Debug.assert((symbol.flags & 2097152) !== 0, "Should only get Alias here."); + ts.Debug.assert((symbol.flags & 2097152 /* Alias */) !== 0, "Should only get Alias here."); var links = getSymbolLinks(symbol); if (!links.immediateTarget) { var node = getDeclarationOfAliasSymbol(symbol); if (!node) return ts.Debug.fail(); - links.immediateTarget = getTargetOfAliasDeclaration(node, true); + links.immediateTarget = getTargetOfAliasDeclaration(node, /*dontRecursivelyResolve*/ true); } return links.immediateTarget; }, @@ -25157,7 +29244,9 @@ var ts; tryGetMemberInModuleExports: function (name, symbol) { return tryGetMemberInModuleExports(ts.escapeLeadingUnderscores(name), symbol); }, tryGetMemberInModuleExportsAndProperties: function (name, symbol) { return tryGetMemberInModuleExportsAndProperties(ts.escapeLeadingUnderscores(name), symbol); }, tryFindAmbientModuleWithoutAugmentations: function (moduleName) { - return tryFindAmbientModule(moduleName, false); + // we deliberately exclude augmentations + // since we are only interested in declarations of the module itself + return tryFindAmbientModule(moduleName, /*withAugmentations*/ false); }, getApparentType: getApparentType, getUnionType: getUnionType, @@ -25185,9 +29274,9 @@ var ts; getSuggestionForNonexistentSymbol: function (location, name, meaning) { return getSuggestionForNonexistentSymbol(location, ts.escapeLeadingUnderscores(name), meaning); }, getSuggestionForNonexistentModule: function (node, target) { return getSuggestionForNonexistentModule(node, target); }, getBaseConstraintOfType: getBaseConstraintOfType, - getDefaultFromTypeParameter: function (type) { return type && type.flags & 65536 ? getDefaultFromTypeParameter(type) : undefined; }, + getDefaultFromTypeParameter: function (type) { return type && type.flags & 65536 /* TypeParameter */ ? getDefaultFromTypeParameter(type) : undefined; }, resolveName: function (name, location, meaning, excludeGlobals) { - return resolveName(location, ts.escapeLeadingUnderscores(name), meaning, undefined, undefined, false, excludeGlobals); + return resolveName(location, ts.escapeLeadingUnderscores(name), meaning, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false, excludeGlobals); }, getJsxNamespace: function (n) { return ts.unescapeLeadingUnderscores(getJsxNamespace(n)); }, getAccessibleSymbolChain: getAccessibleSymbolChain, @@ -25204,11 +29293,15 @@ var ts; getSuggestionDiagnostics: function (file, ct) { var diagnostics; try { + // Record the cancellation token so it can be checked later on during checkSourceElement. + // Do this in a finally block so we can ensure that it gets reset back to nothing after + // this call is done. cancellationToken = ct; + // Ensure file is type checked checkSourceFile(file); - ts.Debug.assert(!!(getNodeLinks(file).flags & 1)); + ts.Debug.assert(!!(getNodeLinks(file).flags & 1 /* TypeChecked */)); diagnostics = ts.addRange(diagnostics, suggestionDiagnostics.get(file.fileName)); - if (!file.isDeclarationFile && (!unusedIsError(0) || !unusedIsError(1))) { + if (!file.isDeclarationFile && (!unusedIsError(0 /* Local */) || !unusedIsError(1 /* Parameter */))) { addUnusedDiagnostics(); } return diagnostics || ts.emptyArray; @@ -25241,56 +29334,63 @@ var ts; var indexedAccessTypes = ts.createMap(); var evolvingArrayTypes = []; var undefinedProperties = ts.createMap(); - var unknownSymbol = createSymbol(4, "unknown"); - var resolvingSymbol = createSymbol(0, "__resolving__"); - var anyType = createIntrinsicType(1, "any"); - var autoType = createIntrinsicType(1, "any"); - var wildcardType = createIntrinsicType(1, "any"); - var errorType = createIntrinsicType(1, "error"); - var unknownType = createIntrinsicType(2, "unknown"); - var undefinedType = createIntrinsicType(8192, "undefined"); - var undefinedWideningType = strictNullChecks ? undefinedType : createIntrinsicType(8192 | 134217728, "undefined"); - var nullType = createIntrinsicType(16384, "null"); - var nullWideningType = strictNullChecks ? nullType : createIntrinsicType(16384 | 134217728, "null"); - var stringType = createIntrinsicType(4, "string"); - var numberType = createIntrinsicType(8, "number"); - var falseType = createIntrinsicType(256, "false"); - var trueType = createIntrinsicType(256, "true"); + var unknownSymbol = createSymbol(4 /* Property */, "unknown"); + var resolvingSymbol = createSymbol(0, "__resolving__" /* Resolving */); + var anyType = createIntrinsicType(1 /* Any */, "any"); + var autoType = createIntrinsicType(1 /* Any */, "any"); + var wildcardType = createIntrinsicType(1 /* Any */, "any"); + var errorType = createIntrinsicType(1 /* Any */, "error"); + var unknownType = createIntrinsicType(2 /* Unknown */, "unknown"); + var undefinedType = createIntrinsicType(8192 /* Undefined */, "undefined"); + var undefinedWideningType = strictNullChecks ? undefinedType : createIntrinsicType(8192 /* Undefined */ | 134217728 /* ContainsWideningType */, "undefined"); + var nullType = createIntrinsicType(16384 /* Null */, "null"); + var nullWideningType = strictNullChecks ? nullType : createIntrinsicType(16384 /* Null */ | 134217728 /* ContainsWideningType */, "null"); + var stringType = createIntrinsicType(4 /* String */, "string"); + var numberType = createIntrinsicType(8 /* Number */, "number"); + var falseType = createIntrinsicType(256 /* BooleanLiteral */, "false"); + var trueType = createIntrinsicType(256 /* BooleanLiteral */, "true"); var booleanType = createBooleanType([falseType, trueType]); - var esSymbolType = createIntrinsicType(1024, "symbol"); - var voidType = createIntrinsicType(4096, "void"); - var neverType = createIntrinsicType(32768, "never"); - var silentNeverType = createIntrinsicType(32768, "never"); - var implicitNeverType = createIntrinsicType(32768, "never"); - var nonPrimitiveType = createIntrinsicType(16777216, "object"); + var esSymbolType = createIntrinsicType(1024 /* ESSymbol */, "symbol"); + var voidType = createIntrinsicType(4096 /* Void */, "void"); + var neverType = createIntrinsicType(32768 /* Never */, "never"); + var silentNeverType = createIntrinsicType(32768 /* Never */, "never"); + var implicitNeverType = createIntrinsicType(32768 /* Never */, "never"); + var nonPrimitiveType = createIntrinsicType(16777216 /* NonPrimitive */, "object"); var stringNumberSymbolType = getUnionType([stringType, numberType, esSymbolType]); var keyofConstraintType = keyofStringsOnly ? stringType : stringNumberSymbolType; var emptyObjectType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, undefined, undefined); - var emptyTypeLiteralSymbol = createSymbol(2048, "__type"); + var emptyTypeLiteralSymbol = createSymbol(2048 /* TypeLiteral */, "__type" /* Type */); emptyTypeLiteralSymbol.members = ts.createSymbolTable(); var emptyTypeLiteralType = createAnonymousType(emptyTypeLiteralSymbol, emptySymbols, ts.emptyArray, ts.emptyArray, undefined, undefined); var emptyGenericType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, undefined, undefined); emptyGenericType.instantiations = ts.createMap(); var anyFunctionType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, undefined, undefined); - anyFunctionType.flags |= 536870912; + // The anyFunctionType contains the anyFunctionType by definition. The flag is further propagated + // in getPropagatingFlagsOfTypes, and it is checked in inferFromTypes. + anyFunctionType.flags |= 536870912 /* ContainsAnyFunctionType */; var noConstraintType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, undefined, undefined); var circularConstraintType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, undefined, undefined); var resolvingDefaultType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, undefined, undefined); - var markerSuperType = createType(65536); - var markerSubType = createType(65536); + var markerSuperType = createType(65536 /* TypeParameter */); + var markerSubType = createType(65536 /* TypeParameter */); markerSubType.constraint = markerSuperType; - var markerOtherType = createType(65536); + var markerOtherType = createType(65536 /* TypeParameter */); var noTypePredicate = createIdentifierTypePredicate("<>", 0, anyType); - var anySignature = createSignature(undefined, undefined, undefined, ts.emptyArray, anyType, undefined, 0, false, false); - var unknownSignature = createSignature(undefined, undefined, undefined, ts.emptyArray, errorType, undefined, 0, false, false); - var resolvingSignature = createSignature(undefined, undefined, undefined, ts.emptyArray, anyType, undefined, 0, false, false); - var silentNeverSignature = createSignature(undefined, undefined, undefined, ts.emptyArray, silentNeverType, undefined, 0, false, false); + var anySignature = createSignature(undefined, undefined, undefined, ts.emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); + var unknownSignature = createSignature(undefined, undefined, undefined, ts.emptyArray, errorType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); + var resolvingSignature = createSignature(undefined, undefined, undefined, ts.emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); + var silentNeverSignature = createSignature(undefined, undefined, undefined, ts.emptyArray, silentNeverType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); var resolvingSignaturesArray = [resolvingSignature]; - var enumNumberIndexInfo = createIndexInfo(stringType, true); - var jsObjectLiteralIndexInfo = createIndexInfo(anyType, false); + var enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true); + var jsObjectLiteralIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false); var globals = ts.createSymbolTable(); var reverseMappedCache = ts.createMap(); var ambientModulesCache; + /** + * List of every ambient module with a "*" wildcard. + * Unlike other ambient modules, these can't be stored in `globals` because symbol tables only deal with exact matches. + * This is only used if there is no exact match. + */ var patternAmbientModules; var globalObjectType; var globalFunctionType; @@ -25305,6 +29405,9 @@ var ts; var autoArrayType; var anyReadonlyArrayType; var deferredGlobalNonNullableTypeAlias; + // The library files are only loaded when the feature is used. + // This allows users to just specify library files they want to used through --lib + // and they will not get an error from not having unrelated library files var deferredGlobalESSymbolConstructorSymbol; var deferredGlobalESSymbolType; var deferredGlobalTypedPropertyDescriptorType; @@ -25321,7 +29424,7 @@ var ts; var deferredGlobalImportMetaType; var deferredGlobalExtractSymbol; var deferredNodes; - var allPotentiallyUnusedIdentifiers = ts.createMap(); + var allPotentiallyUnusedIdentifiers = ts.createMap(); // key is file name var flowLoopStart = 0; var flowLoopCount = 0; var sharedFlowCount = 0; @@ -25346,6 +29449,7 @@ var ts; var potentialNewTargetCollisions = []; var awaitedTypeStack = []; var diagnostics = ts.createDiagnosticCollection(); + // Suggestion diagnostics must have a file. Keyed by source file name. var suggestionDiagnostics = ts.createMultiMap(); var TypeFacts; (function (TypeFacts) { @@ -25373,6 +29477,9 @@ var ts; TypeFacts[TypeFacts["Truthy"] = 1048576] = "Truthy"; TypeFacts[TypeFacts["Falsy"] = 2097152] = "Falsy"; TypeFacts[TypeFacts["All"] = 4194303] = "All"; + // The following members encode facts about particular kinds of types for use in the getTypeFacts function. + // The presence of a particular fact means that the given test is true for some (and possibly all) values + // of that kind of type. TypeFacts[TypeFacts["BaseStringStrictFacts"] = 933633] = "BaseStringStrictFacts"; TypeFacts[TypeFacts["BaseStringFacts"] = 3145473] = "BaseStringFacts"; TypeFacts[TypeFacts["StringStrictFacts"] = 4079361] = "StringStrictFacts"; @@ -25407,22 +29514,22 @@ var ts; TypeFacts[TypeFacts["NullFacts"] = 2340752] = "NullFacts"; })(TypeFacts || (TypeFacts = {})); var typeofEQFacts = ts.createMapFromTemplate({ - string: 1, - number: 2, - boolean: 4, - symbol: 8, - undefined: 16384, - object: 16, - function: 32 + string: 1 /* TypeofEQString */, + number: 2 /* TypeofEQNumber */, + boolean: 4 /* TypeofEQBoolean */, + symbol: 8 /* TypeofEQSymbol */, + undefined: 16384 /* EQUndefined */, + object: 16 /* TypeofEQObject */, + function: 32 /* TypeofEQFunction */ }); var typeofNEFacts = ts.createMapFromTemplate({ - string: 128, - number: 256, - boolean: 512, - symbol: 1024, - undefined: 131072, - object: 2048, - function: 4096 + string: 128 /* TypeofNEString */, + number: 256 /* TypeofNENumber */, + boolean: 512 /* TypeofNEBoolean */, + symbol: 1024 /* TypeofNESymbol */, + undefined: 131072 /* NEUndefined */, + object: 2048 /* TypeofNEObject */, + function: 4096 /* TypeofNEFunction */ }); var typeofTypesByName = ts.createMapFromTemplate({ string: stringType, @@ -25490,52 +29597,55 @@ var ts; var isNotOverloadAndNotAccessor = ts.and(isNotOverload, isNotAccessor); initializeTypeChecker(); return checker; + /** + * @deprecated + */ function getSymbolDisplayBuilder() { return { buildTypeDisplay: function (type, writer, enclosingDeclaration, flags) { typeToString(type, enclosingDeclaration, flags, emitTextWriterWrapper(writer)); }, buildSymbolDisplay: function (symbol, writer, enclosingDeclaration, meaning, flags) { - if (flags === void 0) { flags = 0; } - symbolToString(symbol, enclosingDeclaration, meaning, flags | 4, emitTextWriterWrapper(writer)); + if (flags === void 0) { flags = 0 /* None */; } + symbolToString(symbol, enclosingDeclaration, meaning, flags | 4 /* AllowAnyNodeKind */, emitTextWriterWrapper(writer)); }, buildSignatureDisplay: function (signature, writer, enclosing, flags, kind) { signatureToString(signature, enclosing, flags, kind, emitTextWriterWrapper(writer)); }, buildIndexSignatureDisplay: function (info, writer, kind, enclosing, flags) { - var sig = nodeBuilder.indexInfoToIndexSignatureDeclaration(info, kind, enclosing, toNodeBuilderFlags(flags) | 3112960, writer); + var sig = nodeBuilder.indexInfoToIndexSignatureDeclaration(info, kind, enclosing, toNodeBuilderFlags(flags) | 3112960 /* IgnoreErrors */, writer); var printer = ts.createPrinter({ removeComments: true }); - printer.writeNode(4, sig, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + printer.writeNode(4 /* Unspecified */, sig, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); }, buildParameterDisplay: function (symbol, writer, enclosing, flags) { - var node = nodeBuilder.symbolToParameterDeclaration(symbol, enclosing, toNodeBuilderFlags(flags) | 3112960, writer); + var node = nodeBuilder.symbolToParameterDeclaration(symbol, enclosing, toNodeBuilderFlags(flags) | 3112960 /* IgnoreErrors */, writer); var printer = ts.createPrinter({ removeComments: true }); - printer.writeNode(4, node, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + printer.writeNode(4 /* Unspecified */, node, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); // TODO: GH#18217 }, buildTypeParameterDisplay: function (tp, writer, enclosing, flags) { - var node = nodeBuilder.typeParameterToDeclaration(tp, enclosing, toNodeBuilderFlags(flags) | 3112960 | 8192, writer); + var node = nodeBuilder.typeParameterToDeclaration(tp, enclosing, toNodeBuilderFlags(flags) | 3112960 /* IgnoreErrors */ | 8192 /* OmitParameterModifiers */, writer); var printer = ts.createPrinter({ removeComments: true }); - printer.writeNode(4, node, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + printer.writeNode(4 /* Unspecified */, node, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); // TODO: GH#18217 }, buildTypePredicateDisplay: function (predicate, writer, enclosing, flags) { typePredicateToString(predicate, enclosing, flags, emitTextWriterWrapper(writer)); }, buildTypeParameterDisplayFromSymbol: function (symbol, writer, enclosing, flags) { - var nodes = nodeBuilder.symbolToTypeParameterDeclarations(symbol, enclosing, toNodeBuilderFlags(flags) | 3112960, writer); + var nodes = nodeBuilder.symbolToTypeParameterDeclarations(symbol, enclosing, toNodeBuilderFlags(flags) | 3112960 /* IgnoreErrors */, writer); var printer = ts.createPrinter({ removeComments: true }); - printer.writeList(26896, nodes, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + printer.writeList(26896 /* TypeParameters */, nodes, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); }, buildDisplayForParametersAndDelimiters: function (thisParameter, parameters, writer, enclosing, originalFlags) { var printer = ts.createPrinter({ removeComments: true }); - var flags = 8192 | 3112960 | toNodeBuilderFlags(originalFlags); - var thisParameterArray = thisParameter ? [nodeBuilder.symbolToParameterDeclaration(thisParameter, enclosing, flags)] : []; - var params = ts.createNodeArray(thisParameterArray.concat(ts.map(parameters, function (param) { return nodeBuilder.symbolToParameterDeclaration(param, enclosing, flags); }))); - printer.writeList(1296, params, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + var flags = 8192 /* OmitParameterModifiers */ | 3112960 /* IgnoreErrors */ | toNodeBuilderFlags(originalFlags); + var thisParameterArray = thisParameter ? [nodeBuilder.symbolToParameterDeclaration(thisParameter, enclosing, flags)] : []; // TODO: GH#18217 + var params = ts.createNodeArray(thisParameterArray.concat(ts.map(parameters, function (param) { return nodeBuilder.symbolToParameterDeclaration(param, enclosing, flags); }))); // TODO: GH#18217 + printer.writeList(1296 /* CallExpressionArguments */, params, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); }, buildDisplayForTypeParametersAndDelimiters: function (typeParameters, writer, enclosing, flags) { var printer = ts.createPrinter({ removeComments: true }); - var args = ts.createNodeArray(ts.map(typeParameters, function (p) { return nodeBuilder.typeParameterToDeclaration(p, enclosing, toNodeBuilderFlags(flags)); })); - printer.writeList(26896, args, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + var args = ts.createNodeArray(ts.map(typeParameters, function (p) { return nodeBuilder.typeParameterToDeclaration(p, enclosing, toNodeBuilderFlags(flags)); })); // TODO: GH#18217 + printer.writeList(26896 /* TypeParameters */, args, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); }, buildReturnTypeDisplay: function (signature, writer, enclosing, flags) { writer.writePunctuation(":"); @@ -25544,9 +29654,9 @@ var ts; if (predicate) { return typePredicateToString(predicate, enclosing, flags, emitTextWriterWrapper(writer)); } - var node = nodeBuilder.typeToTypeNode(getReturnTypeOfSignature(signature), enclosing, toNodeBuilderFlags(flags) | 3112960, writer); + var node = nodeBuilder.typeToTypeNode(getReturnTypeOfSignature(signature), enclosing, toNodeBuilderFlags(flags) | 3112960 /* IgnoreErrors */, writer); var printer = ts.createPrinter({ removeComments: true }); - printer.writeNode(4, node, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); + printer.writeNode(4 /* Unspecified */, node, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosing)), emitTextWriterWrapper(writer)); // TODO: GH#18217 } }; function emitTextWriterWrapper(underlying) { @@ -25633,7 +29743,7 @@ var ts; } var jsxPragma = file.pragmas.get("jsx"); if (jsxPragma) { - var chosenpragma = ts.isArray(jsxPragma) ? jsxPragma[0] : jsxPragma; + var chosenpragma = ts.isArray(jsxPragma) ? jsxPragma[0] : jsxPragma; // TODO: GH#18217 file.localJsxFactory = ts.parseIsolatedEntityName(chosenpragma.arguments.factory, languageVersion); if (file.localJsxFactory) { return file.localJsxNamespace = getFirstIdentifier(file.localJsxFactory).escapedText; @@ -25656,6 +29766,8 @@ var ts; return _jsxNamespace; } function getEmitResolver(sourceFile, cancellationToken) { + // Ensure we have all the type information in place for this file so that all the + // emitter questions of this resolver will return the right information. getDiagnostics(sourceFile, cancellationToken); return emitResolver; } @@ -25679,47 +29791,47 @@ var ts; } function createSymbol(flags, name, checkFlags) { symbolCount++; - var symbol = (new Symbol(flags | 33554432, name)); + var symbol = (new Symbol(flags | 33554432 /* Transient */, name)); symbol.checkFlags = checkFlags || 0; return symbol; } function isTransientSymbol(symbol) { - return (symbol.flags & 33554432) !== 0; + return (symbol.flags & 33554432 /* Transient */) !== 0; } function getExcludedSymbolFlags(flags) { var result = 0; - if (flags & 2) - result |= 67216319; - if (flags & 1) - result |= 67216318; - if (flags & 4) - result |= 0; - if (flags & 8) - result |= 68008959; - if (flags & 16) - result |= 67215791; - if (flags & 32) - result |= 68008383; - if (flags & 64) - result |= 67901832; - if (flags & 256) - result |= 68008191; - if (flags & 128) - result |= 68008831; - if (flags & 512) - result |= 67215503; - if (flags & 8192) - result |= 67208127; - if (flags & 32768) - result |= 67150783; - if (flags & 65536) - result |= 67183551; - if (flags & 262144) - result |= 67639784; - if (flags & 524288) - result |= 67901928; - if (flags & 2097152) - result |= 2097152; + if (flags & 2 /* BlockScopedVariable */) + result |= 67216319 /* BlockScopedVariableExcludes */; + if (flags & 1 /* FunctionScopedVariable */) + result |= 67216318 /* FunctionScopedVariableExcludes */; + if (flags & 4 /* Property */) + result |= 0 /* PropertyExcludes */; + if (flags & 8 /* EnumMember */) + result |= 68008959 /* EnumMemberExcludes */; + if (flags & 16 /* Function */) + result |= 67215791 /* FunctionExcludes */; + if (flags & 32 /* Class */) + result |= 68008383 /* ClassExcludes */; + if (flags & 64 /* Interface */) + result |= 67901832 /* InterfaceExcludes */; + if (flags & 256 /* RegularEnum */) + result |= 68008191 /* RegularEnumExcludes */; + if (flags & 128 /* ConstEnum */) + result |= 68008831 /* ConstEnumExcludes */; + if (flags & 512 /* ValueModule */) + result |= 67215503 /* ValueModuleExcludes */; + if (flags & 8192 /* Method */) + result |= 67208127 /* MethodExcludes */; + if (flags & 32768 /* GetAccessor */) + result |= 67150783 /* GetAccessorExcludes */; + if (flags & 65536 /* SetAccessor */) + result |= 67183551 /* SetAccessorExcludes */; + if (flags & 262144 /* TypeParameter */) + result |= 67639784 /* TypeParameterExcludes */; + if (flags & 524288 /* TypeAlias */) + result |= 67901928 /* TypeAliasExcludes */; + if (flags & 2097152 /* Alias */) + result |= 2097152 /* AliasExcludes */; return result; } function recordMergedSymbol(target, source) { @@ -25744,20 +29856,27 @@ var ts; recordMergedSymbol(result, symbol); return result; } + /** + * Note: if target is transient, then it is mutable, and mergeSymbol with both mutate and return it. + * If target is not transient, mergeSymbol will produce a transient clone, mutate that and return it. + */ function mergeSymbol(target, source) { if (!(target.flags & getExcludedSymbolFlags(source.flags)) || - (source.flags | target.flags) & 67108864) { + (source.flags | target.flags) & 67108864 /* JSContainer */) { ts.Debug.assert(source !== target); - if (!(target.flags & 33554432)) { + if (!(target.flags & 33554432 /* Transient */)) { target = cloneSymbol(target); } - if (source.flags & 512 && target.flags & 512 && target.constEnumOnlyModule && !source.constEnumOnlyModule) { + // Javascript static-property-assignment declarations always merge, even though they are also values + if (source.flags & 512 /* ValueModule */ && target.flags & 512 /* ValueModule */ && target.constEnumOnlyModule && !source.constEnumOnlyModule) { + // reset flag when merging instantiated module into value module that has only const enums target.constEnumOnlyModule = false; } target.flags |= source.flags; if (source.valueDeclaration && (!target.valueDeclaration || ts.isEffectiveModuleDeclaration(target.valueDeclaration) && !ts.isEffectiveModuleDeclaration(source.valueDeclaration))) { + // other kinds of value declarations take precedence over modules target.valueDeclaration = source.valueDeclaration; } ts.addRange(target.declarations, source.declarations); @@ -25773,21 +29892,21 @@ var ts; } recordMergedSymbol(target, source); } - else if (target.flags & 1024) { + else if (target.flags & 1024 /* NamespaceModule */) { error(ts.getNameOfDeclaration(source.declarations[0]), ts.Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity, symbolToString(target)); } else { - var message_2 = target.flags & 384 || source.flags & 384 + var message_2 = target.flags & 384 /* Enum */ || source.flags & 384 /* Enum */ ? ts.Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations - : target.flags & 2 || source.flags & 2 + : target.flags & 2 /* BlockScopedVariable */ || source.flags & 2 /* BlockScopedVariable */ ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 : ts.Diagnostics.Duplicate_identifier_0; ts.forEach(source.declarations, function (node) { - var errorNode = (ts.getJavascriptInitializer(node, false) ? ts.getOuterNameOfJsInitializer(node) : ts.getNameOfDeclaration(node)) || node; + var errorNode = (ts.getJavascriptInitializer(node, /*isPrototypeAssignment*/ false) ? ts.getOuterNameOfJsInitializer(node) : ts.getNameOfDeclaration(node)) || node; error(errorNode, message_2, symbolToString(source)); }); ts.forEach(target.declarations, function (node) { - var errorNode = (ts.getJavascriptInitializer(node, false) ? ts.getOuterNameOfJsInitializer(node) : ts.getNameOfDeclaration(node)) || node; + var errorNode = (ts.getJavascriptInitializer(node, /*isPrototypeAssignment*/ false) ? ts.getOuterNameOfJsInitializer(node) : ts.getNameOfDeclaration(node)) || node; error(errorNode, message_2, symbolToString(source)); }); } @@ -25811,6 +29930,9 @@ var ts; function mergeModuleAugmentation(moduleName) { var moduleAugmentation = moduleName.parent; if (moduleAugmentation.symbol.declarations[0] !== moduleAugmentation) { + // this is a combined symbol for multiple augmentations within the same file. + // its symbol already has accumulated information for all declarations + // so we need to add it just once - do the work only for first declaration ts.Debug.assert(moduleAugmentation.symbol.declarations.length > 1); return; } @@ -25818,18 +29940,22 @@ var ts; mergeSymbolTable(globals, moduleAugmentation.symbol.exports); } else { - var moduleNotFoundError = !(moduleName.parent.parent.flags & 4194304) + // find a module that about to be augmented + // do not validate names of augmentations that are defined in ambient context + var moduleNotFoundError = !(moduleName.parent.parent.flags & 4194304 /* Ambient */) ? ts.Diagnostics.Invalid_module_name_in_augmentation_module_0_cannot_be_found : undefined; - var mainModule = resolveExternalModuleNameWorker(moduleName, moduleName, moduleNotFoundError, true); + var mainModule = resolveExternalModuleNameWorker(moduleName, moduleName, moduleNotFoundError, /*isForAugmentation*/ true); if (!mainModule) { return; } + // obtain item referenced by 'export=' mainModule = resolveExternalModuleSymbol(mainModule); - if (mainModule.flags & 1920) { + if (mainModule.flags & 1920 /* Namespace */) { mainModule = mergeSymbol(mainModule, moduleAugmentation.symbol); } else { + // moduleName will be a StringLiteral since this is not `declare global`. error(moduleName, ts.Diagnostics.Cannot_augment_module_0_because_it_resolves_to_a_non_module_entity, moduleName.text); } } @@ -25838,6 +29964,7 @@ var ts; source.forEach(function (sourceSymbol, id) { var targetSymbol = target.get(id); if (targetSymbol) { + // Error on redeclarations ts.forEach(targetSymbol.declarations, addDeclarationDiagnostic(ts.unescapeLeadingUnderscores(id), message)); } else { @@ -25849,7 +29976,7 @@ var ts; } } function getSymbolLinks(symbol) { - if (symbol.flags & 33554432) + if (symbol.flags & 33554432 /* Transient */) return symbol; var id = getSymbolId(symbol); return symbolLinks[id] || (symbolLinks[id] = {}); @@ -25859,30 +29986,38 @@ var ts; return nodeLinks[nodeId] || (nodeLinks[nodeId] = { flags: 0 }); } function isGlobalSourceFile(node) { - return node.kind === 274 && !ts.isExternalOrCommonJsModule(node); + return node.kind === 274 /* SourceFile */ && !ts.isExternalOrCommonJsModule(node); } function getSymbol(symbols, name, meaning) { if (meaning) { var symbol = symbols.get(name); if (symbol) { - ts.Debug.assert((ts.getCheckFlags(symbol) & 1) === 0, "Should never get an instantiated symbol here."); + ts.Debug.assert((ts.getCheckFlags(symbol) & 1 /* Instantiated */) === 0, "Should never get an instantiated symbol here."); if (symbol.flags & meaning) { return symbol; } - if (symbol.flags & 2097152) { + if (symbol.flags & 2097152 /* Alias */) { var target = resolveAlias(symbol); + // Unknown symbol means an error occurred in alias resolution, treat it as positive answer to avoid cascading errors if (target === unknownSymbol || target.flags & meaning) { return symbol; } } } } + // return undefined if we can't find a symbol. } + /** + * Get symbols that represent parameter-property-declaration as parameter and as property declaration + * @param parameter a parameterDeclaration node + * @param parameterName a name of the parameter to get the symbols for. + * @return a tuple of two symbols + */ function getSymbolsOfParameterPropertyDeclaration(parameter, parameterName) { var constructorDeclaration = parameter.parent; var classDeclaration = parameter.parent.parent; - var parameterSymbol = getSymbol(constructorDeclaration.locals, parameterName, 67216319); - var propertySymbol = getSymbol(getMembersOfSymbol(classDeclaration.symbol), parameterName, 67216319); + var parameterSymbol = getSymbol(constructorDeclaration.locals, parameterName, 67216319 /* Value */); + var propertySymbol = getSymbol(getMembersOfSymbol(classDeclaration.symbol), parameterName, 67216319 /* Value */); if (parameterSymbol && propertySymbol) { return [parameterSymbol, propertySymbol]; } @@ -25895,9 +30030,12 @@ var ts; if ((moduleKind && (declarationFile.externalModuleIndicator || useFile.externalModuleIndicator)) || (!compilerOptions.outFile && !compilerOptions.out) || isInTypeQuery(usage) || - declaration.flags & 4194304) { + declaration.flags & 4194304 /* Ambient */) { + // nodes are in different files and order cannot be determined return true; } + // declaration is after usage + // can be legal if usage is deferred (i.e. inside function or in initializer of instance property) if (isUsedInFunctionOrInstanceProperty(usage, declaration)) { return true; } @@ -25905,26 +30043,41 @@ var ts; return sourceFiles.indexOf(declarationFile) <= sourceFiles.indexOf(useFile); } if (declaration.pos <= usage.pos) { - if (declaration.kind === 182) { - var errorBindingElement = ts.getAncestor(usage, 182); + // declaration is before usage + if (declaration.kind === 182 /* BindingElement */) { + // still might be illegal if declaration and usage are both binding elements (eg var [a = b, b = b] = [1, 2]) + var errorBindingElement = ts.getAncestor(usage, 182 /* BindingElement */); if (errorBindingElement) { return ts.findAncestor(errorBindingElement, ts.isBindingElement) !== ts.findAncestor(declaration, ts.isBindingElement) || declaration.pos < errorBindingElement.pos; } - return isBlockScopedNameDeclaredBeforeUse(ts.getAncestor(declaration, 232), usage); + // or it might be illegal if usage happens before parent variable is declared (eg var [a] = a) + return isBlockScopedNameDeclaredBeforeUse(ts.getAncestor(declaration, 232 /* VariableDeclaration */), usage); } - else if (declaration.kind === 232) { + else if (declaration.kind === 232 /* VariableDeclaration */) { + // still might be illegal if usage is in the initializer of the variable declaration (eg var a = a) return !isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration, usage); } else if (ts.isClassDeclaration(declaration)) { + // still might be illegal if the usage is within a computed property name in the class (eg class A { static p = "a"; [A.p]() {} }) return !ts.findAncestor(usage, function (n) { return ts.isComputedPropertyName(n) && n.parent.parent === declaration; }); } return true; } - if (usage.parent.kind === 252 || (usage.parent.kind === 249 && usage.parent.isExportEquals)) { + // declaration is after usage, but it can still be legal if usage is deferred: + // 1. inside an export specifier + // 2. inside a function + // 3. inside an instance property initializer, a reference to a non-instance property + // 4. inside a static property initializer, a reference to a static method in the same class + // 5. inside a TS export= declaration (since we will move the export statement during emit to avoid TDZ) + // or if usage is in a type context: + // 1. inside a type query (typeof in type position) + if (usage.parent.kind === 252 /* ExportSpecifier */ || (usage.parent.kind === 249 /* ExportAssignment */ && usage.parent.isExportEquals)) { + // export specifiers do not use the variable, they only make it available for use return true; } - if (usage.kind === 249 && usage.isExportEquals) { + // When resolving symbols for exports, the `usage` location passed in can be the export site directly + if (usage.kind === 249 /* ExportAssignment */ && usage.isExportEquals) { return true; } var container = ts.getEnclosingBlockScopeContainer(declaration); @@ -25932,14 +30085,17 @@ var ts; function isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration, usage) { var container = ts.getEnclosingBlockScopeContainer(declaration); switch (declaration.parent.parent.kind) { - case 214: - case 220: - case 222: + case 214 /* VariableStatement */: + case 220 /* ForStatement */: + case 222 /* ForOfStatement */: + // variable statement/for/for-of statement case, + // use site should not be inside variable declaration (initializer of declaration or binding element) if (isSameScopeDescendentOf(usage, declaration, container)) { return true; } break; } + // ForIn/ForOf case - use site should not be used in expression part var grandparent = declaration.parent.parent; return ts.isForInOrOfStatement(grandparent) && isSameScopeDescendentOf(usage, grandparent.expression, container); } @@ -25952,16 +30108,16 @@ var ts; return true; } var initializerOfProperty = current.parent && - current.parent.kind === 152 && + current.parent.kind === 152 /* PropertyDeclaration */ && current.parent.initializer === current; if (initializerOfProperty) { - if (ts.hasModifier(current.parent, 32)) { - if (declaration.kind === 154) { + if (ts.hasModifier(current.parent, 32 /* Static */)) { + if (declaration.kind === 154 /* MethodDeclaration */) { return true; } } else { - var isDeclarationInstanceProperty = declaration.kind === 152 && !ts.hasModifier(declaration, 32); + var isDeclarationInstanceProperty = declaration.kind === 152 /* PropertyDeclaration */ && !ts.hasModifier(declaration, 32 /* Static */); if (!isDeclarationInstanceProperty || ts.getContainingClass(usage) !== ts.getContainingClass(declaration)) { return true; } @@ -25971,12 +30127,19 @@ var ts; }); } } + /** + * Resolve a given name for a given meaning at a given location. An error is reported if the name was not found and + * the nameNotFoundMessage argument is not undefined. Returns the resolved symbol, or undefined if no symbol with + * the given name can be found. + * + * @param isUse If true, this will count towards --noUnusedLocals / --noUnusedParameters. + */ function resolveName(location, name, meaning, nameNotFoundMessage, nameArg, isUse, excludeGlobals, suggestedNameNotFoundMessage) { if (excludeGlobals === void 0) { excludeGlobals = false; } return resolveNameHelper(location, name, meaning, nameNotFoundMessage, nameArg, isUse, excludeGlobals, getSymbol, suggestedNameNotFoundMessage); } function resolveNameHelper(location, name, meaning, nameNotFoundMessage, nameArg, isUse, excludeGlobals, lookup, suggestedNameNotFoundMessage) { - var originalLocation = location; + var originalLocation = location; // needed for did-you-mean error reporting, which gathers candidates starting from the original location var result; var lastLocation; var lastSelfReferenceLocation; @@ -25985,25 +30148,40 @@ var ts; var grandparent; var isInExternalModule = false; loop: while (location) { + // Locals of a source file are not in scope (because they get merged into the global symbol table) if (location.locals && !isGlobalSourceFile(location)) { if (result = lookup(location.locals, name, meaning)) { var useResult = true; if (ts.isFunctionLike(location) && lastLocation && lastLocation !== location.body) { - if (meaning & result.flags & 67901928 && lastLocation.kind !== 286) { - useResult = result.flags & 262144 + // symbol lookup restrictions for function-like declarations + // - Type parameters of a function are in scope in the entire function declaration, including the parameter + // list and return type. However, local types are only in scope in the function body. + // - parameters are only in the scope of function body + // This restriction does not apply to JSDoc comment types because they are parented + // at a higher level than type parameters would normally be + if (meaning & result.flags & 67901928 /* Type */ && lastLocation.kind !== 286 /* JSDocComment */) { + useResult = result.flags & 262144 /* TypeParameter */ + // type parameters are visible in parameter list, return type and type parameter list ? lastLocation === location.type || - lastLocation.kind === 149 || - lastLocation.kind === 148 + lastLocation.kind === 149 /* Parameter */ || + lastLocation.kind === 148 /* TypeParameter */ + // local types not visible outside the function body : false; } - if (meaning & 67216319 && result.flags & 1) { + if (meaning & 67216319 /* Value */ && result.flags & 1 /* FunctionScopedVariable */) { + // parameters are visible only inside function body, parameter list and return type + // technically for parameter list case here we might mix parameters and variables declared in function, + // however it is detected separately when checking initializers of parameters + // to make sure that they reference no variables declared after them. useResult = - lastLocation.kind === 149 || + lastLocation.kind === 149 /* Parameter */ || (lastLocation === location.type && !!ts.findAncestor(result.valueDeclaration, ts.isParameter)); } } - else if (location.kind === 171) { + else if (location.kind === 171 /* ConditionalType */) { + // A type parameter declared using 'infer T' in a conditional type is visible only in + // the true branch of the conditional type. useResult = lastLocation === location.trueType; } if (useResult) { @@ -26015,28 +30193,43 @@ var ts; } } switch (location.kind) { - case 274: + case 274 /* SourceFile */: if (!ts.isExternalOrCommonJsModule(location)) break; isInExternalModule = true; - case 239: + // falls through + case 239 /* ModuleDeclaration */: var moduleExports = getSymbolOfNode(location).exports; - if (location.kind === 274 || ts.isAmbientModule(location)) { - if (result = moduleExports.get("default")) { + if (location.kind === 274 /* SourceFile */ || ts.isAmbientModule(location)) { + // It's an external module. First see if the module has an export default and if the local + // name of that export default matches. + if (result = moduleExports.get("default" /* Default */)) { var localSymbol = ts.getLocalSymbolForExportDefault(result); if (localSymbol && (result.flags & meaning) && localSymbol.escapedName === name) { break loop; } result = undefined; } + // Because of module/namespace merging, a module's exports are in scope, + // yet we never want to treat an export specifier as putting a member in scope. + // Therefore, if the name we find is purely an export specifier, it is not actually considered in scope. + // Two things to note about this: + // 1. We have to check this without calling getSymbol. The problem with calling getSymbol + // on an export specifier is that it might find the export specifier itself, and try to + // resolve it as an alias. This will cause the checker to consider the export specifier + // a circular alias reference when it might not be. + // 2. We check === SymbolFlags.Alias in order to check that the symbol is *purely* + // an alias. If we used &, we'd be throwing out symbols that have non alias aspects, + // which is not the desired behavior. var moduleExport = moduleExports.get(name); if (moduleExport && - moduleExport.flags === 2097152 && - ts.getDeclarationOfKind(moduleExport, 252)) { + moduleExport.flags === 2097152 /* Alias */ && + ts.getDeclarationOfKind(moduleExport, 252 /* ExportSpecifier */)) { break; } } - if (name !== "default" && (result = lookup(moduleExports, name, meaning & 2623475))) { + // ES6 exports are also visible locally (except for 'default'), but commonjs exports are not (except typedefs) + if (name !== "default" /* Default */ && (result = lookup(moduleExports, name, meaning & 2623475 /* ModuleMember */))) { if (ts.isSourceFile(location) && location.commonJsModuleIndicator && !result.declarations.some(ts.isJSDocTypeAlias)) { result = undefined; } @@ -26045,37 +30238,48 @@ var ts; } } break; - case 238: - if (result = lookup(getSymbolOfNode(location).exports, name, meaning & 8)) { + case 238 /* EnumDeclaration */: + if (result = lookup(getSymbolOfNode(location).exports, name, meaning & 8 /* EnumMember */)) { break loop; } break; - case 152: - case 151: - if (ts.isClassLike(location.parent) && !ts.hasModifier(location, 32)) { + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + // TypeScript 1.0 spec (April 2014): 8.4.1 + // Initializer expressions for instance member variables are evaluated in the scope + // of the class constructor body but are not permitted to reference parameters or + // local variables of the constructor. This effectively means that entities from outer scopes + // by the same name as a constructor parameter or local variable are inaccessible + // in initializer expressions for instance member variables. + if (ts.isClassLike(location.parent) && !ts.hasModifier(location, 32 /* Static */)) { var ctor = findConstructorDeclaration(location.parent); if (ctor && ctor.locals) { - if (lookup(ctor.locals, name, meaning & 67216319)) { + if (lookup(ctor.locals, name, meaning & 67216319 /* Value */)) { + // Remember the property node, it will be used later to report appropriate error propertyWithInvalidInitializer = location; } } } break; - case 235: - case 205: - case 236: - if (result = lookup(getMembersOfSymbol(getSymbolOfNode(location)), name, meaning & 67901928)) { + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 236 /* InterfaceDeclaration */: + if (result = lookup(getMembersOfSymbol(getSymbolOfNode(location)), name, meaning & 67901928 /* Type */)) { if (!isTypeParameterSymbolDeclaredInContainer(result, location)) { + // ignore type parameters not declared in this container result = undefined; break; } - if (lastLocation && ts.hasModifier(lastLocation, 32)) { + if (lastLocation && ts.hasModifier(lastLocation, 32 /* Static */)) { + // TypeScript 1.0 spec (April 2014): 3.4.1 + // The scope of a type parameter extends over the entire declaration with which the type + // parameter list is associated, with the exception of static member declarations in classes. error(errorLocation, ts.Diagnostics.Static_members_cannot_reference_class_type_parameters); return undefined; } break loop; } - if (location.kind === 205 && meaning & 32) { + if (location.kind === 205 /* ClassExpression */ && meaning & 32 /* Class */) { var className = location.name; if (className && name === className.escapedText) { result = location.symbol; @@ -26083,10 +30287,11 @@ var ts; } } break; - case 207: - if (lastLocation === location.expression && location.parent.token === 85) { + case 207 /* ExpressionWithTypeArguments */: + // The type parameters of a class are not in scope in the base class expression. + if (lastLocation === location.expression && location.parent.token === 85 /* ExtendsKeyword */) { var container = location.parent.parent; - if (ts.isClassLike(container) && (result = lookup(getSymbolOfNode(container).members, name, meaning & 67901928))) { + if (ts.isClassLike(container) && (result = lookup(getSymbolOfNode(container).members, name, meaning & 67901928 /* Type */))) { if (nameNotFoundMessage) { error(errorLocation, ts.Diagnostics.Base_class_expressions_cannot_reference_class_type_parameters); } @@ -26094,33 +30299,42 @@ var ts; } } break; - case 147: + // It is not legal to reference a class's own type parameters from a computed property name that + // belongs to the class. For example: + // + // function foo() { return '' } + // class C { // <-- Class's own type parameter T + // [foo()]() { } // <-- Reference to T from class's own computed property + // } + // + case 147 /* ComputedPropertyName */: grandparent = location.parent.parent; - if (ts.isClassLike(grandparent) || grandparent.kind === 236) { - if (result = lookup(getSymbolOfNode(grandparent).members, name, meaning & 67901928)) { + if (ts.isClassLike(grandparent) || grandparent.kind === 236 /* InterfaceDeclaration */) { + // A reference to this grandparent's type parameters would be an error + if (result = lookup(getSymbolOfNode(grandparent).members, name, meaning & 67901928 /* Type */)) { error(errorLocation, ts.Diagnostics.A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type); return undefined; } } break; - case 154: - case 153: - case 155: - case 156: - case 157: - case 234: - case 193: - if (meaning & 3 && name === "arguments") { + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 234 /* FunctionDeclaration */: + case 193 /* ArrowFunction */: + if (meaning & 3 /* Variable */ && name === "arguments") { result = argumentsSymbol; break loop; } break; - case 192: - if (meaning & 3 && name === "arguments") { + case 192 /* FunctionExpression */: + if (meaning & 3 /* Variable */ && name === "arguments") { result = argumentsSymbol; break loop; } - if (meaning & 16) { + if (meaning & 16 /* Function */) { var functionName = location.name; if (functionName && name === functionName.escapedText) { result = location.symbol; @@ -26128,16 +30342,31 @@ var ts; } } break; - case 150: - if (location.parent && location.parent.kind === 149) { + case 150 /* Decorator */: + // Decorators are resolved at the class declaration. Resolving at the parameter + // or member would result in looking up locals in the method. + // + // function y() {} + // class C { + // method(@y x, y) {} // <-- decorator y should be resolved at the class declaration, not the parameter. + // } + // + if (location.parent && location.parent.kind === 149 /* Parameter */) { location = location.parent; } + // + // function y() {} + // class C { + // @y method(x, y) {} // <-- decorator y should be resolved at the class declaration, not the method. + // } + // if (location.parent && ts.isClassElement(location.parent)) { location = location.parent; } break; - case 298: - case 292: + case 298 /* JSDocTypedefTag */: + case 292 /* JSDocCallbackTag */: + // js type aliases do not resolve names from their host, so skip past it location = ts.getJSDocHost(location); break; } @@ -26147,12 +30376,15 @@ var ts; lastLocation = location; location = location.parent; } + // We just climbed up parents looking for the name, meaning that we started in a descendant node of `lastLocation`. + // If `result === lastSelfReferenceLocation.symbol`, that means that we are somewhere inside `lastSelfReferenceLocation` looking up a name, and resolving to `lastLocation` itself. + // That means that this is a self-reference of `lastLocation`, and shouldn't count this when considering whether `lastLocation` is used. if (isUse && result && (!lastSelfReferenceLocation || result !== lastSelfReferenceLocation.symbol)) { result.isReferenced |= meaning; } if (!result) { if (lastLocation) { - ts.Debug.assert(lastLocation.kind === 274); + ts.Debug.assert(lastLocation.kind === 274 /* SourceFile */); if (lastLocation.commonJsModuleIndicator && name === "exports") { return lastLocation.symbol; } @@ -26163,7 +30395,7 @@ var ts; } if (!result) { if (originalLocation && ts.isInJavaScriptFile(originalLocation) && originalLocation.parent) { - if (ts.isRequireCall(originalLocation.parent, false)) { + if (ts.isRequireCall(originalLocation.parent, /*checkArgumentIsStringLiteralLike*/ false)) { return requireSymbol; } if (ts.isIdentifier(originalLocation) && ts.isPropertyAccessExpression(originalLocation.parent) && @@ -26175,7 +30407,7 @@ var ts; if (!result) { if (nameNotFoundMessage) { if (!errorLocation || - !checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg) && + !checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg) && // TODO: GH#18217 !checkAndReportErrorForExtendingInterface(errorLocation) && !checkAndReportErrorForUsingTypeAsNamespace(errorLocation, name, meaning) && !checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) && @@ -26195,24 +30427,39 @@ var ts; } return undefined; } + // Perform extra checks only if error reporting was requested if (nameNotFoundMessage) { if (propertyWithInvalidInitializer) { + // We have a match, but the reference occurred within a property initializer and the identifier also binds + // to a local variable in the constructor where the code will be emitted. var propertyName = propertyWithInvalidInitializer.name; error(errorLocation, ts.Diagnostics.Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor, ts.declarationNameToString(propertyName), diagnosticName(nameArg)); return undefined; } + // Only check for block-scoped variable if we have an error location and are looking for the + // name with variable meaning + // For example, + // declare module foo { + // interface bar {} + // } + // const foo/*1*/: foo/*2*/.bar; + // The foo at /*1*/ and /*2*/ will share same symbol with two meanings: + // block-scoped variable and namespace module. However, only when we + // try to resolve name in /*1*/ which is used in variable position, + // we want to check for block-scoped if (errorLocation && - (meaning & 2 || - ((meaning & 32 || meaning & 384) && (meaning & 67216319) === 67216319))) { + (meaning & 2 /* BlockScopedVariable */ || + ((meaning & 32 /* Class */ || meaning & 384 /* Enum */) && (meaning & 67216319 /* Value */) === 67216319 /* Value */))) { var exportOrLocalSymbol = getExportSymbolOfValueSymbolIfExported(result); - if (exportOrLocalSymbol.flags & 2 || exportOrLocalSymbol.flags & 32 || exportOrLocalSymbol.flags & 384) { + if (exportOrLocalSymbol.flags & 2 /* BlockScopedVariable */ || exportOrLocalSymbol.flags & 32 /* Class */ || exportOrLocalSymbol.flags & 384 /* Enum */) { checkResolvedBlockScopedVariable(exportOrLocalSymbol, errorLocation); } } - if (result && isInExternalModule && (meaning & 67216319) === 67216319 && !(originalLocation.flags & 2097152)) { + // If we're in an external module, we can't reference value symbols created from UMD export declarations + if (result && isInExternalModule && (meaning & 67216319 /* Value */) === 67216319 /* Value */ && !(originalLocation.flags & 2097152 /* JSDoc */)) { var decls = result.declarations; - if (decls && decls.length === 1 && decls[0].kind === 242) { - error(errorLocation, ts.Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead, ts.unescapeLeadingUnderscores(name)); + if (decls && decls.length === 1 && decls[0].kind === 242 /* NamespaceExportDeclaration */) { + error(errorLocation, ts.Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead, ts.unescapeLeadingUnderscores(name)); // TODO: GH#18217 } } } @@ -26220,12 +30467,12 @@ var ts; } function isSelfReferenceLocation(node) { switch (node.kind) { - case 234: - case 235: - case 236: - case 238: - case 237: - case 239: + case 234 /* FunctionDeclaration */: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + case 238 /* EnumDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 239 /* ModuleDeclaration */: // For `namespace N { N; }` return true; default: return false; @@ -26237,10 +30484,10 @@ var ts; function isTypeParameterSymbolDeclaredInContainer(symbol, container) { for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var decl = _a[_i]; - if (decl.kind === 148) { + if (decl.kind === 148 /* TypeParameter */) { var parent = ts.isJSDocTemplateTag(decl.parent) ? ts.getJSDocHost(decl.parent) : decl.parent; if (parent === container) { - return !(ts.isJSDocTemplateTag(decl.parent) && ts.find(decl.parent.parent.tags, ts.isJSDocTypeAlias)); + return !(ts.isJSDocTemplateTag(decl.parent) && ts.find(decl.parent.parent.tags, ts.isJSDocTypeAlias)); // TODO: GH#18217 } } } @@ -26250,7 +30497,7 @@ var ts; if (!ts.isIdentifier(errorLocation) || errorLocation.escapedText !== name || isTypeReferenceIdentifier(errorLocation) || isInTypeQuery(errorLocation)) { return false; } - var container = ts.getThisContainer(errorLocation, false); + var container = ts.getThisContainer(errorLocation, /*includeArrowFunctions*/ false); var location = container; while (location) { if (ts.isClassLike(location.parent)) { @@ -26258,13 +30505,16 @@ var ts; if (!classSymbol) { break; } + // Check to see if a static member exists. var constructorType = getTypeOfSymbol(classSymbol); if (getPropertyOfType(constructorType, name)) { error(errorLocation, ts.Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0, diagnosticName(nameArg), symbolToString(classSymbol)); return true; } - if (location === container && !ts.hasModifier(location, 32)) { - var instanceType = getDeclaredTypeOfSymbol(classSymbol).thisType; + // No static member is present. + // Check if we're in an instance method and look for a relevant instance member. + if (location === container && !ts.hasModifier(location, 32 /* Static */)) { + var instanceType = getDeclaredTypeOfSymbol(classSymbol).thisType; // TODO: GH#18217 if (getPropertyOfType(instanceType, name)) { error(errorLocation, ts.Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, diagnosticName(nameArg)); return true; @@ -26277,29 +30527,34 @@ var ts; } function checkAndReportErrorForExtendingInterface(errorLocation) { var expression = getEntityNameForExtendingInterface(errorLocation); - if (expression && resolveEntityName(expression, 64, true)) { + if (expression && resolveEntityName(expression, 64 /* Interface */, /*ignoreErrors*/ true)) { error(errorLocation, ts.Diagnostics.Cannot_extend_an_interface_0_Did_you_mean_implements, ts.getTextOfNode(expression)); return true; } return false; } + /** + * Climbs up parents to an ExpressionWithTypeArguments, and returns its expression, + * but returns undefined if that expression is not an EntityNameExpression. + */ function getEntityNameForExtendingInterface(node) { switch (node.kind) { - case 71: - case 185: + case 71 /* Identifier */: + case 185 /* PropertyAccessExpression */: return node.parent ? getEntityNameForExtendingInterface(node.parent) : undefined; - case 207: + case 207 /* ExpressionWithTypeArguments */: if (ts.isEntityNameExpression(node.expression)) { return node.expression; } + // falls through default: return undefined; } } function checkAndReportErrorForUsingTypeAsNamespace(errorLocation, name, meaning) { - var namespaceMeaning = 1920 | (ts.isInJavaScriptFile(errorLocation) ? 67216319 : 0); + var namespaceMeaning = 1920 /* Namespace */ | (ts.isInJavaScriptFile(errorLocation) ? 67216319 /* Value */ : 0); if (meaning === namespaceMeaning) { - var symbol = resolveSymbol(resolveName(errorLocation, name, 67901928 & ~namespaceMeaning, undefined, undefined, false)); + var symbol = resolveSymbol(resolveName(errorLocation, name, 67901928 /* Type */ & ~namespaceMeaning, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)); var parent = errorLocation.parent; if (symbol) { if (ts.isQualifiedName(parent)) { @@ -26318,13 +30573,13 @@ var ts; return false; } function checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) { - if (meaning & (67216319 & ~1024)) { + if (meaning & (67216319 /* Value */ & ~1024 /* NamespaceModule */)) { if (name === "any" || name === "string" || name === "number" || name === "boolean" || name === "never") { error(errorLocation, ts.Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, ts.unescapeLeadingUnderscores(name)); return true; } - var symbol = resolveSymbol(resolveName(errorLocation, name, 67901928 & ~67216319, undefined, undefined, false)); - if (symbol && !(symbol.flags & 1024)) { + var symbol = resolveSymbol(resolveName(errorLocation, name, 67901928 /* Type */ & ~67216319 /* Value */, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)); + if (symbol && !(symbol.flags & 1024 /* NamespaceModule */)) { error(errorLocation, ts.Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, ts.unescapeLeadingUnderscores(name)); return true; } @@ -26332,15 +30587,15 @@ var ts; return false; } function checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation, name, meaning) { - if (meaning & (67216319 & ~1024 & ~67901928)) { - var symbol = resolveSymbol(resolveName(errorLocation, name, 1024 & ~67216319, undefined, undefined, false)); + if (meaning & (67216319 /* Value */ & ~1024 /* NamespaceModule */ & ~67901928 /* Type */)) { + var symbol = resolveSymbol(resolveName(errorLocation, name, 1024 /* NamespaceModule */ & ~67216319 /* Value */, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)); if (symbol) { error(errorLocation, ts.Diagnostics.Cannot_use_namespace_0_as_a_value, ts.unescapeLeadingUnderscores(name)); return true; } } - else if (meaning & (67901928 & ~1024 & ~67216319)) { - var symbol = resolveSymbol(resolveName(errorLocation, name, (512 | 1024) & ~67901928, undefined, undefined, false)); + else if (meaning & (67901928 /* Type */ & ~1024 /* NamespaceModule */ & ~67216319 /* Value */)) { + var symbol = resolveSymbol(resolveName(errorLocation, name, (512 /* ValueModule */ | 1024 /* NamespaceModule */) & ~67901928 /* Type */, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)); if (symbol) { error(errorLocation, ts.Diagnostics.Cannot_use_namespace_0_as_a_type, ts.unescapeLeadingUnderscores(name)); return true; @@ -26349,34 +30604,39 @@ var ts; return false; } function checkResolvedBlockScopedVariable(result, errorLocation) { - ts.Debug.assert(!!(result.flags & 2 || result.flags & 32 || result.flags & 384)); - var declaration = ts.forEach(result.declarations, function (d) { return ts.isBlockOrCatchScoped(d) || ts.isClassLike(d) || (d.kind === 238) ? d : undefined; }); + ts.Debug.assert(!!(result.flags & 2 /* BlockScopedVariable */ || result.flags & 32 /* Class */ || result.flags & 384 /* Enum */)); + // Block-scoped variables cannot be used before their definition + var declaration = ts.forEach(result.declarations, function (d) { return ts.isBlockOrCatchScoped(d) || ts.isClassLike(d) || (d.kind === 238 /* EnumDeclaration */) ? d : undefined; }); if (declaration === undefined) return ts.Debug.fail("Declaration to checkResolvedBlockScopedVariable is undefined"); - if (!(declaration.flags & 4194304) && !isBlockScopedNameDeclaredBeforeUse(declaration, errorLocation)) { - if (result.flags & 2) { + if (!(declaration.flags & 4194304 /* Ambient */) && !isBlockScopedNameDeclaredBeforeUse(declaration, errorLocation)) { + if (result.flags & 2 /* BlockScopedVariable */) { error(errorLocation, ts.Diagnostics.Block_scoped_variable_0_used_before_its_declaration, ts.declarationNameToString(ts.getNameOfDeclaration(declaration))); } - else if (result.flags & 32) { + else if (result.flags & 32 /* Class */) { error(errorLocation, ts.Diagnostics.Class_0_used_before_its_declaration, ts.declarationNameToString(ts.getNameOfDeclaration(declaration))); } - else if (result.flags & 256) { + else if (result.flags & 256 /* RegularEnum */) { error(errorLocation, ts.Diagnostics.Enum_0_used_before_its_declaration, ts.declarationNameToString(ts.getNameOfDeclaration(declaration))); } } } + /* Starting from 'initial' node walk up the parent chain until 'stopAt' node is reached. + * If at any point current node is equal to 'parent' node - return true. + * Return false if 'stopAt' node is reached or isFunctionLike(current) === true. + */ function isSameScopeDescendentOf(initial, parent, stopAt) { return !!parent && !!ts.findAncestor(initial, function (n) { return n === stopAt || ts.isFunctionLike(n) ? "quit" : n === parent; }); } function getAnyImportSyntax(node) { switch (node.kind) { - case 243: + case 243 /* ImportEqualsDeclaration */: return node; - case 245: + case 245 /* ImportClause */: return node.parent; - case 246: + case 246 /* NamespaceImport */: return node.parent.parent; - case 248: + case 248 /* ImportSpecifier */: return node.parent.parent.parent; default: return undefined; @@ -26386,37 +30646,48 @@ var ts; return ts.find(symbol.declarations, ts.isAliasSymbolDeclaration); } function getTargetOfImportEqualsDeclaration(node, dontResolveAlias) { - if (node.moduleReference.kind === 254) { + if (node.moduleReference.kind === 254 /* ExternalModuleReference */) { return resolveExternalModuleSymbol(resolveExternalModuleName(node, ts.getExternalModuleImportEqualsDeclarationExpression(node))); } return getSymbolOfPartOfRightHandSideOfImportEquals(node.moduleReference, dontResolveAlias); } function resolveExportByName(moduleSymbol, name, dontResolveAlias) { - var exportValue = moduleSymbol.exports.get("export="); + var exportValue = moduleSymbol.exports.get("export=" /* ExportEquals */); return exportValue ? getPropertyOfType(getTypeOfSymbol(exportValue), name) : resolveSymbol(moduleSymbol.exports.get(name), dontResolveAlias); } function isSyntacticDefault(node) { - return ((ts.isExportAssignment(node) && !node.isExportEquals) || ts.hasModifier(node, 512) || ts.isExportSpecifier(node)); + return ((ts.isExportAssignment(node) && !node.isExportEquals) || ts.hasModifier(node, 512 /* Default */) || ts.isExportSpecifier(node)); } function canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias) { if (!allowSyntheticDefaultImports) { return false; } + // Declaration files (and ambient modules) if (!file || file.isDeclarationFile) { - var defaultExportSymbol = resolveExportByName(moduleSymbol, "default", true); + // Definitely cannot have a synthetic default if they have a syntactic default member specified + var defaultExportSymbol = resolveExportByName(moduleSymbol, "default" /* Default */, /*dontResolveAlias*/ true); // Dont resolve alias because we want the immediately exported symbol's declaration if (defaultExportSymbol && ts.some(defaultExportSymbol.declarations, isSyntacticDefault)) { return false; } + // It _might_ still be incorrect to assume there is no __esModule marker on the import at runtime, even if there is no `default` member + // So we check a bit more, if (resolveExportByName(moduleSymbol, ts.escapeLeadingUnderscores("__esModule"), dontResolveAlias)) { + // If there is an `__esModule` specified in the declaration (meaning someone explicitly added it or wrote it in their code), + // it definitely is a module and does not have a synthetic default return false; } + // There are _many_ declaration files not written with esmodules in mind that still get compiled into a format with __esModule set + // Meaning there may be no default at runtime - however to be on the permissive side, we allow access to a synthetic default member + // as there is no marker to indicate if the accompanying JS has `__esModule` or not, or is even native esm return true; } + // TypeScript files never have a synthetic default (as they are always emitted with an __esModule marker) _unless_ they contain an export= statement if (!ts.isSourceFileJavaScript(file)) { return hasExportAssignmentSymbol(moduleSymbol); } + // JS files have a synthetic default if they do not contain ES2015+ module syntax (export = is not valid in js) _and_ do not have an __esModule marker return !file.externalModuleIndicator && !resolveExportByName(moduleSymbol, ts.escapeLeadingUnderscores("__esModule"), dontResolveAlias); } function getTargetOfImportClause(node, dontResolveAlias) { @@ -26427,7 +30698,7 @@ var ts; exportDefaultSymbol = moduleSymbol; } else { - exportDefaultSymbol = resolveExportByName(moduleSymbol, "default", dontResolveAlias); + exportDefaultSymbol = resolveExportByName(moduleSymbol, "default" /* Default */, dontResolveAlias); } var file = ts.find(moduleSymbol.declarations, ts.isSourceFile); var hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias); @@ -26435,6 +30706,7 @@ var ts; error(node.name, ts.Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol)); } else if (hasSyntheticDefault) { + // per emit behavior, a synthetic default overrides a "real" .default member if `__esModule` is not present return resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias); } return exportDefaultSymbol; @@ -26444,11 +30716,29 @@ var ts; var moduleSpecifier = node.parent.parent.moduleSpecifier; return resolveESModuleSymbol(resolveExternalModuleName(node, moduleSpecifier), moduleSpecifier, dontResolveAlias); } + // This function creates a synthetic symbol that combines the value side of one symbol with the + // type/namespace side of another symbol. Consider this example: + // + // declare module graphics { + // interface Point { + // x: number; + // y: number; + // } + // } + // declare var graphics: { + // Point: new (x: number, y: number) => graphics.Point; + // } + // declare module "graphics" { + // export = graphics; + // } + // + // An 'import { Point } from "graphics"' needs to create a symbol that combines the value side 'Point' + // property with the type/namespace side interface 'Point'. function combineValueAndTypeSymbols(valueSymbol, typeSymbol) { if (valueSymbol === unknownSymbol && typeSymbol === unknownSymbol) { return unknownSymbol; } - if (valueSymbol.flags & (67901928 | 1920)) { + if (valueSymbol.flags & (67901928 /* Type */ | 1920 /* Namespace */)) { return valueSymbol; } var result = createSymbol(valueSymbol.flags | typeSymbol.flags, valueSymbol.escapedName); @@ -26463,21 +30753,21 @@ var ts; return result; } function getExportOfModule(symbol, name, dontResolveAlias) { - if (symbol.flags & 1536) { + if (symbol.flags & 1536 /* Module */) { return resolveSymbol(getExportsOfSymbol(symbol).get(name), dontResolveAlias); } } function getPropertyOfVariable(symbol, name) { - if (symbol.flags & 3) { + if (symbol.flags & 3 /* Variable */) { var typeAnnotation = symbol.valueDeclaration.type; if (typeAnnotation) { - return resolveSymbol(getPropertyOfType(getTypeFromTypeNode(typeAnnotation), name)); + return resolveSymbol(getPropertyOfType(getTypeFromTypeNode(typeAnnotation), name)); // TODO: GH#18217 } } } function getExternalModuleMember(node, specifier, dontResolveAlias) { if (dontResolveAlias === void 0) { dontResolveAlias = false; } - var moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier); + var moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier); // TODO: GH#18217 var targetSymbol = resolveESModuleSymbol(moduleSymbol, node.moduleSpecifier, dontResolveAlias); if (targetSymbol) { var name = specifier.propertyName || specifier.name; @@ -26486,15 +30776,18 @@ var ts; return moduleSymbol; } var symbolFromVariable = void 0; - if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get("export=")) { + // First check if module was specified with "export=". If so, get the member from the resolved type + if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get("export=" /* ExportEquals */)) { symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name.escapedText); } else { symbolFromVariable = getPropertyOfVariable(targetSymbol, name.escapedText); } + // if symbolFromVariable is export - get its final target symbolFromVariable = resolveSymbol(symbolFromVariable, dontResolveAlias); var symbolFromModule = getExportOfModule(targetSymbol, name.escapedText, dontResolveAlias); - if (!symbolFromModule && allowSyntheticDefaultImports && name.escapedText === "default") { + // If the export member we're looking for is default, and there is no real default but allowSyntheticDefaultImports is on, return the entire module as the default + if (!symbolFromModule && allowSyntheticDefaultImports && name.escapedText === "default" /* Default */) { symbolFromModule = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias); } var symbol = symbolFromModule && symbolFromVariable && symbolFromModule !== symbolFromVariable ? @@ -26524,14 +30817,14 @@ var ts; function getTargetOfExportSpecifier(node, meaning, dontResolveAlias) { return node.parent.parent.moduleSpecifier ? getExternalModuleMember(node.parent.parent, node, dontResolveAlias) : - resolveEntityName(node.propertyName || node.name, meaning, false, dontResolveAlias); + resolveEntityName(node.propertyName || node.name, meaning, /*ignoreErrors*/ false, dontResolveAlias); } function getTargetOfExportAssignment(node, dontResolveAlias) { var expression = (ts.isExportAssignment(node) ? node.expression : node.right); if (ts.isClassExpression(expression)) { return checkExpression(expression).symbol; } - var aliasLike = resolveEntityName(expression, 67216319 | 67901928 | 1920, true, dontResolveAlias); + var aliasLike = resolveEntityName(expression, 67216319 /* Value */ | 67901928 /* Type */ | 1920 /* Namespace */, /*ignoreErrors*/ true, dontResolveAlias); if (aliasLike) { return aliasLike; } @@ -26541,36 +30834,40 @@ var ts; function getTargetOfAliasDeclaration(node, dontRecursivelyResolve) { if (dontRecursivelyResolve === void 0) { dontRecursivelyResolve = false; } switch (node.kind) { - case 243: + case 243 /* ImportEqualsDeclaration */: return getTargetOfImportEqualsDeclaration(node, dontRecursivelyResolve); - case 245: + case 245 /* ImportClause */: return getTargetOfImportClause(node, dontRecursivelyResolve); - case 246: + case 246 /* NamespaceImport */: return getTargetOfNamespaceImport(node, dontRecursivelyResolve); - case 248: + case 248 /* ImportSpecifier */: return getTargetOfImportSpecifier(node, dontRecursivelyResolve); - case 252: - return getTargetOfExportSpecifier(node, 67216319 | 67901928 | 1920, dontRecursivelyResolve); - case 249: - case 200: + case 252 /* ExportSpecifier */: + return getTargetOfExportSpecifier(node, 67216319 /* Value */ | 67901928 /* Type */ | 1920 /* Namespace */, dontRecursivelyResolve); + case 249 /* ExportAssignment */: + case 200 /* BinaryExpression */: return getTargetOfExportAssignment(node, dontRecursivelyResolve); - case 242: + case 242 /* NamespaceExportDeclaration */: return getTargetOfNamespaceExportDeclaration(node, dontRecursivelyResolve); default: return ts.Debug.fail(); } } + /** + * Indicates that a symbol is an alias that does not merge with a local declaration. + * OR Is a JSContainer which may merge an alias with a local declaration + */ function isNonLocalAlias(symbol, excludes) { - if (excludes === void 0) { excludes = 67216319 | 67901928 | 1920; } + if (excludes === void 0) { excludes = 67216319 /* Value */ | 67901928 /* Type */ | 1920 /* Namespace */; } if (!symbol) return false; - return (symbol.flags & (2097152 | excludes)) === 2097152 || !!(symbol.flags & 2097152 && symbol.flags & 67108864); + return (symbol.flags & (2097152 /* Alias */ | excludes)) === 2097152 /* Alias */ || !!(symbol.flags & 2097152 /* Alias */ && symbol.flags & 67108864 /* JSContainer */); } function resolveSymbol(symbol, dontResolveAlias) { return !dontResolveAlias && isNonLocalAlias(symbol) ? resolveAlias(symbol) : symbol; } function resolveAlias(symbol) { - ts.Debug.assert((symbol.flags & 2097152) !== 0, "Should only get Alias here."); + ts.Debug.assert((symbol.flags & 2097152 /* Alias */) !== 0, "Should only get Alias here."); var links = getSymbolLinks(symbol); if (!links.target) { links.target = resolvingSymbol; @@ -26595,12 +30892,15 @@ var ts; var target = resolveAlias(symbol); if (target) { var markAlias = target === unknownSymbol || - ((target.flags & 67216319) && !isConstEnumOrConstEnumOnlyModule(target)); + ((target.flags & 67216319 /* Value */) && !isConstEnumOrConstEnumOnlyModule(target)); if (markAlias) { markAliasSymbolAsReferenced(symbol); } } } + // When an alias symbol is referenced, we need to mark the entity it references as referenced and in turn repeat that until + // we reach a non-alias or an exported entity (which is always considered referenced). We do this by checking the target of + // the alias as an expression (which recursively takes us back here if the target references another alias). function markAliasSymbolAsReferenced(symbol) { var links = getSymbolLinks(symbol); if (!links.referenced) { @@ -26608,50 +30908,66 @@ var ts; var node = getDeclarationOfAliasSymbol(symbol); if (!node) return ts.Debug.fail(); - if (node.kind === 249) { + if (node.kind === 249 /* ExportAssignment */) { + // export default checkExpressionCached(node.expression); } - else if (node.kind === 252) { + else if (node.kind === 252 /* ExportSpecifier */) { + // export { } or export { as foo } checkExpressionCached(node.propertyName || node.name); } else if (ts.isInternalModuleImportEqualsDeclaration(node)) { + // import foo = checkExpressionCached(node.moduleReference); } } } + // This function is only for imports with entity names function getSymbolOfPartOfRightHandSideOfImportEquals(entityName, dontResolveAlias) { - if (entityName.kind === 71 && ts.isRightSideOfQualifiedNameOrPropertyAccess(entityName)) { + // There are three things we might try to look for. In the following examples, + // the search term is enclosed in |...|: + // + // import a = |b|; // Namespace + // import a = |b.c|; // Value, type, namespace + // import a = |b.c|.d; // Namespace + if (entityName.kind === 71 /* Identifier */ && ts.isRightSideOfQualifiedNameOrPropertyAccess(entityName)) { entityName = entityName.parent; } - if (entityName.kind === 71 || entityName.parent.kind === 146) { - return resolveEntityName(entityName, 1920, false, dontResolveAlias); + // Check for case 1 and 3 in the above example + if (entityName.kind === 71 /* Identifier */ || entityName.parent.kind === 146 /* QualifiedName */) { + return resolveEntityName(entityName, 1920 /* Namespace */, /*ignoreErrors*/ false, dontResolveAlias); } else { - ts.Debug.assert(entityName.parent.kind === 243); - return resolveEntityName(entityName, 67216319 | 67901928 | 1920, false, dontResolveAlias); + // Case 2 in above example + // entityName.kind could be a QualifiedName or a Missing identifier + ts.Debug.assert(entityName.parent.kind === 243 /* ImportEqualsDeclaration */); + return resolveEntityName(entityName, 67216319 /* Value */ | 67901928 /* Type */ | 1920 /* Namespace */, /*ignoreErrors*/ false, dontResolveAlias); } } function getFullyQualifiedName(symbol) { return symbol.parent ? getFullyQualifiedName(symbol.parent) + "." + symbolToString(symbol) : symbolToString(symbol); } + /** + * Resolves a qualified name and any involved aliases. + */ function resolveEntityName(name, meaning, ignoreErrors, dontResolveAlias, location) { if (ts.nodeIsMissing(name)) { return undefined; } - var namespaceMeaning = 1920 | (ts.isInJavaScriptFile(name) ? meaning & 67216319 : 0); + var namespaceMeaning = 1920 /* Namespace */ | (ts.isInJavaScriptFile(name) ? meaning & 67216319 /* Value */ : 0); var symbol; - if (name.kind === 71) { + if (name.kind === 71 /* Identifier */) { var message = meaning === namespaceMeaning ? ts.Diagnostics.Cannot_find_namespace_0 : ts.Diagnostics.Cannot_find_name_0; var symbolFromJSPrototype = ts.isInJavaScriptFile(name) ? resolveEntityNameFromJSSpecialAssignment(name, meaning) : undefined; - symbol = resolveName(location || name, name.escapedText, meaning, ignoreErrors || symbolFromJSPrototype ? undefined : message, name, true); + symbol = resolveName(location || name, name.escapedText, meaning, ignoreErrors || symbolFromJSPrototype ? undefined : message, name, /*isUse*/ true); if (!symbol) { return symbolFromJSPrototype; } } - else if (name.kind === 146 || name.kind === 185) { - var left = name.kind === 146 ? name.left : name.expression; - var right = name.kind === 146 ? name.right : name.name; - var namespace = resolveEntityName(left, namespaceMeaning, ignoreErrors, false, location); + else if (name.kind === 146 /* QualifiedName */ || name.kind === 185 /* PropertyAccessExpression */) { + var left = name.kind === 146 /* QualifiedName */ ? name.left : name.expression; + var right = name.kind === 146 /* QualifiedName */ ? name.right : name.name; + var namespace = resolveEntityName(left, namespaceMeaning, ignoreErrors, /*dontResolveAlias*/ false, location); if (!namespace || ts.nodeIsMissing(right)) { return undefined; } @@ -26684,26 +31000,32 @@ var ts; else { throw ts.Debug.assertNever(name, "Unknown entity name kind."); } - ts.Debug.assert((ts.getCheckFlags(symbol) & 1) === 0, "Should never get an instantiated symbol here."); + ts.Debug.assert((ts.getCheckFlags(symbol) & 1 /* Instantiated */) === 0, "Should never get an instantiated symbol here."); return (symbol.flags & meaning) || dontResolveAlias ? symbol : resolveAlias(symbol); } + /** + * 1. For prototype-property methods like `A.prototype.m = function () ...`, try to resolve names in the scope of `A` too. + * Note that prototype-property assignment to locations outside the current file (eg globals) doesn't work, so + * name resolution won't work either. + * 2. For property assignments like `{ x: function f () { } }`, try to resolve names in the scope of `f` too. + */ function resolveEntityNameFromJSSpecialAssignment(name, meaning) { if (isJSDocTypeReference(name.parent)) { var secondaryLocation = getJSSpecialAssignmentLocation(name.parent); if (secondaryLocation) { - return resolveName(secondaryLocation, name.escapedText, meaning, undefined, name, true); + return resolveName(secondaryLocation, name.escapedText, meaning, /*nameNotFoundMessage*/ undefined, name, /*isUse*/ true); } } } function getJSSpecialAssignmentLocation(node) { - var typeAlias = ts.findAncestor(node, function (node) { return !(ts.isJSDocNode(node) || node.flags & 2097152) ? "quit" : ts.isJSDocTypeAlias(node); }); + var typeAlias = ts.findAncestor(node, function (node) { return !(ts.isJSDocNode(node) || node.flags & 2097152 /* JSDoc */) ? "quit" : ts.isJSDocTypeAlias(node); }); if (typeAlias) { return; } var host = ts.getJSDocHost(node); if (ts.isExpressionStatement(host) && ts.isBinaryExpression(host.expression) && - ts.getSpecialPropertyAssignmentKind(host.expression) === 3) { + ts.getSpecialPropertyAssignmentKind(host.expression) === 3 /* PrototypeProperty */) { var symbol = getSymbolOfNode(host.expression.left); return symbol && symbol.parent.valueDeclaration; } @@ -26732,22 +31054,24 @@ var ts; var withoutAtTypePrefix = ts.removePrefix(moduleReference, "@types/"); error(errorNode, diag, withoutAtTypePrefix, moduleReference); } - var ambientModule = tryFindAmbientModule(moduleReference, true); + var ambientModule = tryFindAmbientModule(moduleReference, /*withAugmentations*/ true); if (ambientModule) { return ambientModule; } var currentSourceFile = ts.getSourceFileOfNode(location); - var resolvedModule = ts.getResolvedModule(currentSourceFile, moduleReference); + var resolvedModule = ts.getResolvedModule(currentSourceFile, moduleReference); // TODO: GH#18217 var resolutionDiagnostic = resolvedModule && ts.getResolutionDiagnostic(compilerOptions, resolvedModule); var sourceFile = resolvedModule && !resolutionDiagnostic && host.getSourceFile(resolvedModule.resolvedFileName); if (sourceFile) { if (sourceFile.symbol) { if (resolvedModule.isExternalLibraryImport && !ts.extensionIsTypeScript(resolvedModule.extension)) { - errorOnImplicitAnyModule(false, errorNode, resolvedModule, moduleReference); + errorOnImplicitAnyModule(/*isError*/ false, errorNode, resolvedModule, moduleReference); } + // merged symbol is module declaration symbol combined with all augmentations return getMergedSymbol(sourceFile.symbol); } if (moduleNotFoundError) { + // report errors only if it was requested error(errorNode, ts.Diagnostics.File_0_is_not_a_module, sourceFile.fileName); } return undefined; @@ -26758,23 +31082,26 @@ var ts; return getMergedSymbol(pattern.symbol); } } + // May be an untyped module. If so, ignore resolutionDiagnostic. if (resolvedModule && !ts.resolutionExtensionIsTypeScriptOrJson(resolvedModule.extension) && resolutionDiagnostic === undefined || resolutionDiagnostic === ts.Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type) { if (isForAugmentation) { var diag = ts.Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented; error(errorNode, diag, moduleReference, resolvedModule.resolvedFileName); } else { - errorOnImplicitAnyModule(noImplicitAny && !!moduleNotFoundError, errorNode, resolvedModule, moduleReference); + errorOnImplicitAnyModule(/*isError*/ noImplicitAny && !!moduleNotFoundError, errorNode, resolvedModule, moduleReference); } + // Failed imports and untyped modules are both treated in an untyped manner; only difference is whether we give a diagnostic first. return undefined; } if (moduleNotFoundError) { + // For relative paths, see if this was possibly a projectReference redirect if (ts.pathIsRelative(moduleReference)) { var sourceFile_1 = ts.getSourceFileOfNode(location); var redirects = sourceFile_1.redirectedReferences; if (redirects) { var normalizedTargetPath = ts.getNormalizedAbsolutePath(moduleReference, ts.getDirectoryPath(sourceFile_1.fileName)); - for (var _i = 0, _a = [".ts", ".tsx"]; _i < _a.length; _i++) { + for (var _i = 0, _a = [".ts" /* Ts */, ".tsx" /* Tsx */]; _i < _a.length; _i++) { var ext = _a[_i]; var probePath = normalizedTargetPath + ext; if (redirects.indexOf(probePath) >= 0) { @@ -26802,11 +31129,12 @@ var ts; } function errorOnImplicitAnyModule(isError, errorNode, _a, moduleReference) { var packageId = _a.packageId, resolvedFileName = _a.resolvedFileName; - var errorInfo = packageId && ts.chainDiagnosticMessages(undefined, ts.Diagnostics.Try_npm_install_types_Slash_0_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_module_0, ts.getMangledNameForScopedPackage(packageId.name)); + var errorInfo = packageId && ts.chainDiagnosticMessages( + /*details*/ undefined, ts.Diagnostics.Try_npm_install_types_Slash_0_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_module_0, ts.getMangledNameForScopedPackage(packageId.name)); errorOrSuggestion(isError, errorNode, ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type, moduleReference, resolvedFileName)); } function resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) { - return moduleSymbol && getMergedSymbol(getCommonJsExportEquals(resolveSymbol(moduleSymbol.exports.get("export="), dontResolveAlias), moduleSymbol)) || moduleSymbol; + return moduleSymbol && getMergedSymbol(getCommonJsExportEquals(resolveSymbol(moduleSymbol.exports.get("export=" /* ExportEquals */), dontResolveAlias), moduleSymbol)) || moduleSymbol; } function getCommonJsExportEquals(exported, moduleSymbol) { if (!exported || moduleSymbol.exports.size === 1) { @@ -26814,20 +31142,23 @@ var ts; } var merged = cloneSymbol(exported); if (merged.exports === undefined) { - merged.flags = merged.flags | 512; + merged.flags = merged.flags | 512 /* ValueModule */; merged.exports = ts.createSymbolTable(); } moduleSymbol.exports.forEach(function (s, name) { - if (name === "export=") + if (name === "export=" /* ExportEquals */) return; merged.exports.set(name, merged.exports.has(name) ? mergeSymbol(merged.exports.get(name), s) : s); }); return merged; } + // An external module with an 'export =' declaration may be referenced as an ES6 module provided the 'export =' + // references a symbol that is at least declared as a module or a variable. The target of the 'export =' may + // combine other declarations with the module or variable (e.g. a class/module, function/module, interface/variable). function resolveESModuleSymbol(moduleSymbol, referencingLocation, dontResolveAlias) { var symbol = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias); if (!dontResolveAlias && symbol) { - if (!(symbol.flags & (1536 | 3))) { + if (!(symbol.flags & (1536 /* Module */ | 3 /* Variable */))) { error(referencingLocation, ts.Diagnostics.Module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct, symbolToString(moduleSymbol)); return symbol; } @@ -26836,12 +31167,13 @@ var ts; if ((ts.isImportDeclaration(referenceParent) && ts.getNamespaceDeclarationNode(referenceParent)) || ts.isImportCall(referenceParent)) { var type = getTypeOfSymbol(symbol); - var sigs = getSignaturesOfStructuredType(type, 0); + var sigs = getSignaturesOfStructuredType(type, 0 /* Call */); if (!sigs || !sigs.length) { - sigs = getSignaturesOfStructuredType(type, 1); + sigs = getSignaturesOfStructuredType(type, 1 /* Construct */); } if (sigs && sigs.length) { var moduleType = getTypeWithSyntheticDefaultImportType(type, symbol, moduleSymbol); + // Create a new symbol which has the module's type less the call and construct signatures var result = createSymbol(symbol.flags, symbol.escapedName); result.declarations = symbol.declarations ? symbol.declarations.slice() : []; result.parent = symbol.parent; @@ -26855,7 +31187,7 @@ var ts; result.members = ts.cloneMap(symbol.members); if (symbol.exports) result.exports = ts.cloneMap(symbol.exports); - var resolvedModuleType = resolveStructuredTypeMembers(moduleType); + var resolvedModuleType = resolveStructuredTypeMembers(moduleType); // Should already be resolved from the signature checks above result.type = createAnonymousType(result, resolvedModuleType.members, ts.emptyArray, ts.emptyArray, resolvedModuleType.stringIndexInfo, resolvedModuleType.numberIndexInfo); return result; } @@ -26865,7 +31197,7 @@ var ts; return symbol; } function hasExportAssignmentSymbol(moduleSymbol) { - return moduleSymbol.exports.get("export=") !== undefined; + return moduleSymbol.exports.get("export=" /* ExportEquals */) !== undefined; } function getExportsOfModuleAsArray(moduleSymbol) { return symbolsToArray(getExportsOfModule(moduleSymbol)); @@ -26894,22 +31226,26 @@ var ts; return undefined; } var type = getTypeOfSymbol(exportEquals); - return type.flags & 32764 ? undefined : getPropertyOfType(type, memberName); + return type.flags & 32764 /* Primitive */ ? undefined : getPropertyOfType(type, memberName); } function getExportsOfSymbol(symbol) { - return symbol.flags & 32 ? getResolvedMembersOrExportsOfSymbol(symbol, "resolvedExports") : - symbol.flags & 1536 ? getExportsOfModule(symbol) : + return symbol.flags & 32 /* Class */ ? getResolvedMembersOrExportsOfSymbol(symbol, "resolvedExports" /* resolvedExports */) : + symbol.flags & 1536 /* Module */ ? getExportsOfModule(symbol) : symbol.exports || emptySymbols; } function getExportsOfModule(moduleSymbol) { var links = getSymbolLinks(moduleSymbol); return links.resolvedExports || (links.resolvedExports = getExportsOfModuleWorker(moduleSymbol)); } + /** + * Extends one symbol table with another while collecting information on name collisions for error message generation into the `lookupTable` argument + * Not passing `lookupTable` and `exportNode` disables this collection, and just extends the tables + */ function extendExportSymbols(target, source, lookupTable, exportNode) { if (!source) return; source.forEach(function (sourceSymbol, id) { - if (id === "default") + if (id === "default" /* Default */) return; var targetSymbol = target.get(id); if (!targetSymbol) { @@ -26933,14 +31269,18 @@ var ts; } function getExportsOfModuleWorker(moduleSymbol) { var visitedSymbols = []; + // A module defined by an 'export=' consists on one export that needs to be resolved moduleSymbol = resolveExternalModuleSymbol(moduleSymbol); return visit(moduleSymbol) || emptySymbols; + // The ES6 spec permits export * declarations in a module to circularly reference the module itself. For example, + // module 'a' can 'export * from "b"' and 'b' can 'export * from "a"' without error. function visit(symbol) { - if (!(symbol && symbol.flags & 1955 && ts.pushIfUnique(visitedSymbols, symbol))) { + if (!(symbol && symbol.flags & 1955 /* HasExports */ && ts.pushIfUnique(visitedSymbols, symbol))) { return; } var symbols = ts.cloneMap(symbol.exports); - var exportStars = symbol.exports.get("__export"); + // All export * declarations are collected in an __export symbol by the binder + var exportStars = symbol.exports.get("__export" /* ExportStar */); if (exportStars) { var nestedSymbols = ts.createSymbolTable(); var lookupTable_1 = ts.createMap(); @@ -26952,6 +31292,7 @@ var ts; } lookupTable_1.forEach(function (_a, id) { var exportsWithDuplicate = _a.exportsWithDuplicate; + // It's not an error if the file with multiple `export *`s with duplicate names exports a member with that name itself if (id === "export=" || !(exportsWithDuplicate && exportsWithDuplicate.length) || symbols.has(id)) { return; } @@ -26975,6 +31316,10 @@ var ts; function getParentOfSymbol(symbol) { return getMergedSymbol(symbol.parent && getLateBoundSymbol(symbol.parent)); } + /** + * Attempts to find the symbol corresponding to the container a symbol is in - usually this + * is just its' `.parent`, but for locals, this value is `undefined` + */ function getContainerOfSymbol(symbol) { var container = getParentOfSymbol(symbol); if (container) { @@ -26989,6 +31334,7 @@ var ts; } function getAliasForSymbolInContainer(container, symbol) { if (container === getParentOfSymbol(symbol)) { + // fast path, `symbol` is either already the alias or isn't aliased return symbol; } var exports = getExportsOfSymbol(container); @@ -27008,18 +31354,18 @@ var ts; } } function getExportSymbolOfValueSymbolIfExported(symbol) { - return symbol && (symbol.flags & 1048576) !== 0 + return symbol && (symbol.flags & 1048576 /* ExportValue */) !== 0 ? getMergedSymbol(symbol.exportSymbol) : symbol; } function symbolIsValue(symbol) { - return !!(symbol.flags & 67216319 || symbol.flags & 2097152 && resolveAlias(symbol).flags & 67216319); + return !!(symbol.flags & 67216319 /* Value */ || symbol.flags & 2097152 /* Alias */ && resolveAlias(symbol).flags & 67216319 /* Value */); } function findConstructorDeclaration(node) { var members = node.members; for (var _i = 0, members_2 = members; _i < members_2.length; _i++) { var member = members_2[_i]; - if (member.kind === 155 && ts.nodeIsPresent(member.body)) { + if (member.kind === 155 /* Constructor */ && ts.nodeIsPresent(member.body)) { return member; } } @@ -27037,12 +31383,12 @@ var ts; } function createBooleanType(trueFalseTypes) { var type = getUnionType(trueFalseTypes); - type.flags |= 16; + type.flags |= 16 /* Boolean */; type.intrinsicName = "boolean"; return type; } function createObjectType(objectFlags, symbol) { - var type = createType(131072); + var type = createType(131072 /* Object */); type.objectFlags = objectFlags; type.symbol = symbol; return type; @@ -27050,11 +31396,15 @@ var ts; function createTypeofType() { return getUnionType(ts.arrayFrom(typeofEQFacts.keys(), getLiteralType)); } + // A reserved member name starts with two underscores, but the third character cannot be an underscore + // or the @ symbol. A third underscore indicates an escaped form of an identifer that started + // with at least two underscores. The @ character indicates that the name is denoted by a well known ES + // Symbol instance. function isReservedMemberName(name) { - return name.charCodeAt(0) === 95 && - name.charCodeAt(1) === 95 && - name.charCodeAt(2) !== 95 && - name.charCodeAt(2) !== 64; + return name.charCodeAt(0) === 95 /* _ */ && + name.charCodeAt(1) === 95 /* _ */ && + name.charCodeAt(2) !== 95 /* _ */ && + name.charCodeAt(2) !== 64 /* at */; } function getNamedMembers(members) { var result; @@ -27081,22 +31431,24 @@ var ts; return type; } function createAnonymousType(symbol, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo) { - return setStructuredTypeMembers(createObjectType(16, symbol), members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); + return setStructuredTypeMembers(createObjectType(16 /* Anonymous */, symbol), members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); } function forEachSymbolTableInScope(enclosingDeclaration, callback) { var result; for (var location = enclosingDeclaration; location; location = location.parent) { + // Locals of a source file are not in scope (because they get merged into the global symbol table) if (location.locals && !isGlobalSourceFile(location)) { if (result = callback(location.locals)) { return result; } } switch (location.kind) { - case 274: + case 274 /* SourceFile */: if (!ts.isExternalOrCommonJsModule(location)) { break; } - case 239: + // falls through + case 239 /* ModuleDeclaration */: if (result = callback(getSymbolOfNode(location).exports)) { return result; } @@ -27106,7 +31458,8 @@ var ts; return callback(globals); } function getQualifiedLeftMeaning(rightMeaning) { - return rightMeaning === 67216319 ? 67216319 : 1920; + // If we are looking in value space, the parent meaning is value, other wise it is namespace + return rightMeaning === 67216319 /* Value */ ? 67216319 /* Value */ : 1920 /* Namespace */; } function getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning, useOnlyExternalAliasing, visitedSymbolTablesMap) { if (visitedSymbolTablesMap === void 0) { visitedSymbolTablesMap = ts.createMap(); } @@ -27119,6 +31472,9 @@ var ts; visitedSymbolTablesMap.set(id, visitedSymbolTables = []); } return forEachSymbolTableInScope(enclosingDeclaration, getAccessibleSymbolChainFromSymbolTable); + /** + * @param {ignoreQualification} boolean Set when a symbol is being looked for through the exports of another symbol (meaning we have a route to qualify it already) + */ function getAccessibleSymbolChainFromSymbolTable(symbols, ignoreQualification) { if (!ts.pushIfUnique(visitedSymbolTables, symbols)) { return undefined; @@ -27128,36 +31484,46 @@ var ts; return result; } function canQualifySymbol(symbolFromSymbolTable, meaning) { + // If the symbol is equivalent and doesn't need further qualification, this symbol is accessible return !needsQualification(symbolFromSymbolTable, enclosingDeclaration, meaning) || + // If symbol needs qualification, make sure that parent is accessible, if it is then this symbol is accessible too !!getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing, visitedSymbolTablesMap); } function isAccessible(symbolFromSymbolTable, resolvedAliasSymbol, ignoreQualification) { return symbol === (resolvedAliasSymbol || symbolFromSymbolTable) && + // if the symbolFromSymbolTable is not external module (it could be if it was determined as ambient external module and would be in globals table) + // and if symbolFromSymbolTable or alias resolution matches the symbol, + // check the symbol can be qualified, it is only then this symbol is accessible !ts.some(symbolFromSymbolTable.declarations, hasNonGlobalAugmentationExternalModuleSymbol) && (ignoreQualification || canQualifySymbol(symbolFromSymbolTable, meaning)); } function trySymbolTable(symbols, ignoreQualification) { - if (isAccessible(symbols.get(symbol.escapedName), undefined, ignoreQualification)) { + // If symbol is directly available by its name in the symbol table + if (isAccessible(symbols.get(symbol.escapedName), /*resolvedAliasSymbol*/ undefined, ignoreQualification)) { return [symbol]; } + // Check if symbol is any of the alias return ts.forEachEntry(symbols, function (symbolFromSymbolTable) { - if (symbolFromSymbolTable.flags & 2097152 - && symbolFromSymbolTable.escapedName !== "export=" - && symbolFromSymbolTable.escapedName !== "default" + if (symbolFromSymbolTable.flags & 2097152 /* Alias */ + && symbolFromSymbolTable.escapedName !== "export=" /* ExportEquals */ + && symbolFromSymbolTable.escapedName !== "default" /* Default */ && !(ts.isUMDExportSymbol(symbolFromSymbolTable) && enclosingDeclaration && ts.isExternalModule(ts.getSourceFileOfNode(enclosingDeclaration))) + // If `!useOnlyExternalAliasing`, we can use any type of alias to get the name && (!useOnlyExternalAliasing || ts.some(symbolFromSymbolTable.declarations, ts.isExternalModuleImportEqualsDeclaration))) { var resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable); if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol, ignoreQualification)) { return [symbolFromSymbolTable]; } + // Look in the exported members, if we can find accessibleSymbolChain, symbol is accessible using this chain + // but only if the symbolFromSymbolTable can be qualified var candidateTable = getExportsOfSymbol(resolvedImportedSymbol); - var accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable, true); + var accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable, /*ignoreQualification*/ true); if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) { return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports); } } if (symbolFromSymbolTable.escapedName === symbol.escapedName && symbolFromSymbolTable.exportSymbol) { - if (isAccessible(getMergedSymbol(symbolFromSymbolTable.exportSymbol), undefined, ignoreQualification)) { + if (isAccessible(getMergedSymbol(symbolFromSymbolTable.exportSymbol), /*aliasSymbol*/ undefined, ignoreQualification)) { return [symbol]; } } @@ -27167,18 +31533,24 @@ var ts; function needsQualification(symbol, enclosingDeclaration, meaning) { var qualify = false; forEachSymbolTableInScope(enclosingDeclaration, function (symbolTable) { + // If symbol of this name is not available in the symbol table we are ok var symbolFromSymbolTable = getMergedSymbol(symbolTable.get(symbol.escapedName)); if (!symbolFromSymbolTable) { + // Continue to the next symbol table return false; } + // If the symbol with this name is present it should refer to the symbol if (symbolFromSymbolTable === symbol) { + // No need to qualify return true; } - symbolFromSymbolTable = (symbolFromSymbolTable.flags & 2097152 && !ts.getDeclarationOfKind(symbolFromSymbolTable, 252)) ? resolveAlias(symbolFromSymbolTable) : symbolFromSymbolTable; + // Qualify if the symbol from symbol table has same meaning as expected + symbolFromSymbolTable = (symbolFromSymbolTable.flags & 2097152 /* Alias */ && !ts.getDeclarationOfKind(symbolFromSymbolTable, 252 /* ExportSpecifier */)) ? resolveAlias(symbolFromSymbolTable) : symbolFromSymbolTable; if (symbolFromSymbolTable.flags & meaning) { qualify = true; return true; } + // Continue to the next symbol table return false; }); return qualify; @@ -27188,10 +31560,10 @@ var ts; for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var declaration = _a[_i]; switch (declaration.kind) { - case 152: - case 154: - case 156: - case 157: + case 152 /* PropertyDeclaration */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: continue; default: return false; @@ -27202,97 +31574,129 @@ var ts; return false; } function isTypeSymbolAccessible(typeSymbol, enclosingDeclaration) { - var access = isSymbolAccessible(typeSymbol, enclosingDeclaration, 67901928, false); - return access.accessibility === 0; + var access = isSymbolAccessible(typeSymbol, enclosingDeclaration, 67901928 /* Type */, /*shouldComputeAliasesToMakeVisible*/ false); + return access.accessibility === 0 /* Accessible */; } function isValueSymbolAccessible(typeSymbol, enclosingDeclaration) { - var access = isSymbolAccessible(typeSymbol, enclosingDeclaration, 67216319, false); - return access.accessibility === 0; + var access = isSymbolAccessible(typeSymbol, enclosingDeclaration, 67216319 /* Value */, /*shouldComputeAliasesToMakeVisible*/ false); + return access.accessibility === 0 /* Accessible */; } + /** + * Check if the given symbol in given enclosing declaration is accessible and mark all associated alias to be visible if requested + * + * @param symbol a Symbol to check if accessible + * @param enclosingDeclaration a Node containing reference to the symbol + * @param meaning a SymbolFlags to check if such meaning of the symbol is accessible + * @param shouldComputeAliasToMakeVisible a boolean value to indicate whether to return aliases to be mark visible in case the symbol is accessible + */ function isSymbolAccessible(symbol, enclosingDeclaration, meaning, shouldComputeAliasesToMakeVisible) { if (symbol && enclosingDeclaration) { var initialSymbol = symbol; var meaningToLook = meaning; while (symbol) { - var accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaningToLook, false); + // Symbol is accessible if it by itself is accessible + var accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaningToLook, /*useOnlyExternalAliasing*/ false); if (accessibleSymbolChain) { var hasAccessibleDeclarations = hasVisibleDeclarations(accessibleSymbolChain[0], shouldComputeAliasesToMakeVisible); if (!hasAccessibleDeclarations) { return { - accessibility: 1, + accessibility: 1 /* NotAccessible */, errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning), - errorModuleName: symbol !== initialSymbol ? symbolToString(symbol, enclosingDeclaration, 1920) : undefined, + errorModuleName: symbol !== initialSymbol ? symbolToString(symbol, enclosingDeclaration, 1920 /* Namespace */) : undefined, }; } return hasAccessibleDeclarations; } else { if (ts.some(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol)) { + // Any meaning of a module symbol is always accessible via an `import` type return { - accessibility: 0 + accessibility: 0 /* Accessible */ }; } } + // If we haven't got the accessible symbol, it doesn't mean the symbol is actually inaccessible. + // It could be a qualified symbol and hence verify the path + // e.g.: + // module m { + // export class c { + // } + // } + // const x: typeof m.c + // In the above example when we start with checking if typeof m.c symbol is accessible, + // we are going to see if c can be accessed in scope directly. + // But it can't, hence the accessible is going to be undefined, but that doesn't mean m.c is inaccessible + // It is accessible if the parent m is accessible because then m.c can be accessed through qualification meaningToLook = getQualifiedLeftMeaning(meaning); symbol = getContainerOfSymbol(symbol); } + // This could be a symbol that is not exported in the external module + // or it could be a symbol from different external module that is not aliased and hence cannot be named var symbolExternalModule = ts.forEach(initialSymbol.declarations, getExternalModuleContainer); if (symbolExternalModule) { var enclosingExternalModule = getExternalModuleContainer(enclosingDeclaration); if (symbolExternalModule !== enclosingExternalModule) { + // name from different external module that is not visible return { - accessibility: 2, + accessibility: 2 /* CannotBeNamed */, errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning), errorModuleName: symbolToString(symbolExternalModule) }; } } + // Just a local name that is not accessible return { - accessibility: 1, + accessibility: 1 /* NotAccessible */, errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning), }; } - return { accessibility: 0 }; + return { accessibility: 0 /* Accessible */ }; function getExternalModuleContainer(declaration) { var node = ts.findAncestor(declaration, hasExternalModuleSymbol); return node && getSymbolOfNode(node); } } function hasExternalModuleSymbol(declaration) { - return ts.isAmbientModule(declaration) || (declaration.kind === 274 && ts.isExternalOrCommonJsModule(declaration)); + return ts.isAmbientModule(declaration) || (declaration.kind === 274 /* SourceFile */ && ts.isExternalOrCommonJsModule(declaration)); } function hasNonGlobalAugmentationExternalModuleSymbol(declaration) { - return ts.isModuleWithStringLiteralName(declaration) || (declaration.kind === 274 && ts.isExternalOrCommonJsModule(declaration)); + return ts.isModuleWithStringLiteralName(declaration) || (declaration.kind === 274 /* SourceFile */ && ts.isExternalOrCommonJsModule(declaration)); } function hasVisibleDeclarations(symbol, shouldComputeAliasToMakeVisible) { var aliasesToMakeVisible; if (!ts.every(symbol.declarations, getIsDeclarationVisible)) { return undefined; } - return { accessibility: 0, aliasesToMakeVisible: aliasesToMakeVisible }; + return { accessibility: 0 /* Accessible */, aliasesToMakeVisible: aliasesToMakeVisible }; function getIsDeclarationVisible(declaration) { if (!isDeclarationVisible(declaration)) { + // Mark the unexported alias as visible if its parent is visible + // because these kind of aliases can be used to name types in declaration file var anyImportSyntax = getAnyImportSyntax(declaration); if (anyImportSyntax && - !ts.hasModifier(anyImportSyntax, 1) && + !ts.hasModifier(anyImportSyntax, 1 /* Export */) && // import clause without export isDeclarationVisible(anyImportSyntax.parent)) { return addVisibleAlias(declaration, anyImportSyntax); } else if (ts.isVariableDeclaration(declaration) && ts.isVariableStatement(declaration.parent.parent) && - !ts.hasModifier(declaration.parent.parent, 1) && + !ts.hasModifier(declaration.parent.parent, 1 /* Export */) && // unexported variable statement isDeclarationVisible(declaration.parent.parent.parent)) { return addVisibleAlias(declaration, declaration.parent.parent); } - else if (ts.isLateVisibilityPaintedStatement(declaration) - && !ts.hasModifier(declaration, 1) + else if (ts.isLateVisibilityPaintedStatement(declaration) // unexported top-level statement + && !ts.hasModifier(declaration, 1 /* Export */) && isDeclarationVisible(declaration.parent)) { return addVisibleAlias(declaration, declaration); } + // Declaration is not visible return false; } return true; } function addVisibleAlias(declaration, aliasingStatement) { + // In function "buildTypeDisplay" where we decide whether to write type-alias or serialize types, + // we want to just check if type- alias is accessible or not but we don't care about emitting those alias at that time + // since we will do the emitting later in trackSymbol. if (shouldComputeAliasToMakeVisible) { getNodeLinks(declaration).isVisible = true; aliasesToMakeVisible = ts.appendIfUnique(aliasesToMakeVisible, aliasingStatement); @@ -27301,141 +31705,147 @@ var ts; } } function isEntityNameVisible(entityName, enclosingDeclaration) { + // get symbol of the first identifier of the entityName var meaning; - if (entityName.parent.kind === 165 || + if (entityName.parent.kind === 165 /* TypeQuery */ || ts.isExpressionWithTypeArgumentsInClassExtendsClause(entityName.parent) || - entityName.parent.kind === 147) { - meaning = 67216319 | 1048576; + entityName.parent.kind === 147 /* ComputedPropertyName */) { + // Typeof value + meaning = 67216319 /* Value */ | 1048576 /* ExportValue */; } - else if (entityName.kind === 146 || entityName.kind === 185 || - entityName.parent.kind === 243) { - meaning = 1920; + else if (entityName.kind === 146 /* QualifiedName */ || entityName.kind === 185 /* PropertyAccessExpression */ || + entityName.parent.kind === 243 /* ImportEqualsDeclaration */) { + // Left identifier from type reference or TypeAlias + // Entity name of the import declaration + meaning = 1920 /* Namespace */; } else { - meaning = 67901928; + // Type Reference or TypeAlias entity = Identifier + meaning = 67901928 /* Type */; } var firstIdentifier = getFirstIdentifier(entityName); - var symbol = resolveName(enclosingDeclaration, firstIdentifier.escapedText, meaning, undefined, undefined, false); - return (symbol && hasVisibleDeclarations(symbol, true)) || { - accessibility: 1, + var symbol = resolveName(enclosingDeclaration, firstIdentifier.escapedText, meaning, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); + // Verify if the symbol is accessible + return (symbol && hasVisibleDeclarations(symbol, /*shouldComputeAliasToMakeVisible*/ true)) || { + accessibility: 1 /* NotAccessible */, errorSymbolName: ts.getTextOfNode(firstIdentifier), errorNode: firstIdentifier }; } function symbolToString(symbol, enclosingDeclaration, meaning, flags, writer) { - if (flags === void 0) { flags = 4; } - var nodeFlags = 3112960; - if (flags & 2) { - nodeFlags |= 128; + if (flags === void 0) { flags = 4 /* AllowAnyNodeKind */; } + var nodeFlags = 3112960 /* IgnoreErrors */; + if (flags & 2 /* UseOnlyExternalAliasing */) { + nodeFlags |= 128 /* UseOnlyExternalAliasing */; } - if (flags & 1) { - nodeFlags |= 512; + if (flags & 1 /* WriteTypeParametersOrArguments */) { + nodeFlags |= 512 /* WriteTypeParametersInQualifiedName */; } - if (flags & 8) { - nodeFlags |= 16384; + if (flags & 8 /* UseAliasDefinedOutsideCurrentScope */) { + nodeFlags |= 16384 /* UseAliasDefinedOutsideCurrentScope */; } - var builder = flags & 4 ? nodeBuilder.symbolToExpression : nodeBuilder.symbolToEntityName; + var builder = flags & 4 /* AllowAnyNodeKind */ ? nodeBuilder.symbolToExpression : nodeBuilder.symbolToEntityName; return writer ? symbolToStringWorker(writer).getText() : ts.usingSingleLineStringWriter(symbolToStringWorker); function symbolToStringWorker(writer) { - var entity = builder(symbol, meaning, enclosingDeclaration, nodeFlags); + var entity = builder(symbol, meaning, enclosingDeclaration, nodeFlags); // TODO: GH#18217 var printer = ts.createPrinter({ removeComments: true }); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); - printer.writeNode(4, entity, sourceFile, writer); + printer.writeNode(4 /* Unspecified */, entity, /*sourceFile*/ sourceFile, writer); return writer; } } function signatureToString(signature, enclosingDeclaration, flags, kind, writer) { - if (flags === void 0) { flags = 0; } + if (flags === void 0) { flags = 0 /* None */; } return writer ? signatureToStringWorker(writer).getText() : ts.usingSingleLineStringWriter(signatureToStringWorker); function signatureToStringWorker(writer) { var sigOutput; - if (flags & 262144) { - sigOutput = kind === 1 ? 164 : 163; + if (flags & 262144 /* WriteArrowStyleSignature */) { + sigOutput = kind === 1 /* Construct */ ? 164 /* ConstructorType */ : 163 /* FunctionType */; } else { - sigOutput = kind === 1 ? 159 : 158; + sigOutput = kind === 1 /* Construct */ ? 159 /* ConstructSignature */ : 158 /* CallSignature */; } - var sig = nodeBuilder.signatureToSignatureDeclaration(signature, sigOutput, enclosingDeclaration, toNodeBuilderFlags(flags) | 3112960 | 512); + var sig = nodeBuilder.signatureToSignatureDeclaration(signature, sigOutput, enclosingDeclaration, toNodeBuilderFlags(flags) | 3112960 /* IgnoreErrors */ | 512 /* WriteTypeParametersInQualifiedName */); var printer = ts.createPrinter({ removeComments: true, omitTrailingSemicolon: true }); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); - printer.writeNode(4, sig, sourceFile, writer); + printer.writeNode(4 /* Unspecified */, sig, /*sourceFile*/ sourceFile, writer); // TODO: GH#18217 return writer; } } function typeToString(type, enclosingDeclaration, flags, writer) { - if (flags === void 0) { flags = 1048576 | 16384; } + if (flags === void 0) { flags = 1048576 /* AllowUniqueESSymbolType */ | 16384 /* UseAliasDefinedOutsideCurrentScope */; } if (writer === void 0) { writer = ts.createTextWriter(""); } - var typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | 3112960, writer); + var typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | 3112960 /* IgnoreErrors */, writer); if (typeNode === undefined) return ts.Debug.fail("should always get typenode"); var options = { removeComments: true }; var printer = ts.createPrinter(options); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); - printer.writeNode(4, typeNode, sourceFile, writer); + printer.writeNode(4 /* Unspecified */, typeNode, /*sourceFile*/ sourceFile, writer); var result = writer.getText(); - var maxLength = compilerOptions.noErrorTruncation || flags & 1 ? undefined : 100; + var maxLength = compilerOptions.noErrorTruncation || flags & 1 /* NoTruncation */ ? undefined : 100; if (maxLength && result && result.length >= maxLength) { return result.substr(0, maxLength - "...".length) + "..."; } return result; } function toNodeBuilderFlags(flags) { - if (flags === void 0) { flags = 0; } - return flags & 9469291; + if (flags === void 0) { flags = 0 /* None */; } + return flags & 9469291 /* NodeBuilderFlagsMask */; } function createNodeBuilder() { return { typeToTypeNode: function (type, enclosingDeclaration, flags, tracker) { - ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8) === 0); + ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8 /* Synthesized */) === 0); var context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); var resultingNode = typeToTypeNodeHelper(type, context); var result = context.encounteredError ? undefined : resultingNode; return result; }, indexInfoToIndexSignatureDeclaration: function (indexInfo, kind, enclosingDeclaration, flags, tracker) { - ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8) === 0); + ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8 /* Synthesized */) === 0); var context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); var resultingNode = indexInfoToIndexSignatureDeclarationHelper(indexInfo, kind, context); var result = context.encounteredError ? undefined : resultingNode; - return result; + return result; // TODO: GH#18217 }, signatureToSignatureDeclaration: function (signature, kind, enclosingDeclaration, flags, tracker) { - ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8) === 0); + ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8 /* Synthesized */) === 0); var context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); var resultingNode = signatureToSignatureDeclarationHelper(signature, kind, context); var result = context.encounteredError ? undefined : resultingNode; return result; }, symbolToEntityName: function (symbol, meaning, enclosingDeclaration, flags, tracker) { - ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8) === 0); + ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8 /* Synthesized */) === 0); var context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); - var resultingNode = symbolToName(symbol, context, meaning, false); + var resultingNode = symbolToName(symbol, context, meaning, /*expectsIdentifier*/ false); var result = context.encounteredError ? undefined : resultingNode; return result; }, symbolToExpression: function (symbol, meaning, enclosingDeclaration, flags, tracker) { - ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8) === 0); + ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8 /* Synthesized */) === 0); var context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); var resultingNode = symbolToExpression(symbol, context, meaning); var result = context.encounteredError ? undefined : resultingNode; return result; }, symbolToTypeParameterDeclarations: function (symbol, enclosingDeclaration, flags, tracker) { - ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8) === 0); + ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8 /* Synthesized */) === 0); var context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); var resultingNode = typeParametersToTypeParameterDeclarations(symbol, context); var result = context.encounteredError ? undefined : resultingNode; return result; }, symbolToParameterDeclaration: function (symbol, enclosingDeclaration, flags, tracker) { - ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8) === 0); + ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8 /* Synthesized */) === 0); var context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); var resultingNode = symbolToParameterDeclaration(symbol, context); var result = context.encounteredError ? undefined : resultingNode; return result; }, typeParameterToDeclaration: function (parameter, enclosingDeclaration, flags, tracker) { - ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8) === 0); + ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & 8 /* Synthesized */) === 0); var context = createNodeBuilderContext(enclosingDeclaration, flags, tracker); var resultingNode = typeParameterToDeclaration(parameter, context); var result = context.encounteredError ? undefined : resultingNode; @@ -27445,7 +31855,7 @@ var ts; function createNodeBuilderContext(enclosingDeclaration, flags, tracker) { return { enclosingDeclaration: enclosingDeclaration, - flags: flags || 0, + flags: flags || 0 /* None */, tracker: tracker && tracker.trackSymbol ? tracker : { trackSymbol: ts.noop }, encounteredError: false, visitedSymbols: undefined, @@ -27456,78 +31866,78 @@ var ts; if (cancellationToken && cancellationToken.throwIfCancellationRequested) { cancellationToken.throwIfCancellationRequested(); } - var inTypeAlias = context.flags & 8388608; - context.flags &= ~8388608; + var inTypeAlias = context.flags & 8388608 /* InTypeAlias */; + context.flags &= ~8388608 /* InTypeAlias */; if (!type) { context.encounteredError = true; - return undefined; + return undefined; // TODO: GH#18217 } - if (type.flags & 1) { - return ts.createKeywordTypeNode(119); + if (type.flags & 1 /* Any */) { + return ts.createKeywordTypeNode(119 /* AnyKeyword */); } - if (type.flags & 2) { - return ts.createKeywordTypeNode(142); + if (type.flags & 2 /* Unknown */) { + return ts.createKeywordTypeNode(142 /* UnknownKeyword */); } - if (type.flags & 4) { - return ts.createKeywordTypeNode(137); + if (type.flags & 4 /* String */) { + return ts.createKeywordTypeNode(137 /* StringKeyword */); } - if (type.flags & 8) { - return ts.createKeywordTypeNode(134); + if (type.flags & 8 /* Number */) { + return ts.createKeywordTypeNode(134 /* NumberKeyword */); } - if (type.flags & 16) { - return ts.createKeywordTypeNode(122); + if (type.flags & 16 /* Boolean */) { + return ts.createKeywordTypeNode(122 /* BooleanKeyword */); } - if (type.flags & 512 && !(type.flags & 262144)) { + if (type.flags & 512 /* EnumLiteral */ && !(type.flags & 262144 /* Union */)) { var parentSymbol = getParentOfSymbol(type.symbol); - var parentName = symbolToName(parentSymbol, context, 67901928, false); + var parentName = symbolToName(parentSymbol, context, 67901928 /* Type */, /*expectsIdentifier*/ false); var enumLiteralName = getDeclaredTypeOfSymbol(parentSymbol) === type ? parentName : ts.createQualifiedName(parentName, ts.symbolName(type.symbol)); - return ts.createTypeReferenceNode(enumLiteralName, undefined); + return ts.createTypeReferenceNode(enumLiteralName, /*typeArguments*/ undefined); } - if (type.flags & 544) { - var name = symbolToName(type.symbol, context, 67901928, false); - return ts.createTypeReferenceNode(name, undefined); + if (type.flags & 544 /* EnumLike */) { + var name = symbolToName(type.symbol, context, 67901928 /* Type */, /*expectsIdentifier*/ false); + return ts.createTypeReferenceNode(name, /*typeArguments*/ undefined); } - if (type.flags & (64)) { - return ts.createLiteralTypeNode(ts.setEmitFlags(ts.createLiteral(type.value), 16777216)); + if (type.flags & (64 /* StringLiteral */)) { + return ts.createLiteralTypeNode(ts.setEmitFlags(ts.createLiteral(type.value), 16777216 /* NoAsciiEscaping */)); } - if (type.flags & (128)) { + if (type.flags & (128 /* NumberLiteral */)) { return ts.createLiteralTypeNode((ts.createLiteral(type.value))); } - if (type.flags & 256) { + if (type.flags & 256 /* BooleanLiteral */) { return type.intrinsicName === "true" ? ts.createTrue() : ts.createFalse(); } - if (type.flags & 2048) { - if (!(context.flags & 1048576)) { + if (type.flags & 2048 /* UniqueESSymbol */) { + if (!(context.flags & 1048576 /* AllowUniqueESSymbolType */)) { if (isValueSymbolAccessible(type.symbol, context.enclosingDeclaration)) { - return symbolToTypeNode(type.symbol, context, 67216319); + return symbolToTypeNode(type.symbol, context, 67216319 /* Value */); } if (context.tracker.reportInaccessibleUniqueSymbolError) { context.tracker.reportInaccessibleUniqueSymbolError(); } } - return ts.createTypeOperatorNode(141, ts.createKeywordTypeNode(138)); + return ts.createTypeOperatorNode(141 /* UniqueKeyword */, ts.createKeywordTypeNode(138 /* SymbolKeyword */)); } - if (type.flags & 4096) { - return ts.createKeywordTypeNode(105); + if (type.flags & 4096 /* Void */) { + return ts.createKeywordTypeNode(105 /* VoidKeyword */); } - if (type.flags & 8192) { - return ts.createKeywordTypeNode(140); + if (type.flags & 8192 /* Undefined */) { + return ts.createKeywordTypeNode(140 /* UndefinedKeyword */); } - if (type.flags & 16384) { - return ts.createKeywordTypeNode(95); + if (type.flags & 16384 /* Null */) { + return ts.createKeywordTypeNode(95 /* NullKeyword */); } - if (type.flags & 32768) { - return ts.createKeywordTypeNode(131); + if (type.flags & 32768 /* Never */) { + return ts.createKeywordTypeNode(131 /* NeverKeyword */); } - if (type.flags & 1024) { - return ts.createKeywordTypeNode(138); + if (type.flags & 1024 /* ESSymbol */) { + return ts.createKeywordTypeNode(138 /* SymbolKeyword */); } - if (type.flags & 16777216) { - return ts.createKeywordTypeNode(135); + if (type.flags & 16777216 /* NonPrimitive */) { + return ts.createKeywordTypeNode(135 /* ObjectKeyword */); } - if (type.flags & 65536 && type.isThisType) { - if (context.flags & 4194304) { - if (!context.encounteredError && !(context.flags & 32768)) { + if (type.flags & 65536 /* TypeParameter */ && type.isThisType) { + if (context.flags & 4194304 /* InObjectTypeLiteral */) { + if (!context.encounteredError && !(context.flags & 32768 /* AllowThisInObjectLiteral */)) { context.encounteredError = true; } if (context.tracker.reportInaccessibleThisError) { @@ -27537,61 +31947,63 @@ var ts; return ts.createThis(); } var objectFlags = ts.getObjectFlags(type); - if (objectFlags & 4) { - ts.Debug.assert(!!(type.flags & 131072)); + if (objectFlags & 4 /* Reference */) { + ts.Debug.assert(!!(type.flags & 131072 /* Object */)); return typeReferenceToTypeNode(type); } - if (type.flags & 65536 || objectFlags & 3) { - if (type.flags & 65536 && ts.contains(context.inferTypeParameters, type)) { - return ts.createInferTypeNode(typeParameterToDeclarationWithConstraint(type, context, undefined)); + if (type.flags & 65536 /* TypeParameter */ || objectFlags & 3 /* ClassOrInterface */) { + if (type.flags & 65536 /* TypeParameter */ && ts.contains(context.inferTypeParameters, type)) { + return ts.createInferTypeNode(typeParameterToDeclarationWithConstraint(type, context, /*constraintNode*/ undefined)); } - if (context.flags & 4 && - type.flags & 65536 && + if (context.flags & 4 /* GenerateNamesForShadowedTypeParams */ && + type.flags & 65536 /* TypeParameter */ && ts.length(type.symbol.declarations) && ts.isTypeParameterDeclaration(type.symbol.declarations[0]) && typeParameterShadowsNameInScope(type, context) && !isTypeSymbolAccessible(type.symbol, context.enclosingDeclaration)) { - return ts.createTypeReferenceNode(ts.getGeneratedNameForNode(type.symbol.declarations[0].name, 16 | 8), undefined); + return ts.createTypeReferenceNode(ts.getGeneratedNameForNode(type.symbol.declarations[0].name, 16 /* Optimistic */ | 8 /* ReservedInNestedScopes */), /*typeArguments*/ undefined); } + // Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter. return type.symbol - ? symbolToTypeNode(type.symbol, context, 67901928) - : ts.createTypeReferenceNode(ts.createIdentifier("?"), undefined); + ? symbolToTypeNode(type.symbol, context, 67901928 /* Type */) + : ts.createTypeReferenceNode(ts.createIdentifier("?"), /*typeArguments*/ undefined); } - if (!inTypeAlias && type.aliasSymbol && (context.flags & 16384 || isTypeSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration))) { + if (!inTypeAlias && type.aliasSymbol && (context.flags & 16384 /* UseAliasDefinedOutsideCurrentScope */ || isTypeSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration))) { var typeArgumentNodes = mapToTypeNodes(type.aliasTypeArguments, context); - if (isReservedMemberName(type.aliasSymbol.escapedName) && !(type.aliasSymbol.flags & 32)) + if (isReservedMemberName(type.aliasSymbol.escapedName) && !(type.aliasSymbol.flags & 32 /* Class */)) return ts.createTypeReferenceNode(ts.createIdentifier(""), typeArgumentNodes); - return symbolToTypeNode(type.aliasSymbol, context, 67901928, typeArgumentNodes); + return symbolToTypeNode(type.aliasSymbol, context, 67901928 /* Type */, typeArgumentNodes); } - if (type.flags & (262144 | 524288)) { - var types = type.flags & 262144 ? formatUnionTypes(type.types) : type.types; + if (type.flags & (262144 /* Union */ | 524288 /* Intersection */)) { + var types = type.flags & 262144 /* Union */ ? formatUnionTypes(type.types) : type.types; var typeNodes = mapToTypeNodes(types, context); if (typeNodes && typeNodes.length > 0) { - var unionOrIntersectionTypeNode = ts.createUnionOrIntersectionTypeNode(type.flags & 262144 ? 169 : 170, typeNodes); + var unionOrIntersectionTypeNode = ts.createUnionOrIntersectionTypeNode(type.flags & 262144 /* Union */ ? 169 /* UnionType */ : 170 /* IntersectionType */, typeNodes); return unionOrIntersectionTypeNode; } else { - if (!context.encounteredError && !(context.flags & 262144)) { + if (!context.encounteredError && !(context.flags & 262144 /* AllowEmptyUnionOrIntersection */)) { context.encounteredError = true; } - return undefined; + return undefined; // TODO: GH#18217 } } - if (objectFlags & (16 | 32)) { - ts.Debug.assert(!!(type.flags & 131072)); + if (objectFlags & (16 /* Anonymous */ | 32 /* Mapped */)) { + ts.Debug.assert(!!(type.flags & 131072 /* Object */)); + // The type is an object literal type. return createAnonymousTypeNode(type); } - if (type.flags & 1048576) { + if (type.flags & 1048576 /* Index */) { var indexedType = type.type; var indexTypeNode = typeToTypeNodeHelper(indexedType, context); return ts.createTypeOperatorNode(indexTypeNode); } - if (type.flags & 2097152) { + if (type.flags & 2097152 /* IndexedAccess */) { var objectTypeNode = typeToTypeNodeHelper(type.objectType, context); var indexTypeNode = typeToTypeNodeHelper(type.indexType, context); return ts.createIndexedAccessTypeNode(objectTypeNode, indexTypeNode); } - if (type.flags & 4194304) { + if (type.flags & 4194304 /* Conditional */) { var checkTypeNode = typeToTypeNodeHelper(type.checkType, context); var saveInferTypeParameters = context.inferTypeParameters; context.inferTypeParameters = type.root.inferTypeParameters; @@ -27601,16 +32013,18 @@ var ts; var falseTypeNode = typeToTypeNodeHelper(getFalseTypeFromConditionalType(type), context); return ts.createConditionalTypeNode(checkTypeNode, extendsTypeNode, trueTypeNode, falseTypeNode); } - if (type.flags & 8388608) { + if (type.flags & 8388608 /* Substitution */) { return typeToTypeNodeHelper(type.typeVariable, context); } return ts.Debug.fail("Should be unreachable."); function createMappedTypeNodeFromType(type) { - ts.Debug.assert(!!(type.flags & 131072)); + ts.Debug.assert(!!(type.flags & 131072 /* Object */)); var readonlyToken = type.declaration.readonlyToken ? ts.createToken(type.declaration.readonlyToken.kind) : undefined; var questionToken = type.declaration.questionToken ? ts.createToken(type.declaration.questionToken.kind) : undefined; var appropriateConstraintTypeNode; if (isMappedTypeWithKeyofConstraintDeclaration(type)) { + // We have a { [P in keyof T]: X } + // We do this to ensure we retain the toplevel keyof-ness of the type which may be lost due to keyof distribution during `getConstraintTypeFromMappedType` appropriateConstraintTypeNode = ts.createTypeOperatorNode(typeToTypeNodeHelper(getModifiersTypeFromMappedType(type), context)); } else { @@ -27619,33 +32033,39 @@ var ts; var typeParameterNode = typeParameterToDeclarationWithConstraint(getTypeParameterFromMappedType(type), context, appropriateConstraintTypeNode); var templateTypeNode = typeToTypeNodeHelper(getTemplateTypeFromMappedType(type), context); var mappedTypeNode = ts.createMappedTypeNode(readonlyToken, typeParameterNode, questionToken, templateTypeNode); - return ts.setEmitFlags(mappedTypeNode, 1); + return ts.setEmitFlags(mappedTypeNode, 1 /* SingleLine */); } function createAnonymousTypeNode(type) { var symbol = type.symbol; var id; if (symbol) { - var isConstructorObject = ts.getObjectFlags(type) & 16 && type.symbol && type.symbol.flags & 32; + var isConstructorObject = ts.getObjectFlags(type) & 16 /* Anonymous */ && type.symbol && type.symbol.flags & 32 /* Class */; id = (isConstructorObject ? "+" : "") + getSymbolId(symbol); if (isJavaScriptConstructor(symbol.valueDeclaration)) { - var isInstanceType = type === getInferredClassType(symbol) ? 67901928 : 67216319; + // Instance and static types share the same symbol; only add 'typeof' for the static side. + var isInstanceType = type === getInferredClassType(symbol) ? 67901928 /* Type */ : 67216319 /* Value */; return symbolToTypeNode(symbol, context, isInstanceType); } - else if (symbol.flags & 32 && !getBaseTypeVariableOfClass(symbol) && !(symbol.valueDeclaration.kind === 205 && context.flags & 2048) || - symbol.flags & (384 | 512) || + // Always use 'typeof T' for type of class, enum, and module objects + else if (symbol.flags & 32 /* Class */ && !getBaseTypeVariableOfClass(symbol) && !(symbol.valueDeclaration.kind === 205 /* ClassExpression */ && context.flags & 2048 /* WriteClassExpressionAsTypeLiteral */) || + symbol.flags & (384 /* Enum */ | 512 /* ValueModule */) || shouldWriteTypeOfFunctionSymbol()) { - return symbolToTypeNode(symbol, context, 67216319); + return symbolToTypeNode(symbol, context, 67216319 /* Value */); } else if (context.visitedSymbols && context.visitedSymbols.has(id)) { + // If type is an anonymous type literal in a type alias declaration, use type alias name var typeAlias = getTypeAliasForTypeLiteral(type); if (typeAlias) { - return symbolToTypeNode(typeAlias, context, 67901928); + // The specified symbol flags need to be reinterpreted as type flags + return symbolToTypeNode(typeAlias, context, 67901928 /* Type */); } else { - return ts.createKeywordTypeNode(119); + return ts.createKeywordTypeNode(119 /* AnyKeyword */); } } else { + // Since instantiations of the same anonymous type have the same symbol, tracking symbols instead + // of types allows us to catch circular references to instantiations of the same anonymous type if (!context.visitedSymbols) { context.visitedSymbols = ts.createMap(); } @@ -27656,19 +32076,21 @@ var ts; } } else { + // Anonymous types without a symbol are never circular. return createTypeNodeFromObjectType(type); } function shouldWriteTypeOfFunctionSymbol() { - var isStaticMethodSymbol = !!(symbol.flags & 8192) && - ts.some(symbol.declarations, function (declaration) { return ts.hasModifier(declaration, 32); }); - var isNonLocalFunctionSymbol = !!(symbol.flags & 16) && - (symbol.parent || + var isStaticMethodSymbol = !!(symbol.flags & 8192 /* Method */) && // typeof static method + ts.some(symbol.declarations, function (declaration) { return ts.hasModifier(declaration, 32 /* Static */); }); + var isNonLocalFunctionSymbol = !!(symbol.flags & 16 /* Function */) && + (symbol.parent || // is exported function symbol ts.forEach(symbol.declarations, function (declaration) { - return declaration.parent.kind === 274 || declaration.parent.kind === 240; + return declaration.parent.kind === 274 /* SourceFile */ || declaration.parent.kind === 240 /* ModuleBlock */; })); if (isStaticMethodSymbol || isNonLocalFunctionSymbol) { - return (!!(context.flags & 4096) || (context.visitedSymbols && context.visitedSymbols.has(id))) && - (!(context.flags & 8) || isValueSymbolAccessible(symbol, context.enclosingDeclaration)); + // typeof is allowed only for static/non local functions + return (!!(context.flags & 4096 /* UseTypeOfFunction */) || (context.visitedSymbols && context.visitedSymbols.has(id))) && // it is type of the symbol uses itself recursively + (!(context.flags & 8 /* UseStructuralFallback */) || isValueSymbolAccessible(symbol, context.enclosingDeclaration)); // TODO: GH#18217 // And the build is going to succeed without visibility error or there is no structural fallback allowed } } } @@ -27679,50 +32101,50 @@ var ts; var resolved = resolveStructuredTypeMembers(type); if (!resolved.properties.length && !resolved.stringIndexInfo && !resolved.numberIndexInfo) { if (!resolved.callSignatures.length && !resolved.constructSignatures.length) { - return ts.setEmitFlags(ts.createTypeLiteralNode(undefined), 1); + return ts.setEmitFlags(ts.createTypeLiteralNode(/*members*/ undefined), 1 /* SingleLine */); } if (resolved.callSignatures.length === 1 && !resolved.constructSignatures.length) { var signature = resolved.callSignatures[0]; - var signatureNode = signatureToSignatureDeclarationHelper(signature, 163, context); + var signatureNode = signatureToSignatureDeclarationHelper(signature, 163 /* FunctionType */, context); return signatureNode; } if (resolved.constructSignatures.length === 1 && !resolved.callSignatures.length) { var signature = resolved.constructSignatures[0]; - var signatureNode = signatureToSignatureDeclarationHelper(signature, 164, context); + var signatureNode = signatureToSignatureDeclarationHelper(signature, 164 /* ConstructorType */, context); return signatureNode; } } var savedFlags = context.flags; - context.flags |= 4194304; + context.flags |= 4194304 /* InObjectTypeLiteral */; var members = createTypeNodesFromResolvedType(resolved); context.flags = savedFlags; var typeLiteralNode = ts.createTypeLiteralNode(members); - return ts.setEmitFlags(typeLiteralNode, (context.flags & 1024) ? 0 : 1); + return ts.setEmitFlags(typeLiteralNode, (context.flags & 1024 /* MultilineObjectLiterals */) ? 0 : 1 /* SingleLine */); } function typeReferenceToTypeNode(type) { var typeArguments = type.typeArguments || ts.emptyArray; if (type.target === globalArrayType) { - if (context.flags & 2) { + if (context.flags & 2 /* WriteArrayAsGenericType */) { var typeArgumentNode = typeToTypeNodeHelper(typeArguments[0], context); return ts.createTypeReferenceNode("Array", [typeArgumentNode]); } var elementType = typeToTypeNodeHelper(typeArguments[0], context); return ts.createArrayTypeNode(elementType); } - else if (type.target.objectFlags & 8) { + else if (type.target.objectFlags & 8 /* Tuple */) { if (typeArguments.length > 0) { var tupleConstituentNodes = mapToTypeNodes(typeArguments.slice(0, getTypeReferenceArity(type)), context); if (tupleConstituentNodes && tupleConstituentNodes.length > 0) { return ts.createTupleTypeNode(tupleConstituentNodes); } } - if (context.encounteredError || (context.flags & 524288)) { + if (context.encounteredError || (context.flags & 524288 /* AllowEmptyTuple */)) { return ts.createTupleTypeNode([]); } context.encounteredError = true; - return undefined; + return undefined; // TODO: GH#18217 } - else if (context.flags & 2048 && + else if (context.flags & 2048 /* WriteClassExpressionAsTypeLiteral */ && type.symbol.valueDeclaration && ts.isClassLike(type.symbol.valueDeclaration) && !isValueSymbolAccessible(type.symbol, context.enclosingDeclaration)) { @@ -27735,16 +32157,19 @@ var ts; if (outerTypeParameters) { var length_1 = outerTypeParameters.length; while (i < length_1) { + // Find group of type arguments for type parameters with the same declaring container. var start = i; var parent = getParentSymbolOfTypeParameter(outerTypeParameters[i]); do { i++; } while (i < length_1 && getParentSymbolOfTypeParameter(outerTypeParameters[i]) === parent); + // When type parameters are their own type arguments for the whole group (i.e. we have + // the default outer type arguments), we don't show the group. if (!ts.rangeEquals(outerTypeParameters, typeArguments, start, i)) { var typeArgumentSlice = mapToTypeNodes(typeArguments.slice(start, i), context); var flags_2 = context.flags; - context.flags |= 16; - var ref = symbolToTypeNode(parent, context, 67901928, typeArgumentSlice); + context.flags |= 16 /* ForbidIndexedAccessSymbolReferences */; + var ref = symbolToTypeNode(parent, context, 67901928 /* Type */, typeArgumentSlice); context.flags = flags_2; resultType = !resultType ? ref : appendReferenceToType(resultType, ref); } @@ -27756,19 +32181,21 @@ var ts; typeArgumentNodes = mapToTypeNodes(typeArguments.slice(i, typeParameterCount), context); } var flags = context.flags; - context.flags |= 16; - var finalRef = symbolToTypeNode(type.symbol, context, 67901928, typeArgumentNodes); + context.flags |= 16 /* ForbidIndexedAccessSymbolReferences */; + var finalRef = symbolToTypeNode(type.symbol, context, 67901928 /* Type */, typeArgumentNodes); context.flags = flags; return !resultType ? finalRef : appendReferenceToType(resultType, finalRef); } } function appendReferenceToType(root, ref) { if (ts.isImportTypeNode(root)) { + // first shift type arguments var innerParams = root.typeArguments; if (root.qualifier) { (ts.isIdentifier(root.qualifier) ? root.qualifier : root.qualifier.right).typeArguments = innerParams; } root.typeArguments = ref.typeArguments; + // then move qualifiers var ids = getAccessStack(ref); for (var _i = 0, ids_1 = ids; _i < ids_1.length; _i++) { var id = ids_1[_i]; @@ -27777,9 +32204,11 @@ var ts; return root; } else { + // first shift type arguments var innerParams = root.typeArguments; (ts.isIdentifier(root.typeName) ? root.typeName : root.typeName.right).typeArguments = innerParams; root.typeArguments = ref.typeArguments; + // then move qualifiers var ids = getAccessStack(ref); for (var _a = 0, ids_2 = ids; _a < ids_2.length; _a++) { var id = ids_2[_a]; @@ -27802,20 +32231,20 @@ var ts; var typeElements = []; for (var _i = 0, _a = resolvedType.callSignatures; _i < _a.length; _i++) { var signature = _a[_i]; - typeElements.push(signatureToSignatureDeclarationHelper(signature, 158, context)); + typeElements.push(signatureToSignatureDeclarationHelper(signature, 158 /* CallSignature */, context)); } for (var _b = 0, _c = resolvedType.constructSignatures; _b < _c.length; _b++) { var signature = _c[_b]; - typeElements.push(signatureToSignatureDeclarationHelper(signature, 159, context)); + typeElements.push(signatureToSignatureDeclarationHelper(signature, 159 /* ConstructSignature */, context)); } if (resolvedType.stringIndexInfo) { - var indexInfo = resolvedType.objectFlags & 2048 ? + var indexInfo = resolvedType.objectFlags & 2048 /* ReverseMapped */ ? createIndexInfo(anyType, resolvedType.stringIndexInfo.isReadonly, resolvedType.stringIndexInfo.declaration) : resolvedType.stringIndexInfo; - typeElements.push(indexInfoToIndexSignatureDeclarationHelper(indexInfo, 0, context)); + typeElements.push(indexInfoToIndexSignatureDeclarationHelper(indexInfo, 0 /* String */, context)); } if (resolvedType.numberIndexInfo) { - typeElements.push(indexInfoToIndexSignatureDeclarationHelper(resolvedType.numberIndexInfo, 1, context)); + typeElements.push(indexInfoToIndexSignatureDeclarationHelper(resolvedType.numberIndexInfo, 1 /* Number */, context)); } var properties = resolvedType.properties; if (!properties) { @@ -27823,39 +32252,41 @@ var ts; } for (var _d = 0, properties_1 = properties; _d < properties_1.length; _d++) { var propertySymbol = properties_1[_d]; - if (context.flags & 2048) { - if (propertySymbol.flags & 4194304) { + if (context.flags & 2048 /* WriteClassExpressionAsTypeLiteral */) { + if (propertySymbol.flags & 4194304 /* Prototype */) { continue; } - if (ts.getDeclarationModifierFlagsFromSymbol(propertySymbol) & (8 | 16) && context.tracker.reportPrivateInBaseOfClassExpression) { + if (ts.getDeclarationModifierFlagsFromSymbol(propertySymbol) & (8 /* Private */ | 16 /* Protected */) && context.tracker.reportPrivateInBaseOfClassExpression) { context.tracker.reportPrivateInBaseOfClassExpression(ts.unescapeLeadingUnderscores(propertySymbol.escapedName)); } } - var propertyType = ts.getCheckFlags(propertySymbol) & 2048 && context.flags & 33554432 ? + var propertyType = ts.getCheckFlags(propertySymbol) & 2048 /* ReverseMapped */ && context.flags & 33554432 /* InReverseMappedType */ ? anyType : getTypeOfSymbol(propertySymbol); var saveEnclosingDeclaration = context.enclosingDeclaration; context.enclosingDeclaration = undefined; - if (ts.getCheckFlags(propertySymbol) & 1024) { + if (ts.getCheckFlags(propertySymbol) & 1024 /* Late */) { var decl = ts.first(propertySymbol.declarations); if (context.tracker.trackSymbol && hasLateBindableName(decl)) { + // get symbol of the first identifier of the entityName var firstIdentifier = getFirstIdentifier(decl.name.expression); - var name = resolveName(firstIdentifier, firstIdentifier.escapedText, 67216319 | 1048576, undefined, undefined, true); + var name = resolveName(firstIdentifier, firstIdentifier.escapedText, 67216319 /* Value */ | 1048576 /* ExportValue */, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); if (name) { - context.tracker.trackSymbol(name, saveEnclosingDeclaration, 67216319); + context.tracker.trackSymbol(name, saveEnclosingDeclaration, 67216319 /* Value */); } } } - var propertyName = symbolToName(propertySymbol, context, 67216319, true); + var propertyName = symbolToName(propertySymbol, context, 67216319 /* Value */, /*expectsIdentifier*/ true); context.enclosingDeclaration = saveEnclosingDeclaration; - var optionalToken = propertySymbol.flags & 16777216 ? ts.createToken(55) : undefined; - if (propertySymbol.flags & (16 | 8192) && !getPropertiesOfObjectType(propertyType).length) { - var signatures = getSignaturesOfType(propertyType, 0); + var optionalToken = propertySymbol.flags & 16777216 /* Optional */ ? ts.createToken(55 /* QuestionToken */) : undefined; + if (propertySymbol.flags & (16 /* Function */ | 8192 /* Method */) && !getPropertiesOfObjectType(propertyType).length) { + var signatures = getSignaturesOfType(propertyType, 0 /* Call */); for (var _e = 0, signatures_1 = signatures; _e < signatures_1.length; _e++) { var signature = signatures_1[_e]; - var methodDeclaration = signatureToSignatureDeclarationHelper(signature, 153, context); + var methodDeclaration = signatureToSignatureDeclarationHelper(signature, 153 /* MethodSignature */, context); methodDeclaration.name = propertyName; methodDeclaration.questionToken = optionalToken; if (propertySymbol.valueDeclaration) { + // Copy comments to node for declaration emit ts.setCommentRange(methodDeclaration, propertySymbol.valueDeclaration); } typeElements.push(methodDeclaration); @@ -27863,12 +32294,14 @@ var ts; } else { var savedFlags = context.flags; - context.flags |= !!(ts.getCheckFlags(propertySymbol) & 2048) ? 33554432 : 0; - var propertyTypeNode = propertyType ? typeToTypeNodeHelper(propertyType, context) : ts.createKeywordTypeNode(119); + context.flags |= !!(ts.getCheckFlags(propertySymbol) & 2048 /* ReverseMapped */) ? 33554432 /* InReverseMappedType */ : 0; + var propertyTypeNode = propertyType ? typeToTypeNodeHelper(propertyType, context) : ts.createKeywordTypeNode(119 /* AnyKeyword */); context.flags = savedFlags; - var modifiers = isReadonlySymbol(propertySymbol) ? [ts.createToken(132)] : undefined; - var propertySignature = ts.createPropertySignature(modifiers, propertyName, optionalToken, propertyTypeNode, undefined); + var modifiers = isReadonlySymbol(propertySymbol) ? [ts.createToken(132 /* ReadonlyKeyword */)] : undefined; + var propertySignature = ts.createPropertySignature(modifiers, propertyName, optionalToken, propertyTypeNode, + /*initializer*/ undefined); if (propertySymbol.valueDeclaration) { + // Copy comments to node for declaration emit ts.setCommentRange(propertySignature, propertySymbol.valueDeclaration); } typeElements.push(propertySignature); @@ -27892,24 +32325,30 @@ var ts; } function indexInfoToIndexSignatureDeclarationHelper(indexInfo, kind, context) { var name = ts.getNameFromIndexInfo(indexInfo) || "x"; - var indexerTypeNode = ts.createKeywordTypeNode(kind === 0 ? 137 : 134); - var indexingParameter = ts.createParameter(undefined, undefined, undefined, name, undefined, indexerTypeNode, undefined); + var indexerTypeNode = ts.createKeywordTypeNode(kind === 0 /* String */ ? 137 /* StringKeyword */ : 134 /* NumberKeyword */); + var indexingParameter = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, name, + /*questionToken*/ undefined, indexerTypeNode, + /*initializer*/ undefined); var typeNode = typeToTypeNodeHelper(indexInfo.type || anyType, context); - if (!indexInfo.type && !(context.flags & 2097152)) { + if (!indexInfo.type && !(context.flags & 2097152 /* AllowEmptyIndexInfoType */)) { context.encounteredError = true; } - return ts.createIndexSignature(undefined, indexInfo.isReadonly ? [ts.createToken(132)] : undefined, [indexingParameter], typeNode); + return ts.createIndexSignature( + /*decorators*/ undefined, indexInfo.isReadonly ? [ts.createToken(132 /* ReadonlyKeyword */)] : undefined, [indexingParameter], typeNode); } function signatureToSignatureDeclarationHelper(signature, kind, context) { var typeParameters; var typeArguments; - if (context.flags & 32 && signature.target && signature.mapper && signature.target.typeParameters) { + if (context.flags & 32 /* WriteTypeArgumentsOfSignature */ && signature.target && signature.mapper && signature.target.typeParameters) { typeArguments = signature.target.typeParameters.map(function (parameter) { return typeToTypeNodeHelper(instantiateType(parameter, signature.mapper), context); }); } else { typeParameters = signature.typeParameters && signature.typeParameters.map(function (parameter) { return typeParameterToDeclaration(parameter, context); }); } - var parameters = signature.parameters.map(function (parameter) { return symbolToParameterDeclaration(parameter, context, kind === 155); }); + var parameters = signature.parameters.map(function (parameter) { return symbolToParameterDeclaration(parameter, context, kind === 155 /* Constructor */); }); if (signature.thisParameter) { var thisParameter = symbolToParameterDeclaration(signature.thisParameter, context); parameters.unshift(thisParameter); @@ -27917,8 +32356,8 @@ var ts; var returnTypeNode; var typePredicate = getTypePredicateOfSignature(signature); if (typePredicate) { - var parameterName = typePredicate.kind === 1 ? - ts.setEmitFlags(ts.createIdentifier(typePredicate.parameterName), 16777216) : + var parameterName = typePredicate.kind === 1 /* Identifier */ ? + ts.setEmitFlags(ts.createIdentifier(typePredicate.parameterName), 16777216 /* NoAsciiEscaping */) : ts.createThisTypeNode(); var typeNode = typeToTypeNodeHelper(typePredicate.type, context); returnTypeNode = ts.createTypePredicateNode(parameterName, typeNode); @@ -27927,29 +32366,29 @@ var ts; var returnType = getReturnTypeOfSignature(signature); returnTypeNode = returnType && typeToTypeNodeHelper(returnType, context); } - if (context.flags & 256) { - if (returnTypeNode && returnTypeNode.kind === 119) { + if (context.flags & 256 /* SuppressAnyReturnType */) { + if (returnTypeNode && returnTypeNode.kind === 119 /* AnyKeyword */) { returnTypeNode = undefined; } } else if (!returnTypeNode) { - returnTypeNode = ts.createKeywordTypeNode(119); + returnTypeNode = ts.createKeywordTypeNode(119 /* AnyKeyword */); } return ts.createSignatureDeclaration(kind, typeParameters, parameters, returnTypeNode, typeArguments); } function typeParameterShadowsNameInScope(type, context) { - return !!resolveName(context.enclosingDeclaration, type.symbol.escapedName, 67901928, undefined, type.symbol.escapedName, false); + return !!resolveName(context.enclosingDeclaration, type.symbol.escapedName, 67901928 /* Type */, /*nameNotFoundArg*/ undefined, type.symbol.escapedName, /*isUse*/ false); } function typeParameterToDeclarationWithConstraint(type, context, constraintNode) { var savedContextFlags = context.flags; - context.flags &= ~512; - var shouldUseGeneratedName = context.flags & 4 && + context.flags &= ~512 /* WriteTypeParametersInQualifiedName */; // Avoids potential infinite loop when building for a claimspace with a generic + var shouldUseGeneratedName = context.flags & 4 /* GenerateNamesForShadowedTypeParams */ && type.symbol.declarations[0] && ts.isTypeParameterDeclaration(type.symbol.declarations[0]) && typeParameterShadowsNameInScope(type, context); var name = shouldUseGeneratedName - ? ts.getGeneratedNameForNode(type.symbol.declarations[0].name, 16 | 8) - : symbolToName(type.symbol, context, 67901928, true); + ? ts.getGeneratedNameForNode(type.symbol.declarations[0].name, 16 /* Optimistic */ | 8 /* ReservedInNestedScopes */) + : symbolToName(type.symbol, context, 67901928 /* Type */, /*expectsIdentifier*/ true); var defaultParameter = getDefaultFromTypeParameter(type); var defaultParameterNode = defaultParameter && typeToTypeNodeHelper(defaultParameter, context); context.flags = savedContextFlags; @@ -27961,60 +32400,65 @@ var ts; return typeParameterToDeclarationWithConstraint(type, context, constraintNode); } function symbolToParameterDeclaration(parameterSymbol, context, preserveModifierFlags) { - var parameterDeclaration = ts.getDeclarationOfKind(parameterSymbol, 149); + var parameterDeclaration = ts.getDeclarationOfKind(parameterSymbol, 149 /* Parameter */); if (!parameterDeclaration && !isTransientSymbol(parameterSymbol)) { - parameterDeclaration = ts.getDeclarationOfKind(parameterSymbol, 293); + parameterDeclaration = ts.getDeclarationOfKind(parameterSymbol, 293 /* JSDocParameterTag */); } var parameterType = getTypeOfSymbol(parameterSymbol); if (parameterDeclaration && isRequiredInitializedParameter(parameterDeclaration)) { parameterType = getOptionalType(parameterType); } var parameterTypeNode = typeToTypeNodeHelper(parameterType, context); - var modifiers = !(context.flags & 8192) && preserveModifierFlags && parameterDeclaration && parameterDeclaration.modifiers ? parameterDeclaration.modifiers.map(ts.getSynthesizedClone) : undefined; + var modifiers = !(context.flags & 8192 /* OmitParameterModifiers */) && preserveModifierFlags && parameterDeclaration && parameterDeclaration.modifiers ? parameterDeclaration.modifiers.map(ts.getSynthesizedClone) : undefined; var isRest = parameterDeclaration ? ts.isRestParameter(parameterDeclaration) : parameterSymbol.isRestParameter; - var dotDotDotToken = isRest ? ts.createToken(24) : undefined; + var dotDotDotToken = isRest ? ts.createToken(24 /* DotDotDotToken */) : undefined; var name = parameterDeclaration ? parameterDeclaration.name ? - parameterDeclaration.name.kind === 71 ? ts.setEmitFlags(ts.getSynthesizedClone(parameterDeclaration.name), 16777216) : - parameterDeclaration.name.kind === 146 ? ts.setEmitFlags(ts.getSynthesizedClone(parameterDeclaration.name.right), 16777216) : + parameterDeclaration.name.kind === 71 /* Identifier */ ? ts.setEmitFlags(ts.getSynthesizedClone(parameterDeclaration.name), 16777216 /* NoAsciiEscaping */) : + parameterDeclaration.name.kind === 146 /* QualifiedName */ ? ts.setEmitFlags(ts.getSynthesizedClone(parameterDeclaration.name.right), 16777216 /* NoAsciiEscaping */) : cloneBindingName(parameterDeclaration.name) : ts.symbolName(parameterSymbol) : ts.symbolName(parameterSymbol); - var questionToken = parameterDeclaration && isOptionalParameter(parameterDeclaration) ? ts.createToken(55) : undefined; - var parameterNode = ts.createParameter(undefined, modifiers, dotDotDotToken, name, questionToken, parameterTypeNode, undefined); + var questionToken = parameterDeclaration && isOptionalParameter(parameterDeclaration) ? ts.createToken(55 /* QuestionToken */) : undefined; + var parameterNode = ts.createParameter( + /*decorators*/ undefined, modifiers, dotDotDotToken, name, questionToken, parameterTypeNode, + /*initializer*/ undefined); return parameterNode; function cloneBindingName(node) { return elideInitializerAndSetEmitFlags(node); function elideInitializerAndSetEmitFlags(node) { - var visited = ts.visitEachChild(node, elideInitializerAndSetEmitFlags, ts.nullTransformationContext, undefined, elideInitializerAndSetEmitFlags); + var visited = ts.visitEachChild(node, elideInitializerAndSetEmitFlags, ts.nullTransformationContext, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags); var clone = ts.nodeIsSynthesized(visited) ? visited : ts.getSynthesizedClone(visited); - if (clone.kind === 182) { + if (clone.kind === 182 /* BindingElement */) { clone.initializer = undefined; } - return ts.setEmitFlags(clone, 1 | 16777216); + return ts.setEmitFlags(clone, 1 /* SingleLine */ | 16777216 /* NoAsciiEscaping */); } } } function lookupSymbolChain(symbol, context, meaning, yieldModuleSymbol) { - context.tracker.trackSymbol(symbol, context.enclosingDeclaration, meaning); + context.tracker.trackSymbol(symbol, context.enclosingDeclaration, meaning); // TODO: GH#18217 + // Try to get qualified name if the symbol is not a type parameter and there is an enclosing declaration. var chain; - var isTypeParameter = symbol.flags & 262144; - if (!isTypeParameter && (context.enclosingDeclaration || context.flags & 64)) { - chain = ts.Debug.assertDefined(getSymbolChain(symbol, meaning, true)); + var isTypeParameter = symbol.flags & 262144 /* TypeParameter */; + if (!isTypeParameter && (context.enclosingDeclaration || context.flags & 64 /* UseFullyQualifiedType */)) { + chain = ts.Debug.assertDefined(getSymbolChain(symbol, meaning, /*endOfChain*/ true)); ts.Debug.assert(chain && chain.length > 0); } else { chain = [symbol]; } return chain; + /** @param endOfChain Set to false for recursive calls; non-recursive calls should always output something. */ function getSymbolChain(symbol, meaning, endOfChain) { - var accessibleSymbolChain = getAccessibleSymbolChain(symbol, context.enclosingDeclaration, meaning, !!(context.flags & 128)); + var accessibleSymbolChain = getAccessibleSymbolChain(symbol, context.enclosingDeclaration, meaning, !!(context.flags & 128 /* UseOnlyExternalAliasing */)); var parentSymbol; if (!accessibleSymbolChain || needsQualification(accessibleSymbolChain[0], context.enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) { + // Go up and add our parent. var parent = getContainerOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol); if (parent) { - var parentChain = getSymbolChain(parent, getQualifiedLeftMeaning(meaning), false); + var parentChain = getSymbolChain(parent, getQualifiedLeftMeaning(meaning), /*endOfChain*/ false); if (parentChain) { parentSymbol = parent; accessibleSymbolChain = parentChain.concat(accessibleSymbolChain || [getAliasForSymbolInContainer(parent, symbol) || symbol]); @@ -28024,9 +32468,13 @@ var ts; if (accessibleSymbolChain) { return accessibleSymbolChain; } - if (endOfChain || + if ( + // If this is the last part of outputting the symbol, always output. The cases apply only to parent symbols. + endOfChain || + // If a parent symbol is an external module, don't write it. (We prefer just `x` vs `"foo/bar".x`.) (yieldModuleSymbol || !(!parentSymbol && ts.forEach(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol))) && - !(symbol.flags & (2048 | 4096))) { + // If a parent symbol is an anonymous type, don't write it. + !(symbol.flags & (2048 /* TypeLiteral */ | 4096 /* ObjectLiteral */))) { return [symbol]; } } @@ -28034,7 +32482,7 @@ var ts; function typeParametersToTypeParameterDeclarations(symbol, context) { var typeParameterNodes; var targetSymbol = getTargetSymbol(symbol); - if (targetSymbol.flags & (32 | 64 | 524288)) { + if (targetSymbol.flags & (32 /* Class */ | 64 /* Interface */ | 524288 /* TypeAlias */)) { typeParameterNodes = ts.createNodeArray(ts.map(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol), function (tp) { return typeParameterToDeclaration(tp, context); })); } return typeParameterNodes; @@ -28043,11 +32491,11 @@ var ts; ts.Debug.assert(chain && 0 <= index && index < chain.length); var symbol = chain[index]; var typeParameterNodes; - if (context.flags & 512 && index < (chain.length - 1)) { + if (context.flags & 512 /* WriteTypeParametersInQualifiedName */ && index < (chain.length - 1)) { var parentSymbol = symbol; var nextSymbol = chain[index + 1]; - if (ts.getCheckFlags(nextSymbol) & 1) { - var params = getTypeParametersOfClassOrInterface(parentSymbol.flags & 2097152 ? resolveAlias(parentSymbol) : parentSymbol); + if (ts.getCheckFlags(nextSymbol) & 1 /* Instantiated */) { + var params = getTypeParametersOfClassOrInterface(parentSymbol.flags & 2097152 /* Alias */ ? resolveAlias(parentSymbol) : parentSymbol); typeParameterNodes = mapToTypeNodes(ts.map(params, nextSymbol.mapper), context); } else { @@ -28056,6 +32504,9 @@ var ts; } return typeParameterNodes; } + /** + * Given A[B][C][D], finds A[B] + */ function getTopmostIndexedAccessType(top) { if (ts.isIndexedAccessTypeNode(top.objectType)) { return getTopmostIndexedAccessType(top.objectType); @@ -28063,12 +32514,13 @@ var ts; return top; } function symbolToTypeNode(symbol, context, meaning, overrideTypeArguments) { - var chain = lookupSymbolChain(symbol, context, meaning, !(context.flags & 16384)); - context.flags |= 16777216; + var chain = lookupSymbolChain(symbol, context, meaning, !(context.flags & 16384 /* UseAliasDefinedOutsideCurrentScope */)); // If we're using aliases outside the current scope, dont bother with the module + context.flags |= 16777216 /* InInitialEntityName */; var rootName = getNameOfSymbolAsWritten(chain[0], context); - context.flags ^= 16777216; - var isTypeOf = meaning === 67216319; + context.flags ^= 16777216 /* InInitialEntityName */; + var isTypeOf = meaning === 67216319 /* Value */; if (ambientModuleSymbolRegex.test(rootName)) { + // module is root, must use `ImportTypeNode` var nonRootParts = chain.length > 1 ? createAccessFromSymbolChain(chain, chain.length - 1, 1) : undefined; var typeParameterNodes = overrideTypeArguments || lookupTypeParameterNodes(chain, 0, context); var lit = ts.createLiteralTypeNode(ts.createLiteral(rootName.substring(1, rootName.length - 1))); @@ -28087,7 +32539,7 @@ var ts; } var entityName = createAccessFromSymbolChain(chain, chain.length - 1, 0); if (ts.isIndexedAccessTypeNode(entityName)) { - return entityName; + return entityName; // Indexed accesses can never be `typeof` } if (isTypeOf) { return ts.createTypeQueryNode(entityName); @@ -28102,14 +32554,15 @@ var ts; var typeParameterNodes = index === (chain.length - 1) ? overrideTypeArguments : lookupTypeParameterNodes(chain, index, context); var symbol = chain[index]; if (index === 0) { - context.flags |= 16777216; + context.flags |= 16777216 /* InInitialEntityName */; } var symbolName = getNameOfSymbolAsWritten(symbol, context); if (index === 0) { - context.flags ^= 16777216; + context.flags ^= 16777216 /* InInitialEntityName */; } var parent = chain[index - 1]; - if (!(context.flags & 16) && parent && getMembersOfSymbol(parent) && getMembersOfSymbol(parent).get(symbol.escapedName) === symbol) { + if (!(context.flags & 16 /* ForbidIndexedAccessSymbolReferences */) && parent && getMembersOfSymbol(parent) && getMembersOfSymbol(parent).get(symbol.escapedName) === symbol) { + // Should use an indexed access var LHS = createAccessFromSymbolChain(chain, index - 1, stopper); if (ts.isIndexedAccessTypeNode(LHS)) { return ts.createIndexedAccessTypeNode(LHS, ts.createLiteralTypeNode(ts.createLiteral(symbolName))); @@ -28118,7 +32571,7 @@ var ts; return ts.createIndexedAccessTypeNode(ts.createTypeReferenceNode(LHS, typeParameterNodes), ts.createLiteralTypeNode(ts.createLiteral(symbolName))); } } - var identifier = ts.setEmitFlags(ts.createIdentifier(symbolName, typeParameterNodes), 16777216); + var identifier = ts.setEmitFlags(ts.createIdentifier(symbolName, typeParameterNodes), 16777216 /* NoAsciiEscaping */); identifier.symbol = symbol; if (index > stopper) { var LHS = createAccessFromSymbolChain(chain, index - 1, stopper); @@ -28134,7 +32587,7 @@ var ts; var chain = lookupSymbolChain(symbol, context, meaning); if (expectsIdentifier && chain.length !== 1 && !context.encounteredError - && !(context.flags & 65536)) { + && !(context.flags & 65536 /* AllowQualifedNameInPlaceOfIdentifier */)) { context.encounteredError = true; } return createEntityNameFromSymbolChain(chain, chain.length - 1); @@ -28142,13 +32595,13 @@ var ts; var typeParameterNodes = lookupTypeParameterNodes(chain, index, context); var symbol = chain[index]; if (index === 0) { - context.flags |= 16777216; + context.flags |= 16777216 /* InInitialEntityName */; } var symbolName = getNameOfSymbolAsWritten(symbol, context); if (index === 0) { - context.flags ^= 16777216; + context.flags ^= 16777216 /* InInitialEntityName */; } - var identifier = ts.setEmitFlags(ts.createIdentifier(symbolName, typeParameterNodes), 16777216); + var identifier = ts.setEmitFlags(ts.createIdentifier(symbolName, typeParameterNodes), 16777216 /* NoAsciiEscaping */); identifier.symbol = symbol; return index > 0 ? ts.createQualifiedName(createEntityNameFromSymbolChain(chain, index - 1), identifier) : identifier; } @@ -28160,34 +32613,34 @@ var ts; var typeParameterNodes = lookupTypeParameterNodes(chain, index, context); var symbol = chain[index]; if (index === 0) { - context.flags |= 16777216; + context.flags |= 16777216 /* InInitialEntityName */; } var symbolName = getNameOfSymbolAsWritten(symbol, context); if (index === 0) { - context.flags ^= 16777216; + context.flags ^= 16777216 /* InInitialEntityName */; } var firstChar = symbolName.charCodeAt(0); var canUsePropertyAccess = ts.isIdentifierStart(firstChar, languageVersion); if (index === 0 || canUsePropertyAccess) { - var identifier = ts.setEmitFlags(ts.createIdentifier(symbolName, typeParameterNodes), 16777216); + var identifier = ts.setEmitFlags(ts.createIdentifier(symbolName, typeParameterNodes), 16777216 /* NoAsciiEscaping */); identifier.symbol = symbol; return index > 0 ? ts.createPropertyAccess(createExpressionFromSymbolChain(chain, index - 1), identifier) : identifier; } else { - if (firstChar === 91) { + if (firstChar === 91 /* openBracket */) { symbolName = symbolName.substring(1, symbolName.length - 1); firstChar = symbolName.charCodeAt(0); } var expression = void 0; if (ts.isSingleOrDoubleQuote(firstChar)) { expression = ts.createLiteral(symbolName.substring(1, symbolName.length - 1).replace(/\\./g, function (s) { return s.substring(1); })); - expression.singleQuote = firstChar === 39; + expression.singleQuote = firstChar === 39 /* singleQuote */; } else if (("" + +symbolName) === symbolName) { expression = ts.createLiteral(+symbolName); } if (!expression) { - expression = ts.setEmitFlags(ts.createIdentifier(symbolName, typeParameterNodes), 16777216); + expression = ts.setEmitFlags(ts.createIdentifier(symbolName, typeParameterNodes), 16777216 /* NoAsciiEscaping */); expression.symbol = symbol; } return ts.createElementAccess(createExpressionFromSymbolChain(chain, index - 1), expression); @@ -28196,13 +32649,13 @@ var ts; } } function typePredicateToString(typePredicate, enclosingDeclaration, flags, writer) { - if (flags === void 0) { flags = 16384; } + if (flags === void 0) { flags = 16384 /* UseAliasDefinedOutsideCurrentScope */; } return writer ? typePredicateToStringWorker(writer).getText() : ts.usingSingleLineStringWriter(typePredicateToStringWorker); function typePredicateToStringWorker(writer) { - var predicate = ts.createTypePredicateNode(typePredicate.kind === 1 ? ts.createIdentifier(typePredicate.parameterName) : ts.createThisTypeNode(), nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | 3112960 | 512)); + var predicate = ts.createTypePredicateNode(typePredicate.kind === 1 /* Identifier */ ? ts.createIdentifier(typePredicate.parameterName) : ts.createThisTypeNode(), nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | 3112960 /* IgnoreErrors */ | 512 /* WriteTypeParametersInQualifiedName */)); var printer = ts.createPrinter({ removeComments: true }); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); - printer.writeNode(4, predicate, sourceFile, writer); + printer.writeNode(4 /* Unspecified */, predicate, /*sourceFile*/ sourceFile, writer); return writer; } } @@ -28212,10 +32665,10 @@ var ts; for (var i = 0; i < types.length; i++) { var t = types[i]; flags |= t.flags; - if (!(t.flags & 24576)) { - if (t.flags & (256 | 512)) { - var baseType = t.flags & 256 ? booleanType : getBaseTypeOfEnumLiteralType(t); - if (baseType.flags & 262144) { + if (!(t.flags & 24576 /* Nullable */)) { + if (t.flags & (256 /* BooleanLiteral */ | 512 /* EnumLiteral */)) { + var baseType = t.flags & 256 /* BooleanLiteral */ ? booleanType : getBaseTypeOfEnumLiteralType(t); + if (baseType.flags & 262144 /* Union */) { var count = baseType.types.length; if (i + count <= types.length && types[i + count - 1] === baseType.types[count - 1]) { result.push(baseType); @@ -28227,25 +32680,25 @@ var ts; result.push(t); } } - if (flags & 16384) + if (flags & 16384 /* Null */) result.push(nullType); - if (flags & 8192) + if (flags & 8192 /* Undefined */) result.push(undefinedType); return result || types; } function visibilityToString(flags) { - if (flags === 8) { + if (flags === 8 /* Private */) { return "private"; } - if (flags === 16) { + if (flags === 16 /* Protected */) { return "protected"; } return "public"; } function getTypeAliasForTypeLiteral(type) { - if (type.symbol && type.symbol.flags & 2048) { - var node = ts.findAncestor(type.symbol.declarations[0].parent, function (n) { return n.kind !== 173; }); - if (node.kind === 237) { + if (type.symbol && type.symbol.flags & 2048 /* TypeLiteral */) { + var node = ts.findAncestor(type.symbol.declarations[0].parent, function (n) { return n.kind !== 173 /* ParenthesizedType */; }); + if (node.kind === 237 /* TypeAliasDeclaration */) { return getSymbolOfNode(node); } } @@ -28253,32 +32706,43 @@ var ts; } function isTopLevelInExternalModuleAugmentation(node) { return node && node.parent && - node.parent.kind === 240 && + node.parent.kind === 240 /* ModuleBlock */ && ts.isExternalModuleAugmentation(node.parent.parent); } function isDefaultBindingContext(location) { - return location.kind === 274 || ts.isAmbientModule(location); + return location.kind === 274 /* SourceFile */ || ts.isAmbientModule(location); } + /** + * Gets a human-readable name for a symbol. + * Should *not* be used for the right-hand side of a `.` -- use `symbolName(symbol)` for that instead. + * + * Unlike `symbolName(symbol)`, this will include quotes if the name is from a string literal. + * It will also use a representation of a number as written instead of a decimal form, e.g. `0o11` instead of `9`. + */ function getNameOfSymbolAsWritten(symbol, context) { - if (context && symbol.escapedName === "default" && !(context.flags & 16384) && - (!(context.flags & 16777216) || + if (context && symbol.escapedName === "default" /* Default */ && !(context.flags & 16384 /* UseAliasDefinedOutsideCurrentScope */) && + // If it's not the first part of an entity name, it must print as `default` + (!(context.flags & 16777216 /* InInitialEntityName */) || + // if the symbol is synthesized, it will only be referenced externally it must print as `default` !symbol.declarations || + // if not in the same binding context (source file, module declaration), it must print as `default` (context.enclosingDeclaration && ts.findAncestor(symbol.declarations[0], isDefaultBindingContext) !== ts.findAncestor(context.enclosingDeclaration, isDefaultBindingContext)))) { return "default"; } if (symbol.declarations && symbol.declarations.length) { - if (ts.some(symbol.declarations, hasExternalModuleSymbol) && context.enclosingDeclaration) { - var file = ts.getDeclarationOfKind(symbol, 274); + if (ts.some(symbol.declarations, hasExternalModuleSymbol) && context.enclosingDeclaration) { // TODO: GH#18217 + var file = ts.getDeclarationOfKind(symbol, 274 /* SourceFile */); if (!file || !context.tracker.moduleResolverHost) { if (context.tracker.trackReferencedAmbientModule) { var ambientDecls = ts.filter(symbol.declarations, ts.isAmbientModule); if (ts.length(ambientDecls)) { for (var _i = 0, ambientDecls_1 = ambientDecls; _i < ambientDecls_1.length; _i++) { var decl = ambientDecls_1[_i]; - context.tracker.trackReferencedAmbientModule(decl); + context.tracker.trackReferencedAmbientModule(decl); // TODO: GH#18217 } } } + // ambient module, just use declaration/symbol name (fallthrough) } else { var contextFile = ts.getSourceFileOfNode(ts.getOriginalNode(context.enclosingDeclaration)); @@ -28290,26 +32754,26 @@ var ts; if (name) { return ts.declarationNameToString(name); } - if (declaration.parent && declaration.parent.kind === 232) { + if (declaration.parent && declaration.parent.kind === 232 /* VariableDeclaration */) { return ts.declarationNameToString(declaration.parent.name); } - if (context && !context.encounteredError && !(context.flags & 131072)) { + if (context && !context.encounteredError && !(context.flags & 131072 /* AllowAnonymousIdentifier */)) { context.encounteredError = true; } switch (declaration.kind) { - case 205: + case 205 /* ClassExpression */: return "(Anonymous class)"; - case 192: - case 193: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: return "(Anonymous function)"; } } var nameType = symbol.nameType; if (nameType) { - if (nameType.flags & 64 && !ts.isIdentifierText(nameType.value, compilerOptions.target)) { - return "\"" + ts.escapeString(nameType.value, 34) + "\""; + if (nameType.flags & 64 /* StringLiteral */ && !ts.isIdentifierText(nameType.value, compilerOptions.target)) { + return "\"" + ts.escapeString(nameType.value, 34 /* doubleQuote */) + "\""; } - if (nameType && nameType.flags & 2048) { + if (nameType && nameType.flags & 2048 /* UniqueESSymbol */) { return "[" + getNameOfSymbolAsWritten(nameType.symbol, context) + "]"; } } @@ -28326,66 +32790,81 @@ var ts; return false; function determineIfDeclarationIsVisible() { switch (node.kind) { - case 292: - case 298: + case 292 /* JSDocCallbackTag */: + case 298 /* JSDocTypedefTag */: + // Top-level jsdoc type aliases are considered exported + // First parent is comment node, second is hosting declaration or token; we only care about those tokens or declarations whose parent is a source file return !!(node.parent && node.parent.parent && node.parent.parent.parent && ts.isSourceFile(node.parent.parent.parent)); - case 182: + case 182 /* BindingElement */: return isDeclarationVisible(node.parent.parent); - case 232: + case 232 /* VariableDeclaration */: if (ts.isBindingPattern(node.name) && !node.name.elements.length) { + // If the binding pattern is empty, this variable declaration is not visible return false; } - case 239: - case 235: - case 236: - case 237: - case 234: - case 238: - case 243: + // falls through + case 239 /* ModuleDeclaration */: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 234 /* FunctionDeclaration */: + case 238 /* EnumDeclaration */: + case 243 /* ImportEqualsDeclaration */: + // external module augmentation is always visible if (ts.isExternalModuleAugmentation(node)) { return true; } var parent = getDeclarationContainer(node); - if (!(ts.getCombinedModifierFlags(node) & 1) && - !(node.kind !== 243 && parent.kind !== 274 && parent.flags & 4194304)) { + // If the node is not exported or it is not ambient module element (except import declaration) + if (!(ts.getCombinedModifierFlags(node) & 1 /* Export */) && + !(node.kind !== 243 /* ImportEqualsDeclaration */ && parent.kind !== 274 /* SourceFile */ && parent.flags & 4194304 /* Ambient */)) { return isGlobalSourceFile(parent); } + // Exported members/ambient module elements (exception import declaration) are visible if parent is visible return isDeclarationVisible(parent); - case 152: - case 151: - case 156: - case 157: - case 154: - case 153: - if (ts.hasModifier(node, 8 | 16)) { + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + if (ts.hasModifier(node, 8 /* Private */ | 16 /* Protected */)) { + // Private/protected properties/methods are not visible return false; } - case 155: - case 159: - case 158: - case 160: - case 149: - case 240: - case 163: - case 164: - case 166: - case 162: - case 167: - case 168: - case 169: - case 170: - case 173: + // Public properties/methods are visible if its parents are visible, so: + // falls through + case 155 /* Constructor */: + case 159 /* ConstructSignature */: + case 158 /* CallSignature */: + case 160 /* IndexSignature */: + case 149 /* Parameter */: + case 240 /* ModuleBlock */: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 166 /* TypeLiteral */: + case 162 /* TypeReference */: + case 167 /* ArrayType */: + case 168 /* TupleType */: + case 169 /* UnionType */: + case 170 /* IntersectionType */: + case 173 /* ParenthesizedType */: return isDeclarationVisible(node.parent); - case 245: - case 246: - case 248: + // Default binding, import specifier and namespace import is visible + // only on demand so by default it is not visible + case 245 /* ImportClause */: + case 246 /* NamespaceImport */: + case 248 /* ImportSpecifier */: return false; - case 148: - case 274: - case 242: + // Type parameters are always visible + case 148 /* TypeParameter */: + // Source file and namespace export are always visible + case 274 /* SourceFile */: + case 242 /* NamespaceExportDeclaration */: return true; - case 249: + // Export assignments do not create name bindings outside the module + case 249 /* ExportAssignment */: return false; default: return false; @@ -28394,11 +32873,11 @@ var ts; } function collectLinkedAliases(node, setVisibility) { var exportSymbol; - if (node.parent && node.parent.kind === 249) { - exportSymbol = resolveName(node, node.escapedText, 67216319 | 67901928 | 1920 | 2097152, undefined, node, false); + if (node.parent && node.parent.kind === 249 /* ExportAssignment */) { + exportSymbol = resolveName(node, node.escapedText, 67216319 /* Value */ | 67901928 /* Type */ | 1920 /* Namespace */ | 2097152 /* Alias */, /*nameNotFoundMessage*/ undefined, node, /*isUse*/ false); } - else if (node.parent.kind === 252) { - exportSymbol = getTargetOfExportSpecifier(node.parent, 67216319 | 67901928 | 1920 | 2097152); + else if (node.parent.kind === 252 /* ExportSpecifier */) { + exportSymbol = getTargetOfExportSpecifier(node.parent, 67216319 /* Value */ | 67901928 /* Type */ | 1920 /* Namespace */ | 2097152 /* Alias */); } var result; if (exportSymbol) { @@ -28416,9 +32895,10 @@ var ts; ts.pushIfUnique(result, resultNode); } if (ts.isInternalModuleImportEqualsDeclaration(declaration)) { + // Add the referenced top container visible var internalModuleReference = declaration.moduleReference; var firstIdentifier = getFirstIdentifier(internalModuleReference); - var importSymbol = resolveName(declaration, firstIdentifier.escapedText, 67216319 | 67901928 | 1920, undefined, undefined, false); + var importSymbol = resolveName(declaration, firstIdentifier.escapedText, 67216319 /* Value */ | 67901928 /* Type */ | 1920 /* Namespace */, undefined, undefined, /*isUse*/ false); if (importSymbol) { buildVisibleNodeList(importSymbol.declarations); } @@ -28426,9 +32906,21 @@ var 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. + * 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 + * must match the one passed in. + * + * @param target The symbol, type, or signature whose type is being queried + * @param propertyName The property name that should be used to query the target for its type + */ function pushTypeResolution(target, propertyName) { var resolutionCycleStartIndex = findResolutionCycleStartIndex(target, propertyName); if (resolutionCycleStartIndex >= 0) { + // A cycle was found var length_2 = resolutionTargets.length; for (var i = resolutionCycleStartIndex; i < length_2; i++) { resolutionResults[i] = false; @@ -28436,7 +32928,7 @@ var ts; return false; } resolutionTargets.push(target); - resolutionResults.push(true); + resolutionResults.push(/*items*/ true); resolutionPropertyNames.push(propertyName); return true; } @@ -28452,24 +32944,26 @@ var ts; return -1; } function hasType(target, propertyName) { - if (propertyName === 0) { + if (propertyName === 0 /* Type */) { return !!getSymbolLinks(target).type; } - if (propertyName === 2) { + if (propertyName === 2 /* DeclaredType */) { return !!getSymbolLinks(target).declaredType; } - if (propertyName === 1) { + if (propertyName === 1 /* ResolvedBaseConstructorType */) { return !!target.resolvedBaseConstructorType; } - if (propertyName === 3) { + if (propertyName === 3 /* ResolvedReturnType */) { return !!target.resolvedReturnType; } - if (propertyName === 4) { + if (propertyName === 4 /* ResolvedBaseConstraint */) { var bc = target.resolvedBaseConstraint; return !!bc && bc !== circularConstraintType; } return ts.Debug.fail("Unhandled TypeSystemPropertyName " + propertyName); } + // Pop an entry from the type resolution stack and return its associated result value. The result value will + // be true if no circularities were detected, or false if a circularity was found. function popTypeResolution() { resolutionTargets.pop(); resolutionPropertyNames.pop(); @@ -28478,12 +32972,12 @@ var ts; function getDeclarationContainer(node) { return ts.findAncestor(ts.getRootDeclaration(node), function (node) { switch (node.kind) { - case 232: - case 233: - case 248: - case 247: - case 246: - case 245: + case 232 /* VariableDeclaration */: + case 233 /* VariableDeclarationList */: + case 248 /* ImportSpecifier */: + case 247 /* NamedImports */: + case 246 /* NamespaceImport */: + case 245 /* ImportClause */: return false; default: return true; @@ -28491,29 +32985,36 @@ var ts; }).parent; } function getTypeOfPrototypeProperty(prototype) { + // TypeScript 1.0 spec (April 2014): 8.4 + // Every class automatically contains a static property member named 'prototype', + // the type of which is an instantiation of the class type with type Any supplied as a type argument for each type parameter. + // It is an error to explicitly declare a static property member with the name 'prototype'. var classType = getDeclaredTypeOfSymbol(getParentOfSymbol(prototype)); return classType.typeParameters ? createTypeReference(classType, ts.map(classType.typeParameters, function (_) { return anyType; })) : classType; } + // Return the type of the given property in the given type, or undefined if no such property exists function getTypeOfPropertyOfType(type, name) { var prop = getPropertyOfType(type, name); return prop ? getTypeOfSymbol(prop) : undefined; } function isTypeAny(type) { - return type && (type.flags & 1) !== 0; + return type && (type.flags & 1 /* Any */) !== 0; } + // Return the type of a binding element parent. We check SymbolLinks first to see if a type has been + // assigned by contextual typing. function getTypeForBindingElementParent(node) { var symbol = getSymbolOfNode(node); - return symbol && getSymbolLinks(symbol).type || getTypeForVariableLikeDeclaration(node, false); + return symbol && getSymbolLinks(symbol).type || getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false); } function isComputedNonLiteralName(name) { - return name.kind === 147 && !ts.isStringOrNumericLiteral(name.expression); + return name.kind === 147 /* ComputedPropertyName */ && !ts.isStringOrNumericLiteral(name.expression); } function getRestType(source, properties, symbol) { - source = filterType(source, function (t) { return !(t.flags & 24576); }); - if (source.flags & 32768) { + source = filterType(source, function (t) { return !(t.flags & 24576 /* Nullable */); }); + if (source.flags & 32768 /* Never */) { return emptyObjectType; } - if (source.flags & 262144) { + if (source.flags & 262144 /* Union */) { return mapType(source, function (t) { return getRestType(t, properties, symbol); }); } var members = ts.createSymbolTable(); @@ -28525,22 +33026,27 @@ var ts; for (var _a = 0, _b = getPropertiesOfType(source); _a < _b.length; _a++) { var prop = _b[_a]; var inNamesToRemove = names.has(prop.escapedName); - var isPrivate = ts.getDeclarationModifierFlagsFromSymbol(prop) & (8 | 16); - var isSetOnlyAccessor = prop.flags & 65536 && !(prop.flags & 32768); + var isPrivate = ts.getDeclarationModifierFlagsFromSymbol(prop) & (8 /* Private */ | 16 /* Protected */); + var isSetOnlyAccessor = prop.flags & 65536 /* SetAccessor */ && !(prop.flags & 32768 /* GetAccessor */); if (!inNamesToRemove && !isPrivate && !isClassMethod(prop) && !isSetOnlyAccessor) { members.set(prop.escapedName, getNonReadonlySymbol(prop)); } } - var stringIndexInfo = getIndexInfoOfType(source, 0); - var numberIndexInfo = getIndexInfoOfType(source, 1); + var stringIndexInfo = getIndexInfoOfType(source, 0 /* String */); + var numberIndexInfo = getIndexInfoOfType(source, 1 /* Number */); return createAnonymousType(symbol, members, ts.emptyArray, ts.emptyArray, stringIndexInfo, numberIndexInfo); } + /** Return the inferred type for a binding element */ function getTypeForBindingElement(declaration) { var pattern = declaration.parent; var parentType = getTypeForBindingElementParent(pattern.parent); + // If parent has the unknown (error) type, then so does this binding element if (parentType === errorType) { return errorType; } + // If no type was specified or inferred for parent, + // infer from the initializer of the binding element if one is present. + // Otherwise, go with the undefined type of the parent. if (!parentType) { return declaration.initializer ? checkDeclarationInitializer(declaration) : parentType; } @@ -28548,9 +33054,9 @@ var ts; return parentType; } var type; - if (pattern.kind === 180) { + if (pattern.kind === 180 /* ObjectBindingPattern */) { if (declaration.dotDotDotToken) { - if (parentType.flags & 2 || !isValidSpreadType(parentType)) { + if (parentType.flags & 2 /* Unknown */ || !isValidSpreadType(parentType)) { error(declaration, ts.Diagnostics.Rest_types_may_only_be_created_from_object_types); return errorType; } @@ -28564,20 +33070,21 @@ var ts; type = getRestType(parentType, literalMembers, declaration.symbol); } else { + // Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form) var name = declaration.propertyName || declaration.name; var isLate = isLateBindableName(name); var isWellKnown = ts.isComputedPropertyName(name) && ts.isWellKnownSymbolSyntactically(name.expression); if (!isLate && !isWellKnown && isComputedNonLiteralName(name)) { var exprType = checkExpression(name.expression); - if (isTypeAssignableToKind(exprType, 3072)) { + if (isTypeAssignableToKind(exprType, 3072 /* ESSymbolLike */)) { if (noImplicitAny) { error(declaration, ts.Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(exprType), typeToString(parentType)); } return anyType; } - var indexerType = isTypeAssignableToKind(exprType, 168) && getIndexTypeOfType(parentType, 1) || getIndexTypeOfType(parentType, 0); + var indexerType = isTypeAssignableToKind(exprType, 168 /* NumberLike */) && getIndexTypeOfType(parentType, 1 /* Number */) || getIndexTypeOfType(parentType, 0 /* String */); if (!indexerType && noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors) { - if (getIndexTypeOfType(parentType, 1)) { + if (getIndexTypeOfType(parentType, 1 /* Number */)) { error(declaration, ts.Diagnostics.Element_implicitly_has_an_any_type_because_index_expression_is_not_of_type_number); } else { @@ -28586,14 +33093,17 @@ var ts; } return indexerType || anyType; } + // Use type of the specified property, or otherwise, for a numeric name, the type of the numeric index signature, + // or otherwise the type of the string index signature. var nameType = isLate ? checkComputedPropertyName(name) : undefined; var text = isLate ? getLateBoundNameFromType(nameType) : isWellKnown ? ts.getPropertyNameForKnownSymbolName(ts.idText(name.expression.name)) : ts.getTextOfPropertyName(name); - if (strictNullChecks && declaration.flags & 4194304 && ts.isParameterDeclaration(declaration)) { + // Relax null check on ambient destructuring parameters, since the parameters have no implementation and are just documentation + if (strictNullChecks && declaration.flags & 4194304 /* Ambient */ && ts.isParameterDeclaration(declaration)) { parentType = getNonNullableType(parentType); } - if (isLate && nameType && !getPropertyOfType(parentType, text) && isTypeAssignableToKind(nameType, 3072)) { + if (isLate && nameType && !getPropertyOfType(parentType, text) && isTypeAssignableToKind(nameType, 3072 /* ESSymbolLike */)) { if (noImplicitAny) { error(declaration, ts.Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(nameType), typeToString(parentType)); } @@ -28601,8 +33111,8 @@ var ts; } var declaredType = getConstraintForLocation(getTypeOfPropertyOfType(parentType, text), declaration.name); type = declaredType && getFlowTypeOfReference(declaration, declaredType) || - isNumericLiteralName(text) && getIndexTypeOfType(parentType, 1) || - getIndexTypeOfType(parentType, 0); + isNumericLiteralName(text) && getIndexTypeOfType(parentType, 1 /* Number */) || + getIndexTypeOfType(parentType, 0 /* String */); if (!type) { error(name, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(parentType), ts.declarationNameToString(name)); return errorType; @@ -28610,11 +33120,16 @@ var ts; } } else { - var elementType = checkIteratedTypeOrElementType(parentType, pattern, false, false); + // This elementType will be used if the specific property corresponding to this index is not + // present (aka the tuple element property). This call also checks that the parentType is in + // fact an iterable or array (depending on target language). + var elementType = checkIteratedTypeOrElementType(parentType, pattern, /*allowStringInput*/ false, /*allowAsyncIterables*/ false); if (declaration.dotDotDotToken) { + // Rest element has an array type with the same element type as the parent type type = createArrayType(elementType); } else { + // Use specific property type when parent is a tuple or numeric index type when parent is an array var propName = "" + pattern.elements.indexOf(declaration); type = isTupleLikeType(parentType) ? getTypeOfPropertyOfType(parentType, propName) @@ -28630,11 +33145,13 @@ var ts; } } } - if (strictNullChecks && declaration.initializer && !(getFalsyFlags(checkExpressionCached(declaration.initializer)) & 8192)) { - type = getTypeWithFacts(type, 131072); + // In strict null checking mode, if a default value of a non-undefined type is specified, remove + // undefined from the final type. + if (strictNullChecks && declaration.initializer && !(getFalsyFlags(checkExpressionCached(declaration.initializer)) & 8192 /* Undefined */)) { + type = getTypeWithFacts(type, 131072 /* NEUndefined */); } return declaration.initializer ? - getUnionType([type, checkExpressionCached(declaration.initializer)], 2) : + getUnionType([type, checkExpressionCached(declaration.initializer)], 2 /* Subtype */) : type; } function getTypeForDeclarationFromJSDocComment(declaration) { @@ -28646,22 +33163,29 @@ var ts; } function isNullOrUndefined(node) { var expr = ts.skipParentheses(node); - return expr.kind === 95 || expr.kind === 71 && getResolvedSymbol(expr) === undefinedSymbol; + return expr.kind === 95 /* NullKeyword */ || expr.kind === 71 /* Identifier */ && getResolvedSymbol(expr) === undefinedSymbol; } function isEmptyArrayLiteral(node) { var expr = ts.skipParentheses(node); - return expr.kind === 183 && expr.elements.length === 0; + return expr.kind === 183 /* ArrayLiteralExpression */ && expr.elements.length === 0; } function addOptionality(type, optional) { if (optional === void 0) { optional = true; } return strictNullChecks && optional ? getOptionalType(type) : type; } + // Return the inferred type for a variable, parameter, or property declaration function getTypeForVariableLikeDeclaration(declaration, includeOptionality) { - if (ts.isVariableDeclaration(declaration) && declaration.parent.parent.kind === 221) { + // A variable declared in a for..in statement is of type string, or of type keyof T when the + // right hand expression is of a type parameter type. + if (ts.isVariableDeclaration(declaration) && declaration.parent.parent.kind === 221 /* ForInStatement */) { var indexType = getIndexType(checkNonNullExpression(declaration.parent.parent.expression)); - return indexType.flags & (65536 | 1048576) ? getExtractStringType(indexType) : stringType; + return indexType.flags & (65536 /* TypeParameter */ | 1048576 /* Index */) ? getExtractStringType(indexType) : stringType; } - if (ts.isVariableDeclaration(declaration) && declaration.parent.parent.kind === 222) { + if (ts.isVariableDeclaration(declaration) && declaration.parent.parent.kind === 222 /* ForOfStatement */) { + // checkRightHandSideOfForOf will return undefined if the for-of expression type was + // missing properties/signatures required to get its iteratedType (like + // [Symbol.iterator] or next). This may be because we accessed properties from anyType, + // or it may have led to an error inside getElementTypeOfIterable. var forOfStatement = declaration.parent.parent; return checkRightHandSideOfForOf(forOfStatement.expression, forOfStatement.awaitModifier) || anyType; } @@ -28670,34 +33194,43 @@ var ts; } var isOptional = includeOptionality && (ts.isParameter(declaration) && isJSDocOptionalParameter(declaration) || !ts.isBindingElement(declaration) && !ts.isVariableDeclaration(declaration) && !!declaration.questionToken); + // Use type from type annotation if one is present var declaredType = tryGetTypeFromEffectiveTypeNode(declaration); if (declaredType) { return addOptionality(declaredType, isOptional); } if ((noImplicitAny || ts.isInJavaScriptFile(declaration)) && - declaration.kind === 232 && !ts.isBindingPattern(declaration.name) && - !(ts.getCombinedModifierFlags(declaration) & 1) && !(declaration.flags & 4194304)) { - if (!(ts.getCombinedNodeFlags(declaration) & 2) && (!declaration.initializer || isNullOrUndefined(declaration.initializer))) { + declaration.kind === 232 /* VariableDeclaration */ && !ts.isBindingPattern(declaration.name) && + !(ts.getCombinedModifierFlags(declaration) & 1 /* Export */) && !(declaration.flags & 4194304 /* Ambient */)) { + // If --noImplicitAny is on or the declaration is in a Javascript file, + // use control flow tracked 'any' type for non-ambient, non-exported var or let variables with no + // initializer or a 'null' or 'undefined' initializer. + if (!(ts.getCombinedNodeFlags(declaration) & 2 /* Const */) && (!declaration.initializer || isNullOrUndefined(declaration.initializer))) { return autoType; } + // Use control flow tracked 'any[]' type for non-ambient, non-exported variables with an empty array + // literal initializer. if (declaration.initializer && isEmptyArrayLiteral(declaration.initializer)) { return autoArrayType; } } - if (declaration.kind === 149) { + if (declaration.kind === 149 /* Parameter */) { var func = declaration.parent; - if (func.kind === 157 && !hasNonBindableDynamicName(func)) { - var getter = ts.getDeclarationOfKind(getSymbolOfNode(declaration.parent), 156); + // For a parameter of a set accessor, use the type of the get accessor if one is present + if (func.kind === 157 /* SetAccessor */ && !hasNonBindableDynamicName(func)) { + var getter = ts.getDeclarationOfKind(getSymbolOfNode(declaration.parent), 156 /* GetAccessor */); if (getter) { var getterSignature = getSignatureFromDeclaration(getter); var thisParameter = getAccessorThisParameter(func); if (thisParameter && declaration === thisParameter) { + // Use the type from the *getter* ts.Debug.assert(!thisParameter.type); return getTypeOfSymbol(getterSignature.thisParameter); } return getReturnTypeOfSignature(getterSignature); } } + // Use contextual parameter type if one is available var type = void 0; if (declaration.symbol.escapedName === "this") { type = getContextualThisParameterType(func); @@ -28709,19 +33242,25 @@ var ts; return addOptionality(type, isOptional); } } + // Use the type of the initializer expression if one is present if (declaration.initializer) { var type = checkDeclarationInitializer(declaration); return addOptionality(type, isOptional); } if (ts.isJsxAttribute(declaration)) { + // if JSX attribute doesn't have initializer, by default the attribute will have boolean value of true. + // I.e is sugar for return trueType; } + // If the declaration specifies a binding pattern, use the type implied by the binding pattern if (ts.isBindingPattern(declaration.name)) { - return getTypeFromBindingPattern(declaration.name, false, true); + return getTypeFromBindingPattern(declaration.name, /*includePatternInType*/ false, /*reportErrors*/ true); } + // No type specified and nothing can be inferred return undefined; } function getWidenedTypeFromJSSpecialPropertyDeclarations(symbol) { + // function/class/{} assignments are fresh declarations, not property assignments, so only add prototype assignments var specialDeclaration = ts.getAssignedJavascriptInitializer(symbol.valueDeclaration); if (specialDeclaration) { return getWidenedLiteralType(checkExpressionCached(specialDeclaration)); @@ -28733,18 +33272,20 @@ var ts; var jsDocType; var _loop_4 = function (declaration) { var declarationInConstructor = false; - var expression = declaration.kind === 200 ? declaration : - declaration.kind === 185 ? ts.cast(declaration.parent, ts.isBinaryExpression) : + var expression = declaration.kind === 200 /* BinaryExpression */ ? declaration : + declaration.kind === 185 /* PropertyAccessExpression */ ? ts.cast(declaration.parent, ts.isBinaryExpression) : undefined; if (!expression) { return { value: errorType }; } var special = ts.getSpecialPropertyAssignmentKind(expression); - if (special === 4) { - var thisContainer = ts.getThisContainer(expression, false); - declarationInConstructor = thisContainer.kind === 155 || - thisContainer.kind === 234 || - (thisContainer.kind === 192 && !ts.isPrototypePropertyAssignment(thisContainer.parent)); + if (special === 4 /* ThisProperty */) { + var thisContainer = ts.getThisContainer(expression, /*includeArrowFunctions*/ false); + // Properties defined in a constructor (or base constructor, or javascript constructor function) don't get undefined added. + // Function expressions that are assigned to the prototype count as methods. + declarationInConstructor = thisContainer.kind === 155 /* Constructor */ || + thisContainer.kind === 234 /* FunctionDeclaration */ || + (thisContainer.kind === 192 /* FunctionExpression */ && !ts.isPrototypePropertyAssignment(thisContainer.parent)); if (declarationInConstructor) { definedInConstructor = true; } @@ -28752,6 +33293,7 @@ var ts; definedInMethod = true; } } + // If there is a JSDoc type, use it var type_1 = getTypeForDeclarationFromJSDocComment(expression.parent); if (type_1) { var declarationType = getWidenedType(type_1); @@ -28760,15 +33302,16 @@ var ts; } else if (jsDocType !== errorType && declarationType !== errorType && !isTypeIdenticalTo(jsDocType, declarationType) && - !(symbol.flags & 67108864)) { + !(symbol.flags & 67108864 /* JSContainer */)) { errorNextVariableOrPropertyDeclarationMustHaveSameType(jsDocType, declaration, declarationType); } } else if (!jsDocType) { + // If we don't have an explicit JSDoc type, get the type from the expression. var type_2 = getWidenedLiteralType(checkExpressionCached(expression.right)); - if (ts.getObjectFlags(type_2) & 16 && - special === 2 && - symbol.escapedName === "export=") { + if (ts.getObjectFlags(type_2) & 16 /* Anonymous */ && + special === 2 /* ModuleExports */ && + symbol.escapedName === "export=" /* ExportEquals */) { var exportedType_1 = resolveStructuredTypeMembers(type_2); var members_3 = ts.createSymbolTable(); ts.copyEntries(exportedType_1.members, members_3); @@ -28806,6 +33349,7 @@ var ts; } var type = jsDocType; if (!type) { + // use only the constructor types unless they were only assigned null | undefined (including widening variants) if (definedInMethod) { var propType = getTypeOfSpecialPropertyOfBaseType(symbol); if (propType) { @@ -28813,11 +33357,11 @@ var ts; definedInConstructor = true; } } - var sourceTypes = ts.some(constructorTypes, function (t) { return !!(t.flags & ~(24576 | 134217728)); }) ? constructorTypes : types; - type = getUnionType(sourceTypes, 2); + var sourceTypes = ts.some(constructorTypes, function (t) { return !!(t.flags & ~(24576 /* Nullable */ | 134217728 /* ContainsWideningType */)); }) ? constructorTypes : types; // TODO: GH#18217 + type = getUnionType(sourceTypes, 2 /* Subtype */); } var widened = getWidenedType(addOptionality(type, definedInMethod && !definedInConstructor)); - if (filterType(widened, function (t) { return !!(t.flags & ~24576); }) === neverType) { + if (filterType(widened, function (t) { return !!(t.flags & ~24576 /* Nullable */); }) === neverType) { if (noImplicitAny) { reportImplicitAnyError(symbol.valueDeclaration, anyType); } @@ -28825,9 +33369,10 @@ var ts; } return widened; } + /** check for definition in base class if any declaration is in a class */ function getTypeOfSpecialPropertyOfBaseType(specialProperty) { var parentDeclaration = ts.forEach(specialProperty.declarations, function (d) { - var parent = ts.getThisContainer(d, false).parent; + var parent = ts.getThisContainer(d, /*includeArrowFunctions*/ false).parent; return ts.isClassLike(parent) && parent; }); if (parentDeclaration) { @@ -28838,6 +33383,9 @@ var ts; } } } + // Return the type implied by a binding pattern element. This is the type of the initializer of the element if + // one is present. Otherwise, if the element is itself a binding pattern, it is the type implied by the binding + // pattern. Otherwise, it is the type any. function getTypeFromBindingElement(element, includePatternInType, reportErrors) { if (element.initializer) { return checkDeclarationInitializer(element); @@ -28850,41 +33398,45 @@ var ts; } return anyType; } + // Return the type implied by an object binding pattern function getTypeFromObjectBindingPattern(pattern, includePatternInType, reportErrors) { var members = ts.createSymbolTable(); var stringIndexInfo; - var objectFlags = 128; + var objectFlags = 128 /* ObjectLiteral */; ts.forEach(pattern.elements, function (e) { var name = e.propertyName || e.name; if (isComputedNonLiteralName(name)) { - objectFlags |= 512; + // do not include computed properties in the implied type + objectFlags |= 512 /* ObjectLiteralPatternWithComputedProperties */; return; } if (e.dotDotDotToken) { - stringIndexInfo = createIndexInfo(anyType, false); + stringIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false); return; } var text = ts.getTextOfPropertyName(name); - var flags = 4 | (e.initializer ? 16777216 : 0); + var flags = 4 /* Property */ | (e.initializer ? 16777216 /* Optional */ : 0); var symbol = createSymbol(flags, text); symbol.type = getTypeFromBindingElement(e, includePatternInType, reportErrors); symbol.bindingElement = e; members.set(symbol.escapedName, symbol); }); var result = createAnonymousType(undefined, members, ts.emptyArray, ts.emptyArray, stringIndexInfo, undefined); - result.flags |= 268435456; + result.flags |= 268435456 /* ContainsObjectLiteral */; result.objectFlags |= objectFlags; if (includePatternInType) { result.pattern = pattern; } return result; } + // Return the type implied by an array binding pattern function getTypeFromArrayBindingPattern(pattern, includePatternInType, reportErrors) { var elements = pattern.elements; var lastElement = ts.lastOrUndefined(elements); if (!lastElement || (!ts.isOmittedExpression(lastElement) && lastElement.dotDotDotToken)) { - return languageVersion >= 2 ? createIterableType(anyType) : anyArrayType; + return languageVersion >= 2 /* ES2015 */ ? createIterableType(anyType) : anyArrayType; } + // If the pattern has at least one element, and no rest element, then it should imply a tuple type. var elementTypes = ts.map(elements, function (e) { return ts.isOmittedExpression(e) ? anyType : getTypeFromBindingElement(e, includePatternInType, reportErrors); }); var result = createTupleType(elementTypes); if (includePatternInType) { @@ -28893,27 +33445,46 @@ var ts; } return result; } + // Return the type implied by a binding pattern. This is the type implied purely by the binding pattern itself + // and without regard to its context (i.e. without regard any type annotation or initializer associated with the + // declaration in which the binding pattern is contained). For example, the implied type of [x, y] is [any, any] + // and the implied type of { x, y: z = 1 } is { x: any; y: number; }. The type implied by a binding pattern is + // used as the contextual type of an initializer associated with the binding pattern. Also, for a destructuring + // parameter with no type annotation or initializer, the type implied by the binding pattern becomes the type of + // the parameter. function getTypeFromBindingPattern(pattern, includePatternInType, reportErrors) { if (includePatternInType === void 0) { includePatternInType = false; } if (reportErrors === void 0) { reportErrors = false; } - return pattern.kind === 180 + return pattern.kind === 180 /* ObjectBindingPattern */ ? getTypeFromObjectBindingPattern(pattern, includePatternInType, reportErrors) : getTypeFromArrayBindingPattern(pattern, includePatternInType, reportErrors); } + // Return the type associated with a variable, parameter, or property declaration. In the simple case this is the type + // specified in a type annotation or inferred from an initializer. However, in the case of a destructuring declaration it + // is a bit more involved. For example: + // + // var [x, s = ""] = [1, "one"]; + // + // Here, the array literal [1, "one"] is contextually typed by the type [any, string], which is the implied type of the + // binding pattern [x, s = ""]. Because the contextual type is a tuple type, the resulting type of [1, "one"] is the + // tuple type [number, string]. Thus, the type inferred for 'x' is number and the type inferred for 's' is string. function getWidenedTypeForVariableLikeDeclaration(declaration, reportErrors) { - return widenTypeForVariableLikeDeclaration(getTypeForVariableLikeDeclaration(declaration, true), declaration, reportErrors); + return widenTypeForVariableLikeDeclaration(getTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ true), declaration, reportErrors); } function widenTypeForVariableLikeDeclaration(type, declaration, reportErrors) { if (type) { if (reportErrors) { reportErrorsFromWidening(declaration, type); } - if (type.flags & 2048 && (ts.isBindingElement(declaration) || !declaration.type) && type.symbol !== getSymbolOfNode(declaration)) { + // always widen a 'unique symbol' type if the type was created for a different declaration. + if (type.flags & 2048 /* UniqueESSymbol */ && (ts.isBindingElement(declaration) || !declaration.type) && type.symbol !== getSymbolOfNode(declaration)) { type = esSymbolType; } return getWidenedType(type); } + // Rest parameters default to type any[], other parameters default to type any type = ts.isParameter(declaration) && declaration.dotDotDotToken ? anyArrayType : anyType; + // Report implicit any errors unless this is a private property within an ambient declaration if (reportErrors && noImplicitAny) { if (!declarationBelongsToPrivateAmbientMember(declaration)) { reportImplicitAnyError(declaration, type); @@ -28923,7 +33494,7 @@ var ts; } function declarationBelongsToPrivateAmbientMember(declaration) { var root = ts.getRootDeclaration(declaration); - var memberDeclaration = root.kind === 149 ? root.parent : root; + var memberDeclaration = root.kind === 149 /* Parameter */ ? root.parent : root; return isPrivateWithinAmbient(memberDeclaration); } function tryGetTypeFromEffectiveTypeNode(declaration) { @@ -28935,24 +33506,29 @@ var ts; function getTypeOfVariableOrParameterOrProperty(symbol) { var links = getSymbolLinks(symbol); if (!links.type) { - if (symbol.flags & 4194304) { + // Handle prototype property + if (symbol.flags & 4194304 /* Prototype */) { return links.type = getTypeOfPrototypeProperty(symbol); } + // CommonsJS require and module both have type any. if (symbol === requireSymbol || symbol === moduleSymbol) { return links.type = anyType; } + // Handle catch clause variables var declaration = symbol.valueDeclaration; if (ts.isCatchClauseVariableDeclarationOrBindingElement(declaration)) { return links.type = anyType; } + // Handle export default expressions if (ts.isSourceFile(declaration)) { var jsonSourceFile = ts.cast(declaration, ts.isJsonSourceFile); return links.type = jsonSourceFile.statements.length ? checkExpression(jsonSourceFile.statements[0].expression) : emptyObjectType; } - if (declaration.kind === 249) { + if (declaration.kind === 249 /* ExportAssignment */) { return links.type = checkExpression(declaration.expression); } - if (!pushTypeResolution(symbol, 0)) { + // Handle variable, parameter or property + if (!pushTypeResolution(symbol, 0 /* Type */)) { return errorType; } var type = getJSSpecialType(symbol, declaration); @@ -28964,7 +33540,8 @@ var ts; || ts.isFunctionDeclaration(declaration) || (ts.isMethodDeclaration(declaration) && !ts.isObjectLiteralMethod(declaration)) || ts.isMethodSignature(declaration)) { - if (symbol.flags & (16 | 8192 | 32 | 384 | 512)) { + // Symbol is property of some kind that is merged with something - should use `getTypeOfFuncClassEnumModule` and not `getTypeOfVariableOrParameterOrProperty` + if (symbol.flags & (16 /* Function */ | 8192 /* Method */ | 32 /* Class */ | 384 /* Enum */ | 512 /* ValueModule */)) { return getTypeOfFuncClassEnumModule(symbol); } type = tryGetTypeFromEffectiveTypeNode(declaration) || anyType; @@ -28976,17 +33553,17 @@ var ts; type = tryGetTypeFromEffectiveTypeNode(declaration) || checkJsxAttribute(declaration); } else if (ts.isShorthandPropertyAssignment(declaration)) { - type = tryGetTypeFromEffectiveTypeNode(declaration) || checkExpressionForMutableLocation(declaration.name, 0); + type = tryGetTypeFromEffectiveTypeNode(declaration) || checkExpressionForMutableLocation(declaration.name, 0 /* Normal */); } else if (ts.isObjectLiteralMethod(declaration)) { - type = tryGetTypeFromEffectiveTypeNode(declaration) || checkObjectLiteralMethod(declaration, 0); + type = tryGetTypeFromEffectiveTypeNode(declaration) || checkObjectLiteralMethod(declaration, 0 /* Normal */); } else if (ts.isParameter(declaration) || ts.isPropertyDeclaration(declaration) || ts.isPropertySignature(declaration) || ts.isVariableDeclaration(declaration) || ts.isBindingElement(declaration)) { - type = getWidenedTypeForVariableLikeDeclaration(declaration, true); + type = getWidenedTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ true); } else { return ts.Debug.fail("Unhandled declaration kind! " + ts.Debug.showSyntaxKind(declaration) + " for " + ts.Debug.showSymbol(symbol)); @@ -29006,6 +33583,11 @@ var ts; else if (ts.isJSDocPropertyLikeTag(decl) && decl.typeExpression) { return getTypeFromTypeNode(decl.typeExpression.type); } + // Handle certain special assignment kinds, which happen to union across multiple declarations: + // * module.exports = expr + // * exports.p = expr + // * this.p = expr + // * className.prototype.method = expr else if (ts.isBinaryExpression(decl) || ts.isPropertyAccessExpression(decl) && ts.isBinaryExpression(decl.parent)) { return getJSInitializerType(decl, symbol, ts.getAssignedJavascriptInitializer(ts.isBinaryExpression(decl) ? decl.left : decl)) || @@ -29016,12 +33598,13 @@ var ts; || ts.isPropertySignature(decl) || ts.isVariableDeclaration(decl) || ts.isBindingElement(decl)) { + // Use type from type annotation if one is present var isOptional = ts.isParameter(decl) && isJSDocOptionalParameter(decl) || !ts.isBindingElement(decl) && !ts.isVariableDeclaration(decl) && !!decl.questionToken; var declaredType = tryGetTypeFromEffectiveTypeNode(decl); return declaredType && addOptionality(declaredType, isOptional) || getJSInitializerType(decl, symbol, ts.getDeclaredJavascriptInitializer(decl)) || - getWidenedTypeForVariableLikeDeclaration(decl, true); + getWidenedTypeForVariableLikeDeclaration(decl, /*includeOptionality*/ true); } } function getJSInitializerType(decl, symbol, init) { @@ -29043,7 +33626,7 @@ var ts; } function getAnnotatedAccessorType(accessor) { if (accessor) { - if (accessor.kind === 156) { + if (accessor.kind === 156 /* GetAccessor */) { var getterTypeAnnotation = ts.getEffectiveReturnTypeNode(accessor); return getterTypeAnnotation && getTypeFromTypeNode(getterTypeAnnotation); } @@ -29064,31 +33647,35 @@ var ts; function getTypeOfAccessors(symbol) { var links = getSymbolLinks(symbol); if (!links.type) { - var getter = ts.getDeclarationOfKind(symbol, 156); - var setter = ts.getDeclarationOfKind(symbol, 157); + var getter = ts.getDeclarationOfKind(symbol, 156 /* GetAccessor */); + var setter = ts.getDeclarationOfKind(symbol, 157 /* SetAccessor */); if (getter && ts.isInJavaScriptFile(getter)) { var jsDocType = getTypeForDeclarationFromJSDocComment(getter); if (jsDocType) { return links.type = jsDocType; } } - if (!pushTypeResolution(symbol, 0)) { + if (!pushTypeResolution(symbol, 0 /* Type */)) { return errorType; } var type = void 0; + // First try to see if the user specified a return type on the get-accessor. var getterReturnType = getAnnotatedAccessorType(getter); if (getterReturnType) { type = getterReturnType; } else { + // If the user didn't specify a return type, try to use the set-accessor's parameter type. var setterParameterType = getAnnotatedAccessorType(setter); if (setterParameterType) { type = setterParameterType; } else { + // If there are no specified types, try to infer it from the body of the get accessor if it exists. if (getter && getter.body) { type = getReturnTypeFromBody(getter); } + // Otherwise, fall back to 'any'. else { if (noImplicitAny) { if (setter) { @@ -29106,7 +33693,7 @@ var ts; if (!popTypeResolution()) { type = anyType; if (noImplicitAny) { - var getter_1 = ts.getDeclarationOfKind(symbol, 156); + var getter_1 = ts.getDeclarationOfKind(symbol, 156 /* GetAccessor */); error(getter_1, ts.Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol)); } } @@ -29116,7 +33703,7 @@ var ts; } function getBaseTypeVariableOfClass(symbol) { var baseConstructorType = getBaseConstructorTypeOfClass(getDeclaredTypeOfClassOrInterface(symbol)); - return baseConstructorType.flags & 2162688 ? baseConstructorType : undefined; + return baseConstructorType.flags & 2162688 /* TypeVariable */ ? baseConstructorType : undefined; } function getTypeOfFuncClassEnumModule(symbol) { var links = getSymbolLinks(symbol); @@ -29126,6 +33713,7 @@ var ts; var jsSymbol = getSymbolOfNode(jsDeclaration); if (jsSymbol && (ts.hasEntries(jsSymbol.exports) || ts.hasEntries(jsSymbol.members))) { symbol = cloneSymbol(symbol); + // note:we overwrite links because we just cloned the symbol links = symbol; if (ts.hasEntries(jsSymbol.exports)) { symbol.exports = symbol.exports || ts.createSymbolTable(); @@ -29137,21 +33725,21 @@ var ts; } } } - if (symbol.flags & 1536 && ts.isShorthandAmbientModuleSymbol(symbol)) { + if (symbol.flags & 1536 /* Module */ && ts.isShorthandAmbientModuleSymbol(symbol)) { links.type = anyType; } - else if (symbol.valueDeclaration.kind === 200 || - symbol.valueDeclaration.kind === 185 && symbol.valueDeclaration.parent.kind === 200) { + else if (symbol.valueDeclaration.kind === 200 /* BinaryExpression */ || + symbol.valueDeclaration.kind === 185 /* PropertyAccessExpression */ && symbol.valueDeclaration.parent.kind === 200 /* BinaryExpression */) { links.type = getWidenedTypeFromJSSpecialPropertyDeclarations(symbol); } else { - var type = createObjectType(16, symbol); - if (symbol.flags & 32) { + var type = createObjectType(16 /* Anonymous */, symbol); + if (symbol.flags & 32 /* Class */) { var baseTypeVariable = getBaseTypeVariableOfClass(symbol); links.type = baseTypeVariable ? getIntersectionType([type, baseTypeVariable]) : type; } else { - links.type = strictNullChecks && symbol.flags & 16777216 ? getOptionalType(type) : type; + links.type = strictNullChecks && symbol.flags & 16777216 /* Optional */ ? getOptionalType(type) : type; } } } @@ -29168,7 +33756,12 @@ var ts; var links = getSymbolLinks(symbol); if (!links.type) { var targetSymbol = resolveAlias(symbol); - links.type = targetSymbol.flags & 67216319 + // It only makes sense to get the type of a value symbol. If the result of resolving + // the alias is not a value, then it has no type. To get the type associated with a + // type symbol, call getDeclaredTypeOfSymbol. + // This check is important because without it, a call to getTypeOfSymbol could end + // up recursively calling getTypeOfAlias, causing a stack overflow. + links.type = targetSymbol.flags & 67216319 /* Value */ ? getTypeOfSymbol(targetSymbol) : errorType; } @@ -29182,7 +33775,7 @@ var ts; links.type = errorType; } else { - if (!pushTypeResolution(symbol, 0)) { + if (!pushTypeResolution(symbol, 0 /* Type */)) { return errorType; } symbolInstantiationDepth++; @@ -29197,35 +33790,37 @@ var ts; return links.type; } function reportCircularityError(symbol) { + // Check if variable has type annotation that circularly references the variable itself if (ts.getEffectiveTypeAnnotationNode(symbol.valueDeclaration)) { error(symbol.valueDeclaration, ts.Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol)); return errorType; } + // Otherwise variable has initializer that circularly references the variable itself if (noImplicitAny) { error(symbol.valueDeclaration, ts.Diagnostics._0_implicitly_has_type_any_because_it_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer, symbolToString(symbol)); } return anyType; } function getTypeOfSymbol(symbol) { - if (ts.getCheckFlags(symbol) & 1) { + if (ts.getCheckFlags(symbol) & 1 /* Instantiated */) { return getTypeOfInstantiatedSymbol(symbol); } - if (ts.getCheckFlags(symbol) & 2048) { + if (ts.getCheckFlags(symbol) & 2048 /* ReverseMapped */) { return getTypeOfReverseMappedSymbol(symbol); } - if (symbol.flags & (3 | 4)) { + if (symbol.flags & (3 /* Variable */ | 4 /* Property */)) { return getTypeOfVariableOrParameterOrProperty(symbol); } - if (symbol.flags & (16 | 8192 | 32 | 384 | 512)) { + if (symbol.flags & (16 /* Function */ | 8192 /* Method */ | 32 /* Class */ | 384 /* Enum */ | 512 /* ValueModule */)) { return getTypeOfFuncClassEnumModule(symbol); } - if (symbol.flags & 8) { + if (symbol.flags & 8 /* EnumMember */) { return getTypeOfEnumMember(symbol); } - if (symbol.flags & 98304) { + if (symbol.flags & 98304 /* Accessor */) { return getTypeOfAccessors(symbol); } - if (symbol.flags & 2097152) { + if (symbol.flags & 2097152 /* Alias */) { return getTypeOfAlias(symbol); } return errorType; @@ -29233,25 +33828,29 @@ var ts; function isReferenceToType(type, target) { return type !== undefined && target !== undefined - && (ts.getObjectFlags(type) & 4) !== 0 + && (ts.getObjectFlags(type) & 4 /* Reference */) !== 0 && type.target === target; } function getTargetType(type) { - return ts.getObjectFlags(type) & 4 ? type.target : type; + return ts.getObjectFlags(type) & 4 /* Reference */ ? type.target : type; } + // TODO: GH#18217 If `checkBase` is undefined, we should not call this because this will always return false. function hasBaseType(type, checkBase) { return check(type); function check(type) { - if (ts.getObjectFlags(type) & (3 | 4)) { + if (ts.getObjectFlags(type) & (3 /* ClassOrInterface */ | 4 /* Reference */)) { var target = getTargetType(type); return target === checkBase || ts.some(getBaseTypes(target), check); } - else if (type.flags & 524288) { + else if (type.flags & 524288 /* Intersection */) { return ts.some(type.types, check); } return false; } } + // Appends the type parameters given by a list of declarations to a set of type parameters and returns the resulting set. + // The function allocates a new array if the input type parameter set is undefined, but otherwise it modifies the set + // in-place and returns the same array. function appendTypeParameters(typeParameters, declarations) { for (var _i = 0, declarations_2 = declarations; _i < declarations_2.length; _i++) { var declaration = declarations_2[_i]; @@ -29259,58 +33858,62 @@ var ts; } return typeParameters; } + // Return the outer type parameters of a node or undefined if the node has no outer type parameters. function getOuterTypeParameters(node, includeThisTypes) { while (true) { - node = node.parent; + node = node.parent; // TODO: GH#18217 Use SourceFile kind check instead if (!node) { return undefined; } switch (node.kind) { - case 235: - case 205: - case 236: - case 158: - case 159: - case 153: - case 163: - case 164: - case 284: - case 234: - case 154: - case 192: - case 193: - case 237: - case 297: - case 298: - case 292: - case 177: - case 171: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 236 /* InterfaceDeclaration */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 153 /* MethodSignature */: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 284 /* JSDocFunctionType */: + case 234 /* FunctionDeclaration */: + case 154 /* MethodDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 237 /* TypeAliasDeclaration */: + case 297 /* JSDocTemplateTag */: + case 298 /* JSDocTypedefTag */: + case 292 /* JSDocCallbackTag */: + case 177 /* MappedType */: + case 171 /* ConditionalType */: var outerTypeParameters = getOuterTypeParameters(node, includeThisTypes); - if (node.kind === 177) { + if (node.kind === 177 /* MappedType */) { return ts.append(outerTypeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode(node.typeParameter))); } - else if (node.kind === 171) { + else if (node.kind === 171 /* ConditionalType */) { return ts.concatenate(outerTypeParameters, getInferTypeParameters(node)); } var outerAndOwnTypeParameters = appendTypeParameters(outerTypeParameters, ts.getEffectiveTypeParameterDeclarations(node)); var thisType = includeThisTypes && - (node.kind === 235 || node.kind === 205 || node.kind === 236) && + (node.kind === 235 /* ClassDeclaration */ || node.kind === 205 /* ClassExpression */ || node.kind === 236 /* InterfaceDeclaration */) && getDeclaredTypeOfClassOrInterface(getSymbolOfNode(node)).thisType; return thisType ? ts.append(outerAndOwnTypeParameters, thisType) : outerAndOwnTypeParameters; } } } + // The outer type parameters are those defined by enclosing generic classes, methods, or functions. function getOuterTypeParametersOfClassOrInterface(symbol) { - var declaration = symbol.flags & 32 ? symbol.valueDeclaration : ts.getDeclarationOfKind(symbol, 236); + var declaration = symbol.flags & 32 /* Class */ ? symbol.valueDeclaration : ts.getDeclarationOfKind(symbol, 236 /* InterfaceDeclaration */); return getOuterTypeParameters(declaration); } + // The local type parameters are the combined set of type parameters from all declarations of the class, + // interface, or type alias. function getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) { var result; for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var node = _a[_i]; - if (node.kind === 236 || - node.kind === 235 || - node.kind === 205 || + if (node.kind === 236 /* InterfaceDeclaration */ || + node.kind === 235 /* ClassDeclaration */ || + node.kind === 205 /* ClassExpression */ || ts.isTypeAlias(node)) { var declaration = node; result = appendTypeParameters(result, ts.getEffectiveTypeParameterDeclarations(declaration)); @@ -29318,11 +33921,15 @@ var ts; } return result; } + // The full set of type parameters for a generic class or interface type consists of its outer type parameters plus + // its locally declared type parameters. function getTypeParametersOfClassOrInterface(symbol) { return ts.concatenate(getOuterTypeParametersOfClassOrInterface(symbol), getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol)); } + // A type is a mixin constructor if it has a single construct signature taking no type parameters and a single + // rest parameter of type any[]. function isMixinConstructorType(type) { - var signatures = getSignaturesOfType(type, 1); + var signatures = getSignaturesOfType(type, 1 /* Construct */); if (signatures.length === 1) { var s = signatures[0]; return !s.typeParameters && s.parameters.length === 1 && s.hasRestParameter && getTypeOfParameter(s.parameters[0]) === anyArrayType; @@ -29330,10 +33937,10 @@ var ts; return false; } function isConstructorType(type) { - if (isValidBaseType(type) && getSignaturesOfType(type, 1).length > 0) { + if (isValidBaseType(type) && getSignaturesOfType(type, 1 /* Construct */).length > 0) { return true; } - if (type.flags & 2162688) { + if (type.flags & 2162688 /* TypeVariable */) { var constraint = getBaseConstraintOfType(type); return !!constraint && isValidBaseType(constraint) && isMixinConstructorType(constraint); } @@ -29342,6 +33949,7 @@ var ts; function getBaseTypeNodeOfClass(type) { var decl = type.symbol.valueDeclaration; if (ts.isInJavaScriptFile(decl)) { + // Prefer an @augments tag because it may have type parameters. var tag = ts.getJSDocAugmentsTag(decl); if (tag) { return tag.class; @@ -29352,13 +33960,21 @@ var ts; function getConstructorsForTypeArguments(type, typeArgumentNodes, location) { var typeArgCount = ts.length(typeArgumentNodes); var isJavaScript = ts.isInJavaScriptFile(location); - return ts.filter(getSignaturesOfType(type, 1), function (sig) { return (isJavaScript || typeArgCount >= getMinTypeArgumentCount(sig.typeParameters)) && typeArgCount <= ts.length(sig.typeParameters); }); + return ts.filter(getSignaturesOfType(type, 1 /* Construct */), function (sig) { return (isJavaScript || typeArgCount >= getMinTypeArgumentCount(sig.typeParameters)) && typeArgCount <= ts.length(sig.typeParameters); }); } function getInstantiatedConstructorsForTypeArguments(type, typeArgumentNodes, location) { var signatures = getConstructorsForTypeArguments(type, typeArgumentNodes, location); var typeArguments = ts.map(typeArgumentNodes, getTypeFromTypeNode); return ts.sameMap(signatures, function (sig) { return ts.some(sig.typeParameters) ? getSignatureInstantiation(sig, typeArguments, ts.isInJavaScriptFile(location)) : sig; }); } + /** + * The base constructor of a class can resolve to + * * undefinedType if the class has no extends clause, + * * unknownType if an error occurred during resolution of the extends expression, + * * nullType if the extends expression is the null value, + * * anyType if the extends expression has type any, or + * * an object type with at least one construct signature. + */ function getBaseConstructorTypeOfClass(type) { if (!type.resolvedBaseConstructorType) { var decl = type.symbol.valueDeclaration; @@ -29367,22 +33983,24 @@ var ts; if (!baseTypeNode) { return type.resolvedBaseConstructorType = undefinedType; } - if (!pushTypeResolution(type, 1)) { + if (!pushTypeResolution(type, 1 /* ResolvedBaseConstructorType */)) { return errorType; } var baseConstructorType = checkExpression(baseTypeNode.expression); if (extended && baseTypeNode !== extended) { - ts.Debug.assert(!extended.typeArguments); + ts.Debug.assert(!extended.typeArguments); // Because this is in a JS file, and baseTypeNode is in an @extends tag checkExpression(extended.expression); } - if (baseConstructorType.flags & (131072 | 524288)) { + if (baseConstructorType.flags & (131072 /* Object */ | 524288 /* Intersection */)) { + // Resolving the members of a class requires us to resolve the base class of that class. + // We force resolution here such that we catch circularities now. resolveStructuredTypeMembers(baseConstructorType); } if (!popTypeResolution()) { error(type.symbol.valueDeclaration, ts.Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol)); return type.resolvedBaseConstructorType = errorType; } - if (!(baseConstructorType.flags & 1) && baseConstructorType !== nullWideningType && !isConstructorType(baseConstructorType)) { + if (!(baseConstructorType.flags & 1 /* Any */) && baseConstructorType !== nullWideningType && !isConstructorType(baseConstructorType)) { error(baseTypeNode.expression, ts.Diagnostics.Type_0_is_not_a_constructor_function_type, typeToString(baseConstructorType)); return type.resolvedBaseConstructorType = errorType; } @@ -29392,14 +34010,14 @@ var ts; } function getBaseTypes(type) { if (!type.resolvedBaseTypes) { - if (type.objectFlags & 8) { + if (type.objectFlags & 8 /* Tuple */) { type.resolvedBaseTypes = [createArrayType(getUnionType(type.typeParameters))]; } - else if (type.symbol.flags & (32 | 64)) { - if (type.symbol.flags & 32) { + else if (type.symbol.flags & (32 /* Class */ | 64 /* Interface */)) { + if (type.symbol.flags & 32 /* Class */) { resolveBaseTypesOfClass(type); } - if (type.symbol.flags & 64) { + if (type.symbol.flags & 64 /* Interface */) { resolveBaseTypesOfInterface(type); } } @@ -29412,21 +34030,27 @@ var ts; function resolveBaseTypesOfClass(type) { type.resolvedBaseTypes = ts.resolvingEmptyArray; var baseConstructorType = getApparentType(getBaseConstructorTypeOfClass(type)); - if (!(baseConstructorType.flags & (131072 | 524288 | 1))) { + if (!(baseConstructorType.flags & (131072 /* Object */ | 524288 /* Intersection */ | 1 /* Any */))) { return type.resolvedBaseTypes = ts.emptyArray; } var baseTypeNode = getBaseTypeNodeOfClass(type); var typeArgs = typeArgumentsFromTypeReferenceNode(baseTypeNode); var baseType; var originalBaseType = baseConstructorType && baseConstructorType.symbol ? getDeclaredTypeOfSymbol(baseConstructorType.symbol) : undefined; - if (baseConstructorType.symbol && baseConstructorType.symbol.flags & 32 && + if (baseConstructorType.symbol && baseConstructorType.symbol.flags & 32 /* Class */ && areAllOuterTypeParametersApplied(originalBaseType)) { + // When base constructor type is a class with no captured type arguments we know that the constructors all have the same type parameters as the + // class and all return the instance type of the class. There is no need for further checks and we can apply the + // type arguments in the same manner as a type reference to get the same error reporting experience. baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseConstructorType.symbol, typeArgs); } - else if (baseConstructorType.flags & 1) { + else if (baseConstructorType.flags & 1 /* Any */) { baseType = baseConstructorType; } else { + // The class derives from a "class-like" constructor function, check that we have at least one construct signature + // with a matching number of type parameters and use the return type of the first instantiated signature. Elsewhere + // we check that all instantiated signatures return the same type. var constructors = getInstantiatedConstructorsForTypeArguments(baseConstructorType, baseTypeNode.typeArguments, baseTypeNode); if (!constructors.length) { error(baseTypeNode.expression, ts.Diagnostics.No_base_constructor_has_the_specified_number_of_type_arguments); @@ -29442,15 +34066,21 @@ var ts; return type.resolvedBaseTypes = ts.emptyArray; } if (type === baseType || hasBaseType(baseType, type)) { - error(type.symbol.valueDeclaration, ts.Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, undefined, 2)); + error(type.symbol.valueDeclaration, ts.Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, 2 /* WriteArrayAsGenericType */)); return type.resolvedBaseTypes = ts.emptyArray; } if (type.resolvedBaseTypes === ts.resolvingEmptyArray) { - type.members = undefined; + // Circular reference, likely through instantiation of default parameters + // (otherwise there'd be an error from hasBaseType) - this is fine, but `.members` should be reset + // as `getIndexedAccessType` via `instantiateType` via `getTypeFromClassOrInterfaceReference` forces a + // partial instantiation of the members without the base types fully resolved + type.members = undefined; // TODO: GH#18217 } return type.resolvedBaseTypes = [baseType]; } function areAllOuterTypeParametersApplied(type) { + // An unapplied type parameter has its symbol still the same as the matching argument symbol. + // Since parameters are applied outer-to-inner, only the last outer parameter needs to be checked. var outerTypeParameters = type.outerTypeParameters; if (outerTypeParameters) { var last_1 = outerTypeParameters.length - 1; @@ -29459,15 +34089,17 @@ var ts; } return true; } + // A valid base type is `any`, any non-generic object type or intersection of non-generic + // object types. function isValidBaseType(type) { - return !!(type.flags & (131072 | 16777216 | 1)) && !isGenericMappedType(type) || - !!(type.flags & 524288) && ts.every(type.types, isValidBaseType); + return !!(type.flags & (131072 /* Object */ | 16777216 /* NonPrimitive */ | 1 /* Any */)) && !isGenericMappedType(type) || + !!(type.flags & 524288 /* Intersection */) && ts.every(type.types, isValidBaseType); } function resolveBaseTypesOfInterface(type) { type.resolvedBaseTypes = type.resolvedBaseTypes || ts.emptyArray; for (var _i = 0, _a = type.symbol.declarations; _i < _a.length; _i++) { var declaration = _a[_i]; - if (declaration.kind === 236 && ts.getInterfaceBaseTypeNodes(declaration)) { + if (declaration.kind === 236 /* InterfaceDeclaration */ && ts.getInterfaceBaseTypeNodes(declaration)) { for (var _b = 0, _c = ts.getInterfaceBaseTypeNodes(declaration); _b < _c.length; _b++) { var node = _c[_b]; var baseType = getTypeFromTypeNode(node); @@ -29482,7 +34114,7 @@ var ts; } } else { - error(declaration, ts.Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, undefined, 2)); + error(declaration, ts.Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, 2 /* WriteArrayAsGenericType */)); } } else { @@ -29493,11 +34125,18 @@ var ts; } } } + /** + * Returns true if the interface given by the symbol is free of "this" references. + * + * Specifically, the result is true if the interface itself contains no references + * to "this" in its body, if all base types are interfaces, + * and if none of the base interfaces have a "this" type. + */ function isThislessInterface(symbol) { for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var declaration = _a[_i]; - if (declaration.kind === 236) { - if (declaration.flags & 64) { + if (declaration.kind === 236 /* InterfaceDeclaration */) { + if (declaration.flags & 64 /* ContainsThis */) { return false; } var baseTypeNodes = ts.getInterfaceBaseTypeNodes(declaration); @@ -29505,8 +34144,8 @@ var ts; for (var _b = 0, baseTypeNodes_1 = baseTypeNodes; _b < baseTypeNodes_1.length; _b++) { var node = baseTypeNodes_1[_b]; if (ts.isEntityNameExpression(node.expression)) { - var baseSymbol = resolveEntityName(node.expression, 67901928, true); - if (!baseSymbol || !(baseSymbol.flags & 64) || getDeclaredTypeOfClassOrInterface(baseSymbol).thisType) { + var baseSymbol = resolveEntityName(node.expression, 67901928 /* Type */, /*ignoreErrors*/ true); + if (!baseSymbol || !(baseSymbol.flags & 64 /* Interface */) || getDeclaredTypeOfClassOrInterface(baseSymbol).thisType) { return false; } } @@ -29519,12 +34158,17 @@ var ts; function getDeclaredTypeOfClassOrInterface(symbol) { var links = getSymbolLinks(symbol); if (!links.declaredType) { - var kind = symbol.flags & 32 ? 1 : 2; + var kind = symbol.flags & 32 /* Class */ ? 1 /* Class */ : 2 /* Interface */; var type = links.declaredType = createObjectType(kind, symbol); var outerTypeParameters = getOuterTypeParametersOfClassOrInterface(symbol); var localTypeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol); - if (outerTypeParameters || localTypeParameters || kind === 1 || !isThislessInterface(symbol)) { - type.objectFlags |= 4; + // A class or interface is generic if it has type parameters or a "this" type. We always give classes a "this" type + // because it is not feasible to analyze all members to determine if the "this" type escapes the class (in particular, + // property types inferred from initializers and method return types inferred from return statements are very hard + // to exhaustively analyze). We give interfaces a "this" type if we can't definitely determine that they are free of + // "this" references. + if (outerTypeParameters || localTypeParameters || kind === 1 /* Class */ || !isThislessInterface(symbol)) { + type.objectFlags |= 4 /* Reference */; type.typeParameters = ts.concatenate(outerTypeParameters, localTypeParameters); type.outerTypeParameters = outerTypeParameters; type.localTypeParameters = localTypeParameters; @@ -29532,7 +34176,7 @@ var ts; type.instantiations.set(getTypeListId(type.typeParameters), type); type.target = type; type.typeArguments = type.typeParameters; - type.thisType = createType(65536); + type.thisType = createType(65536 /* TypeParameter */); type.thisType.isThisType = true; type.thisType.symbol = symbol; type.thisType.constraint = type; @@ -29543,17 +34187,22 @@ var ts; function getDeclaredTypeOfTypeAlias(symbol) { var links = getSymbolLinks(symbol); if (!links.declaredType) { - if (!pushTypeResolution(symbol, 2)) { + // Note that we use the links object as the target here because the symbol object is used as the unique + // identity for resolution of the 'type' property in SymbolLinks. + if (!pushTypeResolution(symbol, 2 /* DeclaredType */)) { return errorType; } var declaration = ts.find(symbol.declarations, function (d) { - return ts.isJSDocTypeAlias(d) || d.kind === 237; + return ts.isJSDocTypeAlias(d) || d.kind === 237 /* TypeAliasDeclaration */; }); var typeNode = ts.isJSDocTypeAlias(declaration) ? declaration.typeExpression : declaration.type; + // If typeNode is missing, we will error in checkJSDocTypedefTag. var type = typeNode ? getTypeFromTypeNode(typeNode) : errorType; if (popTypeResolution()) { var typeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol); if (typeParameters) { + // Initialize the instantiation cache for generic type aliases. The declared type corresponds to + // an instantiation of the type alias with the type parameters supplied as type arguments. links.typeParameters = typeParameters; links.instantiations = ts.createMap(); links.instantiations.set(getTypeListId(typeParameters), type); @@ -29568,10 +34217,10 @@ var ts; return links.declaredType; } function isStringConcatExpression(expr) { - if (expr.kind === 9) { + if (expr.kind === 9 /* StringLiteral */) { return true; } - else if (expr.kind === 200) { + else if (expr.kind === 200 /* BinaryExpression */) { return isStringConcatExpression(expr.left) && isStringConcatExpression(expr.right); } return false; @@ -29579,18 +34228,18 @@ var ts; function isLiteralEnumMember(member) { var expr = member.initializer; if (!expr) { - return !(member.flags & 4194304); + return !(member.flags & 4194304 /* Ambient */); } switch (expr.kind) { - case 9: - case 8: + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: return true; - case 198: - return expr.operator === 38 && - expr.operand.kind === 8; - case 71: + case 198 /* PrefixUnaryExpression */: + return expr.operator === 38 /* MinusToken */ && + expr.operand.kind === 8 /* NumericLiteral */; + case 71 /* Identifier */: return ts.nodeIsMissing(expr) || !!getSymbolOfNode(member.parent).exports.get(expr.escapedText); - case 200: + case 200 /* BinaryExpression */: return isStringConcatExpression(expr); default: return false; @@ -29604,11 +34253,11 @@ var ts; var hasNonLiteralMember = false; for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var declaration = _a[_i]; - if (declaration.kind === 238) { + if (declaration.kind === 238 /* EnumDeclaration */) { for (var _b = 0, _c = declaration.members; _b < _c.length; _b++) { var member = _c[_b]; - if (member.initializer && member.initializer.kind === 9) { - return links.enumKind = 1; + if (member.initializer && member.initializer.kind === 9 /* StringLiteral */) { + return links.enumKind = 1 /* Literal */; } if (!isLiteralEnumMember(member)) { hasNonLiteralMember = true; @@ -29616,40 +34265,40 @@ var ts; } } } - return links.enumKind = hasNonLiteralMember ? 0 : 1; + return links.enumKind = hasNonLiteralMember ? 0 /* Numeric */ : 1 /* Literal */; } function getBaseTypeOfEnumLiteralType(type) { - return type.flags & 512 && !(type.flags & 262144) ? getDeclaredTypeOfSymbol(getParentOfSymbol(type.symbol)) : type; + return type.flags & 512 /* EnumLiteral */ && !(type.flags & 262144 /* Union */) ? getDeclaredTypeOfSymbol(getParentOfSymbol(type.symbol)) : type; } function getDeclaredTypeOfEnum(symbol) { var links = getSymbolLinks(symbol); if (links.declaredType) { return links.declaredType; } - if (getEnumKind(symbol) === 1) { + if (getEnumKind(symbol) === 1 /* Literal */) { enumCount++; var memberTypeList = []; for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var declaration = _a[_i]; - if (declaration.kind === 238) { + if (declaration.kind === 238 /* EnumDeclaration */) { for (var _b = 0, _c = declaration.members; _b < _c.length; _b++) { var member = _c[_b]; - var memberType = getLiteralType(getEnumMemberValue(member), enumCount, getSymbolOfNode(member)); + var memberType = getLiteralType(getEnumMemberValue(member), enumCount, getSymbolOfNode(member)); // TODO: GH#18217 getSymbolLinks(getSymbolOfNode(member)).declaredType = memberType; memberTypeList.push(memberType); } } } if (memberTypeList.length) { - var enumType_1 = getUnionType(memberTypeList, 1, symbol, undefined); - if (enumType_1.flags & 262144) { - enumType_1.flags |= 512; + var enumType_1 = getUnionType(memberTypeList, 1 /* Literal */, symbol, /*aliasTypeArguments*/ undefined); + if (enumType_1.flags & 262144 /* Union */) { + enumType_1.flags |= 512 /* EnumLiteral */; enumType_1.symbol = symbol; } return links.declaredType = enumType_1; } } - var enumType = createType(32); + var enumType = createType(32 /* Enum */); enumType.symbol = symbol; return links.declaredType = enumType; } @@ -29666,7 +34315,7 @@ var ts; function getDeclaredTypeOfTypeParameter(symbol) { var links = getSymbolLinks(symbol); if (!links.declaredType) { - var type = createType(65536); + var type = createType(65536 /* TypeParameter */); type.symbol = symbol; links.declaredType = type; } @@ -29683,79 +34332,103 @@ var ts; return tryGetDeclaredTypeOfSymbol(symbol) || errorType; } function tryGetDeclaredTypeOfSymbol(symbol) { - if (symbol.flags & (32 | 64)) { + if (symbol.flags & (32 /* Class */ | 64 /* Interface */)) { return getDeclaredTypeOfClassOrInterface(symbol); } - if (symbol.flags & 524288) { + if (symbol.flags & 524288 /* TypeAlias */) { return getDeclaredTypeOfTypeAlias(symbol); } - if (symbol.flags & 262144) { + if (symbol.flags & 262144 /* TypeParameter */) { return getDeclaredTypeOfTypeParameter(symbol); } - if (symbol.flags & 384) { + if (symbol.flags & 384 /* Enum */) { return getDeclaredTypeOfEnum(symbol); } - if (symbol.flags & 8) { + if (symbol.flags & 8 /* EnumMember */) { return getDeclaredTypeOfEnumMember(symbol); } - if (symbol.flags & 2097152) { + if (symbol.flags & 2097152 /* Alias */) { return getDeclaredTypeOfAlias(symbol); } return undefined; } + /** + * A type is free of this references if it's the any, string, number, boolean, symbol, or void keyword, a string + * literal type, an array with an element type that is free of this references, or a type reference that is + * free of this references. + */ function isThislessType(node) { switch (node.kind) { - case 119: - case 142: - case 137: - case 134: - case 122: - case 138: - case 135: - case 105: - case 140: - case 95: - case 131: - case 178: + case 119 /* AnyKeyword */: + case 142 /* UnknownKeyword */: + case 137 /* StringKeyword */: + case 134 /* NumberKeyword */: + case 122 /* BooleanKeyword */: + case 138 /* SymbolKeyword */: + case 135 /* ObjectKeyword */: + case 105 /* VoidKeyword */: + case 140 /* UndefinedKeyword */: + case 95 /* NullKeyword */: + case 131 /* NeverKeyword */: + case 178 /* LiteralType */: return true; - case 167: + case 167 /* ArrayType */: return isThislessType(node.elementType); - case 162: + case 162 /* TypeReference */: return !node.typeArguments || node.typeArguments.every(isThislessType); } return false; } + /** A type parameter is thisless if its contraint is thisless, or if it has no constraint. */ function isThislessTypeParameter(node) { return !node.constraint || isThislessType(node.constraint); } + /** + * A variable-like declaration is free of this references if it has a type annotation + * that is thisless, or if it has no type annotation and no initializer (and is thus of type any). + */ function isThislessVariableLikeDeclaration(node) { var typeNode = ts.getEffectiveTypeAnnotationNode(node); return typeNode ? isThislessType(typeNode) : !ts.hasInitializer(node); } + /** + * A function-like declaration is considered free of `this` references if it has a return type + * annotation that is free of this references and if each parameter is thisless and if + * each type parameter (if present) is thisless. + */ function isThislessFunctionLikeDeclaration(node) { var returnType = ts.getEffectiveReturnTypeNode(node); var typeParameters = ts.getEffectiveTypeParameterDeclarations(node); - return (node.kind === 155 || (!!returnType && isThislessType(returnType))) && + return (node.kind === 155 /* Constructor */ || (!!returnType && isThislessType(returnType))) && node.parameters.every(isThislessVariableLikeDeclaration) && typeParameters.every(isThislessTypeParameter); } + /** + * Returns true if the class or interface member given by the symbol is free of "this" references. The + * function may return false for symbols that are actually free of "this" references because it is not + * feasible to perform a complete analysis in all cases. In particular, property members with types + * inferred from their initializers and function members with inferred return types are conservatively + * assumed not to be free of "this" references. + */ function isThisless(symbol) { if (symbol.declarations && symbol.declarations.length === 1) { var declaration = symbol.declarations[0]; if (declaration) { switch (declaration.kind) { - case 152: - case 151: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: return isThislessVariableLikeDeclaration(declaration); - case 154: - case 153: - case 155: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: return isThislessFunctionLikeDeclaration(declaration); } } } return false; } + // The mappingThisOnly flag indicates that the only type parameter being mapped is "this". When the flag is true, + // we check symbols to see if we can quickly conclude they are free of "this" references, thus needing no instantiation. function createInstantiatedSymbolTable(symbols, mapper, mappingThisOnly) { var result = ts.createSymbolTable(); for (var _i = 0, symbols_2 = symbols; _i < symbols_2.length; _i++) { @@ -29777,44 +34450,73 @@ var ts; var symbol = type.symbol; var members = getMembersOfSymbol(symbol); type.declaredProperties = getNamedMembers(members); + // Start with signatures at empty array in case of recursive types type.declaredCallSignatures = ts.emptyArray; type.declaredConstructSignatures = ts.emptyArray; - type.declaredCallSignatures = getSignaturesOfSymbol(members.get("__call")); - type.declaredConstructSignatures = getSignaturesOfSymbol(members.get("__new")); - type.declaredStringIndexInfo = getIndexInfoOfSymbol(symbol, 0); - type.declaredNumberIndexInfo = getIndexInfoOfSymbol(symbol, 1); + type.declaredCallSignatures = getSignaturesOfSymbol(members.get("__call" /* Call */)); + type.declaredConstructSignatures = getSignaturesOfSymbol(members.get("__new" /* New */)); + type.declaredStringIndexInfo = getIndexInfoOfSymbol(symbol, 0 /* String */); + type.declaredNumberIndexInfo = getIndexInfoOfSymbol(symbol, 1 /* Number */); } return type; } + /** + * Indicates whether a type can be used as a late-bound name. + */ function isTypeUsableAsLateBoundName(type) { - return !!(type.flags & 2240); + return !!(type.flags & 2240 /* StringOrNumberLiteralOrUnique */); } + /** + * Indicates whether a declaration name is definitely late-bindable. + * A declaration name is only late-bindable if: + * - It is a `ComputedPropertyName`. + * - Its expression is an `Identifier` or either a `PropertyAccessExpression` an + * `ElementAccessExpression` consisting only of these same three types of nodes. + * - The type of its expression is a string or numeric literal type, or is a `unique symbol` type. + */ function isLateBindableName(node) { return ts.isComputedPropertyName(node) && ts.isEntityNameExpression(node.expression) && isTypeUsableAsLateBoundName(checkComputedPropertyName(node)); } + /** + * Indicates whether a declaration has a late-bindable dynamic name. + */ function hasLateBindableName(node) { var name = ts.getNameOfDeclaration(node); return !!name && isLateBindableName(name); } + /** + * Indicates whether a declaration has a dynamic name that cannot be late-bound. + */ function hasNonBindableDynamicName(node) { return ts.hasDynamicName(node) && !hasLateBindableName(node); } + /** + * Indicates whether a declaration name is a dynamic name that cannot be late-bound. + */ function isNonBindableDynamicName(node) { return ts.isDynamicName(node) && !isLateBindableName(node); } + /** + * Gets the symbolic name for a late-bound member from its type. + */ function getLateBoundNameFromType(type) { - if (type.flags & 2048) { + if (type.flags & 2048 /* UniqueESSymbol */) { return "__@" + type.symbol.escapedName + "@" + getSymbolId(type.symbol); } - if (type.flags & 192) { + if (type.flags & 192 /* StringOrNumberLiteral */) { return ts.escapeLeadingUnderscores("" + type.value); } return ts.Debug.fail(); } + /** + * Adds a declaration to a late-bound dynamic member. This performs the same function for + * late-bound members that `addDeclarationToSymbol` in binder.ts performs for early-bound + * members. + */ function addDeclarationToLateBoundSymbol(symbol, member, symbolFlags) { - ts.Debug.assert(!!(ts.getCheckFlags(symbol) & 1024), "Expected a late-bound symbol."); + ts.Debug.assert(!!(ts.getCheckFlags(symbol) & 1024 /* Late */), "Expected a late-bound symbol."); symbol.flags |= symbolFlags; getSymbolLinks(member.symbol).lateSymbol = symbol; if (!symbol.declarations) { @@ -29823,31 +34525,67 @@ var ts; else { symbol.declarations.push(member); } - if (symbolFlags & 67216319) { + if (symbolFlags & 67216319 /* Value */) { if (!symbol.valueDeclaration || symbol.valueDeclaration.kind !== member.kind) { symbol.valueDeclaration = member; } } } + /** + * Performs late-binding of a dynamic member. This performs the same function for + * late-bound members that `declareSymbol` in binder.ts performs for early-bound + * members. + * + * If a symbol is a dynamic name from a computed property, we perform an additional "late" + * binding phase to attempt to resolve the name for the symbol from the type of the computed + * property's expression. If the type of the expression is a string-literal, numeric-literal, + * or unique symbol type, we can use that type as the name of the symbol. + * + * For example, given: + * + * const x = Symbol(); + * + * interface I { + * [x]: number; + * } + * + * The binder gives the property `[x]: number` a special symbol with the name "__computed". + * In the late-binding phase we can type-check the expression `x` and see that it has a + * unique symbol type which we can then use as the name of the member. This allows users + * to define custom symbols that can be used in the members of an object type. + * + * @param parent The containing symbol for the member. + * @param earlySymbols The early-bound symbols of the parent. + * @param lateSymbols The late-bound symbols of the parent. + * @param decl The member to bind. + */ function lateBindMember(parent, earlySymbols, lateSymbols, decl) { ts.Debug.assert(!!decl.symbol, "The member is expected to have a symbol."); var links = getNodeLinks(decl); if (!links.resolvedSymbol) { + // In the event we attempt to resolve the late-bound name of this member recursively, + // fall back to the early-bound name of this member. links.resolvedSymbol = decl.symbol; var type = checkComputedPropertyName(decl.name); if (isTypeUsableAsLateBoundName(type)) { var memberName = getLateBoundNameFromType(type); var symbolFlags = decl.symbol.flags; + // Get or add a late-bound symbol for the member. This allows us to merge late-bound accessor declarations. var lateSymbol = lateSymbols.get(memberName); if (!lateSymbol) - lateSymbols.set(memberName, lateSymbol = createSymbol(0, memberName, 1024)); + lateSymbols.set(memberName, lateSymbol = createSymbol(0 /* None */, memberName, 1024 /* Late */)); + // Report an error if a late-bound member has the same name as an early-bound member, + // or if we have another early-bound symbol declaration with the same name and + // conflicting flags. var earlySymbol = earlySymbols && earlySymbols.get(memberName); if (lateSymbol.flags & getExcludedSymbolFlags(symbolFlags) || earlySymbol) { + // If we have an existing early-bound member, combine its declarations so that we can + // report an error at each declaration. var declarations = earlySymbol ? ts.concatenate(earlySymbol.declarations, lateSymbol.declarations) : lateSymbol.declarations; var name_2 = ts.declarationNameToString(decl.name); ts.forEach(declarations, function (declaration) { return error(ts.getNameOfDeclaration(declaration) || declaration, ts.Diagnostics.Duplicate_declaration_0, name_2); }); error(decl.name || decl, ts.Diagnostics.Duplicate_declaration_0, name_2); - lateSymbol = createSymbol(0, memberName, 1024); + lateSymbol = createSymbol(0 /* None */, memberName, 1024 /* Late */); } lateSymbol.nameType = type; addDeclarationToLateBoundSymbol(lateSymbol, decl, symbolFlags); @@ -29865,11 +34603,15 @@ var ts; function getResolvedMembersOrExportsOfSymbol(symbol, resolutionKind) { var links = getSymbolLinks(symbol); if (!links[resolutionKind]) { - var isStatic = resolutionKind === "resolvedExports"; + var isStatic = resolutionKind === "resolvedExports" /* resolvedExports */; var earlySymbols = !isStatic ? symbol.members : - symbol.flags & 1536 ? getExportsOfModuleWorker(symbol) : + symbol.flags & 1536 /* Module */ ? getExportsOfModuleWorker(symbol) : symbol.exports; + // In the event we recursively resolve the members/exports of the symbol, we + // set the initial value of resolvedMembers/resolvedExports to the early-bound + // members/exports of the symbol. links[resolutionKind] = earlySymbols || emptySymbols; + // fill in any as-yet-unresolved late-bound members. var lateSymbols = ts.createSymbolTable(); for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var decl = _a[_i]; @@ -29887,15 +34629,27 @@ var ts; } return links[resolutionKind]; } + /** + * Gets a SymbolTable containing both the early- and late-bound members of a symbol. + * + * For a description of late-binding, see `lateBindMember`. + */ function getMembersOfSymbol(symbol) { - return symbol.flags & 6240 - ? getResolvedMembersOrExportsOfSymbol(symbol, "resolvedMembers") + return symbol.flags & 6240 /* LateBindingContainer */ + ? getResolvedMembersOrExportsOfSymbol(symbol, "resolvedMembers" /* resolvedMembers */) : symbol.members || emptySymbols; } + /** + * If a symbol is the dynamic name of the member of an object type, get the late-bound + * symbol of the member. + * + * For a description of late-binding, see `lateBindMember`. + */ function getLateBoundSymbol(symbol) { - if (symbol.flags & 106500 && symbol.escapedName === "__computed") { + if (symbol.flags & 106500 /* ClassMember */ && symbol.escapedName === "__computed" /* Computed */) { var links = getSymbolLinks(symbol); if (!links.lateSymbol && ts.some(symbol.declarations, hasLateBindableName)) { + // force late binding of members/exports. This will set the late-bound symbol if (ts.some(symbol.declarations, ts.hasStaticModifier)) { getExportsOfSymbol(symbol.parent); } @@ -29908,7 +34662,7 @@ var ts; return symbol; } function getTypeWithThisArgument(type, thisArgument, needApparentType) { - if (ts.getObjectFlags(type) & 4) { + if (ts.getObjectFlags(type) & 4 /* Reference */) { var target = type.target; var typeArguments = type.typeArguments; if (ts.length(target.typeParameters) === ts.length(typeArguments)) { @@ -29916,7 +34670,7 @@ var ts; return needApparentType ? getApparentType(ref) : ref; } } - else if (type.flags & 524288) { + else if (type.flags & 524288 /* Intersection */) { return getIntersectionType(ts.map(type.types, function (t) { return getTypeWithThisArgument(t, thisArgument, needApparentType); })); } return needApparentType ? getApparentType(type) : type; @@ -29938,7 +34692,7 @@ var ts; } else { mapper = createTypeMapper(typeParameters, typeArguments); - members = createInstantiatedSymbolTable(source.declaredProperties, mapper, typeParameters.length === 1); + members = createInstantiatedSymbolTable(source.declaredProperties, mapper, /*mappingThisOnly*/ typeParameters.length === 1); callSignatures = instantiateSignatures(source.declaredCallSignatures, mapper); constructSignatures = instantiateSignatures(source.declaredConstructSignatures, mapper); stringIndexInfo = instantiateIndexInfo(source.declaredStringIndexInfo, mapper); @@ -29955,14 +34709,14 @@ var ts; var baseType = baseTypes_1[_i]; var instantiatedBaseType = thisArgument ? getTypeWithThisArgument(instantiateType(baseType, mapper), thisArgument) : baseType; addInheritedMembers(members, getPropertiesOfType(instantiatedBaseType)); - callSignatures = ts.concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, 0)); - constructSignatures = ts.concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, 1)); + callSignatures = ts.concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, 0 /* Call */)); + constructSignatures = ts.concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, 1 /* Construct */)); if (!stringIndexInfo) { stringIndexInfo = instantiatedBaseType === anyType ? - createIndexInfo(anyType, false) : - getIndexInfoOfType(instantiatedBaseType, 0); + createIndexInfo(anyType, /*isReadonly*/ false) : + getIndexInfoOfType(instantiatedBaseType, 0 /* String */); } - numberIndexInfo = numberIndexInfo || getIndexInfoOfType(instantiatedBaseType, 1); + numberIndexInfo = numberIndexInfo || getIndexInfoOfType(instantiatedBaseType, 1 /* Number */); } } setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); @@ -29993,13 +34747,14 @@ var ts; return sig; } function cloneSignature(sig) { - return createSignature(sig.declaration, sig.typeParameters, sig.thisParameter, sig.parameters, undefined, undefined, sig.minArgumentCount, sig.hasRestParameter, sig.hasLiteralTypes); + return createSignature(sig.declaration, sig.typeParameters, sig.thisParameter, sig.parameters, /*resolvedReturnType*/ undefined, + /*resolvedTypePredicate*/ undefined, sig.minArgumentCount, sig.hasRestParameter, sig.hasLiteralTypes); } function getDefaultConstructSignatures(classType) { var baseConstructorType = getBaseConstructorTypeOfClass(classType); - var baseSignatures = getSignaturesOfType(baseConstructorType, 1); + var baseSignatures = getSignaturesOfType(baseConstructorType, 1 /* Construct */); if (baseSignatures.length === 0) { - return [createSignature(undefined, classType.localTypeParameters, undefined, ts.emptyArray, classType, undefined, 0, false, false)]; + return [createSignature(undefined, classType.localTypeParameters, undefined, ts.emptyArray, classType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false)]; // TODO: GH#18217 } var baseTypeNode = getBaseTypeNodeOfClass(classType); var isJavaScript = ts.isInJavaScriptFile(baseTypeNode); @@ -30029,11 +34784,13 @@ var ts; } function findMatchingSignatures(signatureLists, signature, listIndex) { if (signature.typeParameters) { + // We require an exact match for generic signatures, so we only return signatures from the first + // signature list and only if they have exact matches in the other signature lists. if (listIndex > 0) { return undefined; } for (var i = 1; i < signatureLists.length; i++) { - if (!findMatchingSignature(signatureLists[i], signature, false, false, false)) { + if (!findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ false)) { return undefined; } } @@ -30041,7 +34798,8 @@ var ts; } var result; for (var i = 0; i < signatureLists.length; i++) { - var match = i === listIndex ? signature : findMatchingSignature(signatureLists[i], signature, true, true, true); + // Allow matching non-generic signatures to have excess parameters and different return types + var match = i === listIndex ? signature : findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ true, /*ignoreThisTypes*/ true, /*ignoreReturnTypes*/ true); if (!match) { return undefined; } @@ -30049,20 +34807,27 @@ var ts; } return result; } + // The signatures of a union type are those signatures that are present in each of the constituent types. + // Generic signatures must match exactly, but non-generic signatures are allowed to have extra optional + // parameters and may differ in return types. When signatures differ in return types, the resulting return + // type is the union of the constituent return types. function getUnionSignatures(types, kind) { var signatureLists = ts.map(types, function (t) { return getSignaturesOfType(t, kind); }); var result; for (var i = 0; i < signatureLists.length; i++) { for (var _i = 0, _a = signatureLists[i]; _i < _a.length; _i++) { var signature = _a[_i]; - if (!result || !findMatchingSignature(result, signature, false, true, true)) { + // Only process signatures with parameter lists that aren't already in the result list + if (!result || !findMatchingSignature(result, signature, /*partialMatch*/ false, /*ignoreThisTypes*/ true, /*ignoreReturnTypes*/ true)) { var unionSignatures = findMatchingSignatures(signatureLists, signature, i); if (unionSignatures) { var s = signature; + // Union the result types when more than one signature matches if (unionSignatures.length > 1) { var thisParameter = signature.thisParameter; if (ts.forEach(unionSignatures, function (sig) { return sig.thisParameter; })) { - var thisType = getUnionType(ts.map(unionSignatures, function (sig) { return sig.thisParameter ? getTypeOfSymbol(sig.thisParameter) : anyType; }), 2); + // TODO: GH#18217 We tested that *some* has thisParameter and now act as if *all* do + var thisType = getUnionType(ts.map(unionSignatures, function (sig) { return sig.thisParameter ? getTypeOfSymbol(sig.thisParameter) : anyType; }), 2 /* Subtype */); thisParameter = createSymbolWithType(signature.thisParameter, thisType); } s = cloneSignature(signature); @@ -30088,13 +34853,15 @@ var ts; indexTypes.push(indexInfo.type); isAnyReadonly = isAnyReadonly || indexInfo.isReadonly; } - return createIndexInfo(getUnionType(indexTypes, 2), isAnyReadonly); + return createIndexInfo(getUnionType(indexTypes, 2 /* Subtype */), isAnyReadonly); } function resolveUnionTypeMembers(type) { - var callSignatures = getUnionSignatures(type.types, 0); - var constructSignatures = getUnionSignatures(type.types, 1); - var stringIndexInfo = getUnionIndexInfo(type.types, 0); - var numberIndexInfo = getUnionIndexInfo(type.types, 1); + // The members and properties collections are empty for union types. To get all properties of a union + // type use getPropertiesOfType (only the language service uses this). + var callSignatures = getUnionSignatures(type.types, 0 /* Call */); + var constructSignatures = getUnionSignatures(type.types, 1 /* Construct */); + var stringIndexInfo = getUnionIndexInfo(type.types, 0 /* String */); + var numberIndexInfo = getUnionIndexInfo(type.types, 1 /* Number */); setStructuredTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); } function intersectTypes(type1, type2) { @@ -30113,12 +34880,14 @@ var ts; mixedTypes.push(type); } else if (isMixinConstructorType(types[i])) { - mixedTypes.push(getReturnTypeOfSignature(getSignaturesOfType(types[i], 1)[0])); + mixedTypes.push(getReturnTypeOfSignature(getSignaturesOfType(types[i], 1 /* Construct */)[0])); } } return getIntersectionType(mixedTypes); } function resolveIntersectionTypeMembers(type) { + // The members and properties collections are empty for intersection types. To get all properties of an + // intersection type use getPropertiesOfType (only the language service uses this). var callSignatures = ts.emptyArray; var constructSignatures = ts.emptyArray; var stringIndexInfo; @@ -30127,8 +34896,13 @@ var ts; var mixinCount = ts.countWhere(types, isMixinConstructorType); var _loop_5 = function (i) { var t = type.types[i]; + // When an intersection type contains mixin constructor types, the construct signatures from + // those types are discarded and their return types are mixed into the return types of all + // other construct signatures in the intersection type. For example, the intersection type + // '{ new(...args: any[]) => A } & { new(s: string) => B }' has a single construct signature + // 'new(s: string) => A & B'. if (mixinCount === 0 || mixinCount === types.length && i === 0 || !isMixinConstructorType(t)) { - var signatures = getSignaturesOfType(t, 1); + var signatures = getSignaturesOfType(t, 1 /* Construct */); if (signatures.length && mixinCount > 0) { signatures = ts.map(signatures, function (s) { var clone = cloneSignature(s); @@ -30138,59 +34912,68 @@ var ts; } constructSignatures = ts.concatenate(constructSignatures, signatures); } - callSignatures = ts.concatenate(callSignatures, getSignaturesOfType(t, 0)); - stringIndexInfo = intersectIndexInfos(stringIndexInfo, getIndexInfoOfType(t, 0)); - numberIndexInfo = intersectIndexInfos(numberIndexInfo, getIndexInfoOfType(t, 1)); + callSignatures = ts.concatenate(callSignatures, getSignaturesOfType(t, 0 /* Call */)); + stringIndexInfo = intersectIndexInfos(stringIndexInfo, getIndexInfoOfType(t, 0 /* String */)); + numberIndexInfo = intersectIndexInfos(numberIndexInfo, getIndexInfoOfType(t, 1 /* Number */)); }; for (var i = 0; i < types.length; i++) { _loop_5(i); } setStructuredTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); } + /** + * Converts an AnonymousType to a ResolvedType. + */ function resolveAnonymousTypeMembers(type) { var symbol = type.symbol; if (type.target) { - var members = createInstantiatedSymbolTable(getPropertiesOfObjectType(type.target), type.mapper, false); - var callSignatures = instantiateSignatures(getSignaturesOfType(type.target, 0), type.mapper); - var constructSignatures = instantiateSignatures(getSignaturesOfType(type.target, 1), type.mapper); - var stringIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, 0), type.mapper); - var numberIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, 1), type.mapper); + var members = createInstantiatedSymbolTable(getPropertiesOfObjectType(type.target), type.mapper, /*mappingThisOnly*/ false); + var callSignatures = instantiateSignatures(getSignaturesOfType(type.target, 0 /* Call */), type.mapper); + var constructSignatures = instantiateSignatures(getSignaturesOfType(type.target, 1 /* Construct */), type.mapper); + var stringIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, 0 /* String */), type.mapper); + var numberIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, 1 /* Number */), type.mapper); setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); } - else if (symbol.flags & 2048) { + else if (symbol.flags & 2048 /* TypeLiteral */) { var members = getMembersOfSymbol(symbol); - var callSignatures = getSignaturesOfSymbol(members.get("__call")); - var constructSignatures = getSignaturesOfSymbol(members.get("__new")); - var stringIndexInfo = getIndexInfoOfSymbol(symbol, 0); - var numberIndexInfo = getIndexInfoOfSymbol(symbol, 1); + var callSignatures = getSignaturesOfSymbol(members.get("__call" /* Call */)); + var constructSignatures = getSignaturesOfSymbol(members.get("__new" /* New */)); + var stringIndexInfo = getIndexInfoOfSymbol(symbol, 0 /* String */); + var numberIndexInfo = getIndexInfoOfSymbol(symbol, 1 /* Number */); setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); } else { + // Combinations of function, class, enum and module var members = emptySymbols; var stringIndexInfo = void 0; if (symbol.exports) { members = getExportsOfSymbol(symbol); } setStructuredTypeMembers(type, members, ts.emptyArray, ts.emptyArray, undefined, undefined); - if (symbol.flags & 32) { + if (symbol.flags & 32 /* Class */) { var classType = getDeclaredTypeOfClassOrInterface(symbol); var baseConstructorType = getBaseConstructorTypeOfClass(classType); - if (baseConstructorType.flags & (131072 | 524288 | 2162688)) { + if (baseConstructorType.flags & (131072 /* Object */ | 524288 /* Intersection */ | 2162688 /* TypeVariable */)) { members = ts.createSymbolTable(getNamedMembers(members)); addInheritedMembers(members, getPropertiesOfType(baseConstructorType)); } else if (baseConstructorType === anyType) { - stringIndexInfo = createIndexInfo(anyType, false); + stringIndexInfo = createIndexInfo(anyType, /*isReadonly*/ false); } } - var numberIndexInfo = symbol.flags & 384 ? enumNumberIndexInfo : undefined; + var numberIndexInfo = symbol.flags & 384 /* Enum */ ? enumNumberIndexInfo : undefined; setStructuredTypeMembers(type, members, ts.emptyArray, ts.emptyArray, stringIndexInfo, numberIndexInfo); - if (symbol.flags & (16 | 8192)) { + // We resolve the members before computing the signatures because a signature may use + // typeof with a qualified name expression that circularly references the type we are + // in the process of resolving (see issue #6072). The temporarily empty signature list + // will never be observed because a qualified name can't reference signatures. + if (symbol.flags & (16 /* Function */ | 8192 /* Method */)) { type.callSignatures = getSignaturesOfSymbol(symbol); } - if (symbol.flags & 32) { + // And likewise for construct signatures for classes + if (symbol.flags & 32 /* Class */) { var classType = getDeclaredTypeOfClassOrInterface(symbol); - var constructSignatures = getSignaturesOfSymbol(symbol.members.get("__constructor")); + var constructSignatures = getSignaturesOfSymbol(symbol.members.get("__constructor" /* Constructor */)); if (!constructSignatures.length) { constructSignatures = getDefaultConstructSignatures(classType); } @@ -30199,16 +34982,16 @@ var ts; } } function resolveReverseMappedTypeMembers(type) { - var indexInfo = getIndexInfoOfType(type.source, 0); + var indexInfo = getIndexInfoOfType(type.source, 0 /* String */); var modifiers = getMappedTypeModifiers(type.mappedType); - var readonlyMask = modifiers & 1 ? false : true; - var optionalMask = modifiers & 4 ? 0 : 16777216; + var readonlyMask = modifiers & 1 /* IncludeReadonly */ ? false : true; + var optionalMask = modifiers & 4 /* IncludeOptional */ ? 0 : 16777216 /* Optional */; var stringIndexInfo = indexInfo && createIndexInfo(inferReverseMappedType(indexInfo.type, type.mappedType), readonlyMask && indexInfo.isReadonly); var members = ts.createSymbolTable(); for (var _i = 0, _a = getPropertiesOfType(type.source); _i < _a.length; _i++) { var prop = _a[_i]; - var checkFlags = 2048 | (readonlyMask && isReadonlySymbol(prop) ? 8 : 0); - var inferredProp = createSymbol(4 | prop.flags & optionalMask, prop.escapedName, checkFlags); + var checkFlags = 2048 /* ReverseMapped */ | (readonlyMask && isReadonlySymbol(prop) ? 8 /* Readonly */ : 0); + var inferredProp = createSymbol(4 /* Property */ | prop.flags & optionalMask, prop.escapedName, checkFlags); inferredProp.declarations = prop.declarations; inferredProp.nameType = prop.nameType; inferredProp.propertyType = getTypeOfSymbol(prop); @@ -30217,48 +35000,64 @@ var ts; } setStructuredTypeMembers(type, members, ts.emptyArray, ts.emptyArray, stringIndexInfo, undefined); } + /** Resolve the members of a mapped type { [P in K]: T } */ function resolveMappedTypeMembers(type) { var members = ts.createSymbolTable(); var stringIndexInfo; var numberIndexInfo; + // Resolve upfront such that recursive references see an empty object type. setStructuredTypeMembers(type, emptySymbols, ts.emptyArray, ts.emptyArray, undefined, undefined); + // In { [P in K]: T }, we refer to P as the type parameter type, K as the constraint type, + // and T as the template type. var typeParameter = getTypeParameterFromMappedType(type); var constraintType = getConstraintTypeFromMappedType(type); var templateType = getTemplateTypeFromMappedType(type.target || type); - var modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); + var modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T' var templateModifiers = getMappedTypeModifiers(type); - var include = keyofStringsOnly ? 64 : 2240; + var include = keyofStringsOnly ? 64 /* StringLiteral */ : 2240 /* StringOrNumberLiteralOrUnique */; if (isMappedTypeWithKeyofConstraintDeclaration(type)) { + // We have a { [P in keyof T]: X } for (var _i = 0, _a = getPropertiesOfType(modifiersType); _i < _a.length; _i++) { var prop = _a[_i]; - addMemberForKeyType(getLiteralTypeFromPropertyName(prop, include), undefined, prop); + addMemberForKeyType(getLiteralTypeFromPropertyName(prop, include), /*_index*/ undefined, prop); } - if (modifiersType.flags & 1 || getIndexInfoOfType(modifiersType, 0)) { + if (modifiersType.flags & 1 /* Any */ || getIndexInfoOfType(modifiersType, 0 /* String */)) { addMemberForKeyType(stringType); } - if (!keyofStringsOnly && getIndexInfoOfType(modifiersType, 1)) { + if (!keyofStringsOnly && getIndexInfoOfType(modifiersType, 1 /* Number */)) { addMemberForKeyType(numberType); } } else { - var keyType = constraintType.flags & 14745600 ? getApparentType(constraintType) : constraintType; - var iterationType = keyType.flags & 1048576 ? getIndexType(getApparentType(keyType.type)) : keyType; + // First, if the constraint type is a type parameter, obtain the base constraint. Then, + // if the key type is a 'keyof X', obtain 'keyof C' where C is the base constraint of X. + // Finally, iterate over the constituents of the resulting iteration type. + var keyType = constraintType.flags & 14745600 /* InstantiableNonPrimitive */ ? getApparentType(constraintType) : constraintType; + var iterationType = keyType.flags & 1048576 /* Index */ ? getIndexType(getApparentType(keyType.type)) : keyType; forEachType(iterationType, addMemberForKeyType); } setStructuredTypeMembers(type, members, ts.emptyArray, ts.emptyArray, stringIndexInfo, numberIndexInfo); function addMemberForKeyType(t, _index, origin) { + // Create a mapper from T to the current iteration type constituent. Then, if the + // mapped type is itself an instantiated type, combine the iteration mapper with the + // instantiation mapper. var templateMapper = combineTypeMappers(type.mapper, createTypeMapper([typeParameter], [t])); var propType = instantiateType(templateType, templateMapper); - if (t.flags & 2240) { + // If the current iteration type constituent is a string literal type, create a property. + // Otherwise, for type string create a string index signature. + if (t.flags & 2240 /* StringOrNumberLiteralOrUnique */) { var propName = getLateBoundNameFromType(t); var modifiersProp = getPropertyOfType(modifiersType, propName); - var isOptional = !!(templateModifiers & 4 || - !(templateModifiers & 8) && modifiersProp && modifiersProp.flags & 16777216); - var isReadonly = !!(templateModifiers & 1 || - !(templateModifiers & 2) && modifiersProp && isReadonlySymbol(modifiersProp)); - var prop = createSymbol(4 | (isOptional ? 16777216 : 0), propName, isReadonly ? 8 : 0); + var isOptional = !!(templateModifiers & 4 /* IncludeOptional */ || + !(templateModifiers & 8 /* ExcludeOptional */) && modifiersProp && modifiersProp.flags & 16777216 /* Optional */); + var isReadonly = !!(templateModifiers & 1 /* IncludeReadonly */ || + !(templateModifiers & 2 /* ExcludeReadonly */) && modifiersProp && isReadonlySymbol(modifiersProp)); + var prop = createSymbol(4 /* Property */ | (isOptional ? 16777216 /* Optional */ : 0), propName, isReadonly ? 8 /* Readonly */ : 0); + // When creating an optional property in strictNullChecks mode, if 'undefined' isn't assignable to the + // type, we include 'undefined' in the type. Similarly, when creating a non-optional property in strictNullChecks + // mode, if the underlying property is optional we remove 'undefined' from the type. prop.type = strictNullChecks && isOptional && !isTypeAssignableTo(undefinedType, propType) ? getOptionalType(propType) : - strictNullChecks && !isOptional && modifiersProp && modifiersProp.flags & 16777216 ? getTypeWithFacts(propType, 131072) : + strictNullChecks && !isOptional && modifiersProp && modifiersProp.flags & 16777216 /* Optional */ ? getTypeWithFacts(propType, 131072 /* NEUndefined */) : propType; if (origin) { prop.syntheticOrigin = origin; @@ -30267,11 +35066,11 @@ var ts; prop.nameType = t; members.set(propName, prop); } - else if (t.flags & (1 | 4)) { - stringIndexInfo = createIndexInfo(propType, !!(templateModifiers & 1)); + else if (t.flags & (1 /* Any */ | 4 /* String */)) { + stringIndexInfo = createIndexInfo(propType, !!(templateModifiers & 1 /* IncludeReadonly */)); } - else if (t.flags & 8) { - numberIndexInfo = createIndexInfo(propType, !!(templateModifiers & 1)); + else if (t.flags & 8 /* Number */) { + numberIndexInfo = createIndexInfo(propType, !!(templateModifiers & 1 /* IncludeReadonly */)); } } } @@ -30286,39 +35085,45 @@ var ts; function getTemplateTypeFromMappedType(type) { return type.templateType || (type.templateType = type.declaration.type ? - instantiateType(addOptionality(getTypeFromTypeNode(type.declaration.type), !!(getMappedTypeModifiers(type) & 4)), type.mapper || identityMapper) : + instantiateType(addOptionality(getTypeFromTypeNode(type.declaration.type), !!(getMappedTypeModifiers(type) & 4 /* IncludeOptional */)), type.mapper || identityMapper) : errorType); } function getConstraintDeclarationForMappedType(type) { return type.declaration.typeParameter.constraint; } function isMappedTypeWithKeyofConstraintDeclaration(type) { - var constraintDeclaration = getConstraintDeclarationForMappedType(type); - return constraintDeclaration.kind === 175 && - constraintDeclaration.operator === 128; + var constraintDeclaration = getConstraintDeclarationForMappedType(type); // TODO: GH#18217 + return constraintDeclaration.kind === 175 /* TypeOperator */ && + constraintDeclaration.operator === 128 /* KeyOfKeyword */; } function getModifiersTypeFromMappedType(type) { if (!type.modifiersType) { if (isMappedTypeWithKeyofConstraintDeclaration(type)) { + // If the constraint declaration is a 'keyof T' node, the modifiers type is T. We check + // AST nodes here because, when T is a non-generic type, the logic below eagerly resolves + // 'keyof T' to a literal union type and we can't recover T from that type. type.modifiersType = instantiateType(getTypeFromTypeNode(getConstraintDeclarationForMappedType(type).type), type.mapper || identityMapper); } else { + // Otherwise, get the declared constraint type, and if the constraint type is a type parameter, + // get the constraint of that type parameter. If the resulting type is an indexed type 'keyof T', + // the modifiers type is T. Otherwise, the modifiers type is {}. var declaredType = getTypeFromMappedTypeNode(type.declaration); var constraint = getConstraintTypeFromMappedType(declaredType); - var extendedConstraint = constraint && constraint.flags & 65536 ? getConstraintOfTypeParameter(constraint) : constraint; - type.modifiersType = extendedConstraint && extendedConstraint.flags & 1048576 ? instantiateType(extendedConstraint.type, type.mapper || identityMapper) : emptyObjectType; + var extendedConstraint = constraint && constraint.flags & 65536 /* TypeParameter */ ? getConstraintOfTypeParameter(constraint) : constraint; + type.modifiersType = extendedConstraint && extendedConstraint.flags & 1048576 /* Index */ ? instantiateType(extendedConstraint.type, type.mapper || identityMapper) : emptyObjectType; } } return type.modifiersType; } function getMappedTypeModifiers(type) { var declaration = type.declaration; - return (declaration.readonlyToken ? declaration.readonlyToken.kind === 38 ? 2 : 1 : 0) | - (declaration.questionToken ? declaration.questionToken.kind === 38 ? 8 : 4 : 0); + return (declaration.readonlyToken ? declaration.readonlyToken.kind === 38 /* MinusToken */ ? 2 /* ExcludeReadonly */ : 1 /* IncludeReadonly */ : 0) | + (declaration.questionToken ? declaration.questionToken.kind === 38 /* MinusToken */ ? 8 /* ExcludeOptional */ : 4 /* IncludeOptional */ : 0); } function getMappedTypeOptionality(type) { var modifiers = getMappedTypeModifiers(type); - return modifiers & 8 ? -1 : modifiers & 4 ? 1 : 0; + return modifiers & 8 /* ExcludeOptional */ ? -1 : modifiers & 4 /* IncludeOptional */ ? 1 : 0; } function getCombinedMappedTypeOptionality(type) { var optionality = getMappedTypeOptionality(type); @@ -30326,47 +35131,51 @@ var ts; return optionality || (isGenericMappedType(modifiersType) ? getMappedTypeOptionality(modifiersType) : 0); } function isPartialMappedType(type) { - return !!(ts.getObjectFlags(type) & 32 && getMappedTypeModifiers(type) & 4); + return !!(ts.getObjectFlags(type) & 32 /* Mapped */ && getMappedTypeModifiers(type) & 4 /* IncludeOptional */); } function isGenericMappedType(type) { - return !!(ts.getObjectFlags(type) & 32) && isGenericIndexType(getConstraintTypeFromMappedType(type)); + return !!(ts.getObjectFlags(type) & 32 /* Mapped */) && isGenericIndexType(getConstraintTypeFromMappedType(type)); } function resolveStructuredTypeMembers(type) { if (!type.members) { - if (type.flags & 131072) { - if (type.objectFlags & 4) { + if (type.flags & 131072 /* Object */) { + if (type.objectFlags & 4 /* Reference */) { resolveTypeReferenceMembers(type); } - else if (type.objectFlags & 3) { + else if (type.objectFlags & 3 /* ClassOrInterface */) { resolveClassOrInterfaceMembers(type); } - else if (type.objectFlags & 2048) { + else if (type.objectFlags & 2048 /* ReverseMapped */) { resolveReverseMappedTypeMembers(type); } - else if (type.objectFlags & 16) { + else if (type.objectFlags & 16 /* Anonymous */) { resolveAnonymousTypeMembers(type); } - else if (type.objectFlags & 32) { + else if (type.objectFlags & 32 /* Mapped */) { resolveMappedTypeMembers(type); } } - else if (type.flags & 262144) { + else if (type.flags & 262144 /* Union */) { resolveUnionTypeMembers(type); } - else if (type.flags & 524288) { + else if (type.flags & 524288 /* Intersection */) { resolveIntersectionTypeMembers(type); } } return type; } + /** Return properties of an object type or an empty array for other types */ function getPropertiesOfObjectType(type) { - if (type.flags & 131072) { + if (type.flags & 131072 /* Object */) { return resolveStructuredTypeMembers(type).properties; } return ts.emptyArray; } + /** If the given type is an object type and that type has a property by the given name, + * return the symbol for that property. Otherwise return undefined. + */ function getPropertyOfObjectType(type, name) { - if (type.flags & 131072) { + if (type.flags & 131072 /* Object */) { var resolved = resolveStructuredTypeMembers(type); var symbol = resolved.members.get(name); if (symbol && symbolIsValue(symbol)) { @@ -30388,7 +35197,9 @@ var ts; } } } - if (type.flags & 262144) { + // The properties of a union type are those that are present in all constituent types, so + // we only need to check the properties of the first type + if (type.flags & 262144 /* Union */) { break; } } @@ -30398,13 +35209,13 @@ var ts; } function getPropertiesOfType(type) { type = getApparentType(type); - return type.flags & 786432 ? + return type.flags & 786432 /* UnionOrIntersection */ ? getPropertiesOfUnionOrIntersectionType(type) : getPropertiesOfObjectType(type); } function getAllPossiblePropertiesOfTypes(types) { var unionType = getUnionType(types); - if (!(unionType.flags & 262144)) { + if (!(unionType.flags & 262144 /* Union */)) { return getAugmentedPropertiesOfType(unionType); } var props = ts.createSymbolTable(); @@ -30414,6 +35225,7 @@ var ts; var escapedName = _b[_a].escapedName; if (!props.has(escapedName)) { var prop = createUnionOrIntersectionProperty(unionType, escapedName); + // May be undefined if the property is private if (prop) props.set(escapedName, prop); } @@ -30422,9 +35234,9 @@ var ts; return ts.arrayFrom(props.values()); } function getConstraintOfType(type) { - return type.flags & 65536 ? getConstraintOfTypeParameter(type) : - type.flags & 2097152 ? getConstraintOfIndexedAccess(type) : - type.flags & 4194304 ? getConstraintOfConditionalType(type) : + return type.flags & 65536 /* TypeParameter */ ? getConstraintOfTypeParameter(type) : + type.flags & 2097152 /* IndexedAccess */ ? getConstraintOfIndexedAccess(type) : + type.flags & 4194304 /* Conditional */ ? getConstraintOfConditionalType(type) : getBaseConstraintOfType(type); } function getConstraintOfTypeParameter(typeParameter) { @@ -30439,18 +35251,23 @@ var ts; function getDefaultConstraintOfConditionalType(type) { if (!type.resolvedDefaultConstraint) { var rootTrueType = type.root.trueType; - var rootTrueConstraint = rootTrueType.flags & 8388608 ? rootTrueType.substitute : rootTrueType; + var rootTrueConstraint = rootTrueType.flags & 8388608 /* Substitution */ ? rootTrueType.substitute : rootTrueType; type.resolvedDefaultConstraint = getUnionType([instantiateType(rootTrueConstraint, type.combinedMapper || type.mapper), getFalseTypeFromConditionalType(type)]); } return type.resolvedDefaultConstraint; } function getConstraintOfDistributiveConditionalType(type) { + // Check if we have a conditional type of the form 'T extends U ? X : Y', where T is a constrained + // type parameter. If so, create an instantiation of the conditional type where T is replaced + // with its constraint. We do this because if the constraint is a union type it will be distributed + // over the conditional type and possibly reduced. For example, 'T extends undefined ? never : T' + // removes 'undefined' from T. if (type.root.isDistributive) { var constraint = getConstraintOfType(getSimplifiedType(type.checkType)); if (constraint) { var mapper = makeUnaryTypeMapper(type.root.checkType, constraint); var instantiated = getConditionalTypeInstantiation(type, combineTypeMappers(mapper, type.mapper)); - if (!(instantiated.flags & 32768)) { + if (!(instantiated.flags & 32768 /* Never */)) { return instantiated; } } @@ -30465,27 +35282,35 @@ var ts; var hasDisjointDomainType = false; for (var _i = 0, _a = type.types; _i < _a.length; _i++) { var t = _a[_i]; - if (t.flags & 15794176) { + if (t.flags & 15794176 /* Instantiable */) { + // We keep following constraints as long as we have an instantiable type that is known + // not to be circular or infinite (hence we stop on index access types). var constraint = getConstraintOfType(t); - while (constraint && constraint.flags & (65536 | 1048576 | 4194304)) { + while (constraint && constraint.flags & (65536 /* TypeParameter */ | 1048576 /* Index */ | 4194304 /* Conditional */)) { constraint = getConstraintOfType(constraint); } if (constraint) { - if (!(constraint.flags & 262144)) { + // A constraint that isn't a union type implies that the final type would be a non-union + // type as well. Since non-union constraints are of no interest, we can exit here. + if (!(constraint.flags & 262144 /* Union */)) { return undefined; } constraints = ts.append(constraints, constraint); } } - else if (t.flags & 16809468) { + else if (t.flags & 16809468 /* DisjointDomains */) { hasDisjointDomainType = true; } } + // If the target is a union type or if we are intersecting with types belonging to one of the + // disjoint domans, we may end up producing a constraint that hasn't been examined before. if (constraints && (targetIsUnion || hasDisjointDomainType)) { if (hasDisjointDomainType) { + // We add any types belong to one of the disjoint domans because they might cause the final + // intersection operation to reduce the union constraints. for (var _b = 0, _c = type.types; _b < _c.length; _b++) { var t = _c[_b]; - if (t.flags & 16809468) { + if (t.flags & 16809468 /* DisjointDomains */) { constraints = ts.append(constraints, t); } } @@ -30495,7 +35320,7 @@ var ts; return undefined; } function getBaseConstraintOfInstantiableNonPrimitiveUnionOrIntersection(type) { - if (type.flags & (14745600 | 786432)) { + if (type.flags & (14745600 /* InstantiableNonPrimitive */ | 786432 /* UnionOrIntersection */)) { var constraint = getResolvedBaseConstraint(type); if (constraint !== noConstraintType && constraint !== circularConstraintType) { return constraint; @@ -30504,17 +35329,26 @@ var ts; } function getBaseConstraintOfType(type) { var constraint = getBaseConstraintOfInstantiableNonPrimitiveUnionOrIntersection(type); - if (!constraint && type.flags & 1048576) { + if (!constraint && type.flags & 1048576 /* Index */) { return keyofConstraintType; } return constraint; } + /** + * This is similar to `getBaseConstraintOfType` except it returns the input type if there's no base constraint, instead of `undefined` + * It also doesn't map indexes to `string`, as where this is used this would be unneeded (and likely undesirable) + */ function getBaseConstraintOrType(type) { return getBaseConstraintOfType(type) || type; } function hasNonCircularBaseConstraint(type) { return getResolvedBaseConstraint(type) !== circularConstraintType; } + /** + * Return the resolved base constraint of a type variable. The noConstraintType singleton is returned if the + * type variable has no constraint, and the circularConstraintType singleton is returned if the constraint + * circularly references the type variable. + */ function getResolvedBaseConstraint(type) { var circular; if (!type.resolvedBaseConstraint) { @@ -30523,7 +35357,7 @@ var ts; } return type.resolvedBaseConstraint; function getBaseConstraint(t) { - if (!pushTypeResolution(t, 4)) { + if (!pushTypeResolution(t, 4 /* ResolvedBaseConstraint */)) { circular = true; return undefined; } @@ -30535,13 +35369,13 @@ var ts; return result; } function computeBaseConstraint(t) { - if (t.flags & 65536) { + if (t.flags & 65536 /* TypeParameter */) { var constraint = getConstraintFromTypeParameter(t); return t.isThisType || !constraint ? constraint : getBaseConstraint(constraint); } - if (t.flags & 786432) { + if (t.flags & 786432 /* UnionOrIntersection */) { var types = t.types; var baseTypes = []; for (var _i = 0, types_4 = types; _i < types_4.length; _i++) { @@ -30551,24 +35385,24 @@ var ts; baseTypes.push(baseType); } } - return t.flags & 262144 && baseTypes.length === types.length ? getUnionType(baseTypes) : - t.flags & 524288 && baseTypes.length ? getIntersectionType(baseTypes) : + return t.flags & 262144 /* Union */ && baseTypes.length === types.length ? getUnionType(baseTypes) : + t.flags & 524288 /* Intersection */ && baseTypes.length ? getIntersectionType(baseTypes) : undefined; } - if (t.flags & 1048576) { + if (t.flags & 1048576 /* Index */) { return keyofConstraintType; } - if (t.flags & 2097152) { + if (t.flags & 2097152 /* IndexedAccess */) { var baseObjectType = getBaseConstraint(t.objectType); var baseIndexType = getBaseConstraint(t.indexType); var baseIndexedAccess = baseObjectType && baseIndexType ? getIndexedAccessType(baseObjectType, baseIndexType) : undefined; return baseIndexedAccess && baseIndexedAccess !== errorType ? getBaseConstraint(baseIndexedAccess) : undefined; } - if (t.flags & 4194304) { + if (t.flags & 4194304 /* Conditional */) { var constraint = getConstraintOfConditionalType(t); return constraint && getBaseConstraint(constraint); } - if (t.flags & 8388608) { + if (t.flags & 8388608 /* Substitution */) { return getBaseConstraint(t.substitute); } if (isGenericMappedType(t)) { @@ -30578,7 +35412,7 @@ var ts; } } function getApparentTypeOfIntersectionType(type) { - return type.resolvedApparentType || (type.resolvedApparentType = getTypeWithThisArgument(type, type, true)); + return type.resolvedApparentType || (type.resolvedApparentType = getTypeWithThisArgument(type, type, /*apparentType*/ true)); } function getResolvedTypeParameterDefault(typeParameter) { if (!typeParameter.default) { @@ -30587,19 +35421,29 @@ var ts; typeParameter.default = targetDefault ? instantiateType(targetDefault, typeParameter.mapper) : noConstraintType; } else { + // To block recursion, set the initial value to the resolvingDefaultType. typeParameter.default = resolvingDefaultType; var defaultDeclaration = typeParameter.symbol && ts.forEach(typeParameter.symbol.declarations, function (decl) { return ts.isTypeParameterDeclaration(decl) && decl.default; }); var defaultType = defaultDeclaration ? getTypeFromTypeNode(defaultDeclaration) : noConstraintType; if (typeParameter.default === resolvingDefaultType) { + // If we have not been called recursively, set the correct default type. typeParameter.default = defaultType; } } } else if (typeParameter.default === resolvingDefaultType) { + // If we are called recursively for this type parameter, mark the default as circular. typeParameter.default = circularConstraintType; } return typeParameter.default; } + /** + * Gets the default type for a type parameter. + * + * If the type parameter is the result of an instantiation, this gets the instantiated + * default type of its target. If the type parameter has no default type or the default is + * circular, `undefined` is returned. + */ function getDefaultFromTypeParameter(typeParameter) { var defaultType = getResolvedTypeParameterDefault(typeParameter); return defaultType !== noConstraintType && defaultType !== circularConstraintType ? defaultType : undefined; @@ -30607,26 +35451,35 @@ var ts; function hasNonCircularTypeParameterDefault(typeParameter) { return getResolvedTypeParameterDefault(typeParameter) !== circularConstraintType; } + /** + * Indicates whether the declaration of a typeParameter has a default type. + */ function hasTypeParameterDefault(typeParameter) { return !!(typeParameter.symbol && ts.forEach(typeParameter.symbol.declarations, function (decl) { return ts.isTypeParameterDeclaration(decl) && decl.default; })); } + /** + * For a type parameter, return the base constraint of the type parameter. For the string, number, + * boolean, and symbol primitive types, return the corresponding object types. Otherwise return the + * type itself. Note that the apparent type of a union type is the union type itself. + */ function getApparentType(type) { - var t = type.flags & 15794176 ? getBaseConstraintOfType(type) || emptyObjectType : type; - return t.flags & 524288 ? getApparentTypeOfIntersectionType(t) : - t.flags & 68 ? globalStringType : - t.flags & 168 ? globalNumberType : - t.flags & 272 ? globalBooleanType : - t.flags & 3072 ? getGlobalESSymbolType(languageVersion >= 2) : - t.flags & 16777216 ? emptyObjectType : - t.flags & 1048576 ? keyofConstraintType : + var t = type.flags & 15794176 /* Instantiable */ ? getBaseConstraintOfType(type) || emptyObjectType : type; + return t.flags & 524288 /* Intersection */ ? getApparentTypeOfIntersectionType(t) : + t.flags & 68 /* StringLike */ ? globalStringType : + t.flags & 168 /* NumberLike */ ? globalNumberType : + t.flags & 272 /* BooleanLike */ ? globalBooleanType : + t.flags & 3072 /* ESSymbolLike */ ? getGlobalESSymbolType(/*reportErrors*/ languageVersion >= 2 /* ES2015 */) : + t.flags & 16777216 /* NonPrimitive */ ? emptyObjectType : + t.flags & 1048576 /* Index */ ? keyofConstraintType : t; } function createUnionOrIntersectionProperty(containingType, name) { var props; - var isUnion = containingType.flags & 262144; - var excludeModifiers = isUnion ? 24 : 0; - var commonFlags = isUnion ? 0 : 16777216; - var syntheticFlag = 4; + var isUnion = containingType.flags & 262144 /* Union */; + var excludeModifiers = isUnion ? 24 /* NonPublicAccessibilityModifier */ : 0; + // Flags we want to propagate to the result if they exist in all source symbols + var commonFlags = isUnion ? 0 /* None */ : 16777216 /* Optional */; + var syntheticFlag = 4 /* SyntheticMethod */; var checkFlags = 0; for (var _i = 0, _a = containingType.types; _i < _a.length; _i++) { var current = _a[_i]; @@ -30637,24 +35490,24 @@ var ts; if (prop && !(modifiers & excludeModifiers)) { commonFlags &= prop.flags; props = ts.appendIfUnique(props, prop); - checkFlags |= (isReadonlySymbol(prop) ? 8 : 0) | - (!(modifiers & 24) ? 64 : 0) | - (modifiers & 16 ? 128 : 0) | - (modifiers & 8 ? 256 : 0) | - (modifiers & 32 ? 512 : 0); + checkFlags |= (isReadonlySymbol(prop) ? 8 /* Readonly */ : 0) | + (!(modifiers & 24 /* NonPublicAccessibilityModifier */) ? 64 /* ContainsPublic */ : 0) | + (modifiers & 16 /* Protected */ ? 128 /* ContainsProtected */ : 0) | + (modifiers & 8 /* Private */ ? 256 /* ContainsPrivate */ : 0) | + (modifiers & 32 /* Static */ ? 512 /* ContainsStatic */ : 0); if (!isPrototypeProperty(prop)) { - syntheticFlag = 2; + syntheticFlag = 2 /* SyntheticProperty */; } } else if (isUnion) { - checkFlags |= 16; + checkFlags |= 16 /* Partial */; } } } if (!props) { return undefined; } - if (props.length === 1 && !(checkFlags & 16)) { + if (props.length === 1 && !(checkFlags & 16 /* Partial */)) { return props[0]; } var declarations; @@ -30681,12 +35534,12 @@ var ts; } else { if (type !== commonType) { - checkFlags |= 32; + checkFlags |= 32 /* HasNonUniformType */; } } propTypes.push(type); } - var result = createSymbol(4 | commonFlags, name, syntheticFlag | checkFlags); + var result = createSymbol(4 /* Property */ | commonFlags, name, syntheticFlag | checkFlags); result.containingType = containingType; if (!hasNonUniformValueDeclaration && commonValueDeclaration) { result.valueDeclaration = commonValueDeclaration; @@ -30696,6 +35549,11 @@ var ts; result.type = isUnion ? getUnionType(propTypes) : getIntersectionType(propTypes); return result; } + // Return the symbol for a given property in a union or intersection type, or undefined if the property + // does not exist in any constituent type. Note that the returned property may only be present in some + // constituents, in which case the isPartial flag is set when the containing type is union type. We need + // these partial properties when identifying discriminant properties, but otherwise they are filtered out + // and do not appear to be present in the union type. function getUnionOrIntersectionProperty(type, name) { var properties = type.propertyCache || (type.propertyCache = ts.createSymbolTable()); var property = properties.get(name); @@ -30709,11 +35567,20 @@ var ts; } function getPropertyOfUnionOrIntersectionType(type, name) { var property = getUnionOrIntersectionProperty(type, name); - return property && !(ts.getCheckFlags(property) & 16) ? property : undefined; + // We need to filter out partial properties in union types + return property && !(ts.getCheckFlags(property) & 16 /* Partial */) ? property : undefined; } + /** + * Return the symbol for the property with the given name in the given type. Creates synthetic union properties when + * necessary, maps primitive types and type parameters are to their apparent types, and augments with properties from + * Object and Function as appropriate. + * + * @param type a type to look up property from + * @param name a name of property to look up in a given type + */ function getPropertyOfType(type, name) { type = getApparentType(type); - if (type.flags & 131072) { + if (type.flags & 131072 /* Object */) { var resolved = resolveStructuredTypeMembers(type); var symbol = resolved.members.get(name); if (symbol && symbolIsValue(symbol)) { @@ -30727,34 +35594,42 @@ var ts; } return getPropertyOfObjectType(globalObjectType, name); } - if (type.flags & 786432) { + if (type.flags & 786432 /* UnionOrIntersection */) { return getPropertyOfUnionOrIntersectionType(type, name); } return undefined; } function getSignaturesOfStructuredType(type, kind) { - if (type.flags & 917504) { + if (type.flags & 917504 /* StructuredType */) { var resolved = resolveStructuredTypeMembers(type); - return kind === 0 ? resolved.callSignatures : resolved.constructSignatures; + return kind === 0 /* Call */ ? resolved.callSignatures : resolved.constructSignatures; } return ts.emptyArray; } + /** + * Return the signatures of the given kind in the given type. Creates synthetic union signatures when necessary and + * maps primitive types and type parameters are to their apparent types. + */ function getSignaturesOfType(type, kind) { return getSignaturesOfStructuredType(getApparentType(type), kind); } function getIndexInfoOfStructuredType(type, kind) { - if (type.flags & 917504) { + if (type.flags & 917504 /* StructuredType */) { var resolved = resolveStructuredTypeMembers(type); - return kind === 0 ? resolved.stringIndexInfo : resolved.numberIndexInfo; + return kind === 0 /* String */ ? resolved.stringIndexInfo : resolved.numberIndexInfo; } } function getIndexTypeOfStructuredType(type, kind) { var info = getIndexInfoOfStructuredType(type, kind); return info && info.type; } + // Return the indexing info of the given kind in the given type. Creates synthetic union index types when necessary and + // maps primitive types and type parameters are to their apparent types. function getIndexInfoOfType(type, kind) { return getIndexInfoOfStructuredType(getApparentType(type), kind); } + // Return the index type of the given kind in the given type. Creates synthetic union index types when necessary and + // maps primitive types and type parameters are to their apparent types. function getIndexTypeOfType(type, kind) { return getIndexTypeOfStructuredType(getApparentType(type), kind); } @@ -30763,16 +35638,18 @@ var ts; var propTypes = []; for (var _i = 0, _a = getPropertiesOfType(type); _i < _a.length; _i++) { var prop = _a[_i]; - if (kind === 0 || isNumericLiteralName(prop.escapedName)) { + if (kind === 0 /* String */ || isNumericLiteralName(prop.escapedName)) { propTypes.push(getTypeOfSymbol(prop)); } } if (propTypes.length) { - return getUnionType(propTypes, 2); + return getUnionType(propTypes, 2 /* Subtype */); } } return undefined; } + // Return list of type parameters with duplicates removed (duplicate identifier errors are generated in the actual + // type checking functions). function getTypeParametersFromDeclaration(declaration) { var result; for (var _i = 0, _a = ts.getEffectiveTypeParameterDeclarations(declaration); _i < _a.length; _i++) { @@ -30791,17 +35668,20 @@ var ts; return result; } function isJSDocOptionalParameter(node) { - return ts.isInJavaScriptFile(node) && (node.type && node.type.kind === 283 + return ts.isInJavaScriptFile(node) && ( + // node.type should only be a JSDocOptionalType when node is a parameter of a JSDocFunctionType + node.type && node.type.kind === 283 /* JSDocOptionalType */ || ts.getJSDocParameterTags(node).some(function (_a) { var isBracketed = _a.isBracketed, typeExpression = _a.typeExpression; - return isBracketed || !!typeExpression && typeExpression.type.kind === 283; + return isBracketed || !!typeExpression && typeExpression.type.kind === 283 /* JSDocOptionalType */; })); } function tryFindAmbientModule(moduleName, withAugmentations) { if (ts.isExternalModuleNameRelative(moduleName)) { return undefined; } - var symbol = getSymbol(globals, '"' + moduleName + '"', 512); + var symbol = getSymbol(globals, '"' + moduleName + '"', 512 /* ValueModule */); + // merged symbol is module declaration symbol combined with all augmentations return symbol && withAugmentations ? getMergedSymbol(symbol) : symbol; } function isOptionalParameter(node) { @@ -30827,24 +35707,29 @@ var ts; return false; } var isBracketed = node.isBracketed, typeExpression = node.typeExpression; - return isBracketed || !!typeExpression && typeExpression.type.kind === 283; + return isBracketed || !!typeExpression && typeExpression.type.kind === 283 /* JSDocOptionalType */; } function createTypePredicateFromTypePredicateNode(node) { var parameterName = node.parameterName; var type = getTypeFromTypeNode(node.type); - if (parameterName.kind === 71) { - return createIdentifierTypePredicate(parameterName && parameterName.escapedText, parameterName && getTypePredicateParameterIndex(node.parent.parameters, parameterName), type); + if (parameterName.kind === 71 /* Identifier */) { + return createIdentifierTypePredicate(parameterName && parameterName.escapedText, // TODO: GH#18217 + parameterName && getTypePredicateParameterIndex(node.parent.parameters, parameterName), type); } else { return createThisTypePredicate(type); } } function createIdentifierTypePredicate(parameterName, parameterIndex, type) { - return { kind: 1, parameterName: parameterName, parameterIndex: parameterIndex, type: type }; + return { kind: 1 /* Identifier */, parameterName: parameterName, parameterIndex: parameterIndex, type: type }; } function createThisTypePredicate(type) { - return { kind: 0, type: type }; + return { kind: 0 /* This */, type: type }; } + /** + * Gets the minimum number of type arguments needed to satisfy all non-optional type + * parameters. + */ function getMinTypeArgumentCount(typeParameters) { var minTypeArgumentCount = 0; if (typeParameters) { @@ -30864,6 +35749,9 @@ var ts; if (!typeArguments) { typeArguments = []; } + // Map an unsatisfied type parameter with a default type. + // If a type parameter does not have a default type, or if the default type + // is a forward reference, the empty object type is used. for (var i = numTypeArguments; i < numTypeParameters; i++) { typeArguments[i] = getDefaultTypeArgumentType(isJavaScriptImplicitAny); } @@ -30895,12 +35783,16 @@ var ts; ts.isValueSignatureDeclaration(declaration) && !ts.hasJSDocParameterTags(declaration) && !ts.getJSDocType(declaration); + // If this is a JSDoc construct signature, then skip the first parameter in the + // parameter list. The first parameter represents the return type of the construct + // signature. for (var i = isJSConstructSignature ? 1 : 0; i < declaration.parameters.length; i++) { var param = declaration.parameters[i]; var paramSymbol = param.symbol; var type = ts.isJSDocParameterTag(param) ? (param.typeExpression && param.typeExpression.type) : param.type; - if (paramSymbol && !!(paramSymbol.flags & 4) && !ts.isBindingPattern(param.name)) { - var resolvedSymbol = resolveName(param, paramSymbol.escapedName, 67216319, undefined, undefined, false); + // Include parameter symbol instead of property symbol in the signature + if (paramSymbol && !!(paramSymbol.flags & 4 /* Property */) && !ts.isBindingPattern(param.name)) { + var resolvedSymbol = resolveName(param, paramSymbol.escapedName, 67216319 /* Value */, undefined, undefined, /*isUse*/ false); paramSymbol = resolvedSymbol; } if (i === 0 && paramSymbol.escapedName === "this") { @@ -30910,9 +35802,10 @@ var ts; else { parameters.push(paramSymbol); } - if (type && type.kind === 178) { + if (type && type.kind === 178 /* LiteralType */) { hasLiteralTypes = true; } + // Record a new minimum argument count if this is not an optional parameter var isOptionalParameter_1 = isOptionalJSDocParameterTag(param) || param.initializer || param.questionToken || param.dotDotDotToken || iife && parameters.length > iife.arguments.length && !type || @@ -30922,25 +35815,32 @@ var ts; minArgumentCount = parameters.length; } } - if ((declaration.kind === 156 || declaration.kind === 157) && + // If only one accessor includes a this-type annotation, the other behaves as if it had the same type annotation + if ((declaration.kind === 156 /* GetAccessor */ || declaration.kind === 157 /* SetAccessor */) && !hasNonBindableDynamicName(declaration) && (!hasThisParameter || !thisParameter)) { - var otherKind = declaration.kind === 156 ? 157 : 156; + var otherKind = declaration.kind === 156 /* GetAccessor */ ? 157 /* SetAccessor */ : 156 /* GetAccessor */; var other = ts.getDeclarationOfKind(getSymbolOfNode(declaration), otherKind); if (other) { thisParameter = getAnnotatedAccessorThisParameter(other); } } - var classType = declaration.kind === 155 ? + var classType = declaration.kind === 155 /* Constructor */ ? getDeclaredTypeOfClassOrInterface(getMergedSymbol(declaration.parent.symbol)) : undefined; var typeParameters = classType ? classType.localTypeParameters : getTypeParametersFromDeclaration(declaration); var returnType = getSignatureReturnTypeFromDeclaration(declaration, isJSConstructSignature, classType); var hasRestLikeParameter = ts.hasRestParameter(declaration) || ts.isInJavaScriptFile(declaration) && maybeAddJsSyntheticRestParameter(declaration, parameters); - links.resolvedSignature = createSignature(declaration, typeParameters, thisParameter, parameters, returnType, undefined, minArgumentCount, hasRestLikeParameter, hasLiteralTypes); + links.resolvedSignature = createSignature(declaration, typeParameters, thisParameter, parameters, returnType, /*resolvedTypePredicate*/ undefined, minArgumentCount, hasRestLikeParameter, hasLiteralTypes); } return links.resolvedSignature; } + /** + * A JS function gets a synthetic rest parameter if it references `arguments` AND: + * 1. It has no parameters but at least one `@param` with a type that starts with `...` + * OR + * 2. It has at least one parameter, and the last parameter has a matching `@param` with a type that starts with `...` + */ function maybeAddJsSyntheticRestParameter(declaration, parameters) { if (ts.isJSDocSignature(declaration) || !containsArgumentsReference(declaration)) { return false; @@ -30950,10 +35850,11 @@ var ts; var lastParamVariadicType = ts.firstDefined(lastParamTags, function (p) { return p.typeExpression && ts.isJSDocVariadicType(p.typeExpression.type) ? p.typeExpression.type : undefined; }); - var syntheticArgsSymbol = createSymbol(3, "args"); + var syntheticArgsSymbol = createSymbol(3 /* Variable */, "args"); syntheticArgsSymbol.type = lastParamVariadicType ? createArrayType(getTypeFromTypeNode(lastParamVariadicType.type)) : anyArrayType; syntheticArgsSymbol.isRestParameter = true; if (lastParamVariadicType) { + // Replace the last parameter with a rest parameter. parameters.pop(); } parameters.push(syntheticArgsSymbol); @@ -30961,7 +35862,7 @@ var ts; } function getSignatureReturnTypeFromDeclaration(declaration, isJSConstructSignature, classType) { if (isJSConstructSignature) { - return getTypeFromTypeNode(declaration.parameters[0].type); + return getTypeFromTypeNode(declaration.parameters[0].type); // TODO: GH#18217 } else if (classType) { return classType; @@ -30970,8 +35871,10 @@ var ts; if (typeNode) { return getTypeFromTypeNode(typeNode); } - if (declaration.kind === 156 && !hasNonBindableDynamicName(declaration)) { - var setter = ts.getDeclarationOfKind(getSymbolOfNode(declaration), 157); + // TypeScript 1.0 spec (April 2014): + // If only one accessor includes a type annotation, the other behaves as if it had the same type annotation. + if (declaration.kind === 156 /* GetAccessor */ && !hasNonBindableDynamicName(declaration)) { + var setter = ts.getDeclarationOfKind(getSymbolOfNode(declaration), 157 /* SetAccessor */); return getAnnotatedAccessorType(setter); } if (ts.nodeIsMissing(declaration.body)) { @@ -30981,7 +35884,7 @@ var ts; function containsArgumentsReference(declaration) { var links = getNodeLinks(declaration); if (links.containsArgumentsReference === undefined) { - if (links.flags & 8192) { + if (links.flags & 8192 /* CaptureArguments */) { links.containsArgumentsReference = true; } else { @@ -30993,13 +35896,13 @@ var ts; if (!node) return false; switch (node.kind) { - case 71: + case 71 /* Identifier */: return node.escapedText === "arguments" && ts.isExpressionNode(node); - case 152: - case 154: - case 156: - case 157: - return node.name.kind === 147 + case 152 /* PropertyDeclaration */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + return node.name.kind === 147 /* ComputedPropertyName */ && traverse(node.name); default: return !ts.nodeStartsNewLexicalEnvironment(node) && !ts.isPartOfTypeNode(node) && !!ts.forEachChild(node, traverse); @@ -31014,6 +35917,9 @@ var ts; var decl = symbol.declarations[i]; if (!ts.isFunctionLike(decl)) continue; + // Don't include signature if node is the implementation of an overloaded function. A node is considered + // an implementation node if it has a body and the previous node is of the same kind and immediately + // precedes the implementation node (i.e. has the same parent and ends where the implementation starts). if (i > 0 && decl.body) { var previous = symbol.declarations[i - 1]; if (decl.parent === previous.parent && decl.kind === previous.kind && decl.pos === previous.end) { @@ -31053,7 +35959,7 @@ var ts; } else { var declaration = signature.declaration; - signature.resolvedTypePredicate = declaration && declaration.type && declaration.type.kind === 161 ? + signature.resolvedTypePredicate = declaration && declaration.type && declaration.type.kind === 161 /* TypePredicate */ ? createTypePredicateFromTypePredicateNode(declaration.type) : noTypePredicate; } @@ -31063,7 +35969,7 @@ var ts; } function getReturnTypeOfSignature(signature) { if (!signature.resolvedReturnType) { - if (!pushTypeResolution(signature, 3)) { + if (!pushTypeResolution(signature, 3 /* ResolvedReturnType */)) { return errorType; } var type = void 0; @@ -31071,7 +35977,7 @@ var ts; type = instantiateType(getReturnTypeOfSignature(signature.target), signature.mapper); } else if (signature.unionSignatures) { - type = getUnionType(ts.map(signature.unionSignatures, getReturnTypeOfSignature), 2); + type = getUnionType(ts.map(signature.unionSignatures, getReturnTypeOfSignature), 2 /* Subtype */); } else { type = getReturnTypeFromBody(signature.declaration); @@ -31094,12 +36000,12 @@ var ts; return signature.resolvedReturnType; } function isResolvingReturnTypeOfSignature(signature) { - return !signature.resolvedReturnType && findResolutionCycleStartIndex(signature, 3) >= 0; + return !signature.resolvedReturnType && findResolutionCycleStartIndex(signature, 3 /* ResolvedReturnType */) >= 0; } function getRestTypeOfSignature(signature) { if (signature.hasRestParameter) { var type = getTypeOfSymbol(ts.last(signature.parameters)); - if (ts.getObjectFlags(type) & 4 && type.target === globalArrayType) { + if (ts.getObjectFlags(type) & 4 /* Reference */ && type.target === globalArrayType) { return type.typeArguments[0]; } } @@ -31116,7 +36022,7 @@ var ts; return instantiation; } function createSignatureInstantiation(signature, typeArguments) { - return instantiateSignature(signature, createSignatureTypeMapper(signature, typeArguments), true); + return instantiateSignature(signature, createSignatureTypeMapper(signature, typeArguments), /*eraseTypeParameters*/ true); } function createSignatureTypeMapper(signature, typeArguments) { return createTypeMapper(signature.typeParameters, typeArguments); @@ -31127,7 +36033,8 @@ var ts; signature; } function createErasedSignature(signature) { - return instantiateSignature(signature, createTypeEraser(signature.typeParameters), true); + // Create an instantiation of the signature where all type arguments are the any type. + return instantiateSignature(signature, createTypeEraser(signature.typeParameters), /*eraseTypeParameters*/ true); } function getCanonicalSignature(signature) { return signature.typeParameters ? @@ -31135,6 +36042,12 @@ var ts; signature; } function createCanonicalSignature(signature) { + // Create an instantiation of the signature where each unconstrained type parameter is replaced with + // its original. When a generic class or interface is instantiated, each generic method in the class or + // interface is instantiated with a fresh set of cloned type parameters (which we need to handle scenarios + // where different generations of the same type parameter are in scope). This leads to a lot of new type + // identities, and potentially a lot of work comparing those identities, so here we create an instantiation + // that uses the original type identities for all unconstrained type parameters. return getSignatureInstantiation(signature, ts.map(signature.typeParameters, function (tp) { return tp.target && !getConstraintOfTypeParameter(tp.target) ? tp.target : tp; }), ts.isInJavaScriptFile(signature.declaration)); } function getBaseSignature(signature) { @@ -31142,14 +36055,18 @@ var ts; if (typeParameters) { var typeEraser_1 = createTypeEraser(typeParameters); var baseConstraints = ts.map(typeParameters, function (tp) { return instantiateType(getBaseConstraintOfType(tp), typeEraser_1) || emptyObjectType; }); - return instantiateSignature(signature, createTypeMapper(typeParameters, baseConstraints), true); + return instantiateSignature(signature, createTypeMapper(typeParameters, baseConstraints), /*eraseTypeParameters*/ true); } return signature; } function getOrCreateTypeFromSignature(signature) { + // There are two ways to declare a construct signature, one is by declaring a class constructor + // using the constructor keyword, and the other is declaring a bare construct signature in an + // object type literal or interface (using the new keyword). Each way of declaring a constructor + // will result in a different declaration kind. if (!signature.isolatedSignatureType) { - var isConstructor = signature.declaration.kind === 155 || signature.declaration.kind === 159; - var type = createObjectType(16); + var isConstructor = signature.declaration.kind === 155 /* Constructor */ || signature.declaration.kind === 159 /* ConstructSignature */; // TODO: GH#18217 + var type = createObjectType(16 /* Anonymous */); type.members = emptySymbols; type.properties = ts.emptyArray; type.callSignatures = !isConstructor ? [signature] : ts.emptyArray; @@ -31159,10 +36076,10 @@ var ts; return signature.isolatedSignatureType; } function getIndexSymbol(symbol) { - return symbol.members.get("__index"); + return symbol.members.get("__index" /* Index */); } function getIndexDeclarationOfSymbol(symbol, kind) { - var syntaxKind = kind === 1 ? 134 : 137; + var syntaxKind = kind === 1 /* Number */ ? 134 /* NumberKeyword */ : 137 /* StringKeyword */; var indexSymbol = getIndexSymbol(symbol); if (indexSymbol) { for (var _i = 0, _a = indexSymbol.declarations; _i < _a.length; _i++) { @@ -31184,12 +36101,12 @@ var ts; function getIndexInfoOfSymbol(symbol, kind) { var declaration = getIndexDeclarationOfSymbol(symbol, kind); if (declaration) { - return createIndexInfo(declaration.type ? getTypeFromTypeNode(declaration.type) : anyType, ts.hasModifier(declaration, 64), declaration); + return createIndexInfo(declaration.type ? getTypeFromTypeNode(declaration.type) : anyType, ts.hasModifier(declaration, 64 /* Readonly */), declaration); } return undefined; } function getConstraintDeclaration(type) { - var decl = type.symbol && ts.getDeclarationOfKind(type.symbol, 148); + var decl = type.symbol && ts.getDeclarationOfKind(type.symbol, 148 /* TypeParameter */); return decl && decl.constraint; } function getInferredTypeParameterConstraint(typeParameter) { @@ -31197,7 +36114,11 @@ var ts; if (typeParameter.symbol) { for (var _i = 0, _a = typeParameter.symbol.declarations; _i < _a.length; _i++) { var declaration = _a[_i]; - if (declaration.parent.kind === 172 && declaration.parent.parent.kind === 162) { + // When an 'infer T' declaration is immediately contained in a type reference node + // (such as 'Foo'), T's constraint is inferred from the constraint of the + // corresponding type parameter in 'Foo'. When multiple 'infer T' declarations are + // present, we form an intersection of the inferred constraint types. + if (declaration.parent.kind === 172 /* InferType */ && declaration.parent.parent.kind === 162 /* TypeReference */) { var typeReference = declaration.parent.parent; var typeParameters = getTypeParametersForTypeReference(typeReference); if (typeParameters) { @@ -31205,6 +36126,12 @@ var ts; if (index < typeParameters.length) { var declaredConstraint = getConstraintOfTypeParameter(typeParameters[index]); if (declaredConstraint) { + // Type parameter constraints can reference other type parameters so + // constraints need to be instantiated. If instantiation produces the + // type parameter itself, we discard that inference. For example, in + // type Foo = [T, U]; + // type Bar = T extends Foo ? Foo : T; + // the instantiated constraint for U is X, so we discard that inference. var mapper = createTypeMapper(typeParameters, getEffectiveTypeArguments(typeReference, typeParameters)); var constraint = instantiateType(declaredConstraint, mapper); if (constraint !== typeParameter) { @@ -31233,7 +36160,7 @@ var ts; return typeParameter.constraint === noConstraintType ? undefined : typeParameter.constraint; } function getParentSymbolOfTypeParameter(typeParameter) { - return getSymbolOfNode(ts.getDeclarationOfKind(typeParameter.symbol, 148).parent); + return getSymbolOfNode(ts.getDeclarationOfKind(typeParameter.symbol, 148 /* TypeParameter */).parent); } function getTypeListId(types) { var result = ""; @@ -31258,6 +36185,10 @@ var ts; } return result; } + // This function is used to propagate certain flags when creating new object type references and union types. + // It is only necessary to do so if a constituent type might be the undefined type, the null type, the type + // of an object literal or the anyFunctionType. This is because there are operations in the type checker + // that care about the presence of such types at arbitrary depth in a containing type. function getPropagatingFlagsOfTypes(types, excludeKinds) { var result = 0; for (var _i = 0, types_5 = types; _i < types_5.length; _i++) { @@ -31266,15 +36197,15 @@ var ts; result |= type.flags; } } - return result & 939524096; + return result & 939524096 /* PropagatingFlags */; } function createTypeReference(target, typeArguments) { var id = getTypeListId(typeArguments); var type = target.instantiations.get(id); if (!type) { - type = createObjectType(4, target.symbol); + type = createObjectType(4 /* Reference */, target.symbol); target.instantiations.set(id, type); - type.flags |= typeArguments ? getPropagatingFlagsOfTypes(typeArguments, 0) : 0; + type.flags |= typeArguments ? getPropagatingFlagsOfTypes(typeArguments, /*excludeKinds*/ 0) : 0; type.target = target; type.typeArguments = typeArguments; } @@ -31291,6 +36222,9 @@ var ts; function getTypeReferenceArity(type) { return ts.length(type.target.typeParameters); } + /** + * Get type from type-reference that reference to class or interface + */ function getTypeFromClassOrInterfaceReference(node, symbol, typeArgs) { var type = getDeclaredTypeOfSymbol(getMergedSymbol(symbol)); var typeParameters = type.localTypeParameters; @@ -31300,7 +36234,7 @@ var ts; var isJs = ts.isInJavaScriptFile(node); var isJsImplicitAny = !noImplicitAny && isJs; if (!isJsImplicitAny && (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length)) { - var missingAugmentsTag = isJs && node.parent.kind !== 290; + var missingAugmentsTag = isJs && node.parent.kind !== 290 /* JSDocAugmentsTag */; var diag = minTypeArgumentCount === typeParameters.length ? missingAugmentsTag ? ts.Diagnostics.Expected_0_type_arguments_provide_these_with_an_extends_tag @@ -31308,12 +36242,16 @@ var ts; : missingAugmentsTag ? ts.Diagnostics.Expected_0_1_type_arguments_provide_these_with_an_extends_tag : ts.Diagnostics.Generic_type_0_requires_between_1_and_2_type_arguments; - var typeStr = typeToString(type, undefined, 2); + var typeStr = typeToString(type, /*enclosingDeclaration*/ undefined, 2 /* WriteArrayAsGenericType */); error(node, diag, typeStr, minTypeArgumentCount, typeParameters.length); if (!isJs) { + // TODO: Adopt same permissive behavior in TS as in JS to reduce follow-on editing experience failures (requires editing fillMissingTypeArguments) return errorType; } } + // In a type reference, the outer type parameters of the referenced class or interface are automatically + // supplied as type arguments and the type reference only specifies arguments for the local type parameters + // of the class or interface. var typeArguments = ts.concatenate(type.outerTypeParameters, fillMissingTypeArguments(typeArgs, typeParameters, minTypeArgumentCount, isJs)); return createTypeReference(type, typeArguments); } @@ -31330,6 +36268,11 @@ var ts; } return instantiation; } + /** + * Get type from reference to type alias. When a type alias is generic, the declared type of the type alias may include + * references to the type parameters of the alias. We replace those with the actual type arguments by instantiating the + * declared type. Instantiations are cached using the type identities of the type arguments as the key. + */ function getTypeFromTypeAliasReference(node, symbol, typeArguments) { var type = getDeclaredTypeOfSymbol(symbol); var typeParameters = getSymbolLinks(symbol).typeParameters; @@ -31348,13 +36291,16 @@ var ts; } function getTypeReferenceName(node) { switch (node.kind) { - case 162: + case 162 /* TypeReference */: return node.typeName; - case 207: + case 207 /* ExpressionWithTypeArguments */: + // We only support expressions that are simple qualified names. For other + // expressions this produces undefined. var expr = node.expression; if (ts.isEntityNameExpression(expr)) { return expr; } + // fall through; } return undefined; } @@ -31365,7 +36311,7 @@ var ts; return resolveEntityName(typeReferenceName, meaning) || unknownSymbol; } function getTypeReferenceType(node, symbol) { - var typeArguments = typeArgumentsFromTypeReferenceNode(node); + var typeArguments = typeArgumentsFromTypeReferenceNode(node); // Do unconditionally so we mark type arguments as referenced. if (symbol === unknownSymbol) { return errorType; } @@ -31373,32 +36319,40 @@ var ts; if (type) { return type; } + // Get type from reference to named type that cannot be generic (enum or type parameter) var res = tryGetDeclaredTypeOfSymbol(symbol); if (res) { return checkNoTypeArguments(node, symbol) ? - res.flags & 65536 ? getConstrainedTypeVariable(res, node) : res : + res.flags & 65536 /* TypeParameter */ ? getConstrainedTypeVariable(res, node) : res : errorType; } - if (!(symbol.flags & 67216319 && isJSDocTypeReference(node))) { + if (!(symbol.flags & 67216319 /* Value */ && isJSDocTypeReference(node))) { return errorType; } var jsdocType = getJSDocTypeReference(node, symbol, typeArguments); if (jsdocType) { return jsdocType; } - resolveTypeReferenceName(getTypeReferenceName(node), 67901928); + // Resolve the type reference as a Type for the purpose of reporting errors. + resolveTypeReferenceName(getTypeReferenceName(node), 67901928 /* Type */); return getTypeOfSymbol(symbol); } + /** + * A jsdoc TypeReference may have resolved to a value (as opposed to a type). If + * the symbol is a constructor function, return the inferred class type; otherwise, + * the type of this reference is just the type of the value we resolved to. + */ function getJSDocTypeReference(node, symbol, typeArguments) { var assignedType = getAssignedClassType(symbol); var valueType = getTypeOfSymbol(symbol); var referenceType = valueType.symbol && valueType.symbol !== symbol && !isInferredClassType(valueType) && getTypeReferenceTypeWorker(node, valueType.symbol, typeArguments); if (referenceType || assignedType) { + // TODO: GH#18217 (should the `|| assignedType` be at a lower precedence?) return (referenceType && assignedType ? getIntersectionType([assignedType, referenceType]) : referenceType || assignedType); } } function getTypeReferenceTypeWorker(node, symbol, typeArguments) { - if (symbol.flags & (32 | 64)) { + if (symbol.flags & (32 /* Class */ | 64 /* Interface */)) { if (symbol.valueDeclaration && ts.isBinaryExpression(symbol.valueDeclaration.parent)) { var jsdocType = getJSDocTypeReference(node, symbol, typeArguments); if (jsdocType) { @@ -31407,23 +36361,23 @@ var ts; } return getTypeFromClassOrInterfaceReference(node, symbol, typeArguments); } - if (symbol.flags & 524288) { + if (symbol.flags & 524288 /* TypeAlias */) { return getTypeFromTypeAliasReference(node, symbol, typeArguments); } - if (symbol.flags & 16 && + if (symbol.flags & 16 /* Function */ && isJSDocTypeReference(node) && (symbol.members || ts.getJSDocClassTag(symbol.valueDeclaration))) { return getInferredClassType(symbol); } } function getSubstitutionType(typeVariable, substitute) { - var result = createType(8388608); + var result = createType(8388608 /* Substitution */); result.typeVariable = typeVariable; result.substitute = substitute; return result; } function isUnaryTupleTypeNode(node) { - return node.kind === 168 && node.elementTypes.length === 1; + return node.kind === 168 /* TupleType */ && node.elementTypes.length === 1; } function getImpliedConstraint(typeVariable, checkNode, extendsNode) { return isUnaryTupleTypeNode(checkNode) && isUnaryTupleTypeNode(extendsNode) ? getImpliedConstraint(typeVariable, checkNode.elementTypes[0], extendsNode.elementTypes[0]) : @@ -31432,9 +36386,9 @@ var ts; } function getConstrainedTypeVariable(typeVariable, node) { var constraints; - while (node && !ts.isStatement(node) && node.kind !== 286) { + while (node && !ts.isStatement(node) && node.kind !== 286 /* JSDocComment */) { var parent = node.parent; - if (parent.kind === 171 && node === parent.trueType) { + if (parent.kind === 171 /* ConditionalType */ && node === parent.trueType) { var constraint = getImpliedConstraint(typeVariable, parent.checkType, parent.extendsType); if (constraint) { constraints = ts.append(constraints, constraint); @@ -31445,7 +36399,7 @@ var ts; return constraints ? getSubstitutionType(typeVariable, getIntersectionType(ts.append(constraints, typeVariable))) : typeVariable; } function isJSDocTypeReference(node) { - return !!(node.flags & 2097152) && node.kind === 162; + return !!(node.flags & 2097152 /* JSDoc */) && node.kind === 162 /* TypeReference */; } function checkNoTypeArguments(node, symbol) { if (node.typeArguments) { @@ -31491,7 +36445,7 @@ var ts; if (ts.isJSDocIndexSignature(node)) { var indexed = getTypeFromTypeNode(typeArgs[0]); var target = getTypeFromTypeNode(typeArgs[1]); - var index = createIndexInfo(target, false); + var index = createIndexInfo(target, /*isReadonly*/ false); return createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, indexed === stringType ? index : undefined, indexed === numberType ? index : undefined); } return anyType; @@ -31503,22 +36457,24 @@ var ts; } function getTypeFromJSDocNullableTypeNode(node) { var type = getTypeFromTypeNode(node.type); - return strictNullChecks ? getNullableType(type, 16384) : type; + return strictNullChecks ? getNullableType(type, 16384 /* Null */) : type; } function getTypeFromTypeReference(node) { var links = getNodeLinks(node); if (!links.resolvedType) { var symbol = void 0; var type = void 0; - var meaning = 67901928; + var meaning = 67901928 /* Type */; if (isJSDocTypeReference(node)) { type = getIntendedTypeFromJSDocTypeReference(node); - meaning |= 67216319; + meaning |= 67216319 /* Value */; } if (!type) { symbol = resolveTypeReferenceName(getTypeReferenceName(node), meaning); type = getTypeReferenceType(node, symbol); } + // Cache both the resolved symbol and the resolved type. The resolved symbol is needed in when we check the + // type reference in checkTypeReferenceNode. links.resolvedSymbol = symbol; links.resolvedType = type; } @@ -31530,6 +36486,10 @@ var ts; function getTypeFromTypeQueryNode(node) { var links = getNodeLinks(node); if (!links.resolvedType) { + // TypeScript 1.0 spec (April 2014): 3.6.3 + // The expression is processed as an identifier expression (section 4.3) + // or property access expression(section 4.10), + // the widened type(section 3.9) of which becomes the result. links.resolvedType = getWidenedType(checkExpression(node.exprName)); } return links.resolvedType; @@ -31540,9 +36500,9 @@ var ts; for (var _i = 0, declarations_3 = declarations; _i < declarations_3.length; _i++) { var declaration = declarations_3[_i]; switch (declaration.kind) { - case 235: - case 236: - case 238: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + case 238 /* EnumDeclaration */: return declaration; } } @@ -31551,7 +36511,7 @@ var ts; return arity ? emptyGenericType : emptyObjectType; } var type = getDeclaredTypeOfSymbol(symbol); - if (!(type.flags & 131072)) { + if (!(type.flags & 131072 /* Object */)) { error(getTypeDeclaration(symbol), ts.Diagnostics.Global_type_0_must_be_a_class_or_interface_type, ts.symbolName(symbol)); return arity ? emptyGenericType : emptyObjectType; } @@ -31562,68 +36522,72 @@ var ts; return type; } function getGlobalValueSymbol(name, reportErrors) { - return getGlobalSymbol(name, 67216319, reportErrors ? ts.Diagnostics.Cannot_find_global_value_0 : undefined); + return getGlobalSymbol(name, 67216319 /* Value */, reportErrors ? ts.Diagnostics.Cannot_find_global_value_0 : undefined); } function getGlobalTypeSymbol(name, reportErrors) { - return getGlobalSymbol(name, 67901928, reportErrors ? ts.Diagnostics.Cannot_find_global_type_0 : undefined); + return getGlobalSymbol(name, 67901928 /* Type */, reportErrors ? ts.Diagnostics.Cannot_find_global_type_0 : undefined); } function getGlobalSymbol(name, meaning, diagnostic) { - return resolveName(undefined, name, meaning, diagnostic, name, false); + // Don't track references for global symbols anyway, so value if `isReference` is arbitrary + return resolveName(undefined, name, meaning, diagnostic, name, /*isUse*/ false); } function getGlobalType(name, arity, reportErrors) { var symbol = getGlobalTypeSymbol(name, reportErrors); return symbol || reportErrors ? getTypeOfGlobalSymbol(symbol, arity) : undefined; } function getGlobalTypedPropertyDescriptorType() { - return deferredGlobalTypedPropertyDescriptorType || (deferredGlobalTypedPropertyDescriptorType = getGlobalType("TypedPropertyDescriptor", 1, true)) || emptyGenericType; + return deferredGlobalTypedPropertyDescriptorType || (deferredGlobalTypedPropertyDescriptorType = getGlobalType("TypedPropertyDescriptor", /*arity*/ 1, /*reportErrors*/ true)) || emptyGenericType; } function getGlobalTemplateStringsArrayType() { - return deferredGlobalTemplateStringsArrayType || (deferredGlobalTemplateStringsArrayType = getGlobalType("TemplateStringsArray", 0, true)) || emptyObjectType; + return deferredGlobalTemplateStringsArrayType || (deferredGlobalTemplateStringsArrayType = getGlobalType("TemplateStringsArray", /*arity*/ 0, /*reportErrors*/ true)) || emptyObjectType; } function getGlobalImportMetaType() { - return deferredGlobalImportMetaType || (deferredGlobalImportMetaType = getGlobalType("ImportMeta", 0, true)) || emptyObjectType; + return deferredGlobalImportMetaType || (deferredGlobalImportMetaType = getGlobalType("ImportMeta", /*arity*/ 0, /*reportErrors*/ true)) || emptyObjectType; } function getGlobalESSymbolConstructorSymbol(reportErrors) { return deferredGlobalESSymbolConstructorSymbol || (deferredGlobalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol", reportErrors)); } function getGlobalESSymbolType(reportErrors) { - return deferredGlobalESSymbolType || (deferredGlobalESSymbolType = getGlobalType("Symbol", 0, reportErrors)) || emptyObjectType; + return deferredGlobalESSymbolType || (deferredGlobalESSymbolType = getGlobalType("Symbol", /*arity*/ 0, reportErrors)) || emptyObjectType; } function getGlobalPromiseType(reportErrors) { - return deferredGlobalPromiseType || (deferredGlobalPromiseType = getGlobalType("Promise", 1, reportErrors)) || emptyGenericType; + return deferredGlobalPromiseType || (deferredGlobalPromiseType = getGlobalType("Promise", /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalPromiseConstructorSymbol(reportErrors) { return deferredGlobalPromiseConstructorSymbol || (deferredGlobalPromiseConstructorSymbol = getGlobalValueSymbol("Promise", reportErrors)); } function getGlobalPromiseConstructorLikeType(reportErrors) { - return deferredGlobalPromiseConstructorLikeType || (deferredGlobalPromiseConstructorLikeType = getGlobalType("PromiseConstructorLike", 0, reportErrors)) || emptyObjectType; + return deferredGlobalPromiseConstructorLikeType || (deferredGlobalPromiseConstructorLikeType = getGlobalType("PromiseConstructorLike", /*arity*/ 0, reportErrors)) || emptyObjectType; } function getGlobalAsyncIterableType(reportErrors) { - return deferredGlobalAsyncIterableType || (deferredGlobalAsyncIterableType = getGlobalType("AsyncIterable", 1, reportErrors)) || emptyGenericType; + return deferredGlobalAsyncIterableType || (deferredGlobalAsyncIterableType = getGlobalType("AsyncIterable", /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalAsyncIteratorType(reportErrors) { - return deferredGlobalAsyncIteratorType || (deferredGlobalAsyncIteratorType = getGlobalType("AsyncIterator", 1, reportErrors)) || emptyGenericType; + return deferredGlobalAsyncIteratorType || (deferredGlobalAsyncIteratorType = getGlobalType("AsyncIterator", /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalAsyncIterableIteratorType(reportErrors) { - return deferredGlobalAsyncIterableIteratorType || (deferredGlobalAsyncIterableIteratorType = getGlobalType("AsyncIterableIterator", 1, reportErrors)) || emptyGenericType; + return deferredGlobalAsyncIterableIteratorType || (deferredGlobalAsyncIterableIteratorType = getGlobalType("AsyncIterableIterator", /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalIterableType(reportErrors) { - return deferredGlobalIterableType || (deferredGlobalIterableType = getGlobalType("Iterable", 1, reportErrors)) || emptyGenericType; + return deferredGlobalIterableType || (deferredGlobalIterableType = getGlobalType("Iterable", /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalIteratorType(reportErrors) { - return deferredGlobalIteratorType || (deferredGlobalIteratorType = getGlobalType("Iterator", 1, reportErrors)) || emptyGenericType; + return deferredGlobalIteratorType || (deferredGlobalIteratorType = getGlobalType("Iterator", /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalIterableIteratorType(reportErrors) { - return deferredGlobalIterableIteratorType || (deferredGlobalIterableIteratorType = getGlobalType("IterableIterator", 1, reportErrors)) || emptyGenericType; + return deferredGlobalIterableIteratorType || (deferredGlobalIterableIteratorType = getGlobalType("IterableIterator", /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalTypeOrUndefined(name, arity) { if (arity === void 0) { arity = 0; } - var symbol = getGlobalSymbol(name, 67901928, undefined); + var symbol = getGlobalSymbol(name, 67901928 /* Type */, /*diagnostic*/ undefined); return symbol && getTypeOfGlobalSymbol(symbol, arity); } function getGlobalExtractSymbol() { - return deferredGlobalExtractSymbol || (deferredGlobalExtractSymbol = getGlobalSymbol("Extract", 524288, ts.Diagnostics.Cannot_find_global_type_0)); + return deferredGlobalExtractSymbol || (deferredGlobalExtractSymbol = getGlobalSymbol("Extract", 524288 /* TypeAlias */, ts.Diagnostics.Cannot_find_global_type_0)); // TODO: GH#18217 } + /** + * Instantiates a global type that is generic with some element type, and returns that instantiation. + */ function createTypeFromGenericGlobalType(genericGlobalType, typeArguments) { return genericGlobalType !== emptyGenericType ? createTypeReference(genericGlobalType, typeArguments) : emptyObjectType; } @@ -31631,16 +36595,16 @@ var ts; return createTypeFromGenericGlobalType(getGlobalTypedPropertyDescriptorType(), [propertyType]); } function createAsyncIterableType(iteratedType) { - return createTypeFromGenericGlobalType(getGlobalAsyncIterableType(true), [iteratedType]); + return createTypeFromGenericGlobalType(getGlobalAsyncIterableType(/*reportErrors*/ true), [iteratedType]); } function createAsyncIterableIteratorType(iteratedType) { - return createTypeFromGenericGlobalType(getGlobalAsyncIterableIteratorType(true), [iteratedType]); + return createTypeFromGenericGlobalType(getGlobalAsyncIterableIteratorType(/*reportErrors*/ true), [iteratedType]); } function createIterableType(iteratedType) { - return createTypeFromGenericGlobalType(getGlobalIterableType(true), [iteratedType]); + return createTypeFromGenericGlobalType(getGlobalIterableType(/*reportErrors*/ true), [iteratedType]); } function createIterableIteratorType(iteratedType) { - return createTypeFromGenericGlobalType(getGlobalIterableIteratorType(true), [iteratedType]); + return createTypeFromGenericGlobalType(getGlobalIterableIteratorType(/*reportErrors*/ true), [iteratedType]); } function createArrayType(elementType) { return createTypeFromGenericGlobalType(globalArrayType, [elementType]); @@ -31652,20 +36616,27 @@ var ts; } return links.resolvedType; } + // We represent tuple types as type references to synthesized generic interface types created by + // this function. The types are of the form: + // + // interface Tuple extends Array { 0: T0, 1: T1, 2: T2, ... } + // + // Note that the generic type created by this function has no symbol associated with it. The same + // is true for each of the synthesized type parameters. function createTupleTypeOfArity(arity) { var typeParameters = []; var properties = []; for (var i = 0; i < arity; i++) { - var typeParameter = createType(65536); + var typeParameter = createType(65536 /* TypeParameter */); typeParameters.push(typeParameter); - var property = createSymbol(4, "" + i); + var property = createSymbol(4 /* Property */, "" + i); property.type = typeParameter; properties.push(property); } - var lengthSymbol = createSymbol(4, "length"); + var lengthSymbol = createSymbol(4 /* Property */, "length"); lengthSymbol.type = getLiteralType(arity); properties.push(lengthSymbol); - var type = createObjectType(8 | 4); + var type = createObjectType(8 /* Tuple */ | 4 /* Reference */); type.typeParameters = typeParameters; type.outerTypeParameters = undefined; type.localTypeParameters = typeParameters; @@ -31673,7 +36644,7 @@ var ts; type.instantiations.set(getTypeListId(type.typeParameters), type); type.target = type; type.typeArguments = type.typeParameters; - type.thisType = createType(65536); + type.thisType = createType(65536 /* TypeParameter */); type.thisType.isThisType = true; type.thisType.constraint = type; type.declaredProperties = properties; @@ -31702,20 +36673,28 @@ var ts; function containsType(types, type) { return ts.binarySearch(types, type, getTypeId, ts.compareValues) >= 0; } + // Return true if the given intersection type contains + // more than one unit type or, + // an object type and a nullable type (null or undefined), or + // a string-like type and a type known to be non-string-like, or + // a number-like type and a type known to be non-number-like, or + // a symbol-like type and a type known to be non-symbol-like, or + // a void-like type and a type known to be non-void-like, or + // a non-primitive type and a type known to be primitive. function isEmptyIntersectionType(type) { var combined = 0; for (var _i = 0, _a = type.types; _i < _a.length; _i++) { var t = _a[_i]; - if (t.flags & 27072 && combined & 27072) { + if (t.flags & 27072 /* Unit */ && combined & 27072 /* Unit */) { return true; } combined |= t.flags; - if (combined & 24576 && combined & (131072 | 16777216) || - combined & 16777216 && combined & (16809468 & ~16777216) || - combined & 68 && combined & (16809468 & ~68) || - combined & 168 && combined & (16809468 & ~168) || - combined & 3072 && combined & (16809468 & ~3072) || - combined & 12288 && combined & (16809468 & ~12288)) { + if (combined & 24576 /* Nullable */ && combined & (131072 /* Object */ | 16777216 /* NonPrimitive */) || + combined & 16777216 /* NonPrimitive */ && combined & (16809468 /* DisjointDomains */ & ~16777216 /* NonPrimitive */) || + combined & 68 /* StringLike */ && combined & (16809468 /* DisjointDomains */ & ~68 /* StringLike */) || + combined & 168 /* NumberLike */ && combined & (16809468 /* DisjointDomains */ & ~168 /* NumberLike */) || + combined & 3072 /* ESSymbolLike */ && combined & (16809468 /* DisjointDomains */ & ~3072 /* ESSymbolLike */) || + combined & 12288 /* VoidLike */ && combined & (16809468 /* DisjointDomains */ & ~12288 /* VoidLike */)) { return true; } } @@ -31723,25 +36702,29 @@ var ts; } function addTypeToUnion(typeSet, includes, type) { var flags = type.flags; - if (flags & 262144) { + if (flags & 262144 /* Union */) { return addTypesToUnion(typeSet, includes, type.types); } - if (!(flags & 32768 || flags & 524288 && isEmptyIntersectionType(type))) { - includes |= flags & ~939524096; - if (flags & 3) { + // We ignore 'never' types in unions. Likewise, we ignore intersections of unit types as they are + // another form of 'never' (in that they have an empty value domain). We could in theory turn + // intersections of unit types into 'never' upon construction, but deferring the reduction makes it + // easier to reason about their origin. + if (!(flags & 32768 /* Never */ || flags & 524288 /* Intersection */ && isEmptyIntersectionType(type))) { + includes |= flags & ~939524096 /* ConstructionFlags */; + if (flags & 3 /* AnyOrUnknown */) { if (type === wildcardType) - includes |= 268435456; + includes |= 268435456 /* Wildcard */; } - else if (!strictNullChecks && flags & 24576) { - if (!(flags & 134217728)) - includes |= 134217728; + else if (!strictNullChecks && flags & 24576 /* Nullable */) { + if (!(flags & 134217728 /* ContainsWideningType */)) + includes |= 134217728 /* NonWideningType */; } else { var len = typeSet.length; var index = len && type.id > typeSet[len - 1].id ? ~len : ts.binarySearch(typeSet, type, getTypeId, ts.compareValues); if (index < 0) { - if (!(flags & 131072 && type.objectFlags & 16 && - type.symbol && type.symbol.flags & (16 | 8192) && containsIdenticalType(typeSet, type))) { + if (!(flags & 131072 /* Object */ && type.objectFlags & 16 /* Anonymous */ && + type.symbol && type.symbol.flags & (16 /* Function */ | 8192 /* Method */) && containsIdenticalType(typeSet, type))) { typeSet.splice(~index, 0, type); } } @@ -31749,6 +36732,8 @@ var ts; } return includes; } + // Add the given types to the given type set. Order is preserved, duplicates are removed, + // and nested types of the given kind are flattened into the set. function addTypesToUnion(typeSet, includes, types) { for (var _i = 0, types_6 = types; _i < types_6.length; _i++) { var type = types_6[_i]; @@ -31768,8 +36753,8 @@ var ts; function isSubtypeOfAny(source, targets) { for (var _i = 0, targets_1 = targets; _i < targets_1.length; _i++) { var target = targets_1[_i]; - if (source !== target && isTypeSubtypeOf(source, target) && (!(ts.getObjectFlags(getTargetType(source)) & 1) || - !(ts.getObjectFlags(getTargetType(target)) & 1) || + if (source !== target && isTypeSubtypeOf(source, target) && (!(ts.getObjectFlags(getTargetType(source)) & 1 /* Class */) || + !(ts.getObjectFlags(getTargetType(target)) & 1 /* Class */) || isTypeDerivedFrom(source, target))) { return true; } @@ -31778,11 +36763,11 @@ var ts; } function isSetOfLiteralsFromSameEnum(types) { var first = types[0]; - if (first.flags & 512) { + if (first.flags & 512 /* EnumLiteral */) { var firstEnum = getParentOfSymbol(first.symbol); for (var i = 1; i < types.length; i++) { var other = types[i]; - if (!(other.flags & 512) || (firstEnum !== getParentOfSymbol(other.symbol))) { + if (!(other.flags & 512 /* EnumLiteral */) || (firstEnum !== getParentOfSymbol(other.symbol))) { return false; } } @@ -31807,17 +36792,24 @@ var ts; while (i > 0) { i--; var t = types[i]; - var remove = t.flags & 64 && includes & 4 || - t.flags & 128 && includes & 8 || - t.flags & 2048 && includes & 1024 || - t.flags & 192 && t.flags & 33554432 && containsType(types, t.regularType); + var remove = t.flags & 64 /* StringLiteral */ && includes & 4 /* String */ || + t.flags & 128 /* NumberLiteral */ && includes & 8 /* Number */ || + t.flags & 2048 /* UniqueESSymbol */ && includes & 1024 /* ESSymbol */ || + t.flags & 192 /* StringOrNumberLiteral */ && t.flags & 33554432 /* FreshLiteral */ && containsType(types, t.regularType); if (remove) { ts.orderedRemoveItemAt(types, i); } } } + // We sort and deduplicate the constituent types based on object identity. If the subtypeReduction + // flag is specified we also reduce the constituent type set to only include types that aren't subtypes + // of other types. Subtype reduction is expensive for large union types and is possible only when union + // types are known not to circularly reference themselves (as is the case with union types created by + // expression constructs such as array literals and the || and ?: operators). Named types can + // circularly reference themselves and therefore cannot be subtype reduced during their declaration. + // For example, "type Item = string | (() => Item" is a named type that circularly references itself. function getUnionType(types, unionReduction, aliasSymbol, aliasTypeArguments) { - if (unionReduction === void 0) { unionReduction = 1; } + if (unionReduction === void 0) { unionReduction = 1 /* Literal */; } if (types.length === 0) { return neverType; } @@ -31826,25 +36818,25 @@ var ts; } var typeSet = []; var includes = addTypesToUnion(typeSet, 0, types); - if (includes & 3) { - return includes & 1 ? includes & 268435456 ? wildcardType : anyType : unknownType; + if (includes & 3 /* AnyOrUnknown */) { + return includes & 1 /* Any */ ? includes & 268435456 /* Wildcard */ ? wildcardType : anyType : unknownType; } switch (unionReduction) { - case 1: - if (includes & 2240) { + case 1 /* Literal */: + if (includes & 2240 /* StringOrNumberLiteralOrUnique */) { removeRedundantLiteralTypes(typeSet, includes); } break; - case 2: + case 2 /* Subtype */: removeSubtypes(typeSet); break; } if (typeSet.length === 0) { - return includes & 16384 ? includes & 134217728 ? nullType : nullWideningType : - includes & 8192 ? includes & 134217728 ? undefinedType : undefinedWideningType : + return includes & 16384 /* Null */ ? includes & 134217728 /* NonWideningType */ ? nullType : nullWideningType : + includes & 8192 /* Undefined */ ? includes & 134217728 /* NonWideningType */ ? undefinedType : undefinedWideningType : neverType; } - return getUnionTypeFromSortedList(typeSet, includes & 16749629 ? 0 : 67108864, aliasSymbol, aliasTypeArguments); + return getUnionTypeFromSortedList(typeSet, includes & 16749629 /* NotUnit */ ? 0 : 67108864 /* UnionOfUnitTypes */, aliasSymbol, aliasTypeArguments); } function getUnionTypePredicate(signatures) { var first; @@ -31857,6 +36849,7 @@ var ts; } if (first) { if (!typePredicateKindsMatch(first, pred)) { + // No common type predicate. return undefined; } } @@ -31866,6 +36859,7 @@ var ts; types.push(pred.type); } if (!first) { + // No union signatures had a type predicate. return undefined; } var unionType = getUnionType(types); @@ -31878,6 +36872,7 @@ var ts; ? ts.isIdentifierTypePredicate(b) && a.parameterIndex === b.parameterIndex : !ts.isIdentifierTypePredicate(b); } + // This function assumes the constituent type list is sorted and deduplicated. function getUnionTypeFromSortedList(types, unionOfUnitTypes, aliasSymbol, aliasTypeArguments) { if (types.length === 0) { return neverType; @@ -31888,10 +36883,16 @@ var ts; var id = getTypeListId(types); var type = unionTypes.get(id); if (!type) { - var propagatedFlags = getPropagatingFlagsOfTypes(types, 24576); - type = createType(262144 | propagatedFlags | unionOfUnitTypes); + var propagatedFlags = getPropagatingFlagsOfTypes(types, /*excludeKinds*/ 24576 /* Nullable */); + type = createType(262144 /* Union */ | propagatedFlags | unionOfUnitTypes); unionTypes.set(id, type); type.types = types; + /* + Note: This is the alias symbol (or lack thereof) that we see when we first encounter this union type. + For aliases of identical unions, eg `type T = A | B; type U = A | B`, the symbol of the first alias encountered is the aliasSymbol. + (In the language service, the order may depend on the order in which a user takes actions, such as hovering over symbols.) + It's important that we create equivalent union types only once, so that's an unfortunate side effect. + */ type.aliasSymbol = aliasSymbol; type.aliasTypeArguments = aliasTypeArguments; } @@ -31901,33 +36902,35 @@ var ts; var links = getNodeLinks(node); if (!links.resolvedType) { var aliasSymbol = getAliasSymbolForTypeNode(node); - links.resolvedType = getUnionType(ts.map(node.types, getTypeFromTypeNode), 1, aliasSymbol, getTypeArgumentsForAliasSymbol(aliasSymbol)); + links.resolvedType = getUnionType(ts.map(node.types, getTypeFromTypeNode), 1 /* Literal */, aliasSymbol, getTypeArgumentsForAliasSymbol(aliasSymbol)); } return links.resolvedType; } function addTypeToIntersection(typeSet, includes, type) { var flags = type.flags; - if (flags & 524288) { + if (flags & 524288 /* Intersection */) { return addTypesToIntersection(typeSet, includes, type.types); } - if (ts.getObjectFlags(type) & 16 && isEmptyObjectType(type)) { - includes |= 536870912; + if (ts.getObjectFlags(type) & 16 /* Anonymous */ && isEmptyObjectType(type)) { + includes |= 536870912 /* EmptyObject */; } else { - includes |= flags & ~939524096; - if (flags & 3) { + includes |= flags & ~939524096 /* ConstructionFlags */; + if (flags & 3 /* AnyOrUnknown */) { if (type === wildcardType) - includes |= 268435456; + includes |= 268435456 /* Wildcard */; } - else if ((strictNullChecks || !(flags & 24576)) && !ts.contains(typeSet, type) && - !(flags & 131072 && type.objectFlags & 16 && - type.symbol && type.symbol.flags & (16 | 8192) && + else if ((strictNullChecks || !(flags & 24576 /* Nullable */)) && !ts.contains(typeSet, type) && + !(flags & 131072 /* Object */ && type.objectFlags & 16 /* Anonymous */ && + type.symbol && type.symbol.flags & (16 /* Function */ | 8192 /* Method */) && containsIdenticalType(typeSet, type))) { typeSet.push(type); } } return includes; } + // Add the given types to the given type set. Order is preserved, freshness is removed from literal + // types, duplicates are removed, and nested types of the given kind are flattened into the set. function addTypesToIntersection(typeSet, includes, types) { for (var _i = 0, types_8 = types; _i < types_8.length; _i++) { var type = types_8[_i]; @@ -31940,22 +36943,25 @@ var ts; while (i > 0) { i--; var t = types[i]; - var remove = t.flags & 4 && includes & 64 || - t.flags & 8 && includes & 128 || - t.flags & 1024 && includes & 2048; + var remove = t.flags & 4 /* String */ && includes & 64 /* StringLiteral */ || + t.flags & 8 /* Number */ && includes & 128 /* NumberLiteral */ || + t.flags & 1024 /* ESSymbol */ && includes & 2048 /* UniqueESSymbol */; if (remove) { ts.orderedRemoveItemAt(types, i); } } } + // When intersecting unions of unit types we can simply intersect based on type identity. + // Here we remove all unions of unit types from the given list and replace them with a + // a single union containing an intersection of the unit types. function intersectUnionsOfUnitTypes(types) { - var unionIndex = ts.findIndex(types, function (t) { return (t.flags & 67108864) !== 0; }); + var unionIndex = ts.findIndex(types, function (t) { return (t.flags & 67108864 /* UnionOfUnitTypes */) !== 0; }); var unionType = types[unionIndex]; var intersection = unionType.types; var i = types.length - 1; var _loop_6 = function () { var t = types[i]; - if (t.flags & 67108864) { + if (t.flags & 67108864 /* UnionOfUnitTypes */) { intersection = ts.filter(intersection, function (u) { return containsType(t.types, u); }); ts.orderedRemoveItemAt(types, i); } @@ -31967,27 +36973,37 @@ var ts; if (intersection === unionType.types) { return false; } - types[unionIndex] = getUnionTypeFromSortedList(intersection, unionType.flags & 67108864); + types[unionIndex] = getUnionTypeFromSortedList(intersection, unionType.flags & 67108864 /* UnionOfUnitTypes */); return true; } + // We normalize combinations of intersection and union types based on the distributive property of the '&' + // operator. Specifically, because X & (A | B) is equivalent to X & A | X & B, we can transform intersection + // types with union type constituents into equivalent union types with intersection type constituents and + // effectively ensure that union types are always at the top level in type representations. + // + // We do not perform structural deduplication on intersection types. Intersection types are created only by the & + // type operator and we can't reduce those because we want to support recursive intersection types. For example, + // a type alias of the form "type List = T & { next: List }" cannot be reduced during its declaration. + // Also, unlike union types, the order of the constituent types is preserved in order that overload resolution + // for intersections of types with signatures can be deterministic. function getIntersectionType(types, aliasSymbol, aliasTypeArguments) { var typeSet = []; var includes = addTypesToIntersection(typeSet, 0, types); - if (includes & 32768) { + if (includes & 32768 /* Never */) { return neverType; } - if (includes & 1) { - return includes & 268435456 ? wildcardType : anyType; + if (includes & 1 /* Any */) { + return includes & 268435456 /* Wildcard */ ? wildcardType : anyType; } - if (!strictNullChecks && includes & 24576) { - return includes & 8192 ? undefinedType : nullType; + if (!strictNullChecks && includes & 24576 /* Nullable */) { + return includes & 8192 /* Undefined */ ? undefinedType : nullType; } - if (includes & 4 && includes & 64 || - includes & 8 && includes & 128 || - includes & 1024 && includes & 2048) { + if (includes & 4 /* String */ && includes & 64 /* StringLiteral */ || + includes & 8 /* Number */ && includes & 128 /* NumberLiteral */ || + includes & 1024 /* ESSymbol */ && includes & 2048 /* UniqueESSymbol */) { removeRedundantPrimitiveTypes(typeSet, includes); } - if (includes & 536870912 && !(includes & 131072)) { + if (includes & 536870912 /* EmptyObject */ && !(includes & 131072 /* Object */)) { typeSet.push(emptyObjectType); } if (typeSet.length === 0) { @@ -31996,22 +37012,27 @@ var ts; if (typeSet.length === 1) { return typeSet[0]; } - if (includes & 262144) { - if (includes & 67108864 && intersectUnionsOfUnitTypes(typeSet)) { + if (includes & 262144 /* Union */) { + if (includes & 67108864 /* UnionOfUnitTypes */ && intersectUnionsOfUnitTypes(typeSet)) { + // When the intersection creates a reduced set (which might mean that *all* union types have + // disappeared), we restart the operation to get a new set of combined flags. Once we have + // reduced we'll never reduce again, so this occurs at most once. return getIntersectionType(typeSet, aliasSymbol, aliasTypeArguments); } - var unionIndex_1 = ts.findIndex(typeSet, function (t) { return (t.flags & 262144) !== 0; }); + // We are attempting to construct a type of the form X & (A | B) & Y. Transform this into a type of + // the form X & A & Y | X & B & Y and recursively reduce until no union type constituents remain. + var unionIndex_1 = ts.findIndex(typeSet, function (t) { return (t.flags & 262144 /* Union */) !== 0; }); var unionType = typeSet[unionIndex_1]; - return getUnionType(ts.map(unionType.types, function (t) { return getIntersectionType(ts.replaceElement(typeSet, unionIndex_1, t)); }), 1, aliasSymbol, aliasTypeArguments); + return getUnionType(ts.map(unionType.types, function (t) { return getIntersectionType(ts.replaceElement(typeSet, unionIndex_1, t)); }), 1 /* Literal */, aliasSymbol, aliasTypeArguments); } var id = getTypeListId(typeSet); var type = intersectionTypes.get(id); if (!type) { - var propagatedFlags = getPropagatingFlagsOfTypes(typeSet, 24576); - type = createType(524288 | propagatedFlags); + var propagatedFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ 24576 /* Nullable */); + type = createType(524288 /* Intersection */ | propagatedFlags); intersectionTypes.set(id, type); type.types = typeSet; - type.aliasSymbol = aliasSymbol; + type.aliasSymbol = aliasSymbol; // See comment in `getUnionTypeFromSortedList`. type.aliasTypeArguments = aliasTypeArguments; } return type; @@ -32025,23 +37046,23 @@ var ts; return links.resolvedType; } function createIndexType(type, stringsOnly) { - var result = createType(1048576); + var result = createType(1048576 /* Index */); result.type = type; result.stringsOnly = stringsOnly; return result; } function getIndexTypeForGenericType(type, stringsOnly) { return stringsOnly ? - type.resolvedStringIndexType || (type.resolvedStringIndexType = createIndexType(type, true)) : - type.resolvedIndexType || (type.resolvedIndexType = createIndexType(type, false)); + type.resolvedStringIndexType || (type.resolvedStringIndexType = createIndexType(type, /*stringsOnly*/ true)) : + type.resolvedIndexType || (type.resolvedIndexType = createIndexType(type, /*stringsOnly*/ false)); } function getLiteralTypeFromPropertyName(prop, include) { - if (!(ts.getDeclarationModifierFlagsFromSymbol(prop) & 24)) { + if (!(ts.getDeclarationModifierFlagsFromSymbol(prop) & 24 /* NonPublicAccessibilityModifier */)) { var type = getLateBoundSymbol(prop).nameType; if (!type && !ts.isKnownSymbol(prop)) { var name = ts.getNameOfDeclaration(prop.valueDeclaration); type = name && ts.isNumericLiteral(name) ? getLiteralType(+name.text) : - name && name.kind === 147 && ts.isNumericLiteral(name.expression) ? getLiteralType(+name.expression.text) : + name && name.kind === 147 /* ComputedPropertyName */ && ts.isNumericLiteral(name.expression) ? getLiteralType(+name.expression.text) : getLiteralType(ts.symbolName(prop)); } if (type && type.flags & include) { @@ -32054,21 +37075,21 @@ var ts; return getUnionType(ts.map(getPropertiesOfType(type), function (t) { return getLiteralTypeFromPropertyName(t, include); })); } function getNonEnumNumberIndexInfo(type) { - var numberIndexInfo = getIndexInfoOfType(type, 1); + var numberIndexInfo = getIndexInfoOfType(type, 1 /* Number */); return numberIndexInfo !== enumNumberIndexInfo ? numberIndexInfo : undefined; } function getIndexType(type, stringsOnly) { if (stringsOnly === void 0) { stringsOnly = keyofStringsOnly; } - return type.flags & 262144 ? getIntersectionType(ts.map(type.types, function (t) { return getIndexType(t, stringsOnly); })) : - type.flags & 524288 ? getUnionType(ts.map(type.types, function (t) { return getIndexType(t, stringsOnly); })) : - maybeTypeOfKind(type, 14745600) ? getIndexTypeForGenericType(type, stringsOnly) : - ts.getObjectFlags(type) & 32 ? getConstraintTypeFromMappedType(type) : + return type.flags & 262144 /* Union */ ? getIntersectionType(ts.map(type.types, function (t) { return getIndexType(t, stringsOnly); })) : + type.flags & 524288 /* Intersection */ ? getUnionType(ts.map(type.types, function (t) { return getIndexType(t, stringsOnly); })) : + maybeTypeOfKind(type, 14745600 /* InstantiableNonPrimitive */) ? getIndexTypeForGenericType(type, stringsOnly) : + ts.getObjectFlags(type) & 32 /* Mapped */ ? getConstraintTypeFromMappedType(type) : type === wildcardType ? wildcardType : - type.flags & 1 ? keyofConstraintType : - stringsOnly ? getIndexInfoOfType(type, 0) ? stringType : getLiteralTypeFromPropertyNames(type, 64) : - getIndexInfoOfType(type, 0) ? getUnionType([stringType, numberType, getLiteralTypeFromPropertyNames(type, 2048)]) : - getNonEnumNumberIndexInfo(type) ? getUnionType([numberType, getLiteralTypeFromPropertyNames(type, 64 | 2048)]) : - getLiteralTypeFromPropertyNames(type, 2240); + type.flags & 1 /* Any */ ? keyofConstraintType : + stringsOnly ? getIndexInfoOfType(type, 0 /* String */) ? stringType : getLiteralTypeFromPropertyNames(type, 64 /* StringLiteral */) : + getIndexInfoOfType(type, 0 /* String */) ? getUnionType([stringType, numberType, getLiteralTypeFromPropertyNames(type, 2048 /* UniqueESSymbol */)]) : + getNonEnumNumberIndexInfo(type) ? getUnionType([numberType, getLiteralTypeFromPropertyNames(type, 64 /* StringLiteral */ | 2048 /* UniqueESSymbol */)]) : + getLiteralTypeFromPropertyNames(type, 2240 /* StringOrNumberLiteralOrUnique */); } function getExtractStringType(type) { if (keyofStringsOnly) { @@ -32079,41 +37100,41 @@ var ts; } function getIndexTypeOrString(type) { var indexType = getExtractStringType(getIndexType(type)); - return indexType.flags & 32768 ? stringType : indexType; + return indexType.flags & 32768 /* Never */ ? stringType : indexType; } function getTypeFromTypeOperatorNode(node) { var links = getNodeLinks(node); if (!links.resolvedType) { switch (node.operator) { - case 128: + case 128 /* KeyOfKeyword */: links.resolvedType = getIndexType(getTypeFromTypeNode(node.type)); break; - case 141: - links.resolvedType = node.type.kind === 138 + case 141 /* UniqueKeyword */: + links.resolvedType = node.type.kind === 138 /* SymbolKeyword */ ? getESSymbolLikeTypeForNode(ts.walkUpParenthesizedTypes(node.parent)) : errorType; break; } } - return links.resolvedType; + return links.resolvedType; // TODO: GH#18217 } function createIndexedAccessType(objectType, indexType) { - var type = createType(2097152); + var type = createType(2097152 /* IndexedAccess */); type.objectType = objectType; type.indexType = indexType; return type; } function getPropertyTypeForIndexType(objectType, indexType, accessNode, cacheSymbol) { - var accessExpression = accessNode && accessNode.kind === 186 ? accessNode : undefined; + var accessExpression = accessNode && accessNode.kind === 186 /* ElementAccessExpression */ ? accessNode : undefined; var propName = isTypeUsableAsLateBoundName(indexType) ? getLateBoundNameFromType(indexType) : - accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression, indexType, false) ? + accessExpression && checkThatExpressionIsProperSymbolReference(accessExpression.argumentExpression, indexType, /*reportError*/ false) ? ts.getPropertyNameForKnownSymbolName(ts.idText(accessExpression.argumentExpression.name)) : undefined; if (propName !== undefined) { var prop = getPropertyOfType(objectType, propName); if (prop) { if (accessExpression) { - markPropertyAsReferenced(prop, accessExpression, accessExpression.expression.kind === 99); + markPropertyAsReferenced(prop, accessExpression, /*isThisAccess*/ accessExpression.expression.kind === 99 /* ThisKeyword */); if (ts.isAssignmentTarget(accessExpression) && (isReferenceToReadonlyEntity(accessExpression, prop) || isReferenceThroughNamespaceImport(accessExpression))) { error(accessExpression.argumentExpression, ts.Diagnostics.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, symbolToString(prop)); return errorType; @@ -32125,16 +37146,16 @@ var ts; return getTypeOfSymbol(prop); } } - if (!(indexType.flags & 24576) && isTypeAssignableToKind(indexType, 68 | 168 | 3072)) { + if (!(indexType.flags & 24576 /* Nullable */) && isTypeAssignableToKind(indexType, 68 /* StringLike */ | 168 /* NumberLike */ | 3072 /* ESSymbolLike */)) { if (isTypeAny(objectType)) { return objectType; } - var indexInfo = isTypeAssignableToKind(indexType, 168) && getIndexInfoOfType(objectType, 1) || - getIndexInfoOfType(objectType, 0) || + var indexInfo = isTypeAssignableToKind(indexType, 168 /* NumberLike */) && getIndexInfoOfType(objectType, 1 /* Number */) || + getIndexInfoOfType(objectType, 0 /* String */) || undefined; if (indexInfo) { - if (accessNode && !isTypeAssignableToKind(indexType, 4 | 8)) { - var indexNode = accessNode.kind === 186 ? accessNode.argumentExpression : accessNode.indexType; + if (accessNode && !isTypeAssignableToKind(indexType, 4 /* String */ | 8 /* Number */)) { + var indexNode = accessNode.kind === 186 /* ElementAccessExpression */ ? accessNode.argumentExpression : accessNode.indexType; error(indexNode, ts.Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeToString(indexType)); } else if (accessExpression && indexInfo.isReadonly && (ts.isAssignmentTarget(accessExpression) || ts.isDeleteTarget(accessExpression))) { @@ -32142,12 +37163,12 @@ var ts; } return indexInfo.type; } - if (indexType.flags & 32768) { + if (indexType.flags & 32768 /* Never */) { return neverType; } if (accessExpression && !isConstEnumObjectType(objectType)) { if (noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors) { - if (getIndexTypeOfType(objectType, 1)) { + if (getIndexTypeOfType(objectType, 1 /* Number */)) { error(accessExpression.argumentExpression, ts.Diagnostics.Element_implicitly_has_an_any_type_because_index_expression_is_not_of_type_number); } else { @@ -32158,11 +37179,11 @@ var ts; } } if (accessNode) { - var indexNode = accessNode.kind === 186 ? accessNode.argumentExpression : accessNode.indexType; - if (indexType.flags & (64 | 128)) { + var indexNode = accessNode.kind === 186 /* ElementAccessExpression */ ? accessNode.argumentExpression : accessNode.indexType; + if (indexType.flags & (64 /* StringLiteral */ | 128 /* NumberLiteral */)) { error(indexNode, ts.Diagnostics.Property_0_does_not_exist_on_type_1, "" + indexType.value, typeToString(objectType)); } - else if (indexType.flags & (4 | 8)) { + else if (indexType.flags & (4 /* String */ | 8 /* Number */)) { error(indexNode, ts.Diagnostics.Type_0_has_no_matching_index_signature_for_type_1, typeToString(objectType), typeToString(indexType)); } else { @@ -32172,13 +37193,15 @@ var ts; return errorType; } function isGenericObjectType(type) { - return maybeTypeOfKind(type, 14745600 | 134217728); + return maybeTypeOfKind(type, 14745600 /* InstantiableNonPrimitive */ | 134217728 /* GenericMappedType */); } function isGenericIndexType(type) { - return maybeTypeOfKind(type, 14745600 | 1048576); + return maybeTypeOfKind(type, 14745600 /* InstantiableNonPrimitive */ | 1048576 /* Index */); } + // Return true if the given type is a non-generic object type with a string index signature and no + // other members. function isStringIndexOnlyType(type) { - if (type.flags & 131072 && !isGenericMappedType(type)) { + if (type.flags & 131072 /* Object */ && !isGenericMappedType(type)) { var t = resolveStructuredTypeMembers(type); return t.properties.length === 0 && t.callSignatures.length === 0 && t.constructSignatures.length === 0 && @@ -32187,25 +37210,33 @@ var ts; return false; } function isMappedTypeToNever(type) { - return !!(ts.getObjectFlags(type) & 32) && getTemplateTypeFromMappedType(type) === neverType; + return !!(ts.getObjectFlags(type) & 32 /* Mapped */) && getTemplateTypeFromMappedType(type) === neverType; } function getSimplifiedType(type) { - return type.flags & 2097152 ? getSimplifiedIndexedAccessType(type) : type; + return type.flags & 2097152 /* IndexedAccess */ ? getSimplifiedIndexedAccessType(type) : type; } + // Transform an indexed access to a simpler form, if possible. Return the simpler form, or return + // the type itself if no transformation is possible. function getSimplifiedIndexedAccessType(type) { if (type.simplified) { return type.simplified === circularConstraintType ? type : type.simplified; } type.simplified = circularConstraintType; + // We recursively simplify the object type as it may in turn be an indexed access type. For example, with + // '{ [P in T]: { [Q in U]: number } }[T][U]' we want to first simplify the inner indexed access type. var objectType = getSimplifiedType(type.objectType); - if (objectType.flags & 524288 && isGenericObjectType(objectType)) { + if (objectType.flags & 524288 /* Intersection */ && isGenericObjectType(objectType)) { + // Given an indexed access type T[K], if T is an intersection containing one or more generic types and one or + // more object types with only a string index signature, e.g. '(U & V & { [x: string]: D })[K]', return a + // transformed type of the form '(U & V)[K] | D'. This allows us to properly reason about higher order indexed + // access types with default property values as expressed by D. if (ts.some(objectType.types, isStringIndexOnlyType)) { var regularTypes = []; var stringIndexTypes = []; for (var _i = 0, _a = objectType.types; _i < _a.length; _i++) { var t = _a[_i]; if (isStringIndexOnlyType(t)) { - stringIndexTypes.push(getIndexTypeOfType(t, 0)); + stringIndexTypes.push(getIndexTypeOfType(t, 0 /* String */)); } else { regularTypes.push(t); @@ -32216,15 +37247,23 @@ var ts; getIntersectionType(stringIndexTypes) ]); } + // Given an indexed access type T[K], if T is an intersection containing one or more generic types and one or + // more mapped types with a template type `never`, '(U & V & { [P in T]: never })[K]', return a + // transformed type that removes the never-mapped type: '(U & V)[K]'. This mirrors what would happen + // eventually anyway, but it easier to reason about. if (ts.some(objectType.types, isMappedTypeToNever)) { var nonNeverTypes = ts.filter(objectType.types, function (t) { return !isMappedTypeToNever(t); }); return type.simplified = getSimplifiedType(getIndexedAccessType(getIntersectionType(nonNeverTypes), type.indexType)); } } + // If the object type is a mapped type { [P in K]: E }, where K is generic, instantiate E using a mapper + // that substitutes the index type for P. For example, for an index access { [P in K]: Box }[X], we + // construct the type Box. We do not further simplify the result because mapped types can be recursive + // and we might never terminate. if (isGenericMappedType(objectType)) { return type.simplified = substituteIndexedMappedType(objectType, type); } - if (objectType.flags & 65536) { + if (objectType.flags & 65536 /* TypeParameter */) { var constraint = getConstraintFromTypeParameter(objectType); if (constraint && isGenericMappedType(constraint)) { return type.simplified = substituteIndexedMappedType(constraint, type); @@ -32241,10 +37280,16 @@ var ts; if (objectType === wildcardType || indexType === wildcardType) { return wildcardType; } - if (isGenericIndexType(indexType) || !(accessNode && accessNode.kind === 186) && isGenericObjectType(objectType)) { - if (objectType.flags & 3) { + // If the index type is generic, or if the object type is generic and doesn't originate in an expression, + // we are performing a higher-order index access where we cannot meaningfully access the properties of the + // object type. Note that for a generic T and a non-generic K, we eagerly resolve T[K] if it originates in + // an expression. This is to preserve backwards compatibility. For example, an element access 'this["foo"]' + // has always been resolved eagerly using the constraint type of 'this' at the given location. + if (isGenericIndexType(indexType) || !(accessNode && accessNode.kind === 186 /* ElementAccessExpression */) && isGenericObjectType(objectType)) { + if (objectType.flags & 3 /* AnyOrUnknown */) { return objectType; } + // Defer the operation by creating an indexed access type. var id = objectType.id + "," + indexType.id; var type = indexedAccessTypes.get(id); if (!type) { @@ -32252,12 +37297,15 @@ var ts; } return type; } + // In the following we resolve T[K] to the type of the property in T selected by K. + // We treat boolean as different from other unions to improve errors; + // skipping straight to getPropertyTypeForIndexType gives errors with 'boolean' instead of 'true'. var apparentObjectType = getApparentType(objectType); - if (indexType.flags & 262144 && !(indexType.flags & 16)) { + if (indexType.flags & 262144 /* Union */ && !(indexType.flags & 16 /* Boolean */)) { var propTypes = []; for (var _i = 0, _a = indexType.types; _i < _a.length; _i++) { var t = _a[_i]; - var propType = getPropertyTypeForIndexType(apparentObjectType, t, accessNode, false); + var propType = getPropertyTypeForIndexType(apparentObjectType, t, accessNode, /*cacheSymbol*/ false); if (propType === errorType) { return errorType; } @@ -32265,7 +37313,7 @@ var ts; } return getUnionType(propTypes); } - return getPropertyTypeForIndexType(apparentObjectType, indexType, accessNode, true); + return getPropertyTypeForIndexType(apparentObjectType, indexType, accessNode, /*cacheSymbol*/ true); } function getTypeFromIndexedAccessTypeNode(node) { var links = getNodeLinks(node); @@ -32273,7 +37321,7 @@ var ts; var objectType = getTypeFromTypeNode(node.objectType); var indexType = getTypeFromTypeNode(node.indexType); var resolved = getIndexedAccessType(objectType, indexType, node); - links.resolvedType = resolved.flags & 2097152 && + links.resolvedType = resolved.flags & 2097152 /* IndexedAccess */ && resolved.objectType === objectType && resolved.indexType === indexType ? getConstrainedTypeVariable(resolved, node) : resolved; @@ -32283,17 +37331,19 @@ var ts; function getTypeFromMappedTypeNode(node) { var links = getNodeLinks(node); if (!links.resolvedType) { - var type = createObjectType(32, node.symbol); + var type = createObjectType(32 /* Mapped */, node.symbol); type.declaration = node; type.aliasSymbol = getAliasSymbolForTypeNode(node); type.aliasTypeArguments = getTypeArgumentsForAliasSymbol(type.aliasSymbol); links.resolvedType = type; + // Eagerly resolve the constraint type which forces an error if the constraint type circularly + // references itself through one or more type aliases. getConstraintTypeFromMappedType(type); } return links.resolvedType; } function getActualTypeVariable(type) { - return type.flags & 8388608 ? type.typeVariable : type; + return type.flags & 8388608 /* Substitution */ ? type.typeVariable : type; } function getConditionalType(root, mapper) { var checkType = instantiateType(root.checkType, mapper); @@ -32301,39 +37351,56 @@ var ts; if (checkType === wildcardType || extendsType === wildcardType) { return wildcardType; } - var isDeferred = root.isDistributive && maybeTypeOfKind(checkType, 15794176); + // If this is a distributive conditional type and the check type is generic we need to defer + // resolution of the conditional type such that a later instantiation will properly distribute + // over union types. + var isDeferred = root.isDistributive && maybeTypeOfKind(checkType, 15794176 /* Instantiable */); var combinedMapper; if (root.inferTypeParameters) { - var context = createInferenceContext(root.inferTypeParameters, undefined, 0); + var context = createInferenceContext(root.inferTypeParameters, /*signature*/ undefined, 0 /* None */); if (!isDeferred) { - inferTypes(context.inferences, checkType, extendsType, 32 | 64); + // We don't want inferences from constraints as they may cause us to eagerly resolve the + // conditional type instead of deferring resolution. Also, we always want strict function + // types rules (i.e. proper contravariance) for inferences. + inferTypes(context.inferences, checkType, extendsType, 32 /* NoConstraints */ | 64 /* AlwaysStrict */); } combinedMapper = combineTypeMappers(mapper, context); } if (!isDeferred) { - if (extendsType.flags & 3) { + if (extendsType.flags & 3 /* AnyOrUnknown */) { return instantiateType(root.trueType, mapper); } - if (checkType.flags & 1) { + // Return union of trueType and falseType for 'any' since it matches anything + if (checkType.flags & 1 /* Any */) { return getUnionType([instantiateType(root.trueType, combinedMapper || mapper), instantiateType(root.falseType, mapper)]); } + // Instantiate the extends type including inferences for 'infer T' type parameters var inferredExtendsType = combinedMapper ? instantiateType(root.extendsType, combinedMapper) : extendsType; + // Return falseType for a definitely false extends check. We check an instantations of the two + // types with type parameters mapped to the wildcard type, the most permissive instantiations + // possible (the wildcard type is assignable to and from all types). If those are not related, + // then no instatiations will be and we can just return the false branch type. if (!isTypeAssignableTo(getWildcardInstantiation(checkType), getWildcardInstantiation(inferredExtendsType))) { return instantiateType(root.falseType, mapper); } - if (checkTypeRelatedTo(checkType, inferredExtendsType, definitelyAssignableRelation, undefined)) { + // Return trueType for a definitely true extends check. The definitely assignable relation excludes + // type variable constraints from consideration. Without the definitely assignable relation, the type + // type Foo = T extends { x: string } ? string : number + // would immediately resolve to 'string' instead of being deferred. + if (checkTypeRelatedTo(checkType, inferredExtendsType, definitelyAssignableRelation, /*errorNode*/ undefined)) { return instantiateType(root.trueType, combinedMapper || mapper); } } + // Return a deferred type for a check that is neither definitely true nor definitely false var erasedCheckType = getActualTypeVariable(checkType); - var result = createType(4194304); + var result = createType(4194304 /* Conditional */); result.root = root; result.checkType = erasedCheckType; result.extendsType = extendsType; result.mapper = mapper; result.combinedMapper = combinedMapper; result.aliasSymbol = root.aliasSymbol; - result.aliasTypeArguments = instantiateTypes(root.aliasTypeArguments, mapper); + result.aliasTypeArguments = instantiateTypes(root.aliasTypeArguments, mapper); // TODO: GH#18217 return result; } function getTrueTypeFromConditionalType(type) { @@ -32346,7 +37413,7 @@ var ts; var result; if (node.locals) { node.locals.forEach(function (symbol) { - if (symbol.flags & 262144) { + if (symbol.flags & 262144 /* TypeParameter */) { result = ts.append(result, getDeclaredTypeOfSymbol(symbol)); } }); @@ -32358,7 +37425,7 @@ var ts; return true; } while (node) { - if (node.kind === 171) { + if (node.kind === 171 /* ConditionalType */) { if (isTypeParameterPossiblyReferenced(tp, node.extendsType)) { return true; } @@ -32373,7 +37440,7 @@ var ts; var checkType = getTypeFromTypeNode(node.checkType); var aliasSymbol = getAliasSymbolForTypeNode(node); var aliasTypeArguments = getTypeArgumentsForAliasSymbol(aliasSymbol); - var allOuterTypeParameters = getOuterTypeParameters(node, true); + var allOuterTypeParameters = getOuterTypeParameters(node, /*includeThisTypes*/ true); var outerTypeParameters = aliasTypeArguments ? allOuterTypeParameters : ts.filter(allOuterTypeParameters, function (tp) { return isPossiblyReferencedInConditionalType(tp, node); }); var root = { node: node, @@ -32381,14 +37448,14 @@ var ts; extendsType: getTypeFromTypeNode(node.extendsType), trueType: getTypeFromTypeNode(node.trueType), falseType: getTypeFromTypeNode(node.falseType), - isDistributive: !!(checkType.flags & 65536), + isDistributive: !!(checkType.flags & 65536 /* TypeParameter */), inferTypeParameters: getInferTypeParameters(node), outerTypeParameters: outerTypeParameters, instantiations: undefined, aliasSymbol: aliasSymbol, aliasTypeArguments: aliasTypeArguments }; - links.resolvedType = getConditionalType(root, undefined); + links.resolvedType = getConditionalType(root, /*mapper*/ undefined); if (outerTypeParameters) { root.instantiations = ts.createMap(); root.instantiations.set(getTypeListId(outerTypeParameters), links.resolvedType); @@ -32414,7 +37481,7 @@ var ts; function getTypeFromImportTypeNode(node) { var links = getNodeLinks(node); if (!links.resolvedType) { - if (node.isTypeOf && node.typeArguments) { + if (node.isTypeOf && node.typeArguments) { // Only the non-typeof form can make use of type arguments error(node, ts.Diagnostics.Type_arguments_cannot_be_used_here); links.resolvedSymbol = unknownSymbol; return links.resolvedType = errorType; @@ -32425,20 +37492,21 @@ var ts; return links.resolvedType = errorType; } var argumentType = getTypeFromTypeNode(node.argument); - var targetMeaning = node.isTypeOf ? 67216319 : 67901928; + var targetMeaning = node.isTypeOf ? 67216319 /* Value */ : 67901928 /* Type */; + // TODO: Future work: support unions/generics/whatever via a deferred import-type var moduleName = argumentType.value; - var innerModuleSymbol = resolveExternalModule(node, moduleName, ts.Diagnostics.Cannot_find_module_0, node, false); + var innerModuleSymbol = resolveExternalModule(node, moduleName, ts.Diagnostics.Cannot_find_module_0, node, /*isForAugmentation*/ false); if (!innerModuleSymbol) { links.resolvedSymbol = unknownSymbol; return links.resolvedType = errorType; } - var moduleSymbol_1 = resolveExternalModuleSymbol(innerModuleSymbol, false); + var moduleSymbol_1 = resolveExternalModuleSymbol(innerModuleSymbol, /*dontResolveAlias*/ false); if (!ts.nodeIsMissing(node.qualifier)) { var nameStack = getIdentifierChain(node.qualifier); var currentNamespace = moduleSymbol_1; var current = void 0; while (current = nameStack.shift()) { - var meaning = nameStack.length ? 1920 : targetMeaning; + var meaning = nameStack.length ? 1920 /* Namespace */ : targetMeaning; var next = getSymbol(getExportsOfSymbol(getMergedSymbol(resolveSymbol(currentNamespace))), current.escapedText, meaning); if (!next) { error(current, ts.Diagnostics.Namespace_0_has_no_exported_member_1, getFullyQualifiedName(currentNamespace), ts.declarationNameToString(current)); @@ -32455,33 +37523,34 @@ var ts; resolveImportSymbolType(node, links, moduleSymbol_1, targetMeaning); } else { - error(node, targetMeaning === 67216319 ? ts.Diagnostics.Module_0_does_not_refer_to_a_value_but_is_used_as_a_value_here : ts.Diagnostics.Module_0_does_not_refer_to_a_type_but_is_used_as_a_type_here, moduleName); + error(node, targetMeaning === 67216319 /* Value */ ? ts.Diagnostics.Module_0_does_not_refer_to_a_value_but_is_used_as_a_value_here : ts.Diagnostics.Module_0_does_not_refer_to_a_type_but_is_used_as_a_type_here, moduleName); links.resolvedSymbol = unknownSymbol; links.resolvedType = errorType; } } } - return links.resolvedType; + return links.resolvedType; // TODO: GH#18217 } function resolveImportSymbolType(node, links, symbol, meaning) { var resolvedSymbol = resolveSymbol(symbol); links.resolvedSymbol = resolvedSymbol; - if (meaning === 67216319) { - return links.resolvedType = getTypeOfSymbol(symbol); + if (meaning === 67216319 /* Value */) { + return links.resolvedType = getTypeOfSymbol(symbol); // intentionally doesn't use resolved symbol so type is cached as expected on the alias } else { - return links.resolvedType = getTypeReferenceType(node, resolvedSymbol); + return links.resolvedType = getTypeReferenceType(node, resolvedSymbol); // getTypeReferenceType doesn't handle aliases - it must get the resolved symbol } } function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node) { var links = getNodeLinks(node); if (!links.resolvedType) { + // Deferred resolution of members is handled by resolveObjectTypeMembers var aliasSymbol = getAliasSymbolForTypeNode(node); if (getMembersOfSymbol(node.symbol).size === 0 && !aliasSymbol) { links.resolvedType = emptyTypeLiteralType; } else { - var type = createObjectType(16, node.symbol); + var type = createObjectType(16 /* Anonymous */, node.symbol); type.aliasSymbol = aliasSymbol; type.aliasTypeArguments = getTypeArgumentsForAliasSymbol(aliasSymbol); if (ts.isJSDocTypeLiteral(node) && node.isArrayType) { @@ -32498,26 +37567,31 @@ var ts; function getTypeArgumentsForAliasSymbol(symbol) { return symbol ? getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) : undefined; } + /** + * Since the source of spread types are object literals, which are not binary, + * this function should be called in a left folding style, with left = previous result of getSpreadType + * and right = the new element to be spread. + */ function getSpreadType(left, right, symbol, typeFlags, objectFlags) { - if (left.flags & 1 || right.flags & 1) { + if (left.flags & 1 /* Any */ || right.flags & 1 /* Any */) { return anyType; } - if (left.flags & 2 || right.flags & 2) { + if (left.flags & 2 /* Unknown */ || right.flags & 2 /* Unknown */) { return unknownType; } - if (left.flags & 32768) { + if (left.flags & 32768 /* Never */) { return right; } - if (right.flags & 32768) { + if (right.flags & 32768 /* Never */) { return left; } - if (left.flags & 262144) { + if (left.flags & 262144 /* Union */) { return mapType(left, function (t) { return getSpreadType(t, right, symbol, typeFlags, objectFlags); }); } - if (right.flags & 262144) { + if (right.flags & 262144 /* Union */) { return mapType(right, function (t) { return getSpreadType(left, t, symbol, typeFlags, objectFlags); }); } - if (right.flags & (272 | 168 | 68 | 544 | 16777216 | 1048576)) { + if (right.flags & (272 /* BooleanLike */ | 168 /* NumberLike */ | 68 /* StringLike */ | 544 /* EnumLike */ | 16777216 /* NonPrimitive */ | 1048576 /* Index */)) { return left; } var members = ts.createSymbolTable(); @@ -32525,17 +37599,19 @@ var ts; var stringIndexInfo; var numberIndexInfo; if (left === emptyObjectType) { - stringIndexInfo = getIndexInfoOfType(right, 0); - numberIndexInfo = getIndexInfoOfType(right, 1); + // for the first spread element, left === emptyObjectType, so take the right's string indexer + stringIndexInfo = getIndexInfoOfType(right, 0 /* String */); + numberIndexInfo = getIndexInfoOfType(right, 1 /* Number */); } else { - stringIndexInfo = unionSpreadIndexInfos(getIndexInfoOfType(left, 0), getIndexInfoOfType(right, 0)); - numberIndexInfo = unionSpreadIndexInfos(getIndexInfoOfType(left, 1), getIndexInfoOfType(right, 1)); + stringIndexInfo = unionSpreadIndexInfos(getIndexInfoOfType(left, 0 /* String */), getIndexInfoOfType(right, 0 /* String */)); + numberIndexInfo = unionSpreadIndexInfos(getIndexInfoOfType(left, 1 /* Number */), getIndexInfoOfType(right, 1 /* Number */)); } for (var _i = 0, _a = getPropertiesOfType(right); _i < _a.length; _i++) { var rightProp = _a[_i]; - var isSetterWithoutGetter = rightProp.flags & 65536 && !(rightProp.flags & 32768); - if (ts.getDeclarationModifierFlagsFromSymbol(rightProp) & (8 | 16)) { + // we approximate own properties as non-methods plus methods that are inside the object literal + var isSetterWithoutGetter = rightProp.flags & 65536 /* SetAccessor */ && !(rightProp.flags & 32768 /* GetAccessor */); + if (ts.getDeclarationModifierFlagsFromSymbol(rightProp) & (8 /* Private */ | 16 /* Protected */)) { skippedPrivateMembers.set(rightProp.escapedName, true); } else if (!isClassMethod(rightProp) && !isSetterWithoutGetter) { @@ -32544,7 +37620,7 @@ var ts; } for (var _b = 0, _c = getPropertiesOfType(left); _b < _c.length; _b++) { var leftProp = _c[_b]; - if (leftProp.flags & 65536 && !(leftProp.flags & 32768) + if (leftProp.flags & 65536 /* SetAccessor */ && !(leftProp.flags & 32768 /* GetAccessor */) || skippedPrivateMembers.has(leftProp.escapedName) || isClassMethod(leftProp)) { continue; @@ -32552,11 +37628,11 @@ var ts; if (members.has(leftProp.escapedName)) { var rightProp = members.get(leftProp.escapedName); var rightType = getTypeOfSymbol(rightProp); - if (rightProp.flags & 16777216) { + if (rightProp.flags & 16777216 /* Optional */) { var declarations = ts.concatenate(leftProp.declarations, rightProp.declarations); - var flags = 4 | (leftProp.flags & 16777216); + var flags = 4 /* Property */ | (leftProp.flags & 16777216 /* Optional */); var result = createSymbol(flags, leftProp.escapedName); - result.type = getUnionType([getTypeOfSymbol(leftProp), getTypeWithFacts(rightType, 131072)]); + result.type = getUnionType([getTypeOfSymbol(leftProp), getTypeWithFacts(rightType, 131072 /* NEUndefined */)]); result.leftSpread = leftProp; result.rightSpread = rightProp; result.declarations = declarations; @@ -32569,15 +37645,15 @@ var ts; } } var spread = createAnonymousType(symbol, members, ts.emptyArray, ts.emptyArray, getNonReadonlyIndexSignature(stringIndexInfo), getNonReadonlyIndexSignature(numberIndexInfo)); - spread.flags |= typeFlags | 268435456; - spread.objectFlags |= objectFlags | (128 | 1024); + spread.flags |= typeFlags | 268435456 /* ContainsObjectLiteral */; + spread.objectFlags |= objectFlags | (128 /* ObjectLiteral */ | 1024 /* ContainsSpread */); return spread; } function getNonReadonlySymbol(prop) { if (!isReadonlySymbol(prop)) { return prop; } - var flags = 4 | (prop.flags & 16777216); + var flags = 4 /* Property */ | (prop.flags & 16777216 /* Optional */); var result = createSymbol(flags, prop.escapedName); result.type = getTypeOfSymbol(prop); result.declarations = prop.declarations; @@ -32587,12 +37663,12 @@ var ts; } function getNonReadonlyIndexSignature(index) { if (index && index.isReadonly) { - return createIndexInfo(index.type, false, index.declaration); + return createIndexInfo(index.type, /*isReadonly*/ false, index.declaration); } return index; } function isClassMethod(prop) { - return prop.flags & 8192 && ts.find(prop.declarations, function (decl) { return ts.isClassLike(decl.parent); }); + return prop.flags & 8192 /* Method */ && ts.find(prop.declarations, function (decl) { return ts.isClassLike(decl.parent); }); } function createLiteralType(flags, value, symbol) { var type = createType(flags); @@ -32601,9 +37677,9 @@ var ts; return type; } function getFreshTypeOfLiteralType(type) { - if (type.flags & 192 && !(type.flags & 33554432)) { + if (type.flags & 192 /* StringOrNumberLiteral */ && !(type.flags & 33554432 /* FreshLiteral */)) { if (!type.freshType) { - var freshType = createLiteralType(type.flags | 33554432, type.value, type.symbol); + var freshType = createLiteralType(type.flags | 33554432 /* FreshLiteral */, type.value, type.symbol); freshType.regularType = type; type.freshType = freshType; } @@ -32612,16 +37688,20 @@ var ts; return type; } function getRegularTypeOfLiteralType(type) { - return type.flags & 192 && type.flags & 33554432 ? type.regularType : - type.flags & 262144 ? getUnionType(ts.sameMap(type.types, getRegularTypeOfLiteralType)) : + return type.flags & 192 /* StringOrNumberLiteral */ && type.flags & 33554432 /* FreshLiteral */ ? type.regularType : + type.flags & 262144 /* Union */ ? getUnionType(ts.sameMap(type.types, getRegularTypeOfLiteralType)) : type; } function getLiteralType(value, enumId, symbol) { + // We store all literal types in a single map with keys of the form '#NNN' and '@SSS', + // where NNN is the text representation of a numeric literal and SSS are the characters + // of a string literal. For literal enum members we use 'EEE#NNN' and 'EEE@SSS', where + // EEE is a unique id for the containing enum type. var qualifier = typeof value === "number" ? "#" : "@"; var key = enumId ? enumId + qualifier + value : qualifier + value; var type = literalTypes.get(key); if (!type) { - var flags = (typeof value === "number" ? 128 : 64) | (enumId ? 512 : 0); + var flags = (typeof value === "number" ? 128 /* NumberLiteral */ : 64 /* StringLiteral */) | (enumId ? 512 /* EnumLiteral */ : 0); literalTypes.set(key, type = createLiteralType(flags, value, symbol)); } return type; @@ -32634,7 +37714,7 @@ var ts; return links.resolvedType; } function createUniqueESSymbolType(symbol) { - var type = createType(2048); + var type = createType(2048 /* UniqueESSymbol */); type.symbol = symbol; return type; } @@ -32647,11 +37727,11 @@ var ts; return esSymbolType; } function getThisType(node) { - var container = ts.getThisContainer(node, false); + var container = ts.getThisContainer(node, /*includeArrowFunctions*/ false); var parent = container && container.parent; - if (parent && (ts.isClassLike(parent) || parent.kind === 236)) { - if (!ts.hasModifier(container, 32) && - (container.kind !== 155 || ts.isNodeDescendantOf(node, container.body))) { + if (parent && (ts.isClassLike(parent) || parent.kind === 236 /* InterfaceDeclaration */)) { + if (!ts.hasModifier(container, 32 /* Static */) && + (container.kind !== 155 /* Constructor */ || ts.isNodeDescendantOf(node, container.body))) { return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(parent)).thisType; } } @@ -32667,84 +37747,86 @@ var ts; } function getTypeFromTypeNode(node) { switch (node.kind) { - case 119: - case 279: - case 280: + case 119 /* AnyKeyword */: + case 279 /* JSDocAllType */: + case 280 /* JSDocUnknownType */: return anyType; - case 142: + case 142 /* UnknownKeyword */: return unknownType; - case 137: + case 137 /* StringKeyword */: return stringType; - case 134: + case 134 /* NumberKeyword */: return numberType; - case 122: + case 122 /* BooleanKeyword */: return booleanType; - case 138: + case 138 /* SymbolKeyword */: return esSymbolType; - case 105: + case 105 /* VoidKeyword */: return voidType; - case 140: + case 140 /* UndefinedKeyword */: return undefinedType; - case 95: + case 95 /* NullKeyword */: return nullType; - case 131: + case 131 /* NeverKeyword */: return neverType; - case 135: - return node.flags & 65536 ? anyType : nonPrimitiveType; - case 174: - case 99: + case 135 /* ObjectKeyword */: + return node.flags & 65536 /* JavaScriptFile */ ? anyType : nonPrimitiveType; + case 174 /* ThisType */: + case 99 /* ThisKeyword */: return getTypeFromThisTypeNode(node); - case 178: + case 178 /* LiteralType */: return getTypeFromLiteralTypeNode(node); - case 162: + case 162 /* TypeReference */: return getTypeFromTypeReference(node); - case 161: + case 161 /* TypePredicate */: return booleanType; - case 207: + case 207 /* ExpressionWithTypeArguments */: return getTypeFromTypeReference(node); - case 165: + case 165 /* TypeQuery */: return getTypeFromTypeQueryNode(node); - case 167: + case 167 /* ArrayType */: return getTypeFromArrayTypeNode(node); - case 168: + case 168 /* TupleType */: return getTypeFromTupleTypeNode(node); - case 169: + case 169 /* UnionType */: return getTypeFromUnionTypeNode(node); - case 170: + case 170 /* IntersectionType */: return getTypeFromIntersectionTypeNode(node); - case 281: + case 281 /* JSDocNullableType */: return getTypeFromJSDocNullableTypeNode(node); - case 283: + case 283 /* JSDocOptionalType */: return addOptionality(getTypeFromTypeNode(node.type)); - case 173: - case 282: - case 278: + case 173 /* ParenthesizedType */: + case 282 /* JSDocNonNullableType */: + case 278 /* JSDocTypeExpression */: return getTypeFromTypeNode(node.type); - case 285: + case 285 /* JSDocVariadicType */: return getTypeFromJSDocVariadicType(node); - case 163: - case 164: - case 166: - case 287: - case 284: - case 288: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 166 /* TypeLiteral */: + case 287 /* JSDocTypeLiteral */: + case 284 /* JSDocFunctionType */: + case 288 /* JSDocSignature */: return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node); - case 175: + case 175 /* TypeOperator */: return getTypeFromTypeOperatorNode(node); - case 176: + case 176 /* IndexedAccessType */: return getTypeFromIndexedAccessTypeNode(node); - case 177: + case 177 /* MappedType */: return getTypeFromMappedTypeNode(node); - case 171: + case 171 /* ConditionalType */: return getTypeFromConditionalTypeNode(node); - case 172: + case 172 /* InferType */: return getTypeFromInferTypeNode(node); - case 179: + case 179 /* ImportType */: return getTypeFromImportTypeNode(node); - case 71: - case 146: + // This function assumes that an identifier or qualified name is a type expression + // Callers should first ensure this by calling isTypeNode + case 71 /* Identifier */: + case 146 /* QualifiedName */: var symbol = getSymbolAtLocation(node); - return (symbol && getDeclaredTypeOfSymbol(symbol)); + return (symbol && getDeclaredTypeOfSymbol(symbol)); // TODO: GH#18217 default: return errorType; } @@ -32795,8 +37877,12 @@ var ts; makeArrayTypeMapper(sources, targets); } function createTypeEraser(sources) { - return createTypeMapper(sources, undefined); + return createTypeMapper(sources, /*targets*/ undefined); } + /** + * Maps forward-references to later types parameters to the empty object type. + * This is used during inference when instantiating type parameter defaults. + */ function createBackreferenceMapper(typeParameters, index) { return function (t) { return typeParameters.indexOf(t) >= index ? emptyObjectType : t; }; } @@ -32805,7 +37891,7 @@ var ts; } function cloneTypeMapper(mapper) { return mapper && isInferenceContext(mapper) ? - createInferenceContext(mapper.typeParameters, mapper.signature, mapper.flags | 2, mapper.compareTypes, mapper.inferences) : + createInferenceContext(mapper.typeParameters, mapper.signature, mapper.flags | 2 /* NoDefault */, mapper.compareTypes, mapper.inferences) : mapper; } function combineTypeMappers(mapper1, mapper2) { @@ -32819,10 +37905,10 @@ var ts; return function (t) { return t === source ? target : baseMapper(t); }; } function wildcardMapper(type) { - return type.flags & 65536 ? wildcardType : type; + return type.flags & 65536 /* TypeParameter */ ? wildcardType : type; } function cloneTypeParameter(typeParameter) { - var result = createType(65536); + var result = createType(65536 /* TypeParameter */); result.symbol = typeParameter.symbol; result.target = typeParameter; return result; @@ -32830,7 +37916,7 @@ var ts; function instantiateTypePredicate(predicate, mapper) { if (ts.isIdentifierTypePredicate(predicate)) { return { - kind: 1, + kind: 1 /* Identifier */, parameterName: predicate.parameterName, parameterIndex: predicate.parameterIndex, type: instantiateType(predicate.type, mapper) @@ -32838,7 +37924,7 @@ var ts; } else { return { - kind: 0, + kind: 0 /* This */, type: instantiateType(predicate.type, mapper) }; } @@ -32846,6 +37932,9 @@ var ts; function instantiateSignature(signature, mapper, eraseTypeParameters) { var freshTypeParameters; if (signature.typeParameters && !eraseTypeParameters) { + // First create a fresh set of type parameters, then include a mapping from the old to the + // new type parameters in the mapper function. Finally store this mapper in the new type + // parameters such that we can use it when instantiating constraints. freshTypeParameters = ts.map(signature.typeParameters, cloneTypeParameter); mapper = combineTypeMappers(createTypeMapper(signature.typeParameters, freshTypeParameters), mapper); for (var _i = 0, freshTypeParameters_1 = freshTypeParameters; _i < freshTypeParameters_1.length; _i++) { @@ -32853,21 +37942,33 @@ var ts; tp.mapper = mapper; } } - var result = createSignature(signature.declaration, freshTypeParameters, signature.thisParameter && instantiateSymbol(signature.thisParameter, mapper), instantiateList(signature.parameters, mapper, instantiateSymbol), undefined, undefined, signature.minArgumentCount, signature.hasRestParameter, signature.hasLiteralTypes); + // Don't compute resolvedReturnType and resolvedTypePredicate now, + // because using `mapper` now could trigger inferences to become fixed. (See `createInferenceContext`.) + // See GH#17600. + var result = createSignature(signature.declaration, freshTypeParameters, signature.thisParameter && instantiateSymbol(signature.thisParameter, mapper), instantiateList(signature.parameters, mapper, instantiateSymbol), + /*resolvedReturnType*/ undefined, + /*resolvedTypePredicate*/ undefined, signature.minArgumentCount, signature.hasRestParameter, signature.hasLiteralTypes); result.target = signature; result.mapper = mapper; return result; } function instantiateSymbol(symbol, mapper) { var links = getSymbolLinks(symbol); - if (links.type && !maybeTypeOfKind(links.type, 131072 | 15794176)) { + if (links.type && !maybeTypeOfKind(links.type, 131072 /* Object */ | 15794176 /* Instantiable */)) { + // If the type of the symbol is already resolved, and if that type could not possibly + // be affected by instantiation, simply return the symbol itself. return symbol; } - if (ts.getCheckFlags(symbol) & 1) { + if (ts.getCheckFlags(symbol) & 1 /* Instantiated */) { + // If symbol being instantiated is itself a instantiation, fetch the original target and combine the + // type mappers. This ensures that original type identities are properly preserved and that aliases + // always reference a non-aliases. symbol = links.target; mapper = combineTypeMappers(links.mapper, mapper); } - var result = createSymbol(symbol.flags, symbol.escapedName, 1 | (ts.getCheckFlags(symbol) & 1024)); + // Keep the flags from the symbol we're instantiating. Mark that is instantiated, and + // also transient so that we can just store data on it directly. + var result = createSymbol(symbol.flags, symbol.escapedName, 1 /* Instantiated */ | (ts.getCheckFlags(symbol) & 1024 /* Late */)); result.declarations = symbol.declarations; result.parent = symbol.parent; result.target = symbol; @@ -32886,11 +37987,15 @@ var ts; return result; } function getAnonymousTypeInstantiation(type, mapper) { - var target = type.objectFlags & 64 ? type.target : type; + var target = type.objectFlags & 64 /* Instantiated */ ? type.target : type; var symbol = target.symbol; var links = getSymbolLinks(symbol); var typeParameters = links.outerTypeParameters; if (!typeParameters) { + // The first time an anonymous type is instantiated we compute and store a list of the type + // parameters that are in scope (and therefore potentially referenced). For type literals that + // aren't the right hand side of a generic type alias declaration we optimize by reducing the + // set of type parameters to those that are possibly referenced in the literal. var declaration_1 = symbol.declarations[0]; if (ts.isInJavaScriptFile(declaration_1)) { var paramTag = ts.findAncestor(declaration_1, ts.isJSDocParameterTag); @@ -32901,13 +38006,13 @@ var ts; } } } - var outerTypeParameters = getOuterTypeParameters(declaration_1, true); + var outerTypeParameters = getOuterTypeParameters(declaration_1, /*includeThisTypes*/ true); if (isJavaScriptConstructor(declaration_1)) { var templateTagParameters = getTypeParametersFromDeclaration(declaration_1); outerTypeParameters = ts.addRange(outerTypeParameters, templateTagParameters); } typeParameters = outerTypeParameters || ts.emptyArray; - typeParameters = symbol.flags & 2048 && !target.aliasTypeArguments ? + typeParameters = symbol.flags & 2048 /* TypeLiteral */ && !target.aliasTypeArguments ? ts.filter(typeParameters, function (tp) { return isTypeParameterPossiblyReferenced(tp, declaration_1); }) : typeParameters; links.outerTypeParameters = typeParameters; @@ -32917,13 +38022,16 @@ var ts; } } if (typeParameters.length) { - var combinedMapper = type.objectFlags & 64 ? combineTypeMappers(type.mapper, mapper) : mapper; + // We are instantiating an anonymous type that has one or more type parameters in scope. Apply the + // mapper to the type parameters to produce the effective list of type arguments, and compute the + // instantiation cache key from the type IDs of the type arguments. + var combinedMapper = type.objectFlags & 64 /* Instantiated */ ? combineTypeMappers(type.mapper, mapper) : mapper; var typeArguments = ts.map(typeParameters, combinedMapper); var id = getTypeListId(typeArguments); var result = links.instantiations.get(id); if (!result) { var newMapper = createTypeMapper(typeParameters, typeArguments); - result = target.objectFlags & 32 ? instantiateMappedType(target, newMapper) : instantiateAnonymousType(target, newMapper); + result = target.objectFlags & 32 /* Mapped */ ? instantiateMappedType(target, newMapper) : instantiateAnonymousType(target, newMapper); links.instantiations.set(id, result); } return result; @@ -32931,35 +38039,43 @@ var ts; return type; } function maybeTypeParameterReference(node) { - return !(node.kind === 146 || - node.parent.kind === 162 && node.parent.typeArguments && node === node.parent.typeName); + return !(node.kind === 146 /* QualifiedName */ || + node.parent.kind === 162 /* TypeReference */ && node.parent.typeArguments && node === node.parent.typeName); } function isTypeParameterPossiblyReferenced(tp, node) { + // If the type parameter doesn't have exactly one declaration, if there are invening statement blocks + // between the node and the type parameter declaration, if the node contains actual references to the + // type parameter, or if the node contains type queries, we consider the type parameter possibly referenced. if (tp.symbol && tp.symbol.declarations && tp.symbol.declarations.length === 1) { var container_3 = tp.symbol.declarations[0].parent; - if (ts.findAncestor(node, function (n) { return n.kind === 213 ? "quit" : n === container_3; })) { + if (ts.findAncestor(node, function (n) { return n.kind === 213 /* Block */ ? "quit" : n === container_3; })) { return !!ts.forEachChild(node, containsReference); } } return true; function containsReference(node) { switch (node.kind) { - case 174: + case 174 /* ThisType */: return !!tp.isThisType; - case 71: + case 71 /* Identifier */: return !tp.isThisType && ts.isPartOfTypeNode(node) && maybeTypeParameterReference(node) && getTypeFromTypeNode(node) === tp; - case 165: + case 165 /* TypeQuery */: return true; } return !!ts.forEachChild(node, containsReference); } } function instantiateMappedType(type, mapper) { + // Check if we have a homomorphic mapped type, i.e. a type of the form { [P in keyof T]: X } for some + // type variable T. If so, the mapped type is distributive over a union type and when T is instantiated + // to a union type A | B, we produce { [P in keyof A]: X } | { [P in keyof B]: X }. Furthermore, for + // homomorphic mapped types we leave primitive types alone. For example, when T is instantiated to a + // union type A | undefined, we produce { [P in keyof A]: X } | undefined. var constraintType = getConstraintTypeFromMappedType(type); - if (constraintType.flags & 1048576) { + if (constraintType.flags & 1048576 /* Index */) { var typeVariable_1 = constraintType.type; - if (typeVariable_1.flags & 65536) { + if (typeVariable_1.flags & 65536 /* TypeParameter */) { var mappedTypeVariable = instantiateType(typeVariable_1, mapper); if (typeVariable_1 !== mappedTypeVariable) { return mapType(mappedTypeVariable, function (t) { @@ -32974,11 +38090,11 @@ var ts; return instantiateAnonymousType(type, mapper); } function isMappableType(type) { - return type.flags & (3 | 14745600 | 131072 | 524288); + return type.flags & (3 /* AnyOrUnknown */ | 14745600 /* InstantiableNonPrimitive */ | 131072 /* Object */ | 524288 /* Intersection */); } function instantiateAnonymousType(type, mapper) { - var result = createObjectType(type.objectFlags | 64, type.symbol); - if (type.objectFlags & 32) { + var result = createObjectType(type.objectFlags | 64 /* Instantiated */, type.symbol); + if (type.objectFlags & 32 /* Mapped */) { result.declaration = type.declaration; } result.target = type; @@ -32990,6 +38106,9 @@ var ts; function getConditionalTypeInstantiation(type, mapper) { var root = type.root; if (root.outerTypeParameters) { + // We are instantiating a conditional type that has one or more type parameters in scope. Apply the + // mapper to the type parameters to produce the effective list of type arguments, and compute the + // instantiation cache key from the type IDs of the type arguments. var typeArguments = ts.map(root.outerTypeParameters, mapper); var id = getTypeListId(typeArguments); var result = root.instantiations.get(id); @@ -33003,10 +38122,13 @@ var ts; return type; } function instantiateConditionalType(root, mapper) { + // Check if we have a conditional type where the check type is a naked type parameter. If so, + // the conditional type is distributive over union types and when T is instantiated to a union + // type A | B, we produce (A extends U ? X : Y) | (B extends U ? X : Y). if (root.isDistributive) { var checkType_1 = root.checkType; var instantiatedType = mapper(checkType_1); - if (checkType_1 !== instantiatedType && instantiatedType.flags & (262144 | 32768)) { + if (checkType_1 !== instantiatedType && instantiatedType.flags & (262144 /* Union */ | 32768 /* Never */)) { return mapType(instantiatedType, function (t) { return getConditionalType(root, createReplacementMapper(checkType_1, t, mapper)); }); } } @@ -33014,83 +38136,90 @@ var ts; } function instantiateType(type, mapper) { if (type && mapper && mapper !== identityMapper) { - if (type.flags & 65536) { + if (type.flags & 65536 /* TypeParameter */) { return mapper(type); } - if (type.flags & 131072) { - if (type.objectFlags & 16) { - return type.symbol && type.symbol.flags & (16 | 8192 | 32 | 2048 | 4096) && type.symbol.declarations ? + if (type.flags & 131072 /* Object */) { + if (type.objectFlags & 16 /* Anonymous */) { + // If the anonymous type originates in a declaration of a function, method, class, or + // interface, in an object type literal, or in an object literal expression, we may need + // to instantiate the type because it might reference a type parameter. + return type.symbol && type.symbol.flags & (16 /* Function */ | 8192 /* Method */ | 32 /* Class */ | 2048 /* TypeLiteral */ | 4096 /* ObjectLiteral */) && type.symbol.declarations ? getAnonymousTypeInstantiation(type, mapper) : type; } - if (type.objectFlags & 32) { + if (type.objectFlags & 32 /* Mapped */) { return getAnonymousTypeInstantiation(type, mapper); } - if (type.objectFlags & 4) { + if (type.objectFlags & 4 /* Reference */) { var typeArguments = type.typeArguments; var newTypeArguments = instantiateTypes(typeArguments, mapper); return newTypeArguments !== typeArguments ? createTypeReference(type.target, newTypeArguments) : type; } } - if (type.flags & 262144 && !(type.flags & 32764)) { + if (type.flags & 262144 /* Union */ && !(type.flags & 32764 /* Primitive */)) { var types = type.types; var newTypes = instantiateTypes(types, mapper); - return newTypes !== types ? getUnionType(newTypes, 1, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)) : type; + return newTypes !== types ? getUnionType(newTypes, 1 /* Literal */, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)) : type; } - if (type.flags & 524288) { + if (type.flags & 524288 /* Intersection */) { var types = type.types; var newTypes = instantiateTypes(types, mapper); return newTypes !== types ? getIntersectionType(newTypes, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)) : type; } - if (type.flags & 1048576) { + if (type.flags & 1048576 /* Index */) { return getIndexType(instantiateType(type.type, mapper)); } - if (type.flags & 2097152) { + if (type.flags & 2097152 /* IndexedAccess */) { return getIndexedAccessType(instantiateType(type.objectType, mapper), instantiateType(type.indexType, mapper)); } - if (type.flags & 4194304) { + if (type.flags & 4194304 /* Conditional */) { return getConditionalTypeInstantiation(type, combineTypeMappers(type.mapper, mapper)); } - if (type.flags & 8388608) { + if (type.flags & 8388608 /* Substitution */) { return instantiateType(type.typeVariable, mapper); } } return type; } function getWildcardInstantiation(type) { - return type.flags & (32764 | 3 | 32768) ? type : + return type.flags & (32764 /* Primitive */ | 3 /* AnyOrUnknown */ | 32768 /* Never */) ? type : type.wildcardInstantiation || (type.wildcardInstantiation = instantiateType(type, wildcardMapper)); } function instantiateIndexInfo(info, mapper) { return info && createIndexInfo(instantiateType(info.type, mapper), info.isReadonly, info.declaration); } + // Returns true if the given expression contains (at any level of nesting) a function or arrow expression + // that is subject to contextual typing. function isContextSensitive(node) { - ts.Debug.assert(node.kind !== 154 || ts.isObjectLiteralMethod(node)); + ts.Debug.assert(node.kind !== 154 /* MethodDeclaration */ || ts.isObjectLiteralMethod(node)); switch (node.kind) { - case 192: - case 193: - case 154: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 154 /* MethodDeclaration */: return isContextSensitiveFunctionLikeDeclaration(node); - case 184: + case 184 /* ObjectLiteralExpression */: return ts.some(node.properties, isContextSensitive); - case 183: + case 183 /* ArrayLiteralExpression */: return ts.some(node.elements, isContextSensitive); - case 201: + case 201 /* ConditionalExpression */: return isContextSensitive(node.whenTrue) || isContextSensitive(node.whenFalse); - case 200: - return node.operatorToken.kind === 54 && + case 200 /* BinaryExpression */: + return node.operatorToken.kind === 54 /* BarBarToken */ && (isContextSensitive(node.left) || isContextSensitive(node.right)); - case 270: + case 270 /* PropertyAssignment */: return isContextSensitive(node.initializer); - case 191: + case 191 /* ParenthesizedExpression */: return isContextSensitive(node.expression); - case 263: + case 263 /* JsxAttributes */: return ts.some(node.properties, isContextSensitive); - case 262: { + case 262 /* JsxAttribute */: { + // If there is no initializer, JSX attribute has a boolean value of true which is not context sensitive. var initializer = node.initializer; return !!initializer && isContextSensitive(initializer); } - case 265: { + case 265 /* JsxExpression */: { + // It is possible to that node.expression is undefined (e.g
) var expression = node.expression; return !!expression && isContextSensitive(expression); } @@ -33098,30 +38227,35 @@ var ts; return false; } function isContextSensitiveFunctionLikeDeclaration(node) { + // Functions with type parameters are not context sensitive. if (node.typeParameters) { return false; } + // Functions with any parameters that lack type annotations are context sensitive. if (ts.some(node.parameters, function (p) { return !ts.getEffectiveTypeAnnotationNode(p); })) { return true; } - if (node.kind !== 193) { + if (node.kind !== 193 /* ArrowFunction */) { + // If the first parameter is not an explicit 'this' parameter, then the function has + // an implicit 'this' parameter which is subject to contextual typing. var parameter = ts.firstOrUndefined(node.parameters); if (!(parameter && ts.parameterIsThisKeyword(parameter))) { return true; } } + // TODO(anhans): A block should be context-sensitive if it has a context-sensitive return value. var body = node.body; - return body.kind === 213 ? false : isContextSensitive(body); + return body.kind === 213 /* Block */ ? false : isContextSensitive(body); } function isContextSensitiveFunctionOrObjectLiteralMethod(func) { return (ts.isInJavaScriptFile(func) && ts.isFunctionDeclaration(func) || isFunctionExpressionOrArrowFunction(func) || ts.isObjectLiteralMethod(func)) && isContextSensitiveFunctionLikeDeclaration(func); } function getTypeWithoutSignatures(type) { - if (type.flags & 131072) { + if (type.flags & 131072 /* Object */) { var resolved = resolveStructuredTypeMembers(type); if (resolved.constructSignatures.length) { - var result = createObjectType(16, type.symbol); + var result = createObjectType(16 /* Anonymous */, type.symbol); result.members = resolved.members; result.properties = resolved.properties; result.callSignatures = ts.emptyArray; @@ -33129,19 +38263,20 @@ var ts; return result; } } - else if (type.flags & 524288) { + else if (type.flags & 524288 /* Intersection */) { return getIntersectionType(ts.map(type.types, getTypeWithoutSignatures)); } return type; } + // TYPE CHECKING function isTypeIdenticalTo(source, target) { return isTypeRelatedTo(source, target, identityRelation); } function compareTypesIdentical(source, target) { - return isTypeRelatedTo(source, target, identityRelation) ? -1 : 0; + return isTypeRelatedTo(source, target, identityRelation) ? -1 /* True */ : 0 /* False */; } function compareTypesAssignable(source, target) { - return isTypeRelatedTo(source, target, assignableRelation) ? -1 : 0; + return isTypeRelatedTo(source, target, assignableRelation) ? -1 /* True */ : 0 /* False */; } function isTypeSubtypeOf(source, target) { return isTypeRelatedTo(source, target, subtypeRelation); @@ -33149,13 +38284,31 @@ var ts; function isTypeAssignableTo(source, target) { return isTypeRelatedTo(source, target, assignableRelation); } + // An object type S is considered to be derived from an object type T if + // S is a union type and every constituent of S is derived from T, + // T is a union type and S is derived from at least one constituent of T, or + // S is a type variable with a base constraint that is derived from T, + // T is one of the global types Object and Function and S is a subtype of T, or + // T occurs directly or indirectly in an 'extends' clause of S. + // Note that this check ignores type parameters and only considers the + // inheritance hierarchy. function isTypeDerivedFrom(source, target) { - return source.flags & 262144 ? ts.every(source.types, function (t) { return isTypeDerivedFrom(t, target); }) : - target.flags & 262144 ? ts.some(target.types, function (t) { return isTypeDerivedFrom(source, t); }) : - source.flags & 14745600 ? isTypeDerivedFrom(getBaseConstraintOfType(source) || emptyObjectType, target) : + return source.flags & 262144 /* Union */ ? ts.every(source.types, function (t) { return isTypeDerivedFrom(t, target); }) : + target.flags & 262144 /* Union */ ? ts.some(target.types, function (t) { return isTypeDerivedFrom(source, t); }) : + source.flags & 14745600 /* InstantiableNonPrimitive */ ? isTypeDerivedFrom(getBaseConstraintOfType(source) || emptyObjectType, target) : target === globalObjectType || target === globalFunctionType ? isTypeSubtypeOf(source, target) : hasBaseType(source, getTargetType(target)); } + /** + * This is *not* a bi-directional relationship. + * If one needs to check both directions for comparability, use a second call to this function or 'checkTypeComparableTo'. + * + * A type S is comparable to a type T if some (but not necessarily all) of the possible values of S are also possible values of T. + * It is used to check following cases: + * - the types of the left and right sides of equality/inequality operators (`===`, `!==`, `==`, `!=`). + * - the types of `case` clause expressions and their respective `switch` expressions. + * - the type of an expression in a type assertion with the type being asserted. + */ function isTypeComparableTo(source, target) { return isTypeRelatedTo(source, target, comparableRelation); } @@ -33165,38 +38318,48 @@ var ts; function checkTypeAssignableTo(source, target, errorNode, headMessage, containingMessageChain) { return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage, containingMessageChain); } + /** + * This is *not* a bi-directional relationship. + * If one needs to check both directions for comparability, use a second call to this function or 'isTypeComparableTo'. + */ function checkTypeComparableTo(source, target, errorNode, headMessage, containingMessageChain) { return checkTypeRelatedTo(source, target, comparableRelation, errorNode, headMessage, containingMessageChain); } function isSignatureAssignableTo(source, target, ignoreReturnTypes) { - return compareSignaturesRelated(source, target, 0, ignoreReturnTypes, false, undefined, compareTypesAssignable) !== 0; + return compareSignaturesRelated(source, target, 0 /* None */, ignoreReturnTypes, /*reportErrors*/ false, + /*errorReporter*/ undefined, compareTypesAssignable) !== 0 /* False */; } + /** + * See signatureRelatedTo, compareSignaturesIdentical + */ function compareSignaturesRelated(source, target, callbackCheck, ignoreReturnTypes, reportErrors, errorReporter, compareTypes) { + // TODO (drosen): De-duplicate code between related functions. if (source === target) { - return -1; + return -1 /* True */; } if (!target.hasRestParameter && source.minArgumentCount > target.parameters.length) { - return 0; + return 0 /* False */; } if (source.typeParameters && source.typeParameters !== target.typeParameters) { target = getCanonicalSignature(target); - source = instantiateSignatureInContextOf(source, target, undefined, compareTypes); + source = instantiateSignatureInContextOf(source, target, /*contextualMapper*/ undefined, compareTypes); } - var kind = target.declaration ? target.declaration.kind : 0; - var strictVariance = !callbackCheck && strictFunctionTypes && kind !== 154 && - kind !== 153 && kind !== 155; - var result = -1; + var kind = target.declaration ? target.declaration.kind : 0 /* Unknown */; + var strictVariance = !callbackCheck && strictFunctionTypes && kind !== 154 /* MethodDeclaration */ && + kind !== 153 /* MethodSignature */ && kind !== 155 /* Constructor */; + var result = -1 /* True */; var sourceThisType = getThisTypeOfSignature(source); if (sourceThisType && sourceThisType !== voidType) { var targetThisType = getThisTypeOfSignature(target); if (targetThisType) { - var related = !strictVariance && compareTypes(sourceThisType, targetThisType, false) + // void sources are assignable to anything. + var related = !strictVariance && compareTypes(sourceThisType, targetThisType, /*reportErrors*/ false) || compareTypes(targetThisType, sourceThisType, reportErrors); if (!related) { if (reportErrors) { errorReporter(ts.Diagnostics.The_this_types_of_each_signature_are_incompatible); } - return 0; + return 0 /* False */; } result &= related; } @@ -33209,18 +38372,27 @@ var ts; for (var i = 0; i < checkCount; i++) { var sourceType = i < sourceMax ? getTypeOfParameter(sourceParams[i]) : getRestTypeOfSignature(source); var targetType = i < targetMax ? getTypeOfParameter(targetParams[i]) : getRestTypeOfSignature(target); + // In order to ensure that any generic type Foo is at least co-variant with respect to T no matter + // how Foo uses T, we need to relate parameters bi-variantly (given that parameters are input positions, + // they naturally relate only contra-variantly). However, if the source and target parameters both have + // function types with a single call signature, we know we are relating two callback parameters. In + // that case it is sufficient to only relate the parameters of the signatures co-variantly because, + // similar to return values, callback parameters are output positions. This means that a Promise, + // where T is used only in callback parameter positions, will be co-variant (as opposed to bi-variant) + // with respect to T. var sourceSig = callbackCheck ? undefined : getSingleCallSignature(getNonNullableType(sourceType)); var targetSig = callbackCheck ? undefined : getSingleCallSignature(getNonNullableType(targetType)); var callbacks = sourceSig && targetSig && !signatureHasTypePredicate(sourceSig) && !signatureHasTypePredicate(targetSig) && - (getFalsyFlags(sourceType) & 24576) === (getFalsyFlags(targetType) & 24576); + (getFalsyFlags(sourceType) & 24576 /* Nullable */) === (getFalsyFlags(targetType) & 24576 /* Nullable */); var related = callbacks ? - compareSignaturesRelated(targetSig, sourceSig, strictVariance ? 2 : 1, false, reportErrors, errorReporter, compareTypes) : - !callbackCheck && !strictVariance && compareTypes(sourceType, targetType, false) || compareTypes(targetType, sourceType, reportErrors); + // TODO: GH#18217 It will work if they're both `undefined`, but not if only one is + compareSignaturesRelated(targetSig, sourceSig, strictVariance ? 2 /* Strict */ : 1 /* Bivariant */, /*ignoreReturnTypes*/ false, reportErrors, errorReporter, compareTypes) : + !callbackCheck && !strictVariance && compareTypes(sourceType, targetType, /*reportErrors*/ false) || compareTypes(targetType, sourceType, reportErrors); if (!related) { if (reportErrors) { errorReporter(ts.Diagnostics.Types_of_parameters_0_and_1_are_incompatible, ts.symbolName(sourceParams[i < sourceMax ? i : sourceMax]), ts.symbolName(targetParams[i < targetMax ? i : targetMax])); } - return 0; + return 0 /* False */; } result &= related; } @@ -33230,21 +38402,25 @@ var ts; return result; } var sourceReturnType = getReturnTypeOfSignature(source); + // The following block preserves behavior forbidding boolean returning functions from being assignable to type guard returning functions var targetTypePredicate = getTypePredicateOfSignature(target); if (targetTypePredicate) { var sourceTypePredicate = getTypePredicateOfSignature(source); if (sourceTypePredicate) { - result &= compareTypePredicateRelatedTo(sourceTypePredicate, targetTypePredicate, source.declaration, target.declaration, reportErrors, errorReporter, compareTypes); + result &= compareTypePredicateRelatedTo(sourceTypePredicate, targetTypePredicate, source.declaration, target.declaration, reportErrors, errorReporter, compareTypes); // TODO: GH#18217 } else if (ts.isIdentifierTypePredicate(targetTypePredicate)) { if (reportErrors) { errorReporter(ts.Diagnostics.Signature_0_must_be_a_type_predicate, signatureToString(source)); } - return 0; + return 0 /* False */; } } else { - result &= callbackCheck === 1 && compareTypes(targetReturnType, sourceReturnType, false) || + // When relating callback signatures, we still need to relate return types bi-variantly as otherwise + // the containing type wouldn't be co-variant. For example, interface Foo { add(cb: () => T): void } + // wouldn't be co-variant for T without this rule. + result &= callbackCheck === 1 /* Bivariant */ && compareTypes(targetReturnType, sourceReturnType, /*reportErrors*/ false) || compareTypes(sourceReturnType, targetReturnType, reportErrors); } } @@ -33256,9 +38432,9 @@ var ts; errorReporter(ts.Diagnostics.A_this_based_type_guard_is_not_compatible_with_a_parameter_based_type_guard); errorReporter(ts.Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); } - return 0; + return 0 /* False */; } - if (source.kind === 1) { + if (source.kind === 1 /* Identifier */) { var targetPredicate = target; var sourceIndex = source.parameterIndex - (ts.getThisParameter(sourceDeclaration) ? 1 : 0); var targetIndex = targetPredicate.parameterIndex - (ts.getThisParameter(targetDeclaration) ? 1 : 0); @@ -33267,11 +38443,11 @@ var ts; errorReporter(ts.Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, source.parameterName, targetPredicate.parameterName); errorReporter(ts.Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); } - return 0; + return 0 /* False */; } } var related = compareTypes(source.type, target.type, reportErrors); - if (related === 0 && reportErrors) { + if (related === 0 /* False */ && reportErrors) { errorReporter(ts.Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); } return related; @@ -33279,12 +38455,13 @@ var ts; function isImplementationCompatibleWithOverload(implementation, overload) { var erasedSource = getErasedSignature(implementation); var erasedTarget = getErasedSignature(overload); + // First see if the return types are compatible in either direction. var sourceReturnType = getReturnTypeOfSignature(erasedSource); var targetReturnType = getReturnTypeOfSignature(erasedTarget); if (targetReturnType === voidType || isTypeRelatedTo(targetReturnType, sourceReturnType, assignableRelation) || isTypeRelatedTo(sourceReturnType, targetReturnType, assignableRelation)) { - return isSignatureAssignableTo(erasedSource, erasedTarget, true); + return isSignatureAssignableTo(erasedSource, erasedTarget, /*ignoreReturnTypes*/ true); } return false; } @@ -33297,6 +38474,8 @@ var ts; function getNumParametersToCheckForSignatureRelatability(source, sourceNonRestParamCount, target, targetNonRestParamCount) { if (source.hasRestParameter === target.hasRestParameter) { if (source.hasRestParameter) { + // If both have rest parameters, get the max and add 1 to + // compensate for the rest parameter. return Math.max(sourceNonRestParamCount, targetNonRestParamCount) + 1; } else { @@ -33304,6 +38483,7 @@ var ts; } } else { + // Return the count for whichever signature doesn't have rest parameters. return source.hasRestParameter ? targetNonRestParamCount : sourceNonRestParamCount; @@ -33317,10 +38497,10 @@ var ts; !t.numberIndexInfo; } function isEmptyObjectType(type) { - return type.flags & 131072 ? isEmptyResolvedType(resolveStructuredTypeMembers(type)) : - type.flags & 16777216 ? true : - type.flags & 262144 ? ts.some(type.types, isEmptyObjectType) : - type.flags & 524288 ? ts.every(type.types, isEmptyObjectType) : + return type.flags & 131072 /* Object */ ? isEmptyResolvedType(resolveStructuredTypeMembers(type)) : + type.flags & 16777216 /* NonPrimitive */ ? true : + type.flags & 262144 /* Union */ ? ts.some(type.types, isEmptyObjectType) : + type.flags & 524288 /* Intersection */ ? ts.every(type.types, isEmptyObjectType) : false; } function isEnumTypeRelatedTo(sourceSymbol, targetSymbol, errorReporter) { @@ -33332,18 +38512,18 @@ var ts; if (relation !== undefined) { return relation; } - if (sourceSymbol.escapedName !== targetSymbol.escapedName || !(sourceSymbol.flags & 256) || !(targetSymbol.flags & 256)) { + if (sourceSymbol.escapedName !== targetSymbol.escapedName || !(sourceSymbol.flags & 256 /* RegularEnum */) || !(targetSymbol.flags & 256 /* RegularEnum */)) { enumRelation.set(id, false); return false; } var targetEnumType = getTypeOfSymbol(targetSymbol); for (var _i = 0, _a = getPropertiesOfType(getTypeOfSymbol(sourceSymbol)); _i < _a.length; _i++) { var property = _a[_i]; - if (property.flags & 8) { + if (property.flags & 8 /* EnumMember */) { var targetProperty = getPropertyOfType(targetEnumType, property.escapedName); - if (!targetProperty || !(targetProperty.flags & 8)) { + if (!targetProperty || !(targetProperty.flags & 8 /* EnumMember */)) { if (errorReporter) { - errorReporter(ts.Diagnostics.Property_0_is_missing_in_type_1, ts.symbolName(property), typeToString(getDeclaredTypeOfSymbol(targetSymbol), undefined, 64)); + errorReporter(ts.Diagnostics.Property_0_is_missing_in_type_1, ts.symbolName(property), typeToString(getDeclaredTypeOfSymbol(targetSymbol), /*enclosingDeclaration*/ undefined, 64 /* UseFullyQualifiedType */)); } enumRelation.set(id, false); return false; @@ -33356,78 +38536,91 @@ var ts; function isSimpleTypeRelatedTo(source, target, relation, errorReporter) { var s = source.flags; var t = target.flags; - if (t & 3 || s & 32768 || source === wildcardType) + if (t & 3 /* AnyOrUnknown */ || s & 32768 /* Never */ || source === wildcardType) return true; - if (t & 32768) + if (t & 32768 /* Never */) return false; - if (s & 68 && t & 4) + if (s & 68 /* StringLike */ && t & 4 /* String */) return true; - if (s & 64 && s & 512 && - t & 64 && !(t & 512) && + if (s & 64 /* StringLiteral */ && s & 512 /* EnumLiteral */ && + t & 64 /* StringLiteral */ && !(t & 512 /* EnumLiteral */) && source.value === target.value) return true; - if (s & 168 && t & 8) + if (s & 168 /* NumberLike */ && t & 8 /* Number */) return true; - if (s & 128 && s & 512 && - t & 128 && !(t & 512) && + if (s & 128 /* NumberLiteral */ && s & 512 /* EnumLiteral */ && + t & 128 /* NumberLiteral */ && !(t & 512 /* EnumLiteral */) && source.value === target.value) return true; - if (s & 272 && t & 16) + if (s & 272 /* BooleanLike */ && t & 16 /* Boolean */) return true; - if (s & 3072 && t & 1024) + if (s & 3072 /* ESSymbolLike */ && t & 1024 /* ESSymbol */) return true; - if (s & 32 && t & 32 && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) + if (s & 32 /* Enum */ && t & 32 /* Enum */ && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true; - if (s & 512 && t & 512) { - if (s & 262144 && t & 262144 && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) + if (s & 512 /* EnumLiteral */ && t & 512 /* EnumLiteral */) { + if (s & 262144 /* Union */ && t & 262144 /* Union */ && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true; - if (s & 448 && t & 448 && + if (s & 448 /* Literal */ && t & 448 /* Literal */ && source.value === target.value && isEnumTypeRelatedTo(getParentOfSymbol(source.symbol), getParentOfSymbol(target.symbol), errorReporter)) return true; } - if (s & 8192 && (!strictNullChecks || t & (8192 | 4096))) + if (s & 8192 /* Undefined */ && (!strictNullChecks || t & (8192 /* Undefined */ | 4096 /* Void */))) return true; - if (s & 16384 && (!strictNullChecks || t & 16384)) + if (s & 16384 /* Null */ && (!strictNullChecks || t & 16384 /* Null */)) return true; - if (s & 131072 && t & 16777216) + if (s & 131072 /* Object */ && t & 16777216 /* NonPrimitive */) return true; - if (s & 2048 || t & 2048) + if (s & 2048 /* UniqueESSymbol */ || t & 2048 /* UniqueESSymbol */) return false; if (relation === assignableRelation || relation === definitelyAssignableRelation || relation === comparableRelation) { - if (s & 1) + if (s & 1 /* Any */) return true; - if (s & (8 | 128) && !(s & 512) && (t & 32 || t & 128 && t & 512)) + // Type number or any numeric literal type is assignable to any numeric enum type or any + // numeric enum literal type. This rule exists for backwards compatibility reasons because + // bit-flag enum types sometimes look like literal enum types with numeric literal values. + if (s & (8 /* Number */ | 128 /* NumberLiteral */) && !(s & 512 /* EnumLiteral */) && (t & 32 /* Enum */ || t & 128 /* NumberLiteral */ && t & 512 /* EnumLiteral */)) return true; } return false; } function isTypeRelatedTo(source, target, relation) { - if (source.flags & 192 && source.flags & 33554432) { + if (source.flags & 192 /* StringOrNumberLiteral */ && source.flags & 33554432 /* FreshLiteral */) { source = source.regularType; } - if (target.flags & 192 && target.flags & 33554432) { + if (target.flags & 192 /* StringOrNumberLiteral */ && target.flags & 33554432 /* FreshLiteral */) { target = target.regularType; } if (source === target || - relation === comparableRelation && !(target.flags & 32768) && isSimpleTypeRelatedTo(target, source, relation) || + relation === comparableRelation && !(target.flags & 32768 /* Never */) && isSimpleTypeRelatedTo(target, source, relation) || relation !== identityRelation && isSimpleTypeRelatedTo(source, target, relation)) { return true; } - if (source.flags & 131072 && target.flags & 131072) { + if (source.flags & 131072 /* Object */ && target.flags & 131072 /* Object */) { var related = relation.get(getRelationKey(source, target, relation)); if (related !== undefined) { - return related === 1; + return related === 1 /* Succeeded */; } } - if (source.flags & 16711680 || target.flags & 16711680) { - return checkTypeRelatedTo(source, target, relation, undefined); + if (source.flags & 16711680 /* StructuredOrInstantiable */ || target.flags & 16711680 /* StructuredOrInstantiable */) { + return checkTypeRelatedTo(source, target, relation, /*errorNode*/ undefined); } return false; } function isIgnoredJsxProperty(source, sourceProp, targetMemberType) { - return ts.getObjectFlags(source) & 4096 && !(isUnhyphenatedJsxName(sourceProp.escapedName) || targetMemberType); + return ts.getObjectFlags(source) & 4096 /* JsxAttributes */ && !(isUnhyphenatedJsxName(sourceProp.escapedName) || targetMemberType); } + /** + * Checks if 'source' is related to 'target' (e.g.: is a assignable to). + * @param source The left-hand-side of the relation. + * @param target The right-hand-side of the relation. + * @param relation The relation considered. One of 'identityRelation', 'subtypeRelation', 'assignableRelation', or 'comparableRelation'. + * Used as both to determine which checks are performed and as a cache of previously computed results. + * @param errorNode The suggested node upon which all errors will be reported, if defined. This may or may not be the actual node used. + * @param headMessage If the error chain should be prepended by a head message, then headMessage will be used. + * @param containingMessageChain A chain of errors to prepend any new errors found. + */ function checkTypeRelatedTo(source, target, relation, errorNode, headMessage, containingMessageChain) { var errorInfo; var maybeKeys; @@ -33435,11 +38628,11 @@ var ts; var targetStack; var maybeCount = 0; var depth = 0; - var expandingFlags = 0; + var expandingFlags = 0 /* None */; var overflow = false; var isIntersectionConstituent = false; ts.Debug.assert(relation !== identityRelation || !errorNode, "no error reporting in identity checking"); - var result = isRelatedTo(source, target, !!errorNode, headMessage); + var result = isRelatedTo(source, target, /*reportErrors*/ !!errorNode, headMessage); if (overflow) { error(errorNode, ts.Diagnostics.Excessive_stack_depth_comparing_types_0_and_1, typeToString(source), typeToString(target)); } @@ -33451,19 +38644,21 @@ var ts; } } var relatedInformation = void 0; + // Check if we should issue an extra diagnostic to produce a quickfix for a slightly incorrect import statement if (headMessage && errorNode && !result && source.symbol) { var links = getSymbolLinks(source.symbol); if (links.originatingImport && !ts.isImportCall(links.originatingImport)) { - var helpfulRetry = checkTypeRelatedTo(getTypeOfSymbol(links.target), target, relation, undefined); + var helpfulRetry = checkTypeRelatedTo(getTypeOfSymbol(links.target), target, relation, /*errorNode*/ undefined); if (helpfulRetry) { + // Likely an incorrect import. Issue a helpful diagnostic to produce a quickfix to change the import var diag = ts.createDiagnosticForNode(links.originatingImport, ts.Diagnostics.Type_originates_at_this_import_A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_Consider_using_a_default_import_or_import_require_here_instead); - relatedInformation = ts.append(relatedInformation, diag); + relatedInformation = ts.append(relatedInformation, diag); // Cause the error to appear with the error that triggered it } } } - diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(errorNode, errorInfo, relatedInformation)); + diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(errorNode, errorInfo, relatedInformation)); // TODO: GH#18217 } - return result !== 0; + return result !== 0 /* False */; function reportError(message, arg0, arg1, arg2) { ts.Debug.assert(!!errorNode); errorInfo = ts.chainDiagnosticMessages(errorInfo, message, arg0, arg1, arg2); @@ -33472,8 +38667,8 @@ var ts; var sourceType = typeToString(source); var targetType = typeToString(target); if (sourceType === targetType) { - sourceType = typeToString(source, undefined, 64); - targetType = typeToString(target, undefined, 64); + sourceType = typeToString(source, /*enclosingDeclaration*/ undefined, 64 /* UseFullyQualifiedType */); + targetType = typeToString(target, /*enclosingDeclaration*/ undefined, 64 /* UseFullyQualifiedType */); } if (!message) { if (relation === comparableRelation) { @@ -33494,18 +38689,20 @@ var ts; if ((globalStringType === source && stringType === target) || (globalNumberType === source && numberType === target) || (globalBooleanType === source && booleanType === target) || - (getGlobalESSymbolType(false) === source && esSymbolType === target)) { + (getGlobalESSymbolType(/*reportErrors*/ false) === source && esSymbolType === target)) { reportError(ts.Diagnostics._0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible, targetType, sourceType); } } function isUnionOrIntersectionTypeWithoutNullableConstituents(type) { - if (!(type.flags & 786432)) { + if (!(type.flags & 786432 /* UnionOrIntersection */)) { return false; } + // at this point we know that this is union or intersection type possibly with nullable constituents. + // check if we still will have compound type if we ignore nullable components. var seenNonNullable = false; for (var _i = 0, _a = type.types; _i < _a.length; _i++) { var t = _a[_i]; - if (t.flags & 24576) { + if (t.flags & 24576 /* Nullable */) { continue; } if (seenNonNullable) { @@ -33515,95 +38712,131 @@ var ts; } return false; } + /** + * Compare two types and return + * * Ternary.True if they are related with no assumptions, + * * Ternary.Maybe if they are related with assumptions of other relationships, or + * * Ternary.False if they are not related. + */ function isRelatedTo(source, target, reportErrors, headMessage) { if (reportErrors === void 0) { reportErrors = false; } - if (source.flags & 192 && source.flags & 33554432) { + if (source.flags & 192 /* StringOrNumberLiteral */ && source.flags & 33554432 /* FreshLiteral */) { source = source.regularType; } - if (target.flags & 192 && target.flags & 33554432) { + if (target.flags & 192 /* StringOrNumberLiteral */ && target.flags & 33554432 /* FreshLiteral */) { target = target.regularType; } - if (source.flags & 8388608) { + if (source.flags & 8388608 /* Substitution */) { source = relation === definitelyAssignableRelation ? source.typeVariable : source.substitute; } - if (target.flags & 8388608) { + if (target.flags & 8388608 /* Substitution */) { target = target.typeVariable; } - if (source.flags & 2097152) { + if (source.flags & 2097152 /* IndexedAccess */) { source = getSimplifiedType(source); } - if (target.flags & 2097152) { + if (target.flags & 2097152 /* IndexedAccess */) { target = getSimplifiedType(target); } + // both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases if (source === target) - return -1; + return -1 /* True */; if (relation === identityRelation) { return isIdenticalTo(source, target); } - if (relation === comparableRelation && !(target.flags & 32768) && isSimpleTypeRelatedTo(target, source, relation) || + if (relation === comparableRelation && !(target.flags & 32768 /* Never */) && isSimpleTypeRelatedTo(target, source, relation) || isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) - return -1; - if (isObjectLiteralType(source) && source.flags & 33554432) { - var discriminantType = target.flags & 262144 ? findMatchingDiscriminantType(source, target) : undefined; + return -1 /* True */; + if (isObjectLiteralType(source) && source.flags & 33554432 /* FreshLiteral */) { + var discriminantType = target.flags & 262144 /* Union */ ? findMatchingDiscriminantType(source, target) : undefined; if (hasExcessProperties(source, target, discriminantType, reportErrors)) { if (reportErrors) { reportRelationError(headMessage, source, target); } - return 0; + return 0 /* False */; } + // Above we check for excess properties with respect to the entire target type. When union + // and intersection types are further deconstructed on the target side, we don't want to + // make the check again (as it might fail for a partial target type). Therefore we obtain + // the regular source type and proceed with that. if (isUnionOrIntersectionTypeWithoutNullableConstituents(target) && !discriminantType) { source = getRegularTypeOfObjectLiteral(source); } } if (relation !== comparableRelation && - !(source.flags & 786432) && - !(target.flags & 262144) && + !(source.flags & 786432 /* UnionOrIntersection */) && + !(target.flags & 262144 /* Union */) && !isIntersectionConstituent && source !== globalObjectType && (getPropertiesOfType(source).length > 0 || typeHasCallOrConstructSignatures(source)) && isWeakType(target) && !hasCommonProperties(source, target)) { if (reportErrors) { - var calls = getSignaturesOfType(source, 0); - var constructs = getSignaturesOfType(source, 1); - if (calls.length > 0 && isRelatedTo(getReturnTypeOfSignature(calls[0]), target, false) || - constructs.length > 0 && isRelatedTo(getReturnTypeOfSignature(constructs[0]), target, false)) { + var calls = getSignaturesOfType(source, 0 /* Call */); + var constructs = getSignaturesOfType(source, 1 /* Construct */); + if (calls.length > 0 && isRelatedTo(getReturnTypeOfSignature(calls[0]), target, /*reportErrors*/ false) || + constructs.length > 0 && isRelatedTo(getReturnTypeOfSignature(constructs[0]), target, /*reportErrors*/ false)) { reportError(ts.Diagnostics.Value_of_type_0_has_no_properties_in_common_with_type_1_Did_you_mean_to_call_it, typeToString(source), typeToString(target)); } else { reportError(ts.Diagnostics.Type_0_has_no_properties_in_common_with_type_1, typeToString(source), typeToString(target)); } } - return 0; + return 0 /* False */; } - var result = 0; + var result = 0 /* False */; var saveErrorInfo = errorInfo; var saveIsIntersectionConstituent = isIntersectionConstituent; isIntersectionConstituent = false; - if (source.flags & 262144) { + // Note that these checks are specifically ordered to produce correct results. In particular, + // we need to deconstruct unions before intersections (because unions are always at the top), + // and we need to handle "each" relations before "some" relations for the same kind of type. + if (source.flags & 262144 /* Union */) { result = relation === comparableRelation ? - someTypeRelatedToType(source, target, reportErrors && !(source.flags & 32764)) : - eachTypeRelatedToType(source, target, reportErrors && !(source.flags & 32764)); + someTypeRelatedToType(source, target, reportErrors && !(source.flags & 32764 /* Primitive */)) : + eachTypeRelatedToType(source, target, reportErrors && !(source.flags & 32764 /* Primitive */)); } else { - if (target.flags & 262144) { - result = typeRelatedToSomeType(source, target, reportErrors && !(source.flags & 32764) && !(target.flags & 32764)); + if (target.flags & 262144 /* Union */) { + result = typeRelatedToSomeType(source, target, reportErrors && !(source.flags & 32764 /* Primitive */) && !(target.flags & 32764 /* Primitive */)); } - else if (target.flags & 524288) { + else if (target.flags & 524288 /* Intersection */) { isIntersectionConstituent = true; result = typeRelatedToEachType(source, target, reportErrors); } - else if (source.flags & 524288) { - result = someTypeRelatedToType(source, target, false); + else if (source.flags & 524288 /* Intersection */) { + // Check to see if any constituents of the intersection are immediately related to the target. + // + // Don't report errors though. Checking whether a constituent is related to the source is not actually + // useful and leads to some confusing error messages. Instead it is better to let the below checks + // take care of this, or to not elaborate at all. For instance, + // + // - For an object type (such as 'C = A & B'), users are usually more interested in structural errors. + // + // - For a union type (such as '(A | B) = (C & D)'), it's better to hold onto the whole intersection + // than to report that 'D' is not assignable to 'A' or 'B'. + // + // - For a primitive type or type parameter (such as 'number = A & B') there is no point in + // breaking the intersection apart. + result = someTypeRelatedToType(source, target, /*reportErrors*/ false); } - if (!result && (source.flags & 16711680 || target.flags & 16711680)) { + if (!result && (source.flags & 16711680 /* StructuredOrInstantiable */ || target.flags & 16711680 /* StructuredOrInstantiable */)) { if (result = recursiveTypeRelatedTo(source, target, reportErrors)) { errorInfo = saveErrorInfo; } } } - if (!result && source.flags & 524288) { - var constraint = getUnionConstraintOfIntersection(source, !!(target.flags & 262144)); + if (!result && source.flags & 524288 /* Intersection */) { + // The combined constraint of an intersection type is the intersection of the constraints of + // the constituents. When an intersection type contains instantiable types with union type + // constraints, there are situations where we need to examine the combined constraint. One is + // when the target is a union type. Another is when the intersection contains types belonging + // to one of the disjoint domains. For example, given type variables T and U, each with the + // constraint 'string | number', the combined constraint of 'T & U' is 'string | number' and + // we need to check this constraint against a union on the target side. Also, given a type + // variable V constrained to 'string | number', 'V & number' has a combined constraint of + // 'string & number | number & number' which reduces to just 'number'. + var constraint = getUnionConstraintOfIntersection(source, !!(target.flags & 262144 /* Union */)); if (constraint) { if (result = isRelatedTo(constraint, target, reportErrors)) { errorInfo = saveErrorInfo; @@ -33612,18 +38845,19 @@ var ts; } isIntersectionConstituent = saveIsIntersectionConstituent; if (!result && reportErrors) { - if (source.flags & 131072 && target.flags & 32764) { + if (source.flags & 131072 /* Object */ && target.flags & 32764 /* Primitive */) { tryElaborateErrorsForPrimitivesAndObjects(source, target); } - else if (source.symbol && source.flags & 131072 && globalObjectType === source) { + else if (source.symbol && source.flags & 131072 /* Object */ && globalObjectType === source) { reportError(ts.Diagnostics.The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead); } - else if (ts.getObjectFlags(source) & 4096 && target.flags & 524288) { + else if (ts.getObjectFlags(source) & 4096 /* JsxAttributes */ && target.flags & 524288 /* Intersection */) { var targetTypes = target.types; var intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes, errorNode); var intrinsicClassAttributes = getJsxType(JsxNames.IntrinsicClassAttributes, errorNode); if (intrinsicAttributes !== errorType && intrinsicClassAttributes !== errorType && (ts.contains(targetTypes, intrinsicAttributes) || ts.contains(targetTypes, intrinsicClassAttributes))) { + // do not report top error return result; } } @@ -33634,32 +38868,32 @@ var ts; function isIdenticalTo(source, target) { var result; var flags = source.flags & target.flags; - if (flags & 131072) { - return recursiveTypeRelatedTo(source, target, false); + if (flags & 131072 /* Object */) { + return recursiveTypeRelatedTo(source, target, /*reportErrors*/ false); } - if (flags & (262144 | 524288)) { + if (flags & (262144 /* Union */ | 524288 /* Intersection */)) { if (result = eachTypeRelatedToSomeType(source, target)) { if (result &= eachTypeRelatedToSomeType(target, source)) { return result; } } } - if (flags & 1048576) { - return isRelatedTo(source.type, target.type, false); + if (flags & 1048576 /* Index */) { + return isRelatedTo(source.type, target.type, /*reportErrors*/ false); } - if (flags & 2097152) { - if (result = isRelatedTo(source.objectType, target.objectType, false)) { - if (result &= isRelatedTo(source.indexType, target.indexType, false)) { + if (flags & 2097152 /* IndexedAccess */) { + if (result = isRelatedTo(source.objectType, target.objectType, /*reportErrors*/ false)) { + if (result &= isRelatedTo(source.indexType, target.indexType, /*reportErrors*/ false)) { return result; } } } - if (flags & 4194304) { + if (flags & 4194304 /* Conditional */) { if (source.root.isDistributive === target.root.isDistributive) { - if (result = isRelatedTo(source.checkType, target.checkType, false)) { - if (result &= isRelatedTo(source.extendsType, target.extendsType, false)) { - if (result &= isRelatedTo(getTrueTypeFromConditionalType(source), getTrueTypeFromConditionalType(target), false)) { - if (result &= isRelatedTo(getFalseTypeFromConditionalType(source), getFalseTypeFromConditionalType(target), false)) { + if (result = isRelatedTo(source.checkType, target.checkType, /*reportErrors*/ false)) { + if (result &= isRelatedTo(source.extendsType, target.extendsType, /*reportErrors*/ false)) { + if (result &= isRelatedTo(getTrueTypeFromConditionalType(source), getTrueTypeFromConditionalType(target), /*reportErrors*/ false)) { + if (result &= isRelatedTo(getFalseTypeFromConditionalType(source), getFalseTypeFromConditionalType(target), /*reportErrors*/ false)) { return result; } } @@ -33667,30 +38901,37 @@ var ts; } } } - if (flags & 8388608) { - return isRelatedTo(source.substitute, target.substitute, false); + if (flags & 8388608 /* Substitution */) { + return isRelatedTo(source.substitute, target.substitute, /*reportErrors*/ false); } - return 0; + return 0 /* False */; } function hasExcessProperties(source, target, discriminant, reportErrors) { - if (maybeTypeOfKind(target, 131072) && !(ts.getObjectFlags(target) & 512)) { - var isComparingJsxAttributes = !!(ts.getObjectFlags(source) & 4096); + if (maybeTypeOfKind(target, 131072 /* Object */) && !(ts.getObjectFlags(target) & 512 /* ObjectLiteralPatternWithComputedProperties */)) { + var isComparingJsxAttributes = !!(ts.getObjectFlags(source) & 4096 /* JsxAttributes */); if ((relation === assignableRelation || relation === definitelyAssignableRelation || relation === comparableRelation) && (isTypeSubsetOf(globalObjectType, target) || (!isComparingJsxAttributes && isEmptyObjectType(target)))) { return false; } if (discriminant) { - return hasExcessProperties(source, discriminant, undefined, reportErrors); + // check excess properties against discriminant type only, not the entire union + return hasExcessProperties(source, discriminant, /*discriminant*/ undefined, reportErrors); } var _loop_7 = function (prop) { if (!isKnownProperty(target, prop.escapedName, isComparingJsxAttributes)) { if (reportErrors) { + // We know *exactly* where things went wrong when comparing the types. + // Use this property as the error node as this will be more helpful in + // reasoning about what went wrong. if (!errorNode) return { value: ts.Debug.fail() }; if (ts.isJsxAttributes(errorNode) || ts.isJsxOpeningLikeElement(errorNode)) { + // JsxAttributes has an object-literal flag and undergo same type-assignablity check as normal object-literal. + // However, using an object-literal error message will be very confusing to the users so we give different a message. reportError(ts.Diagnostics.Property_0_does_not_exist_on_type_1, symbolToString(prop), typeToString(target)); } else { + // use the property's value declaration if the property is assigned inside the literal itself var objectLiteralDeclaration_1 = source.symbol && ts.firstOrUndefined(source.symbol.declarations); var suggestion = void 0; if (prop.valueDeclaration && ts.findAncestor(prop.valueDeclaration, function (d) { return d === objectLiteralDeclaration_1; })) { @@ -33723,13 +38964,13 @@ var ts; return false; } function eachTypeRelatedToSomeType(source, target) { - var result = -1; + var result = -1 /* True */; var sourceTypes = source.types; for (var _i = 0, sourceTypes_1 = sourceTypes; _i < sourceTypes_1.length; _i++) { var sourceType = sourceTypes_1[_i]; - var related = typeRelatedToSomeType(sourceType, target, false); + var related = typeRelatedToSomeType(sourceType, target, /*reportErrors*/ false); if (!related) { - return 0; + return 0 /* False */; } result &= related; } @@ -33737,22 +38978,23 @@ var ts; } function typeRelatedToSomeType(source, target, reportErrors) { var targetTypes = target.types; - if (target.flags & 262144 && containsType(targetTypes, source)) { - return -1; + if (target.flags & 262144 /* Union */ && containsType(targetTypes, source)) { + return -1 /* True */; } for (var _i = 0, targetTypes_1 = targetTypes; _i < targetTypes_1.length; _i++) { var type = targetTypes_1[_i]; - var related = isRelatedTo(source, type, false); + var related = isRelatedTo(source, type, /*reportErrors*/ false); if (related) { return related; } } if (reportErrors) { var discriminantType = findMatchingDiscriminantType(source, target); - isRelatedTo(source, discriminantType || targetTypes[targetTypes.length - 1], true); + isRelatedTo(source, discriminantType || targetTypes[targetTypes.length - 1], /*reportErrors*/ true); } - return 0; + return 0 /* False */; } + // Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly function findMatchingDiscriminantType(source, target) { var match; var sourceProperties = getPropertiesOfObjectType(source); @@ -33767,7 +39009,7 @@ var ts; var targetType = getTypeOfPropertyOfType(type, sourceProperty.escapedName); if (targetType && isRelatedTo(sourceType, targetType)) { if (type === match) - continue; + continue; // Finding multiple fields which discriminate to the same type is fine if (match) { return undefined; } @@ -33780,13 +39022,13 @@ var ts; return match; } function typeRelatedToEachType(source, target, reportErrors) { - var result = -1; + var result = -1 /* True */; var targetTypes = target.types; for (var _i = 0, targetTypes_2 = targetTypes; _i < targetTypes_2.length; _i++) { var targetType = targetTypes_2[_i]; var related = isRelatedTo(source, targetType, reportErrors); if (!related) { - return 0; + return 0 /* False */; } result &= related; } @@ -33794,8 +39036,8 @@ var ts; } function someTypeRelatedToType(source, target, reportErrors) { var sourceTypes = source.types; - if (source.flags & 262144 && containsType(sourceTypes, target)) { - return -1; + if (source.flags & 262144 /* Union */ && containsType(sourceTypes, target)) { + return -1 /* True */; } var len = sourceTypes.length; for (var i = 0; i < len; i++) { @@ -33804,16 +39046,16 @@ var ts; return related; } } - return 0; + return 0 /* False */; } function eachTypeRelatedToType(source, target, reportErrors) { - var result = -1; + var result = -1 /* True */; var sourceTypes = source.types; for (var _i = 0, sourceTypes_2 = sourceTypes; _i < sourceTypes_2.length; _i++) { var sourceType = sourceTypes_2[_i]; var related = isRelatedTo(sourceType, target, reportErrors); if (!related) { - return 0; + return 0 /* False */; } result &= related; } @@ -33823,54 +39065,72 @@ var ts; var sources = source.typeArguments || ts.emptyArray; var targets = target.typeArguments || ts.emptyArray; if (sources.length !== targets.length && relation === identityRelation) { - return 0; + return 0 /* False */; } var length = sources.length <= targets.length ? sources.length : targets.length; - var result = -1; + var result = -1 /* True */; for (var i = 0; i < length; i++) { - var variance = i < variances.length ? variances[i] : 1; - if (variance !== 4) { + // When variance information isn't available we default to covariance. This happens + // in the process of computing variance information for recursive types and when + // comparing 'this' type arguments. + var variance = i < variances.length ? variances[i] : 1 /* Covariant */; + // We ignore arguments for independent type parameters (because they're never witnessed). + if (variance !== 4 /* Independent */) { var s = sources[i]; var t = targets[i]; - var related = -1; - if (variance === 1) { + var related = -1 /* True */; + if (variance === 1 /* Covariant */) { related = isRelatedTo(s, t, reportErrors); } - else if (variance === 2) { + else if (variance === 2 /* Contravariant */) { related = isRelatedTo(t, s, reportErrors); } - else if (variance === 3) { - related = isRelatedTo(t, s, false); + else if (variance === 3 /* Bivariant */) { + // In the bivariant case we first compare contravariantly without reporting + // errors. Then, if that doesn't succeed, we compare covariantly with error + // reporting. Thus, error elaboration will be based on the the covariant check, + // which is generally easier to reason about. + related = isRelatedTo(t, s, /*reportErrors*/ false); if (!related) { related = isRelatedTo(s, t, reportErrors); } } else { + // In the invariant case we first compare covariantly, and only when that + // succeeds do we proceed to compare contravariantly. Thus, error elaboration + // will typically be based on the covariant check. related = isRelatedTo(s, t, reportErrors); if (related) { related &= isRelatedTo(t, s, reportErrors); } } if (!related) { - return 0; + return 0 /* False */; } result &= related; } } return result; } + // Determine if possibly recursive types are related. First, check if the result is already available in the global cache. + // Second, check if we have already started a comparison of the given two types in which case we assume the result to be true. + // Third, check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are + // equal and infinitely expanding. Fourth, if we have reached a depth of 100 nested comparisons, assume we have runaway recursion + // and issue an error. Otherwise, actually compare the structure of the two types. function recursiveTypeRelatedTo(source, target, reportErrors) { if (overflow) { - return 0; + return 0 /* False */; } var id = getRelationKey(source, target, relation); var related = relation.get(id); if (related !== undefined) { - if (reportErrors && related === 2) { - relation.set(id, 3); + if (reportErrors && related === 2 /* Failed */) { + // We are elaborating errors and the cached result is an unreported failure. Record the result as a reported + // failure and continue computing the relation such that errors get reported. + relation.set(id, 3 /* FailedAndReported */); } else { - return related === 1 ? -1 : 0; + return related === 1 /* Succeeded */ ? -1 /* True */ : 0 /* False */; } } if (!maybeKeys) { @@ -33880,13 +39140,14 @@ var ts; } else { for (var i = 0; i < maybeCount; i++) { + // If source and target are already being compared, consider them related with assumptions if (id === maybeKeys[i]) { - return 1; + return 1 /* Maybe */; } } if (depth === 100) { overflow = true; - return 0; + return 0 /* False */; } } var maybeStart = maybeCount; @@ -33896,23 +39157,26 @@ var ts; targetStack[depth] = target; depth++; var saveExpandingFlags = expandingFlags; - if (!(expandingFlags & 1) && isDeeplyNestedType(source, sourceStack, depth)) - expandingFlags |= 1; - if (!(expandingFlags & 2) && isDeeplyNestedType(target, targetStack, depth)) - expandingFlags |= 2; - var result = expandingFlags !== 3 ? structuredTypeRelatedTo(source, target, reportErrors) : 1; + if (!(expandingFlags & 1 /* Source */) && isDeeplyNestedType(source, sourceStack, depth)) + expandingFlags |= 1 /* Source */; + if (!(expandingFlags & 2 /* Target */) && isDeeplyNestedType(target, targetStack, depth)) + expandingFlags |= 2 /* Target */; + var result = expandingFlags !== 3 /* Both */ ? structuredTypeRelatedTo(source, target, reportErrors) : 1 /* Maybe */; expandingFlags = saveExpandingFlags; depth--; if (result) { - if (result === -1 || depth === 0) { + if (result === -1 /* True */ || depth === 0) { + // If result is definitely true, record all maybe keys as having succeeded for (var i = maybeStart; i < maybeCount; i++) { - relation.set(maybeKeys[i], 1); + relation.set(maybeKeys[i], 1 /* Succeeded */); } maybeCount = maybeStart; } } else { - relation.set(id, reportErrors ? 3 : 2); + // A false result goes straight into global cache (when something is false under + // assumptions it will also be false without assumptions) + relation.set(id, reportErrors ? 3 /* FailedAndReported */ : 2 /* Failed */); maybeCount = maybeStart; } return result; @@ -33924,9 +39188,10 @@ var ts; var result; var originalErrorInfo; var saveErrorInfo = errorInfo; - if (target.flags & 65536) { - if (ts.getObjectFlags(source) & 32 && getConstraintTypeFromMappedType(source) === getIndexType(target)) { - if (!(getMappedTypeModifiers(source) & 4)) { + if (target.flags & 65536 /* TypeParameter */) { + // A source type { [P in keyof T]: X } is related to a target type T if X is related to T[P]. + if (ts.getObjectFlags(source) & 32 /* Mapped */ && getConstraintTypeFromMappedType(source) === getIndexType(target)) { + if (!(getMappedTypeModifiers(source) & 4 /* IncludeOptional */)) { var templateType = getTemplateTypeFromMappedType(source); var indexedAccessType = getIndexedAccessType(target, getTypeParameterFromMappedType(source)); if (result = isRelatedTo(templateType, indexedAccessType, reportErrors)) { @@ -33935,12 +39200,15 @@ var ts; } } } - else if (target.flags & 1048576) { - if (source.flags & 1048576) { - if (result = isRelatedTo(target.type, source.type, false)) { + else if (target.flags & 1048576 /* Index */) { + // A keyof S is related to a keyof T if T is related to S. + if (source.flags & 1048576 /* Index */) { + if (result = isRelatedTo(target.type, source.type, /*reportErrors*/ false)) { return result; } } + // A type S is assignable to keyof T if S is assignable to keyof C, where C is the + // simplified form of T or, if T doesn't simplify, the constraint of T. if (relation !== definitelyAssignableRelation) { var simplified = getSimplifiedType(target.type); var constraint = simplified !== target.type ? simplified : getConstraintOfType(target.type); @@ -33951,7 +39219,9 @@ var ts; } } } - else if (target.flags & 2097152) { + else if (target.flags & 2097152 /* IndexedAccess */) { + // A type S is related to a type T[K] if S is related to C, where C is the + // constraint of T[K] var constraint = getConstraintForRelation(target); if (constraint) { if (result = isRelatedTo(source, constraint, reportErrors)) { @@ -33961,13 +39231,15 @@ var ts; } } else if (isGenericMappedType(target)) { + // A source type T is related to a target type { [P in X]: T[P] } var template = getTemplateTypeFromMappedType(target); var modifiers = getMappedTypeModifiers(target); - if (!(modifiers & 8)) { - if (template.flags & 2097152 && template.objectType === source && + if (!(modifiers & 8 /* ExcludeOptional */)) { + if (template.flags & 2097152 /* IndexedAccess */ && template.objectType === source && template.indexType === getTypeParameterFromMappedType(target)) { - return -1; + return -1 /* True */; } + // A source type T is related to a target type { [P in keyof T]: X } if T[P] is related to X. if (!isGenericMappedType(source) && getConstraintTypeFromMappedType(target) === getIndexType(source)) { var indexedAccessType = getIndexedAccessType(source, getTypeParameterFromMappedType(target)); var templateType = getTemplateTypeFromMappedType(target); @@ -33978,8 +39250,9 @@ var ts; } } } - if (source.flags & 2162688) { - if (source.flags & 2097152 && target.flags & 2097152) { + if (source.flags & 2162688 /* TypeVariable */) { + if (source.flags & 2097152 /* IndexedAccess */ && target.flags & 2097152 /* IndexedAccess */) { + // A type S[K] is related to a type T[J] if S is related to T and K is related to J. if (result = isRelatedTo(source.objectType, target.objectType, reportErrors)) { result &= isRelatedTo(source.indexType, target.indexType, reportErrors); } @@ -33989,8 +39262,9 @@ var ts; } } var constraint = getConstraintForRelation(source); - if (!constraint || (source.flags & 65536 && constraint.flags & 3)) { - if (result = isRelatedTo(emptyObjectType, extractTypesOfKind(target, ~16777216))) { + if (!constraint || (source.flags & 65536 /* TypeParameter */ && constraint.flags & 3 /* AnyOrUnknown */)) { + // A type variable with no constraint is not related to the non-primitive object type. + if (result = isRelatedTo(emptyObjectType, extractTypesOfKind(target, ~16777216 /* NonPrimitive */))) { errorInfo = saveErrorInfo; return result; } @@ -34003,14 +39277,17 @@ var ts; } } } - else if (source.flags & 1048576) { + else if (source.flags & 1048576 /* Index */) { if (result = isRelatedTo(keyofConstraintType, target, reportErrors)) { errorInfo = saveErrorInfo; return result; } } - else if (source.flags & 4194304) { - if (target.flags & 4194304) { + else if (source.flags & 4194304 /* Conditional */) { + if (target.flags & 4194304 /* Conditional */) { + // Two conditional types 'T1 extends U1 ? X1 : Y1' and 'T2 extends U2 ? X2 : Y2' are related if + // one of T1 and T2 is related to the other, U1 and U2 are identical types, X1 is related to X2, + // and Y1 is related to Y2. if (isTypeIdenticalTo(source.extendsType, target.extendsType) && (isRelatedTo(source.checkType, target.checkType) || isRelatedTo(target.checkType, source.checkType))) { if (result = isRelatedTo(getTrueTypeFromConditionalType(source), getTrueTypeFromConditionalType(target), reportErrors)) { @@ -34040,42 +39317,68 @@ var ts; } } else { - if (ts.getObjectFlags(source) & 4 && ts.getObjectFlags(target) & 4 && source.target === target.target && - !(ts.getObjectFlags(source) & 8192 || ts.getObjectFlags(target) & 8192)) { + if (ts.getObjectFlags(source) & 4 /* Reference */ && ts.getObjectFlags(target) & 4 /* Reference */ && source.target === target.target && + !(ts.getObjectFlags(source) & 8192 /* MarkerType */ || ts.getObjectFlags(target) & 8192 /* MarkerType */)) { + // We have type references to the same generic type, and the type references are not marker + // type references (which are intended by be compared structurally). Obtain the variance + // information for the type parameters and relate the type arguments accordingly. var variances = getVariances(source.target); if (result = typeArgumentsRelatedTo(source, target, variances, reportErrors)) { return result; } + // The type arguments did not relate appropriately, but it may be because we have no variance + // information (in which case typeArgumentsRelatedTo defaulted to covariance for all type + // arguments). It might also be the case that the target type has a 'void' type argument for + // a covariant type parameter that is only used in return positions within the generic type + // (in which case any type argument is permitted on the source side). In those cases we proceed + // with a structural comparison. Otherwise, we know for certain the instantiations aren't + // related and we can return here. if (variances !== ts.emptyArray && !hasCovariantVoidArgument(target, variances)) { - if (!(reportErrors && ts.some(variances, function (v) { return v === 0; }))) { - return 0; + // In some cases generic types that are covariant in regular type checking mode become + // invariant in --strictFunctionTypes mode because one or more type parameters are used in + // both co- and contravariant positions. In order to make it easier to diagnose *why* such + // types are invariant, if any of the type parameters are invariant we reset the reported + // errors and instead force a structural comparison (which will include elaborations that + // reveal the reason). + if (!(reportErrors && ts.some(variances, function (v) { return v === 0 /* Invariant */; }))) { + return 0 /* False */; } + // We remember the original error information so we can restore it in case the structural + // comparison unexpectedly succeeds. This can happen when the structural comparison result + // is a Ternary.Maybe for example caused by the recursion depth limiter. originalErrorInfo = errorInfo; errorInfo = saveErrorInfo; } } - var sourceIsPrimitive = !!(source.flags & 32764); + // Even if relationship doesn't hold for unions, intersections, or generic type references, + // it may hold in a structural comparison. + var sourceIsPrimitive = !!(source.flags & 32764 /* Primitive */); if (relation !== identityRelation) { source = getApparentType(source); } - if (source.flags & (131072 | 524288) && target.flags & 131072) { + // In a check of the form X = A & B, we will have previously checked if A relates to X or B relates + // to X. Failing both of those we want to check if the aggregation of A and B's members structurally + // relates to X. Thus, we include intersection types on the source side here. + if (source.flags & (131072 /* Object */ | 524288 /* Intersection */) && target.flags & 131072 /* Object */) { + // Report structural errors only if we haven't reported any errors yet var reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo && !sourceIsPrimitive; + // An empty object type is related to any mapped type that includes a '?' modifier. if (isPartialMappedType(target) && !isGenericMappedType(source) && isEmptyObjectType(source)) { - result = -1; + result = -1 /* True */; } else if (isGenericMappedType(target)) { - result = isGenericMappedType(source) ? mappedTypeRelatedTo(source, target, reportStructuralErrors) : 0; + result = isGenericMappedType(source) ? mappedTypeRelatedTo(source, target, reportStructuralErrors) : 0 /* False */; } else { result = propertiesRelatedTo(source, target, reportStructuralErrors); if (result) { - result &= signaturesRelatedTo(source, target, 0, reportStructuralErrors); + result &= signaturesRelatedTo(source, target, 0 /* Call */, reportStructuralErrors); if (result) { - result &= signaturesRelatedTo(source, target, 1, reportStructuralErrors); + result &= signaturesRelatedTo(source, target, 1 /* Construct */, reportStructuralErrors); if (result) { - result &= indexTypesRelatedTo(source, target, 0, sourceIsPrimitive, reportStructuralErrors); + result &= indexTypesRelatedTo(source, target, 0 /* String */, sourceIsPrimitive, reportStructuralErrors); if (result) { - result &= indexTypesRelatedTo(source, target, 1, sourceIsPrimitive, reportStructuralErrors); + result &= indexTypesRelatedTo(source, target, 1 /* Number */, sourceIsPrimitive, reportStructuralErrors); } } } @@ -34090,8 +39393,11 @@ var ts; } } } - return 0; + return 0 /* False */; } + // A type [P in S]: X is related to a type [Q in T]: Y if T is related to S and X' is + // related to Y, where X' is an instantiation of X in which P is replaced with Q. Notice + // that S and T are contra-variant whereas X and Y are co-variant. function mappedTypeRelatedTo(source, target, reportErrors) { var modifiersRelated = relation === comparableRelation || (relation === identityRelation ? getMappedTypeModifiers(source) === getMappedTypeModifiers(target) : getCombinedMappedTypeOptionality(source) <= getCombinedMappedTypeOptionality(target)); @@ -34102,7 +39408,7 @@ var ts; return result_2 & isRelatedTo(instantiateType(getTemplateTypeFromMappedType(source), mapper), getTemplateTypeFromMappedType(target), reportErrors); } } - return 0; + return 0 /* False */; } function propertiesRelatedTo(source, target, reportErrors) { if (relation === identityRelation) { @@ -34114,7 +39420,7 @@ var ts; if (reportErrors) { reportError(ts.Diagnostics.Property_0_is_missing_in_type_1, symbolToString(unmatchedProperty), typeToString(source)); } - return 0; + return 0 /* False */; } if (isObjectLiteralType(target)) { for (var _i = 0, _a = getPropertiesOfType(source); _i < _a.length; _i++) { @@ -34125,16 +39431,16 @@ var ts; if (reportErrors) { reportError(ts.Diagnostics.Property_0_does_not_exist_on_type_1, symbolToString(sourceProp), typeToString(target)); } - return 0; + return 0 /* False */; } } } } - var result = -1; + var result = -1 /* True */; var properties = getPropertiesOfObjectType(target); for (var _b = 0, properties_3 = properties; _b < properties_3.length; _b++) { var targetProp = properties_3[_b]; - if (!(targetProp.flags & 4194304)) { + if (!(targetProp.flags & 4194304 /* Prototype */)) { var sourceProp = getPropertyOfType(source, targetProp.escapedName); if (sourceProp && sourceProp !== targetProp) { if (isIgnoredJsxProperty(source, sourceProp, getTypeOfSymbol(targetProp))) { @@ -34142,74 +39448,86 @@ var ts; } var sourcePropFlags = ts.getDeclarationModifierFlagsFromSymbol(sourceProp); var targetPropFlags = ts.getDeclarationModifierFlagsFromSymbol(targetProp); - if (sourcePropFlags & 8 || targetPropFlags & 8) { + if (sourcePropFlags & 8 /* Private */ || targetPropFlags & 8 /* Private */) { var hasDifferingDeclarations = sourceProp.valueDeclaration !== targetProp.valueDeclaration; - if (ts.getCheckFlags(sourceProp) & 256 && hasDifferingDeclarations) { + if (ts.getCheckFlags(sourceProp) & 256 /* ContainsPrivate */ && hasDifferingDeclarations) { if (reportErrors) { reportError(ts.Diagnostics.Property_0_has_conflicting_declarations_and_is_inaccessible_in_type_1, symbolToString(sourceProp), typeToString(source)); } - return 0; + return 0 /* False */; } if (hasDifferingDeclarations) { if (reportErrors) { - if (sourcePropFlags & 8 && targetPropFlags & 8) { + if (sourcePropFlags & 8 /* Private */ && targetPropFlags & 8 /* Private */) { reportError(ts.Diagnostics.Types_have_separate_declarations_of_a_private_property_0, symbolToString(targetProp)); } else { - reportError(ts.Diagnostics.Property_0_is_private_in_type_1_but_not_in_type_2, symbolToString(targetProp), typeToString(sourcePropFlags & 8 ? source : target), typeToString(sourcePropFlags & 8 ? target : source)); + reportError(ts.Diagnostics.Property_0_is_private_in_type_1_but_not_in_type_2, symbolToString(targetProp), typeToString(sourcePropFlags & 8 /* Private */ ? source : target), typeToString(sourcePropFlags & 8 /* Private */ ? target : source)); } } - return 0; + return 0 /* False */; } } - else if (targetPropFlags & 16) { + else if (targetPropFlags & 16 /* Protected */) { if (!isValidOverrideOf(sourceProp, targetProp)) { if (reportErrors) { reportError(ts.Diagnostics.Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2, symbolToString(targetProp), typeToString(getDeclaringClass(sourceProp) || source), typeToString(getDeclaringClass(targetProp) || target)); } - return 0; + return 0 /* False */; } } - else if (sourcePropFlags & 16) { + else if (sourcePropFlags & 16 /* Protected */) { if (reportErrors) { reportError(ts.Diagnostics.Property_0_is_protected_in_type_1_but_public_in_type_2, symbolToString(targetProp), typeToString(source), typeToString(target)); } - return 0; + return 0 /* False */; } var related = isRelatedTo(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp), reportErrors); if (!related) { if (reportErrors) { reportError(ts.Diagnostics.Types_of_property_0_are_incompatible, symbolToString(targetProp)); } - return 0; + return 0 /* False */; } result &= related; - if (relation !== comparableRelation && sourceProp.flags & 16777216 && !(targetProp.flags & 16777216)) { + // When checking for comparability, be more lenient with optional properties. + if (relation !== comparableRelation && sourceProp.flags & 16777216 /* Optional */ && !(targetProp.flags & 16777216 /* Optional */)) { + // TypeScript 1.0 spec (April 2014): 3.8.3 + // S is a subtype of a type T, and T is a supertype of S if ... + // S' and T are object types and, for each member M in T.. + // M is a property and S' contains a property N where + // if M is a required property, N is also a required property + // (M - property in T) + // (N - property in S) if (reportErrors) { reportError(ts.Diagnostics.Property_0_is_optional_in_type_1_but_required_in_type_2, symbolToString(targetProp), typeToString(source), typeToString(target)); } - return 0; + return 0 /* False */; } } } } return result; } + /** + * A type is 'weak' if it is an object type with at least one optional property + * and no required properties, call/construct signatures or index signatures + */ function isWeakType(type) { - if (type.flags & 131072) { + if (type.flags & 131072 /* Object */) { var resolved = resolveStructuredTypeMembers(type); return resolved.callSignatures.length === 0 && resolved.constructSignatures.length === 0 && !resolved.stringIndexInfo && !resolved.numberIndexInfo && resolved.properties.length > 0 && - ts.every(resolved.properties, function (p) { return !!(p.flags & 16777216); }); + ts.every(resolved.properties, function (p) { return !!(p.flags & 16777216 /* Optional */); }); } - if (type.flags & 524288) { + if (type.flags & 524288 /* Intersection */) { return ts.every(type.types, isWeakType); } return false; } function hasCommonProperties(source, target) { - var isComparingJsxAttributes = !!(ts.getObjectFlags(source) & 4096); + var isComparingJsxAttributes = !!(ts.getObjectFlags(source) & 4096 /* JsxAttributes */); for (var _i = 0, _a = getPropertiesOfType(source); _i < _a.length; _i++) { var prop = _a[_i]; if (isKnownProperty(target, prop.escapedName, isComparingJsxAttributes)) { @@ -34219,24 +39537,24 @@ var ts; return false; } function propertiesIdenticalTo(source, target) { - if (!(source.flags & 131072 && target.flags & 131072)) { - return 0; + if (!(source.flags & 131072 /* Object */ && target.flags & 131072 /* Object */)) { + return 0 /* False */; } var sourceProperties = getPropertiesOfObjectType(source); var targetProperties = getPropertiesOfObjectType(target); if (sourceProperties.length !== targetProperties.length) { - return 0; + return 0 /* False */; } - var result = -1; + var result = -1 /* True */; for (var _i = 0, sourceProperties_1 = sourceProperties; _i < sourceProperties_1.length; _i++) { var sourceProp = sourceProperties_1[_i]; var targetProp = getPropertyOfObjectType(target, sourceProp.escapedName); if (!targetProp) { - return 0; + return 0 /* False */; } var related = compareProperties(sourceProp, targetProp, isRelatedTo); if (!related) { - return 0; + return 0 /* False */; } result &= related; } @@ -34247,43 +39565,57 @@ var ts; return signaturesIdenticalTo(source, target, kind); } if (target === anyFunctionType || source === anyFunctionType) { - return -1; + return -1 /* True */; } var sourceSignatures = getSignaturesOfType(source, kind); var targetSignatures = getSignaturesOfType(target, kind); - if (kind === 1 && sourceSignatures.length && targetSignatures.length) { + if (kind === 1 /* Construct */ && sourceSignatures.length && targetSignatures.length) { if (ts.isAbstractConstructorType(source) && !ts.isAbstractConstructorType(target)) { + // An abstract constructor type is not assignable to a non-abstract constructor type + // as it would otherwise be possible to new an abstract class. Note that the assignability + // check we perform for an extends clause excludes construct signatures from the target, + // so this check never proceeds. if (reportErrors) { reportError(ts.Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type); } - return 0; + return 0 /* False */; } if (!constructorVisibilitiesAreCompatible(sourceSignatures[0], targetSignatures[0], reportErrors)) { - return 0; + return 0 /* False */; } } - var result = -1; + var result = -1 /* True */; var saveErrorInfo = errorInfo; - if (ts.getObjectFlags(source) & 64 && ts.getObjectFlags(target) & 64 && source.symbol === target.symbol) { + if (ts.getObjectFlags(source) & 64 /* Instantiated */ && ts.getObjectFlags(target) & 64 /* Instantiated */ && source.symbol === target.symbol) { + // We have instantiations of the same anonymous type (which typically will be the type of a + // method). Simply do a pairwise comparison of the signatures in the two signature lists instead + // of the much more expensive N * M comparison matrix we explore below. We erase type parameters + // as they are known to always be the same. for (var i = 0; i < targetSignatures.length; i++) { - var related = signatureRelatedTo(sourceSignatures[i], targetSignatures[i], true, reportErrors); + var related = signatureRelatedTo(sourceSignatures[i], targetSignatures[i], /*erase*/ true, reportErrors); if (!related) { - return 0; + return 0 /* False */; } result &= related; } } else if (sourceSignatures.length === 1 && targetSignatures.length === 1) { + // For simple functions (functions with a single signature) we only erase type parameters for + // the comparable relation. Otherwise, if the source signature is generic, we instantiate it + // in the context of the target signature before checking the relationship. Ideally we'd do + // this regardless of the number of signatures, but the potential costs are prohibitive due + // to the quadratic nature of the logic below. var eraseGenerics = relation === comparableRelation || !!compilerOptions.noStrictGenericChecks; result = signatureRelatedTo(sourceSignatures[0], targetSignatures[0], eraseGenerics, reportErrors); } else { outer: for (var _i = 0, targetSignatures_1 = targetSignatures; _i < targetSignatures_1.length; _i++) { var t = targetSignatures_1[_i]; + // Only elaborate errors from the first failure var shouldElaborateErrors = reportErrors; for (var _a = 0, sourceSignatures_1 = sourceSignatures; _a < sourceSignatures_1.length; _a++) { var s = sourceSignatures_1[_a]; - var related = signatureRelatedTo(s, t, true, shouldElaborateErrors); + var related = signatureRelatedTo(s, t, /*erase*/ true, shouldElaborateErrors); if (related) { result &= related; errorInfo = saveErrorInfo; @@ -34292,49 +39624,53 @@ var ts; shouldElaborateErrors = false; } if (shouldElaborateErrors) { - reportError(ts.Diagnostics.Type_0_provides_no_match_for_the_signature_1, typeToString(source), signatureToString(t, undefined, undefined, kind)); + reportError(ts.Diagnostics.Type_0_provides_no_match_for_the_signature_1, typeToString(source), signatureToString(t, /*enclosingDeclaration*/ undefined, /*flags*/ undefined, kind)); } - return 0; + return 0 /* False */; } } return result; } + /** + * See signatureAssignableTo, compareSignaturesIdentical + */ function signatureRelatedTo(source, target, erase, reportErrors) { - return compareSignaturesRelated(erase ? getErasedSignature(source) : source, erase ? getErasedSignature(target) : target, 0, false, reportErrors, reportError, isRelatedTo); + return compareSignaturesRelated(erase ? getErasedSignature(source) : source, erase ? getErasedSignature(target) : target, 0 /* None */, /*ignoreReturnTypes*/ false, reportErrors, reportError, isRelatedTo); } function signaturesIdenticalTo(source, target, kind) { var sourceSignatures = getSignaturesOfType(source, kind); var targetSignatures = getSignaturesOfType(target, kind); if (sourceSignatures.length !== targetSignatures.length) { - return 0; + return 0 /* False */; } - var result = -1; + var result = -1 /* True */; for (var i = 0; i < sourceSignatures.length; i++) { - var related = compareSignaturesIdentical(sourceSignatures[i], targetSignatures[i], false, false, false, isRelatedTo); + var related = compareSignaturesIdentical(sourceSignatures[i], targetSignatures[i], /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ false, isRelatedTo); if (!related) { - return 0; + return 0 /* False */; } result &= related; } return result; } function eachPropertyRelatedTo(source, target, kind, reportErrors) { - var result = -1; + var result = -1 /* True */; for (var _i = 0, _a = getPropertiesOfObjectType(source); _i < _a.length; _i++) { var prop = _a[_i]; - if (isIgnoredJsxProperty(source, prop, undefined)) { + if (isIgnoredJsxProperty(source, prop, /*targetMemberType*/ undefined)) { continue; } - if (prop.nameType && prop.nameType.flags & 2048) { + // Skip over symbol-named members + if (prop.nameType && prop.nameType.flags & 2048 /* UniqueESSymbol */) { continue; } - if (kind === 0 || isNumericLiteralName(prop.escapedName)) { + if (kind === 0 /* String */ || isNumericLiteralName(prop.escapedName)) { var related = isRelatedTo(getTypeOfSymbol(prop), target, reportErrors); if (!related) { if (reportErrors) { reportError(ts.Diagnostics.Property_0_is_incompatible_with_index_signature, symbolToString(prop)); } - return 0; + return 0 /* False */; } result &= related; } @@ -34353,21 +39689,24 @@ var ts; return indexTypesIdenticalTo(source, target, kind); } var targetInfo = getIndexInfoOfType(target, kind); - if (!targetInfo || targetInfo.type.flags & 3 && !sourceIsPrimitive) { - return -1; + if (!targetInfo || targetInfo.type.flags & 3 /* AnyOrUnknown */ && !sourceIsPrimitive) { + // Index signature of type any permits assignment from everything but primitives + return -1 /* True */; } var sourceInfo = getIndexInfoOfType(source, kind) || - kind === 1 && getIndexInfoOfType(source, 0); + kind === 1 /* Number */ && getIndexInfoOfType(source, 0 /* String */); if (sourceInfo) { return indexInfoRelatedTo(sourceInfo, targetInfo, reportErrors); } if (isGenericMappedType(source)) { - return (kind === 0 && isRelatedTo(getTemplateTypeFromMappedType(source), targetInfo.type, reportErrors)); + // A generic mapped type { [P in K]: T } is related to an index signature { [x: string]: U } + // if T is related to U. + return (kind === 0 /* String */ && isRelatedTo(getTemplateTypeFromMappedType(source), targetInfo.type, reportErrors)); // TODO: GH#18217 } if (isObjectTypeWithInferableIndex(source)) { - var related = -1; - if (kind === 0) { - var sourceNumberInfo = getIndexInfoOfType(source, 1); + var related = -1 /* True */; + if (kind === 0 /* String */) { + var sourceNumberInfo = getIndexInfoOfType(source, 1 /* Number */); if (sourceNumberInfo) { related = indexInfoRelatedTo(sourceNumberInfo, targetInfo, reportErrors); } @@ -34380,32 +39719,35 @@ var ts; if (reportErrors) { reportError(ts.Diagnostics.Index_signature_is_missing_in_type_0, typeToString(source)); } - return 0; + return 0 /* False */; } function indexTypesIdenticalTo(source, target, indexKind) { var targetInfo = getIndexInfoOfType(target, indexKind); var sourceInfo = getIndexInfoOfType(source, indexKind); if (!sourceInfo && !targetInfo) { - return -1; + return -1 /* True */; } if (sourceInfo && targetInfo && sourceInfo.isReadonly === targetInfo.isReadonly) { return isRelatedTo(sourceInfo.type, targetInfo.type); } - return 0; + return 0 /* False */; } function constructorVisibilitiesAreCompatible(sourceSignature, targetSignature, reportErrors) { if (!sourceSignature.declaration || !targetSignature.declaration) { return true; } - var sourceAccessibility = ts.getSelectedModifierFlags(sourceSignature.declaration, 24); - var targetAccessibility = ts.getSelectedModifierFlags(targetSignature.declaration, 24); - if (targetAccessibility === 8) { + var sourceAccessibility = ts.getSelectedModifierFlags(sourceSignature.declaration, 24 /* NonPublicAccessibilityModifier */); + var targetAccessibility = ts.getSelectedModifierFlags(targetSignature.declaration, 24 /* NonPublicAccessibilityModifier */); + // A public, protected and private signature is assignable to a private signature. + if (targetAccessibility === 8 /* Private */) { return true; } - if (targetAccessibility === 16 && sourceAccessibility !== 8) { + // A public and protected signature is assignable to a protected signature. + if (targetAccessibility === 16 /* Protected */ && sourceAccessibility !== 8 /* Private */) { return true; } - if (targetAccessibility !== 16 && !sourceAccessibility) { + // Only a public signature is assignable to public signature. + if (targetAccessibility !== 16 /* Protected */ && !sourceAccessibility) { return true; } if (reportErrors) { @@ -34414,11 +39756,19 @@ var ts; return false; } } + // Return a type reference where the source type parameter is replaced with the target marker + // type, and flag the result as a marker type reference. function getMarkerTypeReference(type, source, target) { var result = createTypeReference(type, ts.map(type.typeParameters, function (t) { return t === source ? target : t; })); - result.objectFlags |= 8192; + result.objectFlags |= 8192 /* MarkerType */; return result; } + // Return an array containing the variance of each type parameter. The variance is effectively + // a digest of the type comparisons that occur for each type argument when instantiations of the + // generic type are structurally compared. We infer the variance information by comparing + // instantiations of the generic type for type arguments with known relations. The function + // returns the emptyArray singleton if we're not in strictFunctionTypes mode or if the function + // has been invoked recursively for the given generic type. function getVariances(type) { if (!strictFunctionTypes) { return ts.emptyArray; @@ -34427,19 +39777,28 @@ var ts; var variances = type.variances; if (!variances) { if (type === globalArrayType || type === globalReadonlyArrayType) { - variances = [1]; + // Arrays are known to be covariant, no need to spend time computing this + variances = [1 /* Covariant */]; } else { + // The emptyArray singleton is used to signal a recursive invocation. type.variances = ts.emptyArray; variances = []; for (var _i = 0, typeParameters_1 = typeParameters; _i < typeParameters_1.length; _i++) { var tp = typeParameters_1[_i]; + // We first compare instantiations where the type parameter is replaced with + // marker types that have a known subtype relationship. From this we can infer + // invariance, covariance, contravariance or bivariance. var typeWithSuper = getMarkerTypeReference(type, tp, markerSuperType); var typeWithSub = getMarkerTypeReference(type, tp, markerSubType); - var variance = (isTypeAssignableTo(typeWithSub, typeWithSuper) ? 1 : 0) | - (isTypeAssignableTo(typeWithSuper, typeWithSub) ? 2 : 0); - if (variance === 3 && isTypeAssignableTo(getMarkerTypeReference(type, tp, markerOtherType), typeWithSuper)) { - variance = 4; + var variance = (isTypeAssignableTo(typeWithSub, typeWithSuper) ? 1 /* Covariant */ : 0) | + (isTypeAssignableTo(typeWithSuper, typeWithSub) ? 2 /* Contravariant */ : 0); + // If the instantiations appear to be related bivariantly it may be because the + // type parameter is independent (i.e. it isn't witnessed anywhere in the generic + // type). To determine this we compare instantiations where the type parameter is + // replaced with marker types that are known to be unrelated. + if (variance === 3 /* Bivariant */ && isTypeAssignableTo(getMarkerTypeReference(type, tp, markerOtherType), typeWithSuper)) { + variance = 4 /* Independent */; } variances.push(variance); } @@ -34448,20 +39807,26 @@ var ts; } return variances; } + // Return true if the given type reference has a 'void' type argument for a covariant type parameter. + // See comment at call in recursiveTypeRelatedTo for when this case matters. function hasCovariantVoidArgument(type, variances) { for (var i = 0; i < variances.length; i++) { - if (variances[i] === 1 && type.typeArguments[i].flags & 4096) { + if (variances[i] === 1 /* Covariant */ && type.typeArguments[i].flags & 4096 /* Void */) { return true; } } return false; } function isUnconstrainedTypeParameter(type) { - return type.flags & 65536 && !getConstraintFromTypeParameter(type); + return type.flags & 65536 /* TypeParameter */ && !getConstraintFromTypeParameter(type); } function isTypeReferenceWithGenericArguments(type) { - return !!(ts.getObjectFlags(type) & 4) && ts.some(type.typeArguments, function (t) { return isUnconstrainedTypeParameter(t) || isTypeReferenceWithGenericArguments(t); }); + return !!(ts.getObjectFlags(type) & 4 /* Reference */) && ts.some(type.typeArguments, function (t) { return isUnconstrainedTypeParameter(t) || isTypeReferenceWithGenericArguments(t); }); } + /** + * getTypeReferenceId(A) returns "111=0-12=1" + * where A.id=111 and number.id=12 + */ function getTypeReferenceId(type, typeParameters, depth) { if (depth === void 0) { depth = 0; } var result = "" + type.target.id; @@ -34484,6 +39849,10 @@ var ts; } return result; } + /** + * To improve caching, the relation key for two generic types uses the target's id plus ids of the type parameters. + * For other cases, the types ids are used. + */ function getRelationKey(source, target, relation) { if (relation === identityRelation && source.id > target.id) { var temp = source; @@ -34496,8 +39865,10 @@ var ts; } return source.id + "," + target.id; } + // Invoke the callback for each underlying property symbol of the given symbol and return the first + // value that isn't undefined. function forEachProperty(prop, callback) { - if (ts.getCheckFlags(prop) & 6) { + if (ts.getCheckFlags(prop) & 6 /* Synthetic */) { for (var _i = 0, _a = prop.containingType.types; _i < _a.length; _i++) { var t = _a[_i]; var p = getPropertyOfType(t, prop.escapedName); @@ -34510,31 +39881,43 @@ var ts; } return callback(prop); } + // Return the declaring class type of a property or undefined if property not declared in class function getDeclaringClass(prop) { - return prop.parent && prop.parent.flags & 32 ? getDeclaredTypeOfSymbol(getParentOfSymbol(prop)) : undefined; + return prop.parent && prop.parent.flags & 32 /* Class */ ? getDeclaredTypeOfSymbol(getParentOfSymbol(prop)) : undefined; } + // Return true if some underlying source property is declared in a class that derives + // from the given base class. function isPropertyInClassDerivedFrom(prop, baseClass) { return forEachProperty(prop, function (sp) { var sourceClass = getDeclaringClass(sp); return sourceClass ? hasBaseType(sourceClass, baseClass) : false; }); } + // Return true if source property is a valid override of protected parts of target property. function isValidOverrideOf(sourceProp, targetProp) { - return !forEachProperty(targetProp, function (tp) { return ts.getDeclarationModifierFlagsFromSymbol(tp) & 16 ? + return !forEachProperty(targetProp, function (tp) { return ts.getDeclarationModifierFlagsFromSymbol(tp) & 16 /* Protected */ ? !isPropertyInClassDerivedFrom(sourceProp, getDeclaringClass(tp)) : false; }); } + // Return true if the given class derives from each of the declaring classes of the protected + // constituents of the given property. function isClassDerivedFromDeclaringClasses(checkClass, prop) { - return forEachProperty(prop, function (p) { return ts.getDeclarationModifierFlagsFromSymbol(p) & 16 ? + return forEachProperty(prop, function (p) { return ts.getDeclarationModifierFlagsFromSymbol(p) & 16 /* Protected */ ? !hasBaseType(checkClass, getDeclaringClass(p)) : false; }) ? undefined : checkClass; } + // Return true if the given type is deeply nested. We consider this to be the case when structural type comparisons + // for 5 or more occurrences or instantiations of the type have been recorded on the given stack. It is possible, + // though highly unlikely, for this test to be true in a situation where a chain of instantiations is not infinitely + // expanding. Effectively, we will generate a false positive when two types are structurally equal to at least 5 + // levels, but unequal at some level beyond that. function isDeeplyNestedType(type, stack, depth) { - if (depth >= 5 && type.flags & 131072) { + // We track all object types that have an associated symbol (representing the origin of the type) + if (depth >= 5 && type.flags & 131072 /* Object */) { var symbol = type.symbol; if (symbol) { var count = 0; for (var i = 0; i < depth; i++) { var t = stack[i]; - if (t.flags & 131072 && t.symbol === symbol) { + if (t.flags & 131072 /* Object */ && t.symbol === symbol) { count++; if (count >= 5) return true; @@ -34545,38 +39928,46 @@ var ts; return false; } function isPropertyIdenticalTo(sourceProp, targetProp) { - return compareProperties(sourceProp, targetProp, compareTypesIdentical) !== 0; + return compareProperties(sourceProp, targetProp, compareTypesIdentical) !== 0 /* False */; } function compareProperties(sourceProp, targetProp, compareTypes) { + // Two members are considered identical when + // - they are public properties with identical names, optionality, and types, + // - they are private or protected properties originating in the same declaration and having identical types if (sourceProp === targetProp) { - return -1; + return -1 /* True */; } - var sourcePropAccessibility = ts.getDeclarationModifierFlagsFromSymbol(sourceProp) & 24; - var targetPropAccessibility = ts.getDeclarationModifierFlagsFromSymbol(targetProp) & 24; + var sourcePropAccessibility = ts.getDeclarationModifierFlagsFromSymbol(sourceProp) & 24 /* NonPublicAccessibilityModifier */; + var targetPropAccessibility = ts.getDeclarationModifierFlagsFromSymbol(targetProp) & 24 /* NonPublicAccessibilityModifier */; if (sourcePropAccessibility !== targetPropAccessibility) { - return 0; + return 0 /* False */; } if (sourcePropAccessibility) { if (getTargetSymbol(sourceProp) !== getTargetSymbol(targetProp)) { - return 0; + return 0 /* False */; } } else { - if ((sourceProp.flags & 16777216) !== (targetProp.flags & 16777216)) { - return 0; + if ((sourceProp.flags & 16777216 /* Optional */) !== (targetProp.flags & 16777216 /* Optional */)) { + return 0 /* False */; } } if (isReadonlySymbol(sourceProp) !== isReadonlySymbol(targetProp)) { - return 0; + return 0 /* False */; } return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp)); } function isMatchingSignature(source, target, partialMatch) { + // A source signature matches a target signature if the two signatures have the same number of required, + // optional, and rest parameters. if (source.parameters.length === target.parameters.length && source.minArgumentCount === target.minArgumentCount && source.hasRestParameter === target.hasRestParameter) { return true; } + // A source signature partially matches a target signature if the target signature has no fewer required + // parameters and no more overall parameters than the source signature (where a signature with a rest + // parameter is always considered to have more overall parameters than one without). var sourceRestCount = source.hasRestParameter ? 1 : 0; var targetRestCount = target.hasRestParameter ? 1 : 0; if (partialMatch && source.minArgumentCount <= target.minArgumentCount && (sourceRestCount > targetRestCount || @@ -34585,19 +39976,30 @@ var ts; } return false; } + /** + * See signatureRelatedTo, compareSignaturesIdentical + */ function compareSignaturesIdentical(source, target, partialMatch, ignoreThisTypes, ignoreReturnTypes, compareTypes) { + // TODO (drosen): De-duplicate code between related functions. if (source === target) { - return -1; + return -1 /* True */; } if (!(isMatchingSignature(source, target, partialMatch))) { - return 0; + return 0 /* False */; } + // Check that the two signatures have the same number of type parameters. We might consider + // also checking that any type parameter constraints match, but that would require instantiating + // the constraints with a common set of type arguments to get relatable entities in places where + // type parameters occur in the constraints. The complexity of doing that doesn't seem worthwhile, + // particularly as we're comparing erased versions of the signatures below. if (ts.length(source.typeParameters) !== ts.length(target.typeParameters)) { - return 0; + return 0 /* False */; } + // Spec 1.0 Section 3.8.3 & 3.8.4: + // M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N source = getErasedSignature(source); target = getErasedSignature(target); - var result = -1; + var result = -1 /* True */; if (!ignoreThisTypes) { var sourceThisType = getThisTypeOfSignature(source); if (sourceThisType) { @@ -34605,7 +40007,7 @@ var ts; if (targetThisType) { var related = compareTypes(sourceThisType, targetThisType); if (!related) { - return 0; + return 0 /* False */; } result &= related; } @@ -34617,7 +40019,7 @@ var ts; var t = isRestParameterIndex(target, i) ? getRestTypeOfSignature(target) : getTypeOfParameter(target.parameters[i]); var related = compareTypes(s, t); if (!related) { - return 0; + return 0 /* False */; } result &= related; } @@ -34626,12 +40028,13 @@ var ts; var targetTypePredicate = getTypePredicateOfSignature(target); result &= sourceTypePredicate !== undefined || targetTypePredicate !== undefined ? compareTypePredicatesIdentical(sourceTypePredicate, targetTypePredicate, compareTypes) + // If they're both type predicates their return types will both be `boolean`, so no need to compare those. : compareTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target)); } return result; } function compareTypePredicatesIdentical(source, target, compareTypes) { - return source === undefined || target === undefined || !typePredicateKindsMatch(source, target) ? 0 : compareTypes(source.type, target.type); + return source === undefined || target === undefined || !typePredicateKindsMatch(source, target) ? 0 /* False */ : compareTypes(source.type, target.type); } function isRestParameterIndex(signature, parameterIndex) { return signature.hasRestParameter && parameterIndex >= signature.parameters.length - 1; @@ -34650,6 +40053,9 @@ var ts; } return true; } + // When the candidate types are all literal types with the same base type, return a union + // of those literal types. Otherwise, return the leftmost type for which no type to the + // right is a supertype. function getSupertypeOrUnion(types) { return literalTypesWithSameBaseType(types) ? getUnionType(types) : @@ -34659,20 +40065,23 @@ var ts; if (!strictNullChecks) { return getSupertypeOrUnion(types); } - var primaryTypes = ts.filter(types, function (t) { return !(t.flags & 24576); }); + var primaryTypes = ts.filter(types, function (t) { return !(t.flags & 24576 /* Nullable */); }); return primaryTypes.length ? - getNullableType(getSupertypeOrUnion(primaryTypes), getFalsyFlagsOfTypes(types) & 24576) : - getUnionType(types, 2); + getNullableType(getSupertypeOrUnion(primaryTypes), getFalsyFlagsOfTypes(types) & 24576 /* Nullable */) : + getUnionType(types, 2 /* Subtype */); } + // Return the leftmost type for which no type to the right is a subtype. function getCommonSubtype(types) { return ts.reduceLeft(types, function (s, t) { return isTypeSubtypeOf(t, s) ? t : s; }); } function isArrayType(type) { - return !!(ts.getObjectFlags(type) & 4) && type.target === globalArrayType; + return !!(ts.getObjectFlags(type) & 4 /* Reference */) && type.target === globalArrayType; } function isArrayLikeType(type) { - return ts.getObjectFlags(type) & 4 && (type.target === globalArrayType || type.target === globalReadonlyArrayType) || - !(type.flags & 24576) && isTypeAssignableTo(type, anyReadonlyArrayType); + // A type is array-like if it is a reference to the global Array or global ReadonlyArray type, + // or if it is not the undefined or null type and if it is assignable to ReadonlyArray + return ts.getObjectFlags(type) & 4 /* Reference */ && (type.target === globalArrayType || type.target === globalReadonlyArrayType) || + !(type.flags & 24576 /* Nullable */) && isTypeAssignableTo(type, anyReadonlyArrayType); } function isEmptyArrayLiteralType(type) { var elementType = isArrayType(type) ? type.typeArguments[0] : undefined; @@ -34682,35 +40091,35 @@ var ts; return !!getPropertyOfType(type, "0"); } function isNeitherUnitTypeNorNever(type) { - return !(type.flags & (27072 | 32768)); + return !(type.flags & (27072 /* Unit */ | 32768 /* Never */)); } function isUnitType(type) { - return !!(type.flags & 27072); + return !!(type.flags & 27072 /* Unit */); } function isLiteralType(type) { - return type.flags & 16 ? true : - type.flags & 262144 ? type.flags & 512 ? true : ts.every(type.types, isUnitType) : + return type.flags & 16 /* Boolean */ ? true : + type.flags & 262144 /* Union */ ? type.flags & 512 /* EnumLiteral */ ? true : ts.every(type.types, isUnitType) : isUnitType(type); } function getBaseTypeOfLiteralType(type) { - return type.flags & 512 ? getBaseTypeOfEnumLiteralType(type) : - type.flags & 64 ? stringType : - type.flags & 128 ? numberType : - type.flags & 256 ? booleanType : - type.flags & 262144 ? getUnionType(ts.sameMap(type.types, getBaseTypeOfLiteralType)) : + return type.flags & 512 /* EnumLiteral */ ? getBaseTypeOfEnumLiteralType(type) : + type.flags & 64 /* StringLiteral */ ? stringType : + type.flags & 128 /* NumberLiteral */ ? numberType : + type.flags & 256 /* BooleanLiteral */ ? booleanType : + type.flags & 262144 /* Union */ ? getUnionType(ts.sameMap(type.types, getBaseTypeOfLiteralType)) : type; } function getWidenedLiteralType(type) { - return type.flags & 512 ? getBaseTypeOfEnumLiteralType(type) : - type.flags & 64 && type.flags & 33554432 ? stringType : - type.flags & 128 && type.flags & 33554432 ? numberType : - type.flags & 256 ? booleanType : - type.flags & 262144 ? getUnionType(ts.sameMap(type.types, getWidenedLiteralType)) : + return type.flags & 512 /* EnumLiteral */ ? getBaseTypeOfEnumLiteralType(type) : + type.flags & 64 /* StringLiteral */ && type.flags & 33554432 /* FreshLiteral */ ? stringType : + type.flags & 128 /* NumberLiteral */ && type.flags & 33554432 /* FreshLiteral */ ? numberType : + type.flags & 256 /* BooleanLiteral */ ? booleanType : + type.flags & 262144 /* Union */ ? getUnionType(ts.sameMap(type.types, getWidenedLiteralType)) : type; } function getWidenedUniqueESSymbolType(type) { - return type.flags & 2048 ? esSymbolType : - type.flags & 262144 ? getUnionType(ts.sameMap(type.types, getWidenedUniqueESSymbolType)) : + return type.flags & 2048 /* UniqueESSymbol */ ? esSymbolType : + type.flags & 262144 /* Union */ ? getUnionType(ts.sameMap(type.types, getWidenedUniqueESSymbolType)) : type; } function getWidenedLiteralLikeTypeForContextualType(type, contextualType) { @@ -34719,8 +40128,12 @@ var ts; } return type; } + /** + * Check if a Type was written as a tuple type literal. + * Prefer using isTupleLikeType() unless the use of `elementTypes` is required. + */ function isTupleType(type) { - return !!(ts.getObjectFlags(type) & 4 && type.target.objectFlags & 8); + return !!(ts.getObjectFlags(type) & 4 /* Reference */ && type.target.objectFlags & 8 /* Tuple */); } function getFalsyFlagsOfTypes(types) { var result = 0; @@ -34730,55 +40143,68 @@ var ts; } return result; } + // Returns the String, Number, Boolean, StringLiteral, NumberLiteral, BooleanLiteral, Void, Undefined, or Null + // flags for the string, number, boolean, "", 0, false, void, undefined, or null types respectively. Returns + // no flags for all other types (including non-falsy literal types). function getFalsyFlags(type) { - return type.flags & 262144 ? getFalsyFlagsOfTypes(type.types) : - type.flags & 64 ? type.value === "" ? 64 : 0 : - type.flags & 128 ? type.value === 0 ? 128 : 0 : - type.flags & 256 ? type === falseType ? 256 : 0 : - type.flags & 29148; + return type.flags & 262144 /* Union */ ? getFalsyFlagsOfTypes(type.types) : + type.flags & 64 /* StringLiteral */ ? type.value === "" ? 64 /* StringLiteral */ : 0 : + type.flags & 128 /* NumberLiteral */ ? type.value === 0 ? 128 /* NumberLiteral */ : 0 : + type.flags & 256 /* BooleanLiteral */ ? type === falseType ? 256 /* BooleanLiteral */ : 0 : + type.flags & 29148 /* PossiblyFalsy */; } function removeDefinitelyFalsyTypes(type) { - return getFalsyFlags(type) & 29120 ? - filterType(type, function (t) { return !(getFalsyFlags(t) & 29120); }) : + return getFalsyFlags(type) & 29120 /* DefinitelyFalsy */ ? + filterType(type, function (t) { return !(getFalsyFlags(t) & 29120 /* DefinitelyFalsy */); }) : type; } function extractDefinitelyFalsyTypes(type) { return mapType(type, getDefinitelyFalsyPartOfType); } function getDefinitelyFalsyPartOfType(type) { - return type.flags & 4 ? emptyStringType : - type.flags & 8 ? zeroType : - type.flags & 16 || type === falseType ? falseType : - type.flags & (4096 | 8192 | 16384) || - type.flags & 64 && type.value === "" || - type.flags & 128 && type.value === 0 ? type : + return type.flags & 4 /* String */ ? emptyStringType : + type.flags & 8 /* Number */ ? zeroType : + type.flags & 16 /* Boolean */ || type === falseType ? falseType : + type.flags & (4096 /* Void */ | 8192 /* Undefined */ | 16384 /* Null */) || + type.flags & 64 /* StringLiteral */ && type.value === "" || + type.flags & 128 /* NumberLiteral */ && type.value === 0 ? type : neverType; } + /** + * Add undefined or null or both to a type if they are missing. + * @param type - type to add undefined and/or null to if not present + * @param flags - Either TypeFlags.Undefined or TypeFlags.Null, or both + */ function getNullableType(type, flags) { - var missing = (flags & ~type.flags) & (8192 | 16384); + var missing = (flags & ~type.flags) & (8192 /* Undefined */ | 16384 /* Null */); return missing === 0 ? type : - missing === 8192 ? getUnionType([type, undefinedType]) : - missing === 16384 ? getUnionType([type, nullType]) : + missing === 8192 /* Undefined */ ? getUnionType([type, undefinedType]) : + missing === 16384 /* Null */ ? getUnionType([type, nullType]) : getUnionType([type, undefinedType, nullType]); } function getOptionalType(type) { ts.Debug.assert(strictNullChecks); - return type.flags & 8192 ? type : getUnionType([type, undefinedType]); + return type.flags & 8192 /* Undefined */ ? type : getUnionType([type, undefinedType]); } function getGlobalNonNullableTypeInstantiation(type) { if (!deferredGlobalNonNullableTypeAlias) { - deferredGlobalNonNullableTypeAlias = getGlobalSymbol("NonNullable", 524288, undefined) || unknownSymbol; + deferredGlobalNonNullableTypeAlias = getGlobalSymbol("NonNullable", 524288 /* TypeAlias */, /*diagnostic*/ undefined) || unknownSymbol; } + // Use NonNullable global type alias if available to improve quick info/declaration emit if (deferredGlobalNonNullableTypeAlias !== unknownSymbol) { return getTypeAliasInstantiation(deferredGlobalNonNullableTypeAlias, [type]); } - return getTypeWithFacts(type, 524288); + return getTypeWithFacts(type, 524288 /* NEUndefinedOrNull */); // Type alias unavailable, fall back to non-higherorder behavior } function getNonNullableType(type) { return strictNullChecks ? getGlobalNonNullableTypeInstantiation(type) : type; } + /** + * Return true if type was inferred from an object literal, written as an object type literal, or is the shape of a module + * with no call or construct signatures. + */ function isObjectTypeWithInferableIndex(type) { - return type.symbol && (type.symbol.flags & (4096 | 2048 | 512)) !== 0 && + return type.symbol && (type.symbol.flags & (4096 /* ObjectLiteral */ | 2048 /* TypeLiteral */ | 512 /* ValueModule */)) !== 0 && !typeHasCallOrConstructSignatures(type); } function createSymbolWithType(source, type) { @@ -34805,8 +40231,13 @@ var ts; } return members; } + /** + * If the the provided object literal is subject to the excess properties check, + * create a new that is exempt. Recursively mark object literal members as exempt. + * Leave signatures alone since they are not subject to the check. + */ function getRegularTypeOfObjectLiteral(type) { - if (!(isObjectLiteralType(type) && type.flags & 33554432)) { + if (!(isObjectLiteralType(type) && type.flags & 33554432 /* FreshLiteral */)) { return type; } var regularType = type.regularType; @@ -34816,8 +40247,8 @@ var ts; var resolved = type; var members = transformTypeOfMembers(type, getRegularTypeOfObjectLiteral); var regularNew = createAnonymousType(resolved.symbol, members, resolved.callSignatures, resolved.constructSignatures, resolved.stringIndexInfo, resolved.numberIndexInfo); - regularNew.flags = resolved.flags & ~33554432; - regularNew.objectFlags |= 128; + regularNew.flags = resolved.flags & ~33554432 /* FreshLiteral */; + regularNew.objectFlags |= 128 /* ObjectLiteral */; type.regularType = regularNew; return regularNew; } @@ -34847,7 +40278,7 @@ var ts; var names = ts.createMap(); for (var _i = 0, _a = getSiblingsOfContext(context); _i < _a.length; _i++) { var t = _a[_i]; - if (isObjectLiteralType(t) && !(ts.getObjectFlags(t) & 1024)) { + if (isObjectLiteralType(t) && !(ts.getObjectFlags(t) & 1024 /* ContainsSpread */)) { for (var _b = 0, _c = getPropertiesOfType(t); _b < _c.length; _b++) { var prop = _c[_b]; names.set(prop.escapedName, prop); @@ -34859,11 +40290,13 @@ var ts; return context.resolvedProperties; } function getWidenedProperty(prop, context) { - if (!(prop.flags & 4)) { + if (!(prop.flags & 4 /* Property */)) { + // Since get accessors already widen their return value there is no need to + // widen accessor based properties here. return prop; } var original = getTypeOfSymbol(prop); - var propContext = context && createWideningContext(context, prop.escapedName, undefined); + var propContext = context && createWideningContext(context, prop.escapedName, /*siblings*/ undefined); var widened = getWidenedTypeWithContext(original, propContext); return widened === original ? prop : createSymbolWithType(prop, widened); } @@ -34873,7 +40306,7 @@ var ts; return cached; } var result = createSymbolWithType(prop, undefinedType); - result.flags |= 16777216; + result.flags |= 16777216 /* Optional */; undefinedProperties.set(prop.escapedName, result); return result; } @@ -34891,25 +40324,28 @@ var ts; } } } - var stringIndexInfo = getIndexInfoOfType(type, 0); - var numberIndexInfo = getIndexInfoOfType(type, 1); + var stringIndexInfo = getIndexInfoOfType(type, 0 /* String */); + var numberIndexInfo = getIndexInfoOfType(type, 1 /* Number */); return createAnonymousType(type.symbol, members, ts.emptyArray, ts.emptyArray, stringIndexInfo && createIndexInfo(getWidenedType(stringIndexInfo.type), stringIndexInfo.isReadonly), numberIndexInfo && createIndexInfo(getWidenedType(numberIndexInfo.type), numberIndexInfo.isReadonly)); } function getWidenedType(type) { - return getWidenedTypeWithContext(type, undefined); + return getWidenedTypeWithContext(type, /*context*/ undefined); } function getWidenedTypeWithContext(type, context) { - if (type.flags & 402653184) { - if (type.flags & 24576) { + if (type.flags & 402653184 /* RequiresWidening */) { + if (type.flags & 24576 /* Nullable */) { return anyType; } if (isObjectLiteralType(type)) { return getWidenedTypeOfObjectLiteral(type, context); } - if (type.flags & 262144) { - var unionContext_1 = context || createWideningContext(undefined, undefined, type.types); - var widenedTypes = ts.sameMap(type.types, function (t) { return t.flags & 24576 ? t : getWidenedTypeWithContext(t, unionContext_1); }); - return getUnionType(widenedTypes, ts.some(widenedTypes, isEmptyObjectType) ? 2 : 1); + if (type.flags & 262144 /* Union */) { + var unionContext_1 = context || createWideningContext(/*parent*/ undefined, /*propertyName*/ undefined, type.types); + var widenedTypes = ts.sameMap(type.types, function (t) { return t.flags & 24576 /* Nullable */ ? t : getWidenedTypeWithContext(t, unionContext_1); }); + // Widening an empty object literal transitions from a highly restrictive type to + // a highly inclusive one. For that reason we perform subtype reduction here if the + // union includes empty object types (e.g. reducing {} | string to just {}). + return getUnionType(widenedTypes, ts.some(widenedTypes, isEmptyObjectType) ? 2 /* Subtype */ : 1 /* Literal */); } if (isArrayType(type) || isTupleType(type)) { return createTypeReference(type.target, ts.sameMap(type.typeArguments, getWidenedType)); @@ -34917,10 +40353,21 @@ var ts; } return type; } + /** + * Reports implicit any errors that occur as a result of widening 'null' and 'undefined' + * to 'any'. A call to reportWideningErrorsInType is normally accompanied by a call to + * getWidenedType. But in some cases getWidenedType is called without reporting errors + * (type argument inference is an example). + * + * The return value indicates whether an error was in fact reported. The particular circumstances + * are on a best effort basis. Currently, if the null or undefined that causes widening is inside + * an object literal property (arbitrarily deeply), this function reports an error. If no error is + * reported, reportImplicitAnyError is a suitable fallback to report a general error. + */ function reportWideningErrorsInType(type) { var errorReported = false; - if (type.flags & 134217728) { - if (type.flags & 262144) { + if (type.flags & 134217728 /* ContainsWideningType */) { + if (type.flags & 262144 /* Union */) { if (ts.some(type.types, isEmptyObjectType)) { errorReported = true; } @@ -34945,7 +40392,7 @@ var ts; for (var _d = 0, _e = getPropertiesOfObjectType(type); _d < _e.length; _d++) { var p = _e[_d]; var t = getTypeOfSymbol(p); - if (t.flags & 134217728) { + if (t.flags & 134217728 /* ContainsWideningType */) { if (!reportWideningErrorsInType(t)) { error(p.valueDeclaration, ts.Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, symbolToString(p), typeToString(getWidenedType(t))); } @@ -34960,33 +40407,33 @@ var ts; var typeAsString = typeToString(getWidenedType(type)); var diagnostic; switch (declaration.kind) { - case 200: - case 152: - case 151: + case 200 /* BinaryExpression */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: diagnostic = ts.Diagnostics.Member_0_implicitly_has_an_1_type; break; - case 149: + case 149 /* Parameter */: diagnostic = declaration.dotDotDotToken ? ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type : ts.Diagnostics.Parameter_0_implicitly_has_an_1_type; break; - case 182: + case 182 /* BindingElement */: diagnostic = ts.Diagnostics.Binding_element_0_implicitly_has_an_1_type; break; - case 234: - case 154: - case 153: - case 156: - case 157: - case 192: - case 193: + case 234 /* FunctionDeclaration */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: if (!declaration.name) { error(declaration, ts.Diagnostics.Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeAsString); return; } diagnostic = ts.Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type; break; - case 177: + case 177 /* MappedType */: error(declaration, ts.Diagnostics.Mapped_object_type_implicitly_has_an_any_template_type); return; default: @@ -34995,7 +40442,8 @@ var ts; error(declaration, diagnostic, ts.declarationNameToString(ts.getNameOfDeclaration(declaration)), typeAsString); } function reportErrorsFromWidening(declaration, type) { - if (produceDiagnostics && noImplicitAny && type.flags & 134217728) { + if (produceDiagnostics && noImplicitAny && type.flags & 134217728 /* ContainsWideningType */) { + // Report implicit any error within type if possible, otherwise report error on declaration if (!reportWideningErrorsInType(type)) { reportImplicitAnyError(declaration, type); } @@ -35062,13 +40510,16 @@ var ts; isFixed: inference.isFixed }; } + // Return true if the given type could possibly reference a type parameter for which + // we perform type inference (i.e. a type parameter of a generic function). We cache + // results for union and intersection types for performance reasons. function couldContainTypeVariables(type) { var objectFlags = ts.getObjectFlags(type); - return !!(type.flags & 15794176 || - objectFlags & 4 && ts.forEach(type.typeArguments, couldContainTypeVariables) || - objectFlags & 16 && type.symbol && type.symbol.flags & (16 | 8192 | 2048 | 32) || - objectFlags & 32 || - type.flags & 786432 && couldUnionOrIntersectionContainTypeVariables(type)); + return !!(type.flags & 15794176 /* Instantiable */ || + objectFlags & 4 /* Reference */ && ts.forEach(type.typeArguments, couldContainTypeVariables) || + objectFlags & 16 /* Anonymous */ && type.symbol && type.symbol.flags & (16 /* Function */ | 8192 /* Method */ | 2048 /* TypeLiteral */ | 32 /* Class */) || + objectFlags & 32 /* Mapped */ || + type.flags & 786432 /* UnionOrIntersection */ && couldUnionOrIntersectionContainTypeVariables(type)); } function couldUnionOrIntersectionContainTypeVariables(type) { if (type.couldContainTypeVariables === undefined) { @@ -35077,16 +40528,17 @@ var ts; return type.couldContainTypeVariables; } function isTypeParameterAtTopLevel(type, typeParameter) { - return type === typeParameter || !!(type.flags & 786432) && ts.some(type.types, function (t) { return isTypeParameterAtTopLevel(t, typeParameter); }); + return type === typeParameter || !!(type.flags & 786432 /* UnionOrIntersection */) && ts.some(type.types, function (t) { return isTypeParameterAtTopLevel(t, typeParameter); }); } + /** Create an object with properties named in the string literal type. Every property has type `any` */ function createEmptyObjectTypeFromStringLiteral(type) { var members = ts.createSymbolTable(); forEachType(type, function (t) { - if (!(t.flags & 64)) { + if (!(t.flags & 64 /* StringLiteral */)) { return; } var name = ts.escapeLeadingUnderscores(t.value); - var literalProp = createSymbol(4, name); + var literalProp = createSymbol(4 /* Property */, name); literalProp.type = anyType; if (t.symbol) { literalProp.declarations = t.symbol.declarations; @@ -35094,9 +40546,15 @@ var ts; } members.set(name, literalProp); }); - var indexInfo = type.flags & 4 ? createIndexInfo(emptyObjectType, false) : undefined; + var indexInfo = type.flags & 4 /* String */ ? createIndexInfo(emptyObjectType, /*isReadonly*/ false) : undefined; return createAnonymousType(undefined, members, ts.emptyArray, ts.emptyArray, indexInfo, undefined); } + /** + * Infer a suitable input type for a homomorphic mapped type { [P in keyof T]: X }. We construct + * an object type with the same set of properties as the source type, where the type of each + * property is computed by inferring from the source property type to X for the type + * variable T[P] (i.e. we treat the type T[P] as the type variable we're inferring for). + */ function inferTypeForHomomorphicMappedType(source, target) { var key = source.id + "," + target.id; if (reverseMappedCache.has(key)) { @@ -35109,16 +40567,18 @@ var ts; } function createReverseMappedType(source, target) { var properties = getPropertiesOfType(source); - if (properties.length === 0 && !getIndexInfoOfType(source, 0)) { + if (properties.length === 0 && !getIndexInfoOfType(source, 0 /* String */)) { return undefined; } + // If any property contains context sensitive functions that have been skipped, the source type + // is incomplete and we can't infer a meaningful input type. for (var _i = 0, properties_4 = properties; _i < properties_4.length; _i++) { var prop = properties_4[_i]; - if (getTypeOfSymbol(prop).flags & 536870912) { + if (getTypeOfSymbol(prop).flags & 536870912 /* ContainsAnyFunctionType */) { return undefined; } } - var reversed = createObjectType(2048 | 16, undefined); + var reversed = createObjectType(2048 /* ReverseMapped */ | 16 /* Anonymous */, /*symbol*/ undefined); reversed.source = source; reversed.mappedType = target; return reversed; @@ -35134,10 +40594,10 @@ var ts; return getTypeFromInference(inference); } function getUnmatchedProperty(source, target, requireOptionalProperties) { - var properties = target.flags & 524288 ? getPropertiesOfUnionOrIntersectionType(target) : getPropertiesOfObjectType(target); + var properties = target.flags & 524288 /* Intersection */ ? getPropertiesOfUnionOrIntersectionType(target) : getPropertiesOfObjectType(target); for (var _i = 0, properties_5 = properties; _i < properties_5.length; _i++) { var targetProp = properties_5[_i]; - if (requireOptionalProperties || !(targetProp.flags & 16777216)) { + if (requireOptionalProperties || !(targetProp.flags & 16777216 /* Optional */)) { var sourceProp = getPropertyOfType(source, targetProp.escapedName); if (!sourceProp) { return targetProp; @@ -35147,11 +40607,13 @@ var ts; return undefined; } function typesDefinitelyUnrelated(source, target) { + // Two tuple types with different arity are definitely unrelated. + // Two object types that each have a property that is unmatched in the other are definitely unrelated. return isTupleType(source) && isTupleType(target) && getTypeReferenceArity(source) !== getTypeReferenceArity(target) || - !!getUnmatchedProperty(source, target, false) && !!getUnmatchedProperty(target, source, false); + !!getUnmatchedProperty(source, target, /*requireOptionalProperties*/ false) && !!getUnmatchedProperty(target, source, /*requireOptionalProperties*/ false); } function getTypeFromInference(inference) { - return inference.candidates ? getUnionType(inference.candidates, 2) : + return inference.candidates ? getUnionType(inference.candidates, 2 /* Subtype */) : inference.contraCandidates ? getIntersectionType(inference.contraCandidates) : emptyObjectType; } @@ -35167,6 +40629,9 @@ var ts; return; } if (source === wildcardType) { + // We are inferring from an 'any' type. We want to infer this type for every type parameter + // referenced in the target type, so we record it as the propagation type and infer from the + // target to itself. Then, as we find candidates we substitute the propagation type. var savePropagationType = propagationType; propagationType = source; inferFromTypes(target, target); @@ -35174,6 +40639,8 @@ var ts; return; } if (source.aliasSymbol && source.aliasTypeArguments && source.aliasSymbol === target.aliasSymbol) { + // Source and target are types originating in the same generic type alias declaration. + // Simply infer from source type arguments to target type arguments. var sourceTypes = source.aliasTypeArguments; var targetTypes = target.aliasTypeArguments; for (var i = 0; i < sourceTypes.length; i++) { @@ -35181,8 +40648,10 @@ var ts; } return; } - if (source.flags & 262144 && target.flags & 262144 && !(source.flags & 512 && target.flags & 512) || - source.flags & 524288 && target.flags & 524288) { + if (source.flags & 262144 /* Union */ && target.flags & 262144 /* Union */ && !(source.flags & 512 /* EnumLiteral */ && target.flags & 512 /* EnumLiteral */) || + source.flags & 524288 /* Intersection */ && target.flags & 524288 /* Intersection */) { + // Source and target are both unions or both intersections. If source and target + // are the same type, just relate each constituent type to itself. if (source === target) { for (var _i = 0, _a = source.types; _i < _a.length; _i++) { var t = _a[_i]; @@ -35190,6 +40659,12 @@ var ts; } return; } + // Find each source constituent type that has an identically matching target constituent + // type, and for each such type infer from the type to itself. When inferring from a + // type to itself we effectively find all type parameter occurrences within that type + // and infer themselves as their type arguments. We have special handling for numeric + // and string literals because the number and string types are not represented as unions + // of all their possible values. var matchingTypes = void 0; for (var _b = 0, _c = source.types; _b < _c.length; _b++) { var t = _c[_b]; @@ -35197,20 +40672,30 @@ var ts; (matchingTypes || (matchingTypes = [])).push(t); inferFromTypes(t, t); } - else if (t.flags & (128 | 64)) { + else if (t.flags & (128 /* NumberLiteral */ | 64 /* StringLiteral */)) { var b = getBaseTypeOfLiteralType(t); if (typeIdenticalToSomeType(b, target.types)) { (matchingTypes || (matchingTypes = [])).push(t, b); } } } + // Next, to improve the quality of inferences, reduce the source and target types by + // removing the identically matched constituents. For example, when inferring from + // 'string | string[]' to 'string | T' we reduce the types to 'string[]' and 'T'. if (matchingTypes) { source = removeTypesFromUnionOrIntersection(source, matchingTypes); target = removeTypesFromUnionOrIntersection(target, matchingTypes); } } - if (target.flags & 2162688) { - if (source.flags & 536870912 || source === silentNeverType) { + if (target.flags & 2162688 /* TypeVariable */) { + // If target is a type parameter, make an inference, unless the source type contains + // the anyFunctionType (the wildcard type that's used to avoid contextually typing functions). + // Because the anyFunctionType is internal, it should not be exposed to the user by adding + // it as an inference candidate. Hopefully, a better candidate will come along that does + // not contain anyFunctionType when we come back to this argument for its second round + // of inference. Also, we exclude inferences for silentNeverType (which is used as a wildcard + // when constructing types from type parameters that had no inference candidates). + if (source.flags & 536870912 /* ContainsAnyFunctionType */ || source === silentNeverType) { return; } var inference = getInferenceInfoForType(target); @@ -35230,20 +40715,21 @@ var ts; inference.candidates = ts.append(inference.candidates, candidate); } } - if (!(priority & 8) && target.flags & 65536 && !isTypeParameterAtTopLevel(originalTarget, target)) { + if (!(priority & 8 /* ReturnType */) && target.flags & 65536 /* TypeParameter */ && !isTypeParameterAtTopLevel(originalTarget, target)) { inference.topLevel = false; } } return; } } - if (ts.getObjectFlags(source) & 4 && ts.getObjectFlags(target) & 4 && source.target === target.target) { + if (ts.getObjectFlags(source) & 4 /* Reference */ && ts.getObjectFlags(target) & 4 /* Reference */ && source.target === target.target) { + // If source and target are references to the same generic type, infer from type arguments var sourceTypes = source.typeArguments || ts.emptyArray; var targetTypes = target.typeArguments || ts.emptyArray; var count = sourceTypes.length < targetTypes.length ? sourceTypes.length : targetTypes.length; var variances = getVariances(source.target); for (var i = 0; i < count; i++) { - if (i < variances.length && variances[i] === 2) { + if (i < variances.length && variances[i] === 2 /* Contravariant */) { inferFromContravariantTypes(sourceTypes[i], targetTypes[i]); } else { @@ -35251,34 +40737,35 @@ var ts; } } } - else if (source.flags & 1048576 && target.flags & 1048576) { + else if (source.flags & 1048576 /* Index */ && target.flags & 1048576 /* Index */) { contravariant = !contravariant; inferFromTypes(source.type, target.type); contravariant = !contravariant; } - else if ((isLiteralType(source) || source.flags & 4) && target.flags & 1048576) { + else if ((isLiteralType(source) || source.flags & 4 /* String */) && target.flags & 1048576 /* Index */) { var empty = createEmptyObjectTypeFromStringLiteral(source); contravariant = !contravariant; var savePriority = priority; - priority |= 16; + priority |= 16 /* LiteralKeyof */; inferFromTypes(empty, target.type); priority = savePriority; contravariant = !contravariant; } - else if (source.flags & 2097152 && target.flags & 2097152) { + else if (source.flags & 2097152 /* IndexedAccess */ && target.flags & 2097152 /* IndexedAccess */) { inferFromTypes(source.objectType, target.objectType); inferFromTypes(source.indexType, target.indexType); } - else if (source.flags & 4194304 && target.flags & 4194304) { + else if (source.flags & 4194304 /* Conditional */ && target.flags & 4194304 /* Conditional */) { inferFromTypes(source.checkType, target.checkType); inferFromTypes(source.extendsType, target.extendsType); inferFromTypes(getTrueTypeFromConditionalType(source), getTrueTypeFromConditionalType(target)); inferFromTypes(getFalseTypeFromConditionalType(source), getFalseTypeFromConditionalType(target)); } - else if (target.flags & 786432) { + else if (target.flags & 786432 /* UnionOrIntersection */) { var targetTypes = target.types; var typeVariableCount = 0; var typeVariable = void 0; + // First infer to each type in union or intersection that isn't a type variable for (var _d = 0, targetTypes_3 = targetTypes; _d < targetTypes_3.length; _d++) { var t = targetTypes_3[_d]; if (getInferenceInfoForType(t)) { @@ -35289,14 +40776,18 @@ var ts; inferFromTypes(source, t); } } + // Next, if target containings a single naked type variable, make a secondary inference to that type + // variable. This gives meaningful results for union types in co-variant positions and intersection + // types in contra-variant positions (such as callback parameters). if (typeVariableCount === 1) { var savePriority = priority; - priority |= 1; + priority |= 1 /* NakedTypeVariable */; inferFromTypes(source, typeVariable); priority = savePriority; } } - else if (source.flags & 262144) { + else if (source.flags & 262144 /* Union */) { + // Source is a union or intersection type, infer from each constituent type var sourceTypes = source.types; for (var _e = 0, sourceTypes_3 = sourceTypes; _e < sourceTypes_3.length; _e++) { var sourceType = sourceTypes_3[_e]; @@ -35304,17 +40795,21 @@ var ts; } } else { - if (!(priority & 32 && source.flags & (524288 | 15794176))) { + if (!(priority & 32 /* NoConstraints */ && source.flags & (524288 /* Intersection */ | 15794176 /* Instantiable */))) { source = getApparentType(source); } - if (source.flags & (131072 | 524288)) { + if (source.flags & (131072 /* Object */ | 524288 /* Intersection */)) { var key = source.id + "," + target.id; if (visited && visited.get(key)) { return; } (visited || (visited = ts.createMap())).set(key, true); - var isNonConstructorObject = target.flags & 131072 && - !(ts.getObjectFlags(target) & 16 && target.symbol && target.symbol.flags & 32); + // If we are already processing another target type with the same associated symbol (such as + // an instantiation of the same generic type), we do not explore this target as it would yield + // no further inferences. We exclude the static side of classes from this check since it shares + // its symbol with the instance side which would lead to false positives. + var isNonConstructorObject = target.flags & 131072 /* Object */ && + !(ts.getObjectFlags(target) & 16 /* Anonymous */ && target.symbol && target.symbol.flags & 32 /* Class */); var symbol = isNonConstructorObject ? target.symbol : undefined; if (symbol) { if (ts.contains(symbolStack, symbol)) { @@ -35331,7 +40826,7 @@ var ts; } } function inferFromContravariantTypes(source, target) { - if (strictFunctionTypes || priority & 64) { + if (strictFunctionTypes || priority & 64 /* AlwaysStrict */) { contravariant = !contravariant; inferFromTypes(source, target); contravariant = !contravariant; @@ -35341,7 +40836,7 @@ var ts; } } function getInferenceInfoForType(type) { - if (type.flags & 2162688) { + if (type.flags & 2162688 /* TypeVariable */) { for (var _i = 0, inferences_1 = inferences; _i < inferences_1.length; _i++) { var inference = inferences_1[_i]; if (type === inference.typeParameter) { @@ -35353,37 +40848,46 @@ var ts; } function inferFromObjectTypes(source, target) { if (isGenericMappedType(source) && isGenericMappedType(target)) { + // The source and target types are generic types { [P in S]: X } and { [P in T]: Y }, so we infer + // from S to T and from X to Y. inferFromTypes(getConstraintTypeFromMappedType(source), getConstraintTypeFromMappedType(target)); inferFromTypes(getTemplateTypeFromMappedType(source), getTemplateTypeFromMappedType(target)); } - if (ts.getObjectFlags(target) & 32) { + if (ts.getObjectFlags(target) & 32 /* Mapped */) { var constraintType = getConstraintTypeFromMappedType(target); - if (constraintType.flags & 1048576) { + if (constraintType.flags & 1048576 /* Index */) { + // We're inferring from some source type S to a homomorphic mapped type { [P in keyof T]: X }, + // where T is a type variable. Use inferTypeForHomomorphicMappedType to infer a suitable source + // type and then make a secondary inference from that type to T. We make a secondary inference + // such that direct inferences to T get priority over inferences to Partial, for example. var inference = getInferenceInfoForType(constraintType.type); if (inference && !inference.isFixed) { var inferredType = inferTypeForHomomorphicMappedType(source, target); if (inferredType) { var savePriority = priority; - priority |= 2; + priority |= 2 /* HomomorphicMappedType */; inferFromTypes(inferredType, inference.typeParameter); priority = savePriority; } } return; } - if (constraintType.flags & 65536) { + if (constraintType.flags & 65536 /* TypeParameter */) { + // We're inferring from some source type S to a mapped type { [P in T]: X }, where T is a type + // parameter. Infer from 'keyof S' to T and infer from a union of each property type in S to X. var savePriority = priority; - priority |= 4; + priority |= 4 /* MappedTypeConstraint */; inferFromTypes(getIndexType(source), constraintType); priority = savePriority; inferFromTypes(getUnionType(ts.map(getPropertiesOfType(source), getTypeOfSymbol)), getTemplateTypeFromMappedType(target)); return; } } + // Infer from the members of source and target only if the two types are possibly related if (!typesDefinitelyUnrelated(source, target)) { inferFromProperties(source, target); - inferFromSignatures(source, target, 0); - inferFromSignatures(source, target, 1); + inferFromSignatures(source, target, 0 /* Call */); + inferFromSignatures(source, target, 1 /* Construct */); inferFromIndexTypes(source, target); } } @@ -35419,19 +40923,19 @@ var ts; } } function inferFromIndexTypes(source, target) { - var targetStringIndexType = getIndexTypeOfType(target, 0); + var targetStringIndexType = getIndexTypeOfType(target, 0 /* String */); if (targetStringIndexType) { - var sourceIndexType = getIndexTypeOfType(source, 0) || - getImplicitIndexTypeOfType(source, 0); + var sourceIndexType = getIndexTypeOfType(source, 0 /* String */) || + getImplicitIndexTypeOfType(source, 0 /* String */); if (sourceIndexType) { inferFromTypes(sourceIndexType, targetStringIndexType); } } - var targetNumberIndexType = getIndexTypeOfType(target, 1); + var targetNumberIndexType = getIndexTypeOfType(target, 1 /* Number */); if (targetNumberIndexType) { - var sourceIndexType = getIndexTypeOfType(source, 1) || - getIndexTypeOfType(source, 0) || - getImplicitIndexTypeOfType(source, 1); + var sourceIndexType = getIndexTypeOfType(source, 1 /* Number */) || + getIndexTypeOfType(source, 0 /* String */) || + getImplicitIndexTypeOfType(source, 1 /* Number */); if (sourceIndexType) { inferFromTypes(sourceIndexType, targetNumberIndexType); } @@ -35447,6 +40951,10 @@ var ts; } return false; } + /** + * Return a new union or intersection type computed by removing a given set of types + * from a given union or intersection type. + */ function removeTypesFromUnionOrIntersection(type, typesToRemove) { var reducedTypes = []; for (var _i = 0, _a = type.types; _i < _a.length; _i++) { @@ -35455,38 +40963,46 @@ var ts; reducedTypes.push(t); } } - return type.flags & 262144 ? getUnionType(reducedTypes) : getIntersectionType(reducedTypes); + return type.flags & 262144 /* Union */ ? getUnionType(reducedTypes) : getIntersectionType(reducedTypes); } function hasPrimitiveConstraint(type) { var constraint = getConstraintOfTypeParameter(type); - return !!constraint && maybeTypeOfKind(constraint, 32764 | 1048576); + return !!constraint && maybeTypeOfKind(constraint, 32764 /* Primitive */ | 1048576 /* Index */); } function isObjectLiteralType(type) { - return !!(ts.getObjectFlags(type) & 128); + return !!(ts.getObjectFlags(type) & 128 /* ObjectLiteral */); } function widenObjectLiteralCandidates(candidates) { if (candidates.length > 1) { var objectLiterals = ts.filter(candidates, isObjectLiteralType); if (objectLiterals.length) { - var objectLiteralsType = getWidenedType(getUnionType(objectLiterals, 2)); + var objectLiteralsType = getWidenedType(getUnionType(objectLiterals, 2 /* Subtype */)); return ts.concatenate(ts.filter(candidates, function (t) { return !isObjectLiteralType(t); }), [objectLiteralsType]); } } return candidates; } function getContravariantInference(inference) { - return inference.priority & 28 ? getIntersectionType(inference.contraCandidates) : getCommonSubtype(inference.contraCandidates); + return inference.priority & 28 /* PriorityImpliesCombination */ ? getIntersectionType(inference.contraCandidates) : getCommonSubtype(inference.contraCandidates); } function getCovariantInference(inference, context, signature) { + // Extract all object literal types and replace them with a single widened and normalized type. var candidates = widenObjectLiteralCandidates(inference.candidates); + // We widen inferred literal types if + // all inferences were made to top-level occurrences of the type parameter, and + // the type parameter has no constraint or its constraint includes no primitive or literal types, and + // the type parameter was fixed during inference or does not occur at top-level in the return type. var primitiveConstraint = hasPrimitiveConstraint(inference.typeParameter); var widenLiteralTypes = !primitiveConstraint && inference.topLevel && (inference.isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), inference.typeParameter)); var baseCandidates = primitiveConstraint ? ts.sameMap(candidates, getRegularTypeOfLiteralType) : widenLiteralTypes ? ts.sameMap(candidates, getWidenedLiteralType) : candidates; - var unwidenedType = context.flags & 1 || inference.priority & 28 ? - getUnionType(baseCandidates, 2) : + // If all inferences were made from contravariant positions, infer a common subtype. Otherwise, if + // union types were requested or if all inferences were made from the return type position, infer a + // union type. Otherwise, infer a common supertype. + var unwidenedType = context.flags & 1 /* InferUnionTypes */ || inference.priority & 28 /* PriorityImpliesCombination */ ? + getUnionType(baseCandidates, 2 /* Subtype */) : getCommonSupertype(baseCandidates); return getWidenedType(unwidenedType); } @@ -35498,23 +41014,34 @@ var ts; if (signature) { if (inference.candidates) { inferredType = getCovariantInference(inference, context, signature); - if (inferredType.flags & 32768 && inference.contraCandidates) { + // If we have inferred 'never' but have contravariant candidates. To get a more specific type we + // infer from the contravariant candidates instead. + if (inferredType.flags & 32768 /* Never */ && inference.contraCandidates) { inferredType = getContravariantInference(inference); } } else if (inference.contraCandidates) { + // We only have contravariant inferences, infer the best common subtype of those inferredType = getContravariantInference(inference); } - else if (context.flags & 2) { + else if (context.flags & 2 /* NoDefault */) { + // We use silentNeverType as the wildcard that signals no inferences. inferredType = silentNeverType; } else { + // Infer either the default or the empty object type when no inferences were + // made. It is important to remember that in this case, inference still + // succeeds, meaning there is no error for not having inference candidates. An + // inference error only occurs when there are *conflicting* candidates, i.e. + // candidates with no common supertype. var defaultType = getDefaultFromTypeParameter(inference.typeParameter); if (defaultType) { + // Instantiate the default type. Any forward reference to a type + // parameter should be instantiated to the empty object type. inferredType = instantiateType(defaultType, combineTypeMappers(createBackreferenceMapper(context.signature.typeParameters, index), context)); } else { - inferredType = getDefaultTypeArgumentType(!!(context.flags & 4)); + inferredType = getDefaultTypeArgumentType(!!(context.flags & 4 /* AnyDefault */)); } } } @@ -35542,32 +41069,43 @@ var ts; } return result; } + // EXPRESSION TYPE CHECKING function getResolvedSymbol(node) { var links = getNodeLinks(node); if (!links.resolvedSymbol) { links.resolvedSymbol = !ts.nodeIsMissing(node) && - resolveName(node, node.escapedText, 67216319 | 1048576, ts.Diagnostics.Cannot_find_name_0, node, !ts.isWriteOnlyAccess(node), false, ts.Diagnostics.Cannot_find_name_0_Did_you_mean_1) || unknownSymbol; + resolveName(node, node.escapedText, 67216319 /* Value */ | 1048576 /* ExportValue */, ts.Diagnostics.Cannot_find_name_0, node, !ts.isWriteOnlyAccess(node), + /*excludeGlobals*/ false, ts.Diagnostics.Cannot_find_name_0_Did_you_mean_1) || unknownSymbol; } return links.resolvedSymbol; } function isInTypeQuery(node) { - return !!ts.findAncestor(node, function (n) { return n.kind === 165 ? true : n.kind === 71 || n.kind === 146 ? false : "quit"; }); + // TypeScript 1.0 spec (April 2014): 3.6.3 + // A type query consists of the keyword typeof followed by an expression. + // The expression is restricted to a single identifier or a sequence of identifiers separated by periods + return !!ts.findAncestor(node, function (n) { return n.kind === 165 /* TypeQuery */ ? true : n.kind === 71 /* Identifier */ || n.kind === 146 /* QualifiedName */ ? false : "quit"; }); } + // Return the flow cache key for a "dotted name" (i.e. a sequence of identifiers + // separated by dots). The key consists of the id of the symbol referenced by the + // leftmost identifier followed by zero or more property names separated by dots. + // The result is undefined if the reference isn't a dotted name. We prefix nodes + // occurring in an apparent type position with '@' because the control flow type + // of such nodes may be based on the apparent type instead of the declared type. function getFlowCacheKey(node) { - if (node.kind === 71) { + if (node.kind === 71 /* Identifier */) { var symbol = getResolvedSymbol(node); return symbol !== unknownSymbol ? (isConstraintPosition(node) ? "@" : "") + getSymbolId(symbol) : undefined; } - if (node.kind === 99) { + if (node.kind === 99 /* ThisKeyword */) { return "0"; } - if (node.kind === 185) { + if (node.kind === 185 /* PropertyAccessExpression */) { var key = getFlowCacheKey(node.expression); return key && key + "." + ts.idText(node.name); } - if (node.kind === 182) { + if (node.kind === 182 /* BindingElement */) { var container = node.parent.parent; - var key = container.kind === 182 ? getFlowCacheKey(container) : (container.initializer && getFlowCacheKey(container.initializer)); + var key = container.kind === 182 /* BindingElement */ ? getFlowCacheKey(container) : (container.initializer && getFlowCacheKey(container.initializer)); var text = getBindingElementNameText(node); var result = key && text && (key + "." + text); return result; @@ -35576,17 +41114,18 @@ var ts; } function getBindingElementNameText(element) { var parent = element.parent; - if (parent.kind === 180) { + if (parent.kind === 180 /* ObjectBindingPattern */) { var name = element.propertyName || element.name; switch (name.kind) { - case 71: + case 71 /* Identifier */: return ts.idText(name); - case 147: + case 147 /* ComputedPropertyName */: return ts.isStringOrNumericLiteral(name.expression) ? name.expression.text : undefined; - case 9: - case 8: + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: return name.text; default: + // Per types, array and object binding patterns remain, however they should never be present if propertyName is not defined ts.Debug.fail("Unexpected name kind for binding element name"); } } @@ -35596,28 +41135,28 @@ var ts; } function isMatchingReference(source, target) { switch (source.kind) { - case 71: - return target.kind === 71 && getResolvedSymbol(source) === getResolvedSymbol(target) || - (target.kind === 232 || target.kind === 182) && + case 71 /* Identifier */: + return target.kind === 71 /* Identifier */ && getResolvedSymbol(source) === getResolvedSymbol(target) || + (target.kind === 232 /* VariableDeclaration */ || target.kind === 182 /* BindingElement */) && getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(source)) === getSymbolOfNode(target); - case 99: - return target.kind === 99; - case 97: - return target.kind === 97; - case 185: - return target.kind === 185 && + case 99 /* ThisKeyword */: + return target.kind === 99 /* ThisKeyword */; + case 97 /* SuperKeyword */: + return target.kind === 97 /* SuperKeyword */; + case 185 /* PropertyAccessExpression */: + return target.kind === 185 /* PropertyAccessExpression */ && source.name.escapedText === target.name.escapedText && isMatchingReference(source.expression, target.expression); - case 182: - if (target.kind !== 185) + case 182 /* BindingElement */: + if (target.kind !== 185 /* PropertyAccessExpression */) return false; var t = target; if (t.name.escapedText !== getBindingElementNameText(source)) return false; - if (source.parent.parent.kind === 182 && isMatchingReference(source.parent.parent, t.expression)) { + if (source.parent.parent.kind === 182 /* BindingElement */ && isMatchingReference(source.parent.parent, t.expression)) { return true; } - if (source.parent.parent.kind === 232) { + if (source.parent.parent.kind === 232 /* VariableDeclaration */) { var maybeId = source.parent.parent.initializer; return !!maybeId && isMatchingReference(maybeId, t.expression); } @@ -35625,7 +41164,7 @@ var ts; return false; } function containsMatchingReference(source, target) { - while (source.kind === 185) { + while (source.kind === 185 /* PropertyAccessExpression */) { source = source.expression; if (isMatchingReference(source, target)) { return true; @@ -35633,27 +41172,31 @@ var ts; } return false; } + // Return true if target is a property access xxx.yyy, source is a property access xxx.zzz, the declared + // type of xxx is a union type, and yyy is a property that is possibly a discriminant. We consider a property + // a possible discriminant if its type differs in the constituents of containing union type, and if every + // choice is a unit type or a union of unit types. function containsMatchingReferenceDiscriminant(source, target) { - return target.kind === 185 && + return target.kind === 185 /* PropertyAccessExpression */ && containsMatchingReference(source, target.expression) && isDiscriminantProperty(getDeclaredTypeOfReference(target.expression), target.name.escapedText); } function getDeclaredTypeOfReference(expr) { - if (expr.kind === 71) { + if (expr.kind === 71 /* Identifier */) { return getTypeOfSymbol(getResolvedSymbol(expr)); } - if (expr.kind === 185) { + if (expr.kind === 185 /* PropertyAccessExpression */) { var type = getDeclaredTypeOfReference(expr.expression); return type && getTypeOfPropertyOfType(type, expr.name.escapedText); } return undefined; } function isDiscriminantProperty(type, name) { - if (type && type.flags & 262144) { + if (type && type.flags & 262144 /* Union */) { var prop = getUnionOrIntersectionProperty(type, name); - if (prop && ts.getCheckFlags(prop) & 2) { + if (prop && ts.getCheckFlags(prop) & 2 /* SyntheticProperty */) { if (prop.isDiscriminantProperty === undefined) { - prop.isDiscriminantProperty = !!(prop.checkFlags & 32) && isLiteralType(getTypeOfSymbol(prop)); + prop.isDiscriminantProperty = !!(prop.checkFlags & 32 /* HasNonUniformType */) && isLiteralType(getTypeOfSymbol(prop)); } return prop.isDiscriminantProperty; } @@ -35686,7 +41229,7 @@ var ts; } } } - if (callExpression.expression.kind === 185 && + if (callExpression.expression.kind === 185 /* PropertyAccessExpression */ && isOrContainsMatchingReference(reference, callExpression.expression.expression)) { return true; } @@ -35700,7 +41243,7 @@ var ts; return flow.id; } function typeMaybeAssignableTo(source, target) { - if (!(source.flags & 262144)) { + if (!(source.flags & 262144 /* Union */)) { return isTypeAssignableTo(source, target); } for (var _i = 0, _a = source.types; _i < _a.length; _i++) { @@ -35711,20 +41254,23 @@ var ts; } return false; } + // Remove those constituent types of declaredType to which no constituent type of assignedType is assignable. + // For example, when a variable of type number | string | boolean is assigned a value of type number | boolean, + // we remove type string. function getAssignmentReducedType(declaredType, assignedType) { if (declaredType !== assignedType) { - if (assignedType.flags & 32768) { + if (assignedType.flags & 32768 /* Never */) { return assignedType; } var reducedType = filterType(declaredType, function (t) { return typeMaybeAssignableTo(assignedType, t); }); - if (!(reducedType.flags & 32768)) { + if (!(reducedType.flags & 32768 /* Never */)) { return reducedType; } } return declaredType; } function getTypeFactsOfTypes(types) { - var result = 0; + var result = 0 /* None */; for (var _i = 0, types_12 = types; _i < types_12.length; _i++) { var t = types_12[_i]; result |= getTypeFacts(t); @@ -35732,62 +41278,64 @@ var ts; return result; } function isFunctionObjectType(type) { + // We do a quick check for a "bind" property before performing the more expensive subtype + // check. This gives us a quicker out in the common case where an object type is not a function. var resolved = resolveStructuredTypeMembers(type); return !!(resolved.callSignatures.length || resolved.constructSignatures.length || resolved.members.get("bind") && isTypeSubtypeOf(type, globalFunctionType)); } function getTypeFacts(type) { var flags = type.flags; - if (flags & 4) { - return strictNullChecks ? 4079361 : 4194049; + if (flags & 4 /* String */) { + return strictNullChecks ? 4079361 /* StringStrictFacts */ : 4194049 /* StringFacts */; } - if (flags & 64) { + if (flags & 64 /* StringLiteral */) { var isEmpty = type.value === ""; return strictNullChecks ? - isEmpty ? 3030785 : 1982209 : - isEmpty ? 3145473 : 4194049; + isEmpty ? 3030785 /* EmptyStringStrictFacts */ : 1982209 /* NonEmptyStringStrictFacts */ : + isEmpty ? 3145473 /* EmptyStringFacts */ : 4194049 /* NonEmptyStringFacts */; } - if (flags & (8 | 32)) { - return strictNullChecks ? 4079234 : 4193922; + if (flags & (8 /* Number */ | 32 /* Enum */)) { + return strictNullChecks ? 4079234 /* NumberStrictFacts */ : 4193922 /* NumberFacts */; } - if (flags & 128) { + if (flags & 128 /* NumberLiteral */) { var isZero = type.value === 0; return strictNullChecks ? - isZero ? 3030658 : 1982082 : - isZero ? 3145346 : 4193922; + isZero ? 3030658 /* ZeroStrictFacts */ : 1982082 /* NonZeroStrictFacts */ : + isZero ? 3145346 /* ZeroFacts */ : 4193922 /* NonZeroFacts */; } - if (flags & 16) { - return strictNullChecks ? 4078980 : 4193668; + if (flags & 16 /* Boolean */) { + return strictNullChecks ? 4078980 /* BooleanStrictFacts */ : 4193668 /* BooleanFacts */; } - if (flags & 272) { + if (flags & 272 /* BooleanLike */) { return strictNullChecks ? - type === falseType ? 3030404 : 1981828 : - type === falseType ? 3145092 : 4193668; + type === falseType ? 3030404 /* FalseStrictFacts */ : 1981828 /* TrueStrictFacts */ : + type === falseType ? 3145092 /* FalseFacts */ : 4193668 /* TrueFacts */; } - if (flags & 131072) { + if (flags & 131072 /* Object */) { return isFunctionObjectType(type) ? - strictNullChecks ? 1970144 : 4181984 : - strictNullChecks ? 1972176 : 4184016; + strictNullChecks ? 1970144 /* FunctionStrictFacts */ : 4181984 /* FunctionFacts */ : + strictNullChecks ? 1972176 /* ObjectStrictFacts */ : 4184016 /* ObjectFacts */; } - if (flags & (4096 | 8192)) { - return 2457472; + if (flags & (4096 /* Void */ | 8192 /* Undefined */)) { + return 2457472 /* UndefinedFacts */; } - if (flags & 16384) { - return 2340752; + if (flags & 16384 /* Null */) { + return 2340752 /* NullFacts */; } - if (flags & 3072) { - return strictNullChecks ? 1981320 : 4193160; + if (flags & 3072 /* ESSymbolLike */) { + return strictNullChecks ? 1981320 /* SymbolStrictFacts */ : 4193160 /* SymbolFacts */; } - if (flags & 16777216) { - return strictNullChecks ? 1972176 : 4184016; + if (flags & 16777216 /* NonPrimitive */) { + return strictNullChecks ? 1972176 /* ObjectStrictFacts */ : 4184016 /* ObjectFacts */; } - if (flags & 15794176) { + if (flags & 15794176 /* Instantiable */) { return getTypeFacts(getBaseConstraintOfType(type) || emptyObjectType); } - if (flags & 786432) { + if (flags & 786432 /* UnionOrIntersection */) { return getTypeFactsOfTypes(type.types); } - return 4194303; + return 4194303 /* All */; } function getTypeWithFacts(type, include) { return filterType(type, function (t) { return (getTypeFacts(t) & include) !== 0; }); @@ -35795,35 +41343,35 @@ var ts; function getTypeWithDefault(type, defaultExpression) { if (defaultExpression) { var defaultType = getTypeOfExpression(defaultExpression); - return getUnionType([getTypeWithFacts(type, 131072), defaultType]); + return getUnionType([getTypeWithFacts(type, 131072 /* NEUndefined */), defaultType]); } return type; } function getTypeOfDestructuredProperty(type, name) { var text = ts.getTextOfPropertyName(name); return getConstraintForLocation(getTypeOfPropertyOfType(type, text), name) || - isNumericLiteralName(text) && getIndexTypeOfType(type, 1) || - getIndexTypeOfType(type, 0) || + isNumericLiteralName(text) && getIndexTypeOfType(type, 1 /* Number */) || + getIndexTypeOfType(type, 0 /* String */) || errorType; } function getTypeOfDestructuredArrayElement(type, index) { return isTupleLikeType(type) && getTypeOfPropertyOfType(type, "" + index) || - checkIteratedTypeOrElementType(type, undefined, false, false) || + checkIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false) || errorType; } function getTypeOfDestructuredSpreadExpression(type) { - return createArrayType(checkIteratedTypeOrElementType(type, undefined, false, false) || errorType); + return createArrayType(checkIteratedTypeOrElementType(type, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false) || errorType); } function getAssignedTypeOfBinaryExpression(node) { - var isDestructuringDefaultAssignment = node.parent.kind === 183 && isDestructuringAssignmentTarget(node.parent) || - node.parent.kind === 270 && isDestructuringAssignmentTarget(node.parent.parent); + var isDestructuringDefaultAssignment = node.parent.kind === 183 /* ArrayLiteralExpression */ && isDestructuringAssignmentTarget(node.parent) || + node.parent.kind === 270 /* PropertyAssignment */ && isDestructuringAssignmentTarget(node.parent.parent); return isDestructuringDefaultAssignment ? getTypeWithDefault(getAssignedType(node), node.right) : getTypeOfExpression(node.right); } function isDestructuringAssignmentTarget(parent) { - return parent.parent.kind === 200 && parent.parent.left === parent || - parent.parent.kind === 222 && parent.parent.initializer === parent; + return parent.parent.kind === 200 /* BinaryExpression */ && parent.parent.left === parent || + parent.parent.kind === 222 /* ForOfStatement */ && parent.parent.initializer === parent; } function getAssignedTypeOfArrayLiteralElement(node, element) { return getTypeOfDestructuredArrayElement(getAssignedType(node), node.elements.indexOf(element)); @@ -35840,21 +41388,21 @@ var ts; function getAssignedType(node) { var parent = node.parent; switch (parent.kind) { - case 221: + case 221 /* ForInStatement */: return stringType; - case 222: + case 222 /* ForOfStatement */: return checkRightHandSideOfForOf(parent.expression, parent.awaitModifier) || errorType; - case 200: + case 200 /* BinaryExpression */: return getAssignedTypeOfBinaryExpression(parent); - case 194: + case 194 /* DeleteExpression */: return undefinedType; - case 183: + case 183 /* ArrayLiteralExpression */: return getAssignedTypeOfArrayLiteralElement(parent, node); - case 204: + case 204 /* SpreadElement */: return getAssignedTypeOfSpreadExpression(parent); - case 270: + case 270 /* PropertyAssignment */: return getAssignedTypeOfPropertyAssignment(parent); - case 271: + case 271 /* ShorthandPropertyAssignment */: return getAssignedTypeOfShorthandPropertyAssignment(parent); } return errorType; @@ -35862,7 +41410,7 @@ var ts; function getInitialTypeOfBindingElement(node) { var pattern = node.parent; var parentType = getInitialType(pattern.parent); - var type = pattern.kind === 180 ? + var type = pattern.kind === 180 /* ObjectBindingPattern */ ? getTypeOfDestructuredProperty(parentType, node.propertyName || node.name) : !node.dotDotDotToken ? getTypeOfDestructuredArrayElement(parentType, pattern.elements.indexOf(node)) : @@ -35870,6 +41418,9 @@ var ts; return getTypeWithDefault(type, node.initializer); } function getTypeOfInitializer(node) { + // Return the cached type if one is available. If the type of the variable was inferred + // from its initializer, we'll already have cached the type. Otherwise we compute it now + // without caching such that transient types are reflected. var links = getNodeLinks(node); return links.resolvedType || getTypeOfExpression(node); } @@ -35877,39 +41428,39 @@ var ts; if (node.initializer) { return getTypeOfInitializer(node.initializer); } - if (node.parent.parent.kind === 221) { + if (node.parent.parent.kind === 221 /* ForInStatement */) { return stringType; } - if (node.parent.parent.kind === 222) { + if (node.parent.parent.kind === 222 /* ForOfStatement */) { return checkRightHandSideOfForOf(node.parent.parent.expression, node.parent.parent.awaitModifier) || errorType; } return errorType; } function getInitialType(node) { - return node.kind === 232 ? + return node.kind === 232 /* VariableDeclaration */ ? getInitialTypeOfVariableDeclaration(node) : getInitialTypeOfBindingElement(node); } function getInitialOrAssignedType(node) { - return node.kind === 232 || node.kind === 182 ? + return node.kind === 232 /* VariableDeclaration */ || node.kind === 182 /* BindingElement */ ? getInitialType(node) : getAssignedType(node); } function isEmptyArrayAssignment(node) { - return node.kind === 232 && node.initializer && + return node.kind === 232 /* VariableDeclaration */ && node.initializer && isEmptyArrayLiteral(node.initializer) || - node.kind !== 182 && node.parent.kind === 200 && + node.kind !== 182 /* BindingElement */ && node.parent.kind === 200 /* BinaryExpression */ && isEmptyArrayLiteral(node.parent.right); } function getReferenceCandidate(node) { switch (node.kind) { - case 191: + case 191 /* ParenthesizedExpression */: return getReferenceCandidate(node.expression); - case 200: + case 200 /* BinaryExpression */: switch (node.operatorToken.kind) { - case 58: + case 58 /* EqualsToken */: return getReferenceCandidate(node.left); - case 26: + case 26 /* CommaToken */: return getReferenceCandidate(node.right); } } @@ -35917,13 +41468,13 @@ var ts; } function getReferenceRoot(node) { var parent = node.parent; - return parent.kind === 191 || - parent.kind === 200 && parent.operatorToken.kind === 58 && parent.left === node || - parent.kind === 200 && parent.operatorToken.kind === 26 && parent.right === node ? + return parent.kind === 191 /* ParenthesizedExpression */ || + parent.kind === 200 /* BinaryExpression */ && parent.operatorToken.kind === 58 /* EqualsToken */ && parent.left === node || + parent.kind === 200 /* BinaryExpression */ && parent.operatorToken.kind === 26 /* CommaToken */ && parent.right === node ? getReferenceRoot(parent) : node; } function getTypeOfSwitchClause(clause) { - if (clause.kind === 266) { + if (clause.kind === 266 /* CaseClause */) { return getRegularTypeOfLiteralType(getTypeOfExpression(clause.expression)); } return neverType; @@ -35940,13 +41491,13 @@ var ts; return links.switchTypes; } function eachTypeContainedIn(source, types) { - return source.flags & 262144 ? !ts.forEach(source.types, function (t) { return !ts.contains(types, t); }) : ts.contains(types, source); + return source.flags & 262144 /* Union */ ? !ts.forEach(source.types, function (t) { return !ts.contains(types, t); }) : ts.contains(types, source); } function isTypeSubsetOf(source, target) { - return source === target || target.flags & 262144 && isTypeSubsetOfUnion(source, target); + return source === target || target.flags & 262144 /* Union */ && isTypeSubsetOfUnion(source, target); } function isTypeSubsetOfUnion(source, target) { - if (source.flags & 262144) { + if (source.flags & 262144 /* Union */) { for (var _i = 0, _a = source.types; _i < _a.length; _i++) { var t = _a[_i]; if (!containsType(target.types, t)) { @@ -35955,27 +41506,27 @@ var ts; } return true; } - if (source.flags & 512 && getBaseTypeOfEnumLiteralType(source) === target) { + if (source.flags & 512 /* EnumLiteral */ && getBaseTypeOfEnumLiteralType(source) === target) { return true; } return containsType(target.types, source); } function forEachType(type, f) { - return type.flags & 262144 ? ts.forEach(type.types, f) : f(type); + return type.flags & 262144 /* Union */ ? ts.forEach(type.types, f) : f(type); } function filterType(type, f) { - if (type.flags & 262144) { + if (type.flags & 262144 /* Union */) { var types = type.types; var filtered = ts.filter(types, f); - return filtered === types ? type : getUnionTypeFromSortedList(filtered, type.flags & 67108864); + return filtered === types ? type : getUnionTypeFromSortedList(filtered, type.flags & 67108864 /* UnionOfUnitTypes */); } return f(type) ? type : neverType; } function mapType(type, mapper, noReductions) { - if (type.flags & 32768) { + if (type.flags & 32768 /* Never */) { return type; } - if (!(type.flags & 262144)) { + if (!(type.flags & 262144 /* Union */)) { return mapper(type); } var types = type.types; @@ -35996,17 +41547,20 @@ var ts; } } } - return mappedTypes ? getUnionType(mappedTypes, noReductions ? 0 : 1) : mappedType; + return mappedTypes ? getUnionType(mappedTypes, noReductions ? 0 /* None */ : 1 /* Literal */) : mappedType; } function extractTypesOfKind(type, kind) { return filterType(type, function (t) { return (t.flags & kind) !== 0; }); } + // Return a new type in which occurrences of the string and number primitive types in + // typeWithPrimitives have been replaced with occurrences of string literals and numeric + // literals in typeWithLiterals, respectively. function replacePrimitivesWithLiterals(typeWithPrimitives, typeWithLiterals) { - if (isTypeSubsetOf(stringType, typeWithPrimitives) && maybeTypeOfKind(typeWithLiterals, 64) || - isTypeSubsetOf(numberType, typeWithPrimitives) && maybeTypeOfKind(typeWithLiterals, 128)) { + if (isTypeSubsetOf(stringType, typeWithPrimitives) && maybeTypeOfKind(typeWithLiterals, 64 /* StringLiteral */) || + isTypeSubsetOf(numberType, typeWithPrimitives) && maybeTypeOfKind(typeWithLiterals, 128 /* NumberLiteral */)) { return mapType(typeWithPrimitives, function (t) { - return t.flags & 4 ? extractTypesOfKind(typeWithLiterals, 4 | 64) : - t.flags & 8 ? extractTypesOfKind(typeWithLiterals, 8 | 128) : + return t.flags & 4 /* String */ ? extractTypesOfKind(typeWithLiterals, 4 /* String */ | 64 /* StringLiteral */) : + t.flags & 8 /* Number */ ? extractTypesOfKind(typeWithLiterals, 8 /* Number */ | 128 /* NumberLiteral */) : t; }); } @@ -36021,40 +41575,48 @@ var ts; function createFlowType(type, incomplete) { return incomplete ? { flags: 0, type: type } : type; } + // An evolving array type tracks the element types that have so far been seen in an + // 'x.push(value)' or 'x[n] = value' operation along the control flow graph. Evolving + // array types are ultimately converted into manifest array types (using getFinalArrayType) + // and never escape the getFlowTypeOfReference function. function createEvolvingArrayType(elementType) { - var result = createObjectType(256); + var result = createObjectType(256 /* EvolvingArray */); result.elementType = elementType; return result; } function getEvolvingArrayType(elementType) { return evolvingArrayTypes[elementType.id] || (evolvingArrayTypes[elementType.id] = createEvolvingArrayType(elementType)); } + // When adding evolving array element types we do not perform subtype reduction. Instead, + // we defer subtype reduction until the evolving array type is finalized into a manifest + // array type. function addEvolvingArrayElementType(evolvingArrayType, node) { var elementType = getBaseTypeOfLiteralType(getContextFreeTypeOfExpression(node)); return isTypeSubsetOf(elementType, evolvingArrayType.elementType) ? evolvingArrayType : getEvolvingArrayType(getUnionType([evolvingArrayType.elementType, elementType])); } function createFinalArrayType(elementType) { - return elementType.flags & 32768 ? + return elementType.flags & 32768 /* Never */ ? autoArrayType : - createArrayType(elementType.flags & 262144 ? - getUnionType(elementType.types, 2) : + createArrayType(elementType.flags & 262144 /* Union */ ? + getUnionType(elementType.types, 2 /* Subtype */) : elementType); } + // We perform subtype reduction upon obtaining the final array type from an evolving array type. function getFinalArrayType(evolvingArrayType) { return evolvingArrayType.finalArrayType || (evolvingArrayType.finalArrayType = createFinalArrayType(evolvingArrayType.elementType)); } function finalizeEvolvingArrayType(type) { - return ts.getObjectFlags(type) & 256 ? getFinalArrayType(type) : type; + return ts.getObjectFlags(type) & 256 /* EvolvingArray */ ? getFinalArrayType(type) : type; } function getElementTypeOfEvolvingArrayType(type) { - return ts.getObjectFlags(type) & 256 ? type.elementType : neverType; + return ts.getObjectFlags(type) & 256 /* EvolvingArray */ ? type.elementType : neverType; } function isEvolvingArrayTypeList(types) { var hasEvolvingArrayType = false; for (var _i = 0, types_14 = types; _i < types_14.length; _i++) { var t = types_14[_i]; - if (!(t.flags & 32768)) { - if (!(ts.getObjectFlags(t) & 256)) { + if (!(t.flags & 32768 /* Never */)) { + if (!(ts.getObjectFlags(t) & 256 /* EvolvingArray */)) { return false; } hasEvolvingArrayType = true; @@ -36062,23 +41624,28 @@ var ts; } return hasEvolvingArrayType; } + // At flow control branch or loop junctions, if the type along every antecedent code path + // is an evolving array type, we construct a combined evolving array type. Otherwise we + // finalize all evolving array types. function getUnionOrEvolvingArrayType(types, subtypeReduction) { return isEvolvingArrayTypeList(types) ? getEvolvingArrayType(getUnionType(ts.map(types, getElementTypeOfEvolvingArrayType))) : getUnionType(ts.sameMap(types, finalizeEvolvingArrayType), subtypeReduction); } + // Return true if the given node is 'x' in an 'x.length', x.push(value)', 'x.unshift(value)' or + // 'x[n] = value' operation, where 'n' is an expression of type any, undefined, or a number-like type. function isEvolvingArrayOperationTarget(node) { var root = getReferenceRoot(node); var parent = root.parent; - var isLengthPushOrUnshift = parent.kind === 185 && (parent.name.escapedText === "length" || - parent.parent.kind === 187 && ts.isPushOrUnshiftIdentifier(parent.name)); - var isElementAssignment = parent.kind === 186 && + var isLengthPushOrUnshift = parent.kind === 185 /* PropertyAccessExpression */ && (parent.name.escapedText === "length" || + parent.parent.kind === 187 /* CallExpression */ && ts.isPushOrUnshiftIdentifier(parent.name)); + var isElementAssignment = parent.kind === 186 /* ElementAccessExpression */ && parent.expression === root && - parent.parent.kind === 200 && - parent.parent.operatorToken.kind === 58 && + parent.parent.kind === 200 /* BinaryExpression */ && + parent.parent.operatorToken.kind === 58 /* EqualsToken */ && parent.parent.left === parent && !ts.isAssignmentTarget(parent.parent) && - isTypeAssignableToKind(getTypeOfExpression(parent.argumentExpression), 168); + isTypeAssignableToKind(getTypeOfExpression(parent.argumentExpression), 168 /* NumberLike */); return isLengthPushOrUnshift || isElementAssignment; } function maybeTypePredicateCall(node) { @@ -36089,11 +41656,11 @@ var ts; return links.maybeTypePredicate; } function getMaybeTypePredicate(node) { - if (node.expression.kind !== 97) { + if (node.expression.kind !== 97 /* SuperKeyword */) { var funcType = checkNonNullExpression(node.expression); if (funcType !== silentNeverType) { var apparentType = getApparentType(funcType); - return apparentType !== errorType && ts.some(getSignaturesOfType(apparentType, 0), signatureHasTypePredicate); + return apparentType !== errorType && ts.some(getSignaturesOfType(apparentType, 0 /* Call */), signatureHasTypePredicate); } } return false; @@ -36111,19 +41678,25 @@ var ts; if (flowAnalysisDisabled) { return errorType; } - if (!reference.flowNode || !couldBeUninitialized && !(declaredType.flags & 33492479)) { + if (!reference.flowNode || !couldBeUninitialized && !(declaredType.flags & 33492479 /* Narrowable */)) { return declaredType; } var sharedFlowStart = sharedFlowCount; var evolvedType = getTypeFromFlowType(getTypeAtFlowNode(reference.flowNode)); sharedFlowCount = sharedFlowStart; - var resultType = ts.getObjectFlags(evolvedType) & 256 && isEvolvingArrayOperationTarget(reference) ? anyArrayType : finalizeEvolvingArrayType(evolvedType); - if (reference.parent && reference.parent.kind === 209 && getTypeWithFacts(resultType, 524288).flags & 32768) { + // When the reference is 'x' in an 'x.length', 'x.push(value)', 'x.unshift(value)' or x[n] = value' operation, + // we give type 'any[]' to 'x' instead of using the type determined by control flow analysis such that operations + // on empty arrays are possible without implicit any errors and new element types can be inferred without + // type mismatch errors. + var resultType = ts.getObjectFlags(evolvedType) & 256 /* EvolvingArray */ && isEvolvingArrayOperationTarget(reference) ? anyArrayType : finalizeEvolvingArrayType(evolvedType); + if (reference.parent && reference.parent.kind === 209 /* NonNullExpression */ && getTypeWithFacts(resultType, 524288 /* NEUndefinedOrNull */).flags & 32768 /* Never */) { return declaredType; } return resultType; function getTypeAtFlowNode(flow) { if (flowDepth === 2500) { + // We have made 2500 recursive invocations. To avoid overflowing the call stack we report an error + // and disable further control flow analysis in the containing function or module body. flowAnalysisDisabled = true; reportFlowControlError(reference); return errorType; @@ -36131,7 +41704,10 @@ var ts; flowDepth++; while (true) { var flags = flow.flags; - if (flags & 1024) { + if (flags & 1024 /* Shared */) { + // We cache results of flow type resolution for shared nodes that were previously visited in + // the same getFlowTypeOfReference invocation. A node is considered shared when it is the + // antecedent of more than one node. for (var i = sharedFlowStart; i < sharedFlowCount; i++) { if (sharedFlowNodes[i] === flow) { flowDepth--; @@ -36140,56 +41716,64 @@ var ts; } } var type = void 0; - if (flags & 4096) { + if (flags & 4096 /* AfterFinally */) { + // block flow edge: finally -> pre-try (for larger explanation check comment in binder.ts - bindTryStatement flow.locked = true; type = getTypeAtFlowNode(flow.antecedent); flow.locked = false; } - else if (flags & 2048) { + else if (flags & 2048 /* PreFinally */) { + // locked pre-finally flows are filtered out in getTypeAtFlowBranchLabel + // so here just redirect to antecedent flow = flow.antecedent; continue; } - else if (flags & 16) { + else if (flags & 16 /* Assignment */) { type = getTypeAtFlowAssignment(flow); if (!type) { flow = flow.antecedent; continue; } } - else if (flags & 96) { + else if (flags & 96 /* Condition */) { type = getTypeAtFlowCondition(flow); } - else if (flags & 128) { + else if (flags & 128 /* SwitchClause */) { type = getTypeAtSwitchClause(flow); } - else if (flags & 12) { + else if (flags & 12 /* Label */) { if (flow.antecedents.length === 1) { flow = flow.antecedents[0]; continue; } - type = flags & 4 ? + type = flags & 4 /* BranchLabel */ ? getTypeAtFlowBranchLabel(flow) : getTypeAtFlowLoopLabel(flow); } - else if (flags & 256) { + else if (flags & 256 /* ArrayMutation */) { type = getTypeAtFlowArrayMutation(flow); if (!type) { flow = flow.antecedent; continue; } } - else if (flags & 2) { + else if (flags & 2 /* Start */) { + // Check if we should continue with the control flow of the containing function. var container = flow.container; - if (container && container !== flowContainer && reference.kind !== 185 && reference.kind !== 99) { + if (container && container !== flowContainer && reference.kind !== 185 /* PropertyAccessExpression */ && reference.kind !== 99 /* ThisKeyword */) { flow = container.flowNode; continue; } + // At the top of the flow we have the initial type. type = initialType; } else { + // Unreachable code errors are reported in the binding phase. Here we + // simply return the non-auto declared type to reduce follow-on errors. type = convertAutoToAny(declaredType); } - if (flags & 1024) { + if (flags & 1024 /* Shared */) { + // Record visited node and the associated type in the cache. sharedFlowNodes[sharedFlowCount] = flow; sharedFlowTypes[sharedFlowCount] = type; sharedFlowCount++; @@ -36200,8 +41784,10 @@ var ts; } function getTypeAtFlowAssignment(flow) { var node = flow.node; + // Assignments only narrow the computed type if the declared type is a union type. Thus, we + // only need to evaluate the assigned type if the declared type is a union type. if (isMatchingReference(reference, node)) { - if (ts.getAssignmentTargetKind(node) === 2) { + if (ts.getAssignmentTargetKind(node) === 2 /* Compound */) { var flowType = getTypeAtFlowNode(flow.antecedent); return createFlowType(getBaseTypeOfLiteralType(getTypeFromFlowType(flowType)), isIncomplete(flowType)); } @@ -36212,28 +41798,33 @@ var ts; var assignedType = getBaseTypeOfLiteralType(getInitialOrAssignedType(node)); return isTypeAssignableTo(assignedType, declaredType) ? assignedType : anyArrayType; } - if (declaredType.flags & 262144) { + if (declaredType.flags & 262144 /* Union */) { return getAssignmentReducedType(declaredType, getInitialOrAssignedType(node)); } return declaredType; } + // We didn't have a direct match. However, if the reference is a dotted name, this + // may be an assignment to a left hand part of the reference. For example, for a + // reference 'x.y.z', we may be at an assignment to 'x.y' or 'x'. In that case, + // return the declared type. if (containsMatchingReference(reference, node)) { return declaredType; } + // Assignment doesn't affect reference return undefined; } function getTypeAtFlowArrayMutation(flow) { if (declaredType === autoType || declaredType === autoArrayType) { var node = flow.node; - var expr = node.kind === 187 ? + var expr = node.kind === 187 /* CallExpression */ ? node.expression.expression : node.left.expression; if (isMatchingReference(reference, getReferenceCandidate(expr))) { var flowType = getTypeAtFlowNode(flow.antecedent); var type = getTypeFromFlowType(flowType); - if (ts.getObjectFlags(type) & 256) { + if (ts.getObjectFlags(type) & 256 /* EvolvingArray */) { var evolvedType_1 = type; - if (node.kind === 187) { + if (node.kind === 187 /* CallExpression */) { for (var _i = 0, _a = node.arguments; _i < _a.length; _i++) { var arg = _a[_i]; evolvedType_1 = addEvolvingArrayElementType(evolvedType_1, arg); @@ -36241,7 +41832,7 @@ var ts; } else { var indexType = getTypeOfExpression(node.left.argumentExpression); - if (isTypeAssignableToKind(indexType, 168)) { + if (isTypeAssignableToKind(indexType, 168 /* NumberLike */)) { evolvedType_1 = addEvolvingArrayElementType(evolvedType_1, node.right); } } @@ -36255,17 +41846,24 @@ var ts; function getTypeAtFlowCondition(flow) { var flowType = getTypeAtFlowNode(flow.antecedent); var type = getTypeFromFlowType(flowType); - if (type.flags & 32768) { + if (type.flags & 32768 /* Never */) { return flowType; } - var assumeTrue = (flow.flags & 32) !== 0; + // If we have an antecedent type (meaning we're reachable in some way), we first + // attempt to narrow the antecedent type. If that produces the never type, and if + // the antecedent type is incomplete (i.e. a transient type in a loop), then we + // take the type guard as an indication that control *could* reach here once we + // have the complete type. We proceed by switching to the silent never type which + // doesn't report errors when operators are applied to it. Note that this is the + // *only* place a silent never type is ever generated. + var assumeTrue = (flow.flags & 32 /* TrueCondition */) !== 0; var nonEvolvingType = finalizeEvolvingArrayType(type); var narrowedType = narrowType(nonEvolvingType, flow.expression, assumeTrue); if (narrowedType === nonEvolvingType) { return flowType; } var incomplete = isIncomplete(flowType); - var resultType = incomplete && narrowedType.flags & 32768 ? silentNeverType : narrowedType; + var resultType = incomplete && narrowedType.flags & 32768 /* Never */ ? silentNeverType : narrowedType; return createFlowType(resultType, incomplete); } function getTypeAtSwitchClause(flow) { @@ -36286,15 +41884,25 @@ var ts; var seenIncomplete = false; for (var _i = 0, _a = flow.antecedents; _i < _a.length; _i++) { var antecedent = _a[_i]; - if (antecedent.flags & 2048 && antecedent.lock.locked) { + if (antecedent.flags & 2048 /* PreFinally */ && antecedent.lock.locked) { + // if flow correspond to branch from pre-try to finally and this branch is locked - this means that + // we initially have started following the flow outside the finally block. + // in this case we should ignore this branch. continue; } var flowType = getTypeAtFlowNode(antecedent); var type = getTypeFromFlowType(flowType); + // If the type at a particular antecedent path is the declared type and the + // reference is known to always be assigned (i.e. when declared and initial types + // are the same), there is no reason to process more antecedents since the only + // possible outcome is subtypes that will be removed in the final union type anyway. if (type === declaredType && declaredType === initialType) { return type; } ts.pushIfUnique(antecedentTypes, type); + // If an antecedent type is not a subset of the declared type, we need to perform + // subtype reduction. This happens when a "foreign" type is injected into the control + // flow using the instanceof operator or a user defined type predicate. if (!isTypeSubsetOf(type, declaredType)) { subtypeReduction = true; } @@ -36302,13 +41910,16 @@ var ts; seenIncomplete = true; } } - return createFlowType(getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction ? 2 : 1), seenIncomplete); + return createFlowType(getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction ? 2 /* Subtype */ : 1 /* Literal */), seenIncomplete); } function getTypeAtFlowLoopLabel(flow) { + // If we have previously computed the control flow type for the reference at + // this flow loop junction, return the cached type. var id = getFlowNodeId(flow); var cache = flowLoopCaches[id] || (flowLoopCaches[id] = ts.createMap()); if (!key) { key = getFlowCacheKey(reference); + // No cache key is generated when binding patterns are in unnarrowable situations if (!key) { return declaredType; } @@ -36317,11 +41928,21 @@ var ts; if (cached) { return cached; } + // If this flow loop junction and reference are already being processed, return + // the union of the types computed for each branch so far, marked as incomplete. + // It is possible to see an empty array in cases where loops are nested and the + // back edge of the outer loop reaches an inner loop that is already being analyzed. + // In such cases we restart the analysis of the inner loop, which will then see + // a non-empty in-process array for the outer loop and eventually terminate because + // the first antecedent of a loop junction is always the non-looping control flow + // path that leads to the top. for (var i = flowLoopStart; i < flowLoopCount; i++) { if (flowLoopNodes[i] === flow && flowLoopKeys[i] === key && flowLoopTypes[i].length) { - return createFlowType(getUnionOrEvolvingArrayType(flowLoopTypes[i], 1), true); + return createFlowType(getUnionOrEvolvingArrayType(flowLoopTypes[i], 1 /* Literal */), /*incomplete*/ true); } } + // Add the flow loop junction and reference to the in-process stack and analyze + // each antecedent code path. var antecedentTypes = []; var subtypeReduction = false; var firstAntecedentType; @@ -36337,28 +41958,39 @@ var ts; firstAntecedentType = flowType; } var type = getTypeFromFlowType(flowType); + // If we see a value appear in the cache it is a sign that control flow analysis + // was restarted and completed by checkExpressionCached. We can simply pick up + // the resulting type and bail out. var cached_1 = cache.get(key); if (cached_1) { return cached_1; } ts.pushIfUnique(antecedentTypes, type); + // If an antecedent type is not a subset of the declared type, we need to perform + // subtype reduction. This happens when a "foreign" type is injected into the control + // flow using the instanceof operator or a user defined type predicate. if (!isTypeSubsetOf(type, declaredType)) { subtypeReduction = true; } + // If the type at a particular antecedent path is the declared type there is no + // reason to process more antecedents since the only possible outcome is subtypes + // that will be removed in the final union type anyway. if (type === declaredType) { break; } } - var result = getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction ? 2 : 1); + // The result is incomplete if the first antecedent (the non-looping control flow path) + // is incomplete. + var result = getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction ? 2 /* Subtype */ : 1 /* Literal */); if (isIncomplete(firstAntecedentType)) { - return createFlowType(result, true); + return createFlowType(result, /*incomplete*/ true); } cache.set(key, result); return result; } function isMatchingReferenceDiscriminant(expr, computedType) { - return expr.kind === 185 && - computedType.flags & 262144 && + return expr.kind === 185 /* PropertyAccessExpression */ && + computedType.flags & 262144 /* Union */ && isMatchingReference(reference, expr.expression) && isDiscriminantProperty(computedType, expr.name.escapedText); } @@ -36370,10 +42002,10 @@ var ts; } function narrowTypeByTruthiness(type, expr, assumeTrue) { if (isMatchingReference(reference, expr)) { - return getTypeWithFacts(type, assumeTrue ? 1048576 : 2097152); + return getTypeWithFacts(type, assumeTrue ? 1048576 /* Truthy */ : 2097152 /* Falsy */); } if (isMatchingReferenceDiscriminant(expr, declaredType)) { - return narrowTypeByDiscriminant(type, expr, function (t) { return getTypeWithFacts(t, assumeTrue ? 1048576 : 2097152); }); + return narrowTypeByDiscriminant(type, expr, function (t) { return getTypeWithFacts(t, assumeTrue ? 1048576 /* Truthy */ : 2097152 /* Falsy */); }); } if (containsMatchingReferenceDiscriminant(reference, expr)) { return declaredType; @@ -36381,17 +42013,17 @@ var ts; return type; } function isTypePresencePossible(type, propName, assumeTrue) { - if (getIndexInfoOfType(type, 0)) { + if (getIndexInfoOfType(type, 0 /* String */)) { return true; } var prop = getPropertyOfType(type, propName); if (prop) { - return prop.flags & 16777216 ? true : assumeTrue; + return prop.flags & 16777216 /* Optional */ ? true : assumeTrue; } return !assumeTrue; } function narrowByInKeyword(type, literal, assumeTrue) { - if ((type.flags & (262144 | 131072)) || (type.flags & 65536 && type.isThisType)) { + if ((type.flags & (262144 /* Union */ | 131072 /* Object */)) || (type.flags & 65536 /* TypeParameter */ && type.isThisType)) { var propName_1 = ts.escapeLeadingUnderscores(literal.text); return filterType(type, function (t) { return isTypePresencePossible(t, propName_1, assumeTrue); }); } @@ -36399,19 +42031,19 @@ var ts; } function narrowTypeByBinaryExpression(type, expr, assumeTrue) { switch (expr.operatorToken.kind) { - case 58: + case 58 /* EqualsToken */: return narrowTypeByTruthiness(type, expr.left, assumeTrue); - case 32: - case 33: - case 34: - case 35: + case 32 /* EqualsEqualsToken */: + case 33 /* ExclamationEqualsToken */: + case 34 /* EqualsEqualsEqualsToken */: + case 35 /* ExclamationEqualsEqualsToken */: var operator_1 = expr.operatorToken.kind; var left_1 = getReferenceCandidate(expr.left); var right_1 = getReferenceCandidate(expr.right); - if (left_1.kind === 195 && ts.isStringLiteralLike(right_1)) { + if (left_1.kind === 195 /* TypeOfExpression */ && ts.isStringLiteralLike(right_1)) { return narrowTypeByTypeof(type, left_1, operator_1, right_1, assumeTrue); } - if (right_1.kind === 195 && ts.isStringLiteralLike(left_1)) { + if (right_1.kind === 195 /* TypeOfExpression */ && ts.isStringLiteralLike(left_1)) { return narrowTypeByTypeof(type, right_1, operator_1, left_1, assumeTrue); } if (isMatchingReference(reference, left_1)) { @@ -36430,45 +42062,45 @@ var ts; return declaredType; } break; - case 93: + case 93 /* InstanceOfKeyword */: return narrowTypeByInstanceof(type, expr, assumeTrue); - case 92: + case 92 /* InKeyword */: var target = getReferenceCandidate(expr.right); if (ts.isStringLiteralLike(expr.left) && isMatchingReference(reference, target)) { return narrowByInKeyword(type, expr.left, assumeTrue); } break; - case 26: + case 26 /* CommaToken */: return narrowType(type, expr.right, assumeTrue); } return type; } function narrowTypeByEquality(type, operator, value, assumeTrue) { - if (type.flags & 1) { + if (type.flags & 1 /* Any */) { return type; } - if (operator === 33 || operator === 35) { + if (operator === 33 /* ExclamationEqualsToken */ || operator === 35 /* ExclamationEqualsEqualsToken */) { assumeTrue = !assumeTrue; } var valueType = getTypeOfExpression(value); - if (valueType.flags & 24576) { + if (valueType.flags & 24576 /* Nullable */) { if (!strictNullChecks) { return type; } - var doubleEquals = operator === 32 || operator === 33; + var doubleEquals = operator === 32 /* EqualsEqualsToken */ || operator === 33 /* ExclamationEqualsToken */; var facts = doubleEquals ? - assumeTrue ? 65536 : 524288 : - valueType.flags & 16384 ? - assumeTrue ? 32768 : 262144 : - assumeTrue ? 16384 : 131072; + assumeTrue ? 65536 /* EQUndefinedOrNull */ : 524288 /* NEUndefinedOrNull */ : + valueType.flags & 16384 /* Null */ ? + assumeTrue ? 32768 /* EQNull */ : 262144 /* NENull */ : + assumeTrue ? 16384 /* EQUndefined */ : 131072 /* NEUndefined */; return getTypeWithFacts(type, facts); } - if (type.flags & 16909315) { + if (type.flags & 16909315 /* NotUnionOrUnit */) { return type; } if (assumeTrue) { var narrowedType = filterType(type, function (t) { return areTypesComparable(t, valueType); }); - return narrowedType.flags & 32768 ? type : replacePrimitivesWithLiterals(narrowedType, valueType); + return narrowedType.flags & 32768 /* Never */ ? type : replacePrimitivesWithLiterals(narrowedType, valueType); } if (isUnitType(valueType)) { var regularType_1 = getRegularTypeOfLiteralType(valueType); @@ -36477,26 +42109,32 @@ var ts; return type; } function narrowTypeByTypeof(type, typeOfExpr, operator, literal, assumeTrue) { + // We have '==', '!=', '====', or !==' operator with 'typeof xxx' and string literal operands var target = getReferenceCandidate(typeOfExpr.expression); if (!isMatchingReference(reference, target)) { + // For a reference of the form 'x.y', a 'typeof x === ...' type guard resets the + // narrowed type of 'y' to its declared type. if (containsMatchingReference(reference, target)) { return declaredType; } return type; } - if (operator === 33 || operator === 35) { + if (operator === 33 /* ExclamationEqualsToken */ || operator === 35 /* ExclamationEqualsEqualsToken */) { assumeTrue = !assumeTrue; } - if (type.flags & 1 && literal.text === "function") { + if (type.flags & 1 /* Any */ && literal.text === "function") { return type; } - if (assumeTrue && !(type.flags & 262144)) { + if (assumeTrue && !(type.flags & 262144 /* Union */)) { + // We narrow a non-union type to an exact primitive type if the non-union type + // is a supertype of that primitive type. For example, type 'any' can be narrowed + // to one of the primitive types. var targetType = literal.text === "function" ? globalFunctionType : typeofTypesByName.get(literal.text); if (targetType) { if (isTypeSubtypeOf(targetType, type)) { return targetType; } - if (type.flags & 15794176) { + if (type.flags & 15794176 /* Instantiable */) { var constraint = getBaseConstraintOfType(type) || anyType; if (isTypeSubtypeOf(targetType, constraint)) { return getIntersectionType([type, targetType]); @@ -36505,11 +42143,12 @@ var ts; } } var facts = assumeTrue ? - typeofEQFacts.get(literal.text) || 64 : - typeofNEFacts.get(literal.text) || 8192; + typeofEQFacts.get(literal.text) || 64 /* TypeofEQHostObject */ : + typeofNEFacts.get(literal.text) || 8192 /* TypeofNEHostObject */; return getTypeWithFacts(type, facts); } function narrowTypeBySwitchOnDiscriminant(type, switchStatement, clauseStart, clauseEnd) { + // We only narrow if all case expressions specify values with unit types var switchTypes = getSwitchClauseTypes(switchStatement); if (!switchTypes.length) { return type; @@ -36517,22 +42156,25 @@ var ts; var clauseTypes = switchTypes.slice(clauseStart, clauseEnd); var hasDefaultClause = clauseStart === clauseEnd || ts.contains(clauseTypes, neverType); var discriminantType = getUnionType(clauseTypes); - var caseType = discriminantType.flags & 32768 ? neverType : + var caseType = discriminantType.flags & 32768 /* Never */ ? neverType : replacePrimitivesWithLiterals(filterType(type, function (t) { return areTypesComparable(discriminantType, t); }), discriminantType); if (!hasDefaultClause) { return caseType; } var defaultType = filterType(type, function (t) { return !(isUnitType(t) && ts.contains(switchTypes, getRegularTypeOfLiteralType(t))); }); - return caseType.flags & 32768 ? defaultType : getUnionType([caseType, defaultType]); + return caseType.flags & 32768 /* Never */ ? defaultType : getUnionType([caseType, defaultType]); } function narrowTypeByInstanceof(type, expr, assumeTrue) { var left = getReferenceCandidate(expr.left); if (!isMatchingReference(reference, left)) { + // For a reference of the form 'x.y', an 'x instanceof T' type guard resets the + // narrowed type of 'y' to its declared type. if (containsMatchingReference(reference, left)) { return declaredType; } return type; } + // Check that right operand is a function type with a prototype property var rightType = getTypeOfExpression(expr.right); if (!isTypeSubtypeOf(rightType, globalFunctionType)) { return type; @@ -36540,21 +42182,24 @@ var ts; var targetType; var prototypeProperty = getPropertyOfType(rightType, "prototype"); if (prototypeProperty) { + // Target type is type of the prototype property var prototypePropertyType = getTypeOfSymbol(prototypeProperty); if (!isTypeAny(prototypePropertyType)) { targetType = prototypePropertyType; } } + // Don't narrow from 'any' if the target type is exactly 'Object' or 'Function' if (isTypeAny(type) && (targetType === globalObjectType || targetType === globalFunctionType)) { return type; } if (!targetType) { + // Target type is type of construct signature var constructSignatures = void 0; - if (ts.getObjectFlags(rightType) & 2) { + if (ts.getObjectFlags(rightType) & 2 /* Interface */) { constructSignatures = resolveDeclaredMembers(rightType).declaredConstructSignatures; } - else if (ts.getObjectFlags(rightType) & 16) { - constructSignatures = getSignaturesOfType(rightType, 1); + else if (ts.getObjectFlags(rightType) & 16 /* Anonymous */) { + constructSignatures = getSignaturesOfType(rightType, 1 /* Construct */); } if (constructSignatures && constructSignatures.length) { targetType = getUnionType(ts.map(constructSignatures, function (signature) { return getReturnTypeOfSignature(getErasedSignature(signature)); })); @@ -36569,12 +42214,19 @@ var ts; if (!assumeTrue) { return filterType(type, function (t) { return !isRelated(t, candidate); }); } - if (type.flags & 262144) { + // If the current type is a union type, remove all constituents that couldn't be instances of + // the candidate type. If one or more constituents remain, return a union of those. + if (type.flags & 262144 /* Union */) { var assignableType = filterType(type, function (t) { return isRelated(t, candidate); }); - if (!(assignableType.flags & 32768)) { + if (!(assignableType.flags & 32768 /* Never */)) { return assignableType; } } + // If the candidate type is a subtype of the target type, narrow to the candidate type. + // Otherwise, if the target type is assignable to the candidate type, keep the target type. + // Otherwise, if the candidate type is assignable to the target type, narrow to the candidate + // type. Otherwise, the types are completely unrelated, so narrow to an intersection of the + // two types. return isTypeSubtypeOf(candidate, type) ? candidate : isTypeAssignableTo(type, candidate) ? type : isTypeAssignableTo(candidate, type) ? candidate : @@ -36589,6 +42241,7 @@ var ts; if (!predicate) { return type; } + // Don't narrow from 'any' if the predicate type is exactly 'Object' or 'Function' if (isTypeAny(type) && (predicate.type === globalObjectType || predicate.type === globalFunctionType)) { return type; } @@ -36605,7 +42258,7 @@ var ts; } else { var invokedExpression = ts.skipParentheses(callExpression.expression); - if (invokedExpression.kind === 186 || invokedExpression.kind === 185) { + if (invokedExpression.kind === 186 /* ElementAccessExpression */ || invokedExpression.kind === 185 /* PropertyAccessExpression */) { var accessExpression = invokedExpression; var possibleReference = ts.skipParentheses(accessExpression.expression); if (isMatchingReference(reference, possibleReference)) { @@ -36618,21 +42271,23 @@ var ts; } return type; } + // Narrow the given type based on the given expression having the assumed boolean value. The returned type + // will be a subtype or the same type as the argument. function narrowType(type, expr, assumeTrue) { switch (expr.kind) { - case 71: - case 99: - case 97: - case 185: + case 71 /* Identifier */: + case 99 /* ThisKeyword */: + case 97 /* SuperKeyword */: + case 185 /* PropertyAccessExpression */: return narrowTypeByTruthiness(type, expr, assumeTrue); - case 187: + case 187 /* CallExpression */: return narrowTypeByTypePredicate(type, expr, assumeTrue); - case 191: + case 191 /* ParenthesizedExpression */: return narrowType(type, expr.expression, assumeTrue); - case 200: + case 200 /* BinaryExpression */: return narrowTypeByBinaryExpression(type, expr, assumeTrue); - case 198: - if (expr.operator === 51) { + case 198 /* PrefixUnaryExpression */: + if (expr.operator === 51 /* ExclamationToken */) { return narrowType(type, expr.operand, !assumeTrue); } break; @@ -36642,7 +42297,11 @@ var ts; } function getTypeOfSymbolAtLocation(symbol, location) { symbol = symbol.exportSymbol || symbol; - if (location.kind === 71) { + // If we have an identifier or a property access at the given location, if the location is + // an dotted name expression, and if the location is not an assignment target, obtain the type + // of the expression (which will reflect control flow analysis). If the expression indeed + // resolved to the given symbol, return the narrowed type. + if (location.kind === 71 /* Identifier */) { if (ts.isRightSideOfQualifiedNameOrPropertyAccess(location)) { location = location.parent; } @@ -36653,21 +42312,27 @@ var ts; } } } + // The location isn't a reference to the given symbol, meaning we're being asked + // a hypothetical question of what type the symbol would have if there was a reference + // to it at the given location. Since we have no control flow information for the + // hypothetical reference (control flow information is created and attached by the + // binder), we simply return the declared type of the symbol. return getTypeOfSymbol(symbol); } function getControlFlowContainer(node) { return ts.findAncestor(node.parent, function (node) { return ts.isFunctionLike(node) && !ts.getImmediatelyInvokedFunctionExpression(node) || - node.kind === 240 || - node.kind === 274 || - node.kind === 152; + node.kind === 240 /* ModuleBlock */ || + node.kind === 274 /* SourceFile */ || + node.kind === 152 /* PropertyDeclaration */; }); } + // Check if a parameter is assigned anywhere within its declaring function. function isParameterAssigned(symbol) { var func = ts.getRootDeclaration(symbol.valueDeclaration).parent; var links = getNodeLinks(func); - if (!(links.flags & 4194304)) { - links.flags |= 4194304; + if (!(links.flags & 4194304 /* AssignmentsMarked */)) { + links.flags |= 4194304 /* AssignmentsMarked */; if (!hasParentWithAssignmentsMarked(func)) { markParameterAssignments(func); } @@ -36675,13 +42340,13 @@ var ts; return symbol.isAssigned || false; } function hasParentWithAssignmentsMarked(node) { - return !!ts.findAncestor(node.parent, function (node) { return ts.isFunctionLike(node) && !!(getNodeLinks(node).flags & 4194304); }); + return !!ts.findAncestor(node.parent, function (node) { return ts.isFunctionLike(node) && !!(getNodeLinks(node).flags & 4194304 /* AssignmentsMarked */); }); } function markParameterAssignments(node) { - if (node.kind === 71) { + if (node.kind === 71 /* Identifier */) { if (ts.isAssignmentTarget(node)) { var symbol = getResolvedSymbol(node); - if (symbol.valueDeclaration && ts.getRootDeclaration(symbol.valueDeclaration).kind === 149) { + if (symbol.valueDeclaration && ts.getRootDeclaration(symbol.valueDeclaration).kind === 149 /* Parameter */) { symbol.isAssigned = true; } } @@ -36691,34 +42356,39 @@ var ts; } } function isConstVariable(symbol) { - return symbol.flags & 3 && (getDeclarationNodeFlagsFromSymbol(symbol) & 2) !== 0 && getTypeOfSymbol(symbol) !== autoArrayType; + return symbol.flags & 3 /* Variable */ && (getDeclarationNodeFlagsFromSymbol(symbol) & 2 /* Const */) !== 0 && getTypeOfSymbol(symbol) !== autoArrayType; } + /** remove undefined from the annotated type of a parameter when there is an initializer (that doesn't include undefined) */ function removeOptionalityFromDeclaredType(declaredType, declaration) { var annotationIncludesUndefined = strictNullChecks && - declaration.kind === 149 && + declaration.kind === 149 /* Parameter */ && declaration.initializer && - getFalsyFlags(declaredType) & 8192 && - !(getFalsyFlags(checkExpression(declaration.initializer)) & 8192); - return annotationIncludesUndefined ? getTypeWithFacts(declaredType, 131072) : declaredType; + getFalsyFlags(declaredType) & 8192 /* Undefined */ && + !(getFalsyFlags(checkExpression(declaration.initializer)) & 8192 /* Undefined */); + return annotationIncludesUndefined ? getTypeWithFacts(declaredType, 131072 /* NEUndefined */) : declaredType; } function isConstraintPosition(node) { var parent = node.parent; - return parent.kind === 185 || - parent.kind === 187 && parent.expression === node || - parent.kind === 186 && parent.expression === node || - parent.kind === 182 && parent.name === node && !!parent.initializer; + return parent.kind === 185 /* PropertyAccessExpression */ || + parent.kind === 187 /* CallExpression */ && parent.expression === node || + parent.kind === 186 /* ElementAccessExpression */ && parent.expression === node || + parent.kind === 182 /* BindingElement */ && parent.name === node && !!parent.initializer; } function typeHasNullableConstraint(type) { - return type.flags & 14745600 && maybeTypeOfKind(getBaseConstraintOfType(type) || emptyObjectType, 24576); + return type.flags & 14745600 /* InstantiableNonPrimitive */ && maybeTypeOfKind(getBaseConstraintOfType(type) || emptyObjectType, 24576 /* Nullable */); } function getConstraintForLocation(type, node) { + // When a node is the left hand expression of a property access, element access, or call expression, + // and the type of the node includes type variables with constraints that are nullable, we fetch the + // apparent type of the node *before* performing control flow analysis such that narrowings apply to + // the constraint type. if (type && isConstraintPosition(node) && forEachType(type, typeHasNullableConstraint)) { return mapType(getWidenedType(type), getBaseConstraintOrType); } return type; } function markAliasReferenced(symbol, location) { - if (isNonLocalAlias(symbol, 67216319) && !isInTypeQuery(location) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(symbol))) { + if (isNonLocalAlias(symbol, /*excludes*/ 67216319 /* Value */) && !isInTypeQuery(location) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(symbol))) { markAliasSymbolAsReferenced(symbol); } } @@ -36727,48 +42397,62 @@ var ts; if (symbol === unknownSymbol) { return errorType; } + // As noted in ECMAScript 6 language spec, arrow functions never have an arguments objects. + // Although in down-level emit of arrow function, we emit it using function expression which means that + // arguments objects will be bound to the inner object; emitting arrow function natively in ES6, arguments objects + // will be bound to non-arrow function that contain this arrow function. This results in inconsistent behavior. + // To avoid that we will give an error to users if they use arguments objects in arrow function so that they + // can explicitly bound arguments objects if (symbol === argumentsSymbol) { var container = ts.getContainingFunction(node); - if (languageVersion < 2) { - if (container.kind === 193) { + if (languageVersion < 2 /* ES2015 */) { + if (container.kind === 193 /* ArrowFunction */) { error(node, ts.Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression); } - else if (ts.hasModifier(container, 256)) { + else if (ts.hasModifier(container, 256 /* Async */)) { error(node, ts.Diagnostics.The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_using_a_standard_function_or_method); } } - getNodeLinks(container).flags |= 8192; + getNodeLinks(container).flags |= 8192 /* CaptureArguments */; return getTypeOfSymbol(symbol); } + // We should only mark aliases as referenced if there isn't a local value declaration + // for the symbol. Also, don't mark any property access expression LHS - checkPropertyAccessExpression will handle that if (!(node.parent && ts.isPropertyAccessExpression(node.parent) && node.parent.expression === node)) { markAliasReferenced(symbol, node); } var localOrExportSymbol = getExportSymbolOfValueSymbolIfExported(symbol); var declaration = localOrExportSymbol.valueDeclaration; - if (localOrExportSymbol.flags & 32) { - if (declaration.kind === 235 + if (localOrExportSymbol.flags & 32 /* Class */) { + // Due to the emit for class decorators, any reference to the class from inside of the class body + // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind + // behavior of class names in ES6. + if (declaration.kind === 235 /* ClassDeclaration */ && ts.nodeIsDecorated(declaration)) { var container = ts.getContainingClass(node); while (container !== undefined) { if (container === declaration && container.name !== node) { - getNodeLinks(declaration).flags |= 8388608; - getNodeLinks(node).flags |= 16777216; + getNodeLinks(declaration).flags |= 8388608 /* ClassWithConstructorReference */; + getNodeLinks(node).flags |= 16777216 /* ConstructorReferenceInClass */; break; } container = ts.getContainingClass(container); } } - else if (declaration.kind === 205) { - var container = ts.getThisContainer(node, false); - while (container.kind !== 274) { + else if (declaration.kind === 205 /* ClassExpression */) { + // When we emit a class expression with static members that contain a reference + // to the constructor in the initializer, we will need to substitute that + // binding with an alias as the class name is not in scope. + var container = ts.getThisContainer(node, /*includeArrowFunctions*/ false); + while (container.kind !== 274 /* SourceFile */) { if (container.parent === declaration) { - if (container.kind === 152 && ts.hasModifier(container, 32)) { - getNodeLinks(declaration).flags |= 8388608; - getNodeLinks(node).flags |= 16777216; + if (container.kind === 152 /* PropertyDeclaration */ && ts.hasModifier(container, 32 /* Static */)) { + getNodeLinks(declaration).flags |= 8388608 /* ClassWithConstructorReference */; + getNodeLinks(node).flags |= 16777216 /* ConstructorReferenceInClass */; } break; } - container = ts.getThisContainer(container, false); + container = ts.getThisContainer(container, /*includeArrowFunctions*/ false); } } } @@ -36776,8 +42460,8 @@ var ts; var type = getConstraintForLocation(getTypeOfSymbol(localOrExportSymbol), node); var assignmentKind = ts.getAssignmentTargetKind(node); if (assignmentKind) { - if (!(localOrExportSymbol.flags & 3) && - !(ts.isInJavaScriptFile(node) && localOrExportSymbol.flags & 512)) { + if (!(localOrExportSymbol.flags & 3 /* Variable */) && + !(ts.isInJavaScriptFile(node) && localOrExportSymbol.flags & 512 /* ValueModule */)) { error(node, ts.Diagnostics.Cannot_assign_to_0_because_it_is_not_a_variable, symbolToString(symbol)); return errorType; } @@ -36786,9 +42470,11 @@ var ts; return errorType; } } - var isAlias = localOrExportSymbol.flags & 2097152; - if (localOrExportSymbol.flags & 3) { - if (assignmentKind === 1) { + var isAlias = localOrExportSymbol.flags & 2097152 /* Alias */; + // We only narrow variables and parameters occurring in a non-assignment position. For all other + // entities we simply return the declared type. + if (localOrExportSymbol.flags & 3 /* Variable */) { + if (assignmentKind === 1 /* Definite */) { return type; } } @@ -36801,26 +42487,38 @@ var ts; if (!declaration) { return type; } - var isParameter = ts.getRootDeclaration(declaration).kind === 149; + // The declaration container is the innermost function that encloses the declaration of the variable + // or parameter. The flow container is the innermost function starting with which we analyze the control + // flow graph to determine the control flow based type. + var isParameter = ts.getRootDeclaration(declaration).kind === 149 /* Parameter */; var declarationContainer = getControlFlowContainer(declaration); var flowContainer = getControlFlowContainer(node); var isOuterVariable = flowContainer !== declarationContainer; var isSpreadDestructuringAsignmentTarget = node.parent && node.parent.parent && ts.isSpreadAssignment(node.parent) && isDestructuringAssignmentTarget(node.parent.parent); - while (flowContainer !== declarationContainer && (flowContainer.kind === 192 || - flowContainer.kind === 193 || ts.isObjectLiteralOrClassExpressionMethod(flowContainer)) && + // When the control flow originates in a function expression or arrow function and we are referencing + // a const variable or parameter from an outer function, we extend the origin of the control flow + // analysis to include the immediately enclosing function. + while (flowContainer !== declarationContainer && (flowContainer.kind === 192 /* FunctionExpression */ || + flowContainer.kind === 193 /* ArrowFunction */ || ts.isObjectLiteralOrClassExpressionMethod(flowContainer)) && (isConstVariable(localOrExportSymbol) || isParameter && !isParameterAssigned(localOrExportSymbol))) { flowContainer = getControlFlowContainer(flowContainer); } + // We only look for uninitialized variables in strict null checking mode, and only when we can analyze + // the entire control flow graph from the variable's declaration (i.e. when the flow container and + // declaration container are the same). var assumeInitialized = isParameter || isAlias || isOuterVariable || isSpreadDestructuringAsignmentTarget || - type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & 3) !== 0 || - isInTypeQuery(node) || node.parent.kind === 252) || - node.parent.kind === 209 || - declaration.kind === 232 && declaration.exclamationToken || - declaration.flags & 4194304; + type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & 3 /* AnyOrUnknown */) !== 0 || + isInTypeQuery(node) || node.parent.kind === 252 /* ExportSpecifier */) || + node.parent.kind === 209 /* NonNullExpression */ || + declaration.kind === 232 /* VariableDeclaration */ && declaration.exclamationToken || + declaration.flags & 4194304 /* Ambient */; var initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, declaration) : type) : type === autoType || type === autoArrayType ? undefinedType : getOptionalType(type); var flowType = getFlowTypeOfReference(node, type, initialType, flowContainer, !assumeInitialized); + // A variable is considered uninitialized when it is possible to analyze the entire control flow graph + // from declaration to use, and when the variable's declared type doesn't include undefined but the + // control flow based type does include undefined. if (type === autoType || type === autoArrayType) { if (flowType === autoType || flowType === autoArrayType) { if (noImplicitAny) { @@ -36830,8 +42528,9 @@ var ts; return convertAutoToAny(flowType); } } - else if (!assumeInitialized && !(getFalsyFlags(type) & 8192) && getFalsyFlags(flowType) & 8192) { + else if (!assumeInitialized && !(getFalsyFlags(type) & 8192 /* Undefined */) && getFalsyFlags(flowType) & 8192 /* Undefined */) { error(node, ts.Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol)); + // Return the declared type to reduce follow-on errors return type; } return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType; @@ -36840,17 +42539,21 @@ var ts; return !!ts.findAncestor(node, function (n) { return n === threshold ? "quit" : ts.isFunctionLike(n); }); } function checkNestedBlockScopedBinding(node, symbol) { - if (languageVersion >= 2 || - (symbol.flags & (2 | 32)) === 0 || - symbol.valueDeclaration.parent.kind === 269) { + if (languageVersion >= 2 /* ES2015 */ || + (symbol.flags & (2 /* BlockScopedVariable */ | 32 /* Class */)) === 0 || + symbol.valueDeclaration.parent.kind === 269 /* CatchClause */) { return; } + // 1. walk from the use site up to the declaration and check + // if there is anything function like between declaration and use-site (is binding/class is captured in function). + // 2. walk from the declaration up to the boundary of lexical environment and check + // if there is an iteration statement in between declaration and boundary (is binding/class declared inside iteration statement) var container = ts.getEnclosingBlockScopeContainer(symbol.valueDeclaration); var usedInFunction = isInsideFunction(node.parent, container); var current = container; var containedInIterationStatement = false; while (current && !ts.nodeStartsNewLexicalEnvironment(current)) { - if (ts.isIterationStatement(current, false)) { + if (ts.isIterationStatement(current, /*lookInLabeledStatements*/ false)) { containedInIterationStatement = true; break; } @@ -36858,45 +42561,53 @@ var ts; } if (containedInIterationStatement) { if (usedInFunction) { - getNodeLinks(current).flags |= 65536; + // mark iteration statement as containing block-scoped binding captured in some function + getNodeLinks(current).flags |= 65536 /* LoopWithCapturedBlockScopedBinding */; } - if (container.kind === 220 && - ts.getAncestor(symbol.valueDeclaration, 233).parent === container && + // mark variables that are declared in loop initializer and reassigned inside the body of ForStatement. + // if body of ForStatement will be converted to function then we'll need a extra machinery to propagate reassigned values back. + if (container.kind === 220 /* ForStatement */ && + ts.getAncestor(symbol.valueDeclaration, 233 /* VariableDeclarationList */).parent === container && isAssignedInBodyOfForStatement(node, container)) { - getNodeLinks(symbol.valueDeclaration).flags |= 2097152; + getNodeLinks(symbol.valueDeclaration).flags |= 2097152 /* NeedsLoopOutParameter */; } - getNodeLinks(symbol.valueDeclaration).flags |= 262144; + // set 'declared inside loop' bit on the block-scoped binding + getNodeLinks(symbol.valueDeclaration).flags |= 262144 /* BlockScopedBindingInLoop */; } if (usedInFunction) { - getNodeLinks(symbol.valueDeclaration).flags |= 131072; + getNodeLinks(symbol.valueDeclaration).flags |= 131072 /* CapturedBlockScopedBinding */; } } function isAssignedInBodyOfForStatement(node, container) { + // skip parenthesized nodes var current = node; - while (current.parent.kind === 191) { + while (current.parent.kind === 191 /* ParenthesizedExpression */) { current = current.parent; } + // check if node is used as LHS in some assignment expression var isAssigned = false; if (ts.isAssignmentTarget(current)) { isAssigned = true; } - else if ((current.parent.kind === 198 || current.parent.kind === 199)) { + else if ((current.parent.kind === 198 /* PrefixUnaryExpression */ || current.parent.kind === 199 /* PostfixUnaryExpression */)) { var expr = current.parent; - isAssigned = expr.operator === 43 || expr.operator === 44; + isAssigned = expr.operator === 43 /* PlusPlusToken */ || expr.operator === 44 /* MinusMinusToken */; } if (!isAssigned) { return false; } + // at this point we know that node is the target of assignment + // now check that modification happens inside the statement part of the ForStatement return !!ts.findAncestor(current, function (n) { return n === container ? "quit" : n === container.statement; }); } function captureLexicalThis(node, container) { - getNodeLinks(node).flags |= 2; - if (container.kind === 152 || container.kind === 155) { + getNodeLinks(node).flags |= 2 /* LexicalThis */; + if (container.kind === 152 /* PropertyDeclaration */ || container.kind === 155 /* Constructor */) { var classNode = container.parent; - getNodeLinks(classNode).flags |= 4; + getNodeLinks(classNode).flags |= 4 /* CaptureThis */; } else { - getNodeLinks(container).flags |= 4; + getNodeLinks(container).flags |= 4 /* CaptureThis */; } } function findFirstSuperCall(n) { @@ -36908,14 +42619,26 @@ var ts; } return ts.forEachChild(n, findFirstSuperCall); } + /** + * Return a cached result if super-statement is already found. + * Otherwise, find a super statement in a given constructor function and cache the result in the node-links of the constructor + * + * @param constructor constructor-function to look for super statement + */ function getSuperCallInConstructor(constructor) { var links = getNodeLinks(constructor); + // Only trying to find super-call if we haven't yet tried to find one. Once we try, we will record the result if (links.hasSuperCall === undefined) { links.superCall = findFirstSuperCall(constructor.body); links.hasSuperCall = links.superCall ? true : false; } return links.superCall; } + /** + * Check if the given class-declaration extends null then return true. + * Otherwise, return false + * @param classDecl a class declaration to check if it extends null + */ function classDeclarationExtendsNull(classDecl) { var classSymbol = getSymbolOfNode(classDecl); var classInstanceType = getDeclaredTypeOfSymbol(classSymbol); @@ -36925,42 +42648,60 @@ var ts; function checkThisBeforeSuper(node, container, diagnosticMessage) { var containingClassDecl = container.parent; var baseTypeNode = ts.getClassExtendsHeritageClauseElement(containingClassDecl); + // If a containing class does not have extends clause or the class extends null + // skip checking whether super statement is called before "this" accessing. if (baseTypeNode && !classDeclarationExtendsNull(containingClassDecl)) { var superCall = getSuperCallInConstructor(container); + // We should give an error in the following cases: + // - No super-call + // - "this" is accessing before super-call. + // i.e super(this) + // this.x; super(); + // We want to make sure that super-call is done before accessing "this" so that + // "this" is not accessed as a parameter of the super-call. if (!superCall || superCall.end > node.pos) { + // In ES6, super inside constructor of class-declaration has to precede "this" accessing error(node, diagnosticMessage); } } } function checkThisExpression(node) { - var container = ts.getThisContainer(node, true); + // Stop at the first arrow function so that we can + // tell whether 'this' needs to be captured. + var container = ts.getThisContainer(node, /* includeArrowFunctions */ true); var needToCaptureLexicalThis = false; - if (container.kind === 155) { + if (container.kind === 155 /* Constructor */) { checkThisBeforeSuper(node, container, ts.Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class); } - if (container.kind === 193) { - container = ts.getThisContainer(container, false); - needToCaptureLexicalThis = (languageVersion < 2); + // Now skip arrow functions to get the "real" owner of 'this'. + if (container.kind === 193 /* ArrowFunction */) { + container = ts.getThisContainer(container, /* includeArrowFunctions */ false); + // When targeting es6, arrow function lexically bind "this" so we do not need to do the work of binding "this" in emitted code + needToCaptureLexicalThis = (languageVersion < 2 /* ES2015 */); } switch (container.kind) { - case 239: + case 239 /* ModuleDeclaration */: error(node, ts.Diagnostics.this_cannot_be_referenced_in_a_module_or_namespace_body); + // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks break; - case 238: + case 238 /* EnumDeclaration */: error(node, ts.Diagnostics.this_cannot_be_referenced_in_current_location); + // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks break; - case 155: + case 155 /* Constructor */: if (isInConstructorArgumentInitializer(node, container)) { error(node, ts.Diagnostics.this_cannot_be_referenced_in_constructor_arguments); + // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks } break; - case 152: - case 151: - if (ts.hasModifier(container, 32)) { + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + if (ts.hasModifier(container, 32 /* Static */)) { error(node, ts.Diagnostics.this_cannot_be_referenced_in_a_static_property_initializer); + // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks } break; - case 147: + case 147 /* ComputedPropertyName */: error(node, ts.Diagnostics.this_cannot_be_referenced_in_a_computed_property_name); break; } @@ -36969,23 +42710,28 @@ var ts; } var type = tryGetThisTypeAt(node, container); if (!type && noImplicitThis) { + // With noImplicitThis, functions may not reference 'this' if it has type 'any' error(node, ts.Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation); } return type || anyType; } function tryGetThisTypeAt(node, container) { - if (container === void 0) { container = ts.getThisContainer(node, false); } + if (container === void 0) { container = ts.getThisContainer(node, /*includeArrowFunctions*/ false); } if (ts.isFunctionLike(container) && (!isInParameterInitializerBeforeContainingFunction(node) || ts.getThisParameter(container))) { - if (container.kind === 192 && - container.parent.kind === 200 && - ts.getSpecialPropertyAssignmentKind(container.parent) === 3) { - var className = container.parent - .left - .expression - .expression; + // Note: a parameter initializer should refer to class-this unless function-this is explicitly annotated. + // If this is a function in a JS file, it might be a class method. Check if it's the RHS + // of a x.prototype.y = function [name]() { .... } + if (container.kind === 192 /* FunctionExpression */ && + container.parent.kind === 200 /* BinaryExpression */ && + ts.getSpecialPropertyAssignmentKind(container.parent) === 3 /* PrototypeProperty */) { + // Get the 'x' of 'x.prototype.y = f' (here, 'f' is 'container') + var className = container.parent // x.prototype.y = f + .left // x.prototype.y + .expression // x.prototype + .expression; // x var classSymbol = checkExpression(className).symbol; - if (classSymbol && classSymbol.members && (classSymbol.flags & 16)) { + if (classSymbol && classSymbol.members && (classSymbol.flags & 16 /* Function */)) { return getFlowTypeOfReference(node, getInferredClassType(classSymbol)); } } @@ -36996,7 +42742,7 @@ var ts; } if (ts.isClassLike(container.parent)) { var symbol = getSymbolOfNode(container.parent); - var type = ts.hasModifier(container, 32) ? getTypeOfSymbol(symbol) : getDeclaredTypeOfSymbol(symbol).thisType; + var type = ts.hasModifier(container, 32 /* Static */) ? getTypeOfSymbol(symbol) : getDeclaredTypeOfSymbol(symbol).thisType; return getFlowTypeOfReference(node, type); } if (ts.isInJavaScriptFile(node)) { @@ -37008,7 +42754,7 @@ var ts; } function getTypeForThisExpressionFromJSDoc(node) { var jsdocType = ts.getJSDocType(node); - if (jsdocType && jsdocType.kind === 284) { + if (jsdocType && jsdocType.kind === 284 /* JSDocFunctionType */) { var jsDocFunctionType = jsdocType; if (jsDocFunctionType.parameters.length > 0 && jsDocFunctionType.parameters[0].name && @@ -37022,29 +42768,35 @@ var ts; } } function isInConstructorArgumentInitializer(node, constructorDecl) { - return !!ts.findAncestor(node, function (n) { return n === constructorDecl ? "quit" : n.kind === 149; }); + return !!ts.findAncestor(node, function (n) { return n === constructorDecl ? "quit" : n.kind === 149 /* Parameter */; }); } function checkSuperExpression(node) { - var isCallExpression = node.parent.kind === 187 && node.parent.expression === node; - var container = ts.getSuperContainer(node, true); + var isCallExpression = node.parent.kind === 187 /* CallExpression */ && node.parent.expression === node; + var container = ts.getSuperContainer(node, /*stopOnFunctions*/ true); var needToCaptureLexicalThis = false; + // adjust the container reference in case if super is used inside arrow functions with arbitrarily deep nesting if (!isCallExpression) { - while (container && container.kind === 193) { - container = ts.getSuperContainer(container, true); - needToCaptureLexicalThis = languageVersion < 2; + while (container && container.kind === 193 /* ArrowFunction */) { + container = ts.getSuperContainer(container, /*stopOnFunctions*/ true); + needToCaptureLexicalThis = languageVersion < 2 /* ES2015 */; } } var canUseSuperExpression = isLegalUsageOfSuperExpression(container); var nodeCheckFlag = 0; if (!canUseSuperExpression) { - var current = ts.findAncestor(node, function (n) { return n === container ? "quit" : n.kind === 147; }); - if (current && current.kind === 147) { + // issue more specific error if super is used in computed property name + // class A { foo() { return "1" }} + // class B { + // [super.foo()]() {} + // } + var current = ts.findAncestor(node, function (n) { return n === container ? "quit" : n.kind === 147 /* ComputedPropertyName */; }); + if (current && current.kind === 147 /* ComputedPropertyName */) { error(node, ts.Diagnostics.super_cannot_be_referenced_in_a_computed_property_name); } else if (isCallExpression) { error(node, ts.Diagnostics.Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors); } - else if (!container || !container.parent || !(ts.isClassLike(container.parent) || container.parent.kind === 184)) { + else if (!container || !container.parent || !(ts.isClassLike(container.parent) || container.parent.kind === 184 /* ObjectLiteralExpression */)) { error(node, ts.Diagnostics.super_can_only_be_referenced_in_members_of_derived_classes_or_object_literal_expressions); } else { @@ -37052,36 +42804,97 @@ var ts; } return errorType; } - if (!isCallExpression && container.kind === 155) { + if (!isCallExpression && container.kind === 155 /* Constructor */) { checkThisBeforeSuper(node, container, ts.Diagnostics.super_must_be_called_before_accessing_a_property_of_super_in_the_constructor_of_a_derived_class); } - if (ts.hasModifier(container, 32) || isCallExpression) { - nodeCheckFlag = 512; + if (ts.hasModifier(container, 32 /* Static */) || isCallExpression) { + nodeCheckFlag = 512 /* SuperStatic */; } else { - nodeCheckFlag = 256; + nodeCheckFlag = 256 /* SuperInstance */; } getNodeLinks(node).flags |= nodeCheckFlag; - if (container.kind === 154 && ts.hasModifier(container, 256)) { + // Due to how we emit async functions, we need to specialize the emit for an async method that contains a `super` reference. + // This is due to the fact that we emit the body of an async function inside of a generator function. As generator + // functions cannot reference `super`, we emit a helper inside of the method body, but outside of the generator. This helper + // uses an arrow function, which is permitted to reference `super`. + // + // There are two primary ways we can access `super` from within an async method. The first is getting the value of a property + // or indexed access on super, either as part of a right-hand-side expression or call expression. The second is when setting the value + // of a property or indexed access, either as part of an assignment expression or destructuring assignment. + // + // The simplest case is reading a value, in which case we will emit something like the following: + // + // // ts + // ... + // async asyncMethod() { + // let x = await super.asyncMethod(); + // return x; + // } + // ... + // + // // js + // ... + // asyncMethod() { + // const _super = name => super[name]; + // return __awaiter(this, arguments, Promise, function *() { + // let x = yield _super("asyncMethod").call(this); + // return x; + // }); + // } + // ... + // + // The more complex case is when we wish to assign a value, especially as part of a destructuring assignment. As both cases + // are legal in ES6, but also likely less frequent, we emit the same more complex helper for both scenarios: + // + // // ts + // ... + // async asyncMethod(ar: Promise) { + // [super.a, super.b] = await ar; + // } + // ... + // + // // js + // ... + // asyncMethod(ar) { + // const _super = (function (geti, seti) { + // const cache = Object.create(null); + // return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } }); + // })(name => super[name], (name, value) => super[name] = value); + // return __awaiter(this, arguments, Promise, function *() { + // [_super("a").value, _super("b").value] = yield ar; + // }); + // } + // ... + // + // This helper creates an object with a "value" property that wraps the `super` property or indexed access for both get and set. + // This is required for destructuring assignments, as a call expression cannot be used as the target of a destructuring assignment + // while a property access can. + if (container.kind === 154 /* MethodDeclaration */ && ts.hasModifier(container, 256 /* Async */)) { if (ts.isSuperProperty(node.parent) && ts.isAssignmentTarget(node.parent)) { - getNodeLinks(container).flags |= 4096; + getNodeLinks(container).flags |= 4096 /* AsyncMethodWithSuperBinding */; } else { - getNodeLinks(container).flags |= 2048; + getNodeLinks(container).flags |= 2048 /* AsyncMethodWithSuper */; } } 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 (container.parent.kind === 184) { - if (languageVersion < 2) { + if (container.parent.kind === 184 /* ObjectLiteralExpression */) { + if (languageVersion < 2 /* ES2015 */) { error(node, ts.Diagnostics.super_is_only_allowed_in_members_of_object_literal_expressions_when_option_target_is_ES2015_or_higher); return errorType; } else { + // for object literal assume that type of 'super' is 'any' return anyType; } } + // at this point the only legal case for parent is ClassLikeDeclaration var classLikeDeclaration = container.parent; if (!ts.getClassExtendsHeritageClauseElement(classLikeDeclaration)) { error(node, ts.Diagnostics.super_can_only_be_referenced_in_a_derived_class); @@ -37092,11 +42905,12 @@ var ts; if (!baseClassType) { return errorType; } - if (container.kind === 155 && isInConstructorArgumentInitializer(node, container)) { + if (container.kind === 155 /* Constructor */ && isInConstructorArgumentInitializer(node, container)) { + // issue custom error message for super property access in constructor arguments (to be aligned with old compiler) error(node, ts.Diagnostics.super_cannot_be_referenced_in_constructor_arguments); return errorType; } - return nodeCheckFlag === 512 + return nodeCheckFlag === 512 /* SuperStatic */ ? getBaseConstructorTypeOfClass(classType) : getTypeWithThisArgument(baseClassType, classType.thisType); function isLegalUsageOfSuperExpression(container) { @@ -37104,24 +42918,31 @@ var ts; return false; } if (isCallExpression) { - return container.kind === 155; + // TS 1.0 SPEC (April 2014): 4.8.1 + // Super calls are only permitted in constructors of derived classes + return container.kind === 155 /* Constructor */; } else { - if (ts.isClassLike(container.parent) || container.parent.kind === 184) { - if (ts.hasModifier(container, 32)) { - return container.kind === 154 || - container.kind === 153 || - container.kind === 156 || - container.kind === 157; + // TS 1.0 SPEC (April 2014) + // 'super' property access is allowed + // - In a constructor, instance member function, instance member accessor, or instance member variable initializer where this references a derived class instance + // - In a static member function or static member accessor + // topmost container must be something that is directly nested in the class declaration\object literal expression + if (ts.isClassLike(container.parent) || container.parent.kind === 184 /* ObjectLiteralExpression */) { + if (ts.hasModifier(container, 32 /* Static */)) { + return container.kind === 154 /* MethodDeclaration */ || + container.kind === 153 /* MethodSignature */ || + container.kind === 156 /* GetAccessor */ || + container.kind === 157 /* SetAccessor */; } else { - return container.kind === 154 || - container.kind === 153 || - container.kind === 156 || - container.kind === 157 || - container.kind === 152 || - container.kind === 151 || - container.kind === 155; + return container.kind === 154 /* MethodDeclaration */ || + container.kind === 153 /* MethodSignature */ || + container.kind === 156 /* GetAccessor */ || + container.kind === 157 /* SetAccessor */ || + container.kind === 152 /* PropertyDeclaration */ || + container.kind === 151 /* PropertySignature */ || + container.kind === 155 /* Constructor */; } } } @@ -37129,22 +42950,22 @@ var ts; } } function getContainingObjectLiteral(func) { - return (func.kind === 154 || - func.kind === 156 || - func.kind === 157) && func.parent.kind === 184 ? func.parent : - func.kind === 192 && func.parent.kind === 270 ? func.parent.parent : + return (func.kind === 154 /* MethodDeclaration */ || + func.kind === 156 /* GetAccessor */ || + func.kind === 157 /* SetAccessor */) && func.parent.kind === 184 /* ObjectLiteralExpression */ ? func.parent : + func.kind === 192 /* FunctionExpression */ && func.parent.kind === 270 /* PropertyAssignment */ ? func.parent.parent : undefined; } function getThisTypeArgument(type) { - return ts.getObjectFlags(type) & 4 && type.target === globalThisType ? type.typeArguments[0] : undefined; + return ts.getObjectFlags(type) & 4 /* Reference */ && type.target === globalThisType ? type.typeArguments[0] : undefined; } function getThisTypeFromContextualType(type) { return mapType(type, function (t) { - return t.flags & 524288 ? ts.forEach(t.types, getThisTypeArgument) : getThisTypeArgument(t); + return t.flags & 524288 /* Intersection */ ? ts.forEach(t.types, getThisTypeArgument) : getThisTypeArgument(t); }); } function getContextualThisParameterType(func) { - if (func.kind === 193) { + if (func.kind === 193 /* ArrowFunction */) { return undefined; } if (isContextSensitiveFunctionOrObjectLiteralMethod(func)) { @@ -37160,6 +42981,9 @@ var ts; if (noImplicitThis || inJs) { var containingLiteral = getContainingObjectLiteral(func); if (containingLiteral) { + // We have an object literal method. Check if the containing object literal has a contextual type + // that includes a ThisType. If so, T is the contextual type for 'this'. We continue looking in + // any directly enclosing object literals. var contextualType = getApparentTypeOfContextualType(containingLiteral); var literal = containingLiteral; var type = contextualType; @@ -37168,19 +42992,25 @@ var ts; if (thisType) { return instantiateType(thisType, getContextualMapper(containingLiteral)); } - if (literal.parent.kind !== 270) { + if (literal.parent.kind !== 270 /* PropertyAssignment */) { break; } literal = literal.parent.parent; type = getApparentTypeOfContextualType(literal); } + // There was no contextual ThisType for the containing object literal, so the contextual type + // for 'this' is the non-null form of the contextual type for the containing object literal or + // the type of the object literal itself. return contextualType ? getNonNullableType(contextualType) : checkExpressionCached(containingLiteral); } + // In an assignment of the form 'obj.xxx = function(...)' or 'obj[xxx] = function(...)', the + // contextual type for 'this' is 'obj'. var parent = func.parent; - if (parent.kind === 200 && parent.operatorToken.kind === 58) { + if (parent.kind === 200 /* BinaryExpression */ && parent.operatorToken.kind === 58 /* EqualsToken */) { var target = parent.left; - if (target.kind === 185 || target.kind === 186) { + if (target.kind === 185 /* PropertyAccessExpression */ || target.kind === 186 /* ElementAccessExpression */) { var expression = target.expression; + // Don't contextually type `this` as `exports` in `exports.Point = function(x, y) { this.x = x; this.y = y; }` if (inJs && ts.isIdentifier(expression)) { var sourceFile = ts.getSourceFileOfNode(parent); if (sourceFile.commonJsModuleIndicator && getResolvedSymbol(expression) === sourceFile.symbol) { @@ -37193,6 +43023,7 @@ var ts; } return undefined; } + // Return contextual type of parameter or undefined if no contextual type is available function getContextuallyTypedParameterType(parameter) { var func = parameter.parent; if (!isContextSensitiveFunctionOrObjectLiteralMethod(func)) { @@ -37223,12 +43054,13 @@ var ts; var len = func.parameters.length - (funcHasRestParameters ? 1 : 0); var indexOfParameter = func.parameters.indexOf(parameter); if (ts.getThisParameter(func) !== undefined && !contextualSignature.thisParameter) { - ts.Debug.assert(indexOfParameter !== 0); + ts.Debug.assert(indexOfParameter !== 0); // Otherwise we should not have called `getContextuallyTypedParameterType`. indexOfParameter -= 1; } if (indexOfParameter < len) { return getTypeAtPosition(contextualSignature, indexOfParameter); } + // If last parameter is contextually rest parameter get its type if (funcHasRestParameters && indexOfParameter === (func.parameters.length - 1) && isRestParameterIndex(contextualSignature, func.parameters.length - 1)) { @@ -37236,6 +43068,14 @@ var ts; } } } + // In a variable, parameter or property declaration with a type annotation, + // the contextual type of an initializer expression is the type of the variable, parameter or property. + // Otherwise, in a parameter declaration of a contextually typed function expression, + // the contextual type of an initializer expression is the contextual type of the parameter. + // Otherwise, in a variable or parameter declaration with a binding pattern name, + // the contextual type of an initializer expression is the type implied by the binding pattern. + // Otherwise, in a binding pattern inside a variable or parameter declaration, + // the contextual type of an initializer expression is the type annotation of the containing declaration, if present. function getContextualTypeForInitializerExpression(node) { var declaration = node.parent; if (ts.hasInitializer(declaration) && node === declaration.initializer) { @@ -37243,19 +43083,19 @@ var ts; if (typeNode) { return getTypeFromTypeNode(typeNode); } - if (declaration.kind === 149) { + if (declaration.kind === 149 /* Parameter */) { var type = getContextuallyTypedParameterType(declaration); if (type) { return type; } } if (ts.isBindingPattern(declaration.name)) { - return getTypeFromBindingPattern(declaration.name, true, false); + return getTypeFromBindingPattern(declaration.name, /*includePatternInType*/ true, /*reportErrors*/ false); } if (ts.isBindingPattern(declaration.parent)) { var parentDeclaration = declaration.parent.parent; var name = declaration.propertyName || declaration.name; - if (parentDeclaration.kind !== 182) { + if (parentDeclaration.kind !== 182 /* BindingElement */) { var parentTypeNode = ts.getEffectiveTypeAnnotationNode(parentDeclaration); if (parentTypeNode && !ts.isBindingPattern(name)) { var text = ts.getTextOfPropertyName(name); @@ -37272,13 +43112,13 @@ var ts; var func = ts.getContainingFunction(node); if (func) { var functionFlags = ts.getFunctionFlags(func); - if (functionFlags & 1) { + if (functionFlags & 1 /* Generator */) { // AsyncGenerator function or Generator function return undefined; } var contextualReturnType = getContextualReturnType(func); - return functionFlags & 2 - ? contextualReturnType && getAwaitedTypeOfPromise(contextualReturnType) - : contextualReturnType; + return functionFlags & 2 /* Async */ + ? contextualReturnType && getAwaitedTypeOfPromise(contextualReturnType) // Async function + : contextualReturnType; // Regular function } return undefined; } @@ -37290,7 +43130,7 @@ var ts; if (contextualReturnType) { return node.asteriskToken ? contextualReturnType - : getIteratedTypeOfGenerator(contextualReturnType, (functionFlags & 2) !== 0); + : getIteratedTypeOfGenerator(contextualReturnType, (functionFlags & 2 /* Async */) !== 0); } } return undefined; @@ -37309,28 +43149,35 @@ var ts; return false; } function getContextualReturnType(functionDecl) { - if (functionDecl.kind === 155 || + // If the containing function has a return type annotation, is a constructor, or is a get accessor whose + // corresponding set accessor has a type annotation, return statements in the function are contextually typed + if (functionDecl.kind === 155 /* Constructor */ || ts.getEffectiveReturnTypeNode(functionDecl) || isGetAccessorWithAnnotatedSetAccessor(functionDecl)) { return getReturnTypeOfSignature(getSignatureFromDeclaration(functionDecl)); } + // Otherwise, if the containing function is contextually typed by a function type with exactly one call signature + // and that call signature is non-generic, return statements are contextually typed by the return type of the signature var signature = getContextualSignatureForFunctionLikeDeclaration(functionDecl); if (signature && !isResolvingReturnTypeOfSignature(signature)) { return getReturnTypeOfSignature(signature); } return undefined; } + // In a typed function call, an argument or substitution expression is contextually typed by the type of the corresponding parameter. function getContextualTypeForArgument(callTarget, arg) { - var args = getEffectiveCallArguments(callTarget); - var argIndex = args.indexOf(arg); + var args = getEffectiveCallArguments(callTarget); // TODO: GH#18217 + var argIndex = args.indexOf(arg); // -1 for e.g. the expression of a CallExpression, or the tag of a TaggedTemplateExpression return argIndex === -1 ? undefined : getContextualTypeForArgumentAtIndex(callTarget, argIndex); } function getContextualTypeForArgumentAtIndex(callTarget, argIndex) { + // If we're already in the process of resolving the given signature, don't resolve again as + // that could cause infinite recursion. Instead, return anySignature. var signature = getNodeLinks(callTarget).resolvedSignature === resolvingSignature ? resolvingSignature : getResolvedSignature(callTarget); return getTypeAtPosition(signature, argIndex); } function getContextualTypeForSubstitutionExpression(template, substitutionExpression) { - if (template.parent.kind === 189) { + if (template.parent.kind === 189 /* TaggedTemplateExpression */) { return getContextualTypeForArgument(template.parent, substitutionExpression); } return undefined; @@ -37339,31 +43186,38 @@ var ts; var binaryExpression = node.parent; var left = binaryExpression.left, operatorToken = binaryExpression.operatorToken, right = binaryExpression.right; switch (operatorToken.kind) { - case 58: + case 58 /* EqualsToken */: return node === right && isContextSensitiveAssignment(binaryExpression) ? getTypeOfExpression(left) : undefined; - case 54: + case 54 /* BarBarToken */: + // When an || expression has a contextual type, the operands are contextually typed by that type. When an || + // expression has no contextual type, the right operand is contextually typed by the type of the left operand, + // except for the special case of Javascript declarations of the form `namespace.prop = namespace.prop || {}` var type = getContextualType(binaryExpression); return !type && node === right && !ts.isDefaultedJavascriptInitializer(binaryExpression) ? getTypeOfExpression(left) : type; - case 53: - case 26: + case 53 /* AmpersandAmpersandToken */: + case 26 /* CommaToken */: return node === right ? getContextualType(binaryExpression) : undefined; default: return undefined; } } + // In an assignment expression, the right operand is contextually typed by the type of the left operand. + // Don't do this for special property assignments to avoid circularity. function isContextSensitiveAssignment(binaryExpression) { var kind = ts.getSpecialPropertyAssignmentKind(binaryExpression); switch (kind) { - case 0: + case 0 /* None */: return true; - case 5: + case 5 /* Property */: + // If `binaryExpression.left` was assigned a symbol, then this is a new declaration; otherwise it is an assignment to an existing declaration. + // See `bindStaticPropertyAssignment` in `binder.ts`. return !binaryExpression.left.symbol; - case 1: - case 2: - case 3: - case 4: - case 6: + case 1 /* ExportsProperty */: + case 2 /* ModuleExports */: + case 3 /* PrototypeProperty */: + case 4 /* ThisProperty */: + case 6 /* Prototype */: return false; default: return ts.Debug.assertNever(kind); @@ -37371,19 +43225,24 @@ var ts; } function getTypeOfPropertyOfContextualType(type, name) { return mapType(type, function (t) { - var prop = t.flags & 917504 ? getPropertyOfType(t, name) : undefined; + var prop = t.flags & 917504 /* StructuredType */ ? getPropertyOfType(t, name) : undefined; return prop ? getTypeOfSymbol(prop) : undefined; - }, true); + }, /*noReductions*/ true); } function getIndexTypeOfContextualType(type, kind) { - return mapType(type, function (t) { return getIndexTypeOfStructuredType(t, kind); }, true); + return mapType(type, function (t) { return getIndexTypeOfStructuredType(t, kind); }, /*noReductions*/ true); } + // Return true if the given contextual type is a tuple-like type function contextualTypeIsTupleLikeType(type) { - return !!(type.flags & 262144 ? ts.forEach(type.types, isTupleLikeType) : isTupleLikeType(type)); + return !!(type.flags & 262144 /* Union */ ? ts.forEach(type.types, isTupleLikeType) : isTupleLikeType(type)); } + // In an object literal contextually typed by a type T, the contextual type of a property assignment is the type of + // the matching property in T, if one exists. Otherwise, it is the type of the numeric index signature in T, if one + // exists. Otherwise, it is the type of the string index signature in T, if one exists. function getContextualTypeForObjectLiteralMethod(node) { ts.Debug.assert(ts.isObjectLiteralMethod(node)); - if (node.flags & 8388608) { + if (node.flags & 8388608 /* InWithStatement */) { + // We cannot answer semantic questions within a with block, do not proceed any further return undefined; } return getContextualTypeForObjectLiteralElement(node); @@ -37393,28 +43252,37 @@ var ts; var type = getApparentTypeOfContextualType(objectLiteral); if (type) { if (!hasNonBindableDynamicName(element)) { + // For a (non-symbol) computed property, there is no reason to look up the name + // in the type. It will just be "__computed", which does not appear in any + // SymbolTable. var symbolName_1 = getSymbolOfNode(element).escapedName; var propertyType = getTypeOfPropertyOfContextualType(type, symbolName_1); if (propertyType) { return propertyType; } } - return isNumericName(element.name) && getIndexTypeOfContextualType(type, 1) || - getIndexTypeOfContextualType(type, 0); + return isNumericName(element.name) && getIndexTypeOfContextualType(type, 1 /* Number */) || + getIndexTypeOfContextualType(type, 0 /* String */); } return undefined; } + // In an array literal contextually typed by a type T, the contextual type of an element expression at index N is + // the type of the property with the numeric name N in T, if one exists. Otherwise, if T has a numeric index signature, + // it is the type of the numeric index signature in T. Otherwise, in ES6 and higher, the contextual type is the iterated + // type of T. function getContextualTypeForElementExpression(arrayContextualType, index) { return arrayContextualType && (getTypeOfPropertyOfContextualType(arrayContextualType, "" + index) - || getIndexTypeOfContextualType(arrayContextualType, 1) - || getIteratedTypeOrElementType(arrayContextualType, undefined, false, false, false)); + || getIndexTypeOfContextualType(arrayContextualType, 1 /* Number */) + || getIteratedTypeOrElementType(arrayContextualType, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false, /*checkAssignability*/ false)); } + // In a contextually typed conditional expression, the true/false expressions are contextually typed by the same type. function getContextualTypeForConditionalOperand(node) { var conditional = node.parent; return node === conditional.whenTrue || node === conditional.whenFalse ? getContextualType(conditional) : undefined; } function getContextualTypeForChildJsxExpression(node) { var attributesType = getApparentTypeOfContextualType(node.openingElement.tagName); + // JSX expression is in children of JSX Element, we will look for an "children" atttribute (we get the name from JSX.ElementAttributesProperty) var jsxChildrenPropertyName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(node)); return attributesType && !isTypeAny(attributesType) && jsxChildrenPropertyName && jsxChildrenPropertyName !== "" ? getTypeOfPropertyOfContextualType(attributesType, jsxChildrenPropertyName) : undefined; } @@ -37427,6 +43295,9 @@ var ts; : undefined; } function getContextualTypeForJsxAttribute(attribute) { + // When we trying to resolve JsxOpeningLikeElement as a stateless function element, we will already give its attributes a contextual type + // which is a type of the parameter of the signature we are trying out. + // If there is no contextual type (e.g. we are trying to resolve stateful component), get attributes type from resolving element's tagName if (ts.isJsxAttribute(attribute)) { var attributesType = getApparentTypeOfContextualType(attribute.parent); if (!attributesType || isTypeAny(attributesType)) { @@ -37438,44 +43309,50 @@ var ts; return getContextualType(attribute.parent); } } + // Return true if the given expression is possibly a discriminant value. We limit the kinds of + // expressions we check to those that don't depend on their contextual type in order not to cause + // recursive (and possibly infinite) invocations of getContextualType. function isPossiblyDiscriminantValue(node) { switch (node.kind) { - case 9: - case 8: - case 13: - case 101: - case 86: - case 95: - case 71: + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: + case 13 /* NoSubstitutionTemplateLiteral */: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: + case 95 /* NullKeyword */: + case 71 /* Identifier */: return true; - case 185: - case 191: + case 185 /* PropertyAccessExpression */: + case 191 /* ParenthesizedExpression */: return isPossiblyDiscriminantValue(node.expression); } return false; } + // Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily + // be "pushed" onto a node using the contextualType property. function getApparentTypeOfContextualType(node) { var contextualType = getContextualType(node); contextualType = contextualType && mapType(contextualType, getApparentType); - if (!(contextualType && contextualType.flags & 262144 && ts.isObjectLiteralExpression(node))) { + if (!(contextualType && contextualType.flags & 262144 /* Union */ && ts.isObjectLiteralExpression(node))) { return contextualType; } + // Keep the below up-to-date with the work done within `isRelatedTo` by `findMatchingDiscriminantType` var match; propLoop: for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { var prop = _a[_i]; if (!prop.symbol) continue; - if (prop.kind !== 270) + if (prop.kind !== 270 /* PropertyAssignment */) continue; if (isPossiblyDiscriminantValue(prop.initializer) && isDiscriminantProperty(contextualType, prop.symbol.escapedName)) { var discriminatingType = checkExpression(prop.initializer); for (var _b = 0, _c = contextualType.types; _b < _c.length; _b++) { var type = _c[_b]; var targetType = getTypeOfPropertyOfType(type, prop.symbol.escapedName); - if (targetType && checkTypeAssignableTo(discriminatingType, targetType, undefined)) { + if (targetType && checkTypeAssignableTo(discriminatingType, targetType, /*errorNode*/ undefined)) { if (match) { if (type === match) - continue; + continue; // Finding multiple fields which discriminate to the same type is fine match = undefined; break propLoop; } @@ -37486,8 +43363,26 @@ var ts; } return match || contextualType; } + /** + * Woah! Do you really want to use this function? + * + * Unless you're trying to get the *non-apparent* type for a + * value-literal type or you're authoring relevant portions of this algorithm, + * you probably meant to use 'getApparentTypeOfContextualType'. + * Otherwise this may not be very useful. + * + * In cases where you *are* working on this function, you should understand + * when it is appropriate to use 'getContextualType' and 'getApparentTypeOfContextualType'. + * + * - Use 'getContextualType' when you are simply going to propagate the result to the expression. + * - Use 'getApparentTypeOfContextualType' when you're going to need the members of the type. + * + * @param node the expression whose contextual type will be returned. + * @returns the contextual type of an expression. + */ function getContextualType(node) { - if (node.flags & 8388608) { + if (node.flags & 8388608 /* InWithStatement */) { + // We cannot answer semantic questions within a with block, do not proceed any further return undefined; } if (node.contextualType) { @@ -37495,51 +43390,52 @@ var ts; } var parent = node.parent; switch (parent.kind) { - case 232: - case 149: - case 152: - case 151: - case 182: + case 232 /* VariableDeclaration */: + case 149 /* Parameter */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 182 /* BindingElement */: return getContextualTypeForInitializerExpression(node); - case 193: - case 225: + case 193 /* ArrowFunction */: + case 225 /* ReturnStatement */: return getContextualTypeForReturnExpression(node); - case 203: + case 203 /* YieldExpression */: return getContextualTypeForYieldOperand(parent); - case 187: - case 188: + case 187 /* CallExpression */: + case 188 /* NewExpression */: return getContextualTypeForArgument(parent, node); - case 190: - case 208: + case 190 /* TypeAssertionExpression */: + case 208 /* AsExpression */: return getTypeFromTypeNode(parent.type); - case 200: + case 200 /* BinaryExpression */: return getContextualTypeForBinaryOperand(node); - case 270: - case 271: + case 270 /* PropertyAssignment */: + case 271 /* ShorthandPropertyAssignment */: return getContextualTypeForObjectLiteralElement(parent); - case 272: + case 272 /* SpreadAssignment */: return getApparentTypeOfContextualType(parent.parent); - case 183: { + case 183 /* ArrayLiteralExpression */: { var arrayLiteral = parent; var type = getApparentTypeOfContextualType(arrayLiteral); return getContextualTypeForElementExpression(type, ts.indexOfNode(arrayLiteral.elements, node)); } - case 201: + case 201 /* ConditionalExpression */: return getContextualTypeForConditionalOperand(node); - case 211: - ts.Debug.assert(parent.parent.kind === 202); + case 211 /* TemplateSpan */: + ts.Debug.assert(parent.parent.kind === 202 /* TemplateExpression */); return getContextualTypeForSubstitutionExpression(parent.parent, node); - case 191: { + case 191 /* ParenthesizedExpression */: { + // Like in `checkParenthesizedExpression`, an `/** @type {xyz} */` comment before a parenthesized expression acts as a type cast. var tag = ts.isInJavaScriptFile(parent) ? ts.getJSDocTypeTag(parent) : undefined; return tag ? getTypeFromTypeNode(tag.typeExpression.type) : getContextualType(parent); } - case 265: + case 265 /* JsxExpression */: return getContextualTypeForJsxExpression(parent); - case 262: - case 264: + case 262 /* JsxAttribute */: + case 264 /* JsxSpreadAttribute */: return getContextualTypeForJsxAttribute(parent); - case 257: - case 256: + case 257 /* JsxOpeningElement */: + case 256 /* JsxSelfClosingElement */: return getContextualJsxElementAttributesType(parent); } return undefined; @@ -37554,16 +43450,22 @@ var ts; } var valueType = checkExpression(node.tagName); if (isTypeAny(valueType)) { + // Short-circuit if the class tag is using an element type 'any' return anyType; } var isJs = ts.isInJavaScriptFile(node); return mapType(valueType, function (t) { return getJsxSignaturesParameterTypes(t, isJs, node); }); } function getJsxSignaturesParameterTypes(valueType, isJs, context) { - if (valueType.flags & 4) { + // If the elemType is a string type, we have to return anyType to prevent an error downstream as we will try to find construct or call signature of the type + if (valueType.flags & 4 /* String */) { return anyType; } - else if (valueType.flags & 64) { + else if (valueType.flags & 64 /* StringLiteral */) { + // If the elemType is a stringLiteral type, we can then provide a check to make sure that the string literal type is one of the Jsx intrinsic element type + // For example: + // var CustomTag: "h1" = "h1"; + // Hello World var intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements, context); if (intrinsicElementsType !== errorType) { var stringLiteralTypeName = valueType.value; @@ -37571,19 +43473,22 @@ var ts; if (intrinsicProp) { return getTypeOfSymbol(intrinsicProp); } - var indexSignatureType = getIndexTypeOfType(intrinsicElementsType, 0); + var indexSignatureType = getIndexTypeOfType(intrinsicElementsType, 0 /* String */); if (indexSignatureType) { return indexSignatureType; } } return anyType; } - var signatures = getSignaturesOfType(valueType, 1); + // Resolve the signatures, preferring constructor + var signatures = getSignaturesOfType(valueType, 1 /* Construct */); var ctor = true; if (signatures.length === 0) { - signatures = getSignaturesOfType(valueType, 0); + // No construct signatures, try call signatures + signatures = getSignaturesOfType(valueType, 0 /* Call */); ctor = false; if (signatures.length === 0) { + // We found no signatures at all, which is an error return errorType; } } @@ -37600,7 +43505,7 @@ var ts; links.resolvedSignatures.set(cacheKey, resolvingSignaturesArray); links.resolvedSignatures.set(cacheKey, signatures = instantiateJsxSignatures(context, signatures)); } - return getUnionType(ts.map(signatures, ctor ? function (t) { return getJsxPropsTypeFromClassType(t, isJs, context, false); } : function (t) { return getJsxPropsTypeFromCallSignature(t, context); }), 0); + return getUnionType(ts.map(signatures, ctor ? function (t) { return getJsxPropsTypeFromClassType(t, isJs, context, /*reportErrors*/ false); } : function (t) { return getJsxPropsTypeFromCallSignature(t, context); }), 0 /* None */); } function getJsxPropsTypeFromCallSignature(sig, context) { var propsType = getTypeOfFirstParameterOfSignatureWithFallback(sig, emptyObjectType); @@ -37617,20 +43522,26 @@ var ts; function getJsxPropsTypeFromClassType(sig, isJs, context, reportErrors) { var forcedLookupLocation = getJsxElementPropertiesName(getJsxNamespaceAt(context)); var attributesType = forcedLookupLocation === undefined + // If there is no type ElementAttributesProperty, return the type of the first parameter of the signature, which should be the props type ? getTypeOfFirstParameterOfSignatureWithFallback(sig, emptyObjectType) : forcedLookupLocation === "" + // If there is no e.g. 'props' member in ElementAttributesProperty, use the element class type instead ? getReturnTypeOfSignature(sig) + // Otherwise get the type of the property on the signature return type : getJsxPropsTypeForSignatureFromMember(sig, forcedLookupLocation); if (!attributesType) { + // There is no property named 'props' on this instance type if (reportErrors && !!forcedLookupLocation && !!ts.length(context.attributes.properties)) { error(context, ts.Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, ts.unescapeLeadingUnderscores(forcedLookupLocation)); } return emptyObjectType; } else if (isTypeAny(attributesType)) { + // Props is of type 'any' or unknown return attributesType; } else { + // Normal case -- add in IntrinsicClassElements and IntrinsicElements var apparentAttributesType = attributesType; var intrinsicClassAttribs = getJsxType(JsxNames.IntrinsicClassAttributes, context); if (intrinsicClassAttribs !== errorType) { @@ -37647,8 +43558,10 @@ var ts; return apparentAttributesType; } } + // If the given type is an object or union type with a single signature, and if that signature has at + // least as many parameters as the given function, return the signature. Otherwise return undefined. function getContextualCallSignature(type, node) { - var signatures = getSignaturesOfType(type, 0); + var signatures = getSignaturesOfType(type, 0 /* Call */); if (signatures.length === 1) { var signature = signatures[0]; if (!isAritySmaller(signature, node)) { @@ -37656,6 +43569,7 @@ var ts; } } } + /** If the contextual signature has fewer parameters than the function expression, do not use it */ function isAritySmaller(signature, target) { var targetParameterCount = 0; for (; targetParameterCount < target.parameters.length; targetParameterCount++) { @@ -37671,9 +43585,10 @@ var ts; return sourceLength < targetParameterCount; } function isFunctionExpressionOrArrowFunction(node) { - return node.kind === 192 || node.kind === 193; + return node.kind === 192 /* FunctionExpression */ || node.kind === 193 /* ArrowFunction */; } function getContextualSignatureForFunctionLikeDeclaration(node) { + // Only function expressions, arrow functions, and object literal methods are contextually typed. return isFunctionExpressionOrArrowFunction(node) || ts.isObjectLiteralMethod(node) ? getContextualSignature(node) : undefined; @@ -37683,8 +43598,13 @@ var ts; getContextualTypeForObjectLiteralMethod(node) : getApparentTypeOfContextualType(node); } + // Return the contextual signature for a given expression node. A contextual type provides a + // contextual signature if it has a single call signature and if that call signature is non-generic. + // If the contextual type is a union type, get the signature from each type possible and if they are + // all identical ignoring their return type, the result is same signature but with return type as + // union type of return types from these signatures function getContextualSignature(node) { - ts.Debug.assert(node.kind !== 154 || ts.isObjectLiteralMethod(node)); + ts.Debug.assert(node.kind !== 154 /* MethodDeclaration */ || ts.isObjectLiteralMethod(node)); var type; if (ts.isInJavaScriptFile(node)) { var jsdoc = ts.getJSDocType(node); @@ -37698,7 +43618,7 @@ var ts; if (!type) { return undefined; } - if (!(type.flags & 262144)) { + if (!(type.flags & 262144 /* Union */)) { return getContextualCallSignature(type, node); } var signatureList; @@ -37708,16 +43628,20 @@ var ts; var signature = getContextualCallSignature(current, node); if (signature) { if (!signatureList) { + // This signature will contribute to contextual union signature signatureList = [signature]; } - else if (!compareSignaturesIdentical(signatureList[0], signature, false, true, true, compareTypesIdentical)) { + else if (!compareSignaturesIdentical(signatureList[0], signature, /*partialMatch*/ false, /*ignoreThisTypes*/ true, /*ignoreReturnTypes*/ true, compareTypesIdentical)) { + // Signatures aren't identical, do not use return undefined; } else { + // Use this signature for contextual union signature signatureList.push(signature); } } } + // Result is union of signatures collected (return type is union of return types of this signature set) var result; if (signatureList) { result = cloneSignature(signatureList[0]); @@ -37726,15 +43650,15 @@ var ts; return result; } function checkSpreadExpression(node, checkMode) { - if (languageVersion < 2 && compilerOptions.downlevelIteration) { - checkExternalEmitHelpers(node, 1536); + if (languageVersion < 2 /* ES2015 */ && compilerOptions.downlevelIteration) { + checkExternalEmitHelpers(node, 1536 /* SpreadIncludes */); } var arrayOrIterableType = checkExpression(node.expression, checkMode); - return checkIteratedTypeOrElementType(arrayOrIterableType, node.expression, false, false); + return checkIteratedTypeOrElementType(arrayOrIterableType, node.expression, /*allowStringInput*/ false, /*allowAsyncIterables*/ false); } function hasDefaultValue(node) { - return (node.kind === 182 && !!node.initializer) || - (node.kind === 200 && node.operatorToken.kind === 58); + return (node.kind === 182 /* BindingElement */ && !!node.initializer) || + (node.kind === 200 /* BinaryExpression */ && node.operatorToken.kind === 58 /* EqualsToken */); } function checkArrayLiteral(node, checkMode) { var elements = node.elements; @@ -37744,10 +43668,22 @@ var ts; var contextualType = getApparentTypeOfContextualType(node); for (var index = 0; index < elements.length; index++) { var e = elements[index]; - if (inDestructuringPattern && e.kind === 204) { + if (inDestructuringPattern && e.kind === 204 /* SpreadElement */) { + // Given the following situation: + // var c: {}; + // [...c] = ["", 0]; + // + // c is represented in the tree as a spread element in an array literal. + // But c really functions as a rest element, and its purpose is to provide + // a contextual type for the right hand side of the assignment. Therefore, + // instead of calling checkExpression on "...c", which will give an error + // if c is not iterable/array-like, we need to act as if we are trying to + // get the contextual element type from it. So we do something similar to + // getContextualTypeForElementExpression, which will crucially not error + // if there is no index type / iterated type. var restArrayType = checkExpression(e.expression, checkMode); - var restElementType = getIndexTypeOfType(restArrayType, 1) || - getIteratedTypeOrElementType(restArrayType, undefined, false, false, false); + var restElementType = getIndexTypeOfType(restArrayType, 1 /* Number */) || + getIteratedTypeOrElementType(restArrayType, /*errorNode*/ undefined, /*allowStringInput*/ false, /*allowAsyncIterables*/ false, /*checkAssignability*/ false); if (restElementType) { elementTypes.push(restElementType); } @@ -37757,9 +43693,11 @@ var ts; var type = checkExpressionForMutableLocation(e, checkMode, elementContextualType); elementTypes.push(type); } - hasSpreadElement = hasSpreadElement || e.kind === 204; + hasSpreadElement = hasSpreadElement || e.kind === 204 /* SpreadElement */; } if (!hasSpreadElement) { + // If array literal is actually a destructuring pattern, mark it as an implied type. We do this such + // that we get the same behavior for "var [x, y] = []" and "[x, y] = []". if (inDestructuringPattern && elementTypes.length) { var type = cloneTypeReference(createTupleType(elementTypes)); type.pattern = node; @@ -37767,7 +43705,9 @@ var ts; } if (contextualType && contextualTypeIsTupleLikeType(contextualType)) { var pattern = contextualType.pattern; - if (pattern && (pattern.kind === 181 || pattern.kind === 183)) { + // If array literal is contextually typed by a binding pattern or an assignment pattern, pad the resulting + // tuple type with the corresponding binding or assignment element types to make the lengths equal. + if (pattern && (pattern.kind === 181 /* ArrayBindingPattern */ || pattern.kind === 183 /* ArrayLiteralExpression */)) { var patternElements = pattern.elements; for (var i = elementTypes.length; i < patternElements.length; i++) { var patternElement = patternElements[i]; @@ -37775,7 +43715,7 @@ var ts; elementTypes.push(contextualType.typeArguments[i]); } else { - if (patternElement.kind !== 206) { + if (patternElement.kind !== 206 /* OmittedExpression */) { error(patternElement, ts.Diagnostics.Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value); } elementTypes.push(strictNullChecks ? implicitNeverType : undefinedWideningType); @@ -37788,42 +43728,67 @@ var ts; } } return createArrayType(elementTypes.length ? - getUnionType(elementTypes, 2) : + getUnionType(elementTypes, 2 /* Subtype */) : strictNullChecks ? implicitNeverType : undefinedWideningType); } function isNumericName(name) { switch (name.kind) { - case 147: + case 147 /* ComputedPropertyName */: return isNumericComputedName(name); - case 71: + case 71 /* Identifier */: return isNumericLiteralName(name.escapedText); - case 8: - case 9: + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: return isNumericLiteralName(name.text); default: return false; } } function isNumericComputedName(name) { - return isTypeAssignableToKind(checkComputedPropertyName(name), 168); + // It seems odd to consider an expression of type Any to result in a numeric name, + // but this behavior is consistent with checkIndexedAccess + return isTypeAssignableToKind(checkComputedPropertyName(name), 168 /* NumberLike */); } function isInfinityOrNaNString(name) { return name === "Infinity" || name === "-Infinity" || name === "NaN"; } function isNumericLiteralName(name) { + // The intent of numeric names is that + // - they are names with text in a numeric form, and that + // - setting properties/indexing with them is always equivalent to doing so with the numeric literal 'numLit', + // acquired by applying the abstract 'ToNumber' operation on the name's text. + // + // The subtlety is in the latter portion, as we cannot reliably say that anything that looks like a numeric literal is a numeric name. + // In fact, it is the case that the text of the name must be equal to 'ToString(numLit)' for this to hold. + // + // Consider the property name '"0xF00D"'. When one indexes with '0xF00D', they are actually indexing with the value of 'ToString(0xF00D)' + // according to the ECMAScript specification, so it is actually as if the user indexed with the string '"61453"'. + // Thus, the text of all numeric literals equivalent to '61543' such as '0xF00D', '0xf00D', '0170015', etc. are not valid numeric names + // because their 'ToString' representation is not equal to their original text. + // This is motivated by ECMA-262 sections 9.3.1, 9.8.1, 11.1.5, and 11.2.1. + // + // Here, we test whether 'ToString(ToNumber(name))' is exactly equal to 'name'. + // The '+' prefix operator is equivalent here to applying the abstract ToNumber operation. + // Applying the 'toString()' method on a number gives us the abstract ToString operation on a number. + // + // Note that this accepts the values 'Infinity', '-Infinity', and 'NaN', and that this is intentional. + // This is desired behavior, because when indexing with them as numeric entities, you are indexing + // with the strings '"Infinity"', '"-Infinity"', and '"NaN"' respectively. return (+name).toString() === name; } function checkComputedPropertyName(node) { var links = getNodeLinks(node.expression); if (!links.resolvedType) { links.resolvedType = checkExpression(node.expression); - if (links.resolvedType.flags & 24576 || - !isTypeAssignableToKind(links.resolvedType, 68 | 168 | 3072) && + // This will allow types number, string, symbol or any. It will also allow enums, the unknown + // type, and any union of these types (like string | number). + if (links.resolvedType.flags & 24576 /* Nullable */ || + !isTypeAssignableToKind(links.resolvedType, 68 /* StringLike */ | 168 /* NumberLike */ | 3072 /* ESSymbolLike */) && !isTypeAssignableTo(links.resolvedType, stringNumberSymbolType)) { error(node, ts.Diagnostics.A_computed_property_name_must_be_of_type_string_number_symbol_or_any); } else { - checkThatExpressionIsProperSymbolReference(node.expression, links.resolvedType, true); + checkThatExpressionIsProperSymbolReference(node.expression, links.resolvedType, /*reportError*/ true); } } return links.resolvedType; @@ -37831,23 +43796,24 @@ var ts; function getObjectLiteralIndexInfo(propertyNodes, offset, properties, kind) { var propTypes = []; for (var i = 0; i < properties.length; i++) { - if (kind === 0 || isNumericName(propertyNodes[i + offset].name)) { + if (kind === 0 /* String */ || isNumericName(propertyNodes[i + offset].name)) { propTypes.push(getTypeOfSymbol(properties[i])); } } - var unionType = propTypes.length ? getUnionType(propTypes, 2) : undefinedType; - return createIndexInfo(unionType, false); + var unionType = propTypes.length ? getUnionType(propTypes, 2 /* Subtype */) : undefinedType; + return createIndexInfo(unionType, /*isReadonly*/ false); } function checkObjectLiteral(node, checkMode) { var inDestructuringPattern = ts.isAssignmentTarget(node); + // Grammar checking checkGrammarObjectLiteralExpression(node, inDestructuringPattern); var propertiesTable; var propertiesArray = []; var spread = emptyObjectType; - var propagatedFlags = 33554432; + var propagatedFlags = 33554432 /* FreshLiteral */; var contextualType = getApparentTypeOfContextualType(node); var contextualTypeHasPattern = contextualType && contextualType.pattern && - (contextualType.pattern.kind === 180 || contextualType.pattern.kind === 184); + (contextualType.pattern.kind === 180 /* ObjectBindingPattern */ || contextualType.pattern.kind === 184 /* ObjectLiteralExpression */); var isInJSFile = ts.isInJavaScriptFile(node) && !ts.isInJsonFile(node); var isJSObjectLiteral = !contextualType && isInJSFile; var typeFlags = 0; @@ -37859,13 +43825,13 @@ var ts; for (var i = 0; i < node.properties.length; i++) { var memberDecl = node.properties[i]; var member = getSymbolOfNode(memberDecl); - var computedNameType = memberDecl.name && memberDecl.name.kind === 147 && !ts.isWellKnownSymbolSyntactically(memberDecl.name.expression) ? + var computedNameType = memberDecl.name && memberDecl.name.kind === 147 /* ComputedPropertyName */ && !ts.isWellKnownSymbolSyntactically(memberDecl.name.expression) ? checkComputedPropertyName(memberDecl.name) : undefined; - if (memberDecl.kind === 270 || - memberDecl.kind === 271 || + if (memberDecl.kind === 270 /* PropertyAssignment */ || + memberDecl.kind === 271 /* ShorthandPropertyAssignment */ || ts.isObjectLiteralMethod(memberDecl)) { - var type = memberDecl.kind === 270 ? checkPropertyAssignment(memberDecl, checkMode) : - memberDecl.kind === 271 ? checkExpressionForMutableLocation(memberDecl.name, checkMode) : + var type = memberDecl.kind === 270 /* PropertyAssignment */ ? checkPropertyAssignment(memberDecl, checkMode) : + memberDecl.kind === 271 /* ShorthandPropertyAssignment */ ? checkExpressionForMutableLocation(memberDecl.name, checkMode) : checkObjectLiteralMethod(memberDecl, checkMode); if (isInJSFile) { var jsDocType = getTypeForDeclarationFromJSDocComment(memberDecl); @@ -37875,27 +43841,31 @@ var ts; } } typeFlags |= type.flags; - var nameType = computedNameType && computedNameType.flags & 2240 ? + var nameType = computedNameType && computedNameType.flags & 2240 /* StringOrNumberLiteralOrUnique */ ? computedNameType : undefined; var prop = nameType ? - createSymbol(4 | member.flags, getLateBoundNameFromType(nameType), 1024) : - createSymbol(4 | member.flags, member.escapedName); + createSymbol(4 /* Property */ | member.flags, getLateBoundNameFromType(nameType), 1024 /* Late */) : + createSymbol(4 /* Property */ | member.flags, member.escapedName); if (nameType) { prop.nameType = nameType; } if (inDestructuringPattern) { - var isOptional = (memberDecl.kind === 270 && hasDefaultValue(memberDecl.initializer)) || - (memberDecl.kind === 271 && memberDecl.objectAssignmentInitializer); + // If object literal is an assignment pattern and if the assignment pattern specifies a default value + // for the property, make the property optional. + var isOptional = (memberDecl.kind === 270 /* PropertyAssignment */ && hasDefaultValue(memberDecl.initializer)) || + (memberDecl.kind === 271 /* ShorthandPropertyAssignment */ && memberDecl.objectAssignmentInitializer); if (isOptional) { - prop.flags |= 16777216; + prop.flags |= 16777216 /* Optional */; } } - else if (contextualTypeHasPattern && !(ts.getObjectFlags(contextualType) & 512)) { + else if (contextualTypeHasPattern && !(ts.getObjectFlags(contextualType) & 512 /* ObjectLiteralPatternWithComputedProperties */)) { + // If object literal is contextually typed by the implied type of a binding pattern, and if the + // binding pattern specifies a default value for the property, make the property optional. var impliedProp = getPropertyOfType(contextualType, member.escapedName); if (impliedProp) { - prop.flags |= impliedProp.flags & 16777216; + prop.flags |= impliedProp.flags & 16777216 /* Optional */; } - else if (!compilerOptions.suppressExcessPropertyErrors && !getIndexInfoOfType(contextualType, 0)) { + else if (!compilerOptions.suppressExcessPropertyErrors && !getIndexInfoOfType(contextualType, 0 /* String */)) { error(memberDecl.name, ts.Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1, symbolToString(member), typeToString(contextualType)); } } @@ -37908,12 +43878,12 @@ var ts; prop.target = member; member = prop; } - else if (memberDecl.kind === 272) { - if (languageVersion < 2) { - checkExternalEmitHelpers(memberDecl, 2); + else if (memberDecl.kind === 272 /* SpreadAssignment */) { + if (languageVersion < 2 /* ES2015 */) { + checkExternalEmitHelpers(memberDecl, 2 /* Assign */); } if (propertiesArray.length > 0) { - spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, propagatedFlags, 0); + spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, propagatedFlags, /*objectFlags*/ 0); propertiesArray = []; propertiesTable = ts.createSymbolTable(); hasComputedStringProperty = false; @@ -37925,15 +43895,20 @@ var ts; error(memberDecl, ts.Diagnostics.Spread_types_may_only_be_created_from_object_types); return errorType; } - spread = getSpreadType(spread, type, node.symbol, propagatedFlags, 0); + spread = getSpreadType(spread, type, node.symbol, propagatedFlags, /*objectFlags*/ 0); offset = i + 1; continue; } else { - ts.Debug.assert(memberDecl.kind === 156 || memberDecl.kind === 157); + // TypeScript 1.0 spec (April 2014) + // A get accessor declaration is processed in the same manner as + // an ordinary function declaration(section 6.1) with no parameters. + // A set accessor declaration is processed in the same manner + // as an ordinary function declaration with a single parameter and a Void return type. + ts.Debug.assert(memberDecl.kind === 156 /* GetAccessor */ || memberDecl.kind === 157 /* SetAccessor */); checkNodeDeferred(memberDecl); } - if (computedNameType && !(computedNameType.flags & 2240)) { + if (computedNameType && !(computedNameType.flags & 2240 /* StringOrNumberLiteralOrUnique */)) { if (isTypeAssignableTo(computedNameType, stringNumberSymbolType)) { if (isTypeAssignableTo(computedNameType, numberType)) { hasComputedNumberProperty = true; @@ -37951,11 +43926,13 @@ var ts; } propertiesArray.push(member); } + // If object literal is contextually typed by the implied type of a binding pattern, augment the result + // type with those properties for which the binding pattern specifies a default value. if (contextualTypeHasPattern) { for (var _i = 0, _a = getPropertiesOfType(contextualType); _i < _a.length; _i++) { var prop = _a[_i]; if (!propertiesTable.get(prop.escapedName) && !(spread && getPropertyOfType(spread, prop.escapedName))) { - if (!(prop.flags & 16777216)) { + if (!(prop.flags & 16777216 /* Optional */)) { error(prop.valueDeclaration || prop.bindingElement, ts.Diagnostics.Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value); } propertiesTable.set(prop.escapedName, prop); @@ -37965,42 +43942,44 @@ var ts; } if (spread !== emptyObjectType) { if (propertiesArray.length > 0) { - spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, propagatedFlags, 0); + spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, propagatedFlags, /*objectFlags*/ 0); } return spread; } return createObjectLiteralType(); function createObjectLiteralType() { - var stringIndexInfo = isJSObjectLiteral ? jsObjectLiteralIndexInfo : hasComputedStringProperty ? getObjectLiteralIndexInfo(node.properties, offset, propertiesArray, 0) : undefined; - var numberIndexInfo = hasComputedNumberProperty && !isJSObjectLiteral ? getObjectLiteralIndexInfo(node.properties, offset, propertiesArray, 1) : undefined; + var stringIndexInfo = isJSObjectLiteral ? jsObjectLiteralIndexInfo : hasComputedStringProperty ? getObjectLiteralIndexInfo(node.properties, offset, propertiesArray, 0 /* String */) : undefined; + var numberIndexInfo = hasComputedNumberProperty && !isJSObjectLiteral ? getObjectLiteralIndexInfo(node.properties, offset, propertiesArray, 1 /* Number */) : undefined; var result = createAnonymousType(node.symbol, propertiesTable, ts.emptyArray, ts.emptyArray, stringIndexInfo, numberIndexInfo); - var freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : 33554432; - result.flags |= 268435456 | freshObjectLiteralFlag | (typeFlags & 939524096); - result.objectFlags |= 128; + var freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : 33554432 /* FreshLiteral */; + result.flags |= 268435456 /* ContainsObjectLiteral */ | freshObjectLiteralFlag | (typeFlags & 939524096 /* PropagatingFlags */); + result.objectFlags |= 128 /* ObjectLiteral */; if (patternWithComputedProperties) { - result.objectFlags |= 512; + result.objectFlags |= 512 /* ObjectLiteralPatternWithComputedProperties */; } if (inDestructuringPattern) { result.pattern = node; } - if (!(result.flags & 24576)) { - propagatedFlags |= (result.flags & 939524096); + if (!(result.flags & 24576 /* Nullable */)) { + propagatedFlags |= (result.flags & 939524096 /* PropagatingFlags */); } return result; } } function isValidSpreadType(type) { - return !!(type.flags & (3 | 16777216) || - getFalsyFlags(type) & 29120 && isValidSpreadType(removeDefinitelyFalsyTypes(type)) || - type.flags & 131072 && !isGenericMappedType(type) || - type.flags & 786432 && ts.every(type.types, isValidSpreadType)); + return !!(type.flags & (3 /* AnyOrUnknown */ | 16777216 /* NonPrimitive */) || + getFalsyFlags(type) & 29120 /* DefinitelyFalsy */ && isValidSpreadType(removeDefinitelyFalsyTypes(type)) || + type.flags & 131072 /* Object */ && !isGenericMappedType(type) || + type.flags & 786432 /* UnionOrIntersection */ && ts.every(type.types, isValidSpreadType)); } function checkJsxSelfClosingElement(node, checkMode) { checkJsxOpeningLikeElementOrOpeningFragment(node, checkMode); return getJsxElementTypeAt(node) || anyType; } function checkJsxElement(node, checkMode) { + // Check attributes checkJsxOpeningLikeElementOrOpeningFragment(node.openingElement, checkMode); + // Perform resolution on the closing tag so that rename/go to definition/etc work if (isJsxIntrinsicIdentifier(node.closingElement.tagName)) { getIntrinsicTagSymbol(node.closingElement); } @@ -38011,22 +43990,30 @@ var ts; } function checkJsxFragment(node, checkMode) { checkJsxOpeningLikeElementOrOpeningFragment(node.openingFragment, checkMode); - if (compilerOptions.jsx === 2 && (compilerOptions.jsxFactory || ts.getSourceFileOfNode(node).pragmas.has("jsx"))) { + if (compilerOptions.jsx === 2 /* React */ && (compilerOptions.jsxFactory || ts.getSourceFileOfNode(node).pragmas.has("jsx"))) { error(node, compilerOptions.jsxFactory ? ts.Diagnostics.JSX_fragment_is_not_supported_when_using_jsxFactory : ts.Diagnostics.JSX_fragment_is_not_supported_when_using_an_inline_JSX_factory_pragma); } return getJsxElementTypeAt(node) || anyType; } + /** + * Returns true iff the JSX element name would be a valid JS identifier, ignoring restrictions about keywords not being identifiers + */ function isUnhyphenatedJsxName(name) { + // - is the only character supported in JSX attribute names that isn't valid in JavaScript identifiers return !ts.stringContains(name, "-"); } + /** + * Returns true iff React would emit this tag name as a string rather than an identifier or qualified name + */ function isJsxIntrinsicIdentifier(tagName) { + // TODO (yuisu): comment switch (tagName.kind) { - case 185: - case 99: + case 185 /* PropertyAccessExpression */: + case 99 /* ThisKeyword */: return false; - case 71: + case 71 /* Identifier */: return ts.isIntrinsicJsxName(tagName.escapedText); default: return ts.Debug.fail(); @@ -38035,8 +44022,17 @@ var ts; function checkJsxAttribute(node, checkMode) { return node.initializer ? checkExpressionForMutableLocation(node.initializer, checkMode) - : trueType; + : trueType; // is sugar for } + /** + * Get attributes type of the JSX opening-like element. The result is from resolving "attributes" property of the opening-like element. + * + * @param openingLikeElement a JSX opening-like element + * @param filter a function to remove attributes that will not participate in checking whether attributes are assignable + * @return an anonymous type (similar to the one returned by checkObjectLiteral) in which its properties are attributes property. + * @remarks Because this function calls getSpreadType, it needs to use the same checks as checkObjectLiteral, + * which also calls getSpreadType. + */ function createJsxAttributesTypeFromAttributesProperty(openingLikeElement, checkMode) { var attributes = openingLikeElement.attributes; var attributesTable = ts.createSymbolTable(); @@ -38050,7 +44046,7 @@ var ts; var member = attributeDecl.symbol; if (ts.isJsxAttribute(attributeDecl)) { var exprType = checkJsxAttribute(attributeDecl, checkMode); - var attributeSymbol = createSymbol(4 | 33554432 | member.flags, member.escapedName); + var attributeSymbol = createSymbol(4 /* Property */ | 33554432 /* Transient */ | member.flags, member.escapedName); attributeSymbol.declarations = member.declarations; attributeSymbol.parent = member.parent; if (member.valueDeclaration) { @@ -38064,9 +44060,9 @@ var ts; } } else { - ts.Debug.assert(attributeDecl.kind === 264); + ts.Debug.assert(attributeDecl.kind === 264 /* JsxSpreadAttribute */); if (attributesTable.size > 0) { - spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, 0, 4096); + spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, /*typeFlags*/ 0, 4096 /* JsxAttributes */); attributesTable = ts.createSymbolTable(); } var exprType = checkExpressionCached(attributeDecl.expression, checkMode); @@ -38074,7 +44070,7 @@ var ts; hasSpreadAnyType = true; } if (isValidSpreadType(exprType)) { - spread = getSpreadType(spread, exprType, openingLikeElement.symbol, 0, 4096); + spread = getSpreadType(spread, exprType, openingLikeElement.symbol, /*typeFlags*/ 0, 4096 /* JsxAttributes */); } else { typeToIntersect = typeToIntersect ? getIntersectionType([typeToIntersect, exprType]) : exprType; @@ -38083,23 +44079,29 @@ var ts; } if (!hasSpreadAnyType) { if (attributesTable.size > 0) { - spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, 0, 4096); + spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, /*typeFlags*/ 0, 4096 /* JsxAttributes */); } } - var parent = openingLikeElement.parent.kind === 255 ? openingLikeElement.parent : undefined; + // Handle children attribute + var parent = openingLikeElement.parent.kind === 255 /* JsxElement */ ? openingLikeElement.parent : undefined; + // We have to check that openingElement of the parent is the one we are visiting as this may not be true for selfClosingElement if (parent && parent.openingElement === openingLikeElement && parent.children.length > 0) { var childrenTypes = checkJsxChildren(parent, checkMode); if (!hasSpreadAnyType && jsxChildrenPropertyName && jsxChildrenPropertyName !== "") { + // Error if there is a attribute named "children" explicitly specified and children element. + // This is because children element will overwrite the value from attributes. + // Note: we will not warn "children" attribute overwritten if "children" attribute is specified in object spread. if (explicitlySpecifyChildrenAttribute) { error(attributes, ts.Diagnostics._0_are_specified_twice_The_attribute_named_0_will_be_overwritten, ts.unescapeLeadingUnderscores(jsxChildrenPropertyName)); } - var childrenPropSymbol = createSymbol(4 | 33554432, jsxChildrenPropertyName); + // If there are children in the body of JSX element, create dummy attribute "children" with the union of children types so that it will pass the attribute checking process + var childrenPropSymbol = createSymbol(4 /* Property */ | 33554432 /* Transient */, jsxChildrenPropertyName); childrenPropSymbol.type = childrenTypes.length === 1 ? childrenTypes[0] : createArrayType(getUnionType(childrenTypes)); var childPropMap = ts.createSymbolTable(); childPropMap.set(jsxChildrenPropertyName, childrenPropSymbol); - spread = getSpreadType(spread, createAnonymousType(attributes.symbol, childPropMap, ts.emptyArray, ts.emptyArray, undefined, undefined), attributes.symbol, 0, 4096); + spread = getSpreadType(spread, createAnonymousType(attributes.symbol, childPropMap, ts.emptyArray, ts.emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined), attributes.symbol, /*typeFlags*/ 0, 4096 /* JsxAttributes */); } } if (hasSpreadAnyType) { @@ -38109,10 +44111,15 @@ var ts; return getIntersectionType([typeToIntersect, spread]); } return typeToIntersect || (spread === emptyObjectType ? createJsxAttributesType() : spread); + /** + * Create anonymous type from given attributes symbol table. + * @param symbol a symbol of JsxAttributes containing attributes corresponding to attributesTable + * @param attributesTable a symbol table of attributes property + */ function createJsxAttributesType() { - var result = createAnonymousType(attributes.symbol, attributesTable, ts.emptyArray, ts.emptyArray, undefined, undefined); - result.flags |= 268435456; - result.objectFlags |= 128 | 4096; + var result = createAnonymousType(attributes.symbol, attributesTable, ts.emptyArray, ts.emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined); + result.flags |= 268435456 /* ContainsObjectLiteral */; + result.objectFlags |= 128 /* ObjectLiteral */ | 4096 /* JsxAttributes */; return result; } } @@ -38120,7 +44127,9 @@ var ts; var childrenTypes = []; for (var _i = 0, _a = node.children; _i < _a.length; _i++) { var child = _a[_i]; - if (child.kind === 10) { + // In React, JSX text that contains only whitespaces will be ignored so we don't want to type-check that + // because then type of children property will have constituent of string type. + if (child.kind === 10 /* JsxText */) { if (!child.containsOnlyWhiteSpaces) { childrenTypes.push(stringType); } @@ -38131,32 +44140,46 @@ var ts; } return childrenTypes; } + /** + * Check attributes property of opening-like element. This function is called during chooseOverload to get call signature of a JSX opening-like element. + * (See "checkApplicableSignatureForJsxOpeningLikeElement" for how the function is used) + * @param node a JSXAttributes to be resolved of its type + */ function checkJsxAttributes(node, checkMode) { return createJsxAttributesTypeFromAttributesProperty(node.parent, checkMode); } function getJsxType(name, location) { var namespace = getJsxNamespaceAt(location); var exports = namespace && getExportsOfSymbol(namespace); - var typeSymbol = exports && getSymbol(exports, name, 67901928); + var typeSymbol = exports && getSymbol(exports, name, 67901928 /* Type */); return typeSymbol ? getDeclaredTypeOfSymbol(typeSymbol) : errorType; } + /** + * Looks up an intrinsic tag name and returns a symbol that either points to an intrinsic + * property (in which case nodeLinks.jsxFlags will be IntrinsicNamedElement) or an intrinsic + * string index signature (in which case nodeLinks.jsxFlags will be IntrinsicIndexedElement). + * May also return unknownSymbol if both of these lookups fail. + */ function getIntrinsicTagSymbol(node) { var links = getNodeLinks(node); if (!links.resolvedSymbol) { var intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements, node); if (intrinsicElementsType !== errorType) { + // Property case if (!ts.isIdentifier(node.tagName)) return ts.Debug.fail(); var intrinsicProp = getPropertyOfType(intrinsicElementsType, node.tagName.escapedText); if (intrinsicProp) { - links.jsxFlags |= 1; + links.jsxFlags |= 1 /* IntrinsicNamedElement */; return links.resolvedSymbol = intrinsicProp; } - var indexSignatureType = getIndexTypeOfType(intrinsicElementsType, 0); + // Intrinsic string indexer case + var indexSignatureType = getIndexTypeOfType(intrinsicElementsType, 0 /* String */); if (indexSignatureType) { - links.jsxFlags |= 2; + links.jsxFlags |= 2 /* IntrinsicIndexedElement */; return links.resolvedSymbol = intrinsicElementsType.symbol; } + // Wasn't found error(node, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.idText(node.tagName), "JSX." + JsxNames.IntrinsicElements); return links.resolvedSymbol = unknownSymbol; } @@ -38177,7 +44200,7 @@ var ts; var signature = signatures_3[_i]; if (signature.typeParameters) { var isJavascript = ts.isInJavaScriptFile(node); - var typeArgumentInstantiated = getJsxSignatureTypeArgumentInstantiation(signature, node, isJavascript, false); + var typeArgumentInstantiated = getJsxSignatureTypeArgumentInstantiation(signature, node, isJavascript, /*reportErrors*/ false); if (typeArgumentInstantiated) { hasTypeArgumentError = false; instantiatedSignatures.push(typeArgumentInstantiated); @@ -38186,7 +44209,7 @@ var ts; if (node.typeArguments && hasCorrectTypeArgumentArity(signature, node.typeArguments)) { candidateForTypeArgumentError = signature; } - var inferenceContext = createInferenceContext(signature.typeParameters, signature, isJavascript ? 4 : 0); + var inferenceContext = createInferenceContext(signature.typeParameters, signature, /*flags*/ isJavascript ? 4 /* AnyDefault */ : 0 /* None */); var typeArguments = inferJsxTypeArguments(signature, node, inferenceContext); instantiatedSignatures.push(getSignatureInstantiation(signature, typeArguments, isJavascript)); } @@ -38197,8 +44220,9 @@ var ts; } if (node.typeArguments && hasTypeArgumentError) { if (candidateForTypeArgumentError) { - checkTypeArguments(candidateForTypeArgumentError, node.typeArguments, true); + checkTypeArguments(candidateForTypeArgumentError, node.typeArguments, /*reportErrors*/ true); } + // Length check to avoid issuing an arity error on length=0, the "Type argument list cannot be empty" grammar error alone is fine else if (node.typeArguments.length !== 0) { diagnostics.add(getTypeArgumentArityError(node, signatures, node.typeArguments)); } @@ -38221,32 +44245,52 @@ var ts; } function getJsxNamespaceAt(location) { var namespaceName = getJsxNamespace(location); - var resolvedNamespace = resolveName(location, namespaceName, 1920, undefined, namespaceName, false); + var resolvedNamespace = resolveName(location, namespaceName, 1920 /* Namespace */, /*diagnosticMessage*/ undefined, namespaceName, /*isUse*/ false); if (resolvedNamespace) { - var candidate = getSymbol(getExportsOfSymbol(resolveSymbol(resolvedNamespace)), JsxNames.JSX, 1920); + var candidate = getSymbol(getExportsOfSymbol(resolveSymbol(resolvedNamespace)), JsxNames.JSX, 1920 /* Namespace */); if (candidate) { return candidate; } } - return getGlobalSymbol(JsxNames.JSX, 1920, undefined); + // JSX global fallback + return getGlobalSymbol(JsxNames.JSX, 1920 /* Namespace */, /*diagnosticMessage*/ undefined); // TODO: GH#18217 } + /** + * Look into JSX namespace and then look for container with matching name as nameOfAttribPropContainer. + * Get a single property from that container if existed. Report an error if there are more than one property. + * + * @param nameOfAttribPropContainer a string of value JsxNames.ElementAttributesPropertyNameContainer or JsxNames.ElementChildrenAttributeNameContainer + * if other string is given or the container doesn't exist, return undefined. + */ function getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer, jsxNamespace) { - var jsxElementAttribPropInterfaceSym = jsxNamespace && getSymbol(jsxNamespace.exports, nameOfAttribPropContainer, 67901928); + // JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [symbol] + var jsxElementAttribPropInterfaceSym = jsxNamespace && getSymbol(jsxNamespace.exports, nameOfAttribPropContainer, 67901928 /* Type */); + // JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [type] var jsxElementAttribPropInterfaceType = jsxElementAttribPropInterfaceSym && getDeclaredTypeOfSymbol(jsxElementAttribPropInterfaceSym); + // The properties of JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute var propertiesOfJsxElementAttribPropInterface = jsxElementAttribPropInterfaceType && getPropertiesOfType(jsxElementAttribPropInterfaceType); if (propertiesOfJsxElementAttribPropInterface) { + // Element Attributes has zero properties, so the element attributes type will be the class instance type if (propertiesOfJsxElementAttribPropInterface.length === 0) { return ""; } + // Element Attributes has one property, so the element attributes type will be the type of the corresponding + // property of the class instance type else if (propertiesOfJsxElementAttribPropInterface.length === 1) { return propertiesOfJsxElementAttribPropInterface[0].escapedName; } else if (propertiesOfJsxElementAttribPropInterface.length > 1) { + // More than one property on ElementAttributesProperty is an error error(jsxElementAttribPropInterfaceSym.declarations[0], ts.Diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, ts.unescapeLeadingUnderscores(nameOfAttribPropContainer)); } } return undefined; } + /// e.g. "props" for React.d.ts, + /// or 'undefined' if ElementAttributesProperty doesn't exist (which means all + /// non-intrinsic elements' attributes type is 'any'), + /// or '' if it has 0 properties (which means every + /// non-intrinsic elements' attributes type is the element instance type) function getJsxElementPropertiesName(jsxNamespace) { return getNameFromJsxElementAttributesContainer(JsxNames.ElementAttributesPropertyNameContainer, jsxNamespace); } @@ -38257,7 +44301,7 @@ var ts; if (!propsType) { return undefined; } - if (propsType.flags & 524288) { + if (propsType.flags & 524288 /* Intersection */) { var propsApparentType = []; for (var _i = 0, _a = propsType.types; _i < _a.length; _i++) { var t = _a[_i]; @@ -38267,17 +44311,29 @@ var ts; } return getApparentType(propsType); } + /** + * Get JSX attributes type by trying to resolve openingLikeElement as a stateless function component. + * Return only attributes type of successfully resolved call signature. + * This function assumes that the caller handled other possible element type of the JSX element (e.g. stateful component) + * Unlike tryGetAllJsxStatelessFunctionAttributesType, this function is a default behavior of type-checkers. + * @param openingLikeElement a JSX opening-like element to find attributes type + * @param elementType a type of the opening-like element. This elementType can't be an union type + * @param elemInstanceType an element instance type (the result of newing or invoking this tag) + * @param elementClassType a JSX-ElementClass type. This is a result of looking up ElementClass interface in the JSX global + */ function defaultTryGetJsxStatelessFunctionAttributesType(openingLikeElement, elementType, elemInstanceType, elementClassType) { - ts.Debug.assert(!(elementType.flags & 262144)); + ts.Debug.assert(!(elementType.flags & 262144 /* Union */)); if (!elementClassType || !isTypeAssignableTo(elemInstanceType, elementClassType)) { var jsxStatelessElementType = getJsxStatelessElementTypeAt(openingLikeElement); if (jsxStatelessElementType) { - var callSignature = getResolvedJsxStatelessFunctionSignature(openingLikeElement, elementType, undefined); + // We don't call getResolvedSignature here because we have already resolve the type of JSX Element. + var callSignature = getResolvedJsxStatelessFunctionSignature(openingLikeElement, elementType, /*candidatesOutArray*/ undefined); if (callSignature !== unknownSignature) { var callReturnType = callSignature && getReturnTypeOfSignature(callSignature); var paramType = callReturnType && (callSignature.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(callSignature.parameters[0])); paramType = getApparentTypeOfJsxPropsType(paramType); if (callReturnType && isTypeAssignableTo(callReturnType, jsxStatelessElementType)) { + // Intersect in JSX.IntrinsicAttributes if it exists var intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes, openingLikeElement); if (intrinsicAttributes !== errorType) { paramType = intersectTypes(intrinsicAttributes, paramType); @@ -38289,11 +44345,23 @@ var ts; } return undefined; } + /** + * Get JSX attributes type by trying to resolve openingLikeElement as a stateless function component. + * Return all attributes type of resolved call signature including candidate signatures. + * This function assumes that the caller handled other possible element type of the JSX element. + * This function is a behavior used by language service when looking up completion in JSX element. + * @param openingLikeElement a JSX opening-like element to find attributes type + * @param elementType a type of the opening-like element. This elementType can't be an union type + * @param elemInstanceType an element instance type (the result of newing or invoking this tag) + * @param elementClassType a JSX-ElementClass type. This is a result of looking up ElementClass interface in the JSX global + */ function tryGetAllJsxStatelessFunctionAttributesType(openingLikeElement, elementType, elemInstanceType, elementClassType) { - ts.Debug.assert(!(elementType.flags & 262144)); + ts.Debug.assert(!(elementType.flags & 262144 /* Union */)); if (!elementClassType || !isTypeAssignableTo(elemInstanceType, elementClassType)) { + // Is this is a stateless function component? See if its single signature's return type is assignable to the JSX Element Type var jsxStatelessElementType = getJsxStatelessElementTypeAt(openingLikeElement); if (jsxStatelessElementType) { + // We don't call getResolvedSignature because here we have already resolve the type of JSX Element. var candidatesOutArray = []; getResolvedJsxStatelessFunctionSignature(openingLikeElement, elementType, candidatesOutArray); var result = void 0; @@ -38301,6 +44369,7 @@ var ts; for (var _i = 0, candidatesOutArray_1 = candidatesOutArray; _i < candidatesOutArray_1.length; _i++) { var candidate = candidatesOutArray_1[_i]; var callReturnType = getReturnTypeOfSignature(candidate); + // TODO: GH#18217: callReturnType should always be defined... var paramType = callReturnType && (candidate.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(candidate.parameters[0])); paramType = getApparentTypeOfJsxPropsType(paramType); if (callReturnType && isTypeAssignableTo(callReturnType, jsxStatelessElementType)) { @@ -38309,7 +44378,7 @@ var ts; var attribute = _b[_a]; if (ts.isJsxAttribute(attribute) && isUnhyphenatedJsxName(attribute.name.escapedText) && - !getPropertyOfType(paramType, attribute.name.escapedText)) { + !getPropertyOfType(paramType, attribute.name.escapedText)) { // TODO: GH#18217 shouldBeCandidate = false; break; } @@ -38320,9 +44389,11 @@ var ts; allMatchingAttributesType = intersectTypes(allMatchingAttributesType, paramType); } } + // If we can't find any matching, just return everything. if (!result) { result = allMatchingAttributesType; } + // Intersect in JSX.IntrinsicAttributes if it exists var intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes, openingLikeElement); if (intrinsicAttributes !== errorType) { result = intersectTypes(intrinsicAttributes, result); @@ -38345,34 +44416,62 @@ var ts; return links.resolvedSignatures.get(cacheKey); } links.resolvedSignatures.set(cacheKey, resolvingSignaturesArray); - var signatures = getSignaturesOfType(elementType, 1); + // Resolve the signatures, preferring constructor + var signatures = getSignaturesOfType(elementType, 1 /* Construct */); if (signatures.length === 0) { - signatures = getSignaturesOfType(elementType, 0); + // No construct signatures, try call signatures + signatures = getSignaturesOfType(elementType, 0 /* Call */); if (signatures.length === 0) { + // We found no signatures at all, which is an error if (reportErrors) { error(openingLikeElement.tagName, ts.Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, ts.getTextOfNode(openingLikeElement.tagName)); } return; } } + // Instantiate in context of source type var results = instantiateJsxSignatures(openingLikeElement, signatures); links.resolvedSignatures.set(cacheKey, results); return results; } + /** + * Resolve attributes type of the given opening-like element. The attributes type is a type of attributes associated with the given elementType. + * For instance: + * declare function Foo(attr: { p1: string}): JSX.Element; + * ; // This function will try resolve "Foo" and return an attributes type of "Foo" which is "{ p1: string }" + * + * The function is intended to initially be called from getAttributesTypeFromJsxOpeningLikeElement which already handle JSX-intrinsic-element.. + * This function will try to resolve custom JSX attributes type in following order: string literal, stateless function, and stateful component + * + * @param openingLikeElement a non-intrinsic JSXOPeningLikeElement + * @param shouldIncludeAllStatelessAttributesType a boolean indicating whether to include all attributes types from all stateless function signature + * @param sourceAttributesType Is the attributes type the user passed, and is used to create inferences in the target type if present + * @param elementType an instance type of the given opening-like element. If undefined, the function will check type openinglikeElement's tagname. + * @param elementClassType a JSX-ElementClass type. This is a result of looking up ElementClass interface in the JSX global (imported from react.d.ts) + * @return attributes type if able to resolve the type of node + * anyType if there is no type ElementAttributesProperty or there is an error + * emptyObjectType if there is no "prop" in the element instance type + */ function resolveCustomJsxElementAttributesType(openingLikeElement, shouldIncludeAllStatelessAttributesType, elementType, elementClassType) { - if (elementType.flags & 262144) { + if (elementType.flags & 262144 /* Union */) { var types = elementType.types; return getUnionType(types.map(function (type) { return resolveCustomJsxElementAttributesType(openingLikeElement, shouldIncludeAllStatelessAttributesType, type, elementClassType); - }), 2); + }), 2 /* Subtype */); } + // Shortcircuit any if (isTypeAny(elementType)) { return elementType; } - else if (elementType.flags & 4) { + // If the elemType is a string type, we have to return anyType to prevent an error downstream as we will try to find construct or call signature of the type + else if (elementType.flags & 4 /* String */) { return anyType; } - else if (elementType.flags & 64) { + else if (elementType.flags & 64 /* StringLiteral */) { + // If the elemType is a stringLiteral type, we can then provide a check to make sure that the string literal type is one of the Jsx intrinsic element type + // For example: + // var CustomTag: "h1" = "h1"; + // Hello World var intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements, openingLikeElement); if (intrinsicElementsType !== errorType) { var stringLiteralTypeName = elementType.value; @@ -38380,41 +44479,51 @@ var ts; if (intrinsicProp) { return getTypeOfSymbol(intrinsicProp); } - var indexSignatureType = getIndexTypeOfType(intrinsicElementsType, 0); + var indexSignatureType = getIndexTypeOfType(intrinsicElementsType, 0 /* String */); if (indexSignatureType) { return indexSignatureType; } error(openingLikeElement, ts.Diagnostics.Property_0_does_not_exist_on_type_1, stringLiteralTypeName, "JSX." + JsxNames.IntrinsicElements); } + // If we need to report an error, we already done so here. So just return any to prevent any more error downstream return anyType; } - var instantiatedSignatures = getInstantiatedJsxSignatures(openingLikeElement, elementType, true); + // Get the element instance type (the result of newing or invoking this tag) + var instantiatedSignatures = getInstantiatedJsxSignatures(openingLikeElement, elementType, /*reportErrors*/ true); if (!ts.length(instantiatedSignatures)) { return errorType; } - var elemInstanceType = getUnionType(instantiatedSignatures.map(getReturnTypeOfSignature), 2); + var elemInstanceType = getUnionType(instantiatedSignatures.map(getReturnTypeOfSignature), 2 /* Subtype */); + // If we should include all stateless attributes type, then get all attributes type from all stateless function signature. + // Otherwise get only attributes type from the signature picked by choose-overload logic. var statelessAttributesType = shouldIncludeAllStatelessAttributesType ? tryGetAllJsxStatelessFunctionAttributesType(openingLikeElement, elementType, elemInstanceType, elementClassType) : defaultTryGetJsxStatelessFunctionAttributesType(openingLikeElement, elementType, elemInstanceType, elementClassType); if (statelessAttributesType) { return statelessAttributesType; } + // Issue an error if this return type isn't assignable to JSX.ElementClass if (elementClassType) { checkTypeRelatedTo(elemInstanceType, elementClassType, assignableRelation, openingLikeElement, ts.Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements); } var isJs = ts.isInJavaScriptFile(openingLikeElement); - return getUnionType(instantiatedSignatures.map(function (sig) { return getJsxPropsTypeFromClassType(sig, isJs, openingLikeElement, true); })); + return getUnionType(instantiatedSignatures.map(function (sig) { return getJsxPropsTypeFromClassType(sig, isJs, openingLikeElement, /*reportErrors*/ true); })); } + /** + * Get attributes type of the given intrinsic opening-like Jsx element by resolving the tag name. + * The function is intended to be called from a function which has checked that the opening element is an intrinsic element. + * @param node an intrinsic JSX opening-like element + */ function getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node) { ts.Debug.assert(isJsxIntrinsicIdentifier(node.tagName)); var links = getNodeLinks(node); if (!links.resolvedJsxElementAttributesType) { var symbol = getIntrinsicTagSymbol(node); - if (links.jsxFlags & 1) { + if (links.jsxFlags & 1 /* IntrinsicNamedElement */) { return links.resolvedJsxElementAttributesType = getTypeOfSymbol(symbol); } - else if (links.jsxFlags & 2) { - return links.resolvedJsxElementAttributesType = getIndexInfoOfSymbol(symbol, 0).type; + else if (links.jsxFlags & 2 /* IntrinsicIndexedElement */) { + return links.resolvedJsxElementAttributesType = getIndexInfoOfSymbol(symbol, 0 /* String */).type; } else { return links.resolvedJsxElementAttributesType = errorType; @@ -38422,25 +44531,48 @@ var ts; } return links.resolvedJsxElementAttributesType; } + /** + * Get attributes type of the given custom opening-like JSX element. + * This function is intended to be called from a caller that handles intrinsic JSX element already. + * @param node a custom JSX opening-like element + * @param shouldIncludeAllStatelessAttributesType a boolean value used by language service to get all possible attributes type from an overload stateless function component + */ function getCustomJsxElementAttributesType(node, shouldIncludeAllStatelessAttributesType) { return resolveCustomJsxElementAttributesType(node, shouldIncludeAllStatelessAttributesType, checkExpression(node.tagName), getJsxElementClassTypeAt(node)); } + /** + * Get all possible attributes type, especially from an overload stateless function component, of the given JSX opening-like element. + * This function is called by language service (see: completions-tryGetGlobalSymbols). + * @param node a JSX opening-like element to get attributes type for + */ function getAllAttributesTypeFromJsxOpeningLikeElement(node) { if (isJsxIntrinsicIdentifier(node.tagName)) { return getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node); } else { - return getCustomJsxElementAttributesType(node, true); + // Because in language service, the given JSX opening-like element may be incomplete and therefore, + // we can't resolve to exact signature if the element is a stateless function component so the best thing to do is return all attributes type from all overloads. + return getCustomJsxElementAttributesType(node, /*shouldIncludeAllStatelessAttributesType*/ true); } } + /** + * Get the attributes type, which indicates the attributes that are valid on the given JSXOpeningLikeElement. + * @param node a JSXOpeningLikeElement node + * @return an attributes type of the given node + */ function getAttributesTypeFromJsxOpeningLikeElement(node) { if (isJsxIntrinsicIdentifier(node.tagName)) { return getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node); } else { - return getCustomJsxElementAttributesType(node, false); + return getCustomJsxElementAttributesType(node, /*shouldIncludeAllStatelessAttributesType*/ false); } } + /** + * Given a JSX attribute, returns the symbol for the corresponds property + * of the element attributes type. Will return unknownSymbol for attributes + * that have no matching element attributes type property. + */ function getJsxAttributePropertySymbol(attrib) { var attributesType = getAttributesTypeFromJsxOpeningLikeElement(attrib.parent.parent); var prop = getPropertyOfType(attributesType, attrib.name.escapedText); @@ -38461,12 +44593,16 @@ var ts; return getUnionType([jsxElementType, nullType]); } } + /** + * Returns all the properties of the Jsx.IntrinsicElements interface + */ function getJsxIntrinsicTagNamesAt(location) { var intrinsics = getJsxType(JsxNames.IntrinsicElements, location); return intrinsics ? getPropertiesOfType(intrinsics) : ts.emptyArray; } function checkJsxPreconditions(errorNode) { - if ((compilerOptions.jsx || 0) === 0) { + // Preconditions for using JSX + if ((compilerOptions.jsx || 0 /* None */) === 0 /* None */) { error(errorNode, ts.Diagnostics.Cannot_use_JSX_unless_the_jsx_flag_is_provided); } if (getJsxElementTypeAt(errorNode) === undefined) { @@ -38481,13 +44617,18 @@ var ts; checkGrammarJsxElement(node); } checkJsxPreconditions(node); - var reactRefErr = diagnostics && compilerOptions.jsx === 2 ? ts.Diagnostics.Cannot_find_name_0 : undefined; + // The reactNamespace/jsxFactory's root symbol should be marked as 'used' so we don't incorrectly elide its import. + // And if there is no reactNamespace/jsxFactory's symbol in scope when targeting React emit, we should issue an error. + var reactRefErr = diagnostics && compilerOptions.jsx === 2 /* React */ ? ts.Diagnostics.Cannot_find_name_0 : undefined; var reactNamespace = getJsxNamespace(node); var reactLocation = isNodeOpeningLikeElement ? node.tagName : node; - var reactSym = resolveName(reactLocation, reactNamespace, 67216319, reactRefErr, reactNamespace, true); + var reactSym = resolveName(reactLocation, reactNamespace, 67216319 /* Value */, reactRefErr, reactNamespace, /*isUse*/ true); if (reactSym) { - reactSym.isReferenced = 67108863; - if (reactSym.flags & 2097152 && !isConstEnumOrConstEnumOnlyModule(resolveAlias(reactSym))) { + // Mark local symbol as referenced here because it might not have been marked + // if jsx emit was not react as there wont be error being emitted + reactSym.isReferenced = 67108863 /* All */; + // If react symbol is alias, mark it as refereced + if (reactSym.flags & 2097152 /* Alias */ && !isConstEnumOrConstEnumOnlyModule(resolveAlias(reactSym))) { markAliasSymbolAsReferenced(reactSym); } } @@ -38498,17 +44639,31 @@ var ts; checkJsxChildren(node.parent); } } + /** + * Check if a property with the given name is known anywhere in the given type. In an object type, a property + * is considered known if + * 1. the object type is empty and the check is for assignability, or + * 2. if the object type has index signatures, or + * 3. if the property is actually declared in the object type + * (this means that 'toString', for example, is not usually a known property). + * 4. In a union or intersection type, + * a property is considered known if it is known in any constituent type. + * @param targetType a type to search a given name in + * @param name a property name to search + * @param isComparingJsxAttributes a boolean flag indicating whether we are searching in JsxAttributesType + */ function isKnownProperty(targetType, name, isComparingJsxAttributes) { - if (targetType.flags & 131072) { + if (targetType.flags & 131072 /* Object */) { var resolved = resolveStructuredTypeMembers(targetType); if (resolved.stringIndexInfo || resolved.numberIndexInfo && isNumericLiteralName(name) || getPropertyOfObjectType(targetType, name) || isComparingJsxAttributes && !isUnhyphenatedJsxName(name)) { + // For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known. return true; } } - else if (targetType.flags & 786432) { + else if (targetType.flags & 786432 /* UnionOrIntersection */) { for (var _i = 0, _a = targetType.types; _i < _a.length; _i++) { var t = _a[_i]; if (isKnownProperty(t, name, isComparingJsxAttributes)) { @@ -38518,12 +44673,30 @@ var ts; } return false; } + /** + * Check whether the given attributes of JSX opening-like element is assignable to the tagName attributes. + * Get the attributes type of the opening-like element through resolving the tagName, "target attributes" + * Check assignablity between given attributes property, "source attributes", and the "target attributes" + * @param openingLikeElement an opening-like JSX element to check its JSXAttributes + */ function checkJsxAttributesAssignableToTagNameAttributes(openingLikeElement, checkMode) { + // The function involves following steps: + // 1. Figure out expected attributes type by resolving tagName of the JSX opening-like element, targetAttributesType. + // During these steps, we will try to resolve the tagName as intrinsic name, stateless function, stateful component (in the order) + // 2. Solved JSX attributes type given by users, sourceAttributesType, which is by resolving "attributes" property of the JSX opening-like element. + // 3. Check if the two are assignable to each other + // targetAttributesType is a type of an attribute from resolving tagName of an opening-like JSX element. var targetAttributesType = isJsxIntrinsicIdentifier(openingLikeElement.tagName) ? getIntrinsicAttributesTypeFromJsxOpeningLikeElement(openingLikeElement) : - getCustomJsxElementAttributesType(openingLikeElement, false); + getCustomJsxElementAttributesType(openingLikeElement, /*shouldIncludeAllStatelessAttributesType*/ false); + // sourceAttributesType is a type of an attributes properties. + // i.e
+ // attr1 and attr2 are treated as JSXAttributes attached in the JsxOpeningLikeElement as "attributes". var sourceAttributesType = createJsxAttributesTypeFromAttributesProperty(openingLikeElement, checkMode); + // Check if sourceAttributesType assignable to targetAttributesType though this check will allow excess properties var isSourceAttributeTypeAssignableToTarget = isTypeAssignableTo(sourceAttributesType, targetAttributesType); + // After we check for assignability, we will do another pass to check that all explicitly specified attributes have correct name corresponding in targetAttributeType. + // This will allow excess properties in spread type as it is very common pattern to spread outer attributes into React component in its render method. if (isSourceAttributeTypeAssignableToTarget && !isTypeAny(sourceAttributesType) && !isTypeAny(targetAttributesType)) { for (var _i = 0, _a = openingLikeElement.attributes.properties; _i < _a.length; _i++) { var attribute = _a[_i]; @@ -38532,13 +44705,15 @@ var ts; } var attrName = attribute.name; var isNotIgnoredJsxProperty = (isUnhyphenatedJsxName(ts.idText(attrName)) || !!(getPropertyOfType(targetAttributesType, attrName.escapedText))); - if (isNotIgnoredJsxProperty && !isKnownProperty(targetAttributesType, attrName.escapedText, true)) { + if (isNotIgnoredJsxProperty && !isKnownProperty(targetAttributesType, attrName.escapedText, /*isComparingJsxAttributes*/ true)) { error(attribute, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.idText(attrName), typeToString(targetAttributesType)); + // We break here so that errors won't be cascading break; } } } else if (!isSourceAttributeTypeAssignableToTarget) { + // Assignability failure - check each prop individually, and if that fails, fall back on the bad error span if (ts.length(openingLikeElement.attributes.properties)) { var reportedError = false; var _loop_8 = function (prop) { @@ -38547,8 +44722,9 @@ var ts; var name = ts.idText(prop.name); var sourcePropType = getIndexedAccessType(sourceAttributesType, getLiteralType(name)); var targetPropType = getIndexedAccessType(targetAttributesType, getLiteralType(name)); - var rootChain = function () { return ts.chainDiagnosticMessages(undefined, ts.Diagnostics.Types_of_property_0_are_incompatible, name); }; - if (!checkTypeAssignableTo(sourcePropType, targetPropType, prop, undefined, rootChain)) { + var rootChain = function () { return ts.chainDiagnosticMessages( + /*details*/ undefined, ts.Diagnostics.Types_of_property_0_are_incompatible, name); }; + if (!checkTypeAssignableTo(sourcePropType, targetPropType, prop, /*headMessage*/ undefined, rootChain)) { reportedError = true; } }; @@ -38560,6 +44736,7 @@ var ts; return; } } + // Report fallback error on just the component name checkTypeAssignableTo(sourceAttributesType, targetAttributesType, openingLikeElement.tagName); } } @@ -38575,56 +44752,86 @@ var ts; return errorType; } } + // If a symbol is a synthesized symbol with no value declaration, we assume it is a property. Example of this are the synthesized + // '.prototype' property as well as synthesized tuple index properties. function getDeclarationKindFromSymbol(s) { - return s.valueDeclaration ? s.valueDeclaration.kind : 152; + return s.valueDeclaration ? s.valueDeclaration.kind : 152 /* PropertyDeclaration */; } function getDeclarationNodeFlagsFromSymbol(s) { return s.valueDeclaration ? ts.getCombinedNodeFlags(s.valueDeclaration) : 0; } + /** + * Return whether this symbol is a member of a prototype somewhere + * Note that this is not tracked well within the compiler, so the answer may be incorrect. + */ function isPrototypeProperty(symbol) { - if (symbol.flags & 8192 || ts.getCheckFlags(symbol) & 4) { + if (symbol.flags & 8192 /* Method */ || ts.getCheckFlags(symbol) & 4 /* SyntheticMethod */) { return true; } if (ts.isInJavaScriptFile(symbol.valueDeclaration)) { var parent = symbol.valueDeclaration.parent; return parent && ts.isBinaryExpression(parent) && - ts.getSpecialPropertyAssignmentKind(parent) === 3; + ts.getSpecialPropertyAssignmentKind(parent) === 3 /* PrototypeProperty */; } } + /** + * Check whether the requested property access is valid. + * Returns true if node is a valid property access, and false otherwise. + * @param node The node to be checked. + * @param left The left hand side of the property access (e.g.: the super in `super.foo`). + * @param type The type of left. + * @param prop The symbol for the right hand side of the property access. + */ function checkPropertyAccessibility(node, left, type, prop) { var flags = ts.getDeclarationModifierFlagsFromSymbol(prop); - var errorNode = node.kind === 185 || node.kind === 232 ? + var errorNode = node.kind === 185 /* PropertyAccessExpression */ || node.kind === 232 /* VariableDeclaration */ ? node.name : - node.kind === 179 ? + node.kind === 179 /* ImportType */ ? node : node.right; - if (ts.getCheckFlags(prop) & 256) { + if (ts.getCheckFlags(prop) & 256 /* ContainsPrivate */) { + // Synthetic property with private constituent property error(errorNode, ts.Diagnostics.Property_0_has_conflicting_declarations_and_is_inaccessible_in_type_1, symbolToString(prop), typeToString(type)); return false; } - if (left.kind === 97) { - if (languageVersion < 2) { + if (left.kind === 97 /* SuperKeyword */) { + // TS 1.0 spec (April 2014): 4.8.2 + // - In a constructor, instance member function, instance member accessor, or + // instance member variable initializer where this references a derived class instance, + // a super property access is permitted and must specify a public instance member function of the base class. + // - In a static member function or static member accessor + // where this references the constructor function object of a derived class, + // a super property access is permitted and must specify a public static member function of the base class. + if (languageVersion < 2 /* ES2015 */) { if (symbolHasNonMethodDeclaration(prop)) { error(errorNode, ts.Diagnostics.Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword); return false; } } - if (flags & 128) { + if (flags & 128 /* Abstract */) { + // A method cannot be accessed in a super property access if the method is abstract. + // This error could mask a private property access error. But, a member + // cannot simultaneously be private and abstract, so this will trigger an + // additional error elsewhere. error(errorNode, ts.Diagnostics.Abstract_method_0_in_class_1_cannot_be_accessed_via_super_expression, symbolToString(prop), typeToString(getDeclaringClass(prop))); return false; } } - if ((flags & 128) && ts.isThisProperty(node) && symbolHasNonMethodDeclaration(prop)) { + // Referencing abstract properties within their own constructors is not allowed + if ((flags & 128 /* Abstract */) && ts.isThisProperty(node) && symbolHasNonMethodDeclaration(prop)) { var declaringClassDeclaration = ts.getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)); if (declaringClassDeclaration && isNodeWithinConstructorOfClass(node, declaringClassDeclaration)) { - error(errorNode, ts.Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, symbolToString(prop), ts.getTextOfIdentifierOrLiteral(declaringClassDeclaration.name)); + error(errorNode, ts.Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, symbolToString(prop), ts.getTextOfIdentifierOrLiteral(declaringClassDeclaration.name)); // TODO: GH#18217 return false; } } - if (!(flags & 24)) { + // Public properties are otherwise accessible. + if (!(flags & 24 /* NonPublicAccessibilityModifier */)) { return true; } - if (flags & 8) { + // Property is known to be private or protected at this point + // Private property is accessible if the property is within the declaring class + if (flags & 8 /* Private */) { var declaringClassDeclaration = ts.getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)); if (!isNodeWithinClass(node, declaringClassDeclaration)) { error(errorNode, ts.Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, symbolToString(prop), typeToString(getDeclaringClass(prop))); @@ -38632,27 +44839,36 @@ var ts; } return true; } - if (left.kind === 97) { + // Property is known to be protected at this point + // All protected properties of a supertype are accessible in a super access + if (left.kind === 97 /* SuperKeyword */) { return true; } + // Find the first enclosing class that has the declaring classes of the protected constituents + // of the property as base classes var enclosingClass = forEachEnclosingClass(node, function (enclosingDeclaration) { var enclosingClass = getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingDeclaration)); return isClassDerivedFromDeclaringClasses(enclosingClass, prop) ? enclosingClass : undefined; }); + // A protected property is accessible if the property is within the declaring class or classes derived from it if (!enclosingClass) { + // allow PropertyAccessibility if context is in function with this parameter + // static member access is disallow var thisParameter = void 0; - if (flags & 32 || !(thisParameter = getThisParameterFromNodeContext(node)) || !thisParameter.type) { + if (flags & 32 /* Static */ || !(thisParameter = getThisParameterFromNodeContext(node)) || !thisParameter.type) { error(errorNode, ts.Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, symbolToString(prop), typeToString(getDeclaringClass(prop) || type)); return false; } var thisType = getTypeFromTypeNode(thisParameter.type); - enclosingClass = ((thisType.flags & 65536) ? getConstraintFromTypeParameter(thisType) : thisType); + enclosingClass = ((thisType.flags & 65536 /* TypeParameter */) ? getConstraintFromTypeParameter(thisType) : thisType); } - if (flags & 32) { + // No further restrictions for static properties + if (flags & 32 /* Static */) { return true; } - if (type.flags & 65536) { - type = type.isThisType ? getConstraintOfTypeParameter(type) : getBaseConstraintOfType(type); + if (type.flags & 65536 /* TypeParameter */) { + // get the original type -- represented as the type constraint of the 'this' type + type = type.isThisType ? getConstraintOfTypeParameter(type) : getBaseConstraintOfType(type); // TODO: GH#18217 Use a different variable that's allowed to be undefined } if (!type || !hasBaseType(type, enclosingClass)) { error(errorNode, ts.Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1, symbolToString(prop), typeToString(enclosingClass)); @@ -38661,31 +44877,31 @@ var ts; return true; } function getThisParameterFromNodeContext(node) { - var thisContainer = ts.getThisContainer(node, false); + var thisContainer = ts.getThisContainer(node, /* includeArrowFunctions */ false); return thisContainer && ts.isFunctionLike(thisContainer) ? ts.getThisParameter(thisContainer) : undefined; } function symbolHasNonMethodDeclaration(symbol) { return forEachProperty(symbol, function (prop) { var propKind = getDeclarationKindFromSymbol(prop); - return propKind !== 154 && propKind !== 153; + return propKind !== 154 /* MethodDeclaration */ && propKind !== 153 /* MethodSignature */; }); } function checkNonNullExpression(node, nullDiagnostic, undefinedDiagnostic, nullOrUndefinedDiagnostic) { return checkNonNullType(checkExpression(node), node, nullDiagnostic, undefinedDiagnostic, nullOrUndefinedDiagnostic); } function checkNonNullType(type, node, nullDiagnostic, undefinedDiagnostic, nullOrUndefinedDiagnostic) { - if (type.flags & 2) { + if (type.flags & 2 /* Unknown */) { error(node, ts.Diagnostics.Object_is_of_type_unknown); return errorType; } - var kind = (strictNullChecks ? getFalsyFlags(type) : type.flags) & 24576; + var kind = (strictNullChecks ? getFalsyFlags(type) : type.flags) & 24576 /* Nullable */; if (kind) { - error(node, kind & 8192 ? kind & 16384 ? + error(node, kind & 8192 /* Undefined */ ? kind & 16384 /* Null */ ? (nullOrUndefinedDiagnostic || ts.Diagnostics.Object_is_possibly_null_or_undefined) : (undefinedDiagnostic || ts.Diagnostics.Object_is_possibly_undefined) : (nullDiagnostic || ts.Diagnostics.Object_is_possibly_null)); var t = getNonNullableType(type); - return t.flags & (24576 | 32768) ? errorType : t; + return t.flags & (24576 /* Nullable */ | 32768 /* Never */) ? errorType : t; } return type; } @@ -38712,10 +44928,10 @@ var ts; markAliasReferenced(parentSymbol, node); } if (!prop) { - var indexInfo = getIndexInfoOfType(apparentType, 0); + var indexInfo = getIndexInfoOfType(apparentType, 0 /* String */); if (!(indexInfo && indexInfo.type)) { if (right.escapedText && !checkAndReportErrorForExtendingInterface(node)) { - reportNonexistentProperty(right, leftType.flags & 65536 && leftType.isThisType ? apparentType : leftType); + reportNonexistentProperty(right, leftType.flags & 65536 /* TypeParameter */ && leftType.isThisType ? apparentType : leftType); } return errorType; } @@ -38726,7 +44942,7 @@ var ts; } else { checkPropertyNotUsedBeforeDeclaration(prop, node, right); - markPropertyAsReferenced(prop, node, left.kind === 99); + markPropertyAsReferenced(prop, node, left.kind === 99 /* ThisKeyword */); getNodeLinks(node).resolvedSymbol = prop; checkPropertyAccessibility(node, left, apparentType, prop); if (assignmentKind) { @@ -38737,24 +44953,32 @@ var ts; } propType = getConstraintForLocation(getTypeOfSymbol(prop), node); } - if (node.kind !== 185 || - assignmentKind === 1 || - prop && !(prop.flags & (3 | 4 | 98304)) && !(prop.flags & 8192 && propType.flags & 262144)) { + // Only compute control flow type if this is a property access expression that isn't an + // assignment target, and the referenced property was declared as a variable, property, + // accessor, or optional method. + if (node.kind !== 185 /* PropertyAccessExpression */ || + assignmentKind === 1 /* Definite */ || + prop && !(prop.flags & (3 /* Variable */ | 4 /* Property */ | 98304 /* Accessor */)) && !(prop.flags & 8192 /* Method */ && propType.flags & 262144 /* Union */)) { return propType; } + // If strict null checks and strict property initialization checks are enabled, if we have + // a this.xxx property access, if the property is an instance property without an initializer, + // and if we are in a constructor of the same class as the property declaration, assume that + // the property is uninitialized at the top of the control flow. var assumeUninitialized = false; - if (strictNullChecks && strictPropertyInitialization && left.kind === 99) { + if (strictNullChecks && strictPropertyInitialization && left.kind === 99 /* ThisKeyword */) { var declaration = prop && prop.valueDeclaration; if (declaration && isInstancePropertyWithoutInitializer(declaration)) { var flowContainer = getControlFlowContainer(node); - if (flowContainer.kind === 155 && flowContainer.parent === declaration.parent) { + if (flowContainer.kind === 155 /* Constructor */ && flowContainer.parent === declaration.parent) { assumeUninitialized = true; } } } var flowType = getFlowTypeOfReference(node, propType, assumeUninitialized ? getOptionalType(propType) : propType); - if (assumeUninitialized && !(getFalsyFlags(propType) & 8192) && getFalsyFlags(flowType) & 8192) { - error(right, ts.Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(prop)); + if (assumeUninitialized && !(getFalsyFlags(propType) & 8192 /* Undefined */) && getFalsyFlags(flowType) & 8192 /* Undefined */) { + error(right, ts.Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(prop)); // TODO: GH#18217 + // Return the declared type to reduce follow-on errors return propType; } return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType; @@ -38769,9 +44993,9 @@ var ts; && !isPropertyDeclaredInAncestorClass(prop)) { error(right, ts.Diagnostics.Block_scoped_variable_0_used_before_its_declaration, ts.idText(right)); } - else if (valueDeclaration.kind === 235 && - node.parent.kind !== 162 && - !(valueDeclaration.flags & 4194304) && + else if (valueDeclaration.kind === 235 /* ClassDeclaration */ && + node.parent.kind !== 162 /* TypeReference */ && + !(valueDeclaration.flags & 4194304 /* Ambient */) && !isBlockScopedNameDeclaredBeforeUse(valueDeclaration, right)) { error(right, ts.Diagnostics.Class_0_used_before_its_declaration, ts.idText(right)); } @@ -38779,17 +45003,22 @@ var ts; function isInPropertyInitializer(node) { return !!ts.findAncestor(node, function (node) { switch (node.kind) { - case 152: + case 152 /* PropertyDeclaration */: return true; - case 270: + case 270 /* PropertyAssignment */: + // We might be in `a = { b: this.b }`, so keep looking. See `tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts`. return false; default: return ts.isExpressionNode(node) ? false : "quit"; } }); } + /** + * It's possible that "prop.valueDeclaration" is a local declaration, but the property was also declared in a superclass. + * In that case we won't consider it used before its declaration, because it gets its value from the superclass' declaration. + */ function isPropertyDeclaredInAncestorClass(prop) { - if (!(prop.parent.flags & 32)) { + if (!(prop.parent.flags & 32 /* Class */)) { return false; } var classType = getTypeOfSymbol(prop.parent); @@ -38813,7 +45042,7 @@ var ts; } function reportNonexistentProperty(propNode, containingType) { var errorInfo; - if (containingType.flags & 262144 && !(containingType.flags & 32764)) { + if (containingType.flags & 262144 /* Union */ && !(containingType.flags & 32764 /* Primitive */)) { for (var _i = 0, _a = containingType.types; _i < _a.length; _i++) { var subtype = _a[_i]; if (!getPropertyOfType(subtype, propNode.escapedText)) { @@ -38838,22 +45067,40 @@ var ts; diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(propNode, errorInfo)); } function getSuggestionForNonexistentProperty(node, containingType) { - var suggestion = getSpellingSuggestionForName(ts.idText(node), getPropertiesOfType(containingType), 67216319); + var suggestion = getSpellingSuggestionForName(ts.idText(node), getPropertiesOfType(containingType), 67216319 /* Value */); return suggestion && ts.symbolName(suggestion); } function getSuggestionForNonexistentSymbol(location, outerName, meaning) { ts.Debug.assert(outerName !== undefined, "outername should always be defined"); - var result = resolveNameHelper(location, outerName, meaning, undefined, outerName, false, false, function (symbols, name, meaning) { + var result = resolveNameHelper(location, outerName, meaning, /*nameNotFoundMessage*/ undefined, outerName, /*isUse*/ false, /*excludeGlobals*/ false, function (symbols, name, meaning) { ts.Debug.assertEqual(outerName, name, "name should equal outerName"); var symbol = getSymbol(symbols, name, meaning); + // Sometimes the symbol is found when location is a return type of a function: `typeof x` and `x` is declared in the body of the function + // So the table *contains* `x` but `x` isn't actually in scope. + // However, resolveNameHelper will continue and call this callback again, so we'll eventually get a correct suggestion. return symbol || getSpellingSuggestionForName(ts.unescapeLeadingUnderscores(name), ts.arrayFrom(symbols.values()), meaning); }); return result && ts.symbolName(result); } function getSuggestionForNonexistentModule(name, targetModule) { - var suggestion = targetModule.exports && getSpellingSuggestionForName(ts.idText(name), getExportsOfModuleAsArray(targetModule), 2623475); + var suggestion = targetModule.exports && getSpellingSuggestionForName(ts.idText(name), getExportsOfModuleAsArray(targetModule), 2623475 /* ModuleMember */); return suggestion && ts.symbolName(suggestion); } + /** + * Given a name and a list of symbols whose names are *not* equal to the name, return a spelling suggestion if there is one that is close enough. + * Names less than length 3 only check for case-insensitive equality, not levenshtein distance. + * + * If there is a candidate that's the same except for case, return that. + * If there is a candidate that's within one edit of the name, return that. + * Otherwise, return the candidate with the smallest Levenshtein distance, + * except for candidates: + * * With no name + * * Whose meaning doesn't match the `meaning` parameter. + * * Whose length differs from the target name by more than 0.34 of the length of the name. + * * Whose levenshtein distance is more than 0.4 of the length of the name + * (0.4 allows 1 substitution/transposition for every 5 characters, + * and 1 insertion/deletion at 3 characters) + */ function getSpellingSuggestionForName(name, symbols, meaning) { return ts.getSpellingSuggestion(name, symbols, getCandidateName); function getCandidateName(candidate) { @@ -38862,37 +45109,38 @@ var ts; } } function markPropertyAsReferenced(prop, nodeForCheckWriteOnly, isThisAccess) { - if (!prop || !(prop.flags & 106500) || !prop.valueDeclaration || !ts.hasModifier(prop.valueDeclaration, 8)) { + if (!prop || !(prop.flags & 106500 /* ClassMember */) || !prop.valueDeclaration || !ts.hasModifier(prop.valueDeclaration, 8 /* Private */)) { return; } - if (nodeForCheckWriteOnly && ts.isWriteOnlyAccess(nodeForCheckWriteOnly) && !(prop.flags & 65536 && !(prop.flags & 32768))) { + if (nodeForCheckWriteOnly && ts.isWriteOnlyAccess(nodeForCheckWriteOnly) && !(prop.flags & 65536 /* SetAccessor */ && !(prop.flags & 32768 /* GetAccessor */))) { return; } if (isThisAccess) { + // Find any FunctionLikeDeclaration because those create a new 'this' binding. But this should only matter for methods (or getters/setters). var containingMethod = ts.findAncestor(nodeForCheckWriteOnly, ts.isFunctionLikeDeclaration); if (containingMethod && containingMethod.symbol === prop) { return; } } - (ts.getCheckFlags(prop) & 1 ? getSymbolLinks(prop).target : prop).isReferenced = 67108863; + (ts.getCheckFlags(prop) & 1 /* Instantiated */ ? getSymbolLinks(prop).target : prop).isReferenced = 67108863 /* All */; } function isValidPropertyAccess(node, propertyName) { switch (node.kind) { - case 185: + case 185 /* PropertyAccessExpression */: return isValidPropertyAccessWithType(node, node.expression, propertyName, getWidenedType(checkExpression(node.expression))); - case 146: + case 146 /* QualifiedName */: return isValidPropertyAccessWithType(node, node.left, propertyName, getWidenedType(checkExpression(node.left))); - case 179: + case 179 /* ImportType */: return isValidPropertyAccessWithType(node, node, propertyName, getTypeFromTypeNode(node)); } } function isValidPropertyAccessForCompletions(node, type, property) { - return isValidPropertyAccessWithType(node, node.kind === 179 ? node : node.expression, property.escapedName, type) - && (!(property.flags & 8192) || isValidMethodAccess(property, type)); + return isValidPropertyAccessWithType(node, node.kind === 179 /* ImportType */ ? node : node.expression, property.escapedName, type) + && (!(property.flags & 8192 /* Method */) || isValidMethodAccess(property, type)); } function isValidMethodAccess(method, actualThisType) { var propType = getTypeOfPropertyOfType(actualThisType, method.escapedName); - var signatures = getSignaturesOfType(getNonNullableType(propType), 0); + var signatures = getSignaturesOfType(getNonNullableType(propType), 0 /* Call */); ts.Debug.assert(signatures.length !== 0); return signatures.some(function (sig) { var signatureThisType = getThisTypeOfSignature(sig); @@ -38903,7 +45151,7 @@ var ts; if (!sig.typeParameters) { return signatureThisType; } - var context = createInferenceContext(sig.typeParameters, sig, 0); + var context = createInferenceContext(sig.typeParameters, sig, 0 /* None */); inferTypes(context.inferences, actualThisType, signatureThisType); return instantiateType(signatureThisType, createSignatureTypeMapper(sig, getInferredTypes(context))); } @@ -38913,33 +45161,44 @@ var ts; } var prop = getPropertyOfType(type, propertyName); return prop ? checkPropertyAccessibility(node, left, type, prop) - : ts.isInJavaScriptFile(node) && (type.flags & 262144) !== 0 && type.types.some(function (elementType) { return isValidPropertyAccessWithType(node, left, propertyName, elementType); }); + // In js files properties of unions are allowed in completion + : ts.isInJavaScriptFile(node) && (type.flags & 262144 /* Union */) !== 0 && type.types.some(function (elementType) { return isValidPropertyAccessWithType(node, left, propertyName, elementType); }); } + /** + * Return the symbol of the for-in variable declared or referenced by the given for-in statement. + */ function getForInVariableSymbol(node) { var initializer = node.initializer; - if (initializer.kind === 233) { + if (initializer.kind === 233 /* VariableDeclarationList */) { var variable = initializer.declarations[0]; if (variable && !ts.isBindingPattern(variable.name)) { return getSymbolOfNode(variable); } } - else if (initializer.kind === 71) { + else if (initializer.kind === 71 /* Identifier */) { return getResolvedSymbol(initializer); } return undefined; } + /** + * Return true if the given type is considered to have numeric property names. + */ function hasNumericPropertyNames(type) { - return getIndexTypeOfType(type, 1) && !getIndexTypeOfType(type, 0); + return getIndexTypeOfType(type, 1 /* Number */) && !getIndexTypeOfType(type, 0 /* String */); } + /** + * Return true if given node is an expression consisting of an identifier (possibly parenthesized) + * that references a for-in variable for an object with numeric property names. + */ function isForInVariableForNumericPropertyNames(expr) { var e = ts.skipParentheses(expr); - if (e.kind === 71) { + if (e.kind === 71 /* Identifier */) { var symbol = getResolvedSymbol(e); - if (symbol.flags & 3) { + if (symbol.flags & 3 /* Variable */) { var child = expr; var node = expr.parent; while (node) { - if (node.kind === 221 && + if (node.kind === 221 /* ForInStatement */ && child === node.statement && getForInVariableSymbol(node) === symbol && hasNumericPropertyNames(getTypeOfExpression(node.expression))) { @@ -38957,7 +45216,7 @@ var ts; var indexExpression = node.argumentExpression; if (!indexExpression) { var sourceFile = ts.getSourceFileOfNode(node); - if (node.parent.kind === 188 && node.parent.expression === node) { + if (node.parent.kind === 188 /* NewExpression */ && node.parent.expression === node) { var start = ts.skipTrivia(sourceFile.text, node.expression.end); var end = node.end; grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead); @@ -38973,7 +45232,7 @@ var ts; if (objectType === errorType || objectType === silentNeverType) { return objectType; } - if (isConstEnumObjectType(objectType) && indexExpression.kind !== 9) { + if (isConstEnumObjectType(objectType) && indexExpression.kind !== 9 /* StringLiteral */) { error(indexExpression, ts.Diagnostics.A_const_enum_member_can_only_be_accessed_using_a_string_literal); return errorType; } @@ -38981,24 +45240,29 @@ var ts; } function checkThatExpressionIsProperSymbolReference(expression, expressionType, reportError) { if (expressionType === errorType) { + // There is already an error, so no need to report one. return false; } if (!ts.isWellKnownSymbolSyntactically(expression)) { return false; } - if ((expressionType.flags & 3072) === 0) { + // Make sure the property type is the primitive symbol type + if ((expressionType.flags & 3072 /* ESSymbolLike */) === 0) { if (reportError) { error(expression, ts.Diagnostics.A_computed_property_name_of_the_form_0_must_be_of_type_symbol, ts.getTextOfNode(expression)); } return false; } + // The name is Symbol., so make sure Symbol actually resolves to the + // global Symbol object var leftHandSide = expression.expression; var leftHandSideSymbol = getResolvedSymbol(leftHandSide); if (!leftHandSideSymbol) { return false; } - var globalESSymbol = getGlobalESSymbolConstructorSymbol(true); + var globalESSymbol = getGlobalESSymbolConstructorSymbol(/*reportErrors*/ true); if (!globalESSymbol) { + // Already errored when we tried to look up the symbol return false; } if (leftHandSideSymbol !== globalESSymbol) { @@ -39010,16 +45274,19 @@ var ts; return true; } function callLikeExpressionMayHaveTypeArguments(node) { + // TODO: Also include tagged templates (https://github.com/Microsoft/TypeScript/issues/11947) return ts.isCallOrNewExpression(node); } function resolveUntypedCall(node) { if (callLikeExpressionMayHaveTypeArguments(node)) { + // Check type arguments even though we will give an error that untyped calls may not accept type arguments. + // This gets us diagnostics for the type arguments and marks them as referenced. ts.forEach(node.typeArguments, checkSourceElement); } - if (node.kind === 189) { + if (node.kind === 189 /* TaggedTemplateExpression */) { checkExpression(node.template); } - else if (node.kind !== 150) { + else if (node.kind !== 150 /* Decorator */) { ts.forEach(node.arguments, function (argument) { checkExpression(argument); }); @@ -39030,6 +45297,14 @@ var ts; resolveUntypedCall(node); return unknownSignature; } + // Re-order candidate signatures into the result array. Assumes the result array to be empty. + // The candidate list orders groups in reverse, but within a group signatures are kept in declaration order + // A nit here is that we reorder only signatures that belong to the same symbol, + // so order how inherited signatures are processed is still preserved. + // interface A { (x: string): void } + // interface B extends A { (x: 'foo'): string } + // const b: B; + // b('foo') // <- here overloads should be processed as [(x:'foo'): string, (x: string): void] function reorderCandidates(signatures, result) { var lastParent; var lastSymbol; @@ -39052,13 +45327,20 @@ var ts; } } else { + // current declaration belongs to a different symbol + // set cutoffIndex so re-orderings in the future won't change result set from 0 to cutoffIndex index = cutoffIndex = result.length; lastParent = parent; } lastSymbol = symbol; + // specialized signatures always need to be placed before non-specialized signatures regardless + // of the cutoff position; see GH#1133 if (signature.hasLiteralTypes) { specializedIndex++; spliceIndex = specializedIndex; + // The cutoff index always needs to be greater than or equal to the specialized signature index + // in order to prevent non-specialized signatures from being added before a specialized + // signature. cutoffIndex++; } else { @@ -39070,7 +45352,7 @@ var ts; function getSpreadArgumentIndex(args) { for (var i = 0; i < args.length; i++) { var arg = args[i]; - if (arg && arg.kind === 204) { + if (arg && arg.kind === 204 /* SpreadElement */) { return i; } } @@ -39078,36 +45360,46 @@ var ts; } function hasCorrectArity(node, args, signature, signatureHelpTrailingComma) { if (signatureHelpTrailingComma === void 0) { signatureHelpTrailingComma = false; } - var argCount; - var typeArguments; - var callIsIncomplete = false; + var argCount; // Apparent number of arguments we will have in this call + var typeArguments; // Type arguments (undefined if none) + var callIsIncomplete = false; // In incomplete call we want to be lenient when we have too few arguments var spreadArgIndex = -1; if (ts.isJsxOpeningLikeElement(node)) { + // The arity check will be done in "checkApplicableSignatureForJsxOpeningLikeElement". return true; } - if (node.kind === 189) { + if (node.kind === 189 /* TaggedTemplateExpression */) { + // Even if the call is incomplete, we'll have a missing expression as our last argument, + // so we can say the count is just the arg list length argCount = args.length; typeArguments = node.typeArguments; - if (node.template.kind === 202) { - var lastSpan = ts.last(node.template.templateSpans); + if (node.template.kind === 202 /* TemplateExpression */) { + // If a tagged template expression lacks a tail literal, the call is incomplete. + // Specifically, a template only can end in a TemplateTail or a Missing literal. + var lastSpan = ts.last(node.template.templateSpans); // we should always have at least one span. callIsIncomplete = ts.nodeIsMissing(lastSpan.literal) || !!lastSpan.literal.isUnterminated; } else { + // If the template didn't end in a backtick, or its beginning occurred right prior to EOF, + // then this might actually turn out to be a TemplateHead in the future; + // so we consider the call to be incomplete. var templateLiteral = node.template; - ts.Debug.assert(templateLiteral.kind === 13); + ts.Debug.assert(templateLiteral.kind === 13 /* NoSubstitutionTemplateLiteral */); callIsIncomplete = !!templateLiteral.isUnterminated; } } - else if (node.kind === 150) { + else if (node.kind === 150 /* Decorator */) { typeArguments = undefined; - argCount = getEffectiveArgumentCount(node, undefined, signature); + argCount = getEffectiveArgumentCount(node, /*args*/ undefined, signature); } else { if (!node.arguments) { - ts.Debug.assert(node.kind === 188); + // This only happens when we have something of the form: 'new C' + ts.Debug.assert(node.kind === 188 /* NewExpression */); return signature.minArgumentCount === 0; } argCount = signatureHelpTrailingComma ? args.length + 1 : args.length; + // If we are missing the close parenthesis, the call is incomplete. callIsIncomplete = node.arguments.end === node.end; typeArguments = node.typeArguments; spreadArgIndex = getSpreadArgumentIndex(args); @@ -39115,24 +45407,30 @@ var ts; if (!hasCorrectTypeArgumentArity(signature, typeArguments)) { return false; } + // If a spread argument is present, check that it corresponds to a rest parameter or at least that it's in the valid range. if (spreadArgIndex >= 0) { return isRestParameterIndex(signature, spreadArgIndex) || signature.minArgumentCount <= spreadArgIndex && spreadArgIndex < signature.parameters.length; } + // Too many arguments implies incorrect arity. if (!signature.hasRestParameter && argCount > signature.parameters.length) { return false; } + // If the call is incomplete, we should skip the lower bound check. var hasEnoughArguments = argCount >= signature.minArgumentCount; return callIsIncomplete || hasEnoughArguments; } function hasCorrectTypeArgumentArity(signature, typeArguments) { + // If the user supplied type arguments, but the number of type arguments does not match + // the declared number of type parameters, the call has an incorrect arity. var numTypeParameters = ts.length(signature.typeParameters); var minTypeArgumentCount = getMinTypeArgumentCount(signature.typeParameters); return !typeArguments || (typeArguments.length >= minTypeArgumentCount && typeArguments.length <= numTypeParameters); } + // If type has a single call signature and no other members, return that signature. Otherwise, return undefined. function getSingleCallSignature(type) { - if (type.flags & 131072) { + if (type.flags & 131072 /* Object */) { var resolved = resolveStructuredTypeMembers(type); if (resolved.callSignatures.length === 1 && resolved.constructSignatures.length === 0 && resolved.properties.length === 0 && !resolved.stringIndexInfo && !resolved.numberIndexInfo) { @@ -39141,42 +45439,66 @@ var ts; } return undefined; } + // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) function instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper, compareTypes) { - var context = createInferenceContext(signature.typeParameters, signature, 1, compareTypes); + var context = createInferenceContext(signature.typeParameters, signature, 1 /* InferUnionTypes */, compareTypes); forEachMatchingParameterType(contextualSignature, signature, function (source, target) { + // Type parameters from outer context referenced by source type are fixed by instantiation of the source type inferTypes(context.inferences, instantiateType(source, contextualMapper || identityMapper), target); }); if (!contextualMapper) { - inferTypes(context.inferences, getReturnTypeOfSignature(contextualSignature), getReturnTypeOfSignature(signature), 8); + inferTypes(context.inferences, getReturnTypeOfSignature(contextualSignature), getReturnTypeOfSignature(signature), 8 /* ReturnType */); } return getSignatureInstantiation(signature, getInferredTypes(context), ts.isInJavaScriptFile(contextualSignature.declaration)); } function inferJsxTypeArguments(signature, node, context) { + // Skip context sensitive pass var skipContextParamType = getTypeAtPosition(signature, 0); var checkAttrTypeSkipContextSensitive = checkExpressionWithContextualType(node.attributes, skipContextParamType, identityMapper); inferTypes(context.inferences, checkAttrTypeSkipContextSensitive, skipContextParamType); + // Standard pass var paramType = getTypeAtPosition(signature, 0); var checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, context); inferTypes(context.inferences, checkAttrType, paramType); return getInferredTypes(context); } function inferTypeArguments(node, signature, args, excludeArgument, context) { + // Clear out all the inference results from the last time inferTypeArguments was called on this context for (var _i = 0, _a = context.inferences; _i < _a.length; _i++) { var inference = _a[_i]; + // As an optimization, we don't have to clear (and later recompute) inferred types + // for type parameters that have already been fixed on the previous call to inferTypeArguments. + // It would be just as correct to reset all of them. But then we'd be repeating the same work + // for the type parameters that were fixed, namely the work done by getInferredType. if (!inference.isFixed) { inference.inferredType = undefined; } } - if (node.kind !== 150) { + // If a contextual type is available, infer from that type to the return type of the call expression. For + // example, given a 'function wrap(cb: (x: T) => U): (x: T) => U' and a call expression + // 'let f: (x: string) => number = wrap(s => s.length)', we infer from the declared type of 'f' to the + // return type of 'wrap'. + if (node.kind !== 150 /* Decorator */) { var contextualType = getContextualType(node); if (contextualType) { + // We clone the contextual mapper to avoid disturbing a resolution in progress for an + // outer call expression. Effectively we just want a snapshot of whatever has been + // inferred for any outer call expression so far. var instantiatedType = instantiateType(contextualType, cloneTypeMapper(getContextualMapper(node))); + // If the contextual type is a generic function type with a single call signature, we + // instantiate the type with its own type parameters and type arguments. This ensures that + // the type parameters are not erased to type any during type inference such that they can + // be inferred as actual types from the contextual type. For example: + // declare function arrayMap(f: (x: T) => U): (a: T[]) => U[]; + // const boxElements: (a: A[]) => { value: A }[] = arrayMap(value => ({ value })); + // Above, the type of the 'value' parameter is inferred to be 'A'. var contextualSignature = getSingleCallSignature(instantiatedType); var inferenceSourceType = contextualSignature && contextualSignature.typeParameters ? getOrCreateTypeFromSignature(getSignatureInstantiation(contextualSignature, contextualSignature.typeParameters, ts.isInJavaScriptFile(node))) : instantiatedType; var inferenceTargetType = getReturnTypeOfSignature(signature); - inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, 8); + // Inferences made from return types have lower priority than all other inferences. + inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, 8 /* ReturnType */); } } var thisType = getThisTypeOfSignature(signature); @@ -39185,21 +45507,34 @@ var ts; var thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType; inferTypes(context.inferences, thisArgumentType, thisType); } + // We perform two passes over the arguments. In the first pass we infer from all arguments, but use + // wildcards for all context sensitive function expressions. var argCount = getEffectiveArgumentCount(node, args, signature); for (var i = 0; i < argCount; i++) { var arg = getEffectiveArgument(node, args, i); - if (arg === undefined || arg.kind !== 206) { + // If the effective argument is 'undefined', then it is an argument that is present but is synthetic. + if (arg === undefined || arg.kind !== 206 /* OmittedExpression */) { var paramType = getTypeAtPosition(signature, i); var argType = getEffectiveArgumentType(node, i); + // If the effective argument type is 'undefined', there is no synthetic type + // for the argument. In that case, we should check the argument. if (argType === undefined) { + // For context sensitive arguments we pass the identityMapper, which is a signal to treat all + // context sensitive function expressions as wildcards var mapper = excludeArgument && excludeArgument[i] !== undefined ? identityMapper : context; argType = checkExpressionWithContextualType(arg, paramType, mapper); } inferTypes(context.inferences, argType, paramType); } } + // In the second pass we visit only context sensitive arguments, and only those that aren't excluded, this + // time treating function expressions normally (which may cause previously inferred type arguments to be fixed + // as we construct types for contextually typed parameters) + // Decorators will not have `excludeArgument`, as their arguments cannot be contextually typed. + // Tagged template expressions will always have `undefined` for `excludeArgument[0]`. if (excludeArgument) { for (var i = 0; i < argCount; i++) { + // No need to check for omitted args and template expressions, their exclusion value is always undefined if (excludeArgument[i] === false) { var arg = args[i]; var paramType = getTypeAtPosition(signature, i); @@ -39219,7 +45554,7 @@ var ts; var constraint = getConstraintOfTypeParameter(typeParameters[i]); if (!constraint) continue; - var errorInfo = reportErrors && headMessage ? (function () { return ts.chainDiagnosticMessages(undefined, ts.Diagnostics.Type_0_does_not_satisfy_the_constraint_1); }) : undefined; + var errorInfo = reportErrors && headMessage ? (function () { return ts.chainDiagnosticMessages(/*details*/ undefined, ts.Diagnostics.Type_0_does_not_satisfy_the_constraint_1); }) : undefined; var typeArgumentHeadMessage = headMessage || ts.Diagnostics.Type_0_does_not_satisfy_the_constraint_1; if (!mapper) { mapper = createTypeMapper(typeParameters, typeArgumentTypes); @@ -39231,14 +45566,29 @@ var ts; } return typeArgumentTypes; } + /** + * Check if the given signature can possibly be a signature called by the JSX opening-like element. + * @param node a JSX opening-like element we are trying to figure its call signature + * @param signature a candidate signature we are trying whether it is a call signature + * @param relation a relationship to check parameter and argument type + * @param excludeArgument + */ function checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation) { - var callIsIncomplete = node.attributes.end === node.end; + // JSX opening-like element has correct arity for stateless-function component if the one of the following condition is true: + // 1. callIsIncomplete + // 2. attributes property has same number of properties as the parameter object type. + // We can figure that out by resolving attributes property and check number of properties in the resolved type + // If the call has correct arity, we will then check if the argument type and parameter type is assignable + var callIsIncomplete = node.attributes.end === node.end; // If we are missing the close "/>", the call is incomplete if (callIsIncomplete) { return true; } var headMessage = ts.Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1; + // Stateless function components can have maximum of three arguments: "props", "context", and "updater". + // However "context" and "updater" are implicit and can't be specify by users. Only the first parameter, props, + // can be specified by users through attributes property. var paramType = getTypeAtPosition(signature, 0); - var attributesType = checkExpressionWithContextualType(node.attributes, paramType, undefined); + var attributesType = checkExpressionWithContextualType(node.attributes, paramType, /*contextualMapper*/ undefined); var argProperties = getPropertiesOfType(attributesType); for (var _i = 0, argProperties_1 = argProperties; _i < argProperties_1.length; _i++) { var arg = argProperties_1[_i]; @@ -39246,14 +45596,17 @@ var ts; return false; } } - return checkTypeRelatedTo(attributesType, paramType, relation, undefined, headMessage); + return checkTypeRelatedTo(attributesType, paramType, relation, /*errorNode*/ undefined, headMessage); } function checkApplicableSignature(node, args, signature, relation, excludeArgument, reportErrors) { if (ts.isJsxOpeningLikeElement(node)) { return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation); } var thisType = getThisTypeOfSignature(signature); - if (thisType && thisType !== voidType && node.kind !== 188) { + if (thisType && thisType !== voidType && node.kind !== 188 /* NewExpression */) { + // If the called expression is not of the form `x.f` or `x["f"]`, then sourceType = voidType + // If the signature's 'this' type is voidType, then the check is skipped -- anything is compatible. + // If the expression is a new expression, then the check is skipped. var thisArgumentNode = getThisArgumentOfCall(node); var thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType; var errorNode = reportErrors ? (thisArgumentNode || node) : undefined; @@ -39266,11 +45619,19 @@ var ts; var argCount = getEffectiveArgumentCount(node, args, signature); for (var i = 0; i < argCount; i++) { var arg = getEffectiveArgument(node, args, i); - if (arg === undefined || arg.kind !== 206) { + // If the effective argument is 'undefined', then it is an argument that is present but is synthetic. + if (arg === undefined || arg.kind !== 206 /* OmittedExpression */) { + // Check spread elements against rest type (from arity check we know spread argument corresponds to a rest parameter) var paramType = getTypeAtPosition(signature, i); + // If the effective argument type is undefined, there is no synthetic type for the argument. + // In that case, we should check the argument. var argType = getEffectiveArgumentType(node, i) || checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined); + // If one or more arguments are still excluded (as indicated by a non-null excludeArgument parameter), + // we obtain the regular type of any object literal arguments because we may not have inferred complete + // parameter types yet and therefore excess property checks may yield false positives (see #17041). var checkArgType = excludeArgument ? getRegularTypeOfObjectLiteral(argType) : argType; + // Use argument expression as error location when reporting errors var errorNode = reportErrors ? getEffectiveArgumentErrorNode(node, i, arg) : undefined; if (!checkTypeRelatedTo(checkArgType, paramType, relation, errorNode, headMessage)) { return false; @@ -39279,26 +45640,41 @@ var ts; } return true; } + /** + * Returns the this argument in calls like x.f(...) and x[f](...). Undefined otherwise. + */ function getThisArgumentOfCall(node) { - if (node.kind === 187) { + if (node.kind === 187 /* CallExpression */) { var callee = ts.skipOuterExpressions(node.expression); - if (callee.kind === 185 || callee.kind === 186) { + if (callee.kind === 185 /* PropertyAccessExpression */ || callee.kind === 186 /* ElementAccessExpression */) { return callee.expression; } } } + /** + * Returns the effective arguments for an expression that works like a function invocation. + * + * If 'node' is a CallExpression or a NewExpression, then its argument list is returned. + * If 'node' is a TaggedTemplateExpression, a new argument list is constructed from the substitution + * expressions, where the first element of the list is `undefined`. + * If 'node' is a Decorator, the argument list will be `undefined`, and its arguments and types + * will be supplied from calls to `getEffectiveArgumentCount` and `getEffectiveArgumentType`. + */ function getEffectiveCallArguments(node) { - if (node.kind === 189) { + if (node.kind === 189 /* TaggedTemplateExpression */) { var template = node.template; - var args_4 = [undefined]; - if (template.kind === 202) { + var args_4 = [undefined]; // TODO: GH#18217 + if (template.kind === 202 /* TemplateExpression */) { ts.forEach(template.templateSpans, function (span) { args_4.push(span.expression); }); } return args_4; } - else if (node.kind === 150) { + else if (node.kind === 150 /* Decorator */) { + // For a decorator, we return undefined as we will determine + // the number and types of arguments for a decorator using + // `getEffectiveArgumentCount` and `getEffectiveArgumentType` below. return undefined; } else if (ts.isJsxOpeningLikeElement(node)) { @@ -39308,22 +45684,45 @@ var ts; return node.arguments || ts.emptyArray; } } + /** + * Returns the effective argument count for a node that works like a function invocation. + * If 'node' is a Decorator, the number of arguments is derived from the decoration + * target and the signature: + * If 'node.target' is a class declaration or class expression, the effective argument + * count is 1. + * If 'node.target' is a parameter declaration, the effective argument count is 3. + * If 'node.target' is a property declaration, the effective argument count is 2. + * If 'node.target' is a method or accessor declaration, the effective argument count + * is 3, although it can be 2 if the signature only accepts two arguments, allowing + * us to match a property decorator. + * Otherwise, the argument count is the length of the 'args' array. + */ function getEffectiveArgumentCount(node, args, signature) { - if (node.kind === 150) { + if (node.kind === 150 /* Decorator */) { switch (node.parent.kind) { - case 235: - case 205: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + // A class decorator will have one argument (see `ClassDecorator` in core.d.ts) return 1; - case 152: + case 152 /* PropertyDeclaration */: + // A property declaration decorator will have two arguments (see + // `PropertyDecorator` in core.d.ts) return 2; - case 154: - case 156: - case 157: - if (languageVersion === 0) { + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + // A method or accessor declaration decorator will have two or three arguments (see + // `PropertyDecorator` and `MethodDecorator` in core.d.ts) + // If we are emitting decorators for ES3, we will only pass two arguments. + if (languageVersion === 0 /* ES3 */) { return 2; } + // If the method decorator signature only accepts a target and a key, we will only + // type check those arguments. return signature.parameters.length >= 3 ? 3 : 2; - case 149: + case 149 /* Parameter */: + // A parameter declaration decorator will have three arguments (see + // `ParameterDecorator` in core.d.ts) return 3; default: return ts.Debug.fail(); @@ -39333,53 +45732,97 @@ var ts; return args.length; } } + /** + * Returns the effective type of the first argument to a decorator. + * If 'node' is a class declaration or class expression, the effective argument type + * is the type of the static side of the class. + * If 'node' is a parameter declaration, the effective argument type is either the type + * of the static or instance side of the class for the parameter's parent method, + * depending on whether the method is declared static. + * For a constructor, the type is always the type of the static side of the class. + * If 'node' is a property, method, or accessor declaration, the effective argument + * type is the type of the static or instance side of the parent class for class + * element, depending on whether the element is declared static. + */ function getEffectiveDecoratorFirstArgumentType(node) { - if (node.kind === 235) { + // The first argument to a decorator is its `target`. + if (node.kind === 235 /* ClassDeclaration */) { + // For a class decorator, the `target` is the type of the class (e.g. the + // "static" or "constructor" side of the class) var classSymbol = getSymbolOfNode(node); return getTypeOfSymbol(classSymbol); } - if (node.kind === 149) { + if (node.kind === 149 /* Parameter */) { + // For a parameter decorator, the `target` is the parent type of the + // parameter's containing method. node = node.parent; - if (node.kind === 155) { + if (node.kind === 155 /* Constructor */) { var classSymbol = getSymbolOfNode(node); return getTypeOfSymbol(classSymbol); } } - if (node.kind === 152 || - node.kind === 154 || - node.kind === 156 || - node.kind === 157) { + if (node.kind === 152 /* PropertyDeclaration */ || + node.kind === 154 /* MethodDeclaration */ || + node.kind === 156 /* GetAccessor */ || + node.kind === 157 /* SetAccessor */) { + // For a property or method decorator, the `target` is the + // "static"-side type of the parent of the member if the member is + // declared "static"; otherwise, it is the "instance"-side type of the + // parent of the member. return getParentTypeOfClassElement(node); } ts.Debug.fail("Unsupported decorator target."); return errorType; } + /** + * Returns the effective type for the second argument to a decorator. + * If 'node' is a parameter, its effective argument type is one of the following: + * If 'node.parent' is a constructor, the effective argument type is 'any', as we + * will emit `undefined`. + * If 'node.parent' is a member with an identifier, numeric, or string literal name, + * the effective argument type will be a string literal type for the member name. + * If 'node.parent' is a computed property name, the effective argument type will + * either be a symbol type or the string type. + * If 'node' is a member with an identifier, numeric, or string literal name, the + * effective argument type will be a string literal type for the member name. + * If 'node' is a computed property name, the effective argument type will either + * be a symbol type or the string type. + * A class decorator does not have a second argument type. + */ function getEffectiveDecoratorSecondArgumentType(node) { - if (node.kind === 235) { + // The second argument to a decorator is its `propertyKey` + if (node.kind === 235 /* ClassDeclaration */) { ts.Debug.fail("Class decorators should not have a second synthetic argument."); return errorType; } - if (node.kind === 149) { + if (node.kind === 149 /* Parameter */) { node = node.parent; - if (node.kind === 155) { + if (node.kind === 155 /* Constructor */) { + // For a constructor parameter decorator, the `propertyKey` will be `undefined`. return anyType; } + // For a non-constructor parameter decorator, the `propertyKey` will be either + // a string or a symbol, based on the name of the parameter's containing method. } - if (node.kind === 152 || - node.kind === 154 || - node.kind === 156 || - node.kind === 157) { + if (node.kind === 152 /* PropertyDeclaration */ || + node.kind === 154 /* MethodDeclaration */ || + node.kind === 156 /* GetAccessor */ || + node.kind === 157 /* SetAccessor */) { + // The `propertyKey` for a property or method decorator will be a + // string literal type if the member name is an identifier, number, or string; + // otherwise, if the member name is a computed property name it will + // be either string or symbol. var element = node; var name = element.name; switch (name.kind) { - case 71: + case 71 /* Identifier */: return getLiteralType(ts.idText(name)); - case 8: - case 9: + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: return getLiteralType(name.text); - case 147: + case 147 /* ComputedPropertyName */: var nameType = checkComputedPropertyName(name); - if (isTypeAssignableToKind(nameType, 3072)) { + if (isTypeAssignableToKind(nameType, 3072 /* ESSymbolLike */)) { return nameType; } else { @@ -39393,27 +45836,42 @@ var ts; ts.Debug.fail("Unsupported decorator target."); return errorType; } + /** + * Returns the effective argument type for the third argument to a decorator. + * If 'node' is a parameter, the effective argument type is the number type. + * If 'node' is a method or accessor, the effective argument type is a + * `TypedPropertyDescriptor` instantiated with the type of the member. + * Class and property decorators do not have a third effective argument. + */ function getEffectiveDecoratorThirdArgumentType(node) { - if (node.kind === 235) { + // The third argument to a decorator is either its `descriptor` for a method decorator + // or its `parameterIndex` for a parameter decorator + if (node.kind === 235 /* ClassDeclaration */) { ts.Debug.fail("Class decorators should not have a third synthetic argument."); return errorType; } - if (node.kind === 149) { + if (node.kind === 149 /* Parameter */) { + // The `parameterIndex` for a parameter decorator is always a number return numberType; } - if (node.kind === 152) { + if (node.kind === 152 /* PropertyDeclaration */) { ts.Debug.fail("Property decorators should not have a third synthetic argument."); return errorType; } - if (node.kind === 154 || - node.kind === 156 || - node.kind === 157) { - var propertyType = getTypeOfNode(node); + if (node.kind === 154 /* MethodDeclaration */ || + node.kind === 156 /* GetAccessor */ || + node.kind === 157 /* SetAccessor */) { + // The `descriptor` for a method decorator will be a `TypedPropertyDescriptor` + // for the type of the member. + var propertyType = getTypeOfNode(node); // TODO: GH#18217 return createTypedPropertyDescriptorType(propertyType); } ts.Debug.fail("Unsupported decorator target."); return errorType; } + /** + * Returns the effective argument type for the provided argument to a decorator. + */ function getEffectiveDecoratorArgumentType(node, argIndex) { if (argIndex === 0) { return getEffectiveDecoratorFirstArgumentType(node.parent); @@ -39427,27 +45885,44 @@ var ts; ts.Debug.fail("Decorators should not have a fourth synthetic argument."); return errorType; } + /** + * Gets the effective argument type for an argument in a call expression. + */ function getEffectiveArgumentType(node, argIndex) { - if (node.kind === 150) { + // Decorators provide special arguments, a tagged template expression provides + // a special first argument, and string literals get string literal types + // unless we're reporting errors + if (node.kind === 150 /* Decorator */) { return getEffectiveDecoratorArgumentType(node, argIndex); } - else if (argIndex === 0 && node.kind === 189) { + else if (argIndex === 0 && node.kind === 189 /* TaggedTemplateExpression */) { return getGlobalTemplateStringsArrayType(); } + // This is not a synthetic argument, so we return 'undefined' + // to signal that the caller needs to check the argument. return undefined; } + /** + * Gets the effective argument expression for an argument in a call expression. + */ function getEffectiveArgument(node, args, argIndex) { - if (node.kind === 150 || - (argIndex === 0 && node.kind === 189)) { + // For a decorator or the first argument of a tagged template expression we return undefined. + if (node.kind === 150 /* Decorator */ || + (argIndex === 0 && node.kind === 189 /* TaggedTemplateExpression */)) { return undefined; } return args[argIndex]; } + /** + * Gets the error node to use when reporting errors for an effective argument. + */ function getEffectiveArgumentErrorNode(node, argIndex, arg) { - if (node.kind === 150) { + if (node.kind === 150 /* Decorator */) { + // For a decorator, we use the expression of the decorator for error reporting. return node.expression; } - else if (argIndex === 0 && node.kind === 189) { + else if (argIndex === 0 && node.kind === 189 /* TaggedTemplateExpression */) { + // For a the first argument of a tagged template expression, we use the template of the tag for error reporting. return node.template; } else { @@ -39466,27 +45941,45 @@ var ts; return ts.createDiagnosticForNodeArray(ts.getSourceFileOfNode(node), typeArguments, ts.Diagnostics.Expected_0_type_arguments_but_got_1, paramCount, typeArguments.length); } function resolveCall(node, signatures, candidatesOutArray, fallbackError) { - var isTaggedTemplate = node.kind === 189; - var isDecorator = node.kind === 150; + var isTaggedTemplate = node.kind === 189 /* TaggedTemplateExpression */; + var isDecorator = node.kind === 150 /* Decorator */; var isJsxOpeningOrSelfClosingElement = ts.isJsxOpeningLikeElement(node); var typeArguments; if (!isDecorator) { typeArguments = node.typeArguments; - if (isTaggedTemplate || isJsxOpeningOrSelfClosingElement || node.expression.kind !== 97) { + // We already perform checking on the type arguments on the class declaration itself. + if (isTaggedTemplate || isJsxOpeningOrSelfClosingElement || node.expression.kind !== 97 /* SuperKeyword */) { ts.forEach(typeArguments, checkSourceElement); } } var candidates = candidatesOutArray || []; + // reorderCandidates fills up the candidates array directly reorderCandidates(signatures, candidates); if (!candidates.length) { diagnostics.add(ts.createDiagnosticForNode(node, ts.Diagnostics.Call_target_does_not_contain_any_signatures)); return resolveErrorCall(node); } var args = getEffectiveCallArguments(node); + // The following applies to any value of 'excludeArgument[i]': + // - true: the argument at 'i' is susceptible to a one-time permanent contextual typing. + // - undefined: the argument at 'i' is *not* susceptible to permanent contextual typing. + // - false: the argument at 'i' *was* and *has been* permanently contextually typed. + // + // The idea is that we will perform type argument inference & assignability checking once + // without using the susceptible parameters that are functions, and once more for each of those + // parameters, contextually typing each as we go along. + // + // For a tagged template, then the first argument be 'undefined' if necessary + // because it represents a TemplateStringsArray. + // + // For a decorator, no arguments are susceptible to contextual typing due to the fact + // decorators are applied to a declaration by the emitter, and not to an expression. var isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters; var excludeArgument; var excludeCount = 0; if (!isDecorator && !isSingleNonGenericCandidate) { + // We do not need to call `getEffectiveArgumentCount` here as it only + // applies when calculating the number of arguments for a decorator. for (var i = isTaggedTemplate ? 1 : 0; i < args.length; i++) { if (isContextSensitive(args[i])) { if (!excludeArgument) { @@ -39497,10 +45990,43 @@ var ts; } } } + // The following variables are captured and modified by calls to chooseOverload. + // If overload resolution or type argument inference fails, we want to report the + // best error possible. The best error is one which says that an argument was not + // assignable to a parameter. This implies that everything else about the overload + // was fine. So if there is any overload that is only incorrect because of an + // argument, we will report an error on that one. + // + // function foo(s: string): void; + // function foo(n: number): void; // Report argument error on this overload + // function foo(): void; + // foo(true); + // + // If none of the overloads even made it that far, there are two possibilities. + // There was a problem with type arguments for some overload, in which case + // report an error on that. Or none of the overloads even had correct arity, + // in which case give an arity error. + // + // function foo(x: T): void; // Report type argument error + // function foo(): void; + // foo(0); + // var candidateForArgumentError; var candidateForTypeArgumentError; var result; - var signatureHelpTrailingComma = candidatesOutArray && node.kind === 187 && node.arguments.hasTrailingComma; + // If we are in signature help, a trailing comma indicates that we intend to provide another argument, + // so we will only accept overloads with arity at least 1 higher than the current number of provided arguments. + var signatureHelpTrailingComma = candidatesOutArray && node.kind === 187 /* CallExpression */ && node.arguments.hasTrailingComma; + // Section 4.12.1: + // if the candidate list contains one or more signatures for which the type of each argument + // expression is a subtype of each corresponding parameter type, the return type of the first + // of those signatures becomes the return type of the function call. + // Otherwise, the return type of the first signature in the candidate list becomes the return + // type of the function call. + // + // Whether the call is an error is determined by assignability of the arguments. The subtype pass + // is just important for choosing the best signature. So in the case where there is only one + // signature, the subtype pass is useless. So skipping it is an optimization. if (candidates.length > 1) { result = chooseOverload(candidates, subtypeRelation, signatureHelpTrailingComma); } @@ -39510,14 +46036,24 @@ var ts; if (result) { return result; } + // No signatures were applicable. Now report errors based on the last applicable signature with + // no arguments excluded from assignability checks. + // If candidate is undefined, it means that no candidates had a suitable arity. In that case, + // skip the checkApplicableSignature check. if (candidateForArgumentError) { if (isJsxOpeningOrSelfClosingElement) { + // We do not report any error here because any error will be handled in "resolveCustomJsxElementAttributesType". return candidateForArgumentError; } - checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, undefined, true); + // excludeArgument is undefined, in this case also equivalent to [undefined, undefined, ...] + // The importance of excludeArgument is to prevent us from typing function expression parameters + // in arguments too early. If possible, we'd like to only type them once we know the correct + // overload. However, this matters for the case where the call is correct. When the call is + // an error, we don't need to exclude any arguments, although it would cause no harm to do so. + checkApplicableSignature(node, args, candidateForArgumentError, assignableRelation, /*excludeArgument*/ undefined, /*reportErrors*/ true); } else if (candidateForTypeArgumentError) { - checkTypeArguments(candidateForTypeArgumentError, node.typeArguments, true, fallbackError); + checkTypeArguments(candidateForTypeArgumentError, node.typeArguments, /*reportErrors*/ true, fallbackError); } else if (typeArguments && ts.every(signatures, function (sig) { return ts.length(sig.typeParameters) !== typeArguments.length; })) { diagnostics.add(getTypeArgumentArityError(node, signatures, typeArguments)); @@ -39548,13 +46084,21 @@ var ts; else if (fallbackError) { diagnostics.add(ts.createDiagnosticForNode(node, fallbackError)); } + // No signature was applicable. We have already reported the errors for the invalid signature. + // If this is a type resolution session, e.g. Language Service, try to get better information than anySignature. + // Pick the longest signature. This way we can get a contextual type for cases like: + // declare function f(a: { xa: number; xb: number; }, b: number); + // f({ | + // Also, use explicitly-supplied type arguments if they are provided, so we can get a contextual signature in cases like: + // declare function f(k: keyof T); + // f(" if (!produceDiagnostics) { - ts.Debug.assert(candidates.length > 0); + ts.Debug.assert(candidates.length > 0); // Else would have exited above. var bestIndex = getLongestCandidateIndex(candidates, apparentArgumentCount === undefined ? args.length : apparentArgumentCount); var candidate = candidates[bestIndex]; var typeParameters = candidate.typeParameters; if (typeParameters && callLikeExpressionMayHaveTypeArguments(node) && node.typeArguments) { - var typeArguments_1 = node.typeArguments.map(getTypeOfNode); + var typeArguments_1 = node.typeArguments.map(getTypeOfNode); // TODO: GH#18217 while (typeArguments_1.length > typeParameters.length) { typeArguments_1.pop(); } @@ -39577,7 +46121,7 @@ var ts; if (!hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) { return undefined; } - if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, false)) { + if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) { candidateForArgumentError = candidate; return undefined; } @@ -39590,14 +46134,14 @@ var ts; } var candidate = void 0; var inferenceContext = originalCandidate.typeParameters ? - createInferenceContext(originalCandidate.typeParameters, originalCandidate, ts.isInJavaScriptFile(node) ? 4 : 0) : + createInferenceContext(originalCandidate.typeParameters, originalCandidate, /*flags*/ ts.isInJavaScriptFile(node) ? 4 /* AnyDefault */ : 0 /* None */) : undefined; while (true) { candidate = originalCandidate; if (candidate.typeParameters) { var typeArgumentTypes = void 0; if (typeArguments) { - var typeArgumentResult = checkTypeArguments(candidate, typeArguments, false); + var typeArgumentResult = checkTypeArguments(candidate, typeArguments, /*reportErrors*/ false); if (typeArgumentResult) { typeArgumentTypes = typeArgumentResult; } @@ -39612,7 +46156,7 @@ var ts; var isJavascript = ts.isInJavaScriptFile(candidate.declaration); candidate = getSignatureInstantiation(candidate, typeArgumentTypes, isJavascript); } - if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, false)) { + if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) { candidateForArgumentError = candidate; break; } @@ -39622,7 +46166,7 @@ var ts; } excludeCount--; if (excludeCount > 0) { - excludeArgument[excludeArgument.indexOf(true)] = false; + excludeArgument[excludeArgument.indexOf(/*value*/ true)] = false; } else { excludeArgument = undefined; @@ -39648,13 +46192,15 @@ var ts; return maxParamsIndex; } function resolveCallExpression(node, candidatesOutArray) { - if (node.expression.kind === 97) { + if (node.expression.kind === 97 /* SuperKeyword */) { var superType = checkSuperExpression(node.expression); if (isTypeAny(superType)) { - ts.forEach(node.arguments, checkExpresionNoReturn); + ts.forEach(node.arguments, checkExpresionNoReturn); // Still visit arguments so they get marked for visibility, etc return anySignature; } if (superType !== errorType) { + // In super call, the candidate signatures are the matching arity signatures of the base constructor function instantiated + // with the type arguments specified in the extends clause. var baseTypeNode = ts.getClassExtendsHeritageClauseElement(ts.getContainingClass(node)); if (baseTypeNode) { var baseConstructors = getInstantiatedConstructorsForTypeArguments(superType, baseTypeNode.typeArguments, baseTypeNode); @@ -39669,33 +46215,52 @@ var ts; } var apparentType = getApparentType(funcType); if (apparentType === errorType) { + // Another error has already been reported return resolveErrorCall(node); } - var callSignatures = getSignaturesOfType(apparentType, 0); - var constructSignatures = getSignaturesOfType(apparentType, 1); + // Technically, this signatures list may be incomplete. We are taking the apparent type, + // but we are not including call signatures that may have been added to the Object or + // Function interface, since they have none by default. This is a bit of a leap of faith + // that the user will not add any. + var callSignatures = getSignaturesOfType(apparentType, 0 /* Call */); + var constructSignatures = getSignaturesOfType(apparentType, 1 /* Construct */); + // TS 1.0 Spec: 4.12 + // In an untyped function call no TypeArgs are permitted, Args can be any argument list, no contextual + // types are provided for the argument expressions, and the result is always of type Any. if (isUntypedFunctionCall(funcType, apparentType, callSignatures.length, constructSignatures.length)) { + // The unknownType indicates that an error already occurred (and was reported). No + // need to report another error in this case. if (funcType !== errorType && node.typeArguments) { error(node, ts.Diagnostics.Untyped_function_calls_may_not_accept_type_arguments); } return resolveUntypedCall(node); } + // If FuncExpr's apparent type(section 3.8.1) is a function type, the call is a typed function call. + // TypeScript employs overload resolution in typed function calls in order to support functions + // with multiple call signatures. if (!callSignatures.length) { if (constructSignatures.length) { error(node, ts.Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); } else { - invocationError(node, apparentType, 0); + invocationError(node, apparentType, 0 /* Call */); } return resolveErrorCall(node); } return resolveCall(node, callSignatures, candidatesOutArray); } + /** + * TS 1.0 spec: 4.12 + * If FuncExpr is of type Any, or of an object type that has no call or construct signatures + * but is a subtype of the Function interface, the call is an untyped function call. + */ function isUntypedFunctionCall(funcType, apparentFuncType, numCallSignatures, numConstructSignatures) { - return isTypeAny(funcType) || isTypeAny(apparentFuncType) && funcType.flags & 65536 || - !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & (262144 | 32768)) && isTypeAssignableTo(funcType, globalFunctionType); + // We exclude union types because we may have a union of function types that happen to have no common signatures. + return isTypeAny(funcType) || isTypeAny(apparentFuncType) && funcType.flags & 65536 /* TypeParameter */ || + !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & (262144 /* Union */ | 32768 /* Never */)) && isTypeAssignableTo(funcType, globalFunctionType); } function resolveNewExpression(node, candidatesOutArray) { - if (node.arguments && languageVersion < 1) { + if (node.arguments && languageVersion < 1 /* ES5 */) { var spreadIndex = getSpreadArgumentIndex(node.arguments); if (spreadIndex >= 0) { error(node.arguments[spreadIndex], ts.Diagnostics.Spread_operator_in_new_expressions_is_only_available_when_targeting_ECMAScript_5_and_higher); @@ -39705,29 +46270,50 @@ var ts; if (expressionType === silentNeverType) { return silentNeverSignature; } + // If expressionType's apparent type(section 3.8.1) is an object type with one or + // more construct signatures, the expression is processed in the same manner as a + // function call, but using the construct signatures as the initial set of candidate + // signatures for overload resolution. The result type of the function call becomes + // the result type of the operation. expressionType = getApparentType(expressionType); if (expressionType === errorType) { + // Another error has already been reported return resolveErrorCall(node); } + // TS 1.0 spec: 4.11 + // If expressionType is of type Any, Args can be any argument + // list and the result of the operation is of type Any. if (isTypeAny(expressionType)) { if (node.typeArguments) { error(node, ts.Diagnostics.Untyped_function_calls_may_not_accept_type_arguments); } return resolveUntypedCall(node); } - var constructSignatures = getSignaturesOfType(expressionType, 1); + // Technically, this signatures list may be incomplete. We are taking the apparent type, + // but we are not including construct signatures that may have been added to the Object or + // Function interface, since they have none by default. This is a bit of a leap of faith + // that the user will not add any. + var constructSignatures = getSignaturesOfType(expressionType, 1 /* Construct */); if (constructSignatures.length) { if (!isConstructorAccessible(node, constructSignatures[0])) { return resolveErrorCall(node); } + // If the expression is a class of abstract type, then it cannot be instantiated. + // Note, only class declarations can be declared abstract. + // In the case of a merged class-module or class-interface declaration, + // only the class declaration node will have the Abstract flag set. var valueDecl = expressionType.symbol && ts.getClassLikeDeclarationOfSymbol(expressionType.symbol); - if (valueDecl && ts.hasModifier(valueDecl, 128)) { + if (valueDecl && ts.hasModifier(valueDecl, 128 /* Abstract */)) { error(node, ts.Diagnostics.Cannot_create_an_instance_of_an_abstract_class); return resolveErrorCall(node); } return resolveCall(node, constructSignatures, candidatesOutArray); } - var callSignatures = getSignaturesOfType(expressionType, 0); + // If expressionType's apparent type is an object type with no construct signatures but + // one or more call signatures, the expression is processed as a function call. A compile-time + // error occurs if the result of the function call is not Void. The type of the result of the + // operation is Any. It is an error to have a Void this type. + var callSignatures = getSignaturesOfType(expressionType, 0 /* Call */); if (callSignatures.length) { var signature = resolveCall(node, callSignatures, candidatesOutArray); if (!isJavaScriptConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) { @@ -39738,7 +46324,7 @@ var ts; } return signature; } - invocationError(node, expressionType, 1); + invocationError(node, expressionType, 1 /* Construct */); return resolveErrorCall(node); } function isConstructorAccessible(node, signature) { @@ -39746,12 +46332,14 @@ var ts; return true; } var declaration = signature.declaration; - var modifiers = ts.getSelectedModifierFlags(declaration, 24); + var modifiers = ts.getSelectedModifierFlags(declaration, 24 /* NonPublicAccessibilityModifier */); + // Public constructor is accessible. if (!modifiers) { return true; } var declaringClassDeclaration = ts.getClassLikeDeclarationOfSymbol(declaration.parent.symbol); var declaringClass = getDeclaredTypeOfSymbol(declaration.parent.symbol); + // A private or protected constructor can only be instantiated within its own class (or a subclass, for protected) if (!isNodeWithinClass(node, declaringClassDeclaration)) { var containingClass = ts.getContainingClass(node); if (containingClass) { @@ -39759,17 +46347,17 @@ var ts; var baseTypes = getBaseTypes(containingType); while (baseTypes.length) { var baseType = baseTypes[0]; - if (modifiers & 16 && + if (modifiers & 16 /* Protected */ && baseType.symbol === declaration.parent.symbol) { return true; } baseTypes = getBaseTypes(baseType); } } - if (modifiers & 8) { + if (modifiers & 8 /* Private */) { error(node, ts.Diagnostics.Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration, typeToString(declaringClass)); } - if (modifiers & 16) { + if (modifiers & 16 /* Protected */) { error(node, ts.Diagnostics.Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration, typeToString(declaringClass)); } return false; @@ -39777,7 +46365,7 @@ var ts; return true; } function invocationError(node, apparentType, kind) { - invocationErrorRecovery(apparentType, kind, error(node, kind === 0 + invocationErrorRecovery(apparentType, kind, error(node, kind === 0 /* Call */ ? ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures : ts.Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature, typeToString(apparentType))); } @@ -39786,6 +46374,8 @@ var ts; return; } var importNode = getSymbolLinks(apparentType.symbol).originatingImport; + // Create a diagnostic on the originating import if possible onto which we can attach a quickfix + // An import call expression cannot be rewritten into another form to correct the error - the only solution is to use `.default` at the use-site if (importNode && !ts.isImportCall(importNode)) { var sigs = getSignaturesOfType(getTypeOfSymbol(getSymbolLinks(apparentType.symbol).target), kind); if (!sigs || !sigs.length) @@ -39798,73 +46388,95 @@ var ts; var tagType = checkExpression(node.tag); var apparentType = getApparentType(tagType); if (apparentType === errorType) { + // Another error has already been reported return resolveErrorCall(node); } - var callSignatures = getSignaturesOfType(apparentType, 0); - var constructSignatures = getSignaturesOfType(apparentType, 1); + var callSignatures = getSignaturesOfType(apparentType, 0 /* Call */); + var constructSignatures = getSignaturesOfType(apparentType, 1 /* Construct */); if (isUntypedFunctionCall(tagType, apparentType, callSignatures.length, constructSignatures.length)) { return resolveUntypedCall(node); } if (!callSignatures.length) { - invocationError(node, apparentType, 0); + invocationError(node, apparentType, 0 /* Call */); return resolveErrorCall(node); } return resolveCall(node, callSignatures, candidatesOutArray); } + /** + * Gets the localized diagnostic head message to use for errors when resolving a decorator as a call expression. + */ function getDiagnosticHeadMessageForDecoratorResolution(node) { switch (node.parent.kind) { - case 235: - case 205: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: return ts.Diagnostics.Unable_to_resolve_signature_of_class_decorator_when_called_as_an_expression; - case 149: + case 149 /* Parameter */: return ts.Diagnostics.Unable_to_resolve_signature_of_parameter_decorator_when_called_as_an_expression; - case 152: + case 152 /* PropertyDeclaration */: return ts.Diagnostics.Unable_to_resolve_signature_of_property_decorator_when_called_as_an_expression; - case 154: - case 156: - case 157: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return ts.Diagnostics.Unable_to_resolve_signature_of_method_decorator_when_called_as_an_expression; default: return ts.Debug.fail(); } } + /** + * Resolves a decorator as if it were a call expression. + */ function resolveDecorator(node, candidatesOutArray) { var funcType = checkExpression(node.expression); var apparentType = getApparentType(funcType); if (apparentType === errorType) { return resolveErrorCall(node); } - var callSignatures = getSignaturesOfType(apparentType, 0); - var constructSignatures = getSignaturesOfType(apparentType, 1); + var callSignatures = getSignaturesOfType(apparentType, 0 /* Call */); + var constructSignatures = getSignaturesOfType(apparentType, 1 /* Construct */); if (isUntypedFunctionCall(funcType, apparentType, callSignatures.length, constructSignatures.length)) { return resolveUntypedCall(node); } if (isPotentiallyUncalledDecorator(node, callSignatures)) { - var nodeStr = ts.getTextOfNode(node.expression, false); + var nodeStr = ts.getTextOfNode(node.expression, /*includeTrivia*/ false); error(node, ts.Diagnostics._0_accepts_too_few_arguments_to_be_used_as_a_decorator_here_Did_you_mean_to_call_it_first_and_write_0, nodeStr); return resolveErrorCall(node); } var headMessage = getDiagnosticHeadMessageForDecoratorResolution(node); if (!callSignatures.length) { - var errorInfo = ts.chainDiagnosticMessages(undefined, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType)); + var errorInfo = ts.chainDiagnosticMessages(/*details*/ undefined, ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType)); errorInfo = ts.chainDiagnosticMessages(errorInfo, headMessage); var diag = ts.createDiagnosticForNodeFromMessageChain(node, errorInfo); diagnostics.add(diag); - invocationErrorRecovery(apparentType, 0, diag); + invocationErrorRecovery(apparentType, 0 /* Call */, diag); return resolveErrorCall(node); } return resolveCall(node, callSignatures, candidatesOutArray, headMessage); } + /** + * Sometimes, we have a decorator that could accept zero arguments, + * but is receiving too many arguments as part of the decorator invocation. + * In those cases, a user may have meant to *call* the expression before using it as a decorator. + */ function isPotentiallyUncalledDecorator(decorator, signatures) { return signatures.length && ts.every(signatures, function (signature) { return signature.minArgumentCount === 0 && !signature.hasRestParameter && - signature.parameters.length < getEffectiveArgumentCount(decorator, undefined, signature); + signature.parameters.length < getEffectiveArgumentCount(decorator, /*args*/ undefined, signature); }); } + /** + * This function is similar to getResolvedSignature but is exclusively for trying to resolve JSX stateless-function component. + * The main reason we have to use this function instead of getResolvedSignature because, the caller of this function will already check the type of openingLikeElement's tagName + * and pass the type as elementType. The elementType can not be a union (as such case should be handled by the caller of this function) + * Note: at this point, we are still not sure whether the opening-like element is a stateless function component or not. + * @param openingLikeElement an opening-like JSX element to try to resolve as JSX stateless function + * @param elementType an element type of the opneing-like element by checking opening-like element's tagname. + * @param candidatesOutArray an array of signature to be filled in by the function. It is passed by signature help in the language service; + * the function will fill it up with appropriate candidate signatures + */ function getResolvedJsxStatelessFunctionSignature(openingLikeElement, elementType, candidatesOutArray) { - ts.Debug.assert(!(elementType.flags & 262144)); - var callSignatures = elementType && getSignaturesOfType(elementType, 0); + ts.Debug.assert(!(elementType.flags & 262144 /* Union */)); + var callSignatures = elementType && getSignaturesOfType(elementType, 0 /* Call */); if (callSignatures && callSignatures.length > 0) { return resolveCall(openingLikeElement, callSignatures, candidatesOutArray); } @@ -39872,16 +46484,17 @@ var ts; } function resolveSignature(node, candidatesOutArray) { switch (node.kind) { - case 187: + case 187 /* CallExpression */: return resolveCallExpression(node, candidatesOutArray); - case 188: + case 188 /* NewExpression */: return resolveNewExpression(node, candidatesOutArray); - case 189: + case 189 /* TaggedTemplateExpression */: return resolveTaggedTemplateExpression(node, candidatesOutArray); - case 150: + case 150 /* Decorator */: return resolveDecorator(node, candidatesOutArray); - case 257: - case 256: + case 257 /* JsxOpeningElement */: + case 256 /* JsxSelfClosingElement */: + // This code-path is called by language service var exprTypes = checkExpression(node.tagName); return forEachType(exprTypes, function (exprType) { var sfcResult = getResolvedJsxStatelessFunctionSignature(node, exprType, candidatesOutArray); @@ -39897,21 +46510,41 @@ var ts; } throw ts.Debug.assertNever(node, "Branch in 'resolveSignature' should be unreachable."); } + /** + * Resolve a signature of a given call-like expression. + * @param node a call-like expression to try resolve a signature for + * @param candidatesOutArray an array of signature to be filled in by the function. It is passed by signature help in the language service; + * the function will fill it up with appropriate candidate signatures + * @return a signature of the call-like expression or undefined if one can't be found + */ function getResolvedSignature(node, candidatesOutArray) { var links = getNodeLinks(node); + // If getResolvedSignature has already been called, we will have cached the resolvedSignature. + // However, it is possible that either candidatesOutArray was not passed in the first time, + // or that a different candidatesOutArray was passed in. Therefore, we need to redo the work + // to correctly fill the candidatesOutArray. var cached = links.resolvedSignature; if (cached && cached !== resolvingSignature && !candidatesOutArray) { return cached; } links.resolvedSignature = resolvingSignature; var result = resolveSignature(node, candidatesOutArray); + // If signature resolution originated in control flow type analysis (for example to compute the + // assigned type in a flow assignment) we don't cache the result as it may be based on temporary + // types from the control flow analysis. links.resolvedSignature = flowLoopStart === flowLoopCount ? result : cached; return result; } + /** + * Indicates whether a declaration can be treated as a constructor in a JavaScript + * file. + */ function isJavaScriptConstructor(node) { if (node && ts.isInJavaScriptFile(node)) { + // If the node has a @class tag, treat it like a constructor. if (ts.getJSDocClassTag(node)) return true; + // If the symbol of the node has members, treat it like a constructor. var symbol = ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) ? getSymbolOfNode(node) : ts.isVariableDeclaration(node) && node.initializer && ts.isFunctionExpression(node.initializer) ? getSymbolOfNode(node.initializer) : undefined; @@ -39950,10 +46583,10 @@ var ts; return false; } var parent = node.parent; - while (parent && parent.kind === 185) { + while (parent && parent.kind === 185 /* PropertyAccessExpression */) { parent = parent.parent; } - if (parent && ts.isBinaryExpression(parent) && ts.isPrototypeAccess(parent.left) && parent.operatorToken.kind === 58) { + if (parent && ts.isBinaryExpression(parent) && ts.isPrototypeAccess(parent.left) && parent.operatorToken.kind === 58 /* EqualsToken */) { var right = ts.getInitializerOfBinaryExpression(parent); return ts.isObjectLiteralExpression(right) && right; } @@ -39961,31 +46594,41 @@ var ts; function getInferredClassType(symbol) { var links = getSymbolLinks(symbol); if (!links.inferredClassType) { - links.inferredClassType = createAnonymousType(symbol, getMembersOfSymbol(symbol) || emptySymbols, ts.emptyArray, ts.emptyArray, undefined, undefined); + links.inferredClassType = createAnonymousType(symbol, getMembersOfSymbol(symbol) || emptySymbols, ts.emptyArray, ts.emptyArray, /*stringIndexType*/ undefined, /*numberIndexType*/ undefined); } return links.inferredClassType; } function isInferredClassType(type) { return type.symbol - && ts.getObjectFlags(type) & 16 + && ts.getObjectFlags(type) & 16 /* Anonymous */ && getSymbolLinks(type.symbol).inferredClassType === type; } + /** + * Syntactically and semantically checks a call or new expression. + * @param node The call/new expression to be checked. + * @returns On success, the expression's signature's return type. On failure, anyType. + */ function checkCallExpression(node) { if (!checkGrammarTypeArguments(node, node.typeArguments)) checkGrammarArguments(node.arguments); var signature = getResolvedSignature(node); - if (node.expression.kind === 97) { + if (node.expression.kind === 97 /* SuperKeyword */) { return voidType; } - if (node.kind === 188) { + if (node.kind === 188 /* NewExpression */) { var declaration = signature.declaration; if (declaration && - declaration.kind !== 155 && - declaration.kind !== 159 && - declaration.kind !== 164 && + declaration.kind !== 155 /* Constructor */ && + declaration.kind !== 159 /* ConstructSignature */ && + declaration.kind !== 164 /* ConstructorType */ && !ts.isJSDocConstructSignature(declaration)) { + // When resolved signature is a call signature (and not a construct signature) the result type is any, unless + // the declaring function had members created through 'x.prototype.y = expr' or 'this.y = expr' psuedodeclarations + // in a JS file + // Note:JS inferred classes might come from a variable declaration instead of a function declaration. + // In this case, using getResolvedSymbol directly is required to avoid losing the members from the declaration. var funcSymbol = checkExpression(node.expression).symbol; - if (!funcSymbol && node.expression.kind === 71) { + if (!funcSymbol && node.expression.kind === 71 /* Identifier */) { funcSymbol = getResolvedSymbol(node.expression); } var type = funcSymbol && getJavaScriptClassType(funcSymbol); @@ -39998,11 +46641,14 @@ var ts; return anyType; } } + // In JavaScript files, calls to any identifier 'require' are treated as external module imports if (ts.isInJavaScriptFile(node) && isCommonJsRequire(node)) { return resolveExternalModuleTypeByLiteral(node.arguments[0]); } var returnType = getReturnTypeOfSignature(signature); - if (returnType.flags & 3072 && isSymbolOrSymbolForCall(node)) { + // Treat any call to the global 'Symbol' function that is part of a const variable or readonly property + // as a fresh unique symbol literal type. + if (returnType.flags & 3072 /* ESSymbolLike */ && isSymbolOrSymbolForCall(node)) { return getESSymbolLikeTypeForNode(ts.walkUpParenthesizedExpressions(node.parent)); } var jsAssignmentType; @@ -40027,13 +46673,15 @@ var ts; if (!ts.isIdentifier(left) || left.escapedText !== "Symbol") { return false; } - var globalESSymbol = getGlobalESSymbolConstructorSymbol(false); + // make sure `Symbol` is the global symbol + var globalESSymbol = getGlobalESSymbolConstructorSymbol(/*reportErrors*/ false); if (!globalESSymbol) { return false; } - return globalESSymbol === resolveName(left, "Symbol", 67216319, undefined, undefined, false); + return globalESSymbol === resolveName(left, "Symbol", 67216319 /* Value */, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); } function checkImportCallExpression(node) { + // Check grammar of dynamic import if (!checkGrammarArguments(node.arguments)) checkGrammarImportCallExpression(node); if (node.arguments.length === 0) { @@ -40041,15 +46689,17 @@ var ts; } var specifier = node.arguments[0]; var specifierType = checkExpressionCached(specifier); + // Even though multiple arugments is grammatically incorrect, type-check extra arguments for completion for (var i = 1; i < node.arguments.length; ++i) { checkExpressionCached(node.arguments[i]); } - if (specifierType.flags & 8192 || specifierType.flags & 16384 || !isTypeAssignableTo(specifierType, stringType)) { + if (specifierType.flags & 8192 /* Undefined */ || specifierType.flags & 16384 /* Null */ || !isTypeAssignableTo(specifierType, stringType)) { error(specifier, ts.Diagnostics.Dynamic_import_s_specifier_must_be_of_type_string_but_here_has_type_0, typeToString(specifierType)); } + // resolveExternalModuleName will return undefined if the moduleReferenceExpression is not a string literal var moduleSymbol = resolveExternalModuleName(node, specifier); if (moduleSymbol) { - var esModuleSymbol = resolveESModuleSymbol(moduleSymbol, specifier, true); + var esModuleSymbol = resolveESModuleSymbol(moduleSymbol, specifier, /*dontRecursivelyResolve*/ true); if (esModuleSymbol) { return createPromiseReturnType(node, getTypeWithSyntheticDefaultImportType(getTypeOfSymbol(esModuleSymbol), esModuleSymbol, moduleSymbol)); } @@ -40061,16 +46711,16 @@ var ts; var synthType = type; if (!synthType.syntheticType) { var file = ts.find(originalSymbol.declarations, ts.isSourceFile); - var hasSyntheticDefault = canHaveSyntheticDefault(file, originalSymbol, false); + var hasSyntheticDefault = canHaveSyntheticDefault(file, originalSymbol, /*dontResolveAlias*/ false); if (hasSyntheticDefault) { var memberTable = ts.createSymbolTable(); - var newSymbol = createSymbol(2097152, "default"); + var newSymbol = createSymbol(2097152 /* Alias */, "default" /* Default */); newSymbol.target = resolveSymbol(symbol); - memberTable.set("default", newSymbol); - var anonymousSymbol = createSymbol(2048, "__type"); - var defaultContainingObject = createAnonymousType(anonymousSymbol, memberTable, ts.emptyArray, ts.emptyArray, undefined, undefined); + memberTable.set("default" /* Default */, newSymbol); + var anonymousSymbol = createSymbol(2048 /* TypeLiteral */, "__type" /* Type */); + var defaultContainingObject = createAnonymousType(anonymousSymbol, memberTable, ts.emptyArray, ts.emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined); anonymousSymbol.type = defaultContainingObject; - synthType.syntheticType = isValidSpreadType(type) ? getSpreadType(type, defaultContainingObject, anonymousSymbol, 0, 0) : defaultContainingObject; + synthType.syntheticType = isValidSpreadType(type) ? getSpreadType(type, defaultContainingObject, anonymousSymbol, /*typeFLags*/ 0, /*objectFlags*/ 0) : defaultContainingObject; } else { synthType.syntheticType = type; @@ -40081,33 +46731,36 @@ var ts; return type; } function isCommonJsRequire(node) { - if (!ts.isRequireCall(node, true)) { + if (!ts.isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true)) { return false; } + // Make sure require is not a local function if (!ts.isIdentifier(node.expression)) return ts.Debug.fail(); - var resolvedRequire = resolveName(node.expression, node.expression.escapedText, 67216319, undefined, undefined, true); + var resolvedRequire = resolveName(node.expression, node.expression.escapedText, 67216319 /* Value */, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); // TODO: GH#18217 if (resolvedRequire === requireSymbol) { return true; } - if (resolvedRequire.flags & 2097152) { + // project includes symbol named 'require' - make sure that it is ambient and local non-alias + if (resolvedRequire.flags & 2097152 /* Alias */) { return false; } - var targetDeclarationKind = resolvedRequire.flags & 16 - ? 234 - : resolvedRequire.flags & 3 - ? 232 - : 0; - if (targetDeclarationKind !== 0) { + var targetDeclarationKind = resolvedRequire.flags & 16 /* Function */ + ? 234 /* FunctionDeclaration */ + : resolvedRequire.flags & 3 /* Variable */ + ? 232 /* VariableDeclaration */ + : 0 /* Unknown */; + if (targetDeclarationKind !== 0 /* Unknown */) { var decl = ts.getDeclarationOfKind(resolvedRequire, targetDeclarationKind); - return !!decl && !!(decl.flags & 4194304); + // function/variable declaration should be ambient + return !!decl && !!(decl.flags & 4194304 /* Ambient */); } return false; } function checkTaggedTemplateExpression(node) { checkGrammarTypeArguments(node, node.typeArguments); - if (languageVersion < 2) { - checkExternalEmitHelpers(node, 65536); + if (languageVersion < 2 /* ES2015 */) { + checkExternalEmitHelpers(node, 65536 /* MakeTemplateObject */); } return getReturnTypeOfSignature(getResolvedSignature(node)); } @@ -40131,10 +46784,10 @@ var ts; } function checkMetaProperty(node) { checkGrammarMetaProperty(node); - if (node.keywordToken === 94) { + if (node.keywordToken === 94 /* NewKeyword */) { return checkNewTargetMetaProperty(node); } - if (node.keywordToken === 91) { + if (node.keywordToken === 91 /* ImportKeyword */) { return checkImportMetaProperty(node); } return ts.Debug.assertNever(node.keywordToken); @@ -40145,7 +46798,7 @@ var ts; error(node, ts.Diagnostics.Meta_property_0_is_only_allowed_in_the_body_of_a_function_declaration_function_expression_or_constructor, "new.target"); return errorType; } - else if (container.kind === 155) { + else if (container.kind === 155 /* Constructor */) { var symbol = getSymbolOfNode(container.parent); return getTypeOfSymbol(symbol); } @@ -40155,11 +46808,11 @@ var ts; } } function checkImportMetaProperty(node) { - if (languageVersion < 6 || moduleKind < ts.ModuleKind.ESNext) { + if (languageVersion < 6 /* ESNext */ || moduleKind < ts.ModuleKind.ESNext) { error(node, ts.Diagnostics.The_import_meta_meta_property_is_only_allowed_using_ESNext_for_the_target_and_module_compiler_options); } var file = ts.getSourceFileOfNode(node); - ts.Debug.assert(!!(file.flags & 1048576), "Containing file is missing import meta node flag."); + ts.Debug.assert(!!(file.flags & 1048576 /* PossiblyContainsImportMeta */), "Containing file is missing import meta node flag."); ts.Debug.assert(!!file.externalModuleIndicator, "Containing file should be a module."); return node.name.escapedText === "meta" ? getGlobalImportMetaType() : errorType; } @@ -40202,7 +46855,7 @@ var ts; var parameter = signature.thisParameter; if (!parameter || parameter.valueDeclaration && !parameter.valueDeclaration.type) { if (!parameter) { - signature.thisParameter = createSymbolWithType(context.thisParameter, undefined); + signature.thisParameter = createSymbolWithType(context.thisParameter, /*type*/ undefined); } assignTypeToParameterAndFixTypeParameters(signature.thisParameter, getTypeOfSymbol(context.thisParameter)); } @@ -40216,6 +46869,7 @@ var ts; } } if (signature.hasRestParameter && isRestParameterIndex(context, signature.parameters.length - 1)) { + // parameter might be a transient symbol generated by use of `arguments` in the function body. var parameter = ts.last(signature.parameters); if (isTransientSymbol(parameter) || !ts.getEffectiveTypeAnnotationNode(parameter.valueDeclaration)) { var contextualParameterType = getTypeOfSymbol(ts.last(context.parameters)); @@ -40223,11 +46877,13 @@ var ts; } } } + // When contextual typing assigns a type to a parameter that contains a binding pattern, we also need to push + // the destructured type into the contained binding elements. function assignBindingElementTypes(pattern) { for (var _i = 0, _a = pattern.elements; _i < _a.length; _i++) { var element = _a[_i]; if (!ts.isOmittedExpression(element)) { - if (element.name.kind === 71) { + if (element.name.kind === 71 /* Identifier */) { getSymbolLinks(getSymbolOfNode(element)).type = getTypeForBindingElement(element); } else { @@ -40241,7 +46897,8 @@ var ts; if (!links.type) { links.type = contextualType; var decl = parameter.valueDeclaration; - if (decl.name.kind !== 71) { + if (decl.name.kind !== 71 /* Identifier */) { + // if inference didn't come up with anything but {}, fall back to the binding pattern if present. if (links.type === emptyObjectType) { links.type = getTypeFromBindingPattern(decl.name); } @@ -40250,8 +46907,10 @@ var ts; } } function createPromiseType(promisedType) { - var globalPromiseType = getGlobalPromiseType(true); + // creates a `Promise` type where `T` is the promisedType argument + var globalPromiseType = getGlobalPromiseType(/*reportErrors*/ true); if (globalPromiseType !== emptyGenericType) { + // if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type promisedType = getAwaitedType(promisedType) || emptyObjectType; return createTypeReference(globalPromiseType, [promisedType]); } @@ -40265,7 +46924,7 @@ var ts; ts.Diagnostics.An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option); return errorType; } - else if (!getGlobalPromiseConstructorSymbol(true)) { + else if (!getGlobalPromiseConstructorSymbol(/*reportErrors*/ true)) { error(func, ts.isImportCall(func) ? ts.Diagnostics.A_dynamic_import_call_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option : ts.Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option); @@ -40278,20 +46937,24 @@ var ts; } var functionFlags = ts.getFunctionFlags(func); var type; - if (func.body.kind !== 213) { + if (func.body.kind !== 213 /* Block */) { type = checkExpressionCached(func.body, checkMode); - if (functionFlags & 2) { - type = checkAwaitedType(type, func, ts.Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); + if (functionFlags & 2 /* Async */) { + // From within an async function you can return either a non-promise value or a promise. Any + // Promise/A+ compatible implementation will always assimilate any foreign promise, so the + // return type of the body should be unwrapped to its awaited type, which we will wrap in + // the native Promise type later in this function. + type = checkAwaitedType(type, /*errorNode*/ func, ts.Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); } } else { var types = checkAndAggregateReturnExpressionTypes(func, checkMode); - if (functionFlags & 1) { + if (functionFlags & 1 /* Generator */) { // Generator or AsyncGenerator function types = ts.concatenate(checkAndAggregateYieldOperandTypes(func, checkMode), types); if (!types || types.length === 0) { - var iterableIteratorAny = functionFlags & 2 - ? createAsyncIterableIteratorType(anyType) - : createIterableIteratorType(anyType); + var iterableIteratorAny = functionFlags & 2 /* Async */ + ? createAsyncIterableIteratorType(anyType) // AsyncGenerator function + : createIterableIteratorType(anyType); // Generator function if (noImplicitAny) { error(func.asteriskToken, ts.Diagnostics.Generator_implicitly_has_type_0_because_it_does_not_yield_any_values_Consider_supplying_a_return_type, typeToString(iterableIteratorAny)); } @@ -40300,17 +46963,20 @@ var ts; } else { if (!types) { - return functionFlags & 2 - ? createPromiseReturnType(func, neverType) - : neverType; + // For an async function, the return type will not be never, but rather a Promise for never. + return functionFlags & 2 /* Async */ + ? createPromiseReturnType(func, neverType) // Async function + : neverType; // Normal function } if (types.length === 0) { - return functionFlags & 2 - ? createPromiseReturnType(func, voidType) - : voidType; + // For an async function, the return type will not be void, but rather a Promise for void. + return functionFlags & 2 /* Async */ + ? createPromiseReturnType(func, voidType) // Async function + : voidType; // Normal function } } - type = getUnionType(types, 2); + // Return a union of the return expression types. + type = getUnionType(types, 2 /* Subtype */); } var contextualSignature = getContextualSignatureForFunctionLikeDeclaration(func); if (!contextualSignature) { @@ -40321,14 +46987,14 @@ var ts; contextualSignature === getSignatureFromDeclaration(func) ? type : getReturnTypeOfSignature(contextualSignature); if (contextualType) { - switch (functionFlags & 3) { - case 3: - contextualType = getIteratedTypeOfGenerator(contextualType, true); + switch (functionFlags & 3 /* AsyncGenerator */) { + case 3 /* AsyncGenerator */: + contextualType = getIteratedTypeOfGenerator(contextualType, /*isAsyncGenerator*/ true); break; - case 1: - contextualType = getIteratedTypeOfGenerator(contextualType, false); + case 1 /* Generator */: + contextualType = getIteratedTypeOfGenerator(contextualType, /*isAsyncGenerator*/ false); break; - case 2: + case 2 /* Async */: contextualType = getPromisedTypeOfPromise(contextualType); break; } @@ -40336,12 +47002,15 @@ var ts; type = getWidenedLiteralLikeTypeForContextualType(type, contextualType); } var widenedType = getWidenedType(type); - switch (functionFlags & 3) { - case 3: + switch (functionFlags & 3 /* AsyncGenerator */) { + case 3 /* AsyncGenerator */: return createAsyncIterableIteratorType(widenedType); - case 1: + case 1 /* Generator */: return createIterableIteratorType(widenedType); - case 2: + case 2 /* Async */: + // From within an async function you can return either a non-promise value or a promise. Any + // Promise/A+ compatible implementation will always assimilate any foreign promise, so the + // return type of the body is awaited type of the body, wrapped in a native Promise type. return createPromiseType(widenedType); default: return widenedType; @@ -40349,7 +47018,7 @@ var ts; } function checkAndAggregateYieldOperandTypes(func, checkMode) { var aggregatedTypes = []; - var isAsync = (ts.getFunctionFlags(func) & 2) !== 0; + var isAsync = (ts.getFunctionFlags(func) & 2 /* Async */) !== 0; ts.forEachYieldExpression(func.body, function (yieldExpression) { ts.pushIfUnique(aggregatedTypes, getYieldedTypeOfYieldExpression(yieldExpression, isAsync, checkMode)); }); @@ -40358,7 +47027,8 @@ var ts; function getYieldedTypeOfYieldExpression(node, isAsync, checkMode) { var errorNode = node.expression || node; var expressionType = node.expression ? checkExpressionCached(node.expression, checkMode) : undefinedWideningType; - var yieldedType = node.asteriskToken ? checkIteratedTypeOrElementType(expressionType, errorNode, false, isAsync) : expressionType; + // A `yield*` expression effectively yields everything that its operand yields + var yieldedType = node.asteriskToken ? checkIteratedTypeOrElementType(expressionType, errorNode, /*allowStringInput*/ false, isAsync) : expressionType; return !isAsync ? yieldedType : getAwaitedType(yieldedType, errorNode, node.asteriskToken ? ts.Diagnostics.Type_of_iterated_elements_of_a_yield_Asterisk_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member : ts.Diagnostics.Type_of_yield_operand_in_an_async_generator_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); @@ -40378,14 +47048,15 @@ var ts; return eachTypeContainedIn(mapType(type, getRegularTypeOfLiteralType), switchTypes); } function functionHasImplicitReturn(func) { - if (!(func.flags & 128)) { + if (!(func.flags & 128 /* HasImplicitReturn */)) { return false; } - if (ts.some(func.body.statements, function (statement) { return statement.kind === 227 && isExhaustiveSwitchStatement(statement); })) { + if (ts.some(func.body.statements, function (statement) { return statement.kind === 227 /* SwitchStatement */ && isExhaustiveSwitchStatement(statement); })) { return false; } return true; } + /** NOTE: Return value of `[]` means a different thing than `undefined`. `[]` means func returns `void`, `undefined` means it returns `never`. */ function checkAndAggregateReturnExpressionTypes(func, checkMode) { var functionFlags = ts.getFunctionFlags(func); var aggregatedTypes = []; @@ -40395,10 +47066,14 @@ var ts; var expr = returnStatement.expression; if (expr) { var type = checkExpressionCached(expr, checkMode); - if (functionFlags & 2) { + if (functionFlags & 2 /* Async */) { + // From within an async function you can return either a non-promise value or a promise. Any + // Promise/A+ compatible implementation will always assimilate any foreign promise, so the + // return type of the body should be unwrapped to its awaited type, which should be wrapped in + // the native Promise type by the caller. type = checkAwaitedType(type, func, ts.Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); } - if (type.flags & 32768) { + if (type.flags & 32768 /* Never */) { hasReturnOfTypeNever = true; } ts.pushIfUnique(aggregatedTypes, type); @@ -40412,36 +47087,52 @@ var ts; } if (strictNullChecks && aggregatedTypes.length && hasReturnWithNoExpression && !(isJavaScriptConstructor(func) && aggregatedTypes.some(function (t) { return t.symbol === func.symbol; }))) { + // Javascript "callable constructors", containing eg `if (!(this instanceof A)) return new A()` should not add undefined ts.pushIfUnique(aggregatedTypes, undefinedType); } return aggregatedTypes; } function mayReturnNever(func) { switch (func.kind) { - case 192: - case 193: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: return true; - case 154: - return func.parent.kind === 184; + case 154 /* MethodDeclaration */: + return func.parent.kind === 184 /* ObjectLiteralExpression */; default: return false; } } + /** + * TypeScript Specification 1.0 (6.3) - July 2014 + * An explicitly typed function whose return type isn't the Void type, + * the Any type, or a union type containing the Void or Any type as a constituent + * must have at least one return statement somewhere in its body. + * An exception to this rule is if the function implementation consists of a single 'throw' statement. + * + * @param returnType - return type of the function, can be undefined if return type is not explicitly specified + */ function checkAllCodePathsInNonVoidFunctionReturnOrThrow(func, returnType) { if (!produceDiagnostics) { return; } - if (returnType && maybeTypeOfKind(returnType, 3 | 4096)) { + // Functions with with an explicitly specified 'void' or 'any' return type don't need any return expressions. + if (returnType && maybeTypeOfKind(returnType, 3 /* AnyOrUnknown */ | 4096 /* Void */)) { return; } - if (func.kind === 153 || ts.nodeIsMissing(func.body) || func.body.kind !== 213 || !functionHasImplicitReturn(func)) { + // If all we have is a function signature, or an arrow function with an expression body, then there is nothing to check. + // also if HasImplicitReturn flag is not set this means that all codepaths in function body end with return or throw + if (func.kind === 153 /* MethodSignature */ || ts.nodeIsMissing(func.body) || func.body.kind !== 213 /* Block */ || !functionHasImplicitReturn(func)) { return; } - var hasExplicitReturn = func.flags & 256; - if (returnType && returnType.flags & 32768) { + var hasExplicitReturn = func.flags & 256 /* HasExplicitReturn */; + if (returnType && returnType.flags & 32768 /* Never */) { error(ts.getEffectiveReturnTypeNode(func), ts.Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point); } else if (returnType && !hasExplicitReturn) { + // minimal check: function has syntactic return type annotation and no explicit return statements in the body + // this function does not conform to the specification. + // NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present error(ts.getEffectiveReturnTypeNode(func), ts.Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value); } else if (returnType && strictNullChecks && !isTypeAssignableTo(undefinedType, returnType)) { @@ -40449,6 +47140,9 @@ var ts; } else if (compilerOptions.noImplicitReturns) { if (!returnType) { + // If return type annotation is omitted check if function has any explicit return statements. + // If it does not have any - its inferred return type is void - don't do any checks. + // Otherwise get inferred return type from function body and report error only if it is not void / anytype if (!hasExplicitReturn) { return; } @@ -40461,12 +47155,14 @@ var ts; } } function checkFunctionExpressionOrObjectLiteralMethod(node, checkMode) { - ts.Debug.assert(node.kind !== 154 || ts.isObjectLiteralMethod(node)); - if (checkMode === 1 && isContextSensitive(node)) { + ts.Debug.assert(node.kind !== 154 /* MethodDeclaration */ || ts.isObjectLiteralMethod(node)); + // The identityMapper object is used to indicate that function expressions are wildcards + if (checkMode === 1 /* SkipContextSensitive */ && isContextSensitive(node)) { return anyFunctionType; } + // Grammar checking var hasGrammarError = checkGrammarFunctionLikeDeclaration(node); - if (!hasGrammarError && node.kind === 192) { + if (!hasGrammarError && node.kind === 192 /* FunctionExpression */) { checkGrammarForGenerator(node); } var links = getNodeLinks(node); @@ -40474,15 +47170,19 @@ var ts; if (isTypeAny(type)) { return type; } - if (!(links.flags & 1024)) { + // Check if function expression is contextually typed and assign parameter types if so. + if (!(links.flags & 1024 /* ContextChecked */)) { var contextualSignature = getContextualSignature(node); - if (!(links.flags & 1024)) { - links.flags |= 1024; + // If a type check is started at a function expression that is an argument of a function call, obtaining the + // contextual type may recursively get back to here during overload resolution of the call. If so, we will have + // already assigned contextual types. + if (!(links.flags & 1024 /* ContextChecked */)) { + links.flags |= 1024 /* ContextChecked */; if (contextualSignature) { - var signature = getSignaturesOfType(type, 0)[0]; + var signature = getSignaturesOfType(type, 0 /* Call */)[0]; if (isContextSensitive(node)) { var contextualMapper = getContextualMapper(node); - if (checkMode === 2) { + if (checkMode === 2 /* Inferential */) { inferFromAnnotatedParameters(signature, contextualSignature, contextualMapper); } var instantiatedContextualSignature = contextualMapper === identityMapper ? @@ -40503,31 +47203,42 @@ var ts; return type; } function checkFunctionExpressionOrObjectLiteralMethodDeferred(node) { - ts.Debug.assert(node.kind !== 154 || ts.isObjectLiteralMethod(node)); + ts.Debug.assert(node.kind !== 154 /* MethodDeclaration */ || ts.isObjectLiteralMethod(node)); var functionFlags = ts.getFunctionFlags(node); var returnTypeNode = ts.getEffectiveReturnTypeNode(node); var returnOrPromisedType = returnTypeNode && - ((functionFlags & 3) === 2 ? - checkAsyncFunctionReturnType(node) : - getTypeFromTypeNode(returnTypeNode)); - if ((functionFlags & 1) === 0) { + ((functionFlags & 3 /* AsyncGenerator */) === 2 /* Async */ ? + checkAsyncFunctionReturnType(node) : // Async function + getTypeFromTypeNode(returnTypeNode)); // AsyncGenerator function, Generator function, or normal function + if ((functionFlags & 1 /* Generator */) === 0) { // Async function or normal function + // return is not necessary in the body of generators checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType); } if (node.body) { if (!returnTypeNode) { + // There are some checks that are only performed in getReturnTypeFromBody, that may produce errors + // we need. An example is the noImplicitAny errors resulting from widening the return expression + // of a function. Because checking of function expression bodies is deferred, there was never an + // appropriate time to do this during the main walk of the file (see the comment at the top of + // checkFunctionExpressionBodies). So it must be done now. getReturnTypeOfSignature(getSignatureFromDeclaration(node)); } - if (node.body.kind === 213) { + if (node.body.kind === 213 /* Block */) { checkSourceElement(node.body); } else { + // From within an async function you can return either a non-promise value or a promise. Any + // Promise/A+ compatible implementation will always assimilate any foreign promise, so we + // should not be checking assignability of a promise to the return type. Instead, we need to + // check assignability of the awaited type of the expression body against the promised type of + // its return type annotation. var exprType = checkExpression(node.body); if (returnOrPromisedType) { - if ((functionFlags & 3) === 2) { + if ((functionFlags & 3 /* AsyncGenerator */) === 2 /* Async */) { // Async function var awaitedType = checkAwaitedType(exprType, node.body, ts.Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); checkTypeAssignableTo(awaitedType, returnOrPromisedType, node.body); } - else { + else { // Normal function checkTypeAssignableTo(exprType, returnOrPromisedType, node.body); } } @@ -40535,28 +47246,39 @@ var ts; } } function checkArithmeticOperandType(operand, type, diagnostic) { - if (!isTypeAssignableToKind(type, 168)) { + if (!isTypeAssignableToKind(type, 168 /* NumberLike */)) { error(operand, diagnostic); return false; } return true; } function isReadonlySymbol(symbol) { - return !!(ts.getCheckFlags(symbol) & 8 || - symbol.flags & 4 && ts.getDeclarationModifierFlagsFromSymbol(symbol) & 64 || - symbol.flags & 3 && getDeclarationNodeFlagsFromSymbol(symbol) & 2 || - symbol.flags & 98304 && !(symbol.flags & 65536) || - symbol.flags & 8); + // The following symbols are considered read-only: + // Properties with a 'readonly' modifier + // Variables declared with 'const' + // Get accessors without matching set accessors + // Enum members + // Unions and intersections of the above (unions and intersections eagerly set isReadonly on creation) + return !!(ts.getCheckFlags(symbol) & 8 /* Readonly */ || + symbol.flags & 4 /* Property */ && ts.getDeclarationModifierFlagsFromSymbol(symbol) & 64 /* Readonly */ || + symbol.flags & 3 /* Variable */ && getDeclarationNodeFlagsFromSymbol(symbol) & 2 /* Const */ || + symbol.flags & 98304 /* Accessor */ && !(symbol.flags & 65536 /* SetAccessor */) || + symbol.flags & 8 /* EnumMember */); } function isReferenceToReadonlyEntity(expr, symbol) { if (isReadonlySymbol(symbol)) { - if (symbol.flags & 4 && - (expr.kind === 185 || expr.kind === 186) && - expr.expression.kind === 99) { + // Allow assignments to readonly properties within constructors of the same class declaration. + if (symbol.flags & 4 /* Property */ && + (expr.kind === 185 /* PropertyAccessExpression */ || expr.kind === 186 /* ElementAccessExpression */) && + expr.expression.kind === 99 /* ThisKeyword */) { + // Look for if this is the constructor for the class that `symbol` is a property of. var func = ts.getContainingFunction(expr); - if (!(func && func.kind === 155)) { + if (!(func && func.kind === 155 /* Constructor */)) { return true; } + // If func.parent is a class and symbol is a (readonly) property of that class, or + // if func is a constructor and symbol is a (readonly) parameter property declared in it, + // then symbol is writeable here. return !(func.parent === symbol.valueDeclaration.parent || func === symbol.valueDeclaration.parent); } return true; @@ -40564,21 +47286,22 @@ var ts; return false; } function isReferenceThroughNamespaceImport(expr) { - if (expr.kind === 185 || expr.kind === 186) { + if (expr.kind === 185 /* PropertyAccessExpression */ || expr.kind === 186 /* ElementAccessExpression */) { var node = ts.skipParentheses(expr.expression); - if (node.kind === 71) { + if (node.kind === 71 /* Identifier */) { var symbol = getNodeLinks(node).resolvedSymbol; - if (symbol.flags & 2097152) { + if (symbol.flags & 2097152 /* Alias */) { var declaration = getDeclarationOfAliasSymbol(symbol); - return !!declaration && declaration.kind === 246; + return !!declaration && declaration.kind === 246 /* NamespaceImport */; } } } return false; } function checkReferenceExpression(expr, invalidReferenceMessage) { - var node = ts.skipOuterExpressions(expr, 2 | 1); - if (node.kind !== 71 && node.kind !== 185 && node.kind !== 186) { + // References are combinations of identifiers, parentheses, and property accesses. + var node = ts.skipOuterExpressions(expr, 2 /* Assertions */ | 1 /* Parentheses */); + if (node.kind !== 71 /* Identifier */ && node.kind !== 185 /* PropertyAccessExpression */ && node.kind !== 186 /* ElementAccessExpression */) { error(expr, invalidReferenceMessage); return false; } @@ -40587,7 +47310,7 @@ var ts; function checkDeleteExpression(node) { checkExpression(node.expression); var expr = ts.skipParentheses(node.expression); - if (expr.kind !== 185 && expr.kind !== 186) { + if (expr.kind !== 185 /* PropertyAccessExpression */ && expr.kind !== 186 /* ElementAccessExpression */) { error(expr, ts.Diagnostics.The_operand_of_a_delete_operator_must_be_a_property_reference); return booleanType; } @@ -40607,8 +47330,9 @@ var ts; return undefinedWideningType; } function checkAwaitExpression(node) { + // Grammar checking if (produceDiagnostics) { - if (!(node.flags & 16384)) { + if (!(node.flags & 16384 /* AwaitContext */)) { grammarErrorOnFirstToken(node, ts.Diagnostics.await_expression_is_only_allowed_within_an_async_function); } if (isInParameterInitializerBeforeContainingFunction(node)) { @@ -40623,32 +47347,33 @@ var ts; if (operandType === silentNeverType) { return silentNeverType; } - if (node.operand.kind === 8) { - if (node.operator === 38) { + if (node.operand.kind === 8 /* NumericLiteral */) { + if (node.operator === 38 /* MinusToken */) { return getFreshTypeOfLiteralType(getLiteralType(-node.operand.text)); } - else if (node.operator === 37) { + else if (node.operator === 37 /* PlusToken */) { return getFreshTypeOfLiteralType(getLiteralType(+node.operand.text)); } } switch (node.operator) { - case 37: - case 38: - case 52: + case 37 /* PlusToken */: + case 38 /* MinusToken */: + case 52 /* TildeToken */: checkNonNullType(operandType, node.operand); - if (maybeTypeOfKind(operandType, 3072)) { + if (maybeTypeOfKind(operandType, 3072 /* ESSymbolLike */)) { error(node.operand, ts.Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, ts.tokenToString(node.operator)); } return numberType; - case 51: - var facts = getTypeFacts(operandType) & (1048576 | 2097152); - return facts === 1048576 ? falseType : - facts === 2097152 ? trueType : + case 51 /* ExclamationToken */: + var facts = getTypeFacts(operandType) & (1048576 /* Truthy */ | 2097152 /* Falsy */); + return facts === 1048576 /* Truthy */ ? falseType : + facts === 2097152 /* Falsy */ ? trueType : booleanType; - case 43: - case 44: + case 43 /* PlusPlusToken */: + case 44 /* MinusMinusToken */: var ok = checkArithmeticOperandType(node.operand, checkNonNullType(operandType, node.operand), ts.Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type); if (ok) { + // run check only if former checks succeeded to avoid reporting cascading errors checkReferenceExpression(node.operand, ts.Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access); } return numberType; @@ -40662,15 +47387,18 @@ var ts; } var ok = checkArithmeticOperandType(node.operand, checkNonNullType(operandType, node.operand), ts.Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type); if (ok) { + // run check only if former checks succeeded to avoid reporting cascading errors checkReferenceExpression(node.operand, ts.Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access); } return numberType; } + // Return true if type might be of the given kind. A union or intersection type might be of a given + // kind if at least one constituent type is of the given kind. function maybeTypeOfKind(type, kind) { - if (type.flags & kind & ~134217728 || kind & 134217728 && isGenericMappedType(type)) { + if (type.flags & kind & ~134217728 /* GenericMappedType */ || kind & 134217728 /* GenericMappedType */ && isGenericMappedType(type)) { return true; } - if (type.flags & 786432) { + if (type.flags & 786432 /* UnionOrIntersection */) { var types = type.types; for (var _i = 0, types_16 = types; _i < types_16.length; _i++) { var t = types_16[_i]; @@ -40685,38 +47413,44 @@ var ts; if (source.flags & kind) { return true; } - if (strict && source.flags & (3 | 4096 | 8192 | 16384)) { + if (strict && source.flags & (3 /* AnyOrUnknown */ | 4096 /* Void */ | 8192 /* Undefined */ | 16384 /* Null */)) { return false; } - return !!(kind & 168) && isTypeAssignableTo(source, numberType) || - !!(kind & 68) && isTypeAssignableTo(source, stringType) || - !!(kind & 272) && isTypeAssignableTo(source, booleanType) || - !!(kind & 4096) && isTypeAssignableTo(source, voidType) || - !!(kind & 32768) && isTypeAssignableTo(source, neverType) || - !!(kind & 16384) && isTypeAssignableTo(source, nullType) || - !!(kind & 8192) && isTypeAssignableTo(source, undefinedType) || - !!(kind & 1024) && isTypeAssignableTo(source, esSymbolType) || - !!(kind & 16777216) && isTypeAssignableTo(source, nonPrimitiveType); + return !!(kind & 168 /* NumberLike */) && isTypeAssignableTo(source, numberType) || + !!(kind & 68 /* StringLike */) && isTypeAssignableTo(source, stringType) || + !!(kind & 272 /* BooleanLike */) && isTypeAssignableTo(source, booleanType) || + !!(kind & 4096 /* Void */) && isTypeAssignableTo(source, voidType) || + !!(kind & 32768 /* Never */) && isTypeAssignableTo(source, neverType) || + !!(kind & 16384 /* Null */) && isTypeAssignableTo(source, nullType) || + !!(kind & 8192 /* Undefined */) && isTypeAssignableTo(source, undefinedType) || + !!(kind & 1024 /* ESSymbol */) && isTypeAssignableTo(source, esSymbolType) || + !!(kind & 16777216 /* NonPrimitive */) && isTypeAssignableTo(source, nonPrimitiveType); } function allTypesAssignableToKind(source, kind, strict) { - return source.flags & 262144 ? + return source.flags & 262144 /* Union */ ? ts.every(source.types, function (subType) { return allTypesAssignableToKind(subType, kind, strict); }) : isTypeAssignableToKind(source, kind, strict); } function isConstEnumObjectType(type) { - return !!(ts.getObjectFlags(type) & 16) && !!type.symbol && isConstEnumSymbol(type.symbol); + return !!(ts.getObjectFlags(type) & 16 /* Anonymous */) && !!type.symbol && isConstEnumSymbol(type.symbol); } function isConstEnumSymbol(symbol) { - return (symbol.flags & 128) !== 0; + return (symbol.flags & 128 /* ConstEnum */) !== 0; } function checkInstanceOfExpression(left, right, leftType, rightType) { if (leftType === silentNeverType || rightType === silentNeverType) { return silentNeverType; } + // TypeScript 1.0 spec (April 2014): 4.15.4 + // The instanceof operator requires the left operand to be of type Any, an object type, or a type parameter type, + // and the right operand to be of type Any, a subtype of the 'Function' interface type, or have a call or construct signature. + // The result is always of the Boolean primitive type. + // NOTE: do not raise error if leftType is unknown as related error was already reported if (!isTypeAny(leftType) && - allTypesAssignableToKind(leftType, 32764)) { + allTypesAssignableToKind(leftType, 32764 /* Primitive */)) { error(left, ts.Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); } + // NOTE: do not raise error if right is unknown as related error was already reported if (!(isTypeAny(rightType) || typeHasCallOrConstructSignatures(rightType) || isTypeSubtypeOf(rightType, globalFunctionType))) { error(right, ts.Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type); } @@ -40728,10 +47462,14 @@ var ts; } leftType = checkNonNullType(leftType, left); rightType = checkNonNullType(rightType, right); - if (!(isTypeComparableTo(leftType, stringType) || isTypeAssignableToKind(leftType, 168 | 3072))) { + // TypeScript 1.0 spec (April 2014): 4.15.5 + // The in operator requires the left operand to be of type Any, the String primitive type, or the Number primitive type, + // and the right operand to be of type Any, an object type, or a type parameter type. + // The result is always of the Boolean primitive type. + if (!(isTypeComparableTo(leftType, stringType) || isTypeAssignableToKind(leftType, 168 /* NumberLike */ | 3072 /* ESSymbolLike */))) { error(left, ts.Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol); } - if (!isTypeAssignableToKind(rightType, 16777216 | 14745600)) { + if (!isTypeAssignableToKind(rightType, 16777216 /* NonPrimitive */ | 14745600 /* InstantiableNonPrimitive */)) { error(right, ts.Diagnostics.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); } return booleanType; @@ -40747,10 +47485,11 @@ var ts; } return sourceType; } + /** Note: If property cannot be a SpreadAssignment, then allProperties does not need to be provided */ function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType, property, allProperties) { - if (property.kind === 270 || property.kind === 271) { + if (property.kind === 270 /* PropertyAssignment */ || property.kind === 271 /* ShorthandPropertyAssignment */) { var name = property.name; - if (name.kind === 147) { + if (name.kind === 147 /* ComputedPropertyName */) { checkComputedPropertyName(name); } if (isComputedNonLiteralName(name)) { @@ -40760,13 +47499,14 @@ var ts; var type = isTypeAny(objectLiteralType) ? objectLiteralType : getTypeOfPropertyOfType(objectLiteralType, text) || - isNumericLiteralName(text) && getIndexTypeOfType(objectLiteralType, 1) || - getIndexTypeOfType(objectLiteralType, 0); + isNumericLiteralName(text) && getIndexTypeOfType(objectLiteralType, 1 /* Number */) || + getIndexTypeOfType(objectLiteralType, 0 /* String */); if (type) { - if (property.kind === 271) { + if (property.kind === 271 /* ShorthandPropertyAssignment */) { return checkDestructuringAssignment(property, type); } else { + // non-shorthand property assignments should always have initializers return checkDestructuringAssignment(property.initializer, type); } } @@ -40774,9 +47514,9 @@ var ts; error(name, ts.Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(objectLiteralType), ts.declarationNameToString(name)); } } - else if (property.kind === 272) { - if (languageVersion < 6) { - checkExternalEmitHelpers(property, 4); + else if (property.kind === 272 /* SpreadAssignment */) { + if (languageVersion < 6 /* ESNext */) { + checkExternalEmitHelpers(property, 4 /* Rest */); } var nonRestNames = []; if (allProperties) { @@ -40794,10 +47534,13 @@ var ts; } function checkArrayLiteralAssignment(node, sourceType, checkMode) { var elements = node.elements; - if (languageVersion < 2 && compilerOptions.downlevelIteration) { - checkExternalEmitHelpers(node, 512); + if (languageVersion < 2 /* ES2015 */ && compilerOptions.downlevelIteration) { + checkExternalEmitHelpers(node, 512 /* Read */); } - var elementType = checkIteratedTypeOrElementType(sourceType, node, false, false) || errorType; + // This elementType will be used if the specific property corresponding to this index is not + // present (aka the tuple element property). This call also checks that the parentType is in + // fact an iterable or array (depending on target language). + var elementType = checkIteratedTypeOrElementType(sourceType, node, /*allowStringInput*/ false, /*allowAsyncIterables*/ false) || errorType; for (var i = 0; i < elements.length; i++) { checkArrayLiteralDestructuringElementAssignment(node, sourceType, i, elementType, checkMode); } @@ -40806,8 +47549,8 @@ var ts; function checkArrayLiteralDestructuringElementAssignment(node, sourceType, elementIndex, elementType, checkMode) { var elements = node.elements; var element = elements[elementIndex]; - if (element.kind !== 206) { - if (element.kind !== 204) { + if (element.kind !== 206 /* OmittedExpression */) { + if (element.kind !== 204 /* SpreadElement */) { var propName = "" + elementIndex; var type = isTypeAny(sourceType) ? sourceType @@ -40818,6 +47561,8 @@ var ts; return checkDestructuringAssignment(element, type, checkMode); } else { + // We still need to check element expression here because we may need to set appropriate flag on the expression + // such as NodeCheckFlags.LexicalThis on "this"expression. checkExpression(element); if (isTupleType(sourceType)) { error(element, ts.Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(sourceType), getTypeReferenceArity(sourceType), elements.length); @@ -40833,7 +47578,7 @@ var ts; } else { var restExpression = element.expression; - if (restExpression.kind === 200 && restExpression.operatorToken.kind === 58) { + if (restExpression.kind === 200 /* BinaryExpression */ && restExpression.operatorToken.kind === 58 /* EqualsToken */) { error(restExpression.operatorToken, ts.Diagnostics.A_rest_element_cannot_have_an_initializer); } else { @@ -40847,12 +47592,14 @@ var ts; } function checkDestructuringAssignment(exprOrAssignment, sourceType, checkMode) { var target; - if (exprOrAssignment.kind === 271) { + if (exprOrAssignment.kind === 271 /* ShorthandPropertyAssignment */) { var prop = exprOrAssignment; if (prop.objectAssignmentInitializer) { + // In strict null checking mode, if a default value of a non-undefined type is specified, remove + // undefined from the final type. if (strictNullChecks && - !(getFalsyFlags(checkExpression(prop.objectAssignmentInitializer)) & 8192)) { - sourceType = getTypeWithFacts(sourceType, 131072); + !(getFalsyFlags(checkExpression(prop.objectAssignmentInitializer)) & 8192 /* Undefined */)) { + sourceType = getTypeWithFacts(sourceType, 131072 /* NEUndefined */); } checkBinaryLikeExpression(prop.name, prop.equalsToken, prop.objectAssignmentInitializer, checkMode); } @@ -40861,80 +47608,91 @@ var ts; else { target = exprOrAssignment; } - if (target.kind === 200 && target.operatorToken.kind === 58) { + if (target.kind === 200 /* BinaryExpression */ && target.operatorToken.kind === 58 /* EqualsToken */) { checkBinaryExpression(target, checkMode); target = target.left; } - if (target.kind === 184) { + if (target.kind === 184 /* ObjectLiteralExpression */) { return checkObjectLiteralAssignment(target, sourceType); } - if (target.kind === 183) { + if (target.kind === 183 /* ArrayLiteralExpression */) { return checkArrayLiteralAssignment(target, sourceType, checkMode); } return checkReferenceAssignment(target, sourceType, checkMode); } function checkReferenceAssignment(target, sourceType, checkMode) { var targetType = checkExpression(target, checkMode); - var error = target.parent.kind === 272 ? + var error = target.parent.kind === 272 /* SpreadAssignment */ ? ts.Diagnostics.The_target_of_an_object_rest_assignment_must_be_a_variable_or_a_property_access : ts.Diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access; if (checkReferenceExpression(target, error)) { - checkTypeAssignableTo(sourceType, targetType, target, undefined); + checkTypeAssignableTo(sourceType, targetType, target, /*headMessage*/ undefined); } return sourceType; } + /** + * This is a *shallow* check: An expression is side-effect-free if the + * evaluation of the expression *itself* cannot produce side effects. + * For example, x++ / 3 is side-effect free because the / operator + * does not have side effects. + * The intent is to "smell test" an expression for correctness in positions where + * its value is discarded (e.g. the left side of the comma operator). + */ function isSideEffectFree(node) { node = ts.skipParentheses(node); switch (node.kind) { - case 71: - case 9: - case 12: - case 189: - case 202: - case 13: - case 8: - case 101: - case 86: - case 95: - case 140: - case 192: - case 205: - case 193: - case 183: - case 184: - case 195: - case 209: - case 256: - case 255: + case 71 /* Identifier */: + case 9 /* StringLiteral */: + case 12 /* RegularExpressionLiteral */: + case 189 /* TaggedTemplateExpression */: + case 202 /* TemplateExpression */: + case 13 /* NoSubstitutionTemplateLiteral */: + case 8 /* NumericLiteral */: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: + case 95 /* NullKeyword */: + case 140 /* UndefinedKeyword */: + case 192 /* FunctionExpression */: + case 205 /* ClassExpression */: + case 193 /* ArrowFunction */: + case 183 /* ArrayLiteralExpression */: + case 184 /* ObjectLiteralExpression */: + case 195 /* TypeOfExpression */: + case 209 /* NonNullExpression */: + case 256 /* JsxSelfClosingElement */: + case 255 /* JsxElement */: return true; - case 201: + case 201 /* ConditionalExpression */: return isSideEffectFree(node.whenTrue) && isSideEffectFree(node.whenFalse); - case 200: + case 200 /* BinaryExpression */: if (ts.isAssignmentOperator(node.operatorToken.kind)) { return false; } return isSideEffectFree(node.left) && isSideEffectFree(node.right); - case 198: - case 199: + case 198 /* PrefixUnaryExpression */: + case 199 /* PostfixUnaryExpression */: + // Unary operators ~, !, +, and - have no side effects. + // The rest do. switch (node.operator) { - case 51: - case 37: - case 38: - case 52: + case 51 /* ExclamationToken */: + case 37 /* PlusToken */: + case 38 /* MinusToken */: + case 52 /* TildeToken */: return true; } return false; - case 196: - case 190: - case 208: + // Some forms listed here for clarity + case 196 /* VoidExpression */: // Explicit opt-out + case 190 /* TypeAssertionExpression */: // Not SEF, but can produce useful type warnings + case 208 /* AsExpression */: // Not SEF, but can produce useful type warnings default: return false; } } function isTypeEqualityComparableTo(source, target) { - return (target.flags & 24576) !== 0 || isTypeComparableTo(source, target); + return (target.flags & 24576 /* Nullable */) !== 0 || isTypeComparableTo(source, target); } function checkBinaryExpression(node, checkMode) { if (ts.isInJavaScriptFile(node) && ts.getAssignedJavascriptInitializer(node)) { @@ -40944,46 +47702,49 @@ var ts; } function checkBinaryLikeExpression(left, operatorToken, right, checkMode, errorNode) { var operator = operatorToken.kind; - if (operator === 58 && (left.kind === 184 || left.kind === 183)) { + if (operator === 58 /* EqualsToken */ && (left.kind === 184 /* ObjectLiteralExpression */ || left.kind === 183 /* ArrayLiteralExpression */)) { return checkDestructuringAssignment(left, checkExpression(right, checkMode), checkMode); } var leftType = checkExpression(left, checkMode); var rightType = checkExpression(right, checkMode); switch (operator) { - case 39: - case 40: - case 61: - case 62: - case 41: - case 63: - case 42: - case 64: - case 38: - case 60: - case 45: - case 65: - case 46: - case 66: - case 47: - case 67: - case 49: - case 69: - case 50: - case 70: - case 48: - case 68: + case 39 /* AsteriskToken */: + case 40 /* AsteriskAsteriskToken */: + case 61 /* AsteriskEqualsToken */: + case 62 /* AsteriskAsteriskEqualsToken */: + case 41 /* SlashToken */: + case 63 /* SlashEqualsToken */: + case 42 /* PercentToken */: + case 64 /* PercentEqualsToken */: + case 38 /* MinusToken */: + case 60 /* MinusEqualsToken */: + case 45 /* LessThanLessThanToken */: + case 65 /* LessThanLessThanEqualsToken */: + case 46 /* GreaterThanGreaterThanToken */: + case 66 /* GreaterThanGreaterThanEqualsToken */: + case 47 /* GreaterThanGreaterThanGreaterThanToken */: + case 67 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + case 49 /* BarToken */: + case 69 /* BarEqualsToken */: + case 50 /* CaretToken */: + case 70 /* CaretEqualsToken */: + case 48 /* AmpersandToken */: + case 68 /* AmpersandEqualsToken */: if (leftType === silentNeverType || rightType === silentNeverType) { return silentNeverType; } leftType = checkNonNullType(leftType, left); rightType = checkNonNullType(rightType, right); var suggestedOperator = void 0; - if ((leftType.flags & 272) && - (rightType.flags & 272) && + // if a user tries to apply a bitwise operator to 2 boolean operands + // try and return them a helpful suggestion + if ((leftType.flags & 272 /* BooleanLike */) && + (rightType.flags & 272 /* BooleanLike */) && (suggestedOperator = getSuggestedBooleanOperator(operatorToken.kind)) !== undefined) { error(errorNode || operatorToken, ts.Diagnostics.The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead, ts.tokenToString(operatorToken.kind), ts.tokenToString(suggestedOperator)); } else { + // otherwise just check each operand separately and report errors as normal var leftOk = checkArithmeticOperandType(left, leftType, ts.Diagnostics.The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type); var rightOk = checkArithmeticOperandType(right, rightType, ts.Diagnostics.The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type); if (leftOk && rightOk) { @@ -40991,25 +47752,31 @@ var ts; } } return numberType; - case 37: - case 59: + case 37 /* PlusToken */: + case 59 /* PlusEqualsToken */: if (leftType === silentNeverType || rightType === silentNeverType) { return silentNeverType; } - if (!isTypeAssignableToKind(leftType, 68) && !isTypeAssignableToKind(rightType, 68)) { + if (!isTypeAssignableToKind(leftType, 68 /* StringLike */) && !isTypeAssignableToKind(rightType, 68 /* StringLike */)) { leftType = checkNonNullType(leftType, left); rightType = checkNonNullType(rightType, right); } var resultType = void 0; - if (isTypeAssignableToKind(leftType, 168, true) && isTypeAssignableToKind(rightType, 168, true)) { + if (isTypeAssignableToKind(leftType, 168 /* NumberLike */, /*strict*/ true) && isTypeAssignableToKind(rightType, 168 /* NumberLike */, /*strict*/ true)) { + // Operands of an enum type are treated as having the primitive type Number. + // If both operands are of the Number primitive type, the result is of the Number primitive type. resultType = numberType; } - else if (isTypeAssignableToKind(leftType, 68, true) || isTypeAssignableToKind(rightType, 68, true)) { + else if (isTypeAssignableToKind(leftType, 68 /* StringLike */, /*strict*/ true) || isTypeAssignableToKind(rightType, 68 /* StringLike */, /*strict*/ true)) { + // If one or both operands are of the String primitive type, the result is of the String primitive type. resultType = stringType; } else if (isTypeAny(leftType) || isTypeAny(rightType)) { + // Otherwise, the result is of type Any. + // NOTE: unknown type here denotes error type. Old compiler treated this case as any type so do we. resultType = leftType === errorType || rightType === errorType ? errorType : anyType; } + // Symbols are not allowed at all in arithmetic expressions if (resultType && !checkForDisallowedESSymbolOperand(operator)) { return resultType; } @@ -41017,14 +47784,14 @@ var ts; reportOperatorError(); return anyType; } - if (operator === 59) { + if (operator === 59 /* PlusEqualsToken */) { checkAssignmentOperator(resultType); } return resultType; - case 27: - case 29: - case 30: - case 31: + case 27 /* LessThanToken */: + case 29 /* GreaterThanToken */: + case 30 /* LessThanEqualsToken */: + case 31 /* GreaterThanEqualsToken */: if (checkForDisallowedESSymbolOperand(operator)) { leftType = getBaseTypeOfLiteralType(checkNonNullType(leftType, left)); rightType = getBaseTypeOfLiteralType(checkNonNullType(rightType, right)); @@ -41033,10 +47800,10 @@ var ts; } } return booleanType; - case 32: - case 33: - case 34: - case 35: + case 32 /* EqualsEqualsToken */: + case 33 /* ExclamationEqualsToken */: + case 34 /* EqualsEqualsEqualsToken */: + case 35 /* ExclamationEqualsEqualsToken */: var leftIsLiteral = isLiteralType(leftType); var rightIsLiteral = isLiteralType(rightType); if (!leftIsLiteral || !rightIsLiteral) { @@ -41047,19 +47814,19 @@ var ts; reportOperatorError(); } return booleanType; - case 93: + case 93 /* InstanceOfKeyword */: return checkInstanceOfExpression(left, right, leftType, rightType); - case 92: + case 92 /* InKeyword */: return checkInExpression(left, right, leftType, rightType); - case 53: - return getTypeFacts(leftType) & 1048576 ? + case 53 /* AmpersandAmpersandToken */: + return getTypeFacts(leftType) & 1048576 /* Truthy */ ? getUnionType([extractDefinitelyFalsyTypes(strictNullChecks ? leftType : getBaseTypeOfLiteralType(rightType)), rightType]) : leftType; - case 54: - return getTypeFacts(leftType) & 2097152 ? - getUnionType([removeDefinitelyFalsyTypes(leftType), rightType], 2) : + case 54 /* BarBarToken */: + return getTypeFacts(leftType) & 2097152 /* Falsy */ ? + getUnionType([removeDefinitelyFalsyTypes(leftType), rightType], 2 /* Subtype */) : leftType; - case 58: + case 58 /* EqualsToken */: var special = ts.getSpecialPropertyAssignmentKind(left.parent); checkSpecialAssignment(special, right); if (isJSSpecialPropertyAssignment(special)) { @@ -41069,7 +47836,7 @@ var ts; checkAssignmentOperator(rightType); return getRegularTypeOfObjectLiteral(rightType); } - case 26: + case 26 /* CommaToken */: if (!compilerOptions.allowUnreachableCode && isSideEffectFree(left) && !isEvalNode(right)) { error(left, ts.Diagnostics.Left_side_of_comma_operator_is_unused_and_has_no_side_effects); } @@ -41078,14 +47845,14 @@ var ts; return ts.Debug.fail(); } function checkSpecialAssignment(special, right) { - if (special === 2) { + if (special === 2 /* ModuleExports */) { var rightType_1 = checkExpression(right, checkMode); for (var _i = 0, _a = getPropertiesOfObjectType(rightType_1); _i < _a.length; _i++) { var prop = _a[_i]; var propType = getTypeOfSymbol(prop); - if (propType.symbol && propType.symbol.flags & 32) { + if (propType.symbol && propType.symbol.flags & 32 /* Class */) { var name = prop.escapedName; - var symbol = resolveName(prop.valueDeclaration, name, 67901928, undefined, name, false); + var symbol = resolveName(prop.valueDeclaration, name, 67901928 /* Type */, undefined, name, /*isUse*/ false); if (symbol && symbol.declarations.some(ts.isJSDocTypedefTag)) { grammarErrorOnNode(symbol.declarations[0], ts.Diagnostics.Duplicate_identifier_0, ts.unescapeLeadingUnderscores(name)); return grammarErrorOnNode(prop.valueDeclaration, ts.Diagnostics.Duplicate_identifier_0, ts.unescapeLeadingUnderscores(name)); @@ -41095,11 +47862,12 @@ var ts; } } function isEvalNode(node) { - return node.kind === 71 && node.escapedText === "eval"; + return node.kind === 71 /* Identifier */ && node.escapedText === "eval"; } + // Return true if there was no error, false if there was an error. function checkForDisallowedESSymbolOperand(operator) { - var offendingSymbolOperand = maybeTypeOfKind(leftType, 3072) ? left : - maybeTypeOfKind(rightType, 3072) ? right : + var offendingSymbolOperand = maybeTypeOfKind(leftType, 3072 /* ESSymbolLike */) ? left : + maybeTypeOfKind(rightType, 3072 /* ESSymbolLike */) ? right : undefined; if (offendingSymbolOperand) { error(offendingSymbolOperand, ts.Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, ts.tokenToString(operator)); @@ -41109,35 +47877,42 @@ var ts; } function getSuggestedBooleanOperator(operator) { switch (operator) { - case 49: - case 69: - return 54; - case 50: - case 70: - return 35; - case 48: - case 68: - return 53; + case 49 /* BarToken */: + case 69 /* BarEqualsToken */: + return 54 /* BarBarToken */; + case 50 /* CaretToken */: + case 70 /* CaretEqualsToken */: + return 35 /* ExclamationEqualsEqualsToken */; + case 48 /* AmpersandToken */: + case 68 /* AmpersandEqualsToken */: + return 53 /* AmpersandAmpersandToken */; default: return undefined; } } function checkAssignmentOperator(valueType) { if (produceDiagnostics && ts.isAssignmentOperator(operator)) { + // TypeScript 1.0 spec (April 2014): 4.17 + // An assignment of the form + // VarExpr = ValueExpr + // requires VarExpr to be classified as a reference + // A compound assignment furthermore requires VarExpr to be classified as a reference (section 4.1) + // and the type of the non-compound operation to be assignable to the type of VarExpr. if (checkReferenceExpression(left, ts.Diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access) && (!ts.isIdentifier(left) || ts.unescapeLeadingUnderscores(left.escapedText) !== "exports")) { - checkTypeAssignableTo(valueType, leftType, left, undefined); + // to avoid cascading errors check assignability only if 'isReference' check succeeded and no errors were reported + checkTypeAssignableTo(valueType, leftType, left, /*headMessage*/ undefined); } } } function isJSSpecialPropertyAssignment(special) { switch (special) { - case 1: - case 2: - case 5: - case 6: - case 3: - case 4: + case 1 /* ExportsProperty */: + case 2 /* ModuleExports */: + case 5 /* Property */: + case 6 /* Prototype */: + case 3 /* PrototypeProperty */: + case 4 /* ThisProperty */: var symbol = getSymbolOfNode(left); var init = ts.getAssignedJavascriptInitializer(right); return init && ts.isObjectLiteralExpression(init) && @@ -41166,8 +47941,9 @@ var ts; return false; } function checkYieldExpression(node) { + // Grammar checking if (produceDiagnostics) { - if (!(node.flags & 4096) || isYieldExpressionInClass(node)) { + if (!(node.flags & 4096 /* YieldContext */) || isYieldExpressionInClass(node)) { grammarErrorOnFirstToken(node, ts.Diagnostics.A_yield_expression_is_only_allowed_in_a_generator_body); } if (isInParameterInitializerBeforeContainingFunction(node)) { @@ -41178,45 +47954,58 @@ var ts; if (!func) return anyType; var functionFlags = ts.getFunctionFlags(func); - if (!(functionFlags & 1)) { + if (!(functionFlags & 1 /* Generator */)) { + // If the user's code is syntactically correct, the func should always have a star. After all, we are in a yield context. return anyType; } if (node.asteriskToken) { - if ((functionFlags & 3) === 3 && - languageVersion < 6) { - checkExternalEmitHelpers(node, 26624); + // Async generator functions prior to ESNext require the __await, __asyncDelegator, + // and __asyncValues helpers + if ((functionFlags & 3 /* AsyncGenerator */) === 3 /* AsyncGenerator */ && + languageVersion < 6 /* ESNext */) { + checkExternalEmitHelpers(node, 26624 /* AsyncDelegatorIncludes */); } - if ((functionFlags & 3) === 1 && - languageVersion < 2 && compilerOptions.downlevelIteration) { - checkExternalEmitHelpers(node, 256); + // Generator functions prior to ES2015 require the __values helper + if ((functionFlags & 3 /* AsyncGenerator */) === 1 /* Generator */ && + languageVersion < 2 /* ES2015 */ && compilerOptions.downlevelIteration) { + checkExternalEmitHelpers(node, 256 /* Values */); } } - var isAsync = (functionFlags & 2) !== 0; - var yieldedType = getYieldedTypeOfYieldExpression(node, isAsync); + var isAsync = (functionFlags & 2 /* Async */) !== 0; + var yieldedType = getYieldedTypeOfYieldExpression(node, isAsync); // TODO: GH#18217 + // There is no point in doing an assignability check if the function + // has no explicit return type because the return type is directly computed + // from the yield expressions. var returnType = ts.getEffectiveReturnTypeNode(func); if (returnType) { var signatureElementType = getIteratedTypeOfGenerator(getTypeFromTypeNode(returnType), isAsync) || anyType; - checkTypeAssignableTo(yieldedType, signatureElementType, node.expression || node, undefined); + checkTypeAssignableTo(yieldedType, signatureElementType, node.expression || node, /*headMessage*/ undefined); } + // Both yield and yield* expressions have type 'any' return anyType; } function checkConditionalExpression(node, checkMode) { checkExpression(node.condition); var type1 = checkExpression(node.whenTrue, checkMode); var type2 = checkExpression(node.whenFalse, checkMode); - return getUnionType([type1, type2], 2); + return getUnionType([type1, type2], 2 /* Subtype */); } function checkTemplateExpression(node) { + // We just want to check each expressions, but we are unconcerned with + // the type of each expression, as any value may be coerced into a string. + // It is worth asking whether this is what we really want though. + // A place where we actually *are* concerned with the expressions' types are + // in tagged templates. ts.forEach(node.templateSpans, function (templateSpan) { - if (maybeTypeOfKind(checkExpression(templateSpan.expression), 3072)) { + if (maybeTypeOfKind(checkExpression(templateSpan.expression), 3072 /* ESSymbolLike */)) { error(templateSpan.expression, ts.Diagnostics.Type_0_cannot_be_converted_to_type_1, typeToString(esSymbolType), typeToString(stringType)); } }); return stringType; } function getContextNode(node) { - if (node.kind === 263) { - return node.parent.parent; + if (node.kind === 263 /* JsxAttributes */) { + return node.parent.parent; // Needs to be the root JsxElement, so it encompasses the attributes _and_ the children (which are essentially part of the attributes) } return node; } @@ -41226,8 +48015,8 @@ var ts; var saveContextualMapper = context.contextualMapper; context.contextualType = contextualType; context.contextualMapper = contextualMapper; - var checkMode = contextualMapper === identityMapper ? 1 : - contextualMapper ? 2 : 3; + var checkMode = contextualMapper === identityMapper ? 1 /* SkipContextSensitive */ : + contextualMapper ? 2 /* Inferential */ : 3 /* Contextual */; var result = checkExpression(node, checkMode); context.contextualType = saveContextualType; context.contextualMapper = saveContextualMapper; @@ -41239,6 +48028,9 @@ var ts; if (checkMode) { return checkExpression(node, checkMode); } + // When computing a type that we're going to cache, we need to ignore any ongoing control flow + // analysis because variables may have transient types in indeterminable states. Moving flowLoopStart + // to the top of the stack ensures all transient types are computed from a known point. var saveFlowLoopStart = flowLoopStart; flowLoopStart = flowLoopCount; links.resolvedType = checkExpression(node, checkMode); @@ -41248,16 +48040,16 @@ var ts; } function isTypeAssertion(node) { node = ts.skipParentheses(node); - return node.kind === 190 || node.kind === 208; + return node.kind === 190 /* TypeAssertionExpression */ || node.kind === 208 /* AsExpression */; } function checkDeclarationInitializer(declaration) { var initializer = ts.getEffectiveInitializer(declaration); - var type = getTypeOfExpression(initializer, true); - var widened = ts.getCombinedNodeFlags(declaration) & 2 || - (ts.getCombinedModifierFlags(declaration) & 64 && !ts.isParameterPropertyDeclaration(declaration)) || + var type = getTypeOfExpression(initializer, /*cache*/ true); + var widened = ts.getCombinedNodeFlags(declaration) & 2 /* Const */ || + (ts.getCombinedModifierFlags(declaration) & 64 /* Readonly */ && !ts.isParameterPropertyDeclaration(declaration)) || isTypeAssertion(initializer) ? type : getWidenedLiteralType(type); if (ts.isInJavaScriptFile(declaration)) { - if (widened.flags & 24576) { + if (widened.flags & 24576 /* Nullable */) { if (noImplicitAny) { reportImplicitAnyError(declaration, anyType); } @@ -41274,21 +48066,26 @@ var ts; } function isLiteralOfContextualType(candidateType, contextualType) { if (contextualType) { - if (contextualType.flags & 786432) { + if (contextualType.flags & 786432 /* UnionOrIntersection */) { var types = contextualType.types; return ts.some(types, function (t) { return isLiteralOfContextualType(candidateType, t); }); } - if (contextualType.flags & 14745600) { + if (contextualType.flags & 14745600 /* InstantiableNonPrimitive */) { + // If the contextual type is a type variable constrained to a primitive type, consider + // this a literal context for literals of that primitive type. For example, given a + // type parameter 'T extends string', infer string literal types for T. var constraint = getBaseConstraintOfType(contextualType) || emptyObjectType; - return maybeTypeOfKind(constraint, 4) && maybeTypeOfKind(candidateType, 64) || - maybeTypeOfKind(constraint, 8) && maybeTypeOfKind(candidateType, 128) || - maybeTypeOfKind(constraint, 1024) && maybeTypeOfKind(candidateType, 2048) || + return maybeTypeOfKind(constraint, 4 /* String */) && maybeTypeOfKind(candidateType, 64 /* StringLiteral */) || + maybeTypeOfKind(constraint, 8 /* Number */) && maybeTypeOfKind(candidateType, 128 /* NumberLiteral */) || + maybeTypeOfKind(constraint, 1024 /* ESSymbol */) && maybeTypeOfKind(candidateType, 2048 /* UniqueESSymbol */) || isLiteralOfContextualType(candidateType, constraint); } - return !!(contextualType.flags & (64 | 1048576) && maybeTypeOfKind(candidateType, 64) || - contextualType.flags & 128 && maybeTypeOfKind(candidateType, 128) || - contextualType.flags & 256 && maybeTypeOfKind(candidateType, 256) || - contextualType.flags & 2048 && maybeTypeOfKind(candidateType, 2048)); + // If the contextual type is a literal of a particular primitive type, we consider this a + // literal context for all literals of that primitive type. + return !!(contextualType.flags & (64 /* StringLiteral */ | 1048576 /* Index */) && maybeTypeOfKind(candidateType, 64 /* StringLiteral */) || + contextualType.flags & 128 /* NumberLiteral */ && maybeTypeOfKind(candidateType, 128 /* NumberLiteral */) || + contextualType.flags & 256 /* BooleanLiteral */ && maybeTypeOfKind(candidateType, 256 /* BooleanLiteral */) || + contextualType.flags & 2048 /* UniqueESSymbol */ && maybeTypeOfKind(candidateType, 2048 /* UniqueESSymbol */)); } return false; } @@ -41301,21 +48098,28 @@ var ts; getWidenedLiteralLikeTypeForContextualType(type, contextualType); } function checkPropertyAssignment(node, checkMode) { - if (node.name.kind === 147) { + // Do not use hasDynamicName here, because that returns false for well known symbols. + // We want to perform checkComputedPropertyName for all computed properties, including + // well known symbols. + if (node.name.kind === 147 /* ComputedPropertyName */) { checkComputedPropertyName(node.name); } return checkExpressionForMutableLocation(node.initializer, checkMode); } function checkObjectLiteralMethod(node, checkMode) { + // Grammar checking checkGrammarMethod(node); - if (node.name.kind === 147) { + // Do not use hasDynamicName here, because that returns false for well known symbols. + // We want to perform checkComputedPropertyName for all computed properties, including + // well known symbols. + if (node.name.kind === 147 /* ComputedPropertyName */) { checkComputedPropertyName(node.name); } var uninstantiatedType = checkFunctionExpressionOrObjectLiteralMethod(node, checkMode); return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode); } function instantiateTypeWithSingleGenericCallSignature(node, type, checkMode) { - if (checkMode === 2) { + if (checkMode === 2 /* Inferential */) { var signature = getSingleCallSignature(type); if (signature && signature.typeParameters) { var contextualType = getApparentTypeOfContextualType(node); @@ -41329,16 +48133,34 @@ var ts; } return type; } + /** + * Returns the type of an expression. Unlike checkExpression, this function is simply concerned + * with computing the type and may not fully check all contained sub-expressions for errors. + * A cache argument of true indicates that if the function performs a full type check, it is ok + * to cache the result. + */ function getTypeOfExpression(node, cache) { - if (node.kind === 187 && node.expression.kind !== 97 && !ts.isRequireCall(node, true) && !isSymbolOrSymbolForCall(node)) { + // Optimize for the common case of a call to a function with a single non-generic call + // signature where we can just fetch the return type without checking the arguments. + if (node.kind === 187 /* CallExpression */ && node.expression.kind !== 97 /* SuperKeyword */ && !ts.isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true) && !isSymbolOrSymbolForCall(node)) { var funcType = checkNonNullExpression(node.expression); var signature = getSingleCallSignature(funcType); if (signature && !signature.typeParameters) { return getReturnTypeOfSignature(signature); } } + // Otherwise simply call checkExpression. Ideally, the entire family of checkXXX functions + // should have a parameter that indicates whether full error checking is required such that + // we can perform the optimizations locally. return cache ? checkExpressionCached(node) : checkExpression(node); } + /** + * Returns the type of an expression. Unlike checkExpression, this function is simply concerned + * with computing the type and may not fully check all contained sub-expressions for errors. + * It is intended for uses where you know there is no contextual type, + * and requesting the contextual type might cause a circularity or other bad behaviour. + * It sets the contextual type of the node to any before calling getTypeOfExpression. + */ function getContextFreeTypeOfExpression(node) { var saveContextualType = node.contextualType; node.contextualType = anyType; @@ -41349,9 +48171,16 @@ var ts; function checkExpresionNoReturn(node) { checkExpression(node); } + // Checks an expression and returns its type. The contextualMapper parameter serves two purposes: When + // contextualMapper is not undefined and not equal to the identityMapper function object it indicates that the + // expression is being inferentially typed (section 4.15.2 in spec) and provides the type mapper to use in + // conjunction with the generic contextual type. When contextualMapper is equal to the identityMapper function + // object, it serves as an indicator that all contained function and arrow expressions should be considered to + // have the wildcard function type; this form of type check is used during overload resolution to exclude + // contextually typed function and arrow expressions in the initial phase. function checkExpression(node, checkMode) { var type; - if (node.kind === 146) { + if (node.kind === 146 /* QualifiedName */) { type = checkQualifiedName(node); } else { @@ -41359,10 +48188,14 @@ var ts; type = instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode); } if (isConstEnumObjectType(type)) { - var ok = (node.parent.kind === 185 && node.parent.expression === node) || - (node.parent.kind === 186 && node.parent.expression === node) || - ((node.kind === 71 || node.kind === 146) && isInRightSideOfImportOrExportAssignment(node) || - (node.parent.kind === 165 && node.parent.exprName === node)); + // enum object type for const enums are only permitted in: + // - 'left' in property access + // - 'object' in indexed access + // - target in rhs of import statement + var ok = (node.parent.kind === 185 /* PropertyAccessExpression */ && node.parent.expression === node) || + (node.parent.kind === 186 /* ElementAccessExpression */ && node.parent.expression === node) || + ((node.kind === 71 /* Identifier */ || node.kind === 146 /* QualifiedName */) && isInRightSideOfImportOrExportAssignment(node) || + (node.parent.kind === 165 /* TypeQuery */ && node.parent.exprName === node)); if (!ok) { error(node, ts.Diagnostics.const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment_or_type_query); } @@ -41378,96 +48211,99 @@ var ts; } function checkExpressionWorker(node, checkMode) { switch (node.kind) { - case 71: + case 71 /* Identifier */: return checkIdentifier(node); - case 99: + case 99 /* ThisKeyword */: return checkThisExpression(node); - case 97: + case 97 /* SuperKeyword */: return checkSuperExpression(node); - case 95: + case 95 /* NullKeyword */: return nullWideningType; - case 13: - case 9: + case 13 /* NoSubstitutionTemplateLiteral */: + case 9 /* StringLiteral */: return getFreshTypeOfLiteralType(getLiteralType(node.text)); - case 8: + case 8 /* NumericLiteral */: checkGrammarNumericLiteral(node); return getFreshTypeOfLiteralType(getLiteralType(+node.text)); - case 101: + case 101 /* TrueKeyword */: return trueType; - case 86: + case 86 /* FalseKeyword */: return falseType; - case 202: + case 202 /* TemplateExpression */: return checkTemplateExpression(node); - case 12: + case 12 /* RegularExpressionLiteral */: return globalRegExpType; - case 183: + case 183 /* ArrayLiteralExpression */: return checkArrayLiteral(node, checkMode); - case 184: + case 184 /* ObjectLiteralExpression */: return checkObjectLiteral(node, checkMode); - case 185: + case 185 /* PropertyAccessExpression */: return checkPropertyAccessExpression(node); - case 186: + case 186 /* ElementAccessExpression */: return checkIndexedAccess(node); - case 187: - if (node.expression.kind === 91) { + case 187 /* CallExpression */: + if (node.expression.kind === 91 /* ImportKeyword */) { return checkImportCallExpression(node); } - case 188: + /* falls through */ + case 188 /* NewExpression */: return checkCallExpression(node); - case 189: + case 189 /* TaggedTemplateExpression */: return checkTaggedTemplateExpression(node); - case 191: + case 191 /* ParenthesizedExpression */: return checkParenthesizedExpression(node, checkMode); - case 205: + case 205 /* ClassExpression */: return checkClassExpression(node); - case 192: - case 193: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: return checkFunctionExpressionOrObjectLiteralMethod(node, checkMode); - case 195: + case 195 /* TypeOfExpression */: return checkTypeOfExpression(node); - case 190: - case 208: + case 190 /* TypeAssertionExpression */: + case 208 /* AsExpression */: return checkAssertion(node); - case 209: + case 209 /* NonNullExpression */: return checkNonNullAssertion(node); - case 210: + case 210 /* MetaProperty */: return checkMetaProperty(node); - case 194: + case 194 /* DeleteExpression */: return checkDeleteExpression(node); - case 196: + case 196 /* VoidExpression */: return checkVoidExpression(node); - case 197: + case 197 /* AwaitExpression */: return checkAwaitExpression(node); - case 198: + case 198 /* PrefixUnaryExpression */: return checkPrefixUnaryExpression(node); - case 199: + case 199 /* PostfixUnaryExpression */: return checkPostfixUnaryExpression(node); - case 200: + case 200 /* BinaryExpression */: return checkBinaryExpression(node, checkMode); - case 201: + case 201 /* ConditionalExpression */: return checkConditionalExpression(node, checkMode); - case 204: + case 204 /* SpreadElement */: return checkSpreadExpression(node, checkMode); - case 206: + case 206 /* OmittedExpression */: return undefinedWideningType; - case 203: + case 203 /* YieldExpression */: return checkYieldExpression(node); - case 265: + case 265 /* JsxExpression */: return checkJsxExpression(node, checkMode); - case 255: + case 255 /* JsxElement */: return checkJsxElement(node, checkMode); - case 256: + case 256 /* JsxSelfClosingElement */: return checkJsxSelfClosingElement(node, checkMode); - case 259: + case 259 /* JsxFragment */: return checkJsxFragment(node, checkMode); - case 263: + case 263 /* JsxAttributes */: return checkJsxAttributes(node, checkMode); - case 257: + case 257 /* JsxOpeningElement */: ts.Debug.fail("Shouldn't ever directly check a JsxOpeningElement"); } return errorType; } + // DECLARATION AND STATEMENT TYPE CHECKING function checkTypeParameter(node) { + // Grammar Checking if (node.expression) { grammarErrorOnFirstToken(node.expression, ts.Diagnostics.Type_expected); } @@ -41490,11 +48326,15 @@ var ts; } } function checkParameter(node) { + // Grammar checking + // It is a SyntaxError if the Identifier "eval" or the Identifier "arguments" occurs as the + // Identifier in a PropertySetParameterList of a PropertyAssignment that is contained in strict code + // or if its FunctionBody is strict code(11.1.5). checkGrammarDecoratorsAndModifiers(node); checkVariableLikeDeclaration(node); var func = ts.getContainingFunction(node); - if (ts.hasModifier(node, 92)) { - if (!(func.kind === 155 && ts.nodeIsPresent(func.body))) { + if (ts.hasModifier(node, 92 /* ParameterPropertyModifier */)) { + if (!(func.kind === 155 /* Constructor */ && ts.nodeIsPresent(func.body))) { error(node, ts.Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation); } } @@ -41505,10 +48345,12 @@ var ts; if (func.parameters.indexOf(node) !== 0) { error(node, ts.Diagnostics.A_0_parameter_must_be_the_first_parameter, node.name.escapedText); } - if (func.kind === 155 || func.kind === 159 || func.kind === 164) { + if (func.kind === 155 /* Constructor */ || func.kind === 159 /* ConstructSignature */ || func.kind === 164 /* ConstructorType */) { error(node, ts.Diagnostics.A_constructor_cannot_have_a_this_parameter); } } + // Only check rest parameter type if it's not a binding pattern. Since binding patterns are + // not allowed in a rest parameter, we already have an error from checkGrammarParameterList. if (node.dotDotDotToken && !ts.isBindingPattern(node.name) && !isArrayType(getTypeOfSymbol(node.symbol))) { error(node, ts.Diagnostics.A_rest_parameter_must_be_of_an_array_type); } @@ -41517,7 +48359,7 @@ var ts; if (parameterList) { for (var i = 0; i < parameterList.length; i++) { var param = parameterList[i]; - if (param.name.kind === 71 && param.name.escapedText === parameter.escapedText) { + if (param.name.kind === 71 /* Identifier */ && param.name.escapedText === parameter.escapedText) { return i; } } @@ -41527,6 +48369,7 @@ var ts; function checkTypePredicate(node) { var parent = getTypePredicateParent(node); if (!parent) { + // The parent must not be valid. error(node, ts.Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods); return; } @@ -41545,8 +48388,10 @@ var ts; error(parameterName, ts.Diagnostics.A_type_predicate_cannot_reference_a_rest_parameter); } else { - var leadingError = function () { return ts.chainDiagnosticMessages(undefined, ts.Diagnostics.A_type_predicate_s_type_must_be_assignable_to_its_parameter_s_type); }; - checkTypeAssignableTo(typePredicate.type, getTypeOfNode(parent.parameters[typePredicate.parameterIndex]), node.type, undefined, leadingError); + var leadingError = function () { return ts.chainDiagnosticMessages(/*details*/ undefined, ts.Diagnostics.A_type_predicate_s_type_must_be_assignable_to_its_parameter_s_type); }; + checkTypeAssignableTo(typePredicate.type, getTypeOfNode(parent.parameters[typePredicate.parameterIndex]), // TODO: GH#18217 + node.type, + /*headMessage*/ undefined, leadingError); } } else if (parameterName) { @@ -41567,13 +48412,13 @@ var ts; } function getTypePredicateParent(node) { switch (node.parent.kind) { - case 193: - case 158: - case 234: - case 192: - case 163: - case 154: - case 153: + case 193 /* ArrowFunction */: + case 158 /* CallSignature */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 163 /* FunctionType */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: var parent = node.parent; if (node === parent.type) { return parent; @@ -41587,11 +48432,11 @@ var ts; continue; } var name = element.name; - if (name.kind === 71 && name.escapedText === predicateVariableName) { + if (name.kind === 71 /* Identifier */ && name.escapedText === predicateVariableName) { error(predicateVariableNode, ts.Diagnostics.A_type_predicate_cannot_reference_element_0_in_a_binding_pattern, predicateVariableName); return true; } - else if (name.kind === 181 || name.kind === 180) { + else if (name.kind === 181 /* ArrayBindingPattern */ || name.kind === 180 /* ObjectBindingPattern */) { if (checkIfTypePredicateVariableIsDeclaredInBindingPattern(name, predicateVariableNode, predicateVariableName)) { return true; } @@ -41599,28 +48444,35 @@ var ts; } } function checkSignatureDeclaration(node) { - if (node.kind === 160) { + // Grammar checking + if (node.kind === 160 /* IndexSignature */) { checkGrammarIndexSignature(node); } - else if (node.kind === 163 || node.kind === 234 || node.kind === 164 || - node.kind === 158 || node.kind === 155 || - node.kind === 159) { + // TODO (yuisu): Remove this check in else-if when SyntaxKind.Construct is moved and ambient context is handled + else if (node.kind === 163 /* FunctionType */ || node.kind === 234 /* FunctionDeclaration */ || node.kind === 164 /* ConstructorType */ || + node.kind === 158 /* CallSignature */ || node.kind === 155 /* Constructor */ || + node.kind === 159 /* ConstructSignature */) { checkGrammarFunctionLikeDeclaration(node); } var functionFlags = ts.getFunctionFlags(node); - if (!(functionFlags & 4)) { - if ((functionFlags & 3) === 3 && languageVersion < 6) { - checkExternalEmitHelpers(node, 6144); + if (!(functionFlags & 4 /* Invalid */)) { + // Async generators prior to ESNext require the __await and __asyncGenerator helpers + if ((functionFlags & 3 /* AsyncGenerator */) === 3 /* AsyncGenerator */ && languageVersion < 6 /* ESNext */) { + checkExternalEmitHelpers(node, 6144 /* AsyncGeneratorIncludes */); } - if ((functionFlags & 3) === 2 && languageVersion < 4) { - checkExternalEmitHelpers(node, 64); + // Async functions prior to ES2017 require the __awaiter helper + if ((functionFlags & 3 /* AsyncGenerator */) === 2 /* Async */ && languageVersion < 4 /* ES2017 */) { + checkExternalEmitHelpers(node, 64 /* Awaiter */); } - if ((functionFlags & 3) !== 0 && languageVersion < 2) { - checkExternalEmitHelpers(node, 128); + // Generator functions, Async functions, and Async Generator functions prior to + // ES2015 require the __generator helper + if ((functionFlags & 3 /* AsyncGenerator */) !== 0 /* Normal */ && languageVersion < 2 /* ES2015 */) { + checkExternalEmitHelpers(node, 128 /* Generator */); } } checkTypeParameters(node.typeParameters); ts.forEach(node.parameters, checkParameter); + // TODO(rbuckton): Should we start checking JSDoc types? if (node.type) { checkSourceElement(node.type); } @@ -41629,34 +48481,40 @@ var ts; var returnTypeNode = ts.getEffectiveReturnTypeNode(node); if (noImplicitAny && !returnTypeNode) { switch (node.kind) { - case 159: + case 159 /* ConstructSignature */: error(node, ts.Diagnostics.Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type); break; - case 158: + case 158 /* CallSignature */: error(node, ts.Diagnostics.Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type); break; } } if (returnTypeNode) { var functionFlags_1 = ts.getFunctionFlags(node); - if ((functionFlags_1 & (4 | 1)) === 1) { + if ((functionFlags_1 & (4 /* Invalid */ | 1 /* Generator */)) === 1 /* Generator */) { var returnType = getTypeFromTypeNode(returnTypeNode); if (returnType === voidType) { error(returnTypeNode, ts.Diagnostics.A_generator_cannot_have_a_void_type_annotation); } else { - var generatorElementType = getIteratedTypeOfGenerator(returnType, (functionFlags_1 & 2) !== 0) || anyType; - var iterableIteratorInstantiation = functionFlags_1 & 2 - ? createAsyncIterableIteratorType(generatorElementType) - : createIterableIteratorType(generatorElementType); + var generatorElementType = getIteratedTypeOfGenerator(returnType, (functionFlags_1 & 2 /* Async */) !== 0) || anyType; + var iterableIteratorInstantiation = functionFlags_1 & 2 /* Async */ + ? createAsyncIterableIteratorType(generatorElementType) // AsyncGenerator function + : createIterableIteratorType(generatorElementType); // Generator function + // Naively, one could check that IterableIterator is assignable to the return type annotation. + // However, that would not catch the error in the following case. + // + // interface BadGenerator extends Iterable, Iterator { } + // function* g(): BadGenerator { } // Iterable and Iterator have different types! + // checkTypeAssignableTo(iterableIteratorInstantiation, returnType, returnTypeNode); } } - else if ((functionFlags_1 & 3) === 2) { + else if ((functionFlags_1 & 3 /* AsyncGenerator */) === 2 /* Async */) { checkAsyncFunctionReturnType(node); } } - if (node.kind !== 160 && node.kind !== 284) { + if (node.kind !== 160 /* IndexSignature */ && node.kind !== 284 /* JSDocFunctionType */) { registerForUnusedIdentifiersCheck(node); } } @@ -41673,32 +48531,32 @@ var ts; var staticNames = ts.createUnderscoreEscapedMap(); for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var member = _a[_i]; - if (member.kind === 155) { + if (member.kind === 155 /* Constructor */) { for (var _b = 0, _c = member.parameters; _b < _c.length; _b++) { var param = _c[_b]; if (ts.isParameterPropertyDeclaration(param) && !ts.isBindingPattern(param.name)) { - addName(instanceNames, param.name, param.name.escapedText, 3); + addName(instanceNames, param.name, param.name.escapedText, 3 /* Property */); } } } else { - var isStatic = ts.hasModifier(member, 32); + var isStatic = ts.hasModifier(member, 32 /* Static */); var names = isStatic ? staticNames : instanceNames; var name = member.name; var memberName = name && ts.getPropertyNameForPropertyNameNode(name); if (name && memberName) { switch (member.kind) { - case 156: - addName(names, name, memberName, 1); + case 156 /* GetAccessor */: + addName(names, name, memberName, 1 /* Getter */); break; - case 157: - addName(names, name, memberName, 2); + case 157 /* SetAccessor */: + addName(names, name, memberName, 2 /* Setter */); break; - case 152: - addName(names, name, memberName, 3); + case 152 /* PropertyDeclaration */: + addName(names, name, memberName, 3 /* Property */); break; - case 154: - addName(names, name, memberName, 4); + case 154 /* MethodDeclaration */: + addName(names, name, memberName, 4 /* Method */); break; } } @@ -41707,8 +48565,8 @@ var ts; function addName(names, location, name, meaning) { var prev = names.get(name); if (prev) { - if (prev & 4) { - if (meaning !== 4) { + if (prev & 4 /* Method */) { + if (meaning !== 4 /* Method */) { error(location, ts.Diagnostics.Duplicate_identifier_0, ts.getTextOfNode(location)); } } @@ -41724,11 +48582,22 @@ var ts; } } } + /** + * Static members being set on a constructor function may conflict with built-in properties + * of Function. Esp. in ECMAScript 5 there are non-configurable and non-writable + * built-in properties. This check issues a transpile error when a class has a static + * member with the same name as a non-writable built-in property. + * + * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.3 + * @see http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.5 + * @see http://www.ecma-international.org/ecma-262/6.0/#sec-properties-of-the-function-constructor + * @see http://www.ecma-international.org/ecma-262/6.0/#sec-function-instances + */ function checkClassForStaticPropertyNameConflicts(node) { for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var member = _a[_i]; var memberNameNode = member.name; - var isStatic = ts.hasModifier(member, 32); + var isStatic = ts.hasModifier(member, 32 /* Static */); if (isStatic && memberNameNode) { var memberName = ts.getPropertyNameForPropertyNameNode(memberNameNode); switch (memberName) { @@ -41749,15 +48618,15 @@ var ts; var names = ts.createMap(); for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var member = _a[_i]; - if (member.kind === 151) { + if (member.kind === 151 /* PropertySignature */) { var memberName = void 0; var name = member.name; switch (name.kind) { - case 9: - case 8: + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: memberName = name.text; break; - case 71: + case 71 /* Identifier */: memberName = ts.idText(name); break; default: @@ -41774,12 +48643,17 @@ var ts; } } function checkTypeForDuplicateIndexSignatures(node) { - if (node.kind === 236) { + if (node.kind === 236 /* InterfaceDeclaration */) { var nodeSymbol = getSymbolOfNode(node); + // in case of merging interface declaration it is possible that we'll enter this check procedure several times for every declaration + // to prevent this run check only for the first declaration of a given kind if (nodeSymbol.declarations.length > 0 && nodeSymbol.declarations[0] !== node) { return; } } + // TypeScript 1.0 spec (April 2014) + // 3.7.4: An object type can contain at most one string index signature and one numeric index signature. + // 8.5: A class declaration can have at most one string index member declaration and one numeric index member declaration var indexSymbol = getIndexSymbol(getSymbolOfNode(node)); if (indexSymbol) { var seenNumericIndexer = false; @@ -41789,7 +48663,7 @@ var ts; var declaration = decl; if (declaration.parameters.length === 1 && declaration.parameters[0].type) { switch (declaration.parameters[0].type.kind) { - case 137: + case 137 /* StringKeyword */: if (!seenStringIndexer) { seenStringIndexer = true; } @@ -41797,7 +48671,7 @@ var ts; error(declaration, ts.Diagnostics.Duplicate_string_index_signature); } break; - case 134: + case 134 /* NumberKeyword */: if (!seenNumericIndexer) { seenNumericIndexer = true; } @@ -41811,28 +48685,37 @@ var ts; } } function checkPropertyDeclaration(node) { + // Grammar checking if (!checkGrammarDecoratorsAndModifiers(node) && !checkGrammarProperty(node)) checkGrammarComputedPropertyName(node.name); checkVariableLikeDeclaration(node); } function checkMethodDeclaration(node) { + // Grammar checking if (!checkGrammarMethod(node)) checkGrammarComputedPropertyName(node.name); + // Grammar checking for modifiers is done inside the function checkGrammarFunctionLikeDeclaration checkFunctionOrMethodDeclaration(node); - if (ts.hasModifier(node, 128) && node.kind === 154 && node.body) { + // Abstract methods cannot have an implementation. + // Extra checks are to avoid reporting multiple errors relating to the "abstractness" of the node. + if (ts.hasModifier(node, 128 /* Abstract */) && node.kind === 154 /* MethodDeclaration */ && node.body) { error(node, ts.Diagnostics.Method_0_cannot_have_an_implementation_because_it_is_marked_abstract, ts.declarationNameToString(node.name)); } } function checkConstructorDeclaration(node) { + // Grammar check on signature of constructor and modifier of the constructor is done in checkSignatureDeclaration function. checkSignatureDeclaration(node); + // Grammar check for checking only related to constructorDeclaration if (!checkGrammarConstructorTypeParameters(node)) checkGrammarConstructorTypeAnnotation(node); checkSourceElement(node.body); var symbol = getSymbolOfNode(node); var firstDeclaration = ts.getDeclarationOfKind(symbol, node.kind); + // Only type check the symbol once if (node === firstDeclaration) { checkFunctionOrConstructorSymbol(symbol); } + // exit early in the case of signature - super checks are not relevant to them if (ts.nodeIsMissing(node.body)) { return; } @@ -41840,10 +48723,13 @@ var ts; return; } function isInstancePropertyWithInitializer(n) { - return n.kind === 152 && - !ts.hasModifier(n, 32) && + return n.kind === 152 /* PropertyDeclaration */ && + !ts.hasModifier(n, 32 /* Static */) && !!n.initializer; } + // TS 1.0 spec (April 2014): 8.3.2 + // Constructors of classes with no extends clause may not contain super calls, whereas + // constructors of derived classes must contain at least one super call somewhere in their function body. var containingClassDecl = node.parent; if (ts.getClassExtendsHeritageClauseElement(containingClassDecl)) { captureLexicalThis(node.parent, containingClassDecl); @@ -41853,14 +48739,21 @@ var ts; if (classExtendsNull) { error(superCall, ts.Diagnostics.A_constructor_cannot_contain_a_super_call_when_its_class_extends_null); } + // The first statement in the body of a constructor (excluding prologue directives) must be a super call + // if both of the following are true: + // - The containing class is a derived class. + // - The constructor declares parameter properties + // or the containing class declares instance member variables with initializers. var superCallShouldBeFirst = ts.some(node.parent.members, isInstancePropertyWithInitializer) || - ts.some(node.parameters, function (p) { return ts.hasModifier(p, 92); }); + ts.some(node.parameters, function (p) { return ts.hasModifier(p, 92 /* ParameterPropertyModifier */); }); + // Skip past any prologue directives to find the first statement + // to ensure that it was a super call. if (superCallShouldBeFirst) { var statements = node.body.statements; var superCallStatement = void 0; for (var _i = 0, statements_2 = statements; _i < statements_2.length; _i++) { var statement = statements_2[_i]; - if (statement.kind === 216 && ts.isSuperCall(statement.expression)) { + if (statement.kind === 216 /* ExpressionStatement */ && ts.isSuperCall(statement.expression)) { superCallStatement = statement; break; } @@ -41880,38 +48773,46 @@ var ts; } function checkAccessorDeclaration(node) { if (produceDiagnostics) { + // Grammar checking accessors if (!checkGrammarFunctionLikeDeclaration(node) && !checkGrammarAccessor(node)) checkGrammarComputedPropertyName(node.name); checkDecorators(node); checkSignatureDeclaration(node); - if (node.kind === 156) { - if (!(node.flags & 4194304) && ts.nodeIsPresent(node.body) && (node.flags & 128)) { - if (!(node.flags & 256)) { + if (node.kind === 156 /* GetAccessor */) { + if (!(node.flags & 4194304 /* Ambient */) && ts.nodeIsPresent(node.body) && (node.flags & 128 /* HasImplicitReturn */)) { + if (!(node.flags & 256 /* HasExplicitReturn */)) { error(node.name, ts.Diagnostics.A_get_accessor_must_return_a_value); } } } - if (node.name.kind === 147) { + // Do not use hasDynamicName here, because that returns false for well known symbols. + // We want to perform checkComputedPropertyName for all computed properties, including + // well known symbols. + if (node.name.kind === 147 /* ComputedPropertyName */) { checkComputedPropertyName(node.name); } if (!hasNonBindableDynamicName(node)) { - var otherKind = node.kind === 156 ? 157 : 156; + // TypeScript 1.0 spec (April 2014): 8.4.3 + // Accessors for the same member name must specify the same accessibility. + var otherKind = node.kind === 156 /* GetAccessor */ ? 157 /* SetAccessor */ : 156 /* GetAccessor */; var otherAccessor = ts.getDeclarationOfKind(getSymbolOfNode(node), otherKind); if (otherAccessor) { var nodeFlags = ts.getModifierFlags(node); var otherFlags = ts.getModifierFlags(otherAccessor); - if ((nodeFlags & 28) !== (otherFlags & 28)) { + if ((nodeFlags & 28 /* AccessibilityModifier */) !== (otherFlags & 28 /* AccessibilityModifier */)) { error(node.name, ts.Diagnostics.Getter_and_setter_accessors_do_not_agree_in_visibility); } - if ((nodeFlags & 128) !== (otherFlags & 128)) { + if ((nodeFlags & 128 /* Abstract */) !== (otherFlags & 128 /* Abstract */)) { error(node.name, ts.Diagnostics.Accessors_must_both_be_abstract_or_non_abstract); } + // TypeScript 1.0 spec (April 2014): 4.5 + // If both accessors include type annotations, the specified types must be identical. checkAccessorDeclarationTypesIdentical(node, otherAccessor, getAnnotatedAccessorType, ts.Diagnostics.get_and_set_accessor_must_have_the_same_type); checkAccessorDeclarationTypesIdentical(node, otherAccessor, getThisTypeOfDeclaration, ts.Diagnostics.get_and_set_accessor_must_have_the_same_this_type); } } var returnType = getTypeOfAccessors(getSymbolOfNode(node)); - if (node.kind === 156) { + if (node.kind === 156 /* GetAccessor */) { checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnType); } } @@ -41951,20 +48852,21 @@ var ts; if (type !== errorType) { var symbol = getNodeLinks(node).resolvedSymbol; if (symbol) { - return symbol.flags & 524288 && getSymbolLinks(symbol).typeParameters || - (ts.getObjectFlags(type) & 4 ? type.target.localTypeParameters : undefined); + return symbol.flags & 524288 /* TypeAlias */ && getSymbolLinks(symbol).typeParameters || + (ts.getObjectFlags(type) & 4 /* Reference */ ? type.target.localTypeParameters : undefined); } } return undefined; } function checkTypeReferenceNode(node) { checkGrammarTypeArguments(node, node.typeArguments); - if (node.kind === 162 && node.typeName.jsdocDotPos !== undefined && !ts.isInJavaScriptFile(node) && !ts.isInJSDoc(node)) { + if (node.kind === 162 /* TypeReference */ && node.typeName.jsdocDotPos !== undefined && !ts.isInJavaScriptFile(node) && !ts.isInJSDoc(node)) { grammarErrorAtPos(node, node.typeName.jsdocDotPos, 1, ts.Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments); } var type = getTypeFromTypeReference(node); if (type !== errorType) { if (node.typeArguments) { + // Do type argument local checks only if referenced type is successfully resolved ts.forEach(node.typeArguments, checkSourceElement); if (produceDiagnostics) { var typeParameters = getTypeParametersForTypeReference(node); @@ -41973,7 +48875,7 @@ var ts; } } } - if (type.flags & 32 && getNodeLinks(node).resolvedSymbol.flags & 8) { + if (type.flags & 32 /* Enum */ && getNodeLinks(node).resolvedSymbol.flags & 8 /* EnumMember */) { error(node, ts.Diagnostics.Enum_type_0_has_members_with_initializers_that_are_not_literals, typeToString(type)); } } @@ -41982,7 +48884,7 @@ var ts; var typeReferenceNode = ts.tryCast(node.parent, ts.isTypeReferenceType); if (!typeReferenceNode) return undefined; - var typeParameters = getTypeParametersForTypeReference(typeReferenceNode); + var typeParameters = getTypeParametersForTypeReference(typeReferenceNode); // TODO: GH#18217 var constraint = getConstraintOfTypeParameter(typeParameters[typeReferenceNode.typeArguments.indexOf(node)]); return constraint && instantiateType(constraint, createTypeMapper(typeParameters, getEffectiveTypeArguments(typeReferenceNode, typeParameters))); } @@ -42002,6 +48904,7 @@ var ts; checkSourceElement(node.elementType); } function checkTupleType(node) { + // Grammar checking var hasErrorFromDisallowedTrailingComma = checkGrammarForDisallowedTrailingComma(node.elementTypes); if (!hasErrorFromDisallowedTrailingComma && node.elementTypes.length === 0) { grammarErrorOnNode(node, ts.Diagnostics.A_tuple_type_element_list_cannot_be_empty); @@ -42012,19 +48915,22 @@ var ts; ts.forEach(node.types, checkSourceElement); } function checkIndexedAccessIndexType(type, accessNode) { - if (!(type.flags & 2097152)) { + if (!(type.flags & 2097152 /* IndexedAccess */)) { return type; } + // Check if the index type is assignable to 'keyof T' for the object type. var objectType = type.objectType; var indexType = type.indexType; - if (isTypeAssignableTo(indexType, getIndexType(objectType, false))) { - if (accessNode.kind === 186 && ts.isAssignmentTarget(accessNode) && - ts.getObjectFlags(objectType) & 32 && getMappedTypeModifiers(objectType) & 1) { + if (isTypeAssignableTo(indexType, getIndexType(objectType, /*stringsOnly*/ false))) { + if (accessNode.kind === 186 /* ElementAccessExpression */ && ts.isAssignmentTarget(accessNode) && + ts.getObjectFlags(objectType) & 32 /* Mapped */ && getMappedTypeModifiers(objectType) & 1 /* IncludeReadonly */) { error(accessNode, ts.Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(objectType)); } return type; } - if (getIndexInfoOfType(getApparentType(objectType), 1) && isTypeAssignableToKind(indexType, 168)) { + // Check if we're indexing with a numeric type and if either object or index types + // is a generic type with a constraint that has a numeric index signature. + if (getIndexInfoOfType(getApparentType(objectType), 1 /* Number */) && isTypeAssignableToKind(indexType, 168 /* NumberLike */)) { return type; } error(accessNode, ts.Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(objectType)); @@ -42053,7 +48959,7 @@ var ts; ts.forEachChild(node, checkSourceElement); } function checkInferType(node) { - if (!ts.findAncestor(node, function (n) { return n.parent && n.parent.kind === 171 && n.parent.extendsType === n; })) { + if (!ts.findAncestor(node, function (n) { return n.parent && n.parent.kind === 171 /* ConditionalType */ && n.parent.extendsType === n; })) { grammarErrorOnNode(node, ts.Diagnostics.infer_declarations_are_only_permitted_in_the_extends_clause_of_a_conditional_type); } checkSourceElement(node.typeParameter); @@ -42063,18 +48969,21 @@ var ts; getTypeFromTypeNode(node); } function isPrivateWithinAmbient(node) { - return ts.hasModifier(node, 8) && !!(node.flags & 4194304); + return ts.hasModifier(node, 8 /* Private */) && !!(node.flags & 4194304 /* Ambient */); } function getEffectiveDeclarationFlags(n, flagsToCheck) { var flags = ts.getCombinedModifierFlags(n); - if (n.parent.kind !== 236 && - n.parent.kind !== 235 && - n.parent.kind !== 205 && - n.flags & 4194304) { - if (!(flags & 2) && !(ts.isModuleBlock(n.parent) && ts.isModuleDeclaration(n.parent.parent) && ts.isGlobalScopeAugmentation(n.parent.parent))) { - flags |= 1; + // children of classes (even ambient classes) should not be marked as ambient or export + // because those flags have no useful semantics there. + if (n.parent.kind !== 236 /* InterfaceDeclaration */ && + n.parent.kind !== 235 /* ClassDeclaration */ && + n.parent.kind !== 205 /* ClassExpression */ && + n.flags & 4194304 /* Ambient */) { + if (!(flags & 2 /* Ambient */) && !(ts.isModuleBlock(n.parent) && ts.isModuleDeclaration(n.parent.parent) && ts.isGlobalScopeAugmentation(n.parent.parent))) { + // It is nested in an ambient context, which means it is automatically exported + flags |= 1 /* Export */; } - flags |= 2; + flags |= 2 /* Ambient */; } return flags & flagsToCheck; } @@ -42083,25 +48992,32 @@ var ts; return; } function getCanonicalOverload(overloads, implementation) { + // Consider the canonical set of flags to be the flags of the bodyDeclaration or the first declaration + // Error on all deviations from this canonical set of flags + // The caveat is that if some overloads are defined in lib.d.ts, we don't want to + // report the errors on those. To achieve this, we will say that the implementation is + // the canonical signature only if it is in the same container as the first overload var implementationSharesContainerWithFirstOverload = implementation !== undefined && implementation.parent === overloads[0].parent; return implementationSharesContainerWithFirstOverload ? implementation : overloads[0]; } function checkFlagAgreementBetweenOverloads(overloads, implementation, flagsToCheck, someOverloadFlags, allOverloadFlags) { + // Error if some overloads have a flag that is not shared by all overloads. To find the + // deviations, we XOR someOverloadFlags with allOverloadFlags var someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags; if (someButNotAllOverloadFlags !== 0) { var canonicalFlags_1 = getEffectiveDeclarationFlags(getCanonicalOverload(overloads, implementation), flagsToCheck); ts.forEach(overloads, function (o) { var deviation = getEffectiveDeclarationFlags(o, flagsToCheck) ^ canonicalFlags_1; - if (deviation & 1) { + if (deviation & 1 /* Export */) { error(ts.getNameOfDeclaration(o), ts.Diagnostics.Overload_signatures_must_all_be_exported_or_non_exported); } - else if (deviation & 2) { + else if (deviation & 2 /* Ambient */) { error(ts.getNameOfDeclaration(o), ts.Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient); } - else if (deviation & (8 | 16)) { + else if (deviation & (8 /* Private */ | 16 /* Protected */)) { error(ts.getNameOfDeclaration(o) || o, ts.Diagnostics.Overload_signatures_must_all_be_public_private_or_protected); } - else if (deviation & 128) { + else if (deviation & 128 /* Abstract */) { error(ts.getNameOfDeclaration(o), ts.Diagnostics.Overload_signatures_must_all_be_abstract_or_non_abstract); } }); @@ -42118,8 +49034,8 @@ var ts; }); } } - var flagsToCheck = 1 | 2 | 8 | 16 | 128; - var someNodeFlags = 0; + var flagsToCheck = 1 /* Export */ | 2 /* Ambient */ | 8 /* Private */ | 16 /* Protected */ | 128 /* Abstract */; + var someNodeFlags = 0 /* None */; var allNodeFlags = flagsToCheck; var someHaveQuestionToken = false; var allHaveQuestionToken = true; @@ -42128,7 +49044,7 @@ var ts; var lastSeenNonAmbientDeclaration; var previousDeclaration; var declarations = symbol.declarations; - var isConstructor = (symbol.flags & 16384) !== 0; + var isConstructor = (symbol.flags & 16384 /* Constructor */) !== 0; function reportImplementationExpectedError(node) { if (node.name && ts.nodeIsMissing(node.name)) { return; @@ -42142,17 +49058,24 @@ var ts; seen = c === node; } }); + // We may be here because of some extra nodes between overloads that could not be parsed into a valid node. + // In this case the subsequent node is not really consecutive (.pos !== node.end), and we must ignore it here. if (subsequentNode && subsequentNode.pos === node.end) { if (subsequentNode.kind === node.kind) { var errorNode_1 = subsequentNode.name || subsequentNode; + // TODO: GH#17345: These are methods, so handle computed name case. (`Always allowing computed property names is *not* the correct behavior!) var subsequentName = subsequentNode.name; if (node.name && subsequentName && (ts.isComputedPropertyName(node.name) && ts.isComputedPropertyName(subsequentName) || !ts.isComputedPropertyName(node.name) && !ts.isComputedPropertyName(subsequentName) && ts.getEscapedTextOfIdentifierOrLiteral(node.name) === ts.getEscapedTextOfIdentifierOrLiteral(subsequentName))) { - var reportError = (node.kind === 154 || node.kind === 153) && - ts.hasModifier(node, 32) !== ts.hasModifier(subsequentNode, 32); + var reportError = (node.kind === 154 /* MethodDeclaration */ || node.kind === 153 /* MethodSignature */) && + ts.hasModifier(node, 32 /* Static */) !== ts.hasModifier(subsequentNode, 32 /* Static */); + // we can get here in two cases + // 1. mixed static and instance class members + // 2. something with the same name was defined before the set of overloads that prevents them from merging + // here we'll report error only for the first case since for second we should already report error in binder if (reportError) { - var diagnostic = ts.hasModifier(node, 32) ? ts.Diagnostics.Function_overload_must_be_static : ts.Diagnostics.Function_overload_must_not_be_static; + var diagnostic = ts.hasModifier(node, 32 /* Static */) ? ts.Diagnostics.Function_overload_must_be_static : ts.Diagnostics.Function_overload_must_not_be_static; error(errorNode_1, diagnostic); } return; @@ -42168,7 +49091,9 @@ var ts; error(errorNode, ts.Diagnostics.Constructor_implementation_is_missing); } else { - if (ts.hasModifier(node, 128)) { + // Report different errors regarding non-consecutive blocks of declarations depending on whether + // the node in question is abstract. + if (ts.hasModifier(node, 128 /* Abstract */)) { error(errorNode, ts.Diagnostics.All_declarations_of_an_abstract_method_must_be_consecutive); } else { @@ -42181,12 +49106,19 @@ var ts; for (var _i = 0, declarations_4 = declarations; _i < declarations_4.length; _i++) { var current = declarations_4[_i]; var node = current; - var inAmbientContext = node.flags & 4194304; - var inAmbientContextOrInterface = node.parent.kind === 236 || node.parent.kind === 166 || inAmbientContext; + var inAmbientContext = node.flags & 4194304 /* Ambient */; + var inAmbientContextOrInterface = node.parent.kind === 236 /* InterfaceDeclaration */ || node.parent.kind === 166 /* TypeLiteral */ || inAmbientContext; if (inAmbientContextOrInterface) { + // check if declarations are consecutive only if they are non-ambient + // 1. ambient declarations can be interleaved + // i.e. this is legal + // declare function foo(); + // declare function bar(); + // declare function foo(); + // 2. mixing ambient and non-ambient declarations is a separate error that will be reported - do not want to report an extra one previousDeclaration = undefined; } - if (node.kind === 234 || node.kind === 154 || node.kind === 153 || node.kind === 155) { + if (node.kind === 234 /* FunctionDeclaration */ || node.kind === 154 /* MethodDeclaration */ || node.kind === 153 /* MethodSignature */ || node.kind === 155 /* Constructor */) { var currentNodeFlags = getEffectiveDeclarationFlags(node, flagsToCheck); someNodeFlags |= currentNodeFlags; allNodeFlags &= currentNodeFlags; @@ -42227,8 +49159,9 @@ var ts; error(ts.getNameOfDeclaration(declaration), ts.Diagnostics.Duplicate_function_implementation); }); } + // Abstract methods can't have an implementation -- in particular, they don't need one. if (lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body && - !ts.hasModifier(lastSeenNonAmbientDeclaration, 128) && !lastSeenNonAmbientDeclaration.questionToken) { + !ts.hasModifier(lastSeenNonAmbientDeclaration, 128 /* Abstract */) && !lastSeenNonAmbientDeclaration.questionToken) { reportImplementationExpectedError(lastSeenNonAmbientDeclaration); } if (hasOverloads) { @@ -42251,25 +49184,30 @@ var ts; if (!produceDiagnostics) { return; } + // if localSymbol is defined on node then node itself is exported - check is required var symbol = node.localSymbol; if (!symbol) { + // local symbol is undefined => this declaration is non-exported. + // however symbol might contain other declarations that are exported symbol = getSymbolOfNode(node); if (!symbol.exportSymbol) { + // this is a pure local symbol (all declarations are non-exported) - no need to check anything return; } } + // run the check only for the first declaration in the list if (ts.getDeclarationOfKind(symbol, node.kind) !== node) { return; } - var exportedDeclarationSpaces = 0; - var nonExportedDeclarationSpaces = 0; - var defaultExportedDeclarationSpaces = 0; + var exportedDeclarationSpaces = 0 /* None */; + var nonExportedDeclarationSpaces = 0 /* None */; + var defaultExportedDeclarationSpaces = 0 /* None */; for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var d = _a[_i]; var declarationSpaces = getDeclarationSpaces(d); - var effectiveDeclarationFlags = getEffectiveDeclarationFlags(d, 1 | 512); - if (effectiveDeclarationFlags & 1) { - if (effectiveDeclarationFlags & 512) { + var effectiveDeclarationFlags = getEffectiveDeclarationFlags(d, 1 /* Export */ | 512 /* Default */); + if (effectiveDeclarationFlags & 1 /* Export */) { + if (effectiveDeclarationFlags & 512 /* Default */) { defaultExportedDeclarationSpaces |= declarationSpaces; } else { @@ -42280,14 +49218,17 @@ var ts; nonExportedDeclarationSpaces |= declarationSpaces; } } + // Spaces for anything not declared a 'default export'. var nonDefaultExportedDeclarationSpaces = exportedDeclarationSpaces | nonExportedDeclarationSpaces; var commonDeclarationSpacesForExportsAndLocals = exportedDeclarationSpaces & nonExportedDeclarationSpaces; var commonDeclarationSpacesForDefaultAndNonDefault = defaultExportedDeclarationSpaces & nonDefaultExportedDeclarationSpaces; if (commonDeclarationSpacesForExportsAndLocals || commonDeclarationSpacesForDefaultAndNonDefault) { + // declaration spaces for exported and non-exported declarations intersect for (var _b = 0, _c = symbol.declarations; _b < _c.length; _b++) { var d = _c[_b]; var declarationSpaces = getDeclarationSpaces(d); var name = ts.getNameOfDeclaration(d); + // Only error on the declarations that contributed to the intersecting spaces. if (declarationSpaces & commonDeclarationSpacesForDefaultAndNonDefault) { error(name, ts.Diagnostics.Merged_declaration_0_cannot_include_a_default_export_declaration_Consider_adding_a_separate_export_default_0_declaration_instead, ts.declarationNameToString(name)); } @@ -42306,37 +49247,41 @@ var ts; function getDeclarationSpaces(decl) { var d = decl; switch (d.kind) { - case 236: - case 237: - case 298: - case 292: - return 2; - case 239: - return ts.isAmbientModule(d) || ts.getModuleInstanceState(d) !== 0 - ? 4 | 1 - : 4; - case 235: - case 238: - return 2 | 1; - case 274: - return 2 | 1 | 4; - case 249: + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: + // A jsdoc typedef and callback are, by definition, type aliases + case 298 /* JSDocTypedefTag */: + case 292 /* JSDocCallbackTag */: + return 2 /* ExportType */; + case 239 /* ModuleDeclaration */: + return ts.isAmbientModule(d) || ts.getModuleInstanceState(d) !== 0 /* NonInstantiated */ + ? 4 /* ExportNamespace */ | 1 /* ExportValue */ + : 4 /* ExportNamespace */; + case 235 /* ClassDeclaration */: + case 238 /* EnumDeclaration */: + return 2 /* ExportType */ | 1 /* ExportValue */; + case 274 /* SourceFile */: + return 2 /* ExportType */ | 1 /* ExportValue */ | 4 /* ExportNamespace */; + case 249 /* ExportAssignment */: + // Export assigned entity name expressions act as aliases and should fall through, otherwise they export values if (!ts.isEntityNameExpression(d.expression)) { - return 1; + return 1 /* ExportValue */; } d = d.expression; - case 243: - case 246: - case 245: - var result_3 = 0; + /* falls through */ + // The below options all declare an Alias, which is allowed to merge with other values within the importing module + case 243 /* ImportEqualsDeclaration */: + case 246 /* NamespaceImport */: + case 245 /* ImportClause */: + var result_3 = 0 /* None */; var target = resolveAlias(getSymbolOfNode(d)); ts.forEach(target.declarations, function (d) { result_3 |= getDeclarationSpaces(d); }); return result_3; - case 232: - case 182: - case 234: - case 248: - return 1; + case 232 /* VariableDeclaration */: + case 182 /* BindingElement */: + case 234 /* FunctionDeclaration */: + case 248 /* ImportSpecifier */: // https://github.com/Microsoft/TypeScript/pull/7591 + return 1 /* ExportValue */; default: return ts.Debug.fail(ts.Debug.showSyntaxKind(d)); } @@ -42346,7 +49291,21 @@ var ts; var promisedType = getPromisedTypeOfPromise(type, errorNode); return promisedType && getAwaitedType(promisedType, errorNode, diagnosticMessage); } + /** + * Gets the "promised type" of a promise. + * @param type The type of the promise. + * @remarks The "promised type" of a type is the type of the "value" parameter of the "onfulfilled" callback. + */ function getPromisedTypeOfPromise(promise, errorNode) { + // + // { // promise + // then( // thenFunction + // onfulfilled: ( // onfulfilledParameterType + // value: T // valueParameterType + // ) => any + // ): any; + // } + // if (isTypeAny(promise)) { return undefined; } @@ -42354,33 +49313,40 @@ var ts; if (typeAsPromise.promisedTypeOfPromise) { return typeAsPromise.promisedTypeOfPromise; } - if (isReferenceToType(promise, getGlobalPromiseType(false))) { + if (isReferenceToType(promise, getGlobalPromiseType(/*reportErrors*/ false))) { return typeAsPromise.promisedTypeOfPromise = promise.typeArguments[0]; } - var thenFunction = getTypeOfPropertyOfType(promise, "then"); + var thenFunction = getTypeOfPropertyOfType(promise, "then"); // TODO: GH#18217 if (isTypeAny(thenFunction)) { return undefined; } - var thenSignatures = thenFunction ? getSignaturesOfType(thenFunction, 0) : ts.emptyArray; + var thenSignatures = thenFunction ? getSignaturesOfType(thenFunction, 0 /* Call */) : ts.emptyArray; if (thenSignatures.length === 0) { if (errorNode) { error(errorNode, ts.Diagnostics.A_promise_must_have_a_then_method); } return undefined; } - var onfulfilledParameterType = getTypeWithFacts(getUnionType(ts.map(thenSignatures, getTypeOfFirstParameterOfSignature)), 524288); + var onfulfilledParameterType = getTypeWithFacts(getUnionType(ts.map(thenSignatures, getTypeOfFirstParameterOfSignature)), 524288 /* NEUndefinedOrNull */); if (isTypeAny(onfulfilledParameterType)) { return undefined; } - var onfulfilledParameterSignatures = getSignaturesOfType(onfulfilledParameterType, 0); + var onfulfilledParameterSignatures = getSignaturesOfType(onfulfilledParameterType, 0 /* Call */); if (onfulfilledParameterSignatures.length === 0) { if (errorNode) { error(errorNode, ts.Diagnostics.The_first_parameter_of_the_then_method_of_a_promise_must_be_a_callback); } return undefined; } - return typeAsPromise.promisedTypeOfPromise = getUnionType(ts.map(onfulfilledParameterSignatures, getTypeOfFirstParameterOfSignature), 2); + return typeAsPromise.promisedTypeOfPromise = getUnionType(ts.map(onfulfilledParameterSignatures, getTypeOfFirstParameterOfSignature), 2 /* Subtype */); } + /** + * Gets the "awaited type" of a type. + * @param type The type to await. + * @remarks The "awaited type" of an expression is its "promised type" if the expression is a + * Promise-like type; otherwise, it is the type of the expression. This is used to reflect + * The runtime behavior of the `await` keyword. + */ function checkAwaitedType(type, errorNode, diagnosticMessage) { return getAwaitedType(type, errorNode, diagnosticMessage) || errorType; } @@ -42392,7 +49358,7 @@ var ts; if (isTypeAny(type)) { return typeAsAwaitable.awaitedTypeOfType = type; } - if (type.flags & 262144) { + if (type.flags & 262144 /* Union */) { var types = void 0; for (var _i = 0, _a = type.types; _i < _a.length; _i++) { var constituentType = _a[_i]; @@ -42406,11 +49372,45 @@ var ts; var promisedType = getPromisedTypeOfPromise(type); if (promisedType) { if (type.id === promisedType.id || awaitedTypeStack.indexOf(promisedType.id) >= 0) { + // Verify that we don't have a bad actor in the form of a promise whose + // promised type is the same as the promise type, or a mutually recursive + // promise. If so, we return undefined as we cannot guess the shape. If this + // were the actual case in the JavaScript, this Promise would never resolve. + // + // An example of a bad actor with a singly-recursive promise type might + // be: + // + // interface BadPromise { + // then( + // onfulfilled: (value: BadPromise) => any, + // onrejected: (error: any) => any): BadPromise; + // } + // The above interface will pass the PromiseLike check, and return a + // promised type of `BadPromise`. Since this is a self reference, we + // don't want to keep recursing ad infinitum. + // + // An example of a bad actor in the form of a mutually-recursive + // promise type might be: + // + // interface BadPromiseA { + // then( + // onfulfilled: (value: BadPromiseB) => any, + // onrejected: (error: any) => any): BadPromiseB; + // } + // + // interface BadPromiseB { + // then( + // onfulfilled: (value: BadPromiseA) => any, + // onrejected: (error: any) => any): BadPromiseA; + // } + // if (errorNode) { error(errorNode, ts.Diagnostics.Type_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method); } return undefined; } + // Keep track of the type we're about to unwrap to avoid bad recursive promise types. + // See the comments above for more information. awaitedTypeStack.push(type.id); var awaitedType = getAwaitedType(promisedType, errorNode, diagnosticMessage); awaitedTypeStack.pop(); @@ -42419,8 +49419,23 @@ var ts; } return typeAsAwaitable.awaitedTypeOfType = awaitedType; } + // The type was not a promise, so it could not be unwrapped any further. + // As long as the type does not have a callable "then" property, it is + // safe to return the type; otherwise, an error will be reported in + // the call to getNonThenableType and we will return undefined. + // + // An example of a non-promise "thenable" might be: + // + // await { then(): void {} } + // + // The "thenable" does not match the minimal definition for a promise. When + // a Promise/A+-compatible or ES6 promise tries to adopt this value, the promise + // will never settle. We treat this as an error to help flag an early indicator + // of a runtime problem. If the user wants to return this value from an async + // function, they would need to wrap it in some other value. If they want it to + // be treated as a promise, they can cast to . var thenFunction = getTypeOfPropertyOfType(type, "then"); - if (thenFunction && getSignaturesOfType(thenFunction, 0).length > 0) { + if (thenFunction && getSignaturesOfType(thenFunction, 0 /* Call */).length > 0) { if (errorNode) { if (!diagnosticMessage) return ts.Debug.fail(); @@ -42430,20 +49445,60 @@ var ts; } return typeAsAwaitable.awaitedTypeOfType = type; } + /** + * Checks the return type of an async function to ensure it is a compatible + * Promise implementation. + * + * This checks that an async function has a valid Promise-compatible return type, + * and returns the *awaited type* of the promise. An async function has a valid + * Promise-compatible return type if the resolved value of the return type has a + * construct signature that takes in an `initializer` function that in turn supplies + * a `resolve` function as one of its arguments and results in an object with a + * callable `then` signature. + * + * @param node The signature to check + */ function checkAsyncFunctionReturnType(node) { - var returnTypeNode = ts.getEffectiveReturnTypeNode(node); + // As part of our emit for an async function, we will need to emit the entity name of + // the return type annotation as an expression. To meet the necessary runtime semantics + // for __awaiter, we must also check that the type of the declaration (e.g. the static + // side or "constructor" of the promise type) is compatible `PromiseConstructorLike`. + // + // An example might be (from lib.es6.d.ts): + // + // interface Promise { ... } + // interface PromiseConstructor { + // new (...): Promise; + // } + // declare var Promise: PromiseConstructor; + // + // When an async function declares a return type annotation of `Promise`, we + // need to get the type of the `Promise` variable declaration above, which would + // be `PromiseConstructor`. + // + // The same case applies to a class: + // + // declare class Promise { + // constructor(...); + // then(...): Promise; + // } + // + var returnTypeNode = ts.getEffectiveReturnTypeNode(node); // TODO: GH#18217 var returnType = getTypeFromTypeNode(returnTypeNode); - if (languageVersion >= 2) { + if (languageVersion >= 2 /* ES2015 */) { if (returnType === errorType) { return errorType; } - var globalPromiseType = getGlobalPromiseType(true); + var globalPromiseType = getGlobalPromiseType(/*reportErrors*/ true); if (globalPromiseType !== emptyGenericType && !isReferenceToType(returnType, globalPromiseType)) { + // The promise type was not a valid type reference to the global promise type, so we + // report an error and return the unknown type. error(returnTypeNode, ts.Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type); return errorType; } } else { + // Always mark the type node as referenced if it points to a value markTypeNodeAsReferenced(returnTypeNode); if (returnType === errorType) { return errorType; @@ -42453,10 +49508,10 @@ var ts; error(returnTypeNode, ts.Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, typeToString(returnType)); return errorType; } - var promiseConstructorSymbol = resolveEntityName(promiseConstructorName, 67216319, true); + var promiseConstructorSymbol = resolveEntityName(promiseConstructorName, 67216319 /* Value */, /*ignoreErrors*/ true); var promiseConstructorType = promiseConstructorSymbol ? getTypeOfSymbol(promiseConstructorSymbol) : errorType; if (promiseConstructorType === errorType) { - if (promiseConstructorName.kind === 71 && promiseConstructorName.escapedText === "Promise" && getTargetType(returnType) === getGlobalPromiseType(false)) { + if (promiseConstructorName.kind === 71 /* Identifier */ && promiseConstructorName.escapedText === "Promise" && getTargetType(returnType) === getGlobalPromiseType(/*reportErrors*/ false)) { error(returnTypeNode, ts.Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option); } else { @@ -42464,50 +49519,57 @@ var ts; } return errorType; } - var globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType(true); + var globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType(/*reportErrors*/ true); if (globalPromiseConstructorLikeType === emptyObjectType) { + // If we couldn't resolve the global PromiseConstructorLike type we cannot verify + // compatibility with __awaiter. error(returnTypeNode, ts.Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, ts.entityNameToString(promiseConstructorName)); return errorType; } if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, returnTypeNode, ts.Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value)) { return errorType; } + // Verify there is no local declaration that could collide with the promise constructor. var rootName = promiseConstructorName && getFirstIdentifier(promiseConstructorName); - var collidingSymbol = getSymbol(node.locals, rootName.escapedText, 67216319); + var collidingSymbol = getSymbol(node.locals, rootName.escapedText, 67216319 /* Value */); if (collidingSymbol) { error(collidingSymbol.valueDeclaration, ts.Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions, ts.idText(rootName), ts.entityNameToString(promiseConstructorName)); return errorType; } } + // Get and return the awaited type of the return type. return checkAwaitedType(returnType, node, ts.Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); } + /** Check a decorator */ function checkDecorator(node) { var signature = getResolvedSignature(node); var returnType = getReturnTypeOfSignature(signature); - if (returnType.flags & 1) { + if (returnType.flags & 1 /* Any */) { return; } var expectedReturnType; var headMessage = getDiagnosticHeadMessageForDecoratorResolution(node); var errorInfo; switch (node.parent.kind) { - case 235: + case 235 /* ClassDeclaration */: var classSymbol = getSymbolOfNode(node.parent); var classConstructorType = getTypeOfSymbol(classSymbol); expectedReturnType = getUnionType([classConstructorType, voidType]); break; - case 149: + case 149 /* Parameter */: expectedReturnType = voidType; - errorInfo = ts.chainDiagnosticMessages(undefined, ts.Diagnostics.The_return_type_of_a_parameter_decorator_function_must_be_either_void_or_any); + errorInfo = ts.chainDiagnosticMessages( + /*details*/ undefined, ts.Diagnostics.The_return_type_of_a_parameter_decorator_function_must_be_either_void_or_any); break; - case 152: + case 152 /* PropertyDeclaration */: expectedReturnType = voidType; - errorInfo = ts.chainDiagnosticMessages(undefined, ts.Diagnostics.The_return_type_of_a_property_decorator_function_must_be_either_void_or_any); + errorInfo = ts.chainDiagnosticMessages( + /*details*/ undefined, ts.Diagnostics.The_return_type_of_a_property_decorator_function_must_be_either_void_or_any); break; - case 154: - case 156: - case 157: - var methodType = getTypeOfNode(node.parent); + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + var methodType = getTypeOfNode(node.parent); // TODO: GH#18217 var descriptorType = createTypedPropertyDescriptorType(methodType); expectedReturnType = getUnionType([descriptorType, voidType]); break; @@ -42516,6 +49578,10 @@ var ts; } checkTypeAssignableTo(returnType, expectedReturnType, node, headMessage, function () { return errorInfo; }); } + /** + * If a TypeNode can be resolved to a value symbol imported from an external module, it is + * marked as referenced to prevent import elision. + */ function markTypeNodeAsReferenced(node) { markEntityNameOrEntityExpressionAsReference(node && ts.getEntityNameFromTypeNode(node)); } @@ -42523,15 +49589,22 @@ var ts; if (!typeName) return; var rootName = getFirstIdentifier(typeName); - var meaning = (typeName.kind === 71 ? 67901928 : 1920) | 2097152; - var rootSymbol = resolveName(rootName, rootName.escapedText, meaning, undefined, undefined, true); + var meaning = (typeName.kind === 71 /* Identifier */ ? 67901928 /* Type */ : 1920 /* Namespace */) | 2097152 /* Alias */; + var rootSymbol = resolveName(rootName, rootName.escapedText, meaning, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isRefernce*/ true); if (rootSymbol - && rootSymbol.flags & 2097152 + && rootSymbol.flags & 2097152 /* Alias */ && symbolIsValue(rootSymbol) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(rootSymbol))) { markAliasSymbolAsReferenced(rootSymbol); } } + /** + * This function marks the type used for metadata decorator as referenced if it is import + * from external module. + * This is different from markTypeNodeAsReferenced because it tries to simplify type nodes in + * union and intersection type + * @param node + */ function markDecoratorMedataDataTypeNodeAsReferenced(node) { var entityName = getEntityNameForDecoratorMetadata(node); if (entityName && ts.isEntityName(entityName)) { @@ -42541,25 +49614,32 @@ var ts; function getEntityNameForDecoratorMetadata(node) { if (node) { switch (node.kind) { - case 170: - case 169: + case 170 /* IntersectionType */: + case 169 /* UnionType */: var commonEntityName = void 0; for (var _i = 0, _a = node.types; _i < _a.length; _i++) { var typeNode = _a[_i]; - while (typeNode.kind === 173) { - typeNode = typeNode.type; + while (typeNode.kind === 173 /* ParenthesizedType */) { + typeNode = typeNode.type; // Skip parens if need be } - if (typeNode.kind === 131) { - continue; + if (typeNode.kind === 131 /* NeverKeyword */) { + continue; // Always elide `never` from the union/intersection if possible } - if (!strictNullChecks && (typeNode.kind === 95 || typeNode.kind === 140)) { - continue; + if (!strictNullChecks && (typeNode.kind === 95 /* NullKeyword */ || typeNode.kind === 140 /* UndefinedKeyword */)) { + continue; // Elide null and undefined from unions for metadata, just like what we did prior to the implementation of strict null checks } var individualEntityName = getEntityNameForDecoratorMetadata(typeNode); if (!individualEntityName) { + // Individual is something like string number + // So it would be serialized to either that type or object + // Safe to return here return undefined; } if (commonEntityName) { + // Note this is in sync with the transformation that happens for type node. + // Keep this in sync with serializeUnionOrIntersectionType + // Verify if they refer to same entity and is identifier + // return undefined if they dont match because we would emit object if (!ts.isIdentifier(commonEntityName) || !ts.isIdentifier(individualEntityName) || commonEntityName.escapedText !== individualEntityName.escapedText) { @@ -42571,9 +49651,9 @@ var ts; } } return commonEntityName; - case 173: + case 173 /* ParenthesizedType */: return getEntityNameForDecoratorMetadata(node.type); - case 162: + case 162 /* TypeReference */: return node.typeName; } } @@ -42582,10 +49662,13 @@ var ts; var typeNode = ts.getEffectiveTypeAnnotationNode(node); return ts.isRestParameter(node) ? ts.getRestParameterElementType(typeNode) : typeNode; } + /** Check the decorators of a node */ function checkDecorators(node) { if (!node.decorators) { return; } + // skip this check for nodes that cannot have decorators. These should have already had an error reported by + // checkGrammarDecorators. if (!ts.nodeCanBeDecorated(node, node.parent, node.parent.parent)) { return; } @@ -42593,14 +49676,15 @@ var ts; error(node, ts.Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_to_remove_this_warning); } var firstDecorator = node.decorators[0]; - checkExternalEmitHelpers(firstDecorator, 8); - if (node.kind === 149) { - checkExternalEmitHelpers(firstDecorator, 32); + checkExternalEmitHelpers(firstDecorator, 8 /* Decorate */); + if (node.kind === 149 /* Parameter */) { + checkExternalEmitHelpers(firstDecorator, 32 /* Param */); } if (compilerOptions.emitDecoratorMetadata) { - checkExternalEmitHelpers(firstDecorator, 16); + checkExternalEmitHelpers(firstDecorator, 16 /* Metadata */); + // we only need to perform these checks if we are emitting serialized type metadata for the target of a decorator. switch (node.kind) { - case 235: + case 235 /* ClassDeclaration */: var constructor = ts.getFirstConstructorWithBody(node); if (constructor) { for (var _i = 0, _a = constructor.parameters; _i < _a.length; _i++) { @@ -42609,19 +49693,19 @@ var ts; } } break; - case 154: - case 156: - case 157: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: for (var _b = 0, _c = node.parameters; _b < _c.length; _b++) { var parameter = _c[_b]; markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter)); } markDecoratorMedataDataTypeNodeAsReferenced(ts.getEffectiveReturnTypeNode(node)); break; - case 152: + case 152 /* PropertyDeclaration */: markDecoratorMedataDataTypeNodeAsReferenced(ts.getEffectiveTypeAnnotationNode(node)); break; - case 149: + case 149 /* Parameter */: markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(node)); var containingSignature = node.parent; for (var _d = 0, _e = containingSignature.parameters; _d < _e.length; _d++) { @@ -42643,6 +49727,7 @@ var ts; } function checkJSDocTypeAliasTag(node) { if (!node.typeExpression) { + // If the node had `@property` tags, `typeExpression` would have been set to the first property tag. error(node.name, ts.Diagnostics.JSDoc_typedef_tag_should_either_have_a_type_annotation_or_be_followed_by_property_or_member_tags); } if (node.name) { @@ -42657,18 +49742,21 @@ var ts; checkSourceElement(node.typeExpression); if (!ts.getParameterSymbolFromJSDoc(node)) { var decl = ts.getHostSignatureFromJSDoc(node); + // don't issue an error for invalid hosts -- just functions -- + // and give a better error message when the host function mentions `arguments` + // but the tag doesn't have an array type if (decl) { var i = ts.getJSDocTags(decl).filter(ts.isJSDocParameterTag).indexOf(node); if (i > -1 && i < decl.parameters.length && ts.isBindingPattern(decl.parameters[i].name)) { return; } if (!containsArgumentsReference(decl)) { - error(node.name, ts.Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name, ts.idText(node.name.kind === 146 ? node.name.right : node.name)); + error(node.name, ts.Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name, ts.idText(node.name.kind === 146 /* QualifiedName */ ? node.name.right : node.name)); } else if (ts.findLast(ts.getJSDocTags(decl), ts.isJSDocParameterTag) === node && node.typeExpression && node.typeExpression.type && !isArrayType(getTypeFromTypeNode(node.typeExpression.type))) { - error(node.name, ts.Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name_It_would_match_arguments_if_it_had_an_array_type, ts.idText(node.name.kind === 146 ? node.name.right : node.name)); + error(node.name, ts.Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name_It_would_match_arguments_if_it_had_an_array_type, ts.idText(node.name.kind === 146 /* QualifiedName */ ? node.name.right : node.name)); } } } @@ -42695,9 +49783,9 @@ var ts; } function getIdentifierFromEntityNameExpression(node) { switch (node.kind) { - case 71: + case 71 /* Identifier */: return node; - case 185: + case 185 /* PropertyAccessExpression */: return node.name; default: return undefined; @@ -42707,41 +49795,63 @@ var ts; checkDecorators(node); checkSignatureDeclaration(node); var functionFlags = ts.getFunctionFlags(node); - if (node.name && node.name.kind === 147) { + // Do not use hasDynamicName here, because that returns false for well known symbols. + // We want to perform checkComputedPropertyName for all computed properties, including + // well known symbols. + if (node.name && node.name.kind === 147 /* ComputedPropertyName */) { + // This check will account for methods in class/interface declarations, + // as well as accessors in classes/object literals checkComputedPropertyName(node.name); } if (!hasNonBindableDynamicName(node)) { + // first we want to check the local symbol that contain this declaration + // - if node.localSymbol !== undefined - this is current declaration is exported and localSymbol points to the local symbol + // - if node.localSymbol === undefined - this node is non-exported so we can just pick the result of getSymbolOfNode var symbol = getSymbolOfNode(node); var localSymbol = node.localSymbol || symbol; - var firstDeclaration = ts.find(localSymbol.declarations, function (declaration) { return declaration.kind === node.kind && !(declaration.flags & 65536); }); + // Since the javascript won't do semantic analysis like typescript, + // if the javascript file comes before the typescript file and both contain same name functions, + // checkFunctionOrConstructorSymbol wouldn't be called if we didnt ignore javascript function. + var firstDeclaration = ts.find(localSymbol.declarations, + // Get first non javascript function declaration + function (declaration) { return declaration.kind === node.kind && !(declaration.flags & 65536 /* JavaScriptFile */); }); + // Only type check the symbol once if (node === firstDeclaration) { checkFunctionOrConstructorSymbol(localSymbol); } if (symbol.parent) { + // run check once for the first declaration if (ts.getDeclarationOfKind(symbol, node.kind) === node) { + // run check on export symbol to check that modifiers agree across all exported declarations checkFunctionOrConstructorSymbol(symbol); } } } - var body = node.kind === 153 ? undefined : node.body; + var body = node.kind === 153 /* MethodSignature */ ? undefined : node.body; checkSourceElement(body); var returnTypeNode = ts.getEffectiveReturnTypeNode(node); - if ((functionFlags & 1) === 0) { - var returnOrPromisedType = returnTypeNode && (functionFlags & 2 - ? checkAsyncFunctionReturnType(node) - : getTypeFromTypeNode(returnTypeNode)); + if ((functionFlags & 1 /* Generator */) === 0) { // Async function or normal function + var returnOrPromisedType = returnTypeNode && (functionFlags & 2 /* Async */ + ? checkAsyncFunctionReturnType(node) // Async function + : getTypeFromTypeNode(returnTypeNode)); // normal function checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType); } if (produceDiagnostics && !returnTypeNode) { + // Report an implicit any error if there is no body, no explicit return type, and node is not a private method + // in an ambient context if (noImplicitAny && ts.nodeIsMissing(body) && !isPrivateWithinAmbient(node)) { reportImplicitAnyError(node, anyType); } - if (functionFlags & 1 && ts.nodeIsPresent(body)) { + if (functionFlags & 1 /* Generator */ && ts.nodeIsPresent(body)) { + // A generator with a body and no type annotation can still cause errors. It can error if the + // yielded values have no common supertype, or it can give an implicit any error if it has no + // yielded values. The only way to trigger these errors is to try checking its return type. getReturnTypeOfSignature(getSignatureFromDeclaration(node)); } } } function registerForUnusedIdentifiersCheck(node) { + // May be in a call such as getTypeOfNode that happened to call this. But potentiallyUnusedIdentifiers is only defined in the scope of `checkSourceFile`. if (produceDiagnostics) { var sourceFile = ts.getSourceFileOfNode(node); var potentiallyUnusedIdentifiers = allPotentiallyUnusedIdentifiers.get(sourceFile.path); @@ -42749,6 +49859,8 @@ var ts; potentiallyUnusedIdentifiers = []; allPotentiallyUnusedIdentifiers.set(sourceFile.path, potentiallyUnusedIdentifiers); } + // TODO: GH#22580 + // Debug.assert(addToSeen(seenPotentiallyUnusedIdentifiers, getNodeId(node)), "Adding potentially-unused identifier twice"); potentiallyUnusedIdentifiers.push(node); } } @@ -42756,41 +49868,41 @@ var ts; for (var _i = 0, potentiallyUnusedIdentifiers_1 = potentiallyUnusedIdentifiers; _i < potentiallyUnusedIdentifiers_1.length; _i++) { var node = potentiallyUnusedIdentifiers_1[_i]; switch (node.kind) { - case 235: - case 205: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: checkUnusedClassMembers(node, addDiagnostic); checkUnusedTypeParameters(node, addDiagnostic); break; - case 236: + case 236 /* InterfaceDeclaration */: checkUnusedTypeParameters(node, addDiagnostic); break; - case 274: - case 239: - case 213: - case 241: - case 220: - case 221: - case 222: + case 274 /* SourceFile */: + case 239 /* ModuleDeclaration */: + case 213 /* Block */: + case 241 /* CaseBlock */: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: checkUnusedLocalsAndParameters(node, addDiagnostic); break; - case 155: - case 192: - case 234: - case 193: - case 154: - case 156: - case 157: + case 155 /* Constructor */: + case 192 /* FunctionExpression */: + case 234 /* FunctionDeclaration */: + case 193 /* ArrowFunction */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: if (node.body) { checkUnusedLocalsAndParameters(node, addDiagnostic); } checkUnusedTypeParameters(node, addDiagnostic); break; - case 153: - case 158: - case 159: - case 163: - case 164: - case 237: + case 153 /* MethodSignature */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 237 /* TypeAliasDeclaration */: checkUnusedTypeParameters(node, addDiagnostic); break; default: @@ -42801,41 +49913,43 @@ var ts; function errorUnusedLocal(declaration, name, addDiagnostic) { var node = ts.getNameOfDeclaration(declaration) || declaration; var message = isTypeDeclaration(declaration) ? ts.Diagnostics._0_is_declared_but_never_used : ts.Diagnostics._0_is_declared_but_its_value_is_never_read; - addDiagnostic(0, ts.createDiagnosticForNode(node, message, name)); + addDiagnostic(0 /* Local */, ts.createDiagnosticForNode(node, message, name)); } function parameterNameStartsWithUnderscore(parameterName) { return parameterName && isIdentifierThatStartsWithUnderScore(parameterName); } function isIdentifierThatStartsWithUnderScore(node) { - return ts.isIdentifier(node) && ts.idText(node).charCodeAt(0) === 95; + return ts.isIdentifier(node) && ts.idText(node).charCodeAt(0) === 95 /* _ */; } function checkUnusedClassMembers(node, addDiagnostic) { - if (!(node.flags & 4194304)) { + if (!(node.flags & 4194304 /* Ambient */)) { for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var member = _a[_i]; switch (member.kind) { - case 154: - case 152: - case 156: - case 157: - if (member.kind === 157 && member.symbol.flags & 32768) { + case 154 /* MethodDeclaration */: + case 152 /* PropertyDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + if (member.kind === 157 /* SetAccessor */ && member.symbol.flags & 32768 /* GetAccessor */) { + // Already would have reported an error on the getter. break; } var symbol = getSymbolOfNode(member); - if (!symbol.isReferenced && ts.hasModifier(member, 8)) { - addDiagnostic(0, ts.createDiagnosticForNode(member.name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, symbolToString(symbol))); + if (!symbol.isReferenced && ts.hasModifier(member, 8 /* Private */)) { + addDiagnostic(0 /* Local */, ts.createDiagnosticForNode(member.name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, symbolToString(symbol))); } break; - case 155: + case 155 /* Constructor */: for (var _b = 0, _c = member.parameters; _b < _c.length; _b++) { var parameter = _c[_b]; - if (!parameter.symbol.isReferenced && ts.hasModifier(parameter, 8)) { - addDiagnostic(0, ts.createDiagnosticForNode(parameter.name, ts.Diagnostics.Property_0_is_declared_but_its_value_is_never_read, ts.symbolName(parameter.symbol))); + if (!parameter.symbol.isReferenced && ts.hasModifier(parameter, 8 /* Private */)) { + addDiagnostic(0 /* Local */, ts.createDiagnosticForNode(parameter.name, ts.Diagnostics.Property_0_is_declared_but_its_value_is_never_read, ts.symbolName(parameter.symbol))); } } break; - case 160: - case 212: + case 160 /* IndexSignature */: + case 212 /* SemicolonClassElement */: + // Can't be private break; default: ts.Debug.fail(); @@ -42844,12 +49958,14 @@ var ts; } } function checkUnusedTypeParameters(node, addDiagnostic) { + // Only report errors on the last declaration for the type parameter container; + // this ensures that all uses have been accounted for. var typeParameters = ts.getEffectiveTypeParameterDeclarations(node); - if (!(node.flags & 4194304) && ts.last(getSymbolOfNode(node).declarations) === node) { + if (!(node.flags & 4194304 /* Ambient */) && ts.last(getSymbolOfNode(node).declarations) === node) { for (var _i = 0, typeParameters_2 = typeParameters; _i < typeParameters_2.length; _i++) { var typeParameter = typeParameters_2[_i]; - if (!(getMergedSymbol(typeParameter.symbol).isReferenced & 262144) && !isIdentifierThatStartsWithUnderScore(typeParameter.name)) { - addDiagnostic(1, ts.createDiagnosticForNode(typeParameter.name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.symbolName(typeParameter.symbol))); + if (!(getMergedSymbol(typeParameter.symbol).isReferenced & 262144 /* TypeParameter */) && !isIdentifierThatStartsWithUnderScore(typeParameter.name)) { + addDiagnostic(1 /* Parameter */, ts.createDiagnosticForNode(typeParameter.name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.symbolName(typeParameter.symbol))); } } } @@ -42868,13 +49984,16 @@ var ts; return ts.tryCast(ts.getRootDeclaration(node), ts.isParameter); } function checkUnusedLocalsAndParameters(nodeWithLocals, addDiagnostic) { - if (nodeWithLocals.flags & 4194304) + if (nodeWithLocals.flags & 4194304 /* Ambient */) return; + // Ideally we could use the ImportClause directly as a key, but must wait until we have full ES6 maps. So must store key along with value. var unusedImports = ts.createMap(); var unusedDestructures = ts.createMap(); var unusedVariables = ts.createMap(); nodeWithLocals.locals.forEach(function (local) { - if (local.flags & 262144 ? !(local.flags & 3 && !(local.isReferenced & 3)) : local.isReferenced || local.exportSymbol) { + // If it's purely a type parameter, ignore, will be checked in `checkUnusedTypeParameters`. + // If it's a type parameter merged with a parameter, check if the parameter-side is used. + if (local.flags & 262144 /* TypeParameter */ ? !(local.flags & 3 /* Variable */ && !(local.isReferenced & 3 /* Variable */)) : local.isReferenced || local.exportSymbol) { return; } for (var _i = 0, _a = local.declarations; _i < _a.length; _i++) { @@ -42887,6 +50006,7 @@ var ts; addToGroup(unusedImports, importClauseFromImported(declaration), declaration, getNodeId); } else if (ts.isBindingElement(declaration) && ts.isObjectBindingPattern(declaration.parent)) { + // In `{ a, ...b }, `a` is considered used since it removes a property from `b`. `b` may still be unused though. var lastElement = ts.last(declaration.parent.elements); if (declaration === lastElement || !ts.last(declaration.parent.elements).dotDotDotToken) { addToGroup(unusedDestructures, declaration.parent, declaration, getNodeId); @@ -42900,7 +50020,7 @@ var ts; if (parameter) { var name = ts.getNameOfDeclaration(local.valueDeclaration); if (!ts.isParameterPropertyDeclaration(parameter) && !ts.parameterIsThisKeyword(parameter) && !parameterNameStartsWithUnderscore(name)) { - addDiagnostic(1, ts.createDiagnosticForNode(name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.symbolName(local))); + addDiagnostic(1 /* Parameter */, ts.createDiagnosticForNode(name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.symbolName(local))); } } else { @@ -42914,10 +50034,10 @@ var ts; var importDecl = importClause.parent; var nDeclarations = (importClause.name ? 1 : 0) + (importClause.namedBindings ? - (importClause.namedBindings.kind === 246 ? 1 : importClause.namedBindings.elements.length) + (importClause.namedBindings.kind === 246 /* NamespaceImport */ ? 1 : importClause.namedBindings.elements.length) : 0); if (nDeclarations === unuseds.length) { - addDiagnostic(0, unuseds.length === 1 + addDiagnostic(0 /* Local */, unuseds.length === 1 ? ts.createDiagnosticForNode(importDecl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.first(unuseds).name)) : ts.createDiagnosticForNode(importDecl, ts.Diagnostics.All_imports_in_import_declaration_are_unused)); } @@ -42930,9 +50050,9 @@ var ts; }); unusedDestructures.forEach(function (_a) { var bindingPattern = _a[0], bindingElements = _a[1]; - var kind = tryGetRootParameterDeclaration(bindingPattern.parent) ? 1 : 0; + var kind = tryGetRootParameterDeclaration(bindingPattern.parent) ? 1 /* Parameter */ : 0 /* Local */; if (bindingPattern.elements.length === bindingElements.length) { - if (bindingElements.length === 1 && bindingPattern.parent.kind === 232 && bindingPattern.parent.parent.kind === 233) { + if (bindingElements.length === 1 && bindingPattern.parent.kind === 232 /* VariableDeclaration */ && bindingPattern.parent.parent.kind === 233 /* VariableDeclarationList */) { addToGroup(unusedVariables, bindingPattern.parent.parent, bindingPattern.parent, getNodeId); } else { @@ -42951,37 +50071,38 @@ var ts; unusedVariables.forEach(function (_a) { var declarationList = _a[0], declarations = _a[1]; if (declarationList.declarations.length === declarations.length) { - addDiagnostic(0, declarations.length === 1 + addDiagnostic(0 /* Local */, declarations.length === 1 ? ts.createDiagnosticForNode(ts.first(declarations).name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(ts.first(declarations).name)) - : ts.createDiagnosticForNode(declarationList.parent.kind === 214 ? declarationList.parent : declarationList, ts.Diagnostics.All_variables_are_unused)); + : ts.createDiagnosticForNode(declarationList.parent.kind === 214 /* VariableStatement */ ? declarationList.parent : declarationList, ts.Diagnostics.All_variables_are_unused)); } else { for (var _i = 0, declarations_5 = declarations; _i < declarations_5.length; _i++) { var decl = declarations_5[_i]; - addDiagnostic(0, ts.createDiagnosticForNode(decl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(decl.name, ts.isIdentifier)))); + addDiagnostic(0 /* Local */, ts.createDiagnosticForNode(decl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(decl.name, ts.isIdentifier)))); } } }); } function bindingNameText(name) { switch (name.kind) { - case 71: + case 71 /* Identifier */: return ts.idText(name); - case 181: - case 180: + case 181 /* ArrayBindingPattern */: + case 180 /* ObjectBindingPattern */: return bindingNameText(ts.cast(ts.first(name.elements), ts.isBindingElement).name); default: return ts.Debug.assertNever(name); } } function isImportedDeclaration(node) { - return node.kind === 245 || node.kind === 248 || node.kind === 246; + return node.kind === 245 /* ImportClause */ || node.kind === 248 /* ImportSpecifier */ || node.kind === 246 /* NamespaceImport */; } function importClauseFromImported(decl) { - return decl.kind === 245 ? decl : decl.kind === 246 ? decl.parent : decl.parent.parent; + return decl.kind === 245 /* ImportClause */ ? decl : decl.kind === 246 /* NamespaceImport */ ? decl.parent : decl.parent.parent; } function checkBlock(node) { - if (node.kind === 213) { + // Grammar checking for SyntaxKind.Block + if (node.kind === 213 /* Block */) { checkGrammarStatementInAmbientContext(node); } if (ts.isFunctionOrModuleBlock(node)) { @@ -42997,7 +50118,8 @@ var ts; } } function checkCollisionWithArgumentsInGeneratedCode(node) { - if (languageVersion >= 2 || compilerOptions.noEmit || !ts.hasRestParameter(node) || node.flags & 4194304 || ts.nodeIsMissing(node.body)) { + // no rest parameters \ declaration context \ overload - no codegen impact + if (languageVersion >= 2 /* ES2015 */ || compilerOptions.noEmit || !ts.hasRestParameter(node) || node.flags & 4194304 /* Ambient */ || ts.nodeIsMissing(node.body)) { return; } ts.forEach(node.parameters, function (p) { @@ -43010,27 +50132,31 @@ var ts; if (!(identifier && identifier.escapedText === name)) { return false; } - if (node.kind === 152 || - node.kind === 151 || - node.kind === 154 || - node.kind === 153 || - node.kind === 156 || - node.kind === 157) { + if (node.kind === 152 /* PropertyDeclaration */ || + node.kind === 151 /* PropertySignature */ || + node.kind === 154 /* MethodDeclaration */ || + node.kind === 153 /* MethodSignature */ || + node.kind === 156 /* GetAccessor */ || + node.kind === 157 /* SetAccessor */) { + // it is ok to have member named '_super' or '_this' - member access is always qualified return false; } - if (node.flags & 4194304) { + if (node.flags & 4194304 /* Ambient */) { + // ambient context - no codegen impact return false; } var root = ts.getRootDeclaration(node); - if (root.kind === 149 && ts.nodeIsMissing(root.parent.body)) { + if (root.kind === 149 /* Parameter */ && ts.nodeIsMissing(root.parent.body)) { + // just an overload - no codegen impact return false; } return true; } + // this function will run after checking the source file so 'CaptureThis' is correct for all nodes function checkIfThisIsCapturedInEnclosingScope(node) { ts.findAncestor(node, function (current) { - if (getNodeCheckFlags(current) & 4) { - var isDeclaration_1 = node.kind !== 71; + if (getNodeCheckFlags(current) & 4 /* CaptureThis */) { + var isDeclaration_1 = node.kind !== 71 /* Identifier */; if (isDeclaration_1) { error(ts.getNameOfDeclaration(node), ts.Diagnostics.Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference); } @@ -43044,8 +50170,8 @@ var ts; } function checkIfNewTargetIsCapturedInEnclosingScope(node) { ts.findAncestor(node, function (current) { - if (getNodeCheckFlags(current) & 8) { - var isDeclaration_2 = node.kind !== 71; + if (getNodeCheckFlags(current) & 8 /* CaptureNewTarget */) { + var isDeclaration_2 = node.kind !== 71 /* Identifier */; if (isDeclaration_2) { error(ts.getNameOfDeclaration(node), ts.Diagnostics.Duplicate_identifier_newTarget_Compiler_uses_variable_declaration_newTarget_to_capture_new_target_meta_property_reference); } @@ -43058,57 +50184,96 @@ var ts; }); } function checkCollisionWithRequireExportsInGeneratedCode(node, name) { + // No need to check for require or exports for ES6 modules and later if (moduleKind >= ts.ModuleKind.ES2015 || compilerOptions.noEmit) { return; } if (!needCollisionCheckForIdentifier(node, name, "require") && !needCollisionCheckForIdentifier(node, name, "exports")) { return; } - if (ts.isModuleDeclaration(node) && ts.getModuleInstanceState(node) !== 1) { + // Uninstantiated modules shouldnt do this check + if (ts.isModuleDeclaration(node) && ts.getModuleInstanceState(node) !== 1 /* Instantiated */) { return; } + // In case of variable declaration, node.parent is variable statement so look at the variable statement's parent var parent = getDeclarationContainer(node); - if (parent.kind === 274 && ts.isExternalOrCommonJsModule(parent)) { + if (parent.kind === 274 /* SourceFile */ && ts.isExternalOrCommonJsModule(parent)) { + // If the declaration happens to be in external module, report error that require and exports are reserved keywords error(name, ts.Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module, ts.declarationNameToString(name), ts.declarationNameToString(name)); } } function checkCollisionWithGlobalPromiseInGeneratedCode(node, name) { - if (languageVersion >= 4 || compilerOptions.noEmit || !needCollisionCheckForIdentifier(node, name, "Promise")) { + if (languageVersion >= 4 /* ES2017 */ || compilerOptions.noEmit || !needCollisionCheckForIdentifier(node, name, "Promise")) { return; } - if (ts.isModuleDeclaration(node) && ts.getModuleInstanceState(node) !== 1) { + // Uninstantiated modules shouldnt do this check + if (ts.isModuleDeclaration(node) && ts.getModuleInstanceState(node) !== 1 /* Instantiated */) { return; } + // In case of variable declaration, node.parent is variable statement so look at the variable statement's parent var parent = getDeclarationContainer(node); - if (parent.kind === 274 && ts.isExternalOrCommonJsModule(parent) && parent.flags & 1024) { + if (parent.kind === 274 /* SourceFile */ && ts.isExternalOrCommonJsModule(parent) && parent.flags & 1024 /* HasAsyncFunctions */) { + // If the declaration happens to be in external module, report error that Promise is a reserved identifier. error(name, ts.Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module_containing_async_functions, ts.declarationNameToString(name), ts.declarationNameToString(name)); } } function checkVarDeclaredNamesNotShadowed(node) { - if ((ts.getCombinedNodeFlags(node) & 3) !== 0 || ts.isParameterDeclaration(node)) { + // - ScriptBody : StatementList + // It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList + // also occurs in the VarDeclaredNames of StatementList. + // - Block : { StatementList } + // It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList + // also occurs in the VarDeclaredNames of StatementList. + // Variable declarations are hoisted to the top of their function scope. They can shadow + // block scoped declarations, which bind tighter. this will not be flagged as duplicate definition + // by the binder as the declaration scope is different. + // A non-initialized declaration is a no-op as the block declaration will resolve before the var + // declaration. the problem is if the declaration has an initializer. this will act as a write to the + // block declared value. this is fine for let, but not const. + // Only consider declarations with initializers, uninitialized const declarations will not + // step on a let/const variable. + // Do not consider const and const declarations, as duplicate block-scoped declarations + // are handled by the binder. + // We are only looking for const declarations that step on let\const declarations from a + // different scope. e.g.: + // { + // const x = 0; // localDeclarationSymbol obtained after name resolution will correspond to this declaration + // const x = 0; // symbol for this declaration will be 'symbol' + // } + // skip block-scoped variables and parameters + if ((ts.getCombinedNodeFlags(node) & 3 /* BlockScoped */) !== 0 || ts.isParameterDeclaration(node)) { return; } - if (node.kind === 232 && !node.initializer) { + // skip variable declarations that don't have initializers + // NOTE: in ES6 spec initializer is required in variable declarations where name is binding pattern + // so we'll always treat binding elements as initialized + if (node.kind === 232 /* VariableDeclaration */ && !node.initializer) { return; } var symbol = getSymbolOfNode(node); - if (symbol.flags & 1) { + if (symbol.flags & 1 /* FunctionScopedVariable */) { if (!ts.isIdentifier(node.name)) return ts.Debug.fail(); - var localDeclarationSymbol = resolveName(node, node.name.escapedText, 3, undefined, undefined, false); + var localDeclarationSymbol = resolveName(node, node.name.escapedText, 3 /* Variable */, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); if (localDeclarationSymbol && localDeclarationSymbol !== symbol && - localDeclarationSymbol.flags & 2) { - if (getDeclarationNodeFlagsFromSymbol(localDeclarationSymbol) & 3) { - var varDeclList = ts.getAncestor(localDeclarationSymbol.valueDeclaration, 233); - var container = varDeclList.parent.kind === 214 && varDeclList.parent.parent + localDeclarationSymbol.flags & 2 /* BlockScopedVariable */) { + if (getDeclarationNodeFlagsFromSymbol(localDeclarationSymbol) & 3 /* BlockScoped */) { + var varDeclList = ts.getAncestor(localDeclarationSymbol.valueDeclaration, 233 /* VariableDeclarationList */); + var container = varDeclList.parent.kind === 214 /* VariableStatement */ && varDeclList.parent.parent ? varDeclList.parent.parent : undefined; + // names of block-scoped and function scoped variables can collide only + // if block scoped variable is defined in the function\module\source file scope (because of variable hoisting) var namesShareScope = container && - (container.kind === 213 && ts.isFunctionLike(container.parent) || - container.kind === 240 || - container.kind === 239 || - container.kind === 274); + (container.kind === 213 /* Block */ && ts.isFunctionLike(container.parent) || + container.kind === 240 /* ModuleBlock */ || + container.kind === 239 /* ModuleDeclaration */ || + container.kind === 274 /* SourceFile */); + // here we know that function scoped variable is shadowed by block scoped one + // if they are defined in the same scope - binder has already reported redeclaration error + // otherwise if variable has an initializer - show error that initialization will fail + // since LHS will be block scoped name instead of function scoped if (!namesShareScope) { var name = symbolToString(localDeclarationSymbol); error(node, ts.Diagnostics.Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1, name, name); @@ -43117,21 +50282,27 @@ var ts; } } } + // Check that a parameter initializer contains no references to parameters declared to the right of itself function checkParameterInitializer(node) { - if (ts.getRootDeclaration(node).kind !== 149) { + if (ts.getRootDeclaration(node).kind !== 149 /* Parameter */) { return; } var func = ts.getContainingFunction(node); visit(node.initializer); function visit(n) { if (ts.isTypeNode(n) || ts.isDeclarationName(n)) { + // do not dive in types + // skip declaration names (i.e. in object literal expressions) return; } - if (n.kind === 185) { + if (n.kind === 185 /* PropertyAccessExpression */) { + // skip property names in property access expression return visit(n.expression); } - else if (n.kind === 71) { - var symbol = resolveName(n, n.escapedText, 67216319 | 2097152, undefined, undefined, false); + else if (n.kind === 71 /* Identifier */) { + // check FunctionLikeDeclaration.locals (stores parameters\function local variable) + // if it contains entry with a specified name + var symbol = resolveName(n, n.escapedText, 67216319 /* Value */ | 2097152 /* Alias */, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); if (!symbol || symbol === unknownSymbol || !symbol.valueDeclaration) { return; } @@ -43139,24 +50310,32 @@ var ts; error(n, ts.Diagnostics.Parameter_0_cannot_be_referenced_in_its_initializer, ts.declarationNameToString(node.name)); return; } + // locals map for function contain both parameters and function locals + // so we need to do a bit of extra work to check if reference is legal var enclosingContainer = ts.getEnclosingBlockScopeContainer(symbol.valueDeclaration); if (enclosingContainer === func) { - if (symbol.valueDeclaration.kind === 149 || - symbol.valueDeclaration.kind === 182) { + if (symbol.valueDeclaration.kind === 149 /* Parameter */ || + symbol.valueDeclaration.kind === 182 /* BindingElement */) { + // it is ok to reference parameter in initializer if either + // - parameter is located strictly on the left of current parameter declaration if (symbol.valueDeclaration.pos < node.pos) { return; } + // - parameter is wrapped in function-like entity if (ts.findAncestor(n, function (current) { if (current === node.initializer) { return "quit"; } return ts.isFunctionLike(current.parent) || - (current.parent.kind === 152 && - !(ts.hasModifier(current.parent, 32)) && + // computed property names/initializers in instance property declaration of class like entities + // are executed in constructor and thus deferred + (current.parent.kind === 152 /* PropertyDeclaration */ && + !(ts.hasModifier(current.parent, 32 /* Static */)) && ts.isClassLike(current.parent.parent)); })) { return; } + // fall through to report error } error(n, ts.Diagnostics.Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it, ts.declarationNameToString(node.name), ts.declarationNameToString(n)); } @@ -43169,56 +50348,68 @@ var ts; function convertAutoToAny(type) { return type === autoType ? anyType : type === autoArrayType ? anyArrayType : type; } + // Check variable, parameter, or property declaration function checkVariableLikeDeclaration(node) { checkDecorators(node); if (!ts.isBindingElement(node)) { checkSourceElement(node.type); } + // JSDoc `function(string, string): string` syntax results in parameters with no name if (!node.name) { return; } - if (node.name.kind === 147) { + // For a computed property, just check the initializer and exit + // Do not use hasDynamicName here, because that returns false for well known symbols. + // We want to perform checkComputedPropertyName for all computed properties, including + // well known symbols. + if (node.name.kind === 147 /* ComputedPropertyName */) { checkComputedPropertyName(node.name); if (node.initializer) { checkExpressionCached(node.initializer); } } - if (node.kind === 182) { - if (node.parent.kind === 180 && languageVersion < 6) { - checkExternalEmitHelpers(node, 4); + if (node.kind === 182 /* BindingElement */) { + if (node.parent.kind === 180 /* ObjectBindingPattern */ && languageVersion < 6 /* ESNext */) { + checkExternalEmitHelpers(node, 4 /* Rest */); } - if (node.propertyName && node.propertyName.kind === 147) { + // check computed properties inside property names of binding elements + if (node.propertyName && node.propertyName.kind === 147 /* ComputedPropertyName */) { checkComputedPropertyName(node.propertyName); } + // check private/protected variable access var parent = node.parent.parent; var parentType = getTypeForBindingElementParent(parent); var name = node.propertyName || node.name; if (!ts.isBindingPattern(name)) { - var property = getPropertyOfType(parentType, ts.getTextOfPropertyName(name)); - markPropertyAsReferenced(property, undefined, false); + var property = getPropertyOfType(parentType, ts.getTextOfPropertyName(name)); // TODO: GH#18217 + markPropertyAsReferenced(property, /*nodeForCheckWriteOnly*/ undefined, /*isThisAccess*/ false); // A destructuring is never a write-only reference. if (parent.initializer && property) { checkPropertyAccessibility(parent, parent.initializer, parentType, property); } } } + // For a binding pattern, check contained binding elements if (ts.isBindingPattern(node.name)) { - if (node.name.kind === 181 && languageVersion < 2 && compilerOptions.downlevelIteration) { - checkExternalEmitHelpers(node, 512); + if (node.name.kind === 181 /* ArrayBindingPattern */ && languageVersion < 2 /* ES2015 */ && compilerOptions.downlevelIteration) { + checkExternalEmitHelpers(node, 512 /* Read */); } ts.forEach(node.name.elements, checkSourceElement); } - if (node.initializer && ts.getRootDeclaration(node).kind === 149 && ts.nodeIsMissing(ts.getContainingFunction(node).body)) { + // For a parameter declaration with an initializer, error and exit if the containing function doesn't have a body + if (node.initializer && ts.getRootDeclaration(node).kind === 149 /* Parameter */ && ts.nodeIsMissing(ts.getContainingFunction(node).body)) { error(node, ts.Diagnostics.A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation); return; } + // For a binding pattern, validate the initializer and exit if (ts.isBindingPattern(node.name)) { - if (node.initializer && node.parent.parent.kind !== 221) { + // Don't validate for-in initializer as it is already an error + if (node.initializer && node.parent.parent.kind !== 221 /* ForInStatement */) { var initializerType = checkExpressionCached(node.initializer); if (strictNullChecks && node.name.elements.length === 0) { checkNonNullType(initializerType, node); } else { - checkTypeAssignableTo(initializerType, getWidenedTypeForVariableLikeDeclaration(node), node, undefined); + checkTypeAssignableTo(initializerType, getWidenedTypeForVariableLikeDeclaration(node), node, /*headMessage*/ undefined); } checkParameterInitializer(node); } @@ -43227,36 +50418,41 @@ var ts; var symbol = getSymbolOfNode(node); var type = convertAutoToAny(getTypeOfSymbol(symbol)); if (node === symbol.valueDeclaration) { + // Node is the primary declaration of the symbol, just validate the initializer + // Don't validate for-in initializer as it is already an error var initializer = ts.getEffectiveInitializer(node); if (initializer) { var isJSObjectLiteralInitializer = ts.isInJavaScriptFile(node) && ts.isObjectLiteralExpression(initializer) && (initializer.properties.length === 0 || ts.isPrototypeAccess(node.name)) && ts.hasEntries(symbol.exports); - if (!isJSObjectLiteralInitializer && node.parent.parent.kind !== 221) { - checkTypeAssignableTo(checkExpressionCached(initializer), type, node, undefined); + if (!isJSObjectLiteralInitializer && node.parent.parent.kind !== 221 /* ForInStatement */) { + checkTypeAssignableTo(checkExpressionCached(initializer), type, node, /*headMessage*/ undefined); checkParameterInitializer(node); } } } else { + // Node is a secondary declaration, check that type is identical to primary declaration and check that + // initializer is consistent with type associated with the node var declarationType = convertAutoToAny(getWidenedTypeForVariableLikeDeclaration(node)); if (type !== errorType && declarationType !== errorType && !isTypeIdenticalTo(type, declarationType) && - !(symbol.flags & 67108864)) { + !(symbol.flags & 67108864 /* JSContainer */)) { errorNextVariableOrPropertyDeclarationMustHaveSameType(type, node, declarationType); } if (node.initializer) { - checkTypeAssignableTo(checkExpressionCached(node.initializer), declarationType, node, undefined); + checkTypeAssignableTo(checkExpressionCached(node.initializer), declarationType, node, /*headMessage*/ undefined); } if (!areDeclarationFlagsIdentical(node, symbol.valueDeclaration)) { error(ts.getNameOfDeclaration(symbol.valueDeclaration), ts.Diagnostics.All_declarations_of_0_must_have_identical_modifiers, ts.declarationNameToString(node.name)); error(node.name, ts.Diagnostics.All_declarations_of_0_must_have_identical_modifiers, ts.declarationNameToString(node.name)); } } - if (node.kind !== 152 && node.kind !== 151) { + if (node.kind !== 152 /* PropertyDeclaration */ && node.kind !== 151 /* PropertySignature */) { + // We know we don't have a binding pattern or computed name here checkExportsOnMergedDeclarations(node); - if (node.kind === 232 || node.kind === 182) { + if (node.kind === 232 /* VariableDeclaration */ || node.kind === 182 /* BindingElement */) { checkVarDeclaredNamesNotShadowed(node); } checkCollisionWithRequireExportsInGeneratedCode(node, node.name); @@ -43265,25 +50461,26 @@ var ts; } function errorNextVariableOrPropertyDeclarationMustHaveSameType(firstType, nextDeclaration, nextType) { var nextDeclarationName = ts.getNameOfDeclaration(nextDeclaration); - var message = nextDeclaration.kind === 152 || nextDeclaration.kind === 151 + var message = nextDeclaration.kind === 152 /* PropertyDeclaration */ || nextDeclaration.kind === 151 /* PropertySignature */ ? ts.Diagnostics.Subsequent_property_declarations_must_have_the_same_type_Property_0_must_be_of_type_1_but_here_has_type_2 : ts.Diagnostics.Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2; error(nextDeclarationName, message, ts.declarationNameToString(nextDeclarationName), typeToString(firstType), typeToString(nextType)); } function areDeclarationFlagsIdentical(left, right) { - if ((left.kind === 149 && right.kind === 232) || - (left.kind === 232 && right.kind === 149)) { + if ((left.kind === 149 /* Parameter */ && right.kind === 232 /* VariableDeclaration */) || + (left.kind === 232 /* VariableDeclaration */ && right.kind === 149 /* Parameter */)) { + // Differences in optionality between parameters and variables are allowed. return true; } if (ts.hasQuestionToken(left) !== ts.hasQuestionToken(right)) { return false; } - var interestingFlags = 8 | - 16 | - 256 | - 128 | - 64 | - 32; + var interestingFlags = 8 /* Private */ | + 16 /* Protected */ | + 256 /* Async */ | + 128 /* Abstract */ | + 64 /* Readonly */ | + 32 /* Static */; return ts.getSelectedModifierFlags(left, interestingFlags) === ts.getSelectedModifierFlags(right, interestingFlags); } function checkVariableDeclaration(node) { @@ -43295,41 +50492,47 @@ var ts; return checkVariableLikeDeclaration(node); } function checkVariableStatement(node) { + // Grammar checking if (!checkGrammarDecoratorsAndModifiers(node) && !checkGrammarVariableDeclarationList(node.declarationList)) checkGrammarForDisallowedLetOrConstStatement(node); ts.forEach(node.declarationList.declarations, checkSourceElement); } function checkExpressionStatement(node) { + // Grammar checking checkGrammarStatementInAmbientContext(node); checkExpression(node.expression); } function checkIfStatement(node) { + // Grammar checking checkGrammarStatementInAmbientContext(node); checkExpression(node.expression); checkSourceElement(node.thenStatement); - if (node.thenStatement.kind === 215) { + if (node.thenStatement.kind === 215 /* EmptyStatement */) { error(node.thenStatement, ts.Diagnostics.The_body_of_an_if_statement_cannot_be_the_empty_statement); } checkSourceElement(node.elseStatement); } function checkDoStatement(node) { + // Grammar checking checkGrammarStatementInAmbientContext(node); checkSourceElement(node.statement); checkExpression(node.expression); } function checkWhileStatement(node) { + // Grammar checking checkGrammarStatementInAmbientContext(node); checkExpression(node.expression); checkSourceElement(node.statement); } function checkForStatement(node) { + // Grammar checking if (!checkGrammarStatementInAmbientContext(node)) { - if (node.initializer && node.initializer.kind === 233) { + if (node.initializer && node.initializer.kind === 233 /* VariableDeclarationList */) { checkGrammarVariableDeclarationList(node.initializer); } } if (node.initializer) { - if (node.initializer.kind === 233) { + if (node.initializer.kind === 233 /* VariableDeclarationList */) { ts.forEach(node.initializer.declarations, checkVariableDeclaration); } else { @@ -43349,27 +50552,42 @@ var ts; checkGrammarForInOrForOfStatement(node); if (node.awaitModifier) { var functionFlags = ts.getFunctionFlags(ts.getContainingFunction(node)); - if ((functionFlags & (4 | 2)) === 2 && languageVersion < 6) { - checkExternalEmitHelpers(node, 16384); + if ((functionFlags & (4 /* Invalid */ | 2 /* Async */)) === 2 /* Async */ && languageVersion < 6 /* ESNext */) { + // for..await..of in an async function or async generator function prior to ESNext requires the __asyncValues helper + checkExternalEmitHelpers(node, 16384 /* ForAwaitOfIncludes */); } } - else if (compilerOptions.downlevelIteration && languageVersion < 2) { - checkExternalEmitHelpers(node, 256); + else if (compilerOptions.downlevelIteration && languageVersion < 2 /* ES2015 */) { + // for..of prior to ES2015 requires the __values helper when downlevelIteration is enabled + checkExternalEmitHelpers(node, 256 /* ForOfIncludes */); } - if (node.initializer.kind === 233) { + // Check the LHS and RHS + // If the LHS is a declaration, just check it as a variable declaration, which will in turn check the RHS + // via checkRightHandSideOfForOf. + // If the LHS is an expression, check the LHS, as a destructuring assignment or as a reference. + // Then check that the RHS is assignable to it. + if (node.initializer.kind === 233 /* VariableDeclarationList */) { checkForInOrForOfVariableDeclaration(node); } else { var varExpr = node.initializer; var iteratedType = checkRightHandSideOfForOf(node.expression, node.awaitModifier); - if (varExpr.kind === 183 || varExpr.kind === 184) { + // There may be a destructuring assignment on the left side + if (varExpr.kind === 183 /* ArrayLiteralExpression */ || varExpr.kind === 184 /* ObjectLiteralExpression */) { + // iteratedType may be undefined. In this case, we still want to check the structure of + // varExpr, in particular making sure it's a valid LeftHandSideExpression. But we'd like + // to short circuit the type relation checking as much as possible, so we pass the unknownType. checkDestructuringAssignment(varExpr, iteratedType || errorType); } else { var leftType = checkExpression(varExpr); checkReferenceExpression(varExpr, ts.Diagnostics.The_left_hand_side_of_a_for_of_statement_must_be_a_variable_or_a_property_access); + // iteratedType will be undefined if the rightType was missing properties/signatures + // required to get its iteratedType (like [Symbol.iterator] or next). This may be + // because we accessed properties from anyType, or it may have led to an error inside + // getElementTypeOfIterable. if (iteratedType) { - checkTypeAssignableTo(iteratedType, leftType, varExpr, undefined); + checkTypeAssignableTo(iteratedType, leftType, varExpr, /*headMessage*/ undefined); } } } @@ -43379,9 +50597,15 @@ var ts; } } function checkForInStatement(node) { + // Grammar checking checkGrammarForInOrForOfStatement(node); var rightType = checkNonNullExpression(node.expression); - if (node.initializer.kind === 233) { + // TypeScript 1.0 spec (April 2014): 5.4 + // In a 'for-in' statement of the form + // for (let VarDecl in Expr) Statement + // VarDecl must be a variable declaration without a type annotation that declares a variable of type Any, + // and Expr must be an expression of type Any, an object type, or a type parameter type. + if (node.initializer.kind === 233 /* VariableDeclarationList */) { var variable = node.initializer.declarations[0]; if (variable && ts.isBindingPattern(variable.name)) { error(variable.name, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern); @@ -43389,19 +50613,26 @@ var ts; checkForInOrForOfVariableDeclaration(node); } else { + // In a 'for-in' statement of the form + // for (Var in Expr) Statement + // Var must be an expression classified as a reference of type Any or the String primitive type, + // and Expr must be an expression of type Any, an object type, or a type parameter type. var varExpr = node.initializer; var leftType = checkExpression(varExpr); - if (varExpr.kind === 183 || varExpr.kind === 184) { + if (varExpr.kind === 183 /* ArrayLiteralExpression */ || varExpr.kind === 184 /* ObjectLiteralExpression */) { error(varExpr, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern); } else if (!isTypeAssignableTo(getIndexTypeOrString(rightType), leftType)) { error(varExpr, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any); } else { + // run check only former check succeeded to avoid cascading errors checkReferenceExpression(varExpr, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_must_be_a_variable_or_a_property_access); } } - if (rightType === neverType || !isTypeAssignableToKind(rightType, 16777216 | 14745600)) { + // unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved + // in this case error about missing name is already reported - do not report extra one + if (rightType === neverType || !isTypeAssignableToKind(rightType, 16777216 /* NonPrimitive */ | 14745600 /* InstantiableNonPrimitive */)) { error(node.expression, ts.Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter_but_here_has_type_0, typeToString(rightType)); } checkSourceElement(node.statement); @@ -43411,6 +50642,7 @@ var ts; } function checkForInOrForOfVariableDeclaration(iterationStatement) { var variableDeclarationList = iterationStatement.initializer; + // checkGrammarForInOrForOfStatement will check that there is exactly one declaration. if (variableDeclarationList.declarations.length >= 1) { var decl = variableDeclarationList.declarations[0]; checkVariableDeclaration(decl); @@ -43418,23 +50650,32 @@ var ts; } function checkRightHandSideOfForOf(rhsExpression, awaitModifier) { var expressionType = checkNonNullExpression(rhsExpression); - return checkIteratedTypeOrElementType(expressionType, rhsExpression, true, awaitModifier !== undefined); + return checkIteratedTypeOrElementType(expressionType, rhsExpression, /*allowStringInput*/ true, awaitModifier !== undefined); } function checkIteratedTypeOrElementType(inputType, errorNode, allowStringInput, allowAsyncIterables) { if (isTypeAny(inputType)) { return inputType; } - return getIteratedTypeOrElementType(inputType, errorNode, allowStringInput, allowAsyncIterables, true) || anyType; + return getIteratedTypeOrElementType(inputType, errorNode, allowStringInput, allowAsyncIterables, /*checkAssignability*/ true) || anyType; } + /** + * When consuming an iterable type in a for..of, spread, or iterator destructuring assignment + * we want to get the iterated type of an iterable for ES2015 or later, or the iterated type + * of a iterable (if defined globally) or element type of an array like for ES2015 or earlier. + */ function getIteratedTypeOrElementType(inputType, errorNode, allowStringInput, allowAsyncIterables, checkAssignability) { if (inputType === neverType) { - reportTypeNotIterableError(errorNode, inputType, allowAsyncIterables); + reportTypeNotIterableError(errorNode, inputType, allowAsyncIterables); // TODO: GH#18217 return undefined; } - var uplevelIteration = languageVersion >= 2; + var uplevelIteration = languageVersion >= 2 /* ES2015 */; var downlevelIteration = !uplevelIteration && compilerOptions.downlevelIteration; + // Get the iterated type of an `Iterable` or `IterableIterator` only in ES2015 + // or higher, when inside of an async generator or for-await-if, or when + // downlevelIteration is requested. if (uplevelIteration || downlevelIteration || allowAsyncIterables) { - var iteratedType = getIteratedTypeOfIterable(inputType, uplevelIteration ? errorNode : undefined, allowAsyncIterables, true, checkAssignability); + // We only report errors for an invalid iterable type in ES2015 or higher. + var iteratedType = getIteratedTypeOfIterable(inputType, uplevelIteration ? errorNode : undefined, allowAsyncIterables, /*allowSyncIterables*/ true, checkAssignability); if (iteratedType || uplevelIteration) { return iteratedType; } @@ -43442,33 +50683,45 @@ var ts; var arrayType = inputType; var reportedError = false; var hasStringConstituent = false; + // If strings are permitted, remove any string-like constituents from the array type. + // This allows us to find other non-string element types from an array unioned with + // a string. if (allowStringInput) { - if (arrayType.flags & 262144) { + if (arrayType.flags & 262144 /* Union */) { + // After we remove all types that are StringLike, we will know if there was a string constituent + // based on whether the result of filter is a new array. var arrayTypes = inputType.types; - var filteredTypes = ts.filter(arrayTypes, function (t) { return !(t.flags & 68); }); + var filteredTypes = ts.filter(arrayTypes, function (t) { return !(t.flags & 68 /* StringLike */); }); if (filteredTypes !== arrayTypes) { - arrayType = getUnionType(filteredTypes, 2); + arrayType = getUnionType(filteredTypes, 2 /* Subtype */); } } - else if (arrayType.flags & 68) { + else if (arrayType.flags & 68 /* StringLike */) { arrayType = neverType; } hasStringConstituent = arrayType !== inputType; if (hasStringConstituent) { - if (languageVersion < 1) { + if (languageVersion < 1 /* ES5 */) { if (errorNode) { error(errorNode, ts.Diagnostics.Using_a_string_in_a_for_of_statement_is_only_supported_in_ECMAScript_5_and_higher); reportedError = true; } } - if (arrayType.flags & 32768) { + // Now that we've removed all the StringLike types, if no constituents remain, then the entire + // arrayOrStringType was a string. + if (arrayType.flags & 32768 /* Never */) { return stringType; } } } if (!isArrayLikeType(arrayType)) { if (errorNode && !reportedError) { - var isIterable = !!getIteratedTypeOfIterable(inputType, undefined, allowAsyncIterables, true, checkAssignability); + // Which error we report depends on whether we allow strings or if there was a + // string constituent. For example, if the input type is number | string, we + // want to say that number is not an array type. But if the input was just + // number and string input is allowed, we want to say that number is not an + // array type or a string type. + var isIterable = !!getIteratedTypeOfIterable(inputType, /* errorNode */ undefined, allowAsyncIterables, /*allowSyncIterables*/ true, checkAssignability); var diagnostic = !allowStringInput || hasStringConstituent ? downlevelIteration ? ts.Diagnostics.Type_0_is_not_an_array_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator @@ -43484,15 +50737,54 @@ var ts; } return hasStringConstituent ? stringType : undefined; } - var arrayElementType = getIndexTypeOfType(arrayType, 1); + var arrayElementType = getIndexTypeOfType(arrayType, 1 /* Number */); if (hasStringConstituent && arrayElementType) { - if (arrayElementType.flags & 68) { + // This is just an optimization for the case where arrayOrStringType is string | string[] + if (arrayElementType.flags & 68 /* StringLike */) { return stringType; } - return getUnionType([arrayElementType, stringType], 2); + return getUnionType([arrayElementType, stringType], 2 /* Subtype */); } return arrayElementType; } + /** + * We want to treat type as an iterable, and get the type it is an iterable of. The iterable + * must have the following structure (annotated with the names of the variables below): + * + * { // iterable + * [Symbol.iterator]: { // iteratorMethod + * (): Iterator + * } + * } + * + * For an async iterable, we expect the following structure: + * + * { // iterable + * [Symbol.asyncIterator]: { // iteratorMethod + * (): AsyncIterator + * } + * } + * + * T is the type we are after. At every level that involves analyzing return types + * of signatures, we union the return types of all the signatures. + * + * Another thing to note is that at any step of this process, we could run into a dead end, + * meaning either the property is missing, or we run into the anyType. If either of these things + * happens, we return undefined to signal that we could not find the iterated type. If a property + * is missing, and the previous step did not result in 'any', then we also give an error if the + * caller requested it. Then the caller can decide what to do in the case where there is no iterated + * type. This is different from returning anyType, because that would signify that we have matched the + * whole pattern and that T (above) is 'any'. + * + * For a **for-of** statement, `yield*` (in a normal generator), spread, array + * destructuring, or normal generator we will only ever look for a `[Symbol.iterator]()` + * method. + * + * For an async generator we will only ever look at the `[Symbol.asyncIterator]()` method. + * + * For a **for-await-of** statement or a `yield*` in an async generator we will look for + * the `[Symbol.asyncIterator]()` method first, and then the `[Symbol.iterator]()` method. + */ function getIteratedTypeOfIterable(type, errorNode, allowAsyncIterables, allowSyncIterables, checkAssignability) { if (isTypeAny(type)) { return undefined; @@ -43504,8 +50796,10 @@ var ts; if (typeAsIterable.iteratedTypeOfAsyncIterable) { return typeAsIterable.iteratedTypeOfAsyncIterable; } - if (isReferenceToType(type, getGlobalAsyncIterableType(false)) || - isReferenceToType(type, getGlobalAsyncIterableIteratorType(false))) { + // As an optimization, if the type is an instantiation of the global `AsyncIterable` + // or the global `AsyncIterableIterator` then just grab its type argument. + if (isReferenceToType(type, getGlobalAsyncIterableType(/*reportErrors*/ false)) || + isReferenceToType(type, getGlobalAsyncIterableIteratorType(/*reportErrors*/ false))) { return typeAsIterable.iteratedTypeOfAsyncIterable = type.typeArguments[0]; } } @@ -43513,8 +50807,10 @@ var ts; if (typeAsIterable.iteratedTypeOfIterable) { return typeAsIterable.iteratedTypeOfIterable; } - if (isReferenceToType(type, getGlobalIterableType(false)) || - isReferenceToType(type, getGlobalIterableIteratorType(false))) { + // As an optimization, if the type is an instantiation of the global `Iterable` or + // `IterableIterator` then just grab its type argument. + if (isReferenceToType(type, getGlobalIterableType(/*reportErrors*/ false)) || + isReferenceToType(type, getGlobalIterableIteratorType(/*reportErrors*/ false))) { return typeAsIterable.iteratedTypeOfIterable = type.typeArguments[0]; } } @@ -43523,17 +50819,21 @@ var ts; if (isTypeAny(methodType)) { return undefined; } - var signatures = methodType ? getSignaturesOfType(methodType, 0) : undefined; + var signatures = methodType ? getSignaturesOfType(methodType, 0 /* Call */) : undefined; if (!ts.some(signatures)) { if (errorNode) { + // only report on the first error reportTypeNotIterableError(errorNode, type, allowAsyncIterables); errorNode = undefined; } return undefined; } - var returnType = getUnionType(ts.map(signatures, getReturnTypeOfSignature), 2); - var iteratedType = getIteratedTypeOfIterator(returnType, errorNode, !!asyncMethodType); + var returnType = getUnionType(ts.map(signatures, getReturnTypeOfSignature), 2 /* Subtype */); + var iteratedType = getIteratedTypeOfIterator(returnType, errorNode, /*isAsyncIterator*/ !!asyncMethodType); if (checkAssignability && errorNode && iteratedType) { + // If `checkAssignability` was specified, we were called from + // `checkIteratedTypeOrElementType`. As such, we need to validate that + // the type passed in is actually an Iterable. checkTypeAssignableTo(type, asyncMethodType ? createAsyncIterableType(iteratedType) : createIterableType(iteratedType), errorNode); @@ -43548,6 +50848,28 @@ var ts; ? ts.Diagnostics.Type_0_must_have_a_Symbol_asyncIterator_method_that_returns_an_async_iterator : ts.Diagnostics.Type_0_must_have_a_Symbol_iterator_method_that_returns_an_iterator, typeToString(type)); } + /** + * This function has very similar logic as getIteratedTypeOfIterable, except that it operates on + * Iterators instead of Iterables. Here is the structure: + * + * { // iterator + * next: { // nextMethod + * (): { // nextResult + * value: T // nextValue + * } + * } + * } + * + * For an async iterator, we expect the following structure: + * + * { // iterator + * next: { // nextMethod + * (): PromiseLike<{ // nextResult + * value: T // nextValue + * }> + * } + * } + */ function getIteratedTypeOfIterator(type, errorNode, isAsyncIterator) { if (isTypeAny(type)) { return undefined; @@ -43556,17 +50878,21 @@ var ts; if (isAsyncIterator ? typeAsIterator.iteratedTypeOfAsyncIterator : typeAsIterator.iteratedTypeOfIterator) { return isAsyncIterator ? typeAsIterator.iteratedTypeOfAsyncIterator : typeAsIterator.iteratedTypeOfIterator; } + // As an optimization, if the type is an instantiation of the global `Iterator` (for + // a non-async iterator) or the global `AsyncIterator` (for an async-iterator) then + // just grab its type argument. var getIteratorType = isAsyncIterator ? getGlobalAsyncIteratorType : getGlobalIteratorType; - if (isReferenceToType(type, getIteratorType(false))) { + if (isReferenceToType(type, getIteratorType(/*reportErrors*/ false))) { return isAsyncIterator ? typeAsIterator.iteratedTypeOfAsyncIterator = type.typeArguments[0] : typeAsIterator.iteratedTypeOfIterator = type.typeArguments[0]; } + // Both async and non-async iterators must have a `next` method. var nextMethod = getTypeOfPropertyOfType(type, "next"); if (isTypeAny(nextMethod)) { return undefined; } - var nextMethodSignatures = nextMethod ? getSignaturesOfType(nextMethod, 0) : ts.emptyArray; + var nextMethodSignatures = nextMethod ? getSignaturesOfType(nextMethod, 0 /* Call */) : ts.emptyArray; if (nextMethodSignatures.length === 0) { if (errorNode) { error(errorNode, isAsyncIterator @@ -43575,10 +50901,11 @@ var ts; } return undefined; } - var nextResult = getUnionType(ts.map(nextMethodSignatures, getReturnTypeOfSignature), 2); + var nextResult = getUnionType(ts.map(nextMethodSignatures, getReturnTypeOfSignature), 2 /* Subtype */); if (isTypeAny(nextResult)) { return undefined; } + // For an async iterator, we must get the awaited type of the return type. if (isAsyncIterator) { nextResult = getAwaitedTypeOfPromise(nextResult, errorNode, ts.Diagnostics.The_type_returned_by_the_next_method_of_an_async_iterator_must_be_a_promise_for_a_type_with_a_value_property); if (isTypeAny(nextResult)) { @@ -43598,28 +50925,37 @@ var ts; ? typeAsIterator.iteratedTypeOfAsyncIterator = nextValue : typeAsIterator.iteratedTypeOfIterator = nextValue; } + /** + * A generator may have a return type of `Iterator`, `Iterable`, or + * `IterableIterator`. An async generator may have a return type of `AsyncIterator`, + * `AsyncIterable`, or `AsyncIterableIterator`. This function can be used to extract + * the iterated type from this return type for contextual typing and verifying signatures. + */ function getIteratedTypeOfGenerator(returnType, isAsyncGenerator) { if (isTypeAny(returnType)) { return undefined; } - return getIteratedTypeOfIterable(returnType, undefined, isAsyncGenerator, !isAsyncGenerator, false) - || getIteratedTypeOfIterator(returnType, undefined, isAsyncGenerator); + return getIteratedTypeOfIterable(returnType, /*errorNode*/ undefined, /*allowAsyncIterables*/ isAsyncGenerator, /*allowSyncIterables*/ !isAsyncGenerator, /*checkAssignability*/ false) + || getIteratedTypeOfIterator(returnType, /*errorNode*/ undefined, isAsyncGenerator); } function checkBreakOrContinueStatement(node) { + // Grammar checking if (!checkGrammarStatementInAmbientContext(node)) checkGrammarBreakOrContinueStatement(node); + // TODO: Check that target label is valid } function isGetAccessorWithAnnotatedSetAccessor(node) { - return node.kind === 156 - && ts.getEffectiveSetAccessorTypeAnnotationNode(ts.getDeclarationOfKind(node.symbol, 157)) !== undefined; + return node.kind === 156 /* GetAccessor */ + && ts.getEffectiveSetAccessorTypeAnnotationNode(ts.getDeclarationOfKind(node.symbol, 157 /* SetAccessor */)) !== undefined; } function isUnwrappedReturnTypeVoidOrAny(func, returnType) { - var unwrappedReturnType = (ts.getFunctionFlags(func) & 3) === 2 - ? getPromisedTypeOfPromise(returnType) - : returnType; - return !!unwrappedReturnType && maybeTypeOfKind(unwrappedReturnType, 4096 | 3); + var unwrappedReturnType = (ts.getFunctionFlags(func) & 3 /* AsyncGenerator */) === 2 /* Async */ + ? getPromisedTypeOfPromise(returnType) // Async function + : returnType; // AsyncGenerator function, Generator function, or normal function + return !!unwrappedReturnType && maybeTypeOfKind(unwrappedReturnType, 4096 /* Void */ | 3 /* AnyOrUnknown */); } function checkReturnStatement(node) { + // Grammar checking if (checkGrammarStatementInAmbientContext(node)) { return; } @@ -43631,27 +50967,34 @@ var ts; var signature = getSignatureFromDeclaration(func); var returnType = getReturnTypeOfSignature(signature); var functionFlags = ts.getFunctionFlags(func); - var isGenerator = functionFlags & 1; - if (strictNullChecks || node.expression || returnType.flags & 32768) { + var isGenerator = functionFlags & 1 /* Generator */; + if (strictNullChecks || node.expression || returnType.flags & 32768 /* Never */) { var exprType = node.expression ? checkExpressionCached(node.expression) : undefinedType; - if (isGenerator) { + if (isGenerator) { // AsyncGenerator function or Generator function + // A generator does not need its return expressions checked against its return type. + // Instead, the yield expressions are checked against the element type. + // TODO: Check return types of generators when return type tracking is added + // for generators. return; } - else if (func.kind === 157) { + else if (func.kind === 157 /* SetAccessor */) { if (node.expression) { error(node, ts.Diagnostics.Setters_cannot_return_a_value); } } - else if (func.kind === 155) { + else if (func.kind === 155 /* Constructor */) { if (node.expression && !checkTypeAssignableTo(exprType, returnType, node)) { error(node, ts.Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class); } } else if (ts.getEffectiveReturnTypeNode(func) || isGetAccessorWithAnnotatedSetAccessor(func)) { - if (functionFlags & 2) { + if (functionFlags & 2 /* Async */) { // Async function var promisedType = getPromisedTypeOfPromise(returnType); var awaitedType = checkAwaitedType(exprType, node, ts.Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); if (promisedType) { + // If the function has a return type, but promisedType is + // undefined, an error will be reported in checkAsyncFunctionReturnType + // so we don't need to report one here. checkTypeAssignableTo(awaitedType, promisedType, node); } } @@ -43660,13 +51003,15 @@ var ts; } } } - else if (func.kind !== 155 && compilerOptions.noImplicitReturns && !isUnwrappedReturnTypeVoidOrAny(func, returnType) && !isGenerator) { + else if (func.kind !== 155 /* Constructor */ && compilerOptions.noImplicitReturns && !isUnwrappedReturnTypeVoidOrAny(func, returnType) && !isGenerator) { + // The function has a return type, but the return statement doesn't have an expression. error(node, ts.Diagnostics.Not_all_code_paths_return_a_value); } } function checkWithStatement(node) { + // Grammar checking for withStatement if (!checkGrammarStatementInAmbientContext(node)) { - if (node.flags & 16384) { + if (node.flags & 16384 /* AwaitContext */) { grammarErrorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_an_async_function_block); } } @@ -43679,13 +51024,15 @@ var ts; } } function checkSwitchStatement(node) { + // Grammar checking checkGrammarStatementInAmbientContext(node); var firstDefaultClause; var hasDuplicateDefaultClause = false; var expressionType = checkExpression(node.expression); var expressionIsLiteral = isLiteralType(expressionType); ts.forEach(node.caseBlock.clauses, function (clause) { - if (clause.kind === 267 && !hasDuplicateDefaultClause) { + // Grammar check for duplicate default clauses, skip if we already report duplicate default clause + if (clause.kind === 267 /* DefaultClause */ && !hasDuplicateDefaultClause) { if (firstDefaultClause === undefined) { firstDefaultClause = clause; } @@ -43697,7 +51044,10 @@ var ts; hasDuplicateDefaultClause = true; } } - if (produceDiagnostics && clause.kind === 266) { + if (produceDiagnostics && clause.kind === 266 /* CaseClause */) { + // TypeScript 1.0 spec (April 2014): 5.9 + // In a 'switch' statement, each 'case' expression must be of a type that is comparable + // to or from the type of the 'switch' expression. var caseType = checkExpression(clause.expression); var caseIsLiteral = isLiteralType(caseType); var comparedExpressionType = expressionType; @@ -43706,7 +51056,8 @@ var ts; comparedExpressionType = getBaseTypeOfLiteralType(expressionType); } if (!isTypeEqualityComparableTo(comparedExpressionType, caseType)) { - checkTypeComparableTo(caseType, comparedExpressionType, clause.expression, undefined); + // expressionType is not comparable to caseType, try the reversed check and report errors if it fails + checkTypeComparableTo(caseType, comparedExpressionType, clause.expression, /*headMessage*/ undefined); } } ts.forEach(clause.statements, checkSourceElement); @@ -43716,21 +51067,24 @@ var ts; } } function checkLabeledStatement(node) { + // Grammar checking if (!checkGrammarStatementInAmbientContext(node)) { ts.findAncestor(node.parent, function (current) { if (ts.isFunctionLike(current)) { return "quit"; } - if (current.kind === 228 && current.label.escapedText === node.label.escapedText) { + if (current.kind === 228 /* LabeledStatement */ && current.label.escapedText === node.label.escapedText) { grammarErrorOnNode(node.label, ts.Diagnostics.Duplicate_label_0, ts.getTextOfNode(node.label)); return true; } return false; }); } + // ensure that label is unique checkSourceElement(node.statement); } function checkThrowStatement(node) { + // Grammar checking if (!checkGrammarStatementInAmbientContext(node)) { if (node.expression === undefined) { grammarErrorAfterFirstToken(node, ts.Diagnostics.Line_break_not_permitted_here); @@ -43741,10 +51095,12 @@ var ts; } } function checkTryStatement(node) { + // Grammar checking checkGrammarStatementInAmbientContext(node); checkBlock(node.tryBlock); var catchClause = node.catchClause; if (catchClause) { + // Grammar checking if (catchClause.variableDeclaration) { if (catchClause.variableDeclaration.type) { grammarErrorOnFirstToken(catchClause.variableDeclaration.type, ts.Diagnostics.Catch_clause_variable_cannot_have_a_type_annotation); @@ -43757,7 +51113,7 @@ var ts; if (blockLocals_1) { ts.forEachKey(catchClause.locals, function (caughtName) { var blockLocal = blockLocals_1.get(caughtName); - if (blockLocal && (blockLocal.flags & 2) !== 0) { + if (blockLocal && (blockLocal.flags & 2 /* BlockScopedVariable */) !== 0) { grammarErrorOnNode(blockLocal.valueDeclaration, ts.Diagnostics.Cannot_redeclare_identifier_0_in_catch_clause, caughtName); } }); @@ -43771,25 +51127,28 @@ var ts; } } function checkIndexConstraints(type) { - var declaredNumberIndexer = getIndexDeclarationOfSymbol(type.symbol, 1); - var declaredStringIndexer = getIndexDeclarationOfSymbol(type.symbol, 0); - var stringIndexType = getIndexTypeOfType(type, 0); - var numberIndexType = getIndexTypeOfType(type, 1); + var declaredNumberIndexer = getIndexDeclarationOfSymbol(type.symbol, 1 /* Number */); + var declaredStringIndexer = getIndexDeclarationOfSymbol(type.symbol, 0 /* String */); + var stringIndexType = getIndexTypeOfType(type, 0 /* String */); + var numberIndexType = getIndexTypeOfType(type, 1 /* Number */); if (stringIndexType || numberIndexType) { ts.forEach(getPropertiesOfObjectType(type), function (prop) { var propType = getTypeOfSymbol(prop); - checkIndexConstraintForProperty(prop, propType, type, declaredStringIndexer, stringIndexType, 0); - checkIndexConstraintForProperty(prop, propType, type, declaredNumberIndexer, numberIndexType, 1); + checkIndexConstraintForProperty(prop, propType, type, declaredStringIndexer, stringIndexType, 0 /* String */); + checkIndexConstraintForProperty(prop, propType, type, declaredNumberIndexer, numberIndexType, 1 /* Number */); }); var classDeclaration = type.symbol.valueDeclaration; - if (ts.getObjectFlags(type) & 1 && ts.isClassLike(classDeclaration)) { + if (ts.getObjectFlags(type) & 1 /* Class */ && ts.isClassLike(classDeclaration)) { for (var _i = 0, _a = classDeclaration.members; _i < _a.length; _i++) { var member = _a[_i]; - if (!ts.hasModifier(member, 32) && hasNonBindableDynamicName(member)) { + // Only process instance properties with computed names here. + // Static properties cannot be in conflict with indexers, + // and properties with literal names were already checked. + if (!ts.hasModifier(member, 32 /* Static */) && hasNonBindableDynamicName(member)) { var symbol = getSymbolOfNode(member); var propType = getTypeOfSymbol(symbol); - checkIndexConstraintForProperty(symbol, propType, type, declaredStringIndexer, stringIndexType, 0); - checkIndexConstraintForProperty(symbol, propType, type, declaredNumberIndexer, numberIndexType, 1); + checkIndexConstraintForProperty(symbol, propType, type, declaredStringIndexer, stringIndexType, 0 /* String */); + checkIndexConstraintForProperty(symbol, propType, type, declaredNumberIndexer, numberIndexType, 1 /* Number */); } } } @@ -43797,38 +51156,46 @@ var ts; var errorNode; if (stringIndexType && numberIndexType) { errorNode = declaredNumberIndexer || declaredStringIndexer; - if (!errorNode && (ts.getObjectFlags(type) & 2)) { - var someBaseTypeHasBothIndexers = ts.forEach(getBaseTypes(type), function (base) { return getIndexTypeOfType(base, 0) && getIndexTypeOfType(base, 1); }); + // condition 'errorNode === undefined' may appear if types does not declare nor string neither number indexer + if (!errorNode && (ts.getObjectFlags(type) & 2 /* Interface */)) { + var someBaseTypeHasBothIndexers = ts.forEach(getBaseTypes(type), function (base) { return getIndexTypeOfType(base, 0 /* String */) && getIndexTypeOfType(base, 1 /* Number */); }); errorNode = someBaseTypeHasBothIndexers ? undefined : type.symbol.declarations[0]; } } - if (errorNode && !isTypeAssignableTo(numberIndexType, stringIndexType)) { + if (errorNode && !isTypeAssignableTo(numberIndexType, stringIndexType)) { // TODO: GH#18217 error(errorNode, ts.Diagnostics.Numeric_index_type_0_is_not_assignable_to_string_index_type_1, typeToString(numberIndexType), typeToString(stringIndexType)); } function checkIndexConstraintForProperty(prop, propertyType, containingType, indexDeclaration, indexType, indexKind) { + // ESSymbol properties apply to neither string nor numeric indexers. if (!indexType || ts.isKnownSymbol(prop)) { return; } var propDeclaration = prop.valueDeclaration; - if (indexKind === 1 && !(propDeclaration ? isNumericName(ts.getNameOfDeclaration(propDeclaration)) : isNumericLiteralName(prop.escapedName))) { + // index is numeric and property name is not valid numeric literal + if (indexKind === 1 /* Number */ && !(propDeclaration ? isNumericName(ts.getNameOfDeclaration(propDeclaration)) : isNumericLiteralName(prop.escapedName))) { return; } + // perform property check if property or indexer is declared in 'type' + // this allows us to rule out cases when both property and indexer are inherited from the base class var errorNode; if (propDeclaration && - (propDeclaration.kind === 200 || - ts.getNameOfDeclaration(propDeclaration).kind === 147 || + (propDeclaration.kind === 200 /* BinaryExpression */ || + ts.getNameOfDeclaration(propDeclaration).kind === 147 /* ComputedPropertyName */ || prop.parent === containingType.symbol)) { errorNode = propDeclaration; } else if (indexDeclaration) { errorNode = indexDeclaration; } - else if (ts.getObjectFlags(containingType) & 2) { + else if (ts.getObjectFlags(containingType) & 2 /* Interface */) { + // for interfaces property and indexer might be inherited from different bases + // check if any base class already has both property and indexer. + // check should be performed only if 'type' is the first type that brings property\indexer together var someBaseClassHasBothPropertyAndIndexer = ts.forEach(getBaseTypes(containingType), function (base) { return getPropertyOfObjectType(base, prop.escapedName) && getIndexTypeOfType(base, indexKind); }); errorNode = someBaseClassHasBothPropertyAndIndexer ? undefined : containingType.symbol.declarations[0]; } if (errorNode && !isTypeAssignableTo(propertyType, indexType)) { - var errorMessage = indexKind === 0 + var errorMessage = indexKind === 0 /* String */ ? ts.Diagnostics.Property_0_of_type_1_is_not_assignable_to_string_index_type_2 : ts.Diagnostics.Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2; error(errorNode, errorMessage, symbolToString(prop), typeToString(propertyType), typeToString(indexType)); @@ -43836,6 +51203,8 @@ var ts; } } function checkTypeNameIsReserved(name, message) { + // TS 1.0 spec (April 2014): 3.6.1 + // The predefined type keywords are reserved and cannot be used as names of user defined types. switch (name.escapedText) { case "any": case "unknown": @@ -43848,12 +51217,18 @@ var ts; error(name, message, name.escapedText); } } + /** + * The name cannot be used as 'Object' of user defined types with special target. + */ function checkClassNameCollisionWithObject(name) { - if (languageVersion === 1 && name.escapedText === "Object" + if (languageVersion === 1 /* ES5 */ && name.escapedText === "Object" && moduleKind !== ts.ModuleKind.ES2015 && moduleKind !== ts.ModuleKind.ESNext) { - error(name, ts.Diagnostics.Class_name_cannot_be_Object_when_targeting_ES5_with_module_0, ts.ModuleKind[moduleKind]); + error(name, ts.Diagnostics.Class_name_cannot_be_Object_when_targeting_ES5_with_module_0, ts.ModuleKind[moduleKind]); // https://github.com/Microsoft/TypeScript/issues/17494 } } + /** + * Check each type parameter and check that type parameters have no duplicate type parameter declarations + */ function checkTypeParameters(typeParameterDeclarations) { if (typeParameterDeclarations) { var seenDefault = false; @@ -43876,6 +51251,7 @@ var ts; } } } + /** Check that type parameter lists are identical across multiple declarations */ function checkTypeParameterListsIdentical(symbol) { if (symbol.declarations.length === 1) { return; @@ -43889,6 +51265,7 @@ var ts; } var type = getDeclaredTypeOfSymbol(symbol); if (!areTypeParametersIdentical(declarations, type.localTypeParameters)) { + // Report an error on every conflicting declaration. var name = symbolToString(symbol); for (var _i = 0, declarations_6 = declarations; _i < declarations_6.length; _i++) { var declaration = declarations_6[_i]; @@ -43902,6 +51279,7 @@ var ts; var minTypeArgumentCount = getMinTypeArgumentCount(targetParameters); for (var _i = 0, declarations_7 = declarations; _i < declarations_7.length; _i++) { var declaration = declarations_7[_i]; + // If this declaration has too few or too many type parameters, we report an error var sourceParameters = ts.getEffectiveTypeParameterDeclarations(declaration); var numTypeParameters = sourceParameters.length; if (numTypeParameters < minTypeArgumentCount || numTypeParameters > maxTypeArgumentCount) { @@ -43910,16 +51288,23 @@ var ts; for (var i = 0; i < numTypeParameters; i++) { var source = sourceParameters[i]; var target = targetParameters[i]; + // If the type parameter node does not have the same as the resolved type + // parameter at this position, we report an error. if (source.name.escapedText !== target.symbol.escapedName) { return false; } + // If the type parameter node does not have an identical constraint as the resolved + // type parameter at this position, we report an error. var sourceConstraint = source.constraint && getTypeFromTypeNode(source.constraint); var targetConstraint = getConstraintFromTypeParameter(target); if (sourceConstraint) { + // relax check if later interface augmentation has no constraint if (!targetConstraint || !isTypeIdenticalTo(sourceConstraint, targetConstraint)) { return false; } } + // If the type parameter node has a default and it is not identical to the default + // for the type parameter at this position, we report an error. var sourceDefault = source.default && getTypeFromTypeNode(source.default); var targetDefault = getDefaultFromTypeParameter(target); if (sourceDefault && targetDefault && !isTypeIdenticalTo(sourceDefault, targetDefault)) { @@ -43939,7 +51324,7 @@ var ts; registerForUnusedIdentifiersCheck(node); } function checkClassDeclaration(node) { - if (!node.name && !ts.hasModifier(node, 512)) { + if (!node.name && !ts.hasModifier(node, 512 /* Default */)) { grammarErrorOnFirstToken(node, ts.Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name); } checkClassLikeDeclaration(node); @@ -43953,7 +51338,7 @@ var ts; checkTypeNameIsReserved(node.name, ts.Diagnostics.Class_name_cannot_be_0); checkCollisionWithRequireExportsInGeneratedCode(node, node.name); checkCollisionWithGlobalPromiseInGeneratedCode(node, node.name); - if (!(node.flags & 4194304)) { + if (!(node.flags & 4194304 /* Ambient */)) { checkClassNameCollisionWithObject(node.name); } } @@ -43965,13 +51350,14 @@ var ts; var staticType = getTypeOfSymbol(symbol); checkTypeParameterListsIdentical(symbol); checkClassForDuplicateDeclarations(node); - if (!(node.flags & 4194304)) { + // Only check for reserved static identifiers on non-ambient context. + if (!(node.flags & 4194304 /* Ambient */)) { checkClassForStaticPropertyNameConflicts(node); } var baseTypeNode = ts.getClassExtendsHeritageClauseElement(node); if (baseTypeNode) { - if (languageVersion < 2) { - checkExternalEmitHelpers(baseTypeNode.parent, 1); + if (languageVersion < 2 /* ES2015 */) { + checkExternalEmitHelpers(baseTypeNode.parent, 1 /* Extends */); } var baseTypes = getBaseTypes(type); if (baseTypes.length && produceDiagnostics) { @@ -43990,14 +51376,18 @@ var ts; } } var baseWithThis = getTypeWithThisArgument(baseType_1, type.thisType); - if (!checkTypeAssignableTo(typeWithThis, baseWithThis, undefined)) { + if (!checkTypeAssignableTo(typeWithThis, baseWithThis, /*errorNode*/ undefined)) { issueMemberSpecificError(node, typeWithThis, baseWithThis, ts.Diagnostics.Class_0_incorrectly_extends_base_class_1); } checkTypeAssignableTo(staticType, getTypeWithoutSignatures(staticBaseType), node.name || node, ts.Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1); - if (baseConstructorType.flags & 2162688 && !isMixinConstructorType(staticType)) { + if (baseConstructorType.flags & 2162688 /* TypeVariable */ && !isMixinConstructorType(staticType)) { error(node.name || node, ts.Diagnostics.A_mixin_class_must_have_a_constructor_with_a_single_rest_parameter_of_type_any); } - if (!(staticBaseType.symbol && staticBaseType.symbol.flags & 32) && !(baseConstructorType.flags & 2162688)) { + if (!(staticBaseType.symbol && staticBaseType.symbol.flags & 32 /* Class */) && !(baseConstructorType.flags & 2162688 /* TypeVariable */)) { + // When the static base type is a "class-like" constructor function (but not actually a class), we verify + // that all instantiated base constructor signatures return the same type. We can simply compare the type + // references (as opposed to checking the structure of the types) because elsewhere we have already checked + // that the base type is a class or interface type (and not, for example, an anonymous object type). var constructors = getInstantiatedConstructorsForTypeArguments(staticBaseType, baseTypeNode.typeArguments, baseTypeNode); if (ts.forEach(constructors, function (sig) { return getReturnTypeOfSignature(sig) !== baseType_1; })) { error(baseTypeNode.expression, ts.Diagnostics.Base_constructors_must_all_have_the_same_return_type); @@ -44018,11 +51408,11 @@ var ts; var t = getTypeFromTypeNode(typeRefNode); if (t !== errorType) { if (isValidBaseType(t)) { - var genericDiag = t.symbol && t.symbol.flags & 32 ? + var genericDiag = t.symbol && t.symbol.flags & 32 /* Class */ ? ts.Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass : ts.Diagnostics.Class_0_incorrectly_implements_interface_1; var baseWithThis = getTypeWithThisArgument(t, type.thisType); - if (!checkTypeAssignableTo(typeWithThis, baseWithThis, undefined)) { + if (!checkTypeAssignableTo(typeWithThis, baseWithThis, /*errorNode*/ undefined)) { issueMemberSpecificError(node, typeWithThis, baseWithThis, genericDiag); } } @@ -44040,6 +51430,7 @@ var ts; } } function issueMemberSpecificError(node, typeWithThis, baseWithThis, broadDiag) { + // iterate over all implemented properties and issue errors on each one which isn't compatible, rather than the class as a whole, if possible var issuedMemberError = false; var _loop_9 = function (member) { if (ts.hasStaticModifier(member)) { @@ -44050,8 +51441,9 @@ var ts; var prop = getPropertyOfType(typeWithThis, declaredProp.escapedName); var baseProp = getPropertyOfType(baseWithThis, declaredProp.escapedName); if (prop && baseProp) { - var rootChain = function () { return ts.chainDiagnosticMessages(undefined, ts.Diagnostics.Property_0_in_type_1_is_not_assignable_to_the_same_property_in_base_type_2, symbolToString(declaredProp), typeToString(typeWithThis), typeToString(baseWithThis)); }; - if (!checkTypeAssignableTo(getTypeOfSymbol(prop), getTypeOfSymbol(baseProp), member.name || member, undefined, rootChain)) { + var rootChain = function () { return ts.chainDiagnosticMessages( + /*details*/ undefined, ts.Diagnostics.Property_0_in_type_1_is_not_assignable_to_the_same_property_in_base_type_2, symbolToString(declaredProp), typeToString(typeWithThis), typeToString(baseWithThis)); }; + if (!checkTypeAssignableTo(getTypeOfSymbol(prop), getTypeOfSymbol(baseProp), member.name || member, /*message*/ undefined, rootChain)) { issuedMemberError = true; } } @@ -44062,14 +51454,15 @@ var ts; _loop_9(member); } if (!issuedMemberError) { + // check again with diagnostics to generate a less-specific error checkTypeAssignableTo(typeWithThis, baseWithThis, node.name || node, broadDiag); } } function checkBaseTypeAccessibility(type, node) { - var signatures = getSignaturesOfType(type, 1); + var signatures = getSignaturesOfType(type, 1 /* Construct */); if (signatures.length) { var declaration = signatures[0].declaration; - if (declaration && ts.hasModifier(declaration, 8)) { + if (declaration && ts.hasModifier(declaration, 8 /* Private */)) { var typeClassDeclaration = ts.getClassLikeDeclarationOfSymbol(type.symbol); if (!isNodeWithinClass(node, typeClassDeclaration)) { error(node, ts.Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, getFullyQualifiedName(type.symbol)); @@ -44078,29 +51471,52 @@ var ts; } } function getTargetSymbol(s) { - return ts.getCheckFlags(s) & 1 ? s.target : s; + // if symbol is instantiated its flags are not copied from the 'target' + // so we'll need to get back original 'target' symbol to work with correct set of flags + return ts.getCheckFlags(s) & 1 /* Instantiated */ ? s.target : s; } function getClassOrInterfaceDeclarationsOfSymbol(symbol) { return ts.filter(symbol.declarations, function (d) { - return d.kind === 235 || d.kind === 236; + return d.kind === 235 /* ClassDeclaration */ || d.kind === 236 /* InterfaceDeclaration */; }); } function checkKindsOfPropertyMemberOverrides(type, baseType) { + // TypeScript 1.0 spec (April 2014): 8.2.3 + // A derived class inherits all members from its base class it doesn't override. + // Inheritance means that a derived class implicitly contains all non - overridden members of the base class. + // Both public and private property members are inherited, but only public property members can be overridden. + // A property member in a derived class is said to override a property member in a base class + // when the derived class property member has the same name and kind(instance or static) + // as the base class property member. + // The type of an overriding property member must be assignable(section 3.8.4) + // to the type of the overridden property member, or otherwise a compile - time error occurs. + // Base class instance member functions can be overridden by derived class instance member functions, + // but not by other kinds of members. + // Base class instance member variables and accessors can be overridden by + // derived class instance member variables and accessors, but not by other kinds of members. + // NOTE: assignability is checked in checkClassDeclaration var baseProperties = getPropertiesOfType(baseType); for (var _i = 0, baseProperties_1 = baseProperties; _i < baseProperties_1.length; _i++) { var baseProperty = baseProperties_1[_i]; var base = getTargetSymbol(baseProperty); - if (base.flags & 4194304) { + if (base.flags & 4194304 /* Prototype */) { continue; } - var derived = getTargetSymbol(getPropertyOfObjectType(type, base.escapedName)); + var derived = getTargetSymbol(getPropertyOfObjectType(type, base.escapedName)); // TODO: GH#18217 var baseDeclarationFlags = ts.getDeclarationModifierFlagsFromSymbol(base); ts.Debug.assert(!!derived, "derived should point to something, even if it is the base class' declaration."); if (derived) { + // In order to resolve whether the inherited method was overridden in the base class or not, + // we compare the Symbols obtained. Since getTargetSymbol returns the symbol on the *uninstantiated* + // type declaration, derived and base resolve to the same symbol even in the case of generic classes. if (derived === base) { + // derived class inherits base without override/redeclaration var derivedClassDecl = ts.getClassLikeDeclarationOfSymbol(type.symbol); - if (baseDeclarationFlags & 128 && (!derivedClassDecl || !ts.hasModifier(derivedClassDecl, 128))) { - if (derivedClassDecl.kind === 205) { + // It is an error to inherit an abstract member without implementing it or being declared abstract. + // If there is no declaration for the derived class (as in the case of class expressions), + // then the class cannot be declared abstract. + if (baseDeclarationFlags & 128 /* Abstract */ && (!derivedClassDecl || !ts.hasModifier(derivedClassDecl, 128 /* Abstract */))) { + if (derivedClassDecl.kind === 205 /* ClassExpression */) { error(derivedClassDecl, ts.Diagnostics.Non_abstract_class_expression_does_not_implement_inherited_abstract_member_0_from_class_1, symbolToString(baseProperty), typeToString(baseType)); } else { @@ -44109,23 +51525,26 @@ var ts; } } else { + // derived overrides base. var derivedDeclarationFlags = ts.getDeclarationModifierFlagsFromSymbol(derived); - if (baseDeclarationFlags & 8 || derivedDeclarationFlags & 8) { + if (baseDeclarationFlags & 8 /* Private */ || derivedDeclarationFlags & 8 /* Private */) { + // either base or derived property is private - not override, skip it continue; } - if (isPrototypeProperty(base) || base.flags & 98308 && derived.flags & 98308) { + if (isPrototypeProperty(base) || base.flags & 98308 /* PropertyOrAccessor */ && derived.flags & 98308 /* PropertyOrAccessor */) { + // method is overridden with method or property/accessor is overridden with property/accessor - correct case continue; } var errorMessage = void 0; if (isPrototypeProperty(base)) { - if (derived.flags & 98304) { + if (derived.flags & 98304 /* Accessor */) { errorMessage = ts.Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor; } else { errorMessage = ts.Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_property; } } - else if (base.flags & 98304) { + else if (base.flags & 98304 /* Accessor */) { errorMessage = ts.Diagnostics.Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function; } else { @@ -44159,7 +51578,7 @@ var ts; ok = false; var typeName1 = typeToString(existing.containingType); var typeName2 = typeToString(base); - var errorInfo = ts.chainDiagnosticMessages(undefined, ts.Diagnostics.Named_property_0_of_types_1_and_2_are_not_identical, symbolToString(prop), typeName1, typeName2); + var errorInfo = ts.chainDiagnosticMessages(/*details*/ undefined, ts.Diagnostics.Named_property_0_of_types_1_and_2_are_not_identical, symbolToString(prop), typeName1, typeName2); errorInfo = ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.Interface_0_cannot_simultaneously_extend_types_1_and_2, typeToString(type), typeName1, typeName2); diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(typeNode, errorInfo)); } @@ -44169,7 +51588,7 @@ var ts; return ok; } function checkPropertyInitialization(node) { - if (!strictNullChecks || !strictPropertyInitialization || node.flags & 4194304) { + if (!strictNullChecks || !strictPropertyInitialization || node.flags & 4194304 /* Ambient */) { return; } var constructor = findConstructorDeclaration(node); @@ -44179,7 +51598,7 @@ var ts; var propName = member.name; if (ts.isIdentifier(propName)) { var type = getTypeOfSymbol(getSymbolOfNode(member)); - if (!(type.flags & 3 || getFalsyFlags(type) & 8192)) { + if (!(type.flags & 3 /* AnyOrUnknown */ || getFalsyFlags(type) & 8192 /* Undefined */)) { if (!constructor || !isPropertyInitializedInConstructor(propName, type, constructor)) { error(member.name, ts.Diagnostics.Property_0_has_no_initializer_and_is_not_definitely_assigned_in_the_constructor, ts.declarationNameToString(propName)); } @@ -44189,8 +51608,8 @@ var ts; } } function isInstancePropertyWithoutInitializer(node) { - return node.kind === 152 && - !ts.hasModifier(node, 32 | 128) && + return node.kind === 152 /* PropertyDeclaration */ && + !ts.hasModifier(node, 32 /* Static */ | 128 /* Abstract */) && !node.exclamationToken && !node.initializer; } @@ -44198,9 +51617,10 @@ var ts; var reference = ts.createPropertyAccess(ts.createThis(), propName); reference.flowNode = constructor.returnFlowNode; var flowType = getFlowTypeOfReference(reference, propType, getOptionalType(propType)); - return !(getFalsyFlags(flowType) & 8192); + return !(getFalsyFlags(flowType) & 8192 /* Undefined */); } function checkInterfaceDeclaration(node) { + // Grammar checking if (!checkGrammarDecoratorsAndModifiers(node)) checkGrammarInterfaceDeclaration(node); checkTypeParameters(node.typeParameters); @@ -44209,10 +51629,12 @@ var ts; checkExportsOnMergedDeclarations(node); var symbol = getSymbolOfNode(node); checkTypeParameterListsIdentical(symbol); - var firstInterfaceDecl = ts.getDeclarationOfKind(symbol, 236); + // Only check this symbol once + var firstInterfaceDecl = ts.getDeclarationOfKind(symbol, 236 /* InterfaceDeclaration */); if (node === firstInterfaceDecl) { var type = getDeclaredTypeOfSymbol(symbol); var typeWithThis = getTypeWithThisArgument(type); + // run subsequent checks only if first set succeeded if (checkInheritedPropertiesAreIdentical(type, node.name)) { for (var _i = 0, _a = getBaseTypes(type); _i < _a.length; _i++) { var baseType = _a[_i]; @@ -44236,6 +51658,7 @@ var ts; } } function checkTypeAliasDeclaration(node) { + // Grammar checking checkGrammarDecoratorsAndModifiers(node); checkTypeNameIsReserved(node.name, ts.Diagnostics.Type_alias_name_cannot_be_0); checkTypeParameters(node.typeParameters); @@ -44244,8 +51667,8 @@ var ts; } function computeEnumMemberValues(node) { var nodeLinks = getNodeLinks(node); - if (!(nodeLinks.flags & 16384)) { - nodeLinks.flags |= 16384; + if (!(nodeLinks.flags & 16384 /* EnumValuesComputed */)) { + nodeLinks.flags |= 16384 /* EnumValuesComputed */; var autoValue = 0; for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var member = _a[_i]; @@ -44268,9 +51691,15 @@ var ts; if (member.initializer) { return computeConstantValue(member); } - if (member.parent.flags & 4194304 && !ts.isConst(member.parent)) { + // In ambient enum declarations that specify no const modifier, enum member declarations that omit + // a value are considered computed members (as opposed to having auto-incremented values). + if (member.parent.flags & 4194304 /* Ambient */ && !ts.isConst(member.parent)) { return undefined; } + // If the member declaration specifies no value, the member is considered a constant enum member. + // If the member is the first member in the enum declaration, it is assigned the value zero. + // Otherwise, it is assigned the value of the immediately preceding member plus one, and an error + // occurs if the immediately preceding member is not a constant enum member. if (autoValue !== undefined) { return autoValue; } @@ -44281,7 +51710,7 @@ var ts; var enumKind = getEnumKind(getSymbolOfNode(member.parent)); var isConstEnum = ts.isConst(member.parent); var initializer = member.initializer; - var value = enumKind === 1 && !isLiteralEnumMember(member) ? undefined : evaluate(initializer); + var value = enumKind === 1 /* Literal */ && !isLiteralEnumMember(member) ? undefined : evaluate(initializer); if (value !== undefined) { if (isConstEnum && typeof value === "number" && !isFinite(value)) { error(initializer, isNaN(value) ? @@ -44289,76 +51718,77 @@ var ts; ts.Diagnostics.const_enum_member_initializer_was_evaluated_to_a_non_finite_value); } } - else if (enumKind === 1) { + else if (enumKind === 1 /* Literal */) { error(initializer, ts.Diagnostics.Computed_values_are_not_permitted_in_an_enum_with_string_valued_members); return 0; } else if (isConstEnum) { error(initializer, ts.Diagnostics.In_const_enum_declarations_member_initializer_must_be_constant_expression); } - else if (member.parent.flags & 4194304) { + else if (member.parent.flags & 4194304 /* Ambient */) { error(initializer, ts.Diagnostics.In_ambient_enum_declarations_member_initializer_must_be_constant_expression); } else { - checkTypeAssignableTo(checkExpression(initializer), getDeclaredTypeOfSymbol(getSymbolOfNode(member.parent)), initializer, undefined); + // Only here do we need to check that the initializer is assignable to the enum type. + checkTypeAssignableTo(checkExpression(initializer), getDeclaredTypeOfSymbol(getSymbolOfNode(member.parent)), initializer, /*headMessage*/ undefined); } return value; function evaluate(expr) { switch (expr.kind) { - case 198: + case 198 /* PrefixUnaryExpression */: var value_2 = evaluate(expr.operand); if (typeof value_2 === "number") { switch (expr.operator) { - case 37: return value_2; - case 38: return -value_2; - case 52: return ~value_2; + case 37 /* PlusToken */: return value_2; + case 38 /* MinusToken */: return -value_2; + case 52 /* TildeToken */: return ~value_2; } } break; - case 200: + case 200 /* BinaryExpression */: var left = evaluate(expr.left); var right = evaluate(expr.right); if (typeof left === "number" && typeof right === "number") { switch (expr.operatorToken.kind) { - case 49: return left | right; - case 48: return left & right; - case 46: return left >> right; - case 47: return left >>> right; - case 45: return left << right; - case 50: return left ^ right; - case 39: return left * right; - case 41: return left / right; - case 37: return left + right; - case 38: return left - right; - case 42: return left % right; - case 40: return Math.pow(left, right); + case 49 /* BarToken */: return left | right; + case 48 /* AmpersandToken */: return left & right; + case 46 /* GreaterThanGreaterThanToken */: return left >> right; + case 47 /* GreaterThanGreaterThanGreaterThanToken */: return left >>> right; + case 45 /* LessThanLessThanToken */: return left << right; + case 50 /* CaretToken */: return left ^ right; + case 39 /* AsteriskToken */: return left * right; + case 41 /* SlashToken */: return left / right; + case 37 /* PlusToken */: return left + right; + case 38 /* MinusToken */: return left - right; + case 42 /* PercentToken */: return left % right; + case 40 /* AsteriskAsteriskToken */: return Math.pow(left, right); } } - else if (typeof left === "string" && typeof right === "string" && expr.operatorToken.kind === 37) { + else if (typeof left === "string" && typeof right === "string" && expr.operatorToken.kind === 37 /* PlusToken */) { return left + right; } break; - case 9: + case 9 /* StringLiteral */: return expr.text; - case 8: + case 8 /* NumericLiteral */: checkGrammarNumericLiteral(expr); return +expr.text; - case 191: + case 191 /* ParenthesizedExpression */: return evaluate(expr.expression); - case 71: + case 71 /* Identifier */: var identifier = expr; if (isInfinityOrNaNString(identifier.escapedText)) { return +(identifier.escapedText); } return ts.nodeIsMissing(expr) ? 0 : evaluateEnumMember(expr, getSymbolOfNode(member.parent), identifier.escapedText); - case 186: - case 185: + case 186 /* ElementAccessExpression */: + case 185 /* PropertyAccessExpression */: var ex = expr; if (isConstantMemberAccess(ex)) { var type = getTypeOfExpression(ex.expression); - if (type.symbol && type.symbol.flags & 384) { + if (type.symbol && type.symbol.flags & 384 /* Enum */) { var name = void 0; - if (ex.kind === 185) { + if (ex.kind === 185 /* PropertyAccessExpression */) { name = ex.name.escapedText; } else { @@ -44389,15 +51819,16 @@ var ts; } } function isConstantMemberAccess(node) { - return node.kind === 71 || - node.kind === 185 && isConstantMemberAccess(node.expression) || - node.kind === 186 && isConstantMemberAccess(node.expression) && - node.argumentExpression.kind === 9; + return node.kind === 71 /* Identifier */ || + node.kind === 185 /* PropertyAccessExpression */ && isConstantMemberAccess(node.expression) || + node.kind === 186 /* ElementAccessExpression */ && isConstantMemberAccess(node.expression) && + node.argumentExpression.kind === 9 /* StringLiteral */; } function checkEnumDeclaration(node) { if (!produceDiagnostics) { return; } + // Grammar checking checkGrammarDecoratorsAndModifiers(node); checkTypeNameIsReserved(node.name, ts.Diagnostics.Enum_name_cannot_be_0); checkCollisionWithRequireExportsInGeneratedCode(node, node.name); @@ -44405,13 +51836,20 @@ var ts; checkExportsOnMergedDeclarations(node); computeEnumMemberValues(node); var enumIsConst = ts.isConst(node); - if (compilerOptions.isolatedModules && enumIsConst && node.flags & 4194304) { + if (compilerOptions.isolatedModules && enumIsConst && node.flags & 4194304 /* Ambient */) { error(node.name, ts.Diagnostics.Ambient_const_enums_are_not_allowed_when_the_isolatedModules_flag_is_provided); } + // Spec 2014 - Section 9.3: + // It isn't possible for one enum declaration to continue the automatic numbering sequence of another, + // and when an enum type has multiple declarations, only one declaration is permitted to omit a value + // for the first member. + // + // Only perform this check once per symbol var enumSymbol = getSymbolOfNode(node); var firstDeclaration = ts.getDeclarationOfKind(enumSymbol, node.kind); if (node === firstDeclaration) { if (enumSymbol.declarations.length > 1) { + // check that const is placed\omitted on all enum declarations ts.forEach(enumSymbol.declarations, function (decl) { if (ts.isConstEnumDeclaration(decl) !== enumIsConst) { error(ts.getNameOfDeclaration(decl), ts.Diagnostics.Enum_declarations_must_all_be_const_or_non_const); @@ -44420,7 +51858,8 @@ var ts; } var seenEnumMissingInitialInitializer_1 = false; ts.forEach(enumSymbol.declarations, function (declaration) { - if (declaration.kind !== 238) { + // return true if we hit a violation of the rule, false otherwise + if (declaration.kind !== 238 /* EnumDeclaration */) { return false; } var enumDeclaration = declaration; @@ -44443,9 +51882,9 @@ var ts; var declarations = symbol.declarations; for (var _i = 0, declarations_8 = declarations; _i < declarations_8.length; _i++) { var declaration = declarations_8[_i]; - if ((declaration.kind === 235 || - (declaration.kind === 234 && ts.nodeIsPresent(declaration.body))) && - !(declaration.flags & 4194304)) { + if ((declaration.kind === 235 /* ClassDeclaration */ || + (declaration.kind === 234 /* FunctionDeclaration */ && ts.nodeIsPresent(declaration.body))) && + !(declaration.flags & 4194304 /* Ambient */)) { return declaration; } } @@ -44466,8 +51905,9 @@ var ts; } function checkModuleDeclaration(node) { if (produceDiagnostics) { + // Grammar checking var isGlobalAugmentation = ts.isGlobalScopeAugmentation(node); - var inAmbientContext = node.flags & 4194304; + var inAmbientContext = node.flags & 4194304 /* Ambient */; if (isGlobalAugmentation && !inAmbientContext) { error(node.name, ts.Diagnostics.Augmentations_for_the_global_scope_should_have_declare_modifier_unless_they_appear_in_already_ambient_context); } @@ -44476,10 +51916,11 @@ var ts; ? ts.Diagnostics.An_ambient_module_declaration_is_only_allowed_at_the_top_level_in_a_file : ts.Diagnostics.A_namespace_declaration_is_only_allowed_in_a_namespace_or_module; if (checkGrammarModuleElementContext(node, contextErrorMessage)) { + // If we hit a module declaration in an illegal context, just bail out to avoid cascading errors. return; } if (!checkGrammarDecoratorsAndModifiers(node)) { - if (!inAmbientContext && node.name.kind === 9) { + if (!inAmbientContext && node.name.kind === 9 /* StringLiteral */) { grammarErrorOnNode(node.name, ts.Diagnostics.Only_ambient_modules_can_use_quoted_names); } } @@ -44489,7 +51930,8 @@ var ts; } checkExportsOnMergedDeclarations(node); var symbol = getSymbolOfNode(node); - if (symbol.flags & 512 + // The following checks only apply on a non-ambient instantiated module declaration. + if (symbol.flags & 512 /* ValueModule */ && symbol.declarations.length > 1 && !inAmbientContext && isInstantiatedModule(node, !!compilerOptions.preserveConstEnums || !!compilerOptions.isolatedModules)) { @@ -44502,15 +51944,22 @@ var ts; error(node.name, ts.Diagnostics.A_namespace_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged); } } - var mergedClass = ts.getDeclarationOfKind(symbol, 235); + // if the module merges with a class declaration in the same lexical scope, + // we need to track this to ensure the correct emit. + var mergedClass = ts.getDeclarationOfKind(symbol, 235 /* ClassDeclaration */); if (mergedClass && inSameLexicalScope(node, mergedClass)) { - getNodeLinks(node).flags |= 32768; + getNodeLinks(node).flags |= 32768 /* LexicalModuleMergesWithClass */; } } if (isAmbientExternalModule) { if (ts.isExternalModuleAugmentation(node)) { - var checkBody = isGlobalAugmentation || (getSymbolOfNode(node).flags & 33554432); + // body of the augmentation should be checked for consistency only if augmentation was applied to its target (either global scope or module) + // otherwise we'll be swamped in cascading errors. + // We can detect if augmentation was applied using following rules: + // - augmentation for a global scope is always applied + // - augmentation for some external module is applied if symbol for augmentation is merged (it was combined with target module). + var checkBody = isGlobalAugmentation || (getSymbolOfNode(node).flags & 33554432 /* Transient */); if (checkBody && node.body) { for (var _i = 0, _a = node.body.statements; _i < _a.length; _i++) { var statement = _a[_i]; @@ -44531,6 +51980,8 @@ var ts; error(node.name, ts.Diagnostics.Augmentations_for_the_global_scope_can_only_be_directly_nested_in_external_modules_or_ambient_module_declarations); } else { + // Node is not an augmentation and is not located on the script level. + // This means that this is declaration of ambient module that is located in other module or namespace which is prohibited. error(node.name, ts.Diagnostics.Ambient_modules_cannot_be_nested_in_other_modules_or_namespaces); } } @@ -44545,43 +51996,51 @@ var ts; } function checkModuleAugmentationElement(node, isGlobalAugmentation) { switch (node.kind) { - case 214: + case 214 /* VariableStatement */: + // error each individual name in variable statement instead of marking the entire variable statement for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) { var decl = _a[_i]; checkModuleAugmentationElement(decl, isGlobalAugmentation); } break; - case 249: - case 250: + case 249 /* ExportAssignment */: + case 250 /* ExportDeclaration */: grammarErrorOnFirstToken(node, ts.Diagnostics.Exports_and_export_assignments_are_not_permitted_in_module_augmentations); break; - case 243: - case 244: + case 243 /* ImportEqualsDeclaration */: + case 244 /* ImportDeclaration */: grammarErrorOnFirstToken(node, ts.Diagnostics.Imports_are_not_permitted_in_module_augmentations_Consider_moving_them_to_the_enclosing_external_module); break; - case 182: - case 232: + case 182 /* BindingElement */: + case 232 /* VariableDeclaration */: var name = node.name; if (ts.isBindingPattern(name)) { for (var _b = 0, _c = name.elements; _b < _c.length; _b++) { var el = _c[_b]; + // mark individual names in binding pattern checkModuleAugmentationElement(el, isGlobalAugmentation); } break; } - case 235: - case 238: - case 234: - case 236: - case 239: - case 237: + // falls through + case 235 /* ClassDeclaration */: + case 238 /* EnumDeclaration */: + case 234 /* FunctionDeclaration */: + case 236 /* InterfaceDeclaration */: + case 239 /* ModuleDeclaration */: + case 237 /* TypeAliasDeclaration */: if (isGlobalAugmentation) { return; } var symbol = getSymbolOfNode(node); if (symbol) { - var reportError = !(symbol.flags & 33554432); + // module augmentations cannot introduce new names on the top level scope of the module + // this is done it two steps + // 1. quick check - if symbol for node is not merged - this is local symbol to this augmentation - report error + // 2. main check - report error if value declaration of the parent symbol is module augmentation) + var reportError = !(symbol.flags & 33554432 /* Transient */); if (!reportError) { + // symbol should not originate in augmentation reportError = ts.isExternalModuleAugmentation(symbol.parent.declarations[0]); } } @@ -44590,38 +52049,45 @@ var ts; } function getFirstIdentifier(node) { switch (node.kind) { - case 71: + case 71 /* Identifier */: return node; - case 146: + case 146 /* QualifiedName */: do { node = node.left; - } while (node.kind !== 71); + } while (node.kind !== 71 /* Identifier */); return node; - case 185: + case 185 /* PropertyAccessExpression */: do { node = node.expression; - } while (node.kind !== 71); + } while (node.kind !== 71 /* Identifier */); return node; } } function checkExternalImportOrExportDeclaration(node) { var moduleName = ts.getExternalModuleName(node); if (!moduleName || ts.nodeIsMissing(moduleName)) { + // Should be a parse error. return false; } if (!ts.isStringLiteral(moduleName)) { error(moduleName, ts.Diagnostics.String_literal_expected); return false; } - var inAmbientExternalModule = node.parent.kind === 240 && ts.isAmbientModule(node.parent.parent); - if (node.parent.kind !== 274 && !inAmbientExternalModule) { - error(moduleName, node.kind === 250 ? + var inAmbientExternalModule = node.parent.kind === 240 /* ModuleBlock */ && ts.isAmbientModule(node.parent.parent); + if (node.parent.kind !== 274 /* SourceFile */ && !inAmbientExternalModule) { + error(moduleName, node.kind === 250 /* ExportDeclaration */ ? ts.Diagnostics.Export_declarations_are_not_permitted_in_a_namespace : ts.Diagnostics.Import_declarations_in_a_namespace_cannot_reference_a_module); return false; } if (inAmbientExternalModule && ts.isExternalModuleNameRelative(moduleName.text)) { + // we have already reported errors on top level imports\exports in external module augmentations in checkModuleDeclaration + // no need to do this again. if (!isTopLevelInExternalModuleAugmentation(node)) { + // TypeScript 1.0 spec (April 2013): 12.1.6 + // An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference + // other external modules only through top - level external module names. + // Relative external module names are not permitted. error(node, ts.Diagnostics.Import_or_export_declaration_in_an_ambient_module_declaration_cannot_reference_module_through_relative_module_name); return false; } @@ -44632,19 +52098,26 @@ var ts; var symbol = getSymbolOfNode(node); var target = resolveAlias(symbol); if (target !== unknownSymbol) { - var excludedMeanings = (symbol.flags & (67216319 | 1048576) ? 67216319 : 0) | - (symbol.flags & 67901928 ? 67901928 : 0) | - (symbol.flags & 1920 ? 1920 : 0); + // For external modules symbol represent local symbol for an alias. + // This local symbol will merge any other local declarations (excluding other aliases) + // and symbol.flags will contains combined representation for all merged declaration. + // Based on symbol.flags we can compute a set of excluded meanings (meaning that resolved alias should not have, + // otherwise it will conflict with some local declaration). Note that in addition to normal flags we include matching SymbolFlags.Export* + // in order to prevent collisions with declarations that were exported from the current module (they still contribute to local names). + var excludedMeanings = (symbol.flags & (67216319 /* Value */ | 1048576 /* ExportValue */) ? 67216319 /* Value */ : 0) | + (symbol.flags & 67901928 /* Type */ ? 67901928 /* Type */ : 0) | + (symbol.flags & 1920 /* Namespace */ ? 1920 /* Namespace */ : 0); if (target.flags & excludedMeanings) { - var message = node.kind === 252 ? + var message = node.kind === 252 /* ExportSpecifier */ ? ts.Diagnostics.Export_declaration_conflicts_with_exported_declaration_of_0 : ts.Diagnostics.Import_declaration_conflicts_with_local_declaration_of_0; error(node, message, symbolToString(symbol)); } + // Don't allow to re-export something with no value side when `--isolatedModules` is set. if (compilerOptions.isolatedModules - && node.kind === 252 - && !(target.flags & 67216319) - && !(node.flags & 4194304)) { + && node.kind === 252 /* ExportSpecifier */ + && !(target.flags & 67216319 /* Value */) + && !(node.flags & 4194304 /* Ambient */)) { error(node, ts.Diagnostics.Cannot_re_export_a_type_when_the_isolatedModules_flag_is_provided); } } @@ -44656,6 +52129,7 @@ var ts; } function checkImportDeclaration(node) { if (checkGrammarModuleElementContext(node, ts.Diagnostics.An_import_declaration_can_only_be_used_in_a_namespace_or_module)) { + // If we hit an import declaration in an illegal context, just bail out to avoid cascading errors. return; } if (!checkGrammarDecoratorsAndModifiers(node) && ts.hasModifiers(node)) { @@ -44668,7 +52142,7 @@ var ts; checkImportBinding(importClause); } if (importClause.namedBindings) { - if (importClause.namedBindings.kind === 246) { + if (importClause.namedBindings.kind === 246 /* NamespaceImport */) { checkImportBinding(importClause.namedBindings); } else { @@ -44683,30 +52157,33 @@ var ts; } function checkImportEqualsDeclaration(node) { if (checkGrammarModuleElementContext(node, ts.Diagnostics.An_import_declaration_can_only_be_used_in_a_namespace_or_module)) { + // If we hit an import declaration in an illegal context, just bail out to avoid cascading errors. return; } checkGrammarDecoratorsAndModifiers(node); if (ts.isInternalModuleImportEqualsDeclaration(node) || checkExternalImportOrExportDeclaration(node)) { checkImportBinding(node); - if (ts.hasModifier(node, 1)) { + if (ts.hasModifier(node, 1 /* Export */)) { markExportAsReferenced(node); } - if (node.moduleReference.kind !== 254) { + if (node.moduleReference.kind !== 254 /* ExternalModuleReference */) { var target = resolveAlias(getSymbolOfNode(node)); if (target !== unknownSymbol) { - if (target.flags & 67216319) { + if (target.flags & 67216319 /* Value */) { + // Target is a value symbol, check that it is not hidden by a local declaration with the same name var moduleName = getFirstIdentifier(node.moduleReference); - if (!(resolveEntityName(moduleName, 67216319 | 1920).flags & 1920)) { + if (!(resolveEntityName(moduleName, 67216319 /* Value */ | 1920 /* Namespace */).flags & 1920 /* Namespace */)) { error(moduleName, ts.Diagnostics.Module_0_is_hidden_by_a_local_declaration_with_the_same_name, ts.declarationNameToString(moduleName)); } } - if (target.flags & 67901928) { + if (target.flags & 67901928 /* Type */) { checkTypeNameIsReserved(node.name, ts.Diagnostics.Import_name_cannot_be_0); } } } else { - if (moduleKind >= ts.ModuleKind.ES2015 && !(node.flags & 4194304)) { + if (moduleKind >= ts.ModuleKind.ES2015 && !(node.flags & 4194304 /* Ambient */)) { + // Import equals declaration is deprecated in es6 or above grammarErrorOnNode(node, ts.Diagnostics.Import_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_import_d_from_mod_or_another_module_format_instead); } } @@ -44714,6 +52191,7 @@ var ts; } function checkExportDeclaration(node) { if (checkGrammarModuleElementContext(node, ts.Diagnostics.An_export_declaration_can_only_be_used_in_a_module)) { + // If we hit an export in an illegal context, just bail out to avoid cascading errors. return; } if (!checkGrammarDecoratorsAndModifiers(node) && ts.hasModifiers(node)) { @@ -44721,27 +52199,30 @@ var ts; } if (!node.moduleSpecifier || checkExternalImportOrExportDeclaration(node)) { if (node.exportClause) { + // export { x, y } + // export { x, y } from "foo" ts.forEach(node.exportClause.elements, checkExportSpecifier); - var inAmbientExternalModule = node.parent.kind === 240 && ts.isAmbientModule(node.parent.parent); - var inAmbientNamespaceDeclaration = !inAmbientExternalModule && node.parent.kind === 240 && - !node.moduleSpecifier && node.flags & 4194304; - if (node.parent.kind !== 274 && !inAmbientExternalModule && !inAmbientNamespaceDeclaration) { + var inAmbientExternalModule = node.parent.kind === 240 /* ModuleBlock */ && ts.isAmbientModule(node.parent.parent); + var inAmbientNamespaceDeclaration = !inAmbientExternalModule && node.parent.kind === 240 /* ModuleBlock */ && + !node.moduleSpecifier && node.flags & 4194304 /* Ambient */; + if (node.parent.kind !== 274 /* SourceFile */ && !inAmbientExternalModule && !inAmbientNamespaceDeclaration) { error(node, ts.Diagnostics.Export_declarations_are_not_permitted_in_a_namespace); } } else { + // export * from "foo" var moduleSymbol_2 = resolveExternalModuleName(node, node.moduleSpecifier); if (moduleSymbol_2 && hasExportAssignmentSymbol(moduleSymbol_2)) { error(node.moduleSpecifier, ts.Diagnostics.Module_0_uses_export_and_cannot_be_used_with_export_Asterisk, symbolToString(moduleSymbol_2)); } if (moduleKind !== ts.ModuleKind.System && moduleKind !== ts.ModuleKind.ES2015 && moduleKind !== ts.ModuleKind.ESNext) { - checkExternalEmitHelpers(node, 32768); + checkExternalEmitHelpers(node, 32768 /* ExportStar */); } } } } function checkGrammarModuleElementContext(node, errorMessage) { - var isInAppropriateContext = node.parent.kind === 274 || node.parent.kind === 240 || node.parent.kind === 239; + var isInAppropriateContext = node.parent.kind === 274 /* SourceFile */ || node.parent.kind === 240 /* ModuleBlock */ || node.parent.kind === 239 /* ModuleDeclaration */; if (!isInAppropriateContext) { grammarErrorOnFirstToken(node, errorMessage); } @@ -44750,11 +52231,13 @@ var ts; function checkExportSpecifier(node) { checkAliasSymbol(node); if (compilerOptions.declaration) { - collectLinkedAliases(node.propertyName || node.name, true); + collectLinkedAliases(node.propertyName || node.name, /*setVisibility*/ true); } if (!node.parent.parent.moduleSpecifier) { var exportedName = node.propertyName || node.name; - var symbol = resolveName(exportedName, exportedName.escapedText, 67216319 | 67901928 | 1920 | 2097152, undefined, undefined, true); + // find immediate value referenced by exported name (SymbolFlags.Alias is set so we don't chase down aliases) + var symbol = resolveName(exportedName, exportedName.escapedText, 67216319 /* Value */ | 67901928 /* Type */ | 1920 /* Namespace */ | 2097152 /* Alias */, + /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); if (symbol && (symbol === undefinedSymbol || isGlobalSourceFile(getDeclarationContainer(symbol.declarations[0])))) { error(exportedName, ts.Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, ts.idText(exportedName)); } @@ -44765,10 +52248,11 @@ var ts; } function checkExportAssignment(node) { if (checkGrammarModuleElementContext(node, ts.Diagnostics.An_export_assignment_can_only_be_used_in_a_module)) { + // If we hit an export assignment in an illegal context, just bail out to avoid cascading errors. return; } - var container = node.parent.kind === 274 ? node.parent : node.parent.parent; - if (container.kind === 239 && !ts.isAmbientModule(container)) { + var container = node.parent.kind === 274 /* SourceFile */ ? node.parent : node.parent.parent; + if (container.kind === 239 /* ModuleDeclaration */ && !ts.isAmbientModule(container)) { if (node.isExportEquals) { error(node, ts.Diagnostics.An_export_assignment_cannot_be_used_in_a_namespace); } @@ -44777,27 +52261,30 @@ var ts; } return; } + // Grammar checking if (!checkGrammarDecoratorsAndModifiers(node) && ts.hasModifiers(node)) { grammarErrorOnFirstToken(node, ts.Diagnostics.An_export_assignment_cannot_have_modifiers); } - if (node.expression.kind === 71) { + if (node.expression.kind === 71 /* Identifier */) { markExportAsReferenced(node); if (compilerOptions.declaration) { - collectLinkedAliases(node.expression, true); + collectLinkedAliases(node.expression, /*setVisibility*/ true); } } else { checkExpressionCached(node.expression); } checkExternalModuleExports(container); - if ((node.flags & 4194304) && !ts.isEntityNameExpression(node.expression)) { + if ((node.flags & 4194304 /* Ambient */) && !ts.isEntityNameExpression(node.expression)) { grammarErrorOnNode(node.expression, ts.Diagnostics.The_expression_of_an_export_assignment_must_be_an_identifier_or_qualified_name_in_an_ambient_context); } - if (node.isExportEquals && !(node.flags & 4194304)) { + if (node.isExportEquals && !(node.flags & 4194304 /* Ambient */)) { if (moduleKind >= ts.ModuleKind.ES2015) { + // export assignment is not supported in es6 modules grammarErrorOnNode(node, ts.Diagnostics.Export_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_export_default_or_another_module_format_instead); } else if (moduleKind === ts.ModuleKind.System) { + // system modules does not support export assignment grammarErrorOnNode(node, ts.Diagnostics.Export_assignment_is_not_supported_when_module_flag_is_system); } } @@ -44816,6 +52303,7 @@ var ts; error(declaration, ts.Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements); } } + // Checks for export * conflicts var exports_2 = getExportsOfModule(moduleSymbol); if (exports_2) { exports_2.forEach(function (_a, id) { @@ -44823,11 +52311,15 @@ var ts; if (id === "__export") { return; } - if (flags & (1920 | 64 | 384)) { + // ECMA262: 15.2.1.1 It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries. + // (TS Exceptions: namespaces, function overloads, enums, and interfaces) + if (flags & (1920 /* Namespace */ | 64 /* Interface */ | 384 /* Enum */)) { return; } var exportedDeclarationsCount = ts.countWhere(declarations, isNotOverloadAndNotAccessor); - if (flags & 524288 && exportedDeclarationsCount <= 2) { + if (flags & 524288 /* TypeAlias */ && exportedDeclarationsCount <= 2) { + // it is legal to merge type alias with other values + // so count should be either 1 (just type alias) or 2 (type alias + merged value) return; } if (exportedDeclarationsCount > 1) { @@ -44844,10 +52336,11 @@ var ts; } } function isNotAccessor(declaration) { + // Accessors check for their own matching duplicates, and in contexts where they are valid, there are already duplicate identifier checks return !ts.isAccessor(declaration); } function isNotOverload(declaration) { - return (declaration.kind !== 234 && declaration.kind !== 154) || + return (declaration.kind !== 234 /* FunctionDeclaration */ && declaration.kind !== 154 /* MethodDeclaration */) || !!declaration.body; } function checkSourceElement(node) { @@ -44862,152 +52355,155 @@ var ts; } var kind = node.kind; if (cancellationToken) { + // Only bother checking on a few construct kinds. We don't want to be excessively + // hitting the cancellation token on every node we check. switch (kind) { - case 239: - case 235: - case 236: - case 234: + case 239 /* ModuleDeclaration */: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + case 234 /* FunctionDeclaration */: cancellationToken.throwIfCancellationRequested(); } } switch (kind) { - case 148: + case 148 /* TypeParameter */: return checkTypeParameter(node); - case 149: + case 149 /* Parameter */: return checkParameter(node); - case 152: - case 151: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: return checkPropertyDeclaration(node); - case 163: - case 164: - case 158: - case 159: - case 160: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 160 /* IndexSignature */: return checkSignatureDeclaration(node); - case 154: - case 153: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: return checkMethodDeclaration(node); - case 155: + case 155 /* Constructor */: return checkConstructorDeclaration(node); - case 156: - case 157: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return checkAccessorDeclaration(node); - case 162: + case 162 /* TypeReference */: return checkTypeReferenceNode(node); - case 161: + case 161 /* TypePredicate */: return checkTypePredicate(node); - case 165: + case 165 /* TypeQuery */: return checkTypeQuery(node); - case 166: + case 166 /* TypeLiteral */: return checkTypeLiteral(node); - case 167: + case 167 /* ArrayType */: return checkArrayType(node); - case 168: + case 168 /* TupleType */: return checkTupleType(node); - case 169: - case 170: + case 169 /* UnionType */: + case 170 /* IntersectionType */: return checkUnionOrIntersectionType(node); - case 173: + case 173 /* ParenthesizedType */: return checkSourceElement(node.type); - case 175: + case 175 /* TypeOperator */: return checkTypeOperator(node); - case 171: + case 171 /* ConditionalType */: return checkConditionalType(node); - case 172: + case 172 /* InferType */: return checkInferType(node); - case 179: + case 179 /* ImportType */: return checkImportType(node); - case 290: + case 290 /* JSDocAugmentsTag */: return checkJSDocAugmentsTag(node); - case 298: - case 292: + case 298 /* JSDocTypedefTag */: + case 292 /* JSDocCallbackTag */: return checkJSDocTypeAliasTag(node); - case 296: + case 296 /* JSDocTypeTag */: return checkJSDocTypeTag(node); - case 293: + case 293 /* JSDocParameterTag */: return checkJSDocParameterTag(node); - case 284: + case 284 /* JSDocFunctionType */: checkSignatureDeclaration(node); - case 282: - case 281: - case 279: - case 280: - case 287: + // falls through + case 282 /* JSDocNonNullableType */: + case 281 /* JSDocNullableType */: + case 279 /* JSDocAllType */: + case 280 /* JSDocUnknownType */: + case 287 /* JSDocTypeLiteral */: checkJSDocTypeIsInJsFile(node); ts.forEachChild(node, checkSourceElement); return; - case 285: + case 285 /* JSDocVariadicType */: checkJSDocVariadicType(node); return; - case 278: + case 278 /* JSDocTypeExpression */: return checkSourceElement(node.type); - case 176: + case 176 /* IndexedAccessType */: return checkIndexedAccessType(node); - case 177: + case 177 /* MappedType */: return checkMappedType(node); - case 234: + case 234 /* FunctionDeclaration */: return checkFunctionDeclaration(node); - case 213: - case 240: + case 213 /* Block */: + case 240 /* ModuleBlock */: return checkBlock(node); - case 214: + case 214 /* VariableStatement */: return checkVariableStatement(node); - case 216: + case 216 /* ExpressionStatement */: return checkExpressionStatement(node); - case 217: + case 217 /* IfStatement */: return checkIfStatement(node); - case 218: + case 218 /* DoStatement */: return checkDoStatement(node); - case 219: + case 219 /* WhileStatement */: return checkWhileStatement(node); - case 220: + case 220 /* ForStatement */: return checkForStatement(node); - case 221: + case 221 /* ForInStatement */: return checkForInStatement(node); - case 222: + case 222 /* ForOfStatement */: return checkForOfStatement(node); - case 223: - case 224: + case 223 /* ContinueStatement */: + case 224 /* BreakStatement */: return checkBreakOrContinueStatement(node); - case 225: + case 225 /* ReturnStatement */: return checkReturnStatement(node); - case 226: + case 226 /* WithStatement */: return checkWithStatement(node); - case 227: + case 227 /* SwitchStatement */: return checkSwitchStatement(node); - case 228: + case 228 /* LabeledStatement */: return checkLabeledStatement(node); - case 229: + case 229 /* ThrowStatement */: return checkThrowStatement(node); - case 230: + case 230 /* TryStatement */: return checkTryStatement(node); - case 232: + case 232 /* VariableDeclaration */: return checkVariableDeclaration(node); - case 182: + case 182 /* BindingElement */: return checkBindingElement(node); - case 235: + case 235 /* ClassDeclaration */: return checkClassDeclaration(node); - case 236: + case 236 /* InterfaceDeclaration */: return checkInterfaceDeclaration(node); - case 237: + case 237 /* TypeAliasDeclaration */: return checkTypeAliasDeclaration(node); - case 238: + case 238 /* EnumDeclaration */: return checkEnumDeclaration(node); - case 239: + case 239 /* ModuleDeclaration */: return checkModuleDeclaration(node); - case 244: + case 244 /* ImportDeclaration */: return checkImportDeclaration(node); - case 243: + case 243 /* ImportEqualsDeclaration */: return checkImportEqualsDeclaration(node); - case 250: + case 250 /* ExportDeclaration */: return checkExportDeclaration(node); - case 249: + case 249 /* ExportAssignment */: return checkExportAssignment(node); - case 215: - case 231: + case 215 /* EmptyStatement */: + case 231 /* DebuggerStatement */: checkGrammarStatementInAmbientContext(node); return; - case 253: + case 253 /* MissingDeclaration */: return checkMissingDeclaration(node); } } @@ -45019,6 +52515,7 @@ var ts; function checkJSDocVariadicType(node) { checkJSDocTypeIsInJsFile(node); checkSourceElement(node.type); + // Only legal location is in the *last* parameter tag or last parameter of a JSDoc function. var parent = node.parent; if (ts.isParameter(parent) && ts.isJSDocFunctionType(parent.parent)) { if (ts.last(parent.parent.parameters) !== parent) { @@ -45036,6 +52533,7 @@ var ts; } var param = ts.getParameterSymbolFromJSDoc(paramTag); if (!param) { + // We will error in `checkJSDocParameterTag`. return; } var host = ts.getHostSignatureFromJSDoc(paramTag); @@ -45048,8 +52546,16 @@ var ts; var parent = node.parent; var paramTag = node.parent.parent; if (ts.isJSDocTypeExpression(node.parent) && ts.isJSDocParameterTag(paramTag)) { + // Else we will add a diagnostic, see `checkJSDocVariadicType`. var host_1 = ts.getHostSignatureFromJSDoc(paramTag); if (host_1) { + /* + Only return an array type if the corresponding parameter is marked as a rest parameter, or if there are no parameters. + So in the following situation we will not create an array type: + /** @param {...number} a * / + function f(a) {} + Because `a` will just be of type `number | undefined`. A synthetic `...args` will also be added, which *will* get an array type. + */ var lastParamDeclaration = ts.lastOrUndefined(host_1.parameters); var symbol = ts.getParameterSymbolFromJSDoc(paramTag); if (!lastParamDeclaration || @@ -45063,6 +52569,15 @@ var ts; } return addOptionality(type); } + // Function and class expression bodies are checked after all statements in the enclosing body. This is + // to ensure constructs like the following are permitted: + // const foo = function () { + // const s = foo(); + // return "hello"; + // } + // Here, performing a full type check of the body of the function expression whilst in the process of + // determining the type of foo would cause foo to be given type any because of the recursive reference. + // Delaying the type check of the body ensures foo has been assigned a type. function checkNodeDeferred(node) { if (deferredNodes) { deferredNodes.push(node); @@ -45072,17 +52587,17 @@ var ts; for (var _i = 0, _a = deferredNodes; _i < _a.length; _i++) { var node = _a[_i]; switch (node.kind) { - case 192: - case 193: - case 154: - case 153: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: checkFunctionExpressionOrObjectLiteralMethodDeferred(node); break; - case 156: - case 157: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: checkAccessorDeclaration(node); break; - case 205: + case 205 /* ClassExpression */: checkClassExpressionDeferred(node); break; } @@ -45096,9 +52611,9 @@ var ts; } function unusedIsError(kind) { switch (kind) { - case 0: + case 0 /* Local */: return !!compilerOptions.noUnusedLocals; - case 1: + case 1 /* Parameter */: return !!compilerOptions.noUnusedParameters; default: return ts.Debug.assertNever(kind); @@ -45107,12 +52622,17 @@ var ts; function getPotentiallyUnusedIdentifiers(sourceFile) { return allPotentiallyUnusedIdentifiers.get(sourceFile.path) || ts.emptyArray; } + // Fully type check a source file and collect the relevant diagnostics. function checkSourceFileWorker(node) { var links = getNodeLinks(node); - if (!(links.flags & 1)) { + if (!(links.flags & 1 /* TypeChecked */)) { + // If skipLibCheck is enabled, skip type checking if file is a declaration file. + // If skipDefaultLibCheck is enabled, skip type checking if file contains a + // '/// ' directive. if (compilerOptions.skipLibCheck && node.isDeclarationFile || compilerOptions.skipDefaultLibCheck && node.hasNoDefaultLib) { return; } + // Grammar checking checkGrammarSourceFile(node); ts.clear(potentialThisCollisions); ts.clear(potentialNewTargetCollisions); @@ -45141,11 +52661,14 @@ var ts; ts.forEach(potentialNewTargetCollisions, checkIfNewTargetIsCapturedInEnclosingScope); ts.clear(potentialNewTargetCollisions); } - links.flags |= 1; + links.flags |= 1 /* TypeChecked */; } } function getDiagnostics(sourceFile, ct) { try { + // Record the cancellation token so it can be checked later on during checkSourceElement. + // Do this in a finally block so we can ensure that it gets reset back to nothing after + // this call is done. cancellationToken = ct; return getDiagnosticsWorker(sourceFile); } @@ -45156,20 +52679,29 @@ var ts; function getDiagnosticsWorker(sourceFile) { throwIfNonDiagnosticsProducing(); if (sourceFile) { + // Some global diagnostics are deferred until they are needed and + // may not be reported in the firt call to getGlobalDiagnostics. + // We should catch these changes and report them. var previousGlobalDiagnostics = diagnostics.getGlobalDiagnostics(); var previousGlobalDiagnosticsSize = previousGlobalDiagnostics.length; checkSourceFile(sourceFile); var semanticDiagnostics = diagnostics.getDiagnostics(sourceFile.fileName); var currentGlobalDiagnostics = diagnostics.getGlobalDiagnostics(); if (currentGlobalDiagnostics !== previousGlobalDiagnostics) { + // If the arrays are not the same reference, new diagnostics were added. var deferredGlobalDiagnostics = ts.relativeComplement(previousGlobalDiagnostics, currentGlobalDiagnostics, ts.compareDiagnostics); return ts.concatenate(deferredGlobalDiagnostics, semanticDiagnostics); } else if (previousGlobalDiagnosticsSize === 0 && currentGlobalDiagnostics.length > 0) { + // If the arrays are the same reference, but the length has changed, a single + // new diagnostic was added as DiagnosticCollection attempts to reuse the + // same array. return ts.concatenate(currentGlobalDiagnostics, semanticDiagnostics); } return semanticDiagnostics; } + // Global diagnostics are always added when a file is not provided to + // getDiagnostics ts.forEach(host.getSourceFiles(), checkSourceFile); return diagnostics.getDiagnostics(); } @@ -45182,8 +52714,10 @@ var ts; throw new Error("Trying to get diagnostics from a type checker that does not produce them."); } } + // Language service support function getSymbolsInScope(location, meaning) { - if (location.flags & 8388608) { + if (location.flags & 8388608 /* InWithStatement */) { + // We cannot answer semantic questions within a with block, do not proceed any further return []; } var symbols = ts.createSymbolTable(); @@ -45196,24 +52730,31 @@ var ts; copySymbols(location.locals, meaning); } switch (location.kind) { - case 239: - copySymbols(getSymbolOfNode(location).exports, meaning & 2623475); + case 239 /* ModuleDeclaration */: + copySymbols(getSymbolOfNode(location).exports, meaning & 2623475 /* ModuleMember */); break; - case 238: - copySymbols(getSymbolOfNode(location).exports, meaning & 8); + case 238 /* EnumDeclaration */: + copySymbols(getSymbolOfNode(location).exports, meaning & 8 /* EnumMember */); break; - case 205: + case 205 /* ClassExpression */: var className = location.name; if (className) { copySymbol(location.symbol, meaning); } - case 235: - case 236: + // falls through + // this fall-through is necessary because we would like to handle + // type parameter inside class expression similar to how we handle it in classDeclaration and interface Declaration + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + // If we didn't come from static member of class or interface, + // 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 (!isStatic) { - copySymbols(getMembersOfSymbol(getSymbolOfNode(location)), meaning & 67901928); + copySymbols(getMembersOfSymbol(getSymbolOfNode(location)), meaning & 67901928 /* Type */); } break; - case 192: + case 192 /* FunctionExpression */: var funcName = location.name; if (funcName) { copySymbol(location.symbol, meaning); @@ -45223,14 +52764,24 @@ var ts; if (ts.introducesArgumentsExoticObject(location)) { copySymbol(argumentsSymbol, meaning); } - isStatic = ts.hasModifier(location, 32); + isStatic = ts.hasModifier(location, 32 /* Static */); location = location.parent; } copySymbols(globals, meaning); } + /** + * Copy the given symbol into symbol tables if the symbol has the given meaning + * and it doesn't already existed in the symbol table + * @param key a key for storing in symbol table; if undefined, use symbol.name + * @param symbol the symbol to be added into symbol table + * @param meaning meaning of symbol to filter by before adding to symbol table + */ function copySymbol(symbol, meaning) { if (ts.getCombinedLocalAndExportSymbolFlags(symbol) & meaning) { var id = symbol.escapedName; + // We will copy all symbol regardless of its reserved name because + // symbolsToArray will check whether the key is a reserved name and + // it will not copy symbol with reserved name to the array if (!symbols.has(id)) { symbols.set(id, symbol); } @@ -45245,33 +52796,34 @@ var ts; } } function isTypeDeclarationName(name) { - return name.kind === 71 && + return name.kind === 71 /* Identifier */ && isTypeDeclaration(name.parent) && name.parent.name === name; } function isTypeDeclaration(node) { switch (node.kind) { - case 148: - case 235: - case 236: - case 237: - case 238: + case 148 /* TypeParameter */: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 238 /* EnumDeclaration */: return true; default: return false; } } + // True if the given identifier is part of a type reference function isTypeReferenceIdentifier(node) { - while (node.parent.kind === 146) { + while (node.parent.kind === 146 /* QualifiedName */) { node = node.parent; } - return node.parent.kind === 162; + return node.parent.kind === 162 /* TypeReference */; } function isHeritageClauseElementIdentifier(node) { - while (node.parent.kind === 185) { + while (node.parent.kind === 185 /* PropertyAccessExpression */) { node = node.parent; } - return node.parent.kind === 207; + return node.parent.kind === 207 /* ExpressionWithTypeArguments */; } function forEachEnclosingClass(node, callback) { var result; @@ -45299,13 +52851,13 @@ var ts; return !!forEachEnclosingClass(node, function (n) { return n === classDeclaration; }); } function getLeftSideOfImportEqualsOrExportAssignment(nodeOnRightSide) { - while (nodeOnRightSide.parent.kind === 146) { + while (nodeOnRightSide.parent.kind === 146 /* QualifiedName */) { nodeOnRightSide = nodeOnRightSide.parent; } - if (nodeOnRightSide.parent.kind === 243) { + if (nodeOnRightSide.parent.kind === 243 /* ImportEqualsDeclaration */) { return nodeOnRightSide.parent.moduleReference === nodeOnRightSide ? nodeOnRightSide.parent : undefined; } - if (nodeOnRightSide.parent.kind === 249) { + if (nodeOnRightSide.parent.kind === 249 /* ExportAssignment */) { return nodeOnRightSide.parent.expression === nodeOnRightSide ? nodeOnRightSide.parent : undefined; } return undefined; @@ -45316,12 +52868,12 @@ var ts; function getSpecialPropertyAssignmentSymbolFromEntityName(entityName) { var specialPropertyAssignmentKind = ts.getSpecialPropertyAssignmentKind(entityName.parent.parent); switch (specialPropertyAssignmentKind) { - case 1: - case 3: + case 1 /* ExportsProperty */: + case 3 /* PrototypeProperty */: return getSymbolOfNode(entityName.parent); - case 4: - case 2: - case 5: + case 4 /* ThisProperty */: + case 2 /* ModuleExports */: + case 5 /* Property */: return getSymbolOfNode(entityName.parent.parent); } } @@ -45331,7 +52883,7 @@ var ts; node = parent; parent = parent.parent; } - if (parent && parent.kind === 179 && parent.qualifier === node) { + if (parent && parent.kind === 179 /* ImportType */ && parent.qualifier === node) { return parent; } return undefined; @@ -45341,23 +52893,27 @@ var ts; return getSymbolOfNode(entityName.parent); } if (ts.isInJavaScriptFile(entityName) && - entityName.parent.kind === 185 && + entityName.parent.kind === 185 /* PropertyAccessExpression */ && entityName.parent === entityName.parent.parent.left) { + // Check if this is a special property assignment var specialPropertyAssignmentSymbol = getSpecialPropertyAssignmentSymbolFromEntityName(entityName); if (specialPropertyAssignmentSymbol) { return specialPropertyAssignmentSymbol; } } - if (entityName.parent.kind === 249 && ts.isEntityNameExpression(entityName)) { - var success = resolveEntityName(entityName, 67216319 | 67901928 | 1920 | 2097152, true); + if (entityName.parent.kind === 249 /* ExportAssignment */ && ts.isEntityNameExpression(entityName)) { + // Even an entity name expression that doesn't resolve as an entityname may still typecheck as a property access expression + var success = resolveEntityName(entityName, + /*all meanings*/ 67216319 /* Value */ | 67901928 /* Type */ | 1920 /* Namespace */ | 2097152 /* Alias */, /*ignoreErrors*/ true); if (success && success !== unknownSymbol) { return success; } } else if (!ts.isPropertyAccessExpression(entityName) && isInRightSideOfImportOrExportAssignment(entityName)) { - var importEqualsDeclaration = ts.getAncestor(entityName, 243); + // Since we already checked for ExportAssignment, this really could only be an Import + var importEqualsDeclaration = ts.getAncestor(entityName, 243 /* ImportEqualsDeclaration */); ts.Debug.assert(importEqualsDeclaration !== undefined); - return getSymbolOfPartOfRightHandSideOfImportEquals(entityName, true); + return getSymbolOfPartOfRightHandSideOfImportEquals(entityName, /*dontResolveAlias*/ true); } if (!ts.isPropertyAccessExpression(entityName)) { var possibleImportNode = isImportTypeQualifierPart(entityName); @@ -45371,47 +52927,50 @@ var ts; entityName = entityName.parent; } if (isHeritageClauseElementIdentifier(entityName)) { - var meaning = 0; - if (entityName.parent.kind === 207) { - meaning = 67901928; + var meaning = 0 /* None */; + // In an interface or class, we're definitely interested in a type. + if (entityName.parent.kind === 207 /* ExpressionWithTypeArguments */) { + meaning = 67901928 /* Type */; + // In a class 'extends' clause we are also looking for a value. if (ts.isExpressionWithTypeArgumentsInClassExtendsClause(entityName.parent)) { - meaning |= 67216319; + meaning |= 67216319 /* Value */; } } else { - meaning = 1920; + meaning = 1920 /* Namespace */; } - meaning |= 2097152; + meaning |= 2097152 /* Alias */; var entityNameSymbol = ts.isEntityNameExpression(entityName) ? resolveEntityName(entityName, meaning) : undefined; if (entityNameSymbol) { return entityNameSymbol; } } - if (entityName.parent.kind === 293) { + if (entityName.parent.kind === 293 /* JSDocParameterTag */) { return ts.getParameterSymbolFromJSDoc(entityName.parent); } - if (entityName.parent.kind === 148 && entityName.parent.parent.kind === 297) { - ts.Debug.assert(!ts.isInJavaScriptFile(entityName)); + if (entityName.parent.kind === 148 /* TypeParameter */ && entityName.parent.parent.kind === 297 /* JSDocTemplateTag */) { + ts.Debug.assert(!ts.isInJavaScriptFile(entityName)); // Otherwise `isDeclarationName` would have been true. var typeParameter = ts.getTypeParameterFromJsDoc(entityName.parent); return typeParameter && typeParameter.symbol; } if (ts.isExpressionNode(entityName)) { if (ts.nodeIsMissing(entityName)) { + // Missing entity name. return undefined; } - if (entityName.kind === 71) { + if (entityName.kind === 71 /* Identifier */) { if (ts.isJSXTagName(entityName) && isJsxIntrinsicIdentifier(entityName)) { var symbol = getIntrinsicTagSymbol(entityName.parent); return symbol === unknownSymbol ? undefined : symbol; } - return resolveEntityName(entityName, 67216319, false, true); + return resolveEntityName(entityName, 67216319 /* Value */, /*ignoreErrors*/ false, /*dontResolveAlias*/ true); } - else if (entityName.kind === 185 || entityName.kind === 146) { + else if (entityName.kind === 185 /* PropertyAccessExpression */ || entityName.kind === 146 /* QualifiedName */) { var links = getNodeLinks(entityName); if (links.resolvedSymbol) { return links.resolvedSymbol; } - if (entityName.kind === 185) { + if (entityName.kind === 185 /* PropertyAccessExpression */) { checkPropertyAccessExpression(entityName); } else { @@ -45421,38 +52980,41 @@ var ts; } } else if (isTypeReferenceIdentifier(entityName)) { - var meaning = entityName.parent.kind === 162 ? 67901928 : 1920; - return resolveEntityName(entityName, meaning, false, true); + var meaning = entityName.parent.kind === 162 /* TypeReference */ ? 67901928 /* Type */ : 1920 /* Namespace */; + return resolveEntityName(entityName, meaning, /*ignoreErrors*/ false, /*dontResolveAlias*/ true); } - else if (entityName.parent.kind === 262) { + else if (entityName.parent.kind === 262 /* JsxAttribute */) { return getJsxAttributePropertySymbol(entityName.parent); } - if (entityName.parent.kind === 161) { - return resolveEntityName(entityName, 1); + if (entityName.parent.kind === 161 /* TypePredicate */) { + return resolveEntityName(entityName, /*meaning*/ 1 /* FunctionScopedVariable */); } + // Do we want to return undefined here? return undefined; } function getSymbolAtLocation(node) { - if (node.kind === 274) { + if (node.kind === 274 /* SourceFile */) { return ts.isExternalModule(node) ? getMergedSymbol(node.symbol) : undefined; } var parent = node.parent; var grandParent = parent.parent; - if (node.flags & 8388608) { + if (node.flags & 8388608 /* InWithStatement */) { + // We cannot answer semantic questions within a with block, do not proceed any further return undefined; } if (isDeclarationNameOrImportPropertyName(node)) { + // This is a declaration, call getSymbolOfNode return getSymbolOfNode(parent); } else if (ts.isLiteralComputedPropertyDeclarationName(node)) { return getSymbolOfNode(parent.parent); } - if (node.kind === 71) { + if (node.kind === 71 /* Identifier */) { if (isInRightSideOfImportOrExportAssignment(node)) { return getSymbolOfEntityNameOrPropertyAccessExpression(node); } - else if (parent.kind === 182 && - grandParent.kind === 180 && + else if (parent.kind === 182 /* BindingElement */ && + grandParent.kind === 180 /* ObjectBindingPattern */ && node === parent.propertyName) { var typeOfPattern = getTypeOfNode(grandParent); var propertyDeclaration = typeOfPattern && getPropertyOfType(typeOfPattern, node.escapedText); @@ -45462,12 +53024,12 @@ var ts; } } switch (node.kind) { - case 71: - case 185: - case 146: + case 71 /* Identifier */: + case 185 /* PropertyAccessExpression */: + case 146 /* QualifiedName */: return getSymbolOfEntityNameOrPropertyAccessExpression(node); - case 99: - var container = ts.getThisContainer(node, false); + case 99 /* ThisKeyword */: + var container = ts.getThisContainer(node, /*includeArrowFunctions*/ false); if (ts.isFunctionLike(container)) { var sig = getSignatureFromDeclaration(container); if (sig.thisParameter) { @@ -45477,54 +53039,64 @@ var ts; if (ts.isInExpressionContext(node)) { return checkExpression(node).symbol; } - case 174: + // falls through + case 174 /* ThisType */: return getTypeFromThisTypeNode(node).symbol; - case 97: + case 97 /* SuperKeyword */: return checkExpression(node).symbol; - case 123: + case 123 /* ConstructorKeyword */: + // constructor keyword for an overload, should take us to the definition if it exist var constructorDeclaration = node.parent; - if (constructorDeclaration && constructorDeclaration.kind === 155) { + if (constructorDeclaration && constructorDeclaration.kind === 155 /* Constructor */) { return constructorDeclaration.parent.symbol; } return undefined; - case 9: - case 13: + case 9 /* StringLiteral */: + case 13 /* NoSubstitutionTemplateLiteral */: + // 1). import x = require("./mo/*gotToDefinitionHere*/d") + // 2). External module name in an import declaration + // 3). Dynamic import call or require in javascript + // 4). type A = import("./f/*gotToDefinitionHere*/oo") if ((ts.isExternalModuleImportEqualsDeclaration(node.parent.parent) && ts.getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node) || - ((node.parent.kind === 244 || node.parent.kind === 250) && node.parent.moduleSpecifier === node) || - ((ts.isInJavaScriptFile(node) && ts.isRequireCall(node.parent, false)) || ts.isImportCall(node.parent)) || + ((node.parent.kind === 244 /* ImportDeclaration */ || node.parent.kind === 250 /* ExportDeclaration */) && node.parent.moduleSpecifier === node) || + ((ts.isInJavaScriptFile(node) && ts.isRequireCall(node.parent, /*checkArgumentIsStringLiteralLike*/ false)) || ts.isImportCall(node.parent)) || (ts.isLiteralTypeNode(node.parent) && ts.isLiteralImportTypeNode(node.parent.parent) && node.parent.parent.argument === node.parent)) { return resolveExternalModuleName(node, node); } - case 8: + // falls through + case 8 /* NumericLiteral */: + // index access var objectType = ts.isElementAccessExpression(parent) ? parent.argumentExpression === node ? getTypeOfExpression(parent.expression) : undefined : ts.isLiteralTypeNode(parent) && ts.isIndexedAccessTypeNode(grandParent) ? getTypeFromTypeNode(grandParent.objectType) : undefined; return objectType && getPropertyOfType(objectType, ts.escapeLeadingUnderscores(node.text)); - case 79: - case 89: - case 36: + case 79 /* DefaultKeyword */: + case 89 /* FunctionKeyword */: + case 36 /* EqualsGreaterThanToken */: return getSymbolOfNode(node.parent); - case 179: + case 179 /* ImportType */: return ts.isLiteralImportTypeNode(node) ? getSymbolAtLocation(node.argument.literal) : undefined; default: return undefined; } } function getShorthandAssignmentValueSymbol(location) { - if (location && location.kind === 271) { - return resolveEntityName(location.name, 67216319 | 2097152); + if (location && location.kind === 271 /* ShorthandPropertyAssignment */) { + return resolveEntityName(location.name, 67216319 /* Value */ | 2097152 /* Alias */); } return undefined; } + /** Returns the target of an export specifier without following aliases */ function getExportSpecifierLocalTargetSymbol(node) { return node.parent.parent.moduleSpecifier ? getExternalModuleMember(node.parent.parent, node) : - resolveEntityName(node.propertyName || node.name, 67216319 | 67901928 | 1920 | 2097152); + resolveEntityName(node.propertyName || node.name, 67216319 /* Value */ | 67901928 /* Type */ | 1920 /* Namespace */ | 2097152 /* Alias */); } function getTypeOfNode(node) { - if (node.flags & 8388608) { + if (node.flags & 8388608 /* InWithStatement */) { + // We cannot answer semantic questions within a with block, do not proceed any further return errorType; } if (ts.isPartOfTypeNode(node)) { @@ -45540,12 +53112,15 @@ var ts; return getRegularTypeOfExpression(node); } if (ts.isExpressionWithTypeArgumentsInClassExtendsClause(node)) { + // A SyntaxKind.ExpressionWithTypeArguments is considered a type node, except when it occurs in the + // extends clause of a class. We handle that case here. var classNode = ts.getContainingClass(node); var classType = getDeclaredTypeOfSymbol(getSymbolOfNode(classNode)); var baseType = getBaseTypes(classType)[0]; return baseType && getTypeWithThisArgument(baseType, classType.thisType); } if (isTypeDeclaration(node)) { + // In this case, we call getSymbolOfNode instead of getSymbolAtLocation because it is a declaration var symbol = getSymbolOfNode(node); return getDeclaredTypeOfSymbol(symbol); } @@ -45554,6 +53129,7 @@ var ts; return symbol && getDeclaredTypeOfSymbol(symbol); } if (ts.isDeclaration(node)) { + // In this case, we call getSymbolOfNode instead of getSymbolAtLocation because it is a declaration var symbol = getSymbolOfNode(node); return getTypeOfSymbol(symbol); } @@ -45562,7 +53138,7 @@ var ts; return symbol && getTypeOfSymbol(symbol); } if (ts.isBindingPattern(node)) { - return getTypeForVariableLikeDeclaration(node.parent, true); + return getTypeForVariableLikeDeclaration(node.parent, /*includeOptionality*/ true); } if (isInRightSideOfImportOrExportAssignment(node)) { var symbol = getSymbolAtLocation(node); @@ -45573,26 +53149,48 @@ var ts; } return errorType; } + // Gets the type of object literal or array literal of destructuring assignment. + // { a } from + // for ( { a } of elems) { + // } + // [ a ] from + // [a] = [ some array ...] function getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(expr) { - ts.Debug.assert(expr.kind === 184 || expr.kind === 183); - if (expr.parent.kind === 222) { + ts.Debug.assert(expr.kind === 184 /* ObjectLiteralExpression */ || expr.kind === 183 /* ArrayLiteralExpression */); + // If this is from "for of" + // for ( { a } of elems) { + // } + if (expr.parent.kind === 222 /* ForOfStatement */) { var iteratedType = checkRightHandSideOfForOf(expr.parent.expression, expr.parent.awaitModifier); return checkDestructuringAssignment(expr, iteratedType || errorType); } - if (expr.parent.kind === 200) { + // If this is from "for" initializer + // for ({a } = elems[0];.....) { } + if (expr.parent.kind === 200 /* BinaryExpression */) { var iteratedType = getTypeOfExpression(expr.parent.right); return checkDestructuringAssignment(expr, iteratedType || errorType); } - if (expr.parent.kind === 270) { + // If this is from nested object binding pattern + // for ({ skills: { primary, secondary } } = multiRobot, i = 0; i < 1; i++) { + if (expr.parent.kind === 270 /* PropertyAssignment */) { var typeOfParentObjectLiteral = getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(expr.parent.parent); - return checkObjectLiteralDestructuringPropertyAssignment(typeOfParentObjectLiteral || errorType, expr.parent); + return checkObjectLiteralDestructuringPropertyAssignment(typeOfParentObjectLiteral || errorType, expr.parent); // TODO: GH#18217 } - ts.Debug.assert(expr.parent.kind === 183); + // Array literal assignment - array destructuring pattern + ts.Debug.assert(expr.parent.kind === 183 /* ArrayLiteralExpression */); + // [{ property1: p1, property2 }] = elems; var typeOfArrayLiteral = getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(expr.parent); - var elementType = checkIteratedTypeOrElementType(typeOfArrayLiteral || errorType, expr.parent, false, false) || errorType; - return checkArrayLiteralDestructuringElementAssignment(expr.parent, typeOfArrayLiteral, expr.parent.elements.indexOf(expr), elementType || errorType); + var elementType = checkIteratedTypeOrElementType(typeOfArrayLiteral || errorType, expr.parent, /*allowStringInput*/ false, /*allowAsyncIterables*/ false) || errorType; + return checkArrayLiteralDestructuringElementAssignment(expr.parent, typeOfArrayLiteral, expr.parent.elements.indexOf(expr), elementType || errorType); // TODO: GH#18217 } + // Gets the property symbol corresponding to the property in destructuring assignment + // 'property1' from + // for ( { property1: a } of elems) { + // } + // 'property1' at location 'a' from: + // [a] = [ property1, property2 ] function getPropertySymbolOfDestructuringAssignment(location) { + // Get the type of the object or array literal and then look for property of given name in the type var typeOfObjectLiteral = getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(location.parent.parent); return typeOfObjectLiteral && getPropertyOfType(typeOfObjectLiteral, location.escapedText); } @@ -45602,12 +53200,18 @@ var ts; } return getRegularTypeOfLiteralType(getTypeOfExpression(expr)); } + /** + * Gets either the static or instance type of a class element, based on + * whether the element is declared as "static". + */ function getParentTypeOfClassElement(node) { var classSymbol = getSymbolOfNode(node.parent); - return ts.hasModifier(node, 32) + return ts.hasModifier(node, 32 /* Static */) ? getTypeOfSymbol(classSymbol) : getDeclaredTypeOfSymbol(classSymbol); } + // Return the list of properties of the given type, augmented with properties from Function + // if the type has call or construct signatures function getAugmentedPropertiesOfType(type) { type = getApparentType(type); var propsByName = ts.createSymbolTable(getPropertiesOfType(type)); @@ -45628,10 +53232,10 @@ var ts; return roots ? ts.flatMap(roots, getRootSymbols) : [symbol]; } function getImmediateRootSymbols(symbol) { - if (ts.getCheckFlags(symbol) & 6) { + if (ts.getCheckFlags(symbol) & 6 /* Synthetic */) { return ts.mapDefined(getSymbolLinks(symbol).containingType.types, function (type) { return getPropertyOfType(type, symbol.escapedName); }); } - else if (symbol.flags & 33554432) { + else if (symbol.flags & 33554432 /* Transient */) { var _a = symbol, leftSpread = _a.leftSpread, rightSpread = _a.rightSpread, syntheticOrigin = _a.syntheticOrigin; return leftSpread ? [leftSpread, rightSpread] : syntheticOrigin ? [syntheticOrigin] @@ -45647,11 +53251,12 @@ var ts; } return target; } + // Emitter support function isArgumentsLocalBinding(nodeIn) { if (!ts.isGeneratedIdentifier(nodeIn)) { var node = ts.getParseTreeNode(nodeIn, ts.isIdentifier); if (node) { - var isPropertyName_1 = node.parent.kind === 185 && node.parent.name === node; + var isPropertyName_1 = node.parent.kind === 185 /* PropertyAccessExpression */ && node.parent.name === node; return !isPropertyName_1 && getReferencedValueSymbol(node) === argumentsSymbol; } } @@ -45660,42 +53265,57 @@ var ts; function moduleExportsSomeValue(moduleReferenceExpression) { var moduleSymbol = resolveExternalModuleName(moduleReferenceExpression.parent, moduleReferenceExpression); if (!moduleSymbol || ts.isShorthandAmbientModuleSymbol(moduleSymbol)) { + // If the module is not found or is shorthand, assume that it may export a value. return true; } var hasExportAssignment = hasExportAssignmentSymbol(moduleSymbol); + // if module has export assignment then 'resolveExternalModuleSymbol' will return resolved symbol for export assignment + // otherwise it will return moduleSymbol itself moduleSymbol = resolveExternalModuleSymbol(moduleSymbol); var symbolLinks = getSymbolLinks(moduleSymbol); if (symbolLinks.exportsSomeValue === undefined) { + // for export assignments - check if resolved symbol for RHS is itself a value + // otherwise - check if at least one export is value symbolLinks.exportsSomeValue = hasExportAssignment - ? !!(moduleSymbol.flags & 67216319) + ? !!(moduleSymbol.flags & 67216319 /* Value */) : ts.forEachEntry(getExportsOfModule(moduleSymbol), isValue); } return symbolLinks.exportsSomeValue; function isValue(s) { s = resolveSymbol(s); - return s && !!(s.flags & 67216319); + return s && !!(s.flags & 67216319 /* Value */); } } function isNameOfModuleOrEnumDeclaration(node) { return ts.isModuleOrEnumDeclaration(node.parent) && node === node.parent.name; } + // When resolved as an expression identifier, if the given node references an exported entity, return the declaration + // node of the exported entity's container. Otherwise, return undefined. function getReferencedExportContainer(nodeIn, prefixLocals) { var node = ts.getParseTreeNode(nodeIn, ts.isIdentifier); if (node) { - var symbol = getReferencedValueSymbol(node, isNameOfModuleOrEnumDeclaration(node)); + // When resolving the export container for the name of a module or enum + // declaration, we need to start resolution at the declaration's container. + // Otherwise, we could incorrectly resolve the export container as the + // declaration if it contains an exported member with the same name. + var symbol = getReferencedValueSymbol(node, /*startInDeclarationContainer*/ isNameOfModuleOrEnumDeclaration(node)); if (symbol) { - if (symbol.flags & 1048576) { + if (symbol.flags & 1048576 /* ExportValue */) { + // If we reference an exported entity within the same module declaration, then whether + // we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the + // kinds that we do NOT prefix. var exportSymbol = getMergedSymbol(symbol.exportSymbol); - if (!prefixLocals && exportSymbol.flags & 944 && !(exportSymbol.flags & 3)) { + if (!prefixLocals && exportSymbol.flags & 944 /* ExportHasLocal */ && !(exportSymbol.flags & 3 /* Variable */)) { return undefined; } symbol = exportSymbol; } var parentSymbol_1 = getParentOfSymbol(symbol); if (parentSymbol_1) { - if (parentSymbol_1.flags & 512 && parentSymbol_1.valueDeclaration.kind === 274) { + if (parentSymbol_1.flags & 512 /* ValueModule */ && parentSymbol_1.valueDeclaration.kind === 274 /* SourceFile */) { var symbolFile = parentSymbol_1.valueDeclaration; var referenceFile = ts.getSourceFileOfNode(node); + // If `node` accesses an export and that export isn't in the same file, then symbol is a namespace export, so return undefined. var symbolIsUmdExport = symbolFile !== referenceFile; return symbolIsUmdExport ? undefined : symbolFile; } @@ -45704,30 +53324,50 @@ var ts; } } } + // When resolved as an expression identifier, if the given node references an import, return the declaration of + // that import. Otherwise, return undefined. function getReferencedImportDeclaration(nodeIn) { var node = ts.getParseTreeNode(nodeIn, ts.isIdentifier); if (node) { var symbol = getReferencedValueSymbol(node); - if (isNonLocalAlias(symbol, 67216319)) { + // We should only get the declaration of an alias if there isn't a local value + // declaration for the symbol + if (isNonLocalAlias(symbol, /*excludes*/ 67216319 /* Value */)) { return getDeclarationOfAliasSymbol(symbol); } } return undefined; } function isSymbolOfDeclarationWithCollidingName(symbol) { - if (symbol.flags & 418) { + if (symbol.flags & 418 /* BlockScoped */) { var links = getSymbolLinks(symbol); if (links.isDeclarationWithCollidingName === undefined) { var container = ts.getEnclosingBlockScopeContainer(symbol.valueDeclaration); if (ts.isStatementWithLocals(container)) { var nodeLinks_1 = getNodeLinks(symbol.valueDeclaration); - if (resolveName(container.parent, symbol.escapedName, 67216319, undefined, undefined, false)) { + if (resolveName(container.parent, symbol.escapedName, 67216319 /* Value */, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)) { + // redeclaration - always should be renamed links.isDeclarationWithCollidingName = true; } - else if (nodeLinks_1.flags & 131072) { - var isDeclaredInLoop = nodeLinks_1.flags & 262144; - var inLoopInitializer = ts.isIterationStatement(container, false); - var inLoopBodyBlock = container.kind === 213 && ts.isIterationStatement(container.parent, false); + else if (nodeLinks_1.flags & 131072 /* CapturedBlockScopedBinding */) { + // binding is captured in the function + // should be renamed if: + // - binding is not top level - top level bindings never collide with anything + // AND + // - binding is not declared in loop, should be renamed to avoid name reuse across siblings + // let a, b + // { let x = 1; a = () => x; } + // { let x = 100; b = () => x; } + // console.log(a()); // should print '1' + // console.log(b()); // should print '100' + // OR + // - binding is declared inside loop but not in inside initializer of iteration statement or directly inside loop body + // * variables from initializer are passed to rewritten loop body as parameters so they are not captured directly + // * variables that are declared immediately in loop body will become top level variable after loop is rewritten and thus + // they will not collide with anything + var isDeclaredInLoop = nodeLinks_1.flags & 262144 /* BlockScopedBindingInLoop */; + var inLoopInitializer = ts.isIterationStatement(container, /*lookInLabeledStatements*/ false); + var inLoopBodyBlock = container.kind === 213 /* Block */ && ts.isIterationStatement(container.parent, /*lookInLabeledStatements*/ false); links.isDeclarationWithCollidingName = !ts.isBlockScopedContainerTopLevel(container) && (!isDeclaredInLoop || (!inLoopInitializer && !inLoopBodyBlock)); } else { @@ -45739,6 +53379,9 @@ var ts; } return false; } + // When resolved as an expression identifier, if the given node references a nested block scoped entity with + // a name that either hides an existing name or might hide it when compiled downlevel, + // return the declaration of that entity. Otherwise, return undefined. function getReferencedDeclarationWithCollidingName(nodeIn) { if (!ts.isGeneratedIdentifier(nodeIn)) { var node = ts.getParseTreeNode(nodeIn, ts.isIdentifier); @@ -45751,6 +53394,8 @@ var ts; } return undefined; } + // Return true if the given node is a declaration of a nested block scoped entity with a name that either hides an + // existing name or might hide a name when compiled downlevel function isDeclarationWithCollidingName(nodeIn) { var node = ts.getParseTreeNode(nodeIn, ts.isDeclaration); if (node) { @@ -45763,18 +53408,18 @@ var ts; } function isValueAliasDeclaration(node) { switch (node.kind) { - case 243: - case 245: - case 246: - case 248: - case 252: + case 243 /* ImportEqualsDeclaration */: + case 245 /* ImportClause */: + case 246 /* NamespaceImport */: + case 248 /* ImportSpecifier */: + case 252 /* ExportSpecifier */: return isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol); - case 250: + case 250 /* ExportDeclaration */: var exportClause = node.exportClause; return !!exportClause && ts.some(exportClause.elements, isValueAliasDeclaration); - case 249: + case 249 /* ExportAssignment */: return node.expression - && node.expression.kind === 71 + && node.expression.kind === 71 /* Identifier */ ? isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol) : true; } @@ -45782,7 +53427,8 @@ var ts; } function isTopLevelValueImportEqualsWithEntityName(nodeIn) { var node = ts.getParseTreeNode(nodeIn, ts.isImportEqualsDeclaration); - if (node === undefined || node.parent.kind !== 274 || !ts.isInternalModuleImportEqualsDeclaration(node)) { + if (node === undefined || node.parent.kind !== 274 /* SourceFile */ || !ts.isInternalModuleImportEqualsDeclaration(node)) { + // parent is not source file or it is not reference to internal module return false; } var isValue = isAliasResolvedToValue(getSymbolOfNode(node)); @@ -45793,7 +53439,9 @@ var ts; if (target === unknownSymbol) { return true; } - return !!(target.flags & 67216319) && + // const enums and modules that contain only const enums are not considered values from the emit perspective + // unless 'preserveConstEnums' option is set to true + return !!(target.flags & 67216319 /* Value */) && (compilerOptions.preserveConstEnums || !isConstEnumOrConstEnumOnlyModule(target)); } function isConstEnumOrConstEnumOnlyModule(s) { @@ -45805,8 +53453,9 @@ var ts; if (symbol && getSymbolLinks(symbol).referenced) { return true; } - var target = getSymbolLinks(symbol).target; - if (target && ts.getModifierFlags(node) & 1 && target.flags & 67216319) { + var target = getSymbolLinks(symbol).target; // TODO: GH#18217 + if (target && ts.getModifierFlags(node) & 1 /* Export */ && target.flags & 67216319 /* Value */) { + // An `export import ... =` of a value symbol is always considered referenced return true; } } @@ -45818,10 +53467,21 @@ var ts; function isImplementationOfOverload(node) { if (ts.nodeIsPresent(node.body)) { if (ts.isGetAccessor(node) || ts.isSetAccessor(node)) - return false; + return false; // Get or set accessors can never be overload implementations, but can have up to 2 signatures var symbol = getSymbolOfNode(node); var signaturesOfSymbol = getSignaturesOfSymbol(symbol); + // If this function body corresponds to function with multiple signature, it is implementation of overload + // e.g.: function foo(a: string): string; + // function foo(a: number): number; + // function foo(a: any) { // This is implementation of the overloads + // return a; + // } return signaturesOfSymbol.length > 1 || + // If there is single signature for the symbol, it is overload if that signature isn't coming from the node + // e.g.: function foo(a: string): string; + // function foo(a: any) { // This is implementation of the overloads + // return a; + // } (signaturesOfSymbol.length === 1 && signaturesOfSymbol[0].declaration !== node); } return false; @@ -45831,13 +53491,13 @@ var ts; !isOptionalParameter(parameter) && !ts.isJSDocParameterTag(parameter) && !!parameter.initializer && - !ts.hasModifier(parameter, 92); + !ts.hasModifier(parameter, 92 /* ParameterPropertyModifier */); } function isOptionalUninitializedParameterProperty(parameter) { return strictNullChecks && isOptionalParameter(parameter) && !parameter.initializer && - ts.hasModifier(parameter, 92); + ts.hasModifier(parameter, 92 /* ParameterPropertyModifier */); } function getNodeCheckFlags(node) { return getNodeLinks(node).flags || 0; @@ -45848,19 +53508,20 @@ var ts; } function canHaveConstantValue(node) { switch (node.kind) { - case 273: - case 185: - case 186: + case 273 /* EnumMember */: + case 185 /* PropertyAccessExpression */: + case 186 /* ElementAccessExpression */: return true; } return false; } function getConstantValue(node) { - if (node.kind === 273) { + if (node.kind === 273 /* EnumMember */) { return getEnumMemberValue(node); } var symbol = getNodeLinks(node).resolvedSymbol; - if (symbol && (symbol.flags & 8)) { + if (symbol && (symbol.flags & 8 /* EnumMember */)) { + // inline property\index accesses only for const enums if (ts.isConstEnumDeclaration(symbol.valueDeclaration.parent)) { return getEnumMemberValue(symbol.valueDeclaration); } @@ -45868,9 +53529,10 @@ var ts; return undefined; } function isFunctionType(type) { - return !!(type.flags & 131072) && getSignaturesOfType(type, 0).length > 0; + return !!(type.flags & 131072 /* Object */) && getSignaturesOfType(type, 0 /* Call */).length > 0; } function getTypeReferenceSerializationKind(typeNameIn, location) { + // ensure both `typeName` and `location` are parse tree nodes. var typeName = ts.getParseTreeNode(typeNameIn, ts.isEntityName); if (!typeName) return ts.TypeReferenceSerializationKind.Unknown; @@ -45879,10 +53541,12 @@ var ts; if (!location) return ts.TypeReferenceSerializationKind.Unknown; } - var valueSymbol = resolveEntityName(typeName, 67216319, true, false, location); - var typeSymbol = resolveEntityName(typeName, 67901928, true, false, location); + // Resolve the symbol as a value to ensure the type can be reached at runtime during emit. + var valueSymbol = resolveEntityName(typeName, 67216319 /* Value */, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location); + // Resolve the symbol as a type so that we can provide a more useful hint for the type serializer. + var typeSymbol = resolveEntityName(typeName, 67901928 /* Type */, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location); if (valueSymbol && valueSymbol === typeSymbol) { - var globalPromiseSymbol = getGlobalPromiseConstructorSymbol(false); + var globalPromiseSymbol = getGlobalPromiseConstructorSymbol(/*reportErrors*/ false); if (globalPromiseSymbol && valueSymbol === globalPromiseSymbol) { return ts.TypeReferenceSerializationKind.Promise; } @@ -45891,6 +53555,7 @@ var ts; return ts.TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue; } } + // We might not be able to resolve type symbol so use unknown type in that case (eg error case) if (!typeSymbol) { return ts.TypeReferenceSerializationKind.Unknown; } @@ -45898,25 +53563,25 @@ var ts; if (type === errorType) { return ts.TypeReferenceSerializationKind.Unknown; } - else if (type.flags & 3) { + else if (type.flags & 3 /* AnyOrUnknown */) { return ts.TypeReferenceSerializationKind.ObjectType; } - else if (isTypeAssignableToKind(type, 4096 | 24576 | 32768)) { + else if (isTypeAssignableToKind(type, 4096 /* Void */ | 24576 /* Nullable */ | 32768 /* Never */)) { return ts.TypeReferenceSerializationKind.VoidNullableOrNeverType; } - else if (isTypeAssignableToKind(type, 272)) { + else if (isTypeAssignableToKind(type, 272 /* BooleanLike */)) { return ts.TypeReferenceSerializationKind.BooleanType; } - else if (isTypeAssignableToKind(type, 168)) { + else if (isTypeAssignableToKind(type, 168 /* NumberLike */)) { return ts.TypeReferenceSerializationKind.NumberLikeType; } - else if (isTypeAssignableToKind(type, 68)) { + else if (isTypeAssignableToKind(type, 68 /* StringLike */)) { return ts.TypeReferenceSerializationKind.StringLikeType; } else if (isTupleType(type)) { return ts.TypeReferenceSerializationKind.ArrayLikeType; } - else if (isTypeAssignableToKind(type, 3072)) { + else if (isTypeAssignableToKind(type, 3072 /* ESSymbolLike */)) { return ts.TypeReferenceSerializationKind.ESSymbolType; } else if (isFunctionType(type)) { @@ -45932,36 +53597,37 @@ var ts; function createTypeOfDeclaration(declarationIn, enclosingDeclaration, flags, tracker, addUndefined) { var declaration = ts.getParseTreeNode(declarationIn, ts.isVariableLikeOrAccessor); if (!declaration) { - return ts.createToken(119); + return ts.createToken(119 /* AnyKeyword */); } + // Get type of the symbol if this is the valid symbol otherwise get type at location var symbol = getSymbolOfNode(declaration); - var type = symbol && !(symbol.flags & (2048 | 131072)) + var type = symbol && !(symbol.flags & (2048 /* TypeLiteral */ | 131072 /* Signature */)) ? getWidenedLiteralType(getTypeOfSymbol(symbol)) : errorType; - if (type.flags & 2048 && + if (type.flags & 2048 /* UniqueESSymbol */ && type.symbol === symbol) { - flags |= 1048576; + flags |= 1048576 /* AllowUniqueESSymbolType */; } if (addUndefined) { type = getOptionalType(type); } - return nodeBuilder.typeToTypeNode(type, enclosingDeclaration, flags | 1024, tracker); + return nodeBuilder.typeToTypeNode(type, enclosingDeclaration, flags | 1024 /* MultilineObjectLiterals */, tracker); } function createReturnTypeOfSignatureDeclaration(signatureDeclarationIn, enclosingDeclaration, flags, tracker) { var signatureDeclaration = ts.getParseTreeNode(signatureDeclarationIn, ts.isFunctionLike); if (!signatureDeclaration) { - return ts.createToken(119); + return ts.createToken(119 /* AnyKeyword */); } var signature = getSignatureFromDeclaration(signatureDeclaration); - return nodeBuilder.typeToTypeNode(getReturnTypeOfSignature(signature), enclosingDeclaration, flags | 1024, tracker); + return nodeBuilder.typeToTypeNode(getReturnTypeOfSignature(signature), enclosingDeclaration, flags | 1024 /* MultilineObjectLiterals */, tracker); } function createTypeOfExpression(exprIn, enclosingDeclaration, flags, tracker) { var expr = ts.getParseTreeNode(exprIn, ts.isExpression); if (!expr) { - return ts.createToken(119); + return ts.createToken(119 /* AnyKeyword */); } var type = getWidenedType(getRegularTypeOfExpression(expr)); - return nodeBuilder.typeToTypeNode(type, enclosingDeclaration, flags | 1024, tracker); + return nodeBuilder.typeToTypeNode(type, enclosingDeclaration, flags | 1024 /* MultilineObjectLiterals */, tracker); } function hasGlobalName(name) { return globals.has(ts.escapeLeadingUnderscores(name)); @@ -45973,12 +53639,14 @@ var ts; } var location = reference; if (startInDeclarationContainer) { + // When resolving the name of a declaration as a value, we need to start resolution + // at a point outside of the declaration. var parent = reference.parent; if (ts.isDeclaration(parent) && reference === parent.name) { location = getDeclarationContainer(parent); } } - return resolveName(location, reference.escapedText, 67216319 | 1048576 | 2097152, undefined, undefined, true); + return resolveName(location, reference.escapedText, 67216319 /* Value */ | 1048576 /* ExportValue */ | 2097152 /* Alias */, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); } function getReferencedValueDeclaration(referenceIn) { if (!ts.isGeneratedIdentifier(referenceIn)) { @@ -45995,7 +53663,7 @@ var ts; function isLiteralConstDeclaration(node) { if (ts.isConst(node)) { var type = getTypeOfSymbol(getSymbolOfNode(node)); - return !!(type.flags & 192 && type.flags & 33554432); + return !!(type.flags & 192 /* StringOrNumberLiteral */ && type.flags & 33554432 /* FreshLiteral */); } return false; } @@ -46007,9 +53675,12 @@ var ts; return literalTypeToNode(type); } function createResolver() { + // this variable and functions that use it are deliberately moved here from the outer scope + // to avoid scope pollution var resolvedTypeReferenceDirectives = host.getResolvedTypeReferenceDirectives(); var fileToDirective; if (resolvedTypeReferenceDirectives) { + // populate reverse mapping: file path -> type reference directive that was resolved to this file fileToDirective = ts.createMap(); resolvedTypeReferenceDirectives.forEach(function (resolvedDirective, key) { if (!resolvedDirective || !resolvedDirective.resolvedFileName) { @@ -46026,11 +53697,13 @@ var ts; isDeclarationWithCollidingName: isDeclarationWithCollidingName, isValueAliasDeclaration: function (node) { node = ts.getParseTreeNode(node); + // Synthesized nodes are always treated like values. return node ? isValueAliasDeclaration(node) : true; }, hasGlobalName: hasGlobalName, isReferencedAliasDeclaration: function (node, checkChildren) { node = ts.getParseTreeNode(node); + // Synthesized nodes are always treated as referenced. return node ? isReferencedAliasDeclaration(node, checkChildren) : true; }, getNodeCheckFlags: function (node) { @@ -46065,17 +53738,17 @@ var ts; isLateBound: function (nodeIn) { var node = ts.getParseTreeNode(nodeIn, ts.isDeclaration); var symbol = node && getSymbolOfNode(node); - return !!(symbol && ts.getCheckFlags(symbol) & 1024); + return !!(symbol && ts.getCheckFlags(symbol) & 1024 /* Late */); }, getJsxFactoryEntity: function (location) { return location ? (getJsxNamespace(location), (ts.getSourceFileOfNode(location).localJsxFactory || _jsxFactoryEntity)) : _jsxFactoryEntity; }, getAllAccessorDeclarations: function (accessor) { - accessor = ts.getParseTreeNode(accessor, ts.isGetOrSetAccessorDeclaration); - var otherKind = accessor.kind === 157 ? 156 : 157; + accessor = ts.getParseTreeNode(accessor, ts.isGetOrSetAccessorDeclaration); // TODO: GH#18217 + var otherKind = accessor.kind === 157 /* SetAccessor */ ? 156 /* GetAccessor */ : 157 /* SetAccessor */; var otherAccessor = ts.getDeclarationOfKind(getSymbolOfNode(accessor), otherKind); var firstAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? otherAccessor : accessor; var secondAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? accessor : otherAccessor; - var setAccessor = accessor.kind === 157 ? accessor : otherAccessor; - var getAccessor = accessor.kind === 156 ? accessor : otherAccessor; + var setAccessor = accessor.kind === 157 /* SetAccessor */ ? accessor : otherAccessor; + var getAccessor = accessor.kind === 156 /* GetAccessor */ ? accessor : otherAccessor; return { firstAccessor: firstAccessor, secondAccessor: secondAccessor, @@ -46085,29 +53758,38 @@ var ts; } }; function isInHeritageClause(node) { - return node.parent && node.parent.kind === 207 && node.parent.parent && node.parent.parent.kind === 268; + return node.parent && node.parent.kind === 207 /* ExpressionWithTypeArguments */ && node.parent.parent && node.parent.parent.kind === 268 /* HeritageClause */; } + // defined here to avoid outer scope pollution function getTypeReferenceDirectivesForEntityName(node) { + // program does not have any files with type reference directives - bail out if (!fileToDirective) { return undefined; } - var meaning = 67901928 | 1920; - if ((node.kind === 71 && isInTypeQuery(node)) || (node.kind === 185 && !isInHeritageClause(node))) { - meaning = 67216319 | 1048576; + // property access can only be used as values, or types when within an expression with type arguments inside a heritage clause + // qualified names can only be used as types\namespaces + // identifiers are treated as values only if they appear in type queries + var meaning = 67901928 /* Type */ | 1920 /* Namespace */; + if ((node.kind === 71 /* Identifier */ && isInTypeQuery(node)) || (node.kind === 185 /* PropertyAccessExpression */ && !isInHeritageClause(node))) { + meaning = 67216319 /* Value */ | 1048576 /* ExportValue */; } - var symbol = resolveEntityName(node, meaning, true); + var symbol = resolveEntityName(node, meaning, /*ignoreErrors*/ true); return symbol && symbol !== unknownSymbol ? getTypeReferenceDirectivesForSymbol(symbol, meaning) : undefined; } + // defined here to avoid outer scope pollution function getTypeReferenceDirectivesForSymbol(symbol, meaning) { + // program does not have any files with type reference directives - bail out if (!fileToDirective) { return undefined; } if (!isSymbolFromTypeDeclarationFile(symbol)) { return undefined; } + // check what declarations in the symbol can contribute to the target meaning var typeReferenceDirectives; for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var decl = _a[_i]; + // check meaning of the local symbol to see if declaration needs to be analyzed further if (decl.symbol && decl.symbol.flags & meaning) { var file = ts.getSourceFileOfNode(decl); var typeReferenceDirective = fileToDirective.get(file.path); @@ -46115,6 +53797,7 @@ var ts; (typeReferenceDirectives || (typeReferenceDirectives = [])).push(typeReferenceDirective); } else { + // found at least one entry that does not originate from type reference directive return undefined; } } @@ -46122,9 +53805,12 @@ var ts; return typeReferenceDirectives; } function isSymbolFromTypeDeclarationFile(symbol) { + // bail out if symbol does not have associated declarations (i.e. this is transient symbol created for property in binding pattern) if (!symbol.declarations) { return false; } + // walk the parent chain for symbols to make sure that top level parent symbol is in the global scope + // external modules cannot define or contribute to type declaration files var current = symbol; while (true) { var parent = getParentOfSymbol(current); @@ -46135,9 +53821,10 @@ var ts; break; } } - if (current.valueDeclaration && current.valueDeclaration.kind === 274 && current.flags & 512) { + if (current.valueDeclaration && current.valueDeclaration.kind === 274 /* SourceFile */ && current.flags & 512 /* ValueModule */) { return false; } + // check that at least one declaration of top level symbol originates from type declaration file for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var decl = _a[_i]; var file = ts.getSourceFileOfNode(decl); @@ -46149,18 +53836,20 @@ var ts; } } function getExternalModuleFileFromDeclaration(declaration) { - var specifier = declaration.kind === 239 ? ts.tryCast(declaration.name, ts.isStringLiteral) : ts.getExternalModuleName(declaration); - var moduleSymbol = resolveExternalModuleNameWorker(specifier, specifier, undefined); + var specifier = declaration.kind === 239 /* ModuleDeclaration */ ? ts.tryCast(declaration.name, ts.isStringLiteral) : ts.getExternalModuleName(declaration); + var moduleSymbol = resolveExternalModuleNameWorker(specifier, specifier, /*moduleNotFoundError*/ undefined); // TODO: GH#18217 if (!moduleSymbol) { return undefined; } - return ts.getDeclarationOfKind(moduleSymbol, 274); + return ts.getDeclarationOfKind(moduleSymbol, 274 /* SourceFile */); } function initializeTypeChecker() { + // Bind all source files and propagate errors for (var _i = 0, _a = host.getSourceFiles(); _i < _a.length; _i++) { var file = _a[_i]; ts.bindSourceFile(file, compilerOptions); } + // Initialize global symbol table var augmentations; for (var _b = 0, _c = host.getSourceFiles(); _b < _c.length; _b++) { var file = _c[_b]; @@ -46174,6 +53863,7 @@ var ts; (augmentations || (augmentations = [])).push(file.moduleAugmentations); } if (file.symbol && file.symbol.globalExports) { + // Merge in UMD exports with first-in-wins semantics (see #9771) var source = file.symbol.globalExports; source.forEach(function (sourceSymbol, id) { if (!globals.has(id)) { @@ -46182,7 +53872,15 @@ var ts; }); } } + // We do global augmentations separately from module augmentations (and before creating global types) because they + // 1. Affect global types. We won't have the correct global types until global augmentations are merged. Also, + // 2. Module augmentation instantiation requires creating the type of a module, which, in turn, can require + // checking for an export or property on the module (if export=) which, in turn, can fall back to the + // apparent type of the module - either globalObjectType or globalFunctionType - which wouldn't exist if we + // did module augmentations prior to finalizing the global types. if (augmentations) { + // merge _global_ module augmentations. + // this needs to be done after global symbol table is initialized to make sure that all ambient modules are indexed for (var _d = 0, augmentations_1 = augmentations; _d < augmentations_1.length; _d++) { var list = augmentations_1[_d]; for (var _e = 0, list_1 = list; _e < list_1.length; _e++) { @@ -46193,26 +53891,31 @@ var ts; } } } + // Setup global builtins addToSymbolTable(globals, builtinGlobals, ts.Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0); getSymbolLinks(undefinedSymbol).type = undefinedWideningType; - getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments", 0, true); + getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments", /*arity*/ 0, /*reportErrors*/ true); getSymbolLinks(unknownSymbol).type = errorType; - globalArrayType = getGlobalType("Array", 1, true); - globalObjectType = getGlobalType("Object", 0, true); - globalFunctionType = getGlobalType("Function", 0, true); - globalStringType = getGlobalType("String", 0, true); - globalNumberType = getGlobalType("Number", 0, true); - globalBooleanType = getGlobalType("Boolean", 0, true); - globalRegExpType = getGlobalType("RegExp", 0, true); + // Initialize special types + globalArrayType = getGlobalType("Array", /*arity*/ 1, /*reportErrors*/ true); + globalObjectType = getGlobalType("Object", /*arity*/ 0, /*reportErrors*/ true); + globalFunctionType = getGlobalType("Function", /*arity*/ 0, /*reportErrors*/ true); + globalStringType = getGlobalType("String", /*arity*/ 0, /*reportErrors*/ true); + globalNumberType = getGlobalType("Number", /*arity*/ 0, /*reportErrors*/ true); + globalBooleanType = getGlobalType("Boolean", /*arity*/ 0, /*reportErrors*/ true); + globalRegExpType = getGlobalType("RegExp", /*arity*/ 0, /*reportErrors*/ true); anyArrayType = createArrayType(anyType); autoArrayType = createArrayType(autoType); if (autoArrayType === emptyObjectType) { + // autoArrayType is used as a marker, so even if global Array type is not defined, it needs to be a unique type autoArrayType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, undefined, undefined); } - globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray", 1); + globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray", /*arity*/ 1); anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType; - globalThisType = getGlobalTypeOrUndefined("ThisType", 1); + globalThisType = getGlobalTypeOrUndefined("ThisType", /*arity*/ 1); if (augmentations) { + // merge _nonglobal_ module augmentations. + // this needs to be done after global symbol table is initialized to make sure that all ambient modules are indexed for (var _f = 0, augmentations_2 = augmentations; _f < augmentations_2.length; _f++) { var list = augmentations_2[_f]; for (var _g = 0, list_2 = list; _g < list_2.length; _g++) { @@ -46227,14 +53930,14 @@ var ts; function checkExternalEmitHelpers(location, helpers) { if ((requestedExternalEmitHelpers & helpers) !== helpers && compilerOptions.importHelpers) { var sourceFile = ts.getSourceFileOfNode(location); - if (ts.isEffectiveExternalModule(sourceFile, compilerOptions) && !(location.flags & 4194304)) { + if (ts.isEffectiveExternalModule(sourceFile, compilerOptions) && !(location.flags & 4194304 /* Ambient */)) { var helpersModule = resolveHelpersModule(sourceFile, location); if (helpersModule !== unknownSymbol) { var uncheckedHelpers = helpers & ~requestedExternalEmitHelpers; - for (var helper = 1; helper <= 65536; helper <<= 1) { + for (var helper = 1 /* FirstEmitHelper */; helper <= 65536 /* LastEmitHelper */; helper <<= 1) { if (uncheckedHelpers & helper) { var name = getHelperName(helper); - var symbol = getSymbol(helpersModule.exports, ts.escapeLeadingUnderscores(name), 67216319); + var symbol = getSymbol(helpersModule.exports, ts.escapeLeadingUnderscores(name), 67216319 /* Value */); if (!symbol) { error(location, ts.Diagnostics.This_syntax_requires_an_imported_helper_named_1_but_module_0_has_no_exported_member_1, ts.externalHelpersModuleNameText, name); } @@ -46247,23 +53950,23 @@ var ts; } function getHelperName(helper) { switch (helper) { - case 1: return "__extends"; - case 2: return "__assign"; - case 4: return "__rest"; - case 8: return "__decorate"; - case 16: return "__metadata"; - case 32: return "__param"; - case 64: return "__awaiter"; - case 128: return "__generator"; - case 256: return "__values"; - case 512: return "__read"; - case 1024: return "__spread"; - case 2048: return "__await"; - case 4096: return "__asyncGenerator"; - case 8192: return "__asyncDelegator"; - case 16384: return "__asyncValues"; - case 32768: return "__exportStar"; - case 65536: return "__makeTemplateObject"; + case 1 /* Extends */: return "__extends"; + case 2 /* Assign */: return "__assign"; + case 4 /* Rest */: return "__rest"; + case 8 /* Decorate */: return "__decorate"; + case 16 /* Metadata */: return "__metadata"; + case 32 /* Param */: return "__param"; + case 64 /* Awaiter */: return "__awaiter"; + case 128 /* Generator */: return "__generator"; + case 256 /* Values */: return "__values"; + case 512 /* Read */: return "__read"; + case 1024 /* Spread */: return "__spread"; + case 2048 /* Await */: return "__await"; + case 4096 /* AsyncGenerator */: return "__asyncGenerator"; + case 8192 /* AsyncDelegator */: return "__asyncDelegator"; + case 16384 /* AsyncValues */: return "__asyncValues"; + case 32768 /* ExportStar */: return "__exportStar"; + case 65536 /* MakeTemplateObject */: return "__makeTemplateObject"; default: return ts.Debug.fail("Unrecognized helper"); } } @@ -46273,6 +53976,7 @@ var ts; } return externalHelpersModule; } + // GRAMMAR CHECKING function checkGrammarDecoratorsAndModifiers(node) { return checkGrammarDecorators(node) || checkGrammarModifiers(node); } @@ -46281,14 +53985,14 @@ var ts; return false; } if (!ts.nodeCanBeDecorated(node, node.parent, node.parent.parent)) { - if (node.kind === 154 && !ts.nodeIsPresent(node.body)) { + if (node.kind === 154 /* MethodDeclaration */ && !ts.nodeIsPresent(node.body)) { return grammarErrorOnFirstToken(node, ts.Diagnostics.A_decorator_can_only_decorate_a_method_implementation_not_an_overload); } else { return grammarErrorOnFirstToken(node, ts.Diagnostics.Decorators_are_not_valid_here); } } - else if (node.kind === 156 || node.kind === 157) { + else if (node.kind === 156 /* GetAccessor */ || node.kind === 157 /* SetAccessor */) { var accessors = ts.getAllAccessorDeclarations(node.parent.members, node); if (accessors.firstAccessor.decorators && node === accessors.secondAccessor) { return grammarErrorOnFirstToken(node, ts.Diagnostics.Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name); @@ -46302,44 +54006,44 @@ var ts; return quickResult; } var lastStatic, lastDeclare, lastAsync, lastReadonly; - var flags = 0; + var flags = 0 /* None */; for (var _i = 0, _a = node.modifiers; _i < _a.length; _i++) { var modifier = _a[_i]; - if (modifier.kind !== 132) { - if (node.kind === 151 || node.kind === 153) { + if (modifier.kind !== 132 /* ReadonlyKeyword */) { + if (node.kind === 151 /* PropertySignature */ || node.kind === 153 /* MethodSignature */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_type_member, ts.tokenToString(modifier.kind)); } - if (node.kind === 160) { + if (node.kind === 160 /* IndexSignature */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_an_index_signature, ts.tokenToString(modifier.kind)); } } switch (modifier.kind) { - case 76: - if (node.kind !== 238 && node.parent.kind === 235) { - return grammarErrorOnNode(node, ts.Diagnostics.A_class_member_cannot_have_the_0_keyword, ts.tokenToString(76)); + case 76 /* ConstKeyword */: + if (node.kind !== 238 /* EnumDeclaration */ && node.parent.kind === 235 /* ClassDeclaration */) { + return grammarErrorOnNode(node, ts.Diagnostics.A_class_member_cannot_have_the_0_keyword, ts.tokenToString(76 /* ConstKeyword */)); } break; - case 114: - case 113: - case 112: + case 114 /* PublicKeyword */: + case 113 /* ProtectedKeyword */: + case 112 /* PrivateKeyword */: var text = visibilityToString(ts.modifierToFlag(modifier.kind)); - if (flags & 28) { + if (flags & 28 /* AccessibilityModifier */) { return grammarErrorOnNode(modifier, ts.Diagnostics.Accessibility_modifier_already_seen); } - else if (flags & 32) { + else if (flags & 32 /* Static */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, text, "static"); } - else if (flags & 64) { + else if (flags & 64 /* Readonly */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, text, "readonly"); } - else if (flags & 256) { + else if (flags & 256 /* Async */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, text, "async"); } - else if (node.parent.kind === 240 || node.parent.kind === 274) { + else if (node.parent.kind === 240 /* ModuleBlock */ || node.parent.kind === 274 /* SourceFile */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element, text); } - else if (flags & 128) { - if (modifier.kind === 112) { + else if (flags & 128 /* Abstract */) { + if (modifier.kind === 112 /* PrivateKeyword */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_with_1_modifier, text, "abstract"); } else { @@ -46348,152 +54052,157 @@ var ts; } flags |= ts.modifierToFlag(modifier.kind); break; - case 115: - if (flags & 32) { + case 115 /* StaticKeyword */: + if (flags & 32 /* Static */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "static"); } - else if (flags & 64) { + else if (flags & 64 /* Readonly */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "static", "readonly"); } - else if (flags & 256) { + else if (flags & 256 /* Async */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "static", "async"); } - else if (node.parent.kind === 240 || node.parent.kind === 274) { + else if (node.parent.kind === 240 /* ModuleBlock */ || node.parent.kind === 274 /* SourceFile */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element, "static"); } - else if (node.kind === 149) { + else if (node.kind === 149 /* Parameter */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "static"); } - else if (flags & 128) { + else if (flags & 128 /* Abstract */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "abstract"); } - flags |= 32; + flags |= 32 /* Static */; lastStatic = modifier; break; - case 132: - if (flags & 64) { + case 132 /* ReadonlyKeyword */: + if (flags & 64 /* Readonly */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "readonly"); } - else if (node.kind !== 152 && node.kind !== 151 && node.kind !== 160 && node.kind !== 149) { + else if (node.kind !== 152 /* PropertyDeclaration */ && node.kind !== 151 /* PropertySignature */ && node.kind !== 160 /* IndexSignature */ && node.kind !== 149 /* Parameter */) { + // If node.kind === SyntaxKind.Parameter, checkParameter report an error if it's not a parameter property. return grammarErrorOnNode(modifier, ts.Diagnostics.readonly_modifier_can_only_appear_on_a_property_declaration_or_index_signature); } - flags |= 64; + flags |= 64 /* Readonly */; lastReadonly = modifier; break; - case 84: - if (flags & 1) { + case 84 /* ExportKeyword */: + if (flags & 1 /* Export */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "export"); } - else if (flags & 2) { + else if (flags & 2 /* Ambient */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "export", "declare"); } - else if (flags & 128) { + else if (flags & 128 /* Abstract */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "export", "abstract"); } - else if (flags & 256) { + else if (flags & 256 /* Async */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "export", "async"); } - else if (node.parent.kind === 235) { + else if (node.parent.kind === 235 /* ClassDeclaration */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_class_element, "export"); } - else if (node.kind === 149) { + else if (node.kind === 149 /* Parameter */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "export"); } - flags |= 1; + flags |= 1 /* Export */; break; - case 79: - var container = node.parent.kind === 274 ? node.parent : node.parent.parent; - if (container.kind === 239 && !ts.isAmbientModule(container)) { + case 79 /* DefaultKeyword */: + var container = node.parent.kind === 274 /* SourceFile */ ? node.parent : node.parent.parent; + if (container.kind === 239 /* ModuleDeclaration */ && !ts.isAmbientModule(container)) { return grammarErrorOnNode(modifier, ts.Diagnostics.A_default_export_can_only_be_used_in_an_ECMAScript_style_module); } - flags |= 512; + flags |= 512 /* Default */; break; - case 124: - if (flags & 2) { + case 124 /* DeclareKeyword */: + if (flags & 2 /* Ambient */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "declare"); } - else if (flags & 256) { + else if (flags & 256 /* Async */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async"); } - else if (node.parent.kind === 235) { + else if (node.parent.kind === 235 /* ClassDeclaration */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_class_element, "declare"); } - else if (node.kind === 149) { + else if (node.kind === 149 /* Parameter */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "declare"); } - else if ((node.parent.flags & 4194304) && node.parent.kind === 240) { + else if ((node.parent.flags & 4194304 /* Ambient */) && node.parent.kind === 240 /* ModuleBlock */) { return grammarErrorOnNode(modifier, ts.Diagnostics.A_declare_modifier_cannot_be_used_in_an_already_ambient_context); } - flags |= 2; + flags |= 2 /* Ambient */; lastDeclare = modifier; break; - case 117: - if (flags & 128) { + case 117 /* AbstractKeyword */: + if (flags & 128 /* Abstract */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "abstract"); } - if (node.kind !== 235) { - if (node.kind !== 154 && - node.kind !== 152 && - node.kind !== 156 && - node.kind !== 157) { + if (node.kind !== 235 /* ClassDeclaration */) { + if (node.kind !== 154 /* MethodDeclaration */ && + node.kind !== 152 /* PropertyDeclaration */ && + node.kind !== 156 /* GetAccessor */ && + node.kind !== 157 /* SetAccessor */) { return grammarErrorOnNode(modifier, ts.Diagnostics.abstract_modifier_can_only_appear_on_a_class_method_or_property_declaration); } - if (!(node.parent.kind === 235 && ts.hasModifier(node.parent, 128))) { + if (!(node.parent.kind === 235 /* ClassDeclaration */ && ts.hasModifier(node.parent, 128 /* Abstract */))) { return grammarErrorOnNode(modifier, ts.Diagnostics.Abstract_methods_can_only_appear_within_an_abstract_class); } - if (flags & 32) { + if (flags & 32 /* Static */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "abstract"); } - if (flags & 8) { + if (flags & 8 /* Private */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "private", "abstract"); } } - flags |= 128; + flags |= 128 /* Abstract */; break; - case 120: - if (flags & 256) { + case 120 /* AsyncKeyword */: + if (flags & 256 /* Async */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "async"); } - else if (flags & 2 || node.parent.flags & 4194304) { + else if (flags & 2 /* Ambient */ || node.parent.flags & 4194304 /* Ambient */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async"); } - else if (node.kind === 149) { + else if (node.kind === 149 /* Parameter */) { return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "async"); } - flags |= 256; + flags |= 256 /* Async */; lastAsync = modifier; break; } } - if (node.kind === 155) { - if (flags & 32) { + if (node.kind === 155 /* Constructor */) { + if (flags & 32 /* Static */) { return grammarErrorOnNode(lastStatic, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "static"); } - if (flags & 128) { - return grammarErrorOnNode(lastStatic, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "abstract"); + if (flags & 128 /* Abstract */) { + return grammarErrorOnNode(lastStatic, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "abstract"); // TODO: GH#18217 } - else if (flags & 256) { + else if (flags & 256 /* Async */) { return grammarErrorOnNode(lastAsync, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "async"); } - else if (flags & 64) { + else if (flags & 64 /* Readonly */) { return grammarErrorOnNode(lastReadonly, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "readonly"); } return false; } - else if ((node.kind === 244 || node.kind === 243) && flags & 2) { + else if ((node.kind === 244 /* ImportDeclaration */ || node.kind === 243 /* ImportEqualsDeclaration */) && flags & 2 /* Ambient */) { return grammarErrorOnNode(lastDeclare, ts.Diagnostics.A_0_modifier_cannot_be_used_with_an_import_declaration, "declare"); } - else if (node.kind === 149 && (flags & 92) && ts.isBindingPattern(node.name)) { + else if (node.kind === 149 /* Parameter */ && (flags & 92 /* ParameterPropertyModifier */) && ts.isBindingPattern(node.name)) { return grammarErrorOnNode(node, ts.Diagnostics.A_parameter_property_may_not_be_declared_using_a_binding_pattern); } - else if (node.kind === 149 && (flags & 92) && node.dotDotDotToken) { + else if (node.kind === 149 /* Parameter */ && (flags & 92 /* ParameterPropertyModifier */) && node.dotDotDotToken) { return grammarErrorOnNode(node, ts.Diagnostics.A_parameter_property_cannot_be_declared_using_a_rest_parameter); } - if (flags & 256) { + if (flags & 256 /* Async */) { return checkGrammarAsyncModifier(node, lastAsync); } return false; } + /** + * true | false: Early return this value from checkGrammarModifiers. + * undefined: Need to do full checking on the modifiers. + */ function reportObviousModifierErrors(node) { return !node.modifiers ? false @@ -46503,38 +54212,38 @@ var ts; } function shouldReportBadModifier(node) { switch (node.kind) { - case 156: - case 157: - case 155: - case 152: - case 151: - case 154: - case 153: - case 160: - case 239: - case 244: - case 243: - case 250: - case 249: - case 192: - case 193: - case 149: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 155 /* Constructor */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 160 /* IndexSignature */: + case 239 /* ModuleDeclaration */: + case 244 /* ImportDeclaration */: + case 243 /* ImportEqualsDeclaration */: + case 250 /* ExportDeclaration */: + case 249 /* ExportAssignment */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 149 /* Parameter */: return false; default: - if (node.parent.kind === 240 || node.parent.kind === 274) { + if (node.parent.kind === 240 /* ModuleBlock */ || node.parent.kind === 274 /* SourceFile */) { return false; } switch (node.kind) { - case 234: - return nodeHasAnyModifiersExcept(node, 120); - case 235: - return nodeHasAnyModifiersExcept(node, 117); - case 236: - case 214: - case 237: + case 234 /* FunctionDeclaration */: + return nodeHasAnyModifiersExcept(node, 120 /* AsyncKeyword */); + case 235 /* ClassDeclaration */: + return nodeHasAnyModifiersExcept(node, 117 /* AbstractKeyword */); + case 236 /* InterfaceDeclaration */: + case 214 /* VariableStatement */: + case 237 /* TypeAliasDeclaration */: return true; - case 238: - return nodeHasAnyModifiersExcept(node, 76); + case 238 /* EnumDeclaration */: + return nodeHasAnyModifiersExcept(node, 76 /* ConstKeyword */); default: ts.Debug.fail(); return false; @@ -46546,10 +54255,10 @@ var ts; } function checkGrammarAsyncModifier(node, asyncModifier) { switch (node.kind) { - case 154: - case 234: - case 192: - case 193: + case 154 /* MethodDeclaration */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: return false; } return grammarErrorOnNode(asyncModifier, ts.Diagnostics._0_modifier_cannot_be_used_here, "async"); @@ -46578,7 +54287,7 @@ var ts; if (i !== (parameterCount - 1)) { return grammarErrorOnNode(parameter.dotDotDotToken, ts.Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list); } - if (!(parameter.flags & 4194304)) { + if (!(parameter.flags & 4194304 /* Ambient */)) { // Allow `...foo,` in ambient declarations; see GH#23070 checkGrammarForDisallowedTrailingComma(parameters, ts.Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma); } if (ts.isBindingPattern(parameter.name)) { @@ -46603,6 +54312,7 @@ var ts; } } function checkGrammarFunctionLikeDeclaration(node) { + // Prevent cascading error by short-circuit var file = ts.getSourceFileOfNode(node); return checkGrammarDecoratorsAndModifiers(node) || checkGrammarTypeParameterList(node.typeParameters, file) || checkGrammarParameterList(node.parameters) || checkGrammarArrowFunction(node, file); @@ -46645,12 +54355,12 @@ var ts; if (!parameter.type) { return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_must_have_a_type_annotation); } - if (parameter.type.kind !== 137 && parameter.type.kind !== 134) { + if (parameter.type.kind !== 137 /* StringKeyword */ && parameter.type.kind !== 134 /* NumberKeyword */) { var type = getTypeFromTypeNode(parameter.type); - if (type.flags & 4 || type.flags & 8) { + if (type.flags & 4 /* String */ || type.flags & 8 /* Number */) { return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_type_cannot_be_a_type_alias_Consider_writing_0_Colon_1_Colon_2_instead, ts.getTextOfNode(parameter.name), typeToString(type), typeToString(getTypeFromTypeNode(node.type))); } - if (type.flags & 262144 && allTypesAssignableToKind(type, 64, true)) { + if (type.flags & 262144 /* Union */ && allTypesAssignableToKind(type, 64 /* StringLiteral */, /*strict*/ true)) { return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_type_cannot_be_a_union_type_Consider_using_a_mapped_object_type_instead); } return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_type_must_be_string_or_number); @@ -46661,6 +54371,7 @@ var ts; return false; } function checkGrammarIndexSignature(node) { + // Prevent cascading error by short-circuit return checkGrammarDecoratorsAndModifiers(node) || checkGrammarIndexSignatureParameters(node); } function checkGrammarForAtLeastOneTypeArgument(node, typeArguments) { @@ -46680,7 +54391,7 @@ var ts; if (args) { for (var _i = 0, args_5 = args; _i < args_5.length; _i++) { var arg = args_5[_i]; - if (arg.kind === 206) { + if (arg.kind === 206 /* OmittedExpression */) { return grammarErrorAtPos(arg, arg.pos, 0, ts.Diagnostics.Argument_expression_expected); } } @@ -46710,7 +54421,7 @@ var ts; if (!checkGrammarDecoratorsAndModifiers(node) && node.heritageClauses) { for (var _i = 0, _a = node.heritageClauses; _i < _a.length; _i++) { var heritageClause = _a[_i]; - if (heritageClause.token === 85) { + if (heritageClause.token === 85 /* ExtendsKeyword */) { if (seenExtendsClause) { return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.extends_clause_already_seen); } @@ -46723,12 +54434,13 @@ var ts; seenExtendsClause = true; } else { - ts.Debug.assert(heritageClause.token === 108); + ts.Debug.assert(heritageClause.token === 108 /* ImplementsKeyword */); if (seenImplementsClause) { return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.implements_clause_already_seen); } seenImplementsClause = true; } + // Grammar checking heritageClause inside class declaration checkGrammarHeritageClause(heritageClause); } } @@ -46738,37 +54450,39 @@ var ts; if (node.heritageClauses) { for (var _i = 0, _a = node.heritageClauses; _i < _a.length; _i++) { var heritageClause = _a[_i]; - if (heritageClause.token === 85) { + if (heritageClause.token === 85 /* ExtendsKeyword */) { if (seenExtendsClause) { return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.extends_clause_already_seen); } seenExtendsClause = true; } else { - ts.Debug.assert(heritageClause.token === 108); + ts.Debug.assert(heritageClause.token === 108 /* ImplementsKeyword */); return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.Interface_declaration_cannot_have_implements_clause); } + // Grammar checking heritageClause inside class declaration checkGrammarHeritageClause(heritageClause); } } return false; } function checkGrammarComputedPropertyName(node) { - if (node.kind !== 147) { + // If node is not a computedPropertyName, just skip the grammar checking + if (node.kind !== 147 /* ComputedPropertyName */) { return false; } var computedPropertyName = node; - if (computedPropertyName.expression.kind === 200 && computedPropertyName.expression.operatorToken.kind === 26) { + if (computedPropertyName.expression.kind === 200 /* BinaryExpression */ && computedPropertyName.expression.operatorToken.kind === 26 /* CommaToken */) { return grammarErrorOnNode(computedPropertyName.expression, ts.Diagnostics.A_comma_expression_is_not_allowed_in_a_computed_property_name); } return false; } function checkGrammarForGenerator(node) { if (node.asteriskToken) { - ts.Debug.assert(node.kind === 234 || - node.kind === 192 || - node.kind === 154); - if (node.flags & 4194304) { + ts.Debug.assert(node.kind === 234 /* FunctionDeclaration */ || + node.kind === 192 /* FunctionExpression */ || + node.kind === 154 /* MethodDeclaration */); + if (node.flags & 4194304 /* Ambient */) { return grammarErrorOnNode(node.asteriskToken, ts.Diagnostics.Generators_are_not_allowed_in_an_ambient_context); } if (!node.body) { @@ -46790,40 +54504,54 @@ var ts; var seen = ts.createUnderscoreEscapedMap(); for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { var prop = _a[_i]; - if (prop.kind === 272) { + if (prop.kind === 272 /* SpreadAssignment */) { continue; } var name = prop.name; - if (name.kind === 147) { + if (name.kind === 147 /* ComputedPropertyName */) { + // If the name is not a ComputedPropertyName, the grammar checking will skip it checkGrammarComputedPropertyName(name); } - if (prop.kind === 271 && !inDestructuring && prop.objectAssignmentInitializer) { + if (prop.kind === 271 /* ShorthandPropertyAssignment */ && !inDestructuring && prop.objectAssignmentInitializer) { + // having objectAssignmentInitializer is only valid in ObjectAssignmentPattern + // outside of destructuring it is a syntax error return grammarErrorOnNode(prop.equalsToken, ts.Diagnostics.can_only_be_used_in_an_object_literal_property_inside_a_destructuring_assignment); } + // Modifiers are never allowed on properties except for 'async' on a method declaration if (prop.modifiers) { - for (var _b = 0, _c = prop.modifiers; _b < _c.length; _b++) { + for (var _b = 0, _c = prop.modifiers; _b < _c.length; _b++) { // TODO: GH#19955 var mod = _c[_b]; - if (mod.kind !== 120 || prop.kind !== 154) { + if (mod.kind !== 120 /* AsyncKeyword */ || prop.kind !== 154 /* MethodDeclaration */) { grammarErrorOnNode(mod, ts.Diagnostics._0_modifier_cannot_be_used_here, ts.getTextOfNode(mod)); } } } + // ECMA-262 11.1.5 Object Initializer + // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true + // a.This production is contained in strict code and IsDataDescriptor(previous) is true and + // IsDataDescriptor(propId.descriptor) is true. + // b.IsDataDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true. + // c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(propId.descriptor) is true. + // d.IsAccessorDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true + // and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields var currentKind = void 0; switch (prop.kind) { - case 270: - case 271: + case 270 /* PropertyAssignment */: + case 271 /* ShorthandPropertyAssignment */: + // Grammar checking for computedPropertyName and shorthandPropertyAssignment checkGrammarForInvalidQuestionMark(prop.questionToken, ts.Diagnostics.An_object_member_cannot_be_declared_optional); - if (name.kind === 8) { + if (name.kind === 8 /* NumericLiteral */) { checkGrammarNumericLiteral(name); } - case 154: - currentKind = 1; + // falls through + case 154 /* MethodDeclaration */: + currentKind = 1 /* Property */; break; - case 156: - currentKind = 2; + case 156 /* GetAccessor */: + currentKind = 2 /* GetAccessor */; break; - case 157: - currentKind = 4; + case 157 /* SetAccessor */: + currentKind = 4 /* SetAccessor */; break; default: throw ts.Debug.assertNever(prop, "Unexpected syntax kind:" + prop.kind); @@ -46837,11 +54565,11 @@ var ts; seen.set(effectiveName, currentKind); } else { - if (currentKind === 1 && existingKind === 1) { + if (currentKind === 1 /* Property */ && existingKind === 1 /* Property */) { grammarErrorOnNode(name, ts.Diagnostics.Duplicate_identifier_0, ts.getTextOfNode(name)); } - else if ((currentKind & 6) && (existingKind & 6)) { - if (existingKind !== 6 && currentKind !== existingKind) { + else if ((currentKind & 6 /* GetOrSetAccessor */) && (existingKind & 6 /* GetOrSetAccessor */)) { + if (existingKind !== 6 /* GetOrSetAccessor */ && currentKind !== existingKind) { seen.set(effectiveName, currentKind | existingKind); } else { @@ -46859,7 +54587,7 @@ var ts; var seen = ts.createUnderscoreEscapedMap(); for (var _i = 0, _a = node.attributes.properties; _i < _a.length; _i++) { var attr = _a[_i]; - if (attr.kind === 264) { + if (attr.kind === 264 /* JsxSpreadAttribute */) { continue; } var name = attr.name, initializer = attr.initializer; @@ -46869,7 +54597,7 @@ var ts; else { return grammarErrorOnNode(name, ts.Diagnostics.JSX_elements_cannot_have_multiple_attributes_with_the_same_name); } - if (initializer && initializer.kind === 265 && !initializer.expression) { + if (initializer && initializer.kind === 265 /* JsxExpression */ && !initializer.expression) { return grammarErrorOnNode(initializer, ts.Diagnostics.JSX_attributes_must_only_be_assigned_a_non_empty_expression); } } @@ -46878,33 +54606,40 @@ var ts; if (checkGrammarStatementInAmbientContext(forInOrOfStatement)) { return true; } - if (forInOrOfStatement.kind === 222 && forInOrOfStatement.awaitModifier) { - if ((forInOrOfStatement.flags & 16384) === 0) { + if (forInOrOfStatement.kind === 222 /* ForOfStatement */ && forInOrOfStatement.awaitModifier) { + if ((forInOrOfStatement.flags & 16384 /* AwaitContext */) === 0 /* None */) { return grammarErrorOnNode(forInOrOfStatement.awaitModifier, ts.Diagnostics.A_for_await_of_statement_is_only_allowed_within_an_async_function_or_async_generator); } } - if (forInOrOfStatement.initializer.kind === 233) { + if (forInOrOfStatement.initializer.kind === 233 /* VariableDeclarationList */) { var variableList = forInOrOfStatement.initializer; if (!checkGrammarVariableDeclarationList(variableList)) { var declarations = variableList.declarations; + // declarations.length can be zero if there is an error in variable declaration in for-of or for-in + // See http://www.ecma-international.org/ecma-262/6.0/#sec-for-in-and-for-of-statements for details + // For example: + // var let = 10; + // for (let of [1,2,3]) {} // this is invalid ES6 syntax + // for (let in [1,2,3]) {} // this is invalid ES6 syntax + // We will then want to skip on grammar checking on variableList declaration if (!declarations.length) { return false; } if (declarations.length > 1) { - var diagnostic = forInOrOfStatement.kind === 221 + var diagnostic = forInOrOfStatement.kind === 221 /* ForInStatement */ ? ts.Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement : ts.Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement; return grammarErrorOnFirstToken(variableList.declarations[1], diagnostic); } var firstDeclaration = declarations[0]; if (firstDeclaration.initializer) { - var diagnostic = forInOrOfStatement.kind === 221 + var diagnostic = forInOrOfStatement.kind === 221 /* ForInStatement */ ? ts.Diagnostics.The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer : ts.Diagnostics.The_variable_declaration_of_a_for_of_statement_cannot_have_an_initializer; return grammarErrorOnNode(firstDeclaration.name, diagnostic); } if (firstDeclaration.type) { - var diagnostic = forInOrOfStatement.kind === 221 + var diagnostic = forInOrOfStatement.kind === 221 /* ForInStatement */ ? ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation : ts.Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_use_a_type_annotation; return grammarErrorOnNode(firstDeclaration, diagnostic); @@ -46915,27 +54650,27 @@ var ts; } function checkGrammarAccessor(accessor) { var kind = accessor.kind; - if (languageVersion < 1) { + if (languageVersion < 1 /* ES5 */) { return grammarErrorOnNode(accessor.name, ts.Diagnostics.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher); } - else if (accessor.flags & 4194304) { + else if (accessor.flags & 4194304 /* Ambient */) { return grammarErrorOnNode(accessor.name, ts.Diagnostics.An_accessor_cannot_be_declared_in_an_ambient_context); } - else if (accessor.body === undefined && !ts.hasModifier(accessor, 128)) { + else if (accessor.body === undefined && !ts.hasModifier(accessor, 128 /* Abstract */)) { return grammarErrorAtPos(accessor, accessor.end - 1, ";".length, ts.Diagnostics._0_expected, "{"); } - else if (accessor.body && ts.hasModifier(accessor, 128)) { + else if (accessor.body && ts.hasModifier(accessor, 128 /* Abstract */)) { return grammarErrorOnNode(accessor, ts.Diagnostics.An_abstract_accessor_cannot_have_an_implementation); } else if (accessor.typeParameters) { return grammarErrorOnNode(accessor.name, ts.Diagnostics.An_accessor_cannot_have_type_parameters); } else if (!doesAccessorHaveCorrectParameterCount(accessor)) { - return grammarErrorOnNode(accessor.name, kind === 156 ? + return grammarErrorOnNode(accessor.name, kind === 156 /* GetAccessor */ ? ts.Diagnostics.A_get_accessor_cannot_have_parameters : ts.Diagnostics.A_set_accessor_must_have_exactly_one_parameter); } - else if (kind === 157) { + else if (kind === 157 /* SetAccessor */) { if (accessor.type) { return grammarErrorOnNode(accessor.name, ts.Diagnostics.A_set_accessor_cannot_have_a_return_type_annotation); } @@ -46954,41 +54689,45 @@ var ts; } return false; } + /** Does the accessor have the right number of parameters? + * A get accessor has no parameters or a single `this` parameter. + * A set accessor has one parameter or a `this` parameter and one more parameter. + */ function doesAccessorHaveCorrectParameterCount(accessor) { - return getAccessorThisParameter(accessor) || accessor.parameters.length === (accessor.kind === 156 ? 0 : 1); + return getAccessorThisParameter(accessor) || accessor.parameters.length === (accessor.kind === 156 /* GetAccessor */ ? 0 : 1); } function getAccessorThisParameter(accessor) { - if (accessor.parameters.length === (accessor.kind === 156 ? 1 : 2)) { + if (accessor.parameters.length === (accessor.kind === 156 /* GetAccessor */ ? 1 : 2)) { return ts.getThisParameter(accessor); } } function checkGrammarTypeOperatorNode(node) { - if (node.operator === 141) { - if (node.type.kind !== 138) { - return grammarErrorOnNode(node.type, ts.Diagnostics._0_expected, ts.tokenToString(138)); + if (node.operator === 141 /* UniqueKeyword */) { + if (node.type.kind !== 138 /* SymbolKeyword */) { + return grammarErrorOnNode(node.type, ts.Diagnostics._0_expected, ts.tokenToString(138 /* SymbolKeyword */)); } var parent = ts.walkUpParenthesizedTypes(node.parent); switch (parent.kind) { - case 232: + case 232 /* VariableDeclaration */: var decl = parent; - if (decl.name.kind !== 71) { + if (decl.name.kind !== 71 /* Identifier */) { return grammarErrorOnNode(node, ts.Diagnostics.unique_symbol_types_may_not_be_used_on_a_variable_declaration_with_a_binding_name); } if (!ts.isVariableDeclarationInVariableStatement(decl)) { return grammarErrorOnNode(node, ts.Diagnostics.unique_symbol_types_are_only_allowed_on_variables_in_a_variable_statement); } - if (!(decl.parent.flags & 2)) { + if (!(decl.parent.flags & 2 /* Const */)) { return grammarErrorOnNode(parent.name, ts.Diagnostics.A_variable_whose_type_is_a_unique_symbol_type_must_be_const); } break; - case 152: - if (!ts.hasModifier(parent, 32) || - !ts.hasModifier(parent, 64)) { + case 152 /* PropertyDeclaration */: + if (!ts.hasModifier(parent, 32 /* Static */) || + !ts.hasModifier(parent, 64 /* Readonly */)) { return grammarErrorOnNode(parent.name, ts.Diagnostics.A_property_of_a_class_whose_type_is_a_unique_symbol_type_must_be_both_static_and_readonly); } break; - case 151: - if (!ts.hasModifier(parent, 64)) { + case 151 /* PropertySignature */: + if (!ts.hasModifier(parent, 64 /* Readonly */)) { return grammarErrorOnNode(parent.name, ts.Diagnostics.A_property_of_an_interface_or_type_literal_whose_type_is_a_unique_symbol_type_must_be_readonly); } break; @@ -47006,9 +54745,10 @@ var ts; if (checkGrammarFunctionLikeDeclaration(node)) { return true; } - if (node.kind === 154) { - if (node.parent.kind === 184) { - if (node.modifiers && !(node.modifiers.length === 1 && ts.first(node.modifiers).kind === 120)) { + if (node.kind === 154 /* MethodDeclaration */) { + if (node.parent.kind === 184 /* ObjectLiteralExpression */) { + // We only disallow modifier on a method declaration if it is a property of object-literal-expression + if (node.modifiers && !(node.modifiers.length === 1 && ts.first(node.modifiers).kind === 120 /* AsyncKeyword */)) { return grammarErrorOnFirstToken(node, ts.Diagnostics.Modifiers_cannot_appear_here); } else if (checkGrammarForInvalidQuestionMark(node.questionToken, ts.Diagnostics.An_object_member_cannot_be_declared_optional)) { @@ -47023,17 +54763,22 @@ var ts; } } if (ts.isClassLike(node.parent)) { - if (node.flags & 4194304) { + // Technically, computed properties in ambient contexts is disallowed + // for property declarations and accessors too, not just methods. + // However, property declarations disallow computed names in general, + // and accessors are not allowed in ambient contexts in general, + // so this error only really matters for methods. + if (node.flags & 4194304 /* Ambient */) { return checkGrammarForInvalidDynamicName(node.name, ts.Diagnostics.A_computed_property_name_in_an_ambient_context_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type); } - else if (node.kind === 154 && !node.body) { + else if (node.kind === 154 /* MethodDeclaration */ && !node.body) { return checkGrammarForInvalidDynamicName(node.name, ts.Diagnostics.A_computed_property_name_in_a_method_overload_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type); } } - else if (node.parent.kind === 236) { + else if (node.parent.kind === 236 /* InterfaceDeclaration */) { return checkGrammarForInvalidDynamicName(node.name, ts.Diagnostics.A_computed_property_name_in_an_interface_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type); } - else if (node.parent.kind === 166) { + else if (node.parent.kind === 166 /* TypeLiteral */) { return checkGrammarForInvalidDynamicName(node.name, ts.Diagnostics.A_computed_property_name_in_a_type_literal_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type); } } @@ -47044,23 +54789,27 @@ var ts; return grammarErrorOnNode(node, ts.Diagnostics.Jump_target_cannot_cross_function_boundary); } switch (current.kind) { - case 228: + case 228 /* LabeledStatement */: if (node.label && current.label.escapedText === node.label.escapedText) { - var isMisplacedContinueLabel = node.kind === 223 - && !ts.isIterationStatement(current.statement, true); + // found matching label - verify that label usage is correct + // continue can only target labels that are on iteration statements + var isMisplacedContinueLabel = node.kind === 223 /* ContinueStatement */ + && !ts.isIterationStatement(current.statement, /*lookInLabeledStatement*/ true); if (isMisplacedContinueLabel) { return grammarErrorOnNode(node, ts.Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement); } return false; } break; - case 227: - if (node.kind === 224 && !node.label) { + case 227 /* SwitchStatement */: + if (node.kind === 224 /* BreakStatement */ && !node.label) { + // unlabeled break within switch statement - ok return false; } break; default: - if (ts.isIterationStatement(current, false) && !node.label) { + if (ts.isIterationStatement(current, /*lookInLabeledStatement*/ false) && !node.label) { + // unlabeled break or continue within iteration statement - ok return false; } break; @@ -47068,13 +54817,13 @@ var ts; current = current.parent; } if (node.label) { - var message = node.kind === 224 + var message = node.kind === 224 /* BreakStatement */ ? ts.Diagnostics.A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement : ts.Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement; return grammarErrorOnNode(node, message); } else { - var message = node.kind === 224 + var message = node.kind === 224 /* BreakStatement */ ? ts.Diagnostics.A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement : ts.Diagnostics.A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement; return grammarErrorOnNode(node, message); @@ -47087,25 +54836,26 @@ var ts; return grammarErrorOnNode(node, ts.Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern); } checkGrammarForDisallowedTrailingComma(elements, ts.Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma); - if (node.name.kind === 181 || node.name.kind === 180) { + if (node.name.kind === 181 /* ArrayBindingPattern */ || node.name.kind === 180 /* ObjectBindingPattern */) { return grammarErrorOnNode(node.name, ts.Diagnostics.A_rest_element_cannot_contain_a_binding_pattern); } if (node.propertyName) { return grammarErrorOnNode(node.name, ts.Diagnostics.A_rest_element_cannot_have_a_property_name); } if (node.initializer) { + // Error on equals token which immediately precedes the initializer return grammarErrorAtPos(node, node.initializer.pos - 1, 1, ts.Diagnostics.A_rest_element_cannot_have_an_initializer); } } } function isStringOrNumberLiteralExpression(expr) { - return expr.kind === 9 || expr.kind === 8 || - expr.kind === 198 && expr.operator === 38 && - expr.operand.kind === 8; + return expr.kind === 9 /* StringLiteral */ || expr.kind === 8 /* NumericLiteral */ || + expr.kind === 198 /* PrefixUnaryExpression */ && expr.operator === 38 /* MinusToken */ && + expr.operand.kind === 8 /* NumericLiteral */; } function checkGrammarVariableDeclaration(node) { - if (node.parent.parent.kind !== 221 && node.parent.parent.kind !== 222) { - if (node.flags & 4194304) { + if (node.parent.parent.kind !== 221 /* ForInStatement */ && node.parent.parent.kind !== 222 /* ForOfStatement */) { + if (node.flags & 4194304 /* Ambient */) { if (node.initializer) { if (ts.isConst(node) && !node.type) { if (!isStringOrNumberLiteralExpression(node.initializer)) { @@ -47113,11 +54863,13 @@ var ts; } } else { + // Error on equals token which immediate precedes the initializer var equalsTokenLength = "=".length; return grammarErrorAtPos(node, node.initializer.pos - equalsTokenLength, equalsTokenLength, ts.Diagnostics.Initializers_are_not_allowed_in_ambient_contexts); } } if (node.initializer && !(ts.isConst(node) && isStringOrNumberLiteralExpression(node.initializer))) { + // Error on equals token which immediate precedes the initializer var equalsTokenLength = "=".length; return grammarErrorAtPos(node, node.initializer.pos - equalsTokenLength, equalsTokenLength, ts.Diagnostics.Initializers_are_not_allowed_in_ambient_contexts); } @@ -47131,18 +54883,24 @@ var ts; } } } - if (node.exclamationToken && (node.parent.parent.kind !== 214 || !node.type || node.initializer || node.flags & 4194304)) { + if (node.exclamationToken && (node.parent.parent.kind !== 214 /* VariableStatement */ || !node.type || node.initializer || node.flags & 4194304 /* Ambient */)) { return grammarErrorOnNode(node.exclamationToken, ts.Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context); } if (compilerOptions.module !== ts.ModuleKind.ES2015 && compilerOptions.module !== ts.ModuleKind.ESNext && compilerOptions.module !== ts.ModuleKind.System && !compilerOptions.noEmit && - !(node.parent.parent.flags & 4194304) && ts.hasModifier(node.parent.parent, 1)) { + !(node.parent.parent.flags & 4194304 /* Ambient */) && ts.hasModifier(node.parent.parent, 1 /* Export */)) { checkESModuleMarker(node.name); } var checkLetConstNames = (ts.isLet(node) || ts.isConst(node)); + // 1. LexicalDeclaration : LetOrConst BindingList ; + // It is a Syntax Error if the BoundNames of BindingList contains "let". + // 2. ForDeclaration: ForDeclaration : LetOrConst ForBinding + // It is a Syntax Error if the BoundNames of ForDeclaration contains "let". + // It is a SyntaxError if a VariableDeclaration or VariableDeclarationNoIn occurs within strict code + // and its Identifier is eval or arguments return checkLetConstNames && checkGrammarNameInLetOrConstDeclarations(node.name); } function checkESModuleMarker(name) { - if (name.kind === 71) { + if (name.kind === 71 /* Identifier */) { if (ts.idText(name) === "__esModule") { return grammarErrorOnNode(name, ts.Diagnostics.Identifier_expected_esModule_is_reserved_as_an_exported_marker_when_transforming_ECMAScript_modules); } @@ -47159,8 +54917,8 @@ var ts; return false; } function checkGrammarNameInLetOrConstDeclarations(name) { - if (name.kind === 71) { - if (name.originalKeywordKind === 110) { + if (name.kind === 71 /* Identifier */) { + if (name.originalKeywordKind === 110 /* LetKeyword */) { return grammarErrorOnNode(name, ts.Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations); } } @@ -47187,15 +54945,15 @@ var ts; } function allowLetAndConstDeclarations(parent) { switch (parent.kind) { - case 217: - case 218: - case 219: - case 226: - case 220: - case 221: - case 222: + case 217 /* IfStatement */: + case 218 /* DoStatement */: + case 219 /* WhileStatement */: + case 226 /* WithStatement */: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: return false; - case 228: + case 228 /* LabeledStatement */: return allowLetAndConstDeclarations(parent.parent); } return true; @@ -47213,12 +54971,12 @@ var ts; function checkGrammarMetaProperty(node) { var escapedText = node.name.escapedText; switch (node.keywordToken) { - case 94: + case 94 /* NewKeyword */: if (escapedText !== "target") { return grammarErrorOnNode(node.name, ts.Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, node.name.escapedText, ts.tokenToString(node.keywordToken), "target"); } break; - case 91: + case 91 /* ImportKeyword */: if (escapedText !== "meta") { return grammarErrorOnNode(node.name, ts.Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, node.name.escapedText, ts.tokenToString(node.keywordToken), "meta"); } @@ -47272,7 +55030,7 @@ var ts; return true; } } - else if (node.parent.kind === 236) { + else if (node.parent.kind === 236 /* InterfaceDeclaration */) { if (checkGrammarForInvalidDynamicName(node.name, ts.Diagnostics.A_computed_property_name_in_an_interface_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type)) { return true; } @@ -47280,7 +55038,7 @@ var ts; return grammarErrorOnNode(node.initializer, ts.Diagnostics.An_interface_property_cannot_have_an_initializer); } } - else if (node.parent.kind === 166) { + else if (node.parent.kind === 166 /* TypeLiteral */) { if (checkGrammarForInvalidDynamicName(node.name, ts.Diagnostics.A_computed_property_name_in_a_type_literal_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type)) { return true; } @@ -47288,23 +55046,35 @@ var ts; return grammarErrorOnNode(node.initializer, ts.Diagnostics.A_type_literal_property_cannot_have_an_initializer); } } - if (node.flags & 4194304 && node.initializer) { + if (node.flags & 4194304 /* Ambient */ && node.initializer) { return grammarErrorOnFirstToken(node.initializer, ts.Diagnostics.Initializers_are_not_allowed_in_ambient_contexts); } if (ts.isPropertyDeclaration(node) && node.exclamationToken && (!ts.isClassLike(node.parent) || !node.type || node.initializer || - node.flags & 4194304 || ts.hasModifier(node, 32 | 128))) { + node.flags & 4194304 /* Ambient */ || ts.hasModifier(node, 32 /* Static */ | 128 /* Abstract */))) { return grammarErrorOnNode(node.exclamationToken, ts.Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context); } } function checkGrammarTopLevelElementForRequiredDeclareModifier(node) { - if (node.kind === 236 || - node.kind === 237 || - node.kind === 244 || - node.kind === 243 || - node.kind === 250 || - node.kind === 249 || - node.kind === 242 || - ts.hasModifier(node, 2 | 1 | 512)) { + // A declare modifier is required for any top level .d.ts declaration except export=, export default, export as namespace + // interfaces and imports categories: + // + // DeclarationElement: + // ExportAssignment + // export_opt InterfaceDeclaration + // export_opt TypeAliasDeclaration + // export_opt ImportDeclaration + // export_opt ExternalImportDeclaration + // export_opt AmbientDeclaration + // + // TODO: The spec needs to be amended to reflect this grammar. + if (node.kind === 236 /* InterfaceDeclaration */ || + node.kind === 237 /* TypeAliasDeclaration */ || + node.kind === 244 /* ImportDeclaration */ || + node.kind === 243 /* ImportEqualsDeclaration */ || + node.kind === 250 /* ExportDeclaration */ || + node.kind === 249 /* ExportAssignment */ || + node.kind === 242 /* NamespaceExportDeclaration */ || + ts.hasModifier(node, 2 /* Ambient */ | 1 /* Export */ | 512 /* Default */)) { return false; } return grammarErrorOnFirstToken(node, ts.Diagnostics.A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file); @@ -47312,7 +55082,7 @@ var ts; function checkGrammarTopLevelElementsForRequiredDeclareModifier(file) { for (var _i = 0, _a = file.statements; _i < _a.length; _i++) { var decl = _a[_i]; - if (ts.isDeclaration(decl) || decl.kind === 214) { + if (ts.isDeclaration(decl) || decl.kind === 214 /* VariableStatement */) { if (checkGrammarTopLevelElementForRequiredDeclareModifier(decl)) { return true; } @@ -47321,42 +55091,54 @@ var ts; return false; } function checkGrammarSourceFile(node) { - return !!(node.flags & 4194304) && checkGrammarTopLevelElementsForRequiredDeclareModifier(node); + return !!(node.flags & 4194304 /* Ambient */) && checkGrammarTopLevelElementsForRequiredDeclareModifier(node); } function checkGrammarStatementInAmbientContext(node) { - if (node.flags & 4194304) { + if (node.flags & 4194304 /* Ambient */) { + // An accessors is already reported about the ambient context if (ts.isAccessor(node.parent)) { return getNodeLinks(node).hasReportedStatementInAmbientContext = true; } + // Find containing block which is either Block, ModuleBlock, SourceFile var links = getNodeLinks(node); if (!links.hasReportedStatementInAmbientContext && ts.isFunctionLike(node.parent)) { return getNodeLinks(node).hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, ts.Diagnostics.An_implementation_cannot_be_declared_in_ambient_contexts); } - if (node.parent.kind === 213 || node.parent.kind === 240 || node.parent.kind === 274) { + // We are either parented by another statement, or some sort of block. + // If we're in a block, we only want to really report an error once + // to prevent noisiness. So use a bit on the block to indicate if + // this has already been reported, and don't report if it has. + // + if (node.parent.kind === 213 /* Block */ || node.parent.kind === 240 /* ModuleBlock */ || node.parent.kind === 274 /* SourceFile */) { var links_1 = getNodeLinks(node.parent); + // Check if the containing block ever report this error if (!links_1.hasReportedStatementInAmbientContext) { return links_1.hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, ts.Diagnostics.Statements_are_not_allowed_in_ambient_contexts); } } else { + // We must be parented by a statement. If so, there's no need + // to report the error as our parent will have already done it. + // Debug.assert(isStatement(node.parent)); } } return false; } function checkGrammarNumericLiteral(node) { - if (node.numericLiteralFlags & 32) { + // Grammar checking + if (node.numericLiteralFlags & 32 /* Octal */) { var diagnosticMessage = void 0; - if (languageVersion >= 1) { + if (languageVersion >= 1 /* ES5 */) { diagnosticMessage = ts.Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher_Use_the_syntax_0; } - else if (ts.isChildOfNodeWithKind(node, 178)) { + else if (ts.isChildOfNodeWithKind(node, 178 /* LiteralType */)) { diagnosticMessage = ts.Diagnostics.Octal_literal_types_must_use_ES2015_syntax_Use_the_syntax_0; } - else if (ts.isChildOfNodeWithKind(node, 273)) { + else if (ts.isChildOfNodeWithKind(node, 273 /* EnumMember */)) { diagnosticMessage = ts.Diagnostics.Octal_literals_are_not_allowed_in_enums_members_initializer_Use_the_syntax_0; } if (diagnosticMessage) { - var withMinus = ts.isPrefixUnaryExpression(node.parent) && node.parent.operator === 38; + var withMinus = ts.isPrefixUnaryExpression(node.parent) && node.parent.operator === 38 /* MinusToken */; var literal = (withMinus ? "-" : "") + "0o" + node.text; return grammarErrorOnNode(withMinus ? node.parent : node, diagnosticMessage, literal); } @@ -47367,7 +55149,7 @@ var ts; var sourceFile = ts.getSourceFileOfNode(node); if (!hasParseDiagnostics(sourceFile)) { var span = ts.getSpanOfTokenAtPosition(sourceFile, node.pos); - diagnostics.add(ts.createFileDiagnostic(sourceFile, ts.textSpanEnd(span), 0, message, arg0, arg1, arg2)); + diagnostics.add(ts.createFileDiagnostic(sourceFile, ts.textSpanEnd(span), /*length*/ 0, message, arg0, arg1, arg2)); return true; } return false; @@ -47376,6 +55158,7 @@ var ts; if (!ambientModulesCache) { ambientModulesCache = []; globals.forEach(function (global, sym) { + // No need to `unescapeLeadingUnderscores`, an escaped symbol is never an ambient module. if (ambientModuleSymbolRegex.test(sym)) { ambientModulesCache.push(global); } @@ -47394,6 +55177,8 @@ var ts; if (nodeArguments.length !== 1) { return grammarErrorOnNode(node, ts.Diagnostics.Dynamic_import_must_have_one_specifier_as_an_argument); } + // see: parseArgumentOrArrayLiteralElement...we use this function which parse arguments of callExpression to parse specifier for dynamic import. + // parseArgumentOrArrayLiteralElement allows spread element to be in an argument list which is not allowed as specifier in dynamic import. if (ts.isSpreadElement(nodeArguments[0])) { return grammarErrorOnNode(nodeArguments[0], ts.Diagnostics.Specifier_of_dynamic_import_cannot_be_spread_element); } @@ -47401,10 +55186,11 @@ var ts; } } ts.createTypeChecker = createTypeChecker; + /** Like 'isDeclarationName', but returns true for LHS of `import { x as y }` or `export { x as y }`. */ function isDeclarationNameOrImportPropertyName(name) { switch (name.parent.kind) { - case 248: - case 252: + case 248 /* ImportSpecifier */: + case 252 /* ExportSpecifier */: return ts.isIdentifier(name); default: return ts.isDeclarationName(name); @@ -47412,36 +55198,40 @@ var ts; } function isSomeImportDeclaration(decl) { switch (decl.kind) { - case 245: - case 243: - case 246: - case 248: + case 245 /* ImportClause */: // For default import + case 243 /* ImportEqualsDeclaration */: + case 246 /* NamespaceImport */: + case 248 /* ImportSpecifier */: // For rename import `x as y` return true; - case 71: - return decl.parent.kind === 248; + case 71 /* Identifier */: + // For regular import, `decl` is an Identifier under the ImportSpecifier. + return decl.parent.kind === 248 /* ImportSpecifier */; default: return false; } } var JsxNames; (function (JsxNames) { + // tslint:disable variable-name JsxNames.JSX = "JSX"; JsxNames.IntrinsicElements = "IntrinsicElements"; JsxNames.ElementClass = "ElementClass"; - JsxNames.ElementAttributesPropertyNameContainer = "ElementAttributesProperty"; + JsxNames.ElementAttributesPropertyNameContainer = "ElementAttributesProperty"; // TODO: Deprecate and remove support JsxNames.ElementChildrenAttributeNameContainer = "ElementChildrenAttribute"; JsxNames.Element = "Element"; JsxNames.IntrinsicAttributes = "IntrinsicAttributes"; JsxNames.IntrinsicClassAttributes = "IntrinsicClassAttributes"; + // tslint:enable variable-name })(JsxNames || (JsxNames = {})); })(ts || (ts = {})); var ts; (function (ts) { function createSynthesizedNode(kind) { var node = ts.createNode(kind, -1, -1); - node.flags |= 8; + node.flags |= 8 /* Synthesized */; return node; } + /* @internal */ function updateNode(updated, original) { if (updated !== original) { setOriginalNode(updated, original); @@ -47451,6 +55241,9 @@ var ts; return updated; } ts.updateNode = updateNode; + /** + * Make `elements` into a `NodeArray`. If `elements` is `undefined`, returns an empty `NodeArray`. + */ function createNodeArray(elements, hasTrailingComma) { if (!elements || elements === ts.emptyArray) { elements = []; @@ -47465,7 +55258,14 @@ var ts; return array; } ts.createNodeArray = createNodeArray; + /** + * Creates a shallow, memberwise clone of a node with no source map location. + */ + /* @internal */ function getSynthesizedClone(node) { + // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of + // the original node. We also need to exclude specific properties and only include own- + // properties (to skip members already defined on the shared prototype). if (node === undefined) { return node; } @@ -47498,20 +55298,20 @@ var ts; } ts.createLiteral = createLiteral; function createNumericLiteral(value) { - var node = createSynthesizedNode(8); + var node = createSynthesizedNode(8 /* NumericLiteral */); node.text = value; node.numericLiteralFlags = 0; return node; } ts.createNumericLiteral = createNumericLiteral; function createStringLiteral(text) { - var node = createSynthesizedNode(9); + var node = createSynthesizedNode(9 /* StringLiteral */); node.text = text; return node; } ts.createStringLiteral = createStringLiteral; function createRegularExpressionLiteral(text) { - var node = createSynthesizedNode(12); + var node = createSynthesizedNode(12 /* RegularExpressionLiteral */); node.text = text; return node; } @@ -47522,10 +55322,10 @@ var ts; return node; } function createIdentifier(text, typeArguments) { - var node = createSynthesizedNode(71); + var node = createSynthesizedNode(71 /* Identifier */); node.escapedText = ts.escapeLeadingUnderscores(text); - node.originalKeywordKind = text ? ts.stringToToken(text) : 0; - node.autoGenerateFlags = 0; + node.originalKeywordKind = text ? ts.stringToToken(text) : 0 /* Unknown */; + node.autoGenerateFlags = 0 /* None */; node.autoGenerateId = 0; if (typeArguments) { node.typeArguments = createNodeArray(typeArguments); @@ -47542,29 +55342,31 @@ var ts; var nextAutoGenerateId = 0; function createTempVariable(recordTempVariable, reservedInNestedScopes) { var name = createIdentifier(""); - name.autoGenerateFlags = 1; + name.autoGenerateFlags = 1 /* Auto */; name.autoGenerateId = nextAutoGenerateId; nextAutoGenerateId++; if (recordTempVariable) { recordTempVariable(name); } if (reservedInNestedScopes) { - name.autoGenerateFlags |= 8; + name.autoGenerateFlags |= 8 /* ReservedInNestedScopes */; } return name; } ts.createTempVariable = createTempVariable; + /** Create a unique temporary variable for use in a loop. */ function createLoopVariable() { var name = createIdentifier(""); - name.autoGenerateFlags = 2; + name.autoGenerateFlags = 2 /* Loop */; name.autoGenerateId = nextAutoGenerateId; nextAutoGenerateId++; return name; } ts.createLoopVariable = createLoopVariable; + /** Create a unique name based on the supplied text. */ function createUniqueName(text) { var name = createIdentifier(text); - name.autoGenerateFlags = 3; + name.autoGenerateFlags = 3 /* Unique */; name.autoGenerateId = nextAutoGenerateId; nextAutoGenerateId++; return name; @@ -47572,95 +55374,100 @@ var ts; ts.createUniqueName = createUniqueName; function createOptimisticUniqueName(text) { var name = createIdentifier(text); - name.autoGenerateFlags = 3 | 16; + name.autoGenerateFlags = 3 /* Unique */ | 16 /* Optimistic */; name.autoGenerateId = nextAutoGenerateId; nextAutoGenerateId++; return name; } ts.createOptimisticUniqueName = createOptimisticUniqueName; + /** Create a unique name based on the supplied text. This does not consider names injected by the transformer. */ function createFileLevelUniqueName(text) { var name = createOptimisticUniqueName(text); - name.autoGenerateFlags |= 32; + name.autoGenerateFlags |= 32 /* FileLevel */; return name; } ts.createFileLevelUniqueName = createFileLevelUniqueName; function getGeneratedNameForNode(node, flags) { var name = createIdentifier(ts.isIdentifier(node) ? ts.idText(node) : ""); - name.autoGenerateFlags = 4 | flags; + name.autoGenerateFlags = 4 /* Node */ | flags; name.autoGenerateId = nextAutoGenerateId; name.original = node; nextAutoGenerateId++; return name; } ts.getGeneratedNameForNode = getGeneratedNameForNode; + // Punctuation function createToken(token) { return createSynthesizedNode(token); } ts.createToken = createToken; + // Reserved words function createSuper() { - return createSynthesizedNode(97); + return createSynthesizedNode(97 /* SuperKeyword */); } ts.createSuper = createSuper; function createThis() { - return createSynthesizedNode(99); + return createSynthesizedNode(99 /* ThisKeyword */); } ts.createThis = createThis; function createNull() { - return createSynthesizedNode(95); + return createSynthesizedNode(95 /* NullKeyword */); } ts.createNull = createNull; function createTrue() { - return createSynthesizedNode(101); + return createSynthesizedNode(101 /* TrueKeyword */); } ts.createTrue = createTrue; function createFalse() { - return createSynthesizedNode(86); + return createSynthesizedNode(86 /* FalseKeyword */); } ts.createFalse = createFalse; + // Modifiers function createModifier(kind) { return createToken(kind); } ts.createModifier = createModifier; function createModifiersFromModifierFlags(flags) { var result = []; - if (flags & 1) { - result.push(createModifier(84)); + if (flags & 1 /* Export */) { + result.push(createModifier(84 /* ExportKeyword */)); } - if (flags & 2) { - result.push(createModifier(124)); + if (flags & 2 /* Ambient */) { + result.push(createModifier(124 /* DeclareKeyword */)); } - if (flags & 512) { - result.push(createModifier(79)); + if (flags & 512 /* Default */) { + result.push(createModifier(79 /* DefaultKeyword */)); } - if (flags & 2048) { - result.push(createModifier(76)); + if (flags & 2048 /* Const */) { + result.push(createModifier(76 /* ConstKeyword */)); } - if (flags & 4) { - result.push(createModifier(114)); + if (flags & 4 /* Public */) { + result.push(createModifier(114 /* PublicKeyword */)); } - if (flags & 8) { - result.push(createModifier(112)); + if (flags & 8 /* Private */) { + result.push(createModifier(112 /* PrivateKeyword */)); } - if (flags & 16) { - result.push(createModifier(113)); + if (flags & 16 /* Protected */) { + result.push(createModifier(113 /* ProtectedKeyword */)); } - if (flags & 128) { - result.push(createModifier(117)); + if (flags & 128 /* Abstract */) { + result.push(createModifier(117 /* AbstractKeyword */)); } - if (flags & 32) { - result.push(createModifier(115)); + if (flags & 32 /* Static */) { + result.push(createModifier(115 /* StaticKeyword */)); } - if (flags & 64) { - result.push(createModifier(132)); + if (flags & 64 /* Readonly */) { + result.push(createModifier(132 /* ReadonlyKeyword */)); } - if (flags & 256) { - result.push(createModifier(120)); + if (flags & 256 /* Async */) { + result.push(createModifier(120 /* AsyncKeyword */)); } return result; } ts.createModifiersFromModifierFlags = createModifiersFromModifierFlags; + // Names function createQualifiedName(left, right) { - var node = createSynthesizedNode(146); + var node = createSynthesizedNode(146 /* QualifiedName */); node.left = left; node.right = asName(right); return node; @@ -47674,13 +55481,13 @@ var ts; } ts.updateQualifiedName = updateQualifiedName; function parenthesizeForComputedName(expression) { - return (ts.isBinaryExpression(expression) && expression.operatorToken.kind === 26) || - expression.kind === 303 ? + return (ts.isBinaryExpression(expression) && expression.operatorToken.kind === 26 /* CommaToken */) || + expression.kind === 303 /* CommaListExpression */ ? createParen(expression) : expression; } function createComputedPropertyName(expression) { - var node = createSynthesizedNode(147); + var node = createSynthesizedNode(147 /* ComputedPropertyName */); node.expression = parenthesizeForComputedName(expression); return node; } @@ -47691,8 +55498,9 @@ var ts; : node; } ts.updateComputedPropertyName = updateComputedPropertyName; + // Signature elements function createTypeParameterDeclaration(name, constraint, defaultType) { - var node = createSynthesizedNode(148); + var node = createSynthesizedNode(148 /* TypeParameter */); node.name = asName(name); node.constraint = constraint; node.default = defaultType; @@ -47708,7 +55516,7 @@ var ts; } ts.updateTypeParameterDeclaration = updateTypeParameterDeclaration; function createParameter(decorators, modifiers, dotDotDotToken, name, questionToken, type, initializer) { - var node = createSynthesizedNode(149); + var node = createSynthesizedNode(149 /* Parameter */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.dotDotDotToken = dotDotDotToken; @@ -47732,7 +55540,7 @@ var ts; } ts.updateParameter = updateParameter; function createDecorator(expression) { - var node = createSynthesizedNode(150); + var node = createSynthesizedNode(150 /* Decorator */); node.expression = ts.parenthesizeForAccess(expression); return node; } @@ -47743,8 +55551,9 @@ var ts; : node; } ts.updateDecorator = updateDecorator; + // Type Elements function createPropertySignature(modifiers, name, questionToken, type, initializer) { - var node = createSynthesizedNode(151); + var node = createSynthesizedNode(151 /* PropertySignature */); node.modifiers = asNodeArray(modifiers); node.name = asName(name); node.questionToken = questionToken; @@ -47764,12 +55573,12 @@ var ts; } ts.updatePropertySignature = updatePropertySignature; function createProperty(decorators, modifiers, name, questionOrExclamationToken, type, initializer) { - var node = createSynthesizedNode(152); + var node = createSynthesizedNode(152 /* PropertyDeclaration */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.name = asName(name); - node.questionToken = questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === 55 ? questionOrExclamationToken : undefined; - node.exclamationToken = questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === 51 ? questionOrExclamationToken : undefined; + node.questionToken = questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === 55 /* QuestionToken */ ? questionOrExclamationToken : undefined; + node.exclamationToken = questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === 51 /* ExclamationToken */ ? questionOrExclamationToken : undefined; node.type = type; node.initializer = initializer; return node; @@ -47779,8 +55588,8 @@ var ts; return node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name - || node.questionToken !== (questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === 55 ? questionOrExclamationToken : undefined) - || node.exclamationToken !== (questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === 51 ? questionOrExclamationToken : undefined) + || node.questionToken !== (questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === 55 /* QuestionToken */ ? questionOrExclamationToken : undefined) + || node.exclamationToken !== (questionOrExclamationToken !== undefined && questionOrExclamationToken.kind === 51 /* ExclamationToken */ ? questionOrExclamationToken : undefined) || node.type !== type || node.initializer !== initializer ? updateNode(createProperty(decorators, modifiers, name, questionOrExclamationToken, type, initializer), node) @@ -47788,7 +55597,7 @@ var ts; } ts.updateProperty = updateProperty; function createMethodSignature(typeParameters, parameters, type, name, questionToken) { - var node = createSignatureDeclaration(153, typeParameters, parameters, type); + var node = createSignatureDeclaration(153 /* MethodSignature */, typeParameters, parameters, type); node.name = asName(name); node.questionToken = questionToken; return node; @@ -47805,7 +55614,7 @@ var ts; } ts.updateMethodSignature = updateMethodSignature; function createMethod(decorators, modifiers, asteriskToken, name, questionToken, typeParameters, parameters, type, body) { - var node = createSynthesizedNode(154); + var node = createSynthesizedNode(154 /* MethodDeclaration */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.asteriskToken = asteriskToken; @@ -47833,7 +55642,7 @@ var ts; } ts.updateMethod = updateMethod; function createConstructor(decorators, modifiers, parameters, body) { - var node = createSynthesizedNode(155); + var node = createSynthesizedNode(155 /* Constructor */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.typeParameters = undefined; @@ -47853,7 +55662,7 @@ var ts; } ts.updateConstructor = updateConstructor; function createGetAccessor(decorators, modifiers, name, parameters, type, body) { - var node = createSynthesizedNode(156); + var node = createSynthesizedNode(156 /* GetAccessor */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.name = asName(name); @@ -47876,7 +55685,7 @@ var ts; } ts.updateGetAccessor = updateGetAccessor; function createSetAccessor(decorators, modifiers, name, parameters, body) { - var node = createSynthesizedNode(157); + var node = createSynthesizedNode(157 /* SetAccessor */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.name = asName(name); @@ -47897,7 +55706,7 @@ var ts; } ts.updateSetAccessor = updateSetAccessor; function createCallSignature(typeParameters, parameters, type) { - return createSignatureDeclaration(158, typeParameters, parameters, type); + return createSignatureDeclaration(158 /* CallSignature */, typeParameters, parameters, type); } ts.createCallSignature = createCallSignature; function updateCallSignature(node, typeParameters, parameters, type) { @@ -47905,7 +55714,7 @@ var ts; } ts.updateCallSignature = updateCallSignature; function createConstructSignature(typeParameters, parameters, type) { - return createSignatureDeclaration(159, typeParameters, parameters, type); + return createSignatureDeclaration(159 /* ConstructSignature */, typeParameters, parameters, type); } ts.createConstructSignature = createConstructSignature; function updateConstructSignature(node, typeParameters, parameters, type) { @@ -47913,7 +55722,7 @@ var ts; } ts.updateConstructSignature = updateConstructSignature; function createIndexSignature(decorators, modifiers, parameters, type) { - var node = createSynthesizedNode(160); + var node = createSynthesizedNode(160 /* IndexSignature */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.parameters = createNodeArray(parameters); @@ -47930,6 +55739,7 @@ var ts; : node; } ts.updateIndexSignature = updateIndexSignature; + /* @internal */ function createSignatureDeclaration(kind, typeParameters, parameters, type, typeArguments) { var node = createSynthesizedNode(kind); node.typeParameters = asNodeArray(typeParameters); @@ -47946,12 +55756,13 @@ var ts; ? updateNode(createSignatureDeclaration(node.kind, typeParameters, parameters, type), node) : node; } + // Types function createKeywordTypeNode(kind) { return createSynthesizedNode(kind); } ts.createKeywordTypeNode = createKeywordTypeNode; function createTypePredicateNode(parameterName, type) { - var node = createSynthesizedNode(161); + var node = createSynthesizedNode(161 /* TypePredicate */); node.parameterName = asName(parameterName); node.type = type; return node; @@ -47965,7 +55776,7 @@ var ts; } ts.updateTypePredicateNode = updateTypePredicateNode; function createTypeReferenceNode(typeName, typeArguments) { - var node = createSynthesizedNode(162); + var node = createSynthesizedNode(162 /* TypeReference */); node.typeName = asName(typeName); node.typeArguments = typeArguments && ts.parenthesizeTypeParameters(typeArguments); return node; @@ -47979,7 +55790,7 @@ var ts; } ts.updateTypeReferenceNode = updateTypeReferenceNode; function createFunctionTypeNode(typeParameters, parameters, type) { - return createSignatureDeclaration(163, typeParameters, parameters, type); + return createSignatureDeclaration(163 /* FunctionType */, typeParameters, parameters, type); } ts.createFunctionTypeNode = createFunctionTypeNode; function updateFunctionTypeNode(node, typeParameters, parameters, type) { @@ -47987,7 +55798,7 @@ var ts; } ts.updateFunctionTypeNode = updateFunctionTypeNode; function createConstructorTypeNode(typeParameters, parameters, type) { - return createSignatureDeclaration(164, typeParameters, parameters, type); + return createSignatureDeclaration(164 /* ConstructorType */, typeParameters, parameters, type); } ts.createConstructorTypeNode = createConstructorTypeNode; function updateConstructorTypeNode(node, typeParameters, parameters, type) { @@ -47995,7 +55806,7 @@ var ts; } ts.updateConstructorTypeNode = updateConstructorTypeNode; function createTypeQueryNode(exprName) { - var node = createSynthesizedNode(165); + var node = createSynthesizedNode(165 /* TypeQuery */); node.exprName = exprName; return node; } @@ -48007,7 +55818,7 @@ var ts; } ts.updateTypeQueryNode = updateTypeQueryNode; function createTypeLiteralNode(members) { - var node = createSynthesizedNode(166); + var node = createSynthesizedNode(166 /* TypeLiteral */); node.members = createNodeArray(members); return node; } @@ -48019,7 +55830,7 @@ var ts; } ts.updateTypeLiteralNode = updateTypeLiteralNode; function createArrayTypeNode(elementType) { - var node = createSynthesizedNode(167); + var node = createSynthesizedNode(167 /* ArrayType */); node.elementType = ts.parenthesizeArrayTypeMember(elementType); return node; } @@ -48031,7 +55842,7 @@ var ts; } ts.updateArrayTypeNode = updateArrayTypeNode; function createTupleTypeNode(elementTypes) { - var node = createSynthesizedNode(168); + var node = createSynthesizedNode(168 /* TupleType */); node.elementTypes = createNodeArray(elementTypes); return node; } @@ -48043,7 +55854,7 @@ var ts; } ts.updateTypleTypeNode = updateTypleTypeNode; function createUnionTypeNode(types) { - return createUnionOrIntersectionTypeNode(169, types); + return createUnionOrIntersectionTypeNode(169 /* UnionType */, types); } ts.createUnionTypeNode = createUnionTypeNode; function updateUnionTypeNode(node, types) { @@ -48051,7 +55862,7 @@ var ts; } ts.updateUnionTypeNode = updateUnionTypeNode; function createIntersectionTypeNode(types) { - return createUnionOrIntersectionTypeNode(170, types); + return createUnionOrIntersectionTypeNode(170 /* IntersectionType */, types); } ts.createIntersectionTypeNode = createIntersectionTypeNode; function updateIntersectionTypeNode(node, types) { @@ -48070,7 +55881,7 @@ var ts; : node; } function createConditionalTypeNode(checkType, extendsType, trueType, falseType) { - var node = createSynthesizedNode(171); + var node = createSynthesizedNode(171 /* ConditionalType */); node.checkType = ts.parenthesizeConditionalTypeMember(checkType); node.extendsType = ts.parenthesizeConditionalTypeMember(extendsType); node.trueType = trueType; @@ -48088,7 +55899,7 @@ var ts; } ts.updateConditionalTypeNode = updateConditionalTypeNode; function createInferTypeNode(typeParameter) { - var node = createSynthesizedNode(172); + var node = createSynthesizedNode(172 /* InferType */); node.typeParameter = typeParameter; return node; } @@ -48100,7 +55911,7 @@ var ts; } ts.updateInferTypeNode = updateInferTypeNode; function createImportTypeNode(argument, qualifier, typeArguments, isTypeOf) { - var node = createSynthesizedNode(179); + var node = createSynthesizedNode(179 /* ImportType */); node.argument = argument; node.qualifier = qualifier; node.typeArguments = asNodeArray(typeArguments); @@ -48118,7 +55929,7 @@ var ts; } ts.updateImportTypeNode = updateImportTypeNode; function createParenthesizedType(type) { - var node = createSynthesizedNode(173); + var node = createSynthesizedNode(173 /* ParenthesizedType */); node.type = type; return node; } @@ -48130,12 +55941,12 @@ var ts; } ts.updateParenthesizedType = updateParenthesizedType; function createThisTypeNode() { - return createSynthesizedNode(174); + return createSynthesizedNode(174 /* ThisType */); } ts.createThisTypeNode = createThisTypeNode; function createTypeOperatorNode(operatorOrType, type) { - var node = createSynthesizedNode(175); - node.operator = typeof operatorOrType === "number" ? operatorOrType : 128; + var node = createSynthesizedNode(175 /* TypeOperator */); + node.operator = typeof operatorOrType === "number" ? operatorOrType : 128 /* KeyOfKeyword */; node.type = ts.parenthesizeElementTypeMember(typeof operatorOrType === "number" ? type : operatorOrType); return node; } @@ -48145,7 +55956,7 @@ var ts; } ts.updateTypeOperatorNode = updateTypeOperatorNode; function createIndexedAccessTypeNode(objectType, indexType) { - var node = createSynthesizedNode(176); + var node = createSynthesizedNode(176 /* IndexedAccessType */); node.objectType = ts.parenthesizeElementTypeMember(objectType); node.indexType = indexType; return node; @@ -48159,7 +55970,7 @@ var ts; } ts.updateIndexedAccessTypeNode = updateIndexedAccessTypeNode; function createMappedTypeNode(readonlyToken, typeParameter, questionToken, type) { - var node = createSynthesizedNode(177); + var node = createSynthesizedNode(177 /* MappedType */); node.readonlyToken = readonlyToken; node.typeParameter = typeParameter; node.questionToken = questionToken; @@ -48177,7 +55988,7 @@ var ts; } ts.updateMappedTypeNode = updateMappedTypeNode; function createLiteralTypeNode(literal) { - var node = createSynthesizedNode(178); + var node = createSynthesizedNode(178 /* LiteralType */); node.literal = literal; return node; } @@ -48188,8 +55999,9 @@ var ts; : node; } ts.updateLiteralTypeNode = updateLiteralTypeNode; + // Binding Patterns function createObjectBindingPattern(elements) { - var node = createSynthesizedNode(180); + var node = createSynthesizedNode(180 /* ObjectBindingPattern */); node.elements = createNodeArray(elements); return node; } @@ -48201,7 +56013,7 @@ var ts; } ts.updateObjectBindingPattern = updateObjectBindingPattern; function createArrayBindingPattern(elements) { - var node = createSynthesizedNode(181); + var node = createSynthesizedNode(181 /* ArrayBindingPattern */); node.elements = createNodeArray(elements); return node; } @@ -48213,7 +56025,7 @@ var ts; } ts.updateArrayBindingPattern = updateArrayBindingPattern; function createBindingElement(dotDotDotToken, propertyName, name, initializer) { - var node = createSynthesizedNode(182); + var node = createSynthesizedNode(182 /* BindingElement */); node.dotDotDotToken = dotDotDotToken; node.propertyName = asName(propertyName); node.name = asName(name); @@ -48230,8 +56042,9 @@ var ts; : node; } ts.updateBindingElement = updateBindingElement; + // Expression function createArrayLiteral(elements, multiLine) { - var node = createSynthesizedNode(183); + var node = createSynthesizedNode(183 /* ArrayLiteralExpression */); node.elements = ts.parenthesizeListElements(createNodeArray(elements)); if (multiLine) node.multiLine = true; @@ -48245,7 +56058,7 @@ var ts; } ts.updateArrayLiteral = updateArrayLiteral; function createObjectLiteral(properties, multiLine) { - var node = createSynthesizedNode(184); + var node = createSynthesizedNode(184 /* ObjectLiteralExpression */); node.properties = createNodeArray(properties); if (multiLine) node.multiLine = true; @@ -48259,14 +56072,16 @@ var ts; } ts.updateObjectLiteral = updateObjectLiteral; function createPropertyAccess(expression, name) { - var node = createSynthesizedNode(185); + var node = createSynthesizedNode(185 /* PropertyAccessExpression */); node.expression = ts.parenthesizeForAccess(expression); - node.name = asName(name); - setEmitFlags(node, 131072); + node.name = asName(name); // TODO: GH#18217 + setEmitFlags(node, 131072 /* NoIndentation */); return node; } ts.createPropertyAccess = createPropertyAccess; function updatePropertyAccess(node, expression, name) { + // Because we are updating existed propertyAccess we want to inherit its emitFlags + // instead of using the default from createPropertyAccess return node.expression !== expression || node.name !== name ? updateNode(setEmitFlags(createPropertyAccess(expression, name), ts.getEmitFlags(node)), node) @@ -48274,7 +56089,7 @@ var ts; } ts.updatePropertyAccess = updatePropertyAccess; function createElementAccess(expression, index) { - var node = createSynthesizedNode(186); + var node = createSynthesizedNode(186 /* ElementAccessExpression */); node.expression = ts.parenthesizeForAccess(expression); node.argumentExpression = asExpression(index); return node; @@ -48288,7 +56103,7 @@ var ts; } ts.updateElementAccess = updateElementAccess; function createCall(expression, typeArguments, argumentsArray) { - var node = createSynthesizedNode(187); + var node = createSynthesizedNode(187 /* CallExpression */); node.expression = ts.parenthesizeForAccess(expression); node.typeArguments = asNodeArray(typeArguments); node.arguments = ts.parenthesizeListElements(createNodeArray(argumentsArray)); @@ -48304,7 +56119,7 @@ var ts; } ts.updateCall = updateCall; function createNew(expression, typeArguments, argumentsArray) { - var node = createSynthesizedNode(188); + var node = createSynthesizedNode(188 /* NewExpression */); node.expression = ts.parenthesizeForNew(expression); node.typeArguments = asNodeArray(typeArguments); node.arguments = argumentsArray ? ts.parenthesizeListElements(createNodeArray(argumentsArray)) : undefined; @@ -48320,7 +56135,7 @@ var ts; } ts.updateNew = updateNew; function createTaggedTemplate(tag, typeArgumentsOrTemplate, template) { - var node = createSynthesizedNode(189); + var node = createSynthesizedNode(189 /* TaggedTemplateExpression */); node.tag = ts.parenthesizeForAccess(tag); if (template) { node.typeArguments = asNodeArray(typeArgumentsOrTemplate); @@ -48343,7 +56158,7 @@ var ts; } ts.updateTaggedTemplate = updateTaggedTemplate; function createTypeAssertion(type, expression) { - var node = createSynthesizedNode(190); + var node = createSynthesizedNode(190 /* TypeAssertionExpression */); node.type = type; node.expression = ts.parenthesizePrefixOperand(expression); return node; @@ -48357,7 +56172,7 @@ var ts; } ts.updateTypeAssertion = updateTypeAssertion; function createParen(expression) { - var node = createSynthesizedNode(191); + var node = createSynthesizedNode(191 /* ParenthesizedExpression */); node.expression = expression; return node; } @@ -48369,7 +56184,7 @@ var ts; } ts.updateParen = updateParen; function createFunctionExpression(modifiers, asteriskToken, name, typeParameters, parameters, type, body) { - var node = createSynthesizedNode(192); + var node = createSynthesizedNode(192 /* FunctionExpression */); node.modifiers = asNodeArray(modifiers); node.asteriskToken = asteriskToken; node.name = asName(name); @@ -48393,12 +56208,12 @@ var ts; } ts.updateFunctionExpression = updateFunctionExpression; function createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body) { - var node = createSynthesizedNode(193); + var node = createSynthesizedNode(193 /* ArrowFunction */); node.modifiers = asNodeArray(modifiers); node.typeParameters = asNodeArray(typeParameters); node.parameters = createNodeArray(parameters); node.type = type; - node.equalsGreaterThanToken = equalsGreaterThanToken || createToken(36); + node.equalsGreaterThanToken = equalsGreaterThanToken || createToken(36 /* EqualsGreaterThanToken */); node.body = ts.parenthesizeConciseBody(body); return node; } @@ -48412,7 +56227,7 @@ var ts; } else { equalsGreaterThanToken = ts.cast(equalsGreaterThanTokenOrBody, function (n) { - return n.kind === 36; + return n.kind === 36 /* EqualsGreaterThanToken */; }); body = bodyOrUndefined; } @@ -48427,7 +56242,7 @@ var ts; } ts.updateArrowFunction = updateArrowFunction; function createDelete(expression) { - var node = createSynthesizedNode(194); + var node = createSynthesizedNode(194 /* DeleteExpression */); node.expression = ts.parenthesizePrefixOperand(expression); return node; } @@ -48439,7 +56254,7 @@ var ts; } ts.updateDelete = updateDelete; function createTypeOf(expression) { - var node = createSynthesizedNode(195); + var node = createSynthesizedNode(195 /* TypeOfExpression */); node.expression = ts.parenthesizePrefixOperand(expression); return node; } @@ -48451,7 +56266,7 @@ var ts; } ts.updateTypeOf = updateTypeOf; function createVoid(expression) { - var node = createSynthesizedNode(196); + var node = createSynthesizedNode(196 /* VoidExpression */); node.expression = ts.parenthesizePrefixOperand(expression); return node; } @@ -48463,7 +56278,7 @@ var ts; } ts.updateVoid = updateVoid; function createAwait(expression) { - var node = createSynthesizedNode(197); + var node = createSynthesizedNode(197 /* AwaitExpression */); node.expression = ts.parenthesizePrefixOperand(expression); return node; } @@ -48475,7 +56290,7 @@ var ts; } ts.updateAwait = updateAwait; function createPrefix(operator, operand) { - var node = createSynthesizedNode(198); + var node = createSynthesizedNode(198 /* PrefixUnaryExpression */); node.operator = operator; node.operand = ts.parenthesizePrefixOperand(operand); return node; @@ -48488,7 +56303,7 @@ var ts; } ts.updatePrefix = updatePrefix; function createPostfix(operand, operator) { - var node = createSynthesizedNode(199); + var node = createSynthesizedNode(199 /* PostfixUnaryExpression */); node.operand = ts.parenthesizePostfixOperand(operand); node.operator = operator; return node; @@ -48501,12 +56316,12 @@ var ts; } ts.updatePostfix = updatePostfix; function createBinary(left, operator, right) { - var node = createSynthesizedNode(200); + var node = createSynthesizedNode(200 /* BinaryExpression */); var operatorToken = asToken(operator); var operatorKind = operatorToken.kind; - node.left = ts.parenthesizeBinaryOperand(operatorKind, left, true, undefined); + node.left = ts.parenthesizeBinaryOperand(operatorKind, left, /*isLeftSideOfBinary*/ true, /*leftOperand*/ undefined); node.operatorToken = operatorToken; - node.right = ts.parenthesizeBinaryOperand(operatorKind, right, false, node.left); + node.right = ts.parenthesizeBinaryOperand(operatorKind, right, /*isLeftSideOfBinary*/ false, node.left); return node; } ts.createBinary = createBinary; @@ -48518,11 +56333,11 @@ var ts; } ts.updateBinary = updateBinary; function createConditional(condition, questionTokenOrWhenTrue, whenTrueOrWhenFalse, colonToken, whenFalse) { - var node = createSynthesizedNode(201); + var node = createSynthesizedNode(201 /* ConditionalExpression */); node.condition = ts.parenthesizeForConditionalHead(condition); - node.questionToken = whenFalse ? questionTokenOrWhenTrue : createToken(55); + node.questionToken = whenFalse ? questionTokenOrWhenTrue : createToken(55 /* QuestionToken */); node.whenTrue = ts.parenthesizeSubexpressionOfConditionalExpression(whenFalse ? whenTrueOrWhenFalse : questionTokenOrWhenTrue); - node.colonToken = whenFalse ? colonToken : createToken(56); + node.colonToken = whenFalse ? colonToken : createToken(56 /* ColonToken */); node.whenFalse = ts.parenthesizeSubexpressionOfConditionalExpression(whenFalse ? whenFalse : whenTrueOrWhenFalse); return node; } @@ -48548,7 +56363,7 @@ var ts; } ts.updateConditional = updateConditional; function createTemplateExpression(head, templateSpans) { - var node = createSynthesizedNode(202); + var node = createSynthesizedNode(202 /* TemplateExpression */); node.head = head; node.templateSpans = createNodeArray(templateSpans); return node; @@ -48562,33 +56377,33 @@ var ts; } ts.updateTemplateExpression = updateTemplateExpression; function createTemplateHead(text) { - var node = createSynthesizedNode(14); + var node = createSynthesizedNode(14 /* TemplateHead */); node.text = text; return node; } ts.createTemplateHead = createTemplateHead; function createTemplateMiddle(text) { - var node = createSynthesizedNode(15); + var node = createSynthesizedNode(15 /* TemplateMiddle */); node.text = text; return node; } ts.createTemplateMiddle = createTemplateMiddle; function createTemplateTail(text) { - var node = createSynthesizedNode(16); + var node = createSynthesizedNode(16 /* TemplateTail */); node.text = text; return node; } ts.createTemplateTail = createTemplateTail; function createNoSubstitutionTemplateLiteral(text) { - var node = createSynthesizedNode(13); + var node = createSynthesizedNode(13 /* NoSubstitutionTemplateLiteral */); node.text = text; return node; } ts.createNoSubstitutionTemplateLiteral = createNoSubstitutionTemplateLiteral; function createYield(asteriskTokenOrExpression, expression) { - var node = createSynthesizedNode(203); - node.asteriskToken = asteriskTokenOrExpression && asteriskTokenOrExpression.kind === 39 ? asteriskTokenOrExpression : undefined; - node.expression = asteriskTokenOrExpression && asteriskTokenOrExpression.kind !== 39 ? asteriskTokenOrExpression : expression; + var node = createSynthesizedNode(203 /* YieldExpression */); + node.asteriskToken = asteriskTokenOrExpression && asteriskTokenOrExpression.kind === 39 /* AsteriskToken */ ? asteriskTokenOrExpression : undefined; + node.expression = asteriskTokenOrExpression && asteriskTokenOrExpression.kind !== 39 /* AsteriskToken */ ? asteriskTokenOrExpression : expression; return node; } ts.createYield = createYield; @@ -48600,7 +56415,7 @@ var ts; } ts.updateYield = updateYield; function createSpread(expression) { - var node = createSynthesizedNode(204); + var node = createSynthesizedNode(204 /* SpreadElement */); node.expression = ts.parenthesizeExpressionForList(expression); return node; } @@ -48612,7 +56427,7 @@ var ts; } ts.updateSpread = updateSpread; function createClassExpression(modifiers, name, typeParameters, heritageClauses, members) { - var node = createSynthesizedNode(205); + var node = createSynthesizedNode(205 /* ClassExpression */); node.decorators = undefined; node.modifiers = asNodeArray(modifiers); node.name = asName(name); @@ -48633,11 +56448,11 @@ var ts; } ts.updateClassExpression = updateClassExpression; function createOmittedExpression() { - return createSynthesizedNode(206); + return createSynthesizedNode(206 /* OmittedExpression */); } ts.createOmittedExpression = createOmittedExpression; function createExpressionWithTypeArguments(typeArguments, expression) { - var node = createSynthesizedNode(207); + var node = createSynthesizedNode(207 /* ExpressionWithTypeArguments */); node.expression = ts.parenthesizeForAccess(expression); node.typeArguments = asNodeArray(typeArguments); return node; @@ -48651,7 +56466,7 @@ var ts; } ts.updateExpressionWithTypeArguments = updateExpressionWithTypeArguments; function createAsExpression(expression, type) { - var node = createSynthesizedNode(208); + var node = createSynthesizedNode(208 /* AsExpression */); node.expression = expression; node.type = type; return node; @@ -48665,7 +56480,7 @@ var ts; } ts.updateAsExpression = updateAsExpression; function createNonNullExpression(expression) { - var node = createSynthesizedNode(209); + var node = createSynthesizedNode(209 /* NonNullExpression */); node.expression = ts.parenthesizeForAccess(expression); return node; } @@ -48677,7 +56492,7 @@ var ts; } ts.updateNonNullExpression = updateNonNullExpression; function createMetaProperty(keywordToken, name) { - var node = createSynthesizedNode(210); + var node = createSynthesizedNode(210 /* MetaProperty */); node.keywordToken = keywordToken; node.name = name; return node; @@ -48689,8 +56504,9 @@ var ts; : node; } ts.updateMetaProperty = updateMetaProperty; + // Misc function createTemplateSpan(expression, literal) { - var node = createSynthesizedNode(211); + var node = createSynthesizedNode(211 /* TemplateSpan */); node.expression = expression; node.literal = literal; return node; @@ -48704,19 +56520,21 @@ var ts; } ts.updateTemplateSpan = updateTemplateSpan; function createSemicolonClassElement() { - return createSynthesizedNode(212); + return createSynthesizedNode(212 /* SemicolonClassElement */); } ts.createSemicolonClassElement = createSemicolonClassElement; + // Element function createBlock(statements, multiLine) { - var block = createSynthesizedNode(213); + var block = createSynthesizedNode(213 /* Block */); block.statements = createNodeArray(statements); if (multiLine) block.multiLine = multiLine; return block; } ts.createBlock = createBlock; + /* @internal */ function createExpressionStatement(expression) { - var node = createSynthesizedNode(216); + var node = createSynthesizedNode(216 /* ExpressionStatement */); node.expression = expression; return node; } @@ -48728,7 +56546,7 @@ var ts; } ts.updateBlock = updateBlock; function createVariableStatement(modifiers, declarationList) { - var node = createSynthesizedNode(214); + var node = createSynthesizedNode(214 /* VariableStatement */); node.decorators = undefined; node.modifiers = asNodeArray(modifiers); node.declarationList = ts.isArray(declarationList) ? createVariableDeclarationList(declarationList) : declarationList; @@ -48743,7 +56561,7 @@ var ts; } ts.updateVariableStatement = updateVariableStatement; function createEmptyStatement() { - return createSynthesizedNode(215); + return createSynthesizedNode(215 /* EmptyStatement */); } ts.createEmptyStatement = createEmptyStatement; function createStatement(expression) { @@ -48757,7 +56575,7 @@ var ts; } ts.updateStatement = updateStatement; function createIf(expression, thenStatement, elseStatement) { - var node = createSynthesizedNode(217); + var node = createSynthesizedNode(217 /* IfStatement */); node.expression = expression; node.thenStatement = thenStatement; node.elseStatement = elseStatement; @@ -48773,7 +56591,7 @@ var ts; } ts.updateIf = updateIf; function createDo(statement, expression) { - var node = createSynthesizedNode(218); + var node = createSynthesizedNode(218 /* DoStatement */); node.statement = statement; node.expression = expression; return node; @@ -48787,7 +56605,7 @@ var ts; } ts.updateDo = updateDo; function createWhile(expression, statement) { - var node = createSynthesizedNode(219); + var node = createSynthesizedNode(219 /* WhileStatement */); node.expression = expression; node.statement = statement; return node; @@ -48801,7 +56619,7 @@ var ts; } ts.updateWhile = updateWhile; function createFor(initializer, condition, incrementor, statement) { - var node = createSynthesizedNode(220); + var node = createSynthesizedNode(220 /* ForStatement */); node.initializer = initializer; node.condition = condition; node.incrementor = incrementor; @@ -48819,7 +56637,7 @@ var ts; } ts.updateFor = updateFor; function createForIn(initializer, expression, statement) { - var node = createSynthesizedNode(221); + var node = createSynthesizedNode(221 /* ForInStatement */); node.initializer = initializer; node.expression = expression; node.statement = statement; @@ -48835,7 +56653,7 @@ var ts; } ts.updateForIn = updateForIn; function createForOf(awaitModifier, initializer, expression, statement) { - var node = createSynthesizedNode(222); + var node = createSynthesizedNode(222 /* ForOfStatement */); node.awaitModifier = awaitModifier; node.initializer = initializer; node.expression = expression; @@ -48853,7 +56671,7 @@ var ts; } ts.updateForOf = updateForOf; function createContinue(label) { - var node = createSynthesizedNode(223); + var node = createSynthesizedNode(223 /* ContinueStatement */); node.label = asName(label); return node; } @@ -48865,7 +56683,7 @@ var ts; } ts.updateContinue = updateContinue; function createBreak(label) { - var node = createSynthesizedNode(224); + var node = createSynthesizedNode(224 /* BreakStatement */); node.label = asName(label); return node; } @@ -48877,7 +56695,7 @@ var ts; } ts.updateBreak = updateBreak; function createReturn(expression) { - var node = createSynthesizedNode(225); + var node = createSynthesizedNode(225 /* ReturnStatement */); node.expression = expression; return node; } @@ -48889,7 +56707,7 @@ var ts; } ts.updateReturn = updateReturn; function createWith(expression, statement) { - var node = createSynthesizedNode(226); + var node = createSynthesizedNode(226 /* WithStatement */); node.expression = expression; node.statement = statement; return node; @@ -48903,7 +56721,7 @@ var ts; } ts.updateWith = updateWith; function createSwitch(expression, caseBlock) { - var node = createSynthesizedNode(227); + var node = createSynthesizedNode(227 /* SwitchStatement */); node.expression = ts.parenthesizeExpressionForList(expression); node.caseBlock = caseBlock; return node; @@ -48917,7 +56735,7 @@ var ts; } ts.updateSwitch = updateSwitch; function createLabel(label, statement) { - var node = createSynthesizedNode(228); + var node = createSynthesizedNode(228 /* LabeledStatement */); node.label = asName(label); node.statement = statement; return node; @@ -48931,7 +56749,7 @@ var ts; } ts.updateLabel = updateLabel; function createThrow(expression) { - var node = createSynthesizedNode(229); + var node = createSynthesizedNode(229 /* ThrowStatement */); node.expression = expression; return node; } @@ -48943,7 +56761,7 @@ var ts; } ts.updateThrow = updateThrow; function createTry(tryBlock, catchClause, finallyBlock) { - var node = createSynthesizedNode(230); + var node = createSynthesizedNode(230 /* TryStatement */); node.tryBlock = tryBlock; node.catchClause = catchClause; node.finallyBlock = finallyBlock; @@ -48959,11 +56777,11 @@ var ts; } ts.updateTry = updateTry; function createDebuggerStatement() { - return createSynthesizedNode(231); + return createSynthesizedNode(231 /* DebuggerStatement */); } ts.createDebuggerStatement = createDebuggerStatement; function createVariableDeclaration(name, type, initializer) { - var node = createSynthesizedNode(232); + var node = createSynthesizedNode(232 /* VariableDeclaration */); node.name = asName(name); node.type = type; node.initializer = initializer !== undefined ? ts.parenthesizeExpressionForList(initializer) : undefined; @@ -48979,9 +56797,9 @@ var ts; } ts.updateVariableDeclaration = updateVariableDeclaration; function createVariableDeclarationList(declarations, flags) { - if (flags === void 0) { flags = 0; } - var node = createSynthesizedNode(233); - node.flags |= flags & 3; + if (flags === void 0) { flags = 0 /* None */; } + var node = createSynthesizedNode(233 /* VariableDeclarationList */); + node.flags |= flags & 3 /* BlockScoped */; node.declarations = createNodeArray(declarations); return node; } @@ -48993,7 +56811,7 @@ var ts; } ts.updateVariableDeclarationList = updateVariableDeclarationList; function createFunctionDeclaration(decorators, modifiers, asteriskToken, name, typeParameters, parameters, type, body) { - var node = createSynthesizedNode(234); + var node = createSynthesizedNode(234 /* FunctionDeclaration */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.asteriskToken = asteriskToken; @@ -49019,7 +56837,7 @@ var ts; } ts.updateFunctionDeclaration = updateFunctionDeclaration; function createClassDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members) { - var node = createSynthesizedNode(235); + var node = createSynthesizedNode(235 /* ClassDeclaration */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.name = asName(name); @@ -49041,7 +56859,7 @@ var ts; } ts.updateClassDeclaration = updateClassDeclaration; function createInterfaceDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members) { - var node = createSynthesizedNode(236); + var node = createSynthesizedNode(236 /* InterfaceDeclaration */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.name = asName(name); @@ -49063,7 +56881,7 @@ var ts; } ts.updateInterfaceDeclaration = updateInterfaceDeclaration; function createTypeAliasDeclaration(decorators, modifiers, name, typeParameters, type) { - var node = createSynthesizedNode(237); + var node = createSynthesizedNode(237 /* TypeAliasDeclaration */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.name = asName(name); @@ -49083,7 +56901,7 @@ var ts; } ts.updateTypeAliasDeclaration = updateTypeAliasDeclaration; function createEnumDeclaration(decorators, modifiers, name, members) { - var node = createSynthesizedNode(238); + var node = createSynthesizedNode(238 /* EnumDeclaration */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.name = asName(name); @@ -49101,9 +56919,9 @@ var ts; } ts.updateEnumDeclaration = updateEnumDeclaration; function createModuleDeclaration(decorators, modifiers, name, body, flags) { - if (flags === void 0) { flags = 0; } - var node = createSynthesizedNode(239); - node.flags |= flags & (16 | 4 | 512); + if (flags === void 0) { flags = 0 /* None */; } + var node = createSynthesizedNode(239 /* ModuleDeclaration */); + node.flags |= flags & (16 /* Namespace */ | 4 /* NestedNamespace */ | 512 /* GlobalAugmentation */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.name = name; @@ -49121,7 +56939,7 @@ var ts; } ts.updateModuleDeclaration = updateModuleDeclaration; function createModuleBlock(statements) { - var node = createSynthesizedNode(240); + var node = createSynthesizedNode(240 /* ModuleBlock */); node.statements = createNodeArray(statements); return node; } @@ -49133,7 +56951,7 @@ var ts; } ts.updateModuleBlock = updateModuleBlock; function createCaseBlock(clauses) { - var node = createSynthesizedNode(241); + var node = createSynthesizedNode(241 /* CaseBlock */); node.clauses = createNodeArray(clauses); return node; } @@ -49145,7 +56963,7 @@ var ts; } ts.updateCaseBlock = updateCaseBlock; function createNamespaceExportDeclaration(name) { - var node = createSynthesizedNode(242); + var node = createSynthesizedNode(242 /* NamespaceExportDeclaration */); node.name = asName(name); return node; } @@ -49157,7 +56975,7 @@ var ts; } ts.updateNamespaceExportDeclaration = updateNamespaceExportDeclaration; function createImportEqualsDeclaration(decorators, modifiers, name, moduleReference) { - var node = createSynthesizedNode(243); + var node = createSynthesizedNode(243 /* ImportEqualsDeclaration */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.name = asName(name); @@ -49175,7 +56993,7 @@ var ts; } ts.updateImportEqualsDeclaration = updateImportEqualsDeclaration; function createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier) { - var node = createSynthesizedNode(244); + var node = createSynthesizedNode(244 /* ImportDeclaration */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.importClause = importClause; @@ -49193,7 +57011,7 @@ var ts; } ts.updateImportDeclaration = updateImportDeclaration; function createImportClause(name, namedBindings) { - var node = createSynthesizedNode(245); + var node = createSynthesizedNode(245 /* ImportClause */); node.name = name; node.namedBindings = namedBindings; return node; @@ -49207,7 +57025,7 @@ var ts; } ts.updateImportClause = updateImportClause; function createNamespaceImport(name) { - var node = createSynthesizedNode(246); + var node = createSynthesizedNode(246 /* NamespaceImport */); node.name = name; return node; } @@ -49219,7 +57037,7 @@ var ts; } ts.updateNamespaceImport = updateNamespaceImport; function createNamedImports(elements) { - var node = createSynthesizedNode(247); + var node = createSynthesizedNode(247 /* NamedImports */); node.elements = createNodeArray(elements); return node; } @@ -49231,7 +57049,7 @@ var ts; } ts.updateNamedImports = updateNamedImports; function createImportSpecifier(propertyName, name) { - var node = createSynthesizedNode(248); + var node = createSynthesizedNode(248 /* ImportSpecifier */); node.propertyName = propertyName; node.name = name; return node; @@ -49245,11 +57063,11 @@ var ts; } ts.updateImportSpecifier = updateImportSpecifier; function createExportAssignment(decorators, modifiers, isExportEquals, expression) { - var node = createSynthesizedNode(249); + var node = createSynthesizedNode(249 /* ExportAssignment */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.isExportEquals = isExportEquals; - node.expression = isExportEquals ? ts.parenthesizeBinaryOperand(58, expression, false, undefined) : ts.parenthesizeDefaultExpression(expression); + node.expression = isExportEquals ? ts.parenthesizeBinaryOperand(58 /* EqualsToken */, expression, /*isLeftSideOfBinary*/ false, /*leftOperand*/ undefined) : ts.parenthesizeDefaultExpression(expression); return node; } ts.createExportAssignment = createExportAssignment; @@ -49262,7 +57080,7 @@ var ts; } ts.updateExportAssignment = updateExportAssignment; function createExportDeclaration(decorators, modifiers, exportClause, moduleSpecifier) { - var node = createSynthesizedNode(250); + var node = createSynthesizedNode(250 /* ExportDeclaration */); node.decorators = asNodeArray(decorators); node.modifiers = asNodeArray(modifiers); node.exportClause = exportClause; @@ -49280,7 +57098,7 @@ var ts; } ts.updateExportDeclaration = updateExportDeclaration; function createNamedExports(elements) { - var node = createSynthesizedNode(251); + var node = createSynthesizedNode(251 /* NamedExports */); node.elements = createNodeArray(elements); return node; } @@ -49292,7 +57110,7 @@ var ts; } ts.updateNamedExports = updateNamedExports; function createExportSpecifier(propertyName, name) { - var node = createSynthesizedNode(252); + var node = createSynthesizedNode(252 /* ExportSpecifier */); node.propertyName = asName(propertyName); node.name = asName(name); return node; @@ -49305,8 +57123,9 @@ var ts; : node; } ts.updateExportSpecifier = updateExportSpecifier; + // Module references function createExternalModuleReference(expression) { - var node = createSynthesizedNode(254); + var node = createSynthesizedNode(254 /* ExternalModuleReference */); node.expression = expression; return node; } @@ -49317,8 +57136,9 @@ var ts; : node; } ts.updateExternalModuleReference = updateExternalModuleReference; + // JSX function createJsxElement(openingElement, children, closingElement) { - var node = createSynthesizedNode(255); + var node = createSynthesizedNode(255 /* JsxElement */); node.openingElement = openingElement; node.children = createNodeArray(children); node.closingElement = closingElement; @@ -49334,7 +57154,7 @@ var ts; } ts.updateJsxElement = updateJsxElement; function createJsxSelfClosingElement(tagName, typeArguments, attributes) { - var node = createSynthesizedNode(256); + var node = createSynthesizedNode(256 /* JsxSelfClosingElement */); node.tagName = tagName; node.typeArguments = typeArguments && createNodeArray(typeArguments); node.attributes = attributes; @@ -49350,7 +57170,7 @@ var ts; } ts.updateJsxSelfClosingElement = updateJsxSelfClosingElement; function createJsxOpeningElement(tagName, typeArguments, attributes) { - var node = createSynthesizedNode(257); + var node = createSynthesizedNode(257 /* JsxOpeningElement */); node.tagName = tagName; node.typeArguments = typeArguments && createNodeArray(typeArguments); node.attributes = attributes; @@ -49366,7 +57186,7 @@ var ts; } ts.updateJsxOpeningElement = updateJsxOpeningElement; function createJsxClosingElement(tagName) { - var node = createSynthesizedNode(258); + var node = createSynthesizedNode(258 /* JsxClosingElement */); node.tagName = tagName; return node; } @@ -49378,7 +57198,7 @@ var ts; } ts.updateJsxClosingElement = updateJsxClosingElement; function createJsxFragment(openingFragment, children, closingFragment) { - var node = createSynthesizedNode(259); + var node = createSynthesizedNode(259 /* JsxFragment */); node.openingFragment = openingFragment; node.children = createNodeArray(children); node.closingFragment = closingFragment; @@ -49394,7 +57214,7 @@ var ts; } ts.updateJsxFragment = updateJsxFragment; function createJsxAttribute(name, initializer) { - var node = createSynthesizedNode(262); + var node = createSynthesizedNode(262 /* JsxAttribute */); node.name = name; node.initializer = initializer; return node; @@ -49408,7 +57228,7 @@ var ts; } ts.updateJsxAttribute = updateJsxAttribute; function createJsxAttributes(properties) { - var node = createSynthesizedNode(263); + var node = createSynthesizedNode(263 /* JsxAttributes */); node.properties = createNodeArray(properties); return node; } @@ -49420,7 +57240,7 @@ var ts; } ts.updateJsxAttributes = updateJsxAttributes; function createJsxSpreadAttribute(expression) { - var node = createSynthesizedNode(264); + var node = createSynthesizedNode(264 /* JsxSpreadAttribute */); node.expression = expression; return node; } @@ -49432,7 +57252,7 @@ var ts; } ts.updateJsxSpreadAttribute = updateJsxSpreadAttribute; function createJsxExpression(dotDotDotToken, expression) { - var node = createSynthesizedNode(265); + var node = createSynthesizedNode(265 /* JsxExpression */); node.dotDotDotToken = dotDotDotToken; node.expression = expression; return node; @@ -49444,8 +57264,9 @@ var ts; : node; } ts.updateJsxExpression = updateJsxExpression; + // Clauses function createCaseClause(expression, statements) { - var node = createSynthesizedNode(266); + var node = createSynthesizedNode(266 /* CaseClause */); node.expression = ts.parenthesizeExpressionForList(expression); node.statements = createNodeArray(statements); return node; @@ -49459,7 +57280,7 @@ var ts; } ts.updateCaseClause = updateCaseClause; function createDefaultClause(statements) { - var node = createSynthesizedNode(267); + var node = createSynthesizedNode(267 /* DefaultClause */); node.statements = createNodeArray(statements); return node; } @@ -49471,7 +57292,7 @@ var ts; } ts.updateDefaultClause = updateDefaultClause; function createHeritageClause(token, types) { - var node = createSynthesizedNode(268); + var node = createSynthesizedNode(268 /* HeritageClause */); node.token = token; node.types = createNodeArray(types); return node; @@ -49484,7 +57305,7 @@ var ts; } ts.updateHeritageClause = updateHeritageClause; function createCatchClause(variableDeclaration, block) { - var node = createSynthesizedNode(269); + var node = createSynthesizedNode(269 /* CatchClause */); node.variableDeclaration = ts.isString(variableDeclaration) ? createVariableDeclaration(variableDeclaration) : variableDeclaration; node.block = block; return node; @@ -49497,8 +57318,9 @@ var ts; : node; } ts.updateCatchClause = updateCatchClause; + // Property assignments function createPropertyAssignment(name, initializer) { - var node = createSynthesizedNode(270); + var node = createSynthesizedNode(270 /* PropertyAssignment */); node.name = asName(name); node.questionToken = undefined; node.initializer = ts.parenthesizeExpressionForList(initializer); @@ -49513,7 +57335,7 @@ var ts; } ts.updatePropertyAssignment = updatePropertyAssignment; function createShorthandPropertyAssignment(name, objectAssignmentInitializer) { - var node = createSynthesizedNode(271); + var node = createSynthesizedNode(271 /* ShorthandPropertyAssignment */); node.name = asName(name); node.objectAssignmentInitializer = objectAssignmentInitializer !== undefined ? ts.parenthesizeExpressionForList(objectAssignmentInitializer) : undefined; return node; @@ -49527,8 +57349,8 @@ var ts; } ts.updateShorthandPropertyAssignment = updateShorthandPropertyAssignment; function createSpreadAssignment(expression) { - var node = createSynthesizedNode(272); - node.expression = expression !== undefined ? ts.parenthesizeExpressionForList(expression) : undefined; + var node = createSynthesizedNode(272 /* SpreadAssignment */); + node.expression = expression !== undefined ? ts.parenthesizeExpressionForList(expression) : undefined; // TODO: GH#18217 return node; } ts.createSpreadAssignment = createSpreadAssignment; @@ -49538,8 +57360,9 @@ var ts; : node; } ts.updateSpreadAssignment = updateSpreadAssignment; + // Enum function createEnumMember(name, initializer) { - var node = createSynthesizedNode(273); + var node = createSynthesizedNode(273 /* EnumMember */); node.name = asName(name); node.initializer = initializer && ts.parenthesizeExpressionForList(initializer); return node; @@ -49552,6 +57375,7 @@ var ts; : node; } ts.updateEnumMember = updateEnumMember; + // Top-level nodes function updateSourceFileNode(node, statements, isDeclarationFile, referencedFiles, typeReferences, hasNoDefaultLib, libReferences) { if (node.statements !== statements || (isDeclarationFile !== undefined && node.isDeclarationFile !== isDeclarationFile) || @@ -49559,7 +57383,7 @@ var ts; (typeReferences !== undefined && node.typeReferenceDirectives !== typeReferences) || (libReferences !== undefined && node.libReferenceDirectives !== libReferences) || (hasNoDefaultLib !== undefined && node.hasNoDefaultLib !== hasNoDefaultLib)) { - var updated = createSynthesizedNode(274); + var updated = createSynthesizedNode(274 /* SourceFile */); updated.flags |= node.flags; updated.statements = createNodeArray(statements); updated.endOfFileToken = node.endOfFileToken; @@ -49624,6 +57448,9 @@ var ts; return node; } ts.updateSourceFileNode = updateSourceFileNode; + /** + * Creates a shallow, memberwise clone of a node for mutation. + */ function getMutableClone(node) { var clone = getSynthesizedClone(node); clone.pos = node.pos; @@ -49632,29 +57459,54 @@ var ts; return clone; } ts.getMutableClone = getMutableClone; + // Transformation nodes + /** + * Creates a synthetic statement to act as a placeholder for a not-emitted statement in + * order to preserve comments. + * + * @param original The original statement. + */ function createNotEmittedStatement(original) { - var node = createSynthesizedNode(301); + var node = createSynthesizedNode(301 /* NotEmittedStatement */); node.original = original; setTextRange(node, original); return node; } ts.createNotEmittedStatement = createNotEmittedStatement; + /** + * Creates a synthetic element to act as a placeholder for the end of an emitted declaration in + * order to properly emit exports. + */ + /* @internal */ function createEndOfDeclarationMarker(original) { - var node = createSynthesizedNode(305); + var node = createSynthesizedNode(305 /* EndOfDeclarationMarker */); node.emitNode = {}; node.original = original; return node; } ts.createEndOfDeclarationMarker = createEndOfDeclarationMarker; + /** + * Creates a synthetic element to act as a placeholder for the beginning of a merged declaration in + * order to properly emit exports. + */ + /* @internal */ function createMergeDeclarationMarker(original) { - var node = createSynthesizedNode(304); + var node = createSynthesizedNode(304 /* MergeDeclarationMarker */); node.emitNode = {}; node.original = original; return node; } ts.createMergeDeclarationMarker = createMergeDeclarationMarker; + /** + * Creates a synthetic expression to act as a placeholder for a not-emitted expression in + * order to preserve comments or sourcemap positions. + * + * @param expression The inner expression to emit. + * @param original The original outer expression. + * @param location The location for the expression. Defaults to the positions from "original" if provided. + */ function createPartiallyEmittedExpression(expression, original) { - var node = createSynthesizedNode(302); + var node = createSynthesizedNode(302 /* PartiallyEmittedExpression */); node.expression = expression; node.original = original; setTextRange(node, original); @@ -49670,17 +57522,17 @@ var ts; ts.updatePartiallyEmittedExpression = updatePartiallyEmittedExpression; function flattenCommaElements(node) { if (ts.nodeIsSynthesized(node) && !ts.isParseTreeNode(node) && !node.original && !node.emitNode && !node.id) { - if (node.kind === 303) { + if (node.kind === 303 /* CommaListExpression */) { return node.elements; } - if (ts.isBinaryExpression(node) && node.operatorToken.kind === 26) { + if (ts.isBinaryExpression(node) && node.operatorToken.kind === 26 /* CommaToken */) { return [node.left, node.right]; } } return node; } function createCommaList(elements) { - var node = createSynthesizedNode(303); + var node = createSynthesizedNode(303 /* CommaListExpression */); node.elements = createNodeArray(ts.sameFlatMap(elements, flattenCommaElements)); return node; } @@ -49693,14 +57545,14 @@ var ts; ts.updateCommaList = updateCommaList; function createBundle(sourceFiles, prepends) { if (prepends === void 0) { prepends = ts.emptyArray; } - var node = ts.createNode(275); + var node = ts.createNode(275 /* Bundle */); node.prepends = prepends; node.sourceFiles = sourceFiles; return node; } ts.createBundle = createBundle; function createUnparsedSourceFile(text, mapPath, map) { - var node = ts.createNode(276); + var node = ts.createNode(276 /* UnparsedSource */); node.text = text; node.sourceMapPath = mapPath; node.sourceMapText = map; @@ -49708,7 +57560,7 @@ var ts; } ts.createUnparsedSourceFile = createUnparsedSourceFile; function createInputFiles(javascript, declaration, javascriptMapPath, javascriptMapText, declarationMapPath, declarationMapText) { - var node = ts.createNode(277); + var node = ts.createNode(277 /* InputFiles */); node.javascriptText = javascript; node.javascriptMapPath = javascriptMapPath; node.javascriptMapText = javascriptMapText; @@ -49727,55 +57579,70 @@ var ts; } ts.updateBundle = updateBundle; function createImmediatelyInvokedFunctionExpression(statements, param, paramValue) { - return createCall(createFunctionExpression(undefined, undefined, undefined, undefined, param ? [param] : [], undefined, createBlock(statements, true)), undefined, paramValue ? [paramValue] : []); + return createCall(createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ param ? [param] : [], + /*type*/ undefined, createBlock(statements, /*multiLine*/ true)), + /*typeArguments*/ undefined, + /*argumentsArray*/ paramValue ? [paramValue] : []); } ts.createImmediatelyInvokedFunctionExpression = createImmediatelyInvokedFunctionExpression; function createImmediatelyInvokedArrowFunction(statements, param, paramValue) { - return createCall(createArrowFunction(undefined, undefined, param ? [param] : [], undefined, undefined, createBlock(statements, true)), undefined, paramValue ? [paramValue] : []); + return createCall(createArrowFunction( + /*modifiers*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ param ? [param] : [], + /*type*/ undefined, + /*equalsGreaterThanToken*/ undefined, createBlock(statements, /*multiLine*/ true)), + /*typeArguments*/ undefined, + /*argumentsArray*/ paramValue ? [paramValue] : []); } ts.createImmediatelyInvokedArrowFunction = createImmediatelyInvokedArrowFunction; function createComma(left, right) { - return createBinary(left, 26, right); + return createBinary(left, 26 /* CommaToken */, right); } ts.createComma = createComma; function createLessThan(left, right) { - return createBinary(left, 27, right); + return createBinary(left, 27 /* LessThanToken */, right); } ts.createLessThan = createLessThan; function createAssignment(left, right) { - return createBinary(left, 58, right); + return createBinary(left, 58 /* EqualsToken */, right); } ts.createAssignment = createAssignment; function createStrictEquality(left, right) { - return createBinary(left, 34, right); + return createBinary(left, 34 /* EqualsEqualsEqualsToken */, right); } ts.createStrictEquality = createStrictEquality; function createStrictInequality(left, right) { - return createBinary(left, 35, right); + return createBinary(left, 35 /* ExclamationEqualsEqualsToken */, right); } ts.createStrictInequality = createStrictInequality; function createAdd(left, right) { - return createBinary(left, 37, right); + return createBinary(left, 37 /* PlusToken */, right); } ts.createAdd = createAdd; function createSubtract(left, right) { - return createBinary(left, 38, right); + return createBinary(left, 38 /* MinusToken */, right); } ts.createSubtract = createSubtract; function createPostfixIncrement(operand) { - return createPostfix(operand, 43); + return createPostfix(operand, 43 /* PlusPlusToken */); } ts.createPostfixIncrement = createPostfixIncrement; function createLogicalAnd(left, right) { - return createBinary(left, 53, right); + return createBinary(left, 53 /* AmpersandAmpersandToken */, right); } ts.createLogicalAnd = createLogicalAnd; function createLogicalOr(left, right) { - return createBinary(left, 54, right); + return createBinary(left, 54 /* BarBarToken */, right); } ts.createLogicalOr = createLogicalOr; function createLogicalNot(operand) { - return createPrefix(51, operand); + return createPrefix(51 /* ExclamationToken */, operand); } ts.createLogicalNot = createLogicalNot; function createVoidZero() { @@ -49783,13 +57650,14 @@ var ts; } ts.createVoidZero = createVoidZero; function createExportDefault(expression) { - return createExportAssignment(undefined, undefined, false, expression); + return createExportAssignment(/*decorators*/ undefined, /*modifiers*/ undefined, /*isExportEquals*/ false, expression); } ts.createExportDefault = createExportDefault; function createExternalModuleExport(exportName) { - return createExportDeclaration(undefined, undefined, createNamedExports([createExportSpecifier(undefined, exportName)])); + return createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([createExportSpecifier(/*propertyName*/ undefined, exportName)])); } ts.createExternalModuleExport = createExternalModuleExport; + // Utilities function asName(name) { return ts.isString(name) ? createIdentifier(name) : name; } @@ -49802,7 +57670,17 @@ var ts; function asToken(value) { return typeof value === "number" ? createToken(value) : value; } + /** + * Clears any EmitNode entries from parse-tree nodes. + * @param sourceFile A source file. + */ function disposeEmitNodes(sourceFile) { + // During transformation we may need to annotate a parse tree node with transient + // transformation properties. As parse tree nodes live longer than transformation + // nodes, we need to make sure we reclaim any memory allocated for custom ranges + // from these nodes to ensure we do not hold onto entire subtrees just for position + // information. We also need to reset these nodes to a pre-transformation state + // for incremental parsing scenarios so that we do not impact later emit. sourceFile = ts.getSourceFileOfNode(ts.getParseTreeNode(sourceFile)); var emitNode = sourceFile && sourceFile.emitNode; var annotatedNodes = emitNode && emitNode.annotatedNodes; @@ -49814,10 +57692,18 @@ var ts; } } ts.disposeEmitNodes = disposeEmitNodes; + /** + * Associates a node with the current transformation, initializing + * various transient transformation properties. + */ + /* @internal */ function getOrCreateEmitNode(node) { if (!node.emitNode) { if (ts.isParseTreeNode(node)) { - if (node.kind === 274) { + // To avoid holding onto transformation artifacts, we keep track of any + // parse tree node we are annotating. This allows us to clean them up after + // all transformations have completed. + if (node.kind === 274 /* SourceFile */) { return node.emitNode = { annotatedNodes: [node] }; } var sourceFile = ts.getSourceFileOfNode(node); @@ -49836,38 +57722,61 @@ var ts; return range; } ts.setTextRange = setTextRange; + /** + * Sets flags that control emit behavior of a node. + */ function setEmitFlags(node, emitFlags) { getOrCreateEmitNode(node).flags = emitFlags; return node; } ts.setEmitFlags = setEmitFlags; + /** + * Sets flags that control emit behavior of a node. + */ + /* @internal */ function addEmitFlags(node, emitFlags) { var emitNode = getOrCreateEmitNode(node); emitNode.flags = emitNode.flags | emitFlags; return node; } ts.addEmitFlags = addEmitFlags; + /** + * Gets a custom text range to use when emitting source maps. + */ function getSourceMapRange(node) { var emitNode = node.emitNode; return (emitNode && emitNode.sourceMapRange) || node; } ts.getSourceMapRange = getSourceMapRange; + /** + * Sets a custom text range to use when emitting source maps. + */ function setSourceMapRange(node, range) { getOrCreateEmitNode(node).sourceMapRange = range; return node; } ts.setSourceMapRange = setSourceMapRange; + // tslint:disable-next-line variable-name var SourceMapSource; + /** + * Create an external source map source file reference + */ function createSourceMapSource(fileName, text, skipTrivia) { return new (SourceMapSource || (SourceMapSource = ts.objectAllocator.getSourceMapSourceConstructor()))(fileName, text, skipTrivia); } ts.createSourceMapSource = createSourceMapSource; + /** + * Gets the TextRange to use for source maps for a token of a node. + */ function getTokenSourceMapRange(node, token) { var emitNode = node.emitNode; var tokenSourceMapRanges = emitNode && emitNode.tokenSourceMapRanges; return tokenSourceMapRanges && tokenSourceMapRanges[token]; } ts.getTokenSourceMapRange = getTokenSourceMapRange; + /** + * Sets the TextRange to use for source maps for a token of a node. + */ function setTokenSourceMapRange(node, token, range) { var emitNode = getOrCreateEmitNode(node); var tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = []); @@ -49875,21 +57784,35 @@ var ts; return node; } ts.setTokenSourceMapRange = setTokenSourceMapRange; + /** + * Gets a custom text range to use when emitting comments. + */ + /*@internal*/ function getStartsOnNewLine(node) { var emitNode = node.emitNode; return emitNode && emitNode.startsOnNewLine; } ts.getStartsOnNewLine = getStartsOnNewLine; + /** + * Sets a custom text range to use when emitting comments. + */ + /*@internal*/ function setStartsOnNewLine(node, newLine) { getOrCreateEmitNode(node).startsOnNewLine = newLine; return node; } ts.setStartsOnNewLine = setStartsOnNewLine; + /** + * Gets a custom text range to use when emitting comments. + */ function getCommentRange(node) { var emitNode = node.emitNode; return (emitNode && emitNode.commentRange) || node; } ts.getCommentRange = getCommentRange; + /** + * Sets a custom text range to use when emitting comments. + */ function setCommentRange(node, range) { getOrCreateEmitNode(node).commentRange = range; return node; @@ -49932,23 +57855,35 @@ var ts; return node; } ts.moveSyntheticComments = moveSyntheticComments; + /** + * Gets the constant value to emit for an expression. + */ function getConstantValue(node) { var emitNode = node.emitNode; return emitNode && emitNode.constantValue; } ts.getConstantValue = getConstantValue; + /** + * Sets the constant value to emit for an expression. + */ function setConstantValue(node, value) { var emitNode = getOrCreateEmitNode(node); emitNode.constantValue = value; return node; } ts.setConstantValue = setConstantValue; + /** + * Adds an EmitHelper to a node. + */ function addEmitHelper(node, helper) { var emitNode = getOrCreateEmitNode(node); emitNode.helpers = ts.append(emitNode.helpers, helper); return node; } ts.addEmitHelper = addEmitHelper; + /** + * Add EmitHelpers to a node. + */ function addEmitHelpers(node, helpers) { if (ts.some(helpers)) { var emitNode = getOrCreateEmitNode(node); @@ -49960,6 +57895,9 @@ var ts; return node; } ts.addEmitHelpers = addEmitHelpers; + /** + * Removes an EmitHelper from a node. + */ function removeEmitHelper(node, helper) { var emitNode = node.emitNode; if (emitNode) { @@ -49971,11 +57909,17 @@ var ts; return false; } ts.removeEmitHelper = removeEmitHelper; + /** + * Gets the EmitHelpers of a node. + */ function getEmitHelpers(node) { var emitNode = node.emitNode; return emitNode && emitNode.helpers; } ts.getEmitHelpers = getEmitHelpers; + /** + * Moves matching emit helpers from a source node to a target node. + */ function moveEmitHelpers(source, target, predicate) { var sourceEmitNode = source.emitNode; var sourceEmitHelpers = sourceEmitNode && sourceEmitNode.helpers; @@ -49998,15 +57942,16 @@ var ts; } } ts.moveEmitHelpers = moveEmitHelpers; + /* @internal */ function compareEmitHelpers(x, y) { if (x === y) - return 0; + return 0 /* EqualTo */; if (x.priority === y.priority) - return 0; + return 0 /* EqualTo */; if (x.priority === undefined) - return 1; + return 1 /* GreaterThan */; if (y.priority === undefined) - return -1; + return -1 /* LessThan */; return ts.compareValues(x.priority, y.priority); } ts.compareEmitHelpers = compareEmitHelpers; @@ -50024,6 +57969,7 @@ var ts; var flags = sourceEmitNode.flags, leadingComments = sourceEmitNode.leadingComments, trailingComments = sourceEmitNode.trailingComments, commentRange = sourceEmitNode.commentRange, sourceMapRange = sourceEmitNode.sourceMapRange, tokenSourceMapRanges = sourceEmitNode.tokenSourceMapRanges, constantValue = sourceEmitNode.constantValue, helpers = sourceEmitNode.helpers, startsOnNewLine = sourceEmitNode.startsOnNewLine; if (!destEmitNode) destEmitNode = {}; + // We are using `.slice()` here in case `destEmitNode.leadingComments` is pushed to later. if (leadingComments) destEmitNode.leadingComments = ts.addRange(leadingComments.slice(), destEmitNode.leadingComments); if (trailingComments) @@ -50053,6 +57999,7 @@ var ts; return destRanges; } })(ts || (ts = {})); +/* @internal */ (function (ts) { ts.nullTransformationContext = { enableEmitNotification: ts.noop, @@ -50088,19 +58035,21 @@ var ts; var expression = ts.setTextRange(ts.isIdentifier(memberName) ? ts.createPropertyAccess(target, memberName) : ts.createElementAccess(target, memberName), memberName); - ts.getOrCreateEmitNode(expression).flags |= 64; + ts.getOrCreateEmitNode(expression).flags |= 64 /* NoNestedSourceMaps */; return expression; } } ts.createMemberAccessForPropertyName = createMemberAccessForPropertyName; function createFunctionCall(func, thisArg, argumentsList, location) { - return ts.setTextRange(ts.createCall(ts.createPropertyAccess(func, "call"), undefined, [ + return ts.setTextRange(ts.createCall(ts.createPropertyAccess(func, "call"), + /*typeArguments*/ undefined, [ thisArg ].concat(argumentsList)), location); } ts.createFunctionCall = createFunctionCall; function createFunctionApply(func, thisArg, argumentsExpression, location) { - return ts.setTextRange(ts.createCall(ts.createPropertyAccess(func, "apply"), undefined, [ + return ts.setTextRange(ts.createCall(ts.createPropertyAccess(func, "apply"), + /*typeArguments*/ undefined, [ thisArg, argumentsExpression ]), location); @@ -50111,20 +58060,27 @@ var ts; if (start !== undefined) { argumentsList.push(typeof start === "number" ? ts.createLiteral(start) : start); } - return ts.createCall(ts.createPropertyAccess(array, "slice"), undefined, argumentsList); + return ts.createCall(ts.createPropertyAccess(array, "slice"), /*typeArguments*/ undefined, argumentsList); } ts.createArraySlice = createArraySlice; function createArrayConcat(array, values) { - return ts.createCall(ts.createPropertyAccess(array, "concat"), undefined, values); + return ts.createCall(ts.createPropertyAccess(array, "concat"), + /*typeArguments*/ undefined, values); } ts.createArrayConcat = createArrayConcat; function createMathPow(left, right, location) { - return ts.setTextRange(ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Math"), "pow"), undefined, [left, right]), location); + return ts.setTextRange(ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Math"), "pow"), + /*typeArguments*/ undefined, [left, right]), location); } ts.createMathPow = createMathPow; function createReactNamespace(reactNamespace, parent) { + // To ensure the emit resolver can properly resolve the namespace, we need to + // treat this identifier as if it were a source tree node by clearing the `Synthesized` + // flag and setting a parent node. var react = ts.createIdentifier(reactNamespace || "React"); - react.flags &= ~8; + react.flags &= ~8 /* Synthesized */; + // Set the parent that is in parse tree + // this makes sure that parent chain is intact for checker to traverse complete scope tree react.parent = ts.getParseTreeNode(parent); return react; } @@ -50164,7 +58120,8 @@ var ts; argumentsList.push(children[0]); } } - return ts.setTextRange(ts.createCall(createJsxFactoryExpression(jsxFactoryEntity, reactNamespace, parentElement), undefined, argumentsList), location); + return ts.setTextRange(ts.createCall(createJsxFactoryExpression(jsxFactoryEntity, reactNamespace, parentElement), + /*typeArguments*/ undefined, argumentsList), location); } ts.createExpressionForJsxElement = createExpressionForJsxElement; function createExpressionForJsxFragment(jsxFactoryEntity, reactNamespace, children, parentElement, location) { @@ -50183,11 +58140,13 @@ var ts; argumentsList.push(children[0]); } } - return ts.setTextRange(ts.createCall(createJsxFactoryExpression(jsxFactoryEntity, reactNamespace, parentElement), undefined, argumentsList), location); + return ts.setTextRange(ts.createCall(createJsxFactoryExpression(jsxFactoryEntity, reactNamespace, parentElement), + /*typeArguments*/ undefined, argumentsList), location); } ts.createExpressionForJsxFragment = createExpressionForJsxFragment; + // Helpers function getHelperName(name) { - return ts.setEmitFlags(ts.createIdentifier(name), 4096 | 2); + return ts.setEmitFlags(ts.createIdentifier(name), 4096 /* HelperName */ | 2 /* AdviseOnEmitNode */); } ts.getHelperName = getHelperName; var valuesHelper = { @@ -50197,7 +58156,8 @@ var ts; }; function createValuesHelper(context, expression, location) { context.requestEmitHelper(valuesHelper); - return ts.setTextRange(ts.createCall(getHelperName("__values"), undefined, [expression]), location); + return ts.setTextRange(ts.createCall(getHelperName("__values"), + /*typeArguments*/ undefined, [expression]), location); } ts.createValuesHelper = createValuesHelper; var readHelper = { @@ -50207,7 +58167,8 @@ var ts; }; function createReadHelper(context, iteratorRecord, count, location) { context.requestEmitHelper(readHelper); - return ts.setTextRange(ts.createCall(getHelperName("__read"), undefined, count !== undefined + return ts.setTextRange(ts.createCall(getHelperName("__read"), + /*typeArguments*/ undefined, count !== undefined ? [iteratorRecord, ts.createLiteral(count)] : [iteratorRecord]), location); } @@ -50220,18 +58181,23 @@ var ts; function createSpreadHelper(context, argumentList, location) { context.requestEmitHelper(readHelper); context.requestEmitHelper(spreadHelper); - return ts.setTextRange(ts.createCall(getHelperName("__spread"), undefined, argumentList), location); + return ts.setTextRange(ts.createCall(getHelperName("__spread"), + /*typeArguments*/ undefined, argumentList), location); } ts.createSpreadHelper = createSpreadHelper; + // Utilities function createForOfBindingStatement(node, boundValue) { if (ts.isVariableDeclarationList(node)) { var firstDeclaration = ts.first(node.declarations); - var updatedDeclaration = ts.updateVariableDeclaration(firstDeclaration, firstDeclaration.name, undefined, boundValue); - return ts.setTextRange(ts.createVariableStatement(undefined, ts.updateVariableDeclarationList(node, [updatedDeclaration])), node); + var updatedDeclaration = ts.updateVariableDeclaration(firstDeclaration, firstDeclaration.name, + /*typeNode*/ undefined, boundValue); + return ts.setTextRange(ts.createVariableStatement( + /*modifiers*/ undefined, ts.updateVariableDeclarationList(node, [updatedDeclaration])), + /*location*/ node); } else { - var updatedExpression = ts.setTextRange(ts.createAssignment(node, boundValue), node); - return ts.setTextRange(ts.createStatement(updatedExpression), node); + var updatedExpression = ts.setTextRange(ts.createAssignment(node, boundValue), /*location*/ node); + return ts.setTextRange(ts.createStatement(updatedExpression), /*location*/ node); } } ts.createForOfBindingStatement = createForOfBindingStatement; @@ -50240,7 +58206,7 @@ var ts; return ts.updateBlock(dest, ts.setTextRange(ts.createNodeArray([source].concat(dest.statements)), dest.statements)); } else { - return ts.createBlock(ts.createNodeArray([dest, source]), true); + return ts.createBlock(ts.createNodeArray([dest, source]), /*multiLine*/ true); } } ts.insertLeadingStatement = insertLeadingStatement; @@ -50248,7 +58214,7 @@ var ts; if (!outermostLabeledStatement) { return node; } - var updated = ts.updateLabel(outermostLabeledStatement, outermostLabeledStatement.label, outermostLabeledStatement.statement.kind === 228 + var updated = ts.updateLabel(outermostLabeledStatement, outermostLabeledStatement.label, outermostLabeledStatement.statement.kind === 228 /* LabeledStatement */ ? restoreEnclosingLabel(node, outermostLabeledStatement.statement) : node); if (afterRestoreLabelCallback) { @@ -50260,19 +58226,19 @@ var ts; function shouldBeCapturedInTempVariable(node, cacheIdentifiers) { var target = ts.skipParentheses(node); switch (target.kind) { - case 71: + case 71 /* Identifier */: return cacheIdentifiers; - case 99: - case 8: - case 9: + case 99 /* ThisKeyword */: + case 8 /* NumericLiteral */: + case 9 /* StringLiteral */: return false; - case 183: + case 183 /* ArrayLiteralExpression */: var elements = target.elements; if (elements.length === 0) { return false; } return true; - case 184: + case 184 /* ObjectLiteralExpression */: return target.properties.length > 0; default: return true; @@ -50280,27 +58246,28 @@ var ts; } function createCallBinding(expression, recordTempVariable, languageVersion, cacheIdentifiers) { if (cacheIdentifiers === void 0) { cacheIdentifiers = false; } - var callee = skipOuterExpressions(expression, 7); + var callee = skipOuterExpressions(expression, 7 /* All */); var thisArg; var target; if (ts.isSuperProperty(callee)) { thisArg = ts.createThis(); target = callee; } - else if (callee.kind === 97) { + else if (callee.kind === 97 /* SuperKeyword */) { thisArg = ts.createThis(); - target = languageVersion < 2 + target = languageVersion < 2 /* ES2015 */ ? ts.setTextRange(ts.createIdentifier("_super"), callee) : callee; } - else if (ts.getEmitFlags(callee) & 4096) { + else if (ts.getEmitFlags(callee) & 4096 /* HelperName */) { thisArg = ts.createVoidZero(); target = parenthesizeForAccess(callee); } else { switch (callee.kind) { - case 185: { + case 185 /* PropertyAccessExpression */: { if (shouldBeCapturedInTempVariable(callee.expression, cacheIdentifiers)) { + // for `a.b()` target is `(_a = a).b` and thisArg is `_a` thisArg = ts.createTempVariable(recordTempVariable); target = ts.createPropertyAccess(ts.setTextRange(ts.createAssignment(thisArg, callee.expression), callee.expression), callee.name); ts.setTextRange(target, callee); @@ -50311,8 +58278,9 @@ var ts; } break; } - case 186: { + case 186 /* ElementAccessExpression */: { if (shouldBeCapturedInTempVariable(callee.expression, cacheIdentifiers)) { + // for `a[b]()` target is `(_a = a)[b]` and thisArg is `_a` thisArg = ts.createTempVariable(recordTempVariable); target = ts.createElementAccess(ts.setTextRange(ts.createAssignment(thisArg, callee.expression), callee.expression), callee.argumentExpression); ts.setTextRange(target, callee); @@ -50324,6 +58292,7 @@ var ts; break; } default: { + // for `a()` target is `a` and thisArg is `void 0` thisArg = ts.createVoidZero(); target = parenthesizeForAccess(expression); break; @@ -50334,6 +58303,8 @@ var ts; } ts.createCallBinding = createCallBinding; function inlineExpressions(expressions) { + // Avoid deeply nested comma expressions as traversing them during emit can result in "Maximum call + // stack size exceeded" errors. return expressions.length > 10 ? ts.createCommaList(expressions) : ts.reduceLeft(expressions, ts.createComma); @@ -50364,14 +58335,14 @@ var ts; ts.createExpressionForPropertyName = createExpressionForPropertyName; function createExpressionForObjectLiteralElementLike(node, property, receiver) { switch (property.kind) { - case 156: - case 157: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return createExpressionForAccessorDeclaration(node.properties, property, receiver, !!node.multiLine); - case 270: + case 270 /* PropertyAssignment */: return createExpressionForPropertyAssignment(property, receiver); - case 271: + case 271 /* ShorthandPropertyAssignment */: return createExpressionForShorthandPropertyAssignment(property, receiver); - case 154: + case 154 /* MethodDeclaration */: return createExpressionForMethodDeclaration(property, receiver); } } @@ -50381,14 +58352,24 @@ var ts; if (property === firstAccessor) { var properties_9 = []; if (getAccessor) { - var getterFunction = ts.createFunctionExpression(getAccessor.modifiers, undefined, undefined, undefined, getAccessor.parameters, undefined, getAccessor.body); + var getterFunction = ts.createFunctionExpression(getAccessor.modifiers, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, getAccessor.parameters, + /*type*/ undefined, getAccessor.body // TODO: GH#18217 + ); ts.setTextRange(getterFunction, getAccessor); ts.setOriginalNode(getterFunction, getAccessor); var getter = ts.createPropertyAssignment("get", getterFunction); properties_9.push(getter); } if (setAccessor) { - var setterFunction = ts.createFunctionExpression(setAccessor.modifiers, undefined, undefined, undefined, setAccessor.parameters, undefined, setAccessor.body); + var setterFunction = ts.createFunctionExpression(setAccessor.modifiers, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, setAccessor.parameters, + /*type*/ undefined, setAccessor.body // TODO: GH#18217 + ); ts.setTextRange(setterFunction, setAccessor); ts.setOriginalNode(setterFunction, setAccessor); var setter = ts.createPropertyAssignment("set", setterFunction); @@ -50396,48 +58377,108 @@ var ts; } properties_9.push(ts.createPropertyAssignment("enumerable", ts.createTrue())); properties_9.push(ts.createPropertyAssignment("configurable", ts.createTrue())); - var expression = ts.setTextRange(ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Object"), "defineProperty"), undefined, [ + var expression = ts.setTextRange(ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Object"), "defineProperty"), + /*typeArguments*/ undefined, [ receiver, createExpressionForPropertyName(property.name), ts.createObjectLiteral(properties_9, multiLine) - ]), firstAccessor); + ]), + /*location*/ firstAccessor); return ts.aggregateTransformFlags(expression); } return undefined; } function createExpressionForPropertyAssignment(property, receiver) { - return ts.aggregateTransformFlags(ts.setOriginalNode(ts.setTextRange(ts.createAssignment(createMemberAccessForPropertyName(receiver, property.name, property.name), property.initializer), property), property)); + return ts.aggregateTransformFlags(ts.setOriginalNode(ts.setTextRange(ts.createAssignment(createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name), property.initializer), property), property)); } function createExpressionForShorthandPropertyAssignment(property, receiver) { - return ts.aggregateTransformFlags(ts.setOriginalNode(ts.setTextRange(ts.createAssignment(createMemberAccessForPropertyName(receiver, property.name, property.name), ts.getSynthesizedClone(property.name)), property), property)); + return ts.aggregateTransformFlags(ts.setOriginalNode(ts.setTextRange(ts.createAssignment(createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name), ts.getSynthesizedClone(property.name)), + /*location*/ property), + /*original*/ property)); } function createExpressionForMethodDeclaration(method, receiver) { - return ts.aggregateTransformFlags(ts.setOriginalNode(ts.setTextRange(ts.createAssignment(createMemberAccessForPropertyName(receiver, method.name, method.name), ts.setOriginalNode(ts.setTextRange(ts.createFunctionExpression(method.modifiers, method.asteriskToken, undefined, undefined, method.parameters, undefined, method.body), method), method)), method), method)); + return ts.aggregateTransformFlags(ts.setOriginalNode(ts.setTextRange(ts.createAssignment(createMemberAccessForPropertyName(receiver, method.name, /*location*/ method.name), ts.setOriginalNode(ts.setTextRange(ts.createFunctionExpression(method.modifiers, method.asteriskToken, + /*name*/ undefined, + /*typeParameters*/ undefined, method.parameters, + /*type*/ undefined, method.body // TODO: GH#18217 + ), + /*location*/ method), + /*original*/ method)), + /*location*/ method), + /*original*/ method)); } + /** + * Gets the internal name of a declaration. This is primarily used for declarations that can be + * referred to by name in the body of an ES5 class function body. An internal name will *never* + * be prefixed with an module or namespace export modifier like "exports." when emitted as an + * expression. An internal name will also *never* be renamed due to a collision with a block + * scoped variable. + * + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ function getInternalName(node, allowComments, allowSourceMaps) { - return getName(node, allowComments, allowSourceMaps, 16384 | 32768); + return getName(node, allowComments, allowSourceMaps, 16384 /* LocalName */ | 32768 /* InternalName */); } ts.getInternalName = getInternalName; + /** + * Gets whether an identifier should only be referred to by its internal name. + */ function isInternalName(node) { - return (ts.getEmitFlags(node) & 32768) !== 0; + return (ts.getEmitFlags(node) & 32768 /* InternalName */) !== 0; } ts.isInternalName = isInternalName; + /** + * Gets the local name of a declaration. This is primarily used for declarations that can be + * referred to by name in the declaration's immediate scope (classes, enums, namespaces). A + * local name will *never* be prefixed with an module or namespace export modifier like + * "exports." when emitted as an expression. + * + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ function getLocalName(node, allowComments, allowSourceMaps) { - return getName(node, allowComments, allowSourceMaps, 16384); + return getName(node, allowComments, allowSourceMaps, 16384 /* LocalName */); } ts.getLocalName = getLocalName; + /** + * Gets whether an identifier should only be referred to by its local name. + */ function isLocalName(node) { - return (ts.getEmitFlags(node) & 16384) !== 0; + return (ts.getEmitFlags(node) & 16384 /* LocalName */) !== 0; } ts.isLocalName = isLocalName; + /** + * Gets the export name of a declaration. This is primarily used for declarations that can be + * referred to by name in the declaration's immediate scope (classes, enums, namespaces). An + * export name will *always* be prefixed with an module or namespace export modifier like + * `"exports."` when emitted as an expression if the name points to an exported symbol. + * + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ function getExportName(node, allowComments, allowSourceMaps) { - return getName(node, allowComments, allowSourceMaps, 8192); + return getName(node, allowComments, allowSourceMaps, 8192 /* ExportName */); } ts.getExportName = getExportName; + /** + * Gets whether an identifier should only be referred to by its export representation if the + * name points to an exported symbol. + */ function isExportName(node) { - return (ts.getEmitFlags(node) & 8192) !== 0; + return (ts.getEmitFlags(node) & 8192 /* ExportName */) !== 0; } ts.isExportName = isExportName; + /** + * Gets the name of a declaration for use in declarations. + * + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ function getDeclarationName(node, allowComments, allowSourceMaps) { return getName(node, allowComments, allowSourceMaps); } @@ -50449,30 +58490,49 @@ var ts; var name = ts.getMutableClone(nodeName); emitFlags |= ts.getEmitFlags(nodeName); if (!allowSourceMaps) - emitFlags |= 48; + emitFlags |= 48 /* NoSourceMap */; if (!allowComments) - emitFlags |= 1536; + emitFlags |= 1536 /* NoComments */; if (emitFlags) ts.setEmitFlags(name, emitFlags); return name; } return ts.getGeneratedNameForNode(node); } + /** + * Gets the exported name of a declaration for use in expressions. + * + * An exported name will *always* be prefixed with an module or namespace export modifier like + * "exports." if the name points to an exported symbol. + * + * @param ns The namespace identifier. + * @param node The declaration. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ function getExternalModuleOrNamespaceExportName(ns, node, allowComments, allowSourceMaps) { - if (ns && ts.hasModifier(node, 1)) { + if (ns && ts.hasModifier(node, 1 /* Export */)) { return getNamespaceMemberName(ns, getName(node), allowComments, allowSourceMaps); } return getExportName(node, allowComments, allowSourceMaps); } ts.getExternalModuleOrNamespaceExportName = getExternalModuleOrNamespaceExportName; + /** + * Gets a namespace-qualified name for use in expressions. + * + * @param ns The namespace identifier. + * @param name The name. + * @param allowComments A value indicating whether comments may be emitted for the name. + * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. + */ function getNamespaceMemberName(ns, name, allowComments, allowSourceMaps) { var qualifiedName = ts.createPropertyAccess(ns, ts.nodeIsSynthesized(name) ? name : ts.getSynthesizedClone(name)); ts.setTextRange(qualifiedName, name); var emitFlags = 0; if (!allowSourceMaps) - emitFlags |= 48; + emitFlags |= 48 /* NoSourceMap */; if (!allowComments) - emitFlags |= 1536; + emitFlags |= 1536 /* NoComments */; if (emitFlags) ts.setEmitFlags(qualifiedName, emitFlags); return qualifiedName; @@ -50489,7 +58549,7 @@ var ts; ts.setOriginalNode(updated, node); ts.setTextRange(updated, node); if (ts.getStartsOnNewLine(node)) { - ts.setStartsOnNewLine(updated, true); + ts.setStartsOnNewLine(updated, /*newLine*/ true); } ts.aggregateTransformFlags(updated); return updated; @@ -50498,11 +58558,28 @@ var ts; function isUseStrictPrologue(node) { return ts.isStringLiteral(node.expression) && node.expression.text === "use strict"; } + /** + * Add any necessary prologue-directives into target statement-array. + * The function needs to be called during each transformation step. + * This function needs to be called whenever we transform the statement + * list of a source file, namespace, or function-like body. + * + * @param target: result statements array + * @param source: origin statements array + * @param ensureUseStrict: boolean determining whether the function need to add prologue-directives + * @param visitor: Optional callback used to visit any custom prologue directives. + */ function addPrologue(target, source, ensureUseStrict, visitor) { var offset = addStandardPrologue(target, source, ensureUseStrict); return addCustomPrologue(target, source, offset, visitor); } ts.addPrologue = addPrologue; + /** + * Add just the standard (string-expression) prologue-directives into target statement-array. + * The function needs to be called during each transformation step. + * This function needs to be called whenever we transform the statement + * list of a source file, namespace, or function-like body. + */ function addStandardPrologue(target, source, ensureUseStrict) { ts.Debug.assert(target.length === 0, "Prologue directives should be at the first statement in the target statements array"); var foundUseStrict = false; @@ -50531,7 +58608,7 @@ var ts; var numStatements = source.length; while (statementOffset !== undefined && statementOffset < numStatements) { var statement = source[statementOffset]; - if (ts.getEmitFlags(statement) & 1048576) { + if (ts.getEmitFlags(statement) & 1048576 /* CustomPrologue */) { ts.append(target, visitor ? ts.visitNode(statement, visitor, ts.isStatement) : statement); } else { @@ -50549,6 +58626,11 @@ var ts; && isUseStrictPrologue(firstStatement); } ts.startsWithUseStrict = startsWithUseStrict; + /** + * Ensures "use strict" directive is added + * + * @param statements An array of statements + */ function ensureUseStrict(statements) { var foundUseStrict = false; for (var _i = 0, statements_3 = statements; _i < statements_3.length; _i++) { @@ -50571,9 +58653,19 @@ var ts; return statements; } ts.ensureUseStrict = ensureUseStrict; + /** + * Wraps the operand to a BinaryExpression in parentheses if they are needed to preserve the intended + * order of operations. + * + * @param binaryOperator The operator for the BinaryExpression. + * @param operand The operand for the BinaryExpression. + * @param isLeftSideOfBinary A value indicating whether the operand is the left side of the + * BinaryExpression. + */ function parenthesizeBinaryOperand(binaryOperator, operand, isLeftSideOfBinary, leftOperand) { var skipped = ts.skipPartiallyEmittedExpressions(operand); - if (skipped.kind === 191) { + // If the resulting expression is already parenthesized, we do not need to do any further processing. + if (skipped.kind === 191 /* ParenthesizedExpression */) { return operand; } return binaryOperandNeedsParentheses(binaryOperator, operand, isLeftSideOfBinary, leftOperand) @@ -50581,55 +58673,131 @@ var ts; : operand; } ts.parenthesizeBinaryOperand = parenthesizeBinaryOperand; + /** + * Determines whether the operand to a BinaryExpression needs to be parenthesized. + * + * @param binaryOperator The operator for the BinaryExpression. + * @param operand The operand for the BinaryExpression. + * @param isLeftSideOfBinary A value indicating whether the operand is the left side of the + * BinaryExpression. + */ function binaryOperandNeedsParentheses(binaryOperator, operand, isLeftSideOfBinary, leftOperand) { - var binaryOperatorPrecedence = ts.getOperatorPrecedence(200, binaryOperator); - var binaryOperatorAssociativity = ts.getOperatorAssociativity(200, binaryOperator); + // If the operand has lower precedence, then it needs to be parenthesized to preserve the + // intent of the expression. For example, if the operand is `a + b` and the operator is + // `*`, then we need to parenthesize the operand to preserve the intended order of + // operations: `(a + b) * x`. + // + // If the operand has higher precedence, then it does not need to be parenthesized. For + // example, if the operand is `a * b` and the operator is `+`, then we do not need to + // parenthesize to preserve the intended order of operations: `a * b + x`. + // + // If the operand has the same precedence, then we need to check the associativity of + // the operator based on whether this is the left or right operand of the expression. + // + // For example, if `a / d` is on the right of operator `*`, we need to parenthesize + // to preserve the intended order of operations: `x * (a / d)` + // + // If `a ** d` is on the left of operator `**`, we need to parenthesize to preserve + // the intended order of operations: `(a ** b) ** c` + var binaryOperatorPrecedence = ts.getOperatorPrecedence(200 /* BinaryExpression */, binaryOperator); + var binaryOperatorAssociativity = ts.getOperatorAssociativity(200 /* BinaryExpression */, binaryOperator); var emittedOperand = ts.skipPartiallyEmittedExpressions(operand); var operandPrecedence = ts.getExpressionPrecedence(emittedOperand); switch (ts.compareValues(operandPrecedence, binaryOperatorPrecedence)) { - case -1: + case -1 /* LessThan */: + // If the operand is the right side of a right-associative binary operation + // and is a yield expression, then we do not need parentheses. if (!isLeftSideOfBinary - && binaryOperatorAssociativity === 1 - && operand.kind === 203) { + && binaryOperatorAssociativity === 1 /* Right */ + && operand.kind === 203 /* YieldExpression */) { return false; } return true; - case 1: + case 1 /* GreaterThan */: return false; - case 0: + case 0 /* EqualTo */: if (isLeftSideOfBinary) { - return binaryOperatorAssociativity === 1; + // No need to parenthesize the left operand when the binary operator is + // left associative: + // (a*b)/x -> a*b/x + // (a**b)/x -> a**b/x + // + // Parentheses are needed for the left operand when the binary operator is + // right associative: + // (a/b)**x -> (a/b)**x + // (a**b)**x -> (a**b)**x + return binaryOperatorAssociativity === 1 /* Right */; } else { if (ts.isBinaryExpression(emittedOperand) && emittedOperand.operatorToken.kind === binaryOperator) { + // No need to parenthesize the right operand when the binary operator and + // operand are the same and one of the following: + // x*(a*b) => x*a*b + // x|(a|b) => x|a|b + // x&(a&b) => x&a&b + // x^(a^b) => x^a^b if (operatorHasAssociativeProperty(binaryOperator)) { return false; } - if (binaryOperator === 37) { - var leftKind = leftOperand ? getLiteralKindOfBinaryPlusOperand(leftOperand) : 0; + // No need to parenthesize the right operand when the binary operator + // is plus (+) if both the left and right operands consist solely of either + // literals of the same kind or binary plus (+) expressions for literals of + // the same kind (recursively). + // "a"+(1+2) => "a"+(1+2) + // "a"+("b"+"c") => "a"+"b"+"c" + if (binaryOperator === 37 /* PlusToken */) { + var leftKind = leftOperand ? getLiteralKindOfBinaryPlusOperand(leftOperand) : 0 /* Unknown */; if (ts.isLiteralKind(leftKind) && leftKind === getLiteralKindOfBinaryPlusOperand(emittedOperand)) { return false; } } } + // No need to parenthesize the right operand when the operand is right + // associative: + // x/(a**b) -> x/a**b + // x**(a**b) -> x**a**b + // + // Parentheses are needed for the right operand when the operand is left + // associative: + // x/(a*b) -> x/(a*b) + // x**(a/b) -> x**(a/b) var operandAssociativity = ts.getExpressionAssociativity(emittedOperand); - return operandAssociativity === 0; + return operandAssociativity === 0 /* Left */; } } } + /** + * Determines whether a binary operator is mathematically associative. + * + * @param binaryOperator The binary operator. + */ function operatorHasAssociativeProperty(binaryOperator) { - return binaryOperator === 39 - || binaryOperator === 49 - || binaryOperator === 48 - || binaryOperator === 50; + // The following operators are associative in JavaScript: + // (a*b)*c -> a*(b*c) -> a*b*c + // (a|b)|c -> a|(b|c) -> a|b|c + // (a&b)&c -> a&(b&c) -> a&b&c + // (a^b)^c -> a^(b^c) -> a^b^c + // + // While addition is associative in mathematics, JavaScript's `+` is not + // guaranteed to be associative as it is overloaded with string concatenation. + return binaryOperator === 39 /* AsteriskToken */ + || binaryOperator === 49 /* BarToken */ + || binaryOperator === 48 /* AmpersandToken */ + || binaryOperator === 50 /* CaretToken */; } + /** + * This function determines whether an expression consists of a homogeneous set of + * literal expressions or binary plus expressions that all share the same literal kind. + * It is used to determine whether the right-hand operand of a binary plus expression can be + * emitted without parentheses. + */ function getLiteralKindOfBinaryPlusOperand(node) { node = ts.skipPartiallyEmittedExpressions(node); if (ts.isLiteralKind(node.kind)) { return node.kind; } - if (node.kind === 200 && node.operatorToken.kind === 37) { + if (node.kind === 200 /* BinaryExpression */ && node.operatorToken.kind === 37 /* PlusToken */) { if (node.cachedLiteralKind !== undefined) { return node.cachedLiteralKind; } @@ -50637,46 +58805,66 @@ var ts; var literalKind = ts.isLiteralKind(leftKind) && leftKind === getLiteralKindOfBinaryPlusOperand(node.right) ? leftKind - : 0; + : 0 /* Unknown */; node.cachedLiteralKind = literalKind; return literalKind; } - return 0; + return 0 /* Unknown */; } function parenthesizeForConditionalHead(condition) { - var conditionalPrecedence = ts.getOperatorPrecedence(201, 55); + var conditionalPrecedence = ts.getOperatorPrecedence(201 /* ConditionalExpression */, 55 /* QuestionToken */); var emittedCondition = ts.skipPartiallyEmittedExpressions(condition); var conditionPrecedence = ts.getExpressionPrecedence(emittedCondition); - if (ts.compareValues(conditionPrecedence, conditionalPrecedence) === -1) { + if (ts.compareValues(conditionPrecedence, conditionalPrecedence) === -1 /* LessThan */) { return ts.createParen(condition); } return condition; } ts.parenthesizeForConditionalHead = parenthesizeForConditionalHead; function parenthesizeSubexpressionOfConditionalExpression(e) { + // per ES grammar both 'whenTrue' and 'whenFalse' parts of conditional expression are assignment expressions + // so in case when comma expression is introduced as a part of previous transformations + // if should be wrapped in parens since comma operator has the lowest precedence var emittedExpression = ts.skipPartiallyEmittedExpressions(e); - return emittedExpression.kind === 200 && emittedExpression.operatorToken.kind === 26 || - emittedExpression.kind === 303 + return emittedExpression.kind === 200 /* BinaryExpression */ && emittedExpression.operatorToken.kind === 26 /* CommaToken */ || + emittedExpression.kind === 303 /* CommaListExpression */ ? ts.createParen(e) : e; } ts.parenthesizeSubexpressionOfConditionalExpression = parenthesizeSubexpressionOfConditionalExpression; + /** + * [Per the spec](https://tc39.github.io/ecma262/#prod-ExportDeclaration), `export default` accepts _AssigmentExpression_ but + * has a lookahead restriction for `function`, `async function`, and `class`. + * + * Basically, that means we need to parenthesize in the following cases: + * + * - BinaryExpression of CommaToken + * - CommaList (synthetic list of multiple comma expressions) + * - FunctionExpression + * - ClassExpression + */ function parenthesizeDefaultExpression(e) { var check = ts.skipPartiallyEmittedExpressions(e); - return (check.kind === 205 || - check.kind === 192 || - check.kind === 303 || - ts.isBinaryExpression(check) && check.operatorToken.kind === 26) + return (check.kind === 205 /* ClassExpression */ || + check.kind === 192 /* FunctionExpression */ || + check.kind === 303 /* CommaListExpression */ || + ts.isBinaryExpression(check) && check.operatorToken.kind === 26 /* CommaToken */) ? ts.createParen(e) : e; } ts.parenthesizeDefaultExpression = parenthesizeDefaultExpression; + /** + * Wraps an expression in parentheses if it is needed in order to use the expression + * as the expression of a NewExpression node. + * + * @param expression The Expression node. + */ function parenthesizeForNew(expression) { - var leftmostExpr = getLeftmostExpression(expression, true); + var leftmostExpr = getLeftmostExpression(expression, /*stopAtCallExpressions*/ true); switch (leftmostExpr.kind) { - case 187: + case 187 /* CallExpression */: return ts.createParen(expression); - case 188: + case 188 /* NewExpression */: return !leftmostExpr.arguments ? ts.createParen(expression) : expression; @@ -50684,10 +58872,22 @@ var ts; return parenthesizeForAccess(expression); } ts.parenthesizeForNew = parenthesizeForNew; + /** + * Wraps an expression in parentheses if it is needed in order to use the expression for + * property or element access. + * + * @param expr The expression node. + */ function parenthesizeForAccess(expression) { + // isLeftHandSideExpression is almost the correct criterion for when it is not necessary + // to parenthesize the expression before a dot. The known exception is: + // + // NewExpression: + // new C.x -> not the same as (new C).x + // var emittedExpression = ts.skipPartiallyEmittedExpressions(expression); if (ts.isLeftHandSideExpression(emittedExpression) - && (emittedExpression.kind !== 188 || emittedExpression.arguments)) { + && (emittedExpression.kind !== 188 /* NewExpression */ || emittedExpression.arguments)) { return expression; } return ts.setTextRange(ts.createParen(expression), expression); @@ -50725,7 +58925,7 @@ var ts; function parenthesizeExpressionForList(expression) { var emittedExpression = ts.skipPartiallyEmittedExpressions(expression); var expressionPrecedence = ts.getExpressionPrecedence(emittedExpression); - var commaPrecedence = ts.getOperatorPrecedence(200, 26); + var commaPrecedence = ts.getOperatorPrecedence(200 /* BinaryExpression */, 26 /* CommaToken */); return expressionPrecedence > commaPrecedence ? expression : ts.setTextRange(ts.createParen(expression), expression); @@ -50736,29 +58936,29 @@ var ts; if (ts.isCallExpression(emittedExpression)) { var callee = emittedExpression.expression; var kind = ts.skipPartiallyEmittedExpressions(callee).kind; - if (kind === 192 || kind === 193) { + if (kind === 192 /* FunctionExpression */ || kind === 193 /* ArrowFunction */) { var mutableCall = ts.getMutableClone(emittedExpression); mutableCall.expression = ts.setTextRange(ts.createParen(callee), callee); - return recreateOuterExpressions(expression, mutableCall, 4); + return recreateOuterExpressions(expression, mutableCall, 4 /* PartiallyEmittedExpressions */); } } - var leftmostExpressionKind = getLeftmostExpression(emittedExpression, false).kind; - if (leftmostExpressionKind === 184 || leftmostExpressionKind === 192) { + var leftmostExpressionKind = getLeftmostExpression(emittedExpression, /*stopAtCallExpressions*/ false).kind; + if (leftmostExpressionKind === 184 /* ObjectLiteralExpression */ || leftmostExpressionKind === 192 /* FunctionExpression */) { return ts.setTextRange(ts.createParen(expression), expression); } return expression; } ts.parenthesizeExpressionForExpressionStatement = parenthesizeExpressionForExpressionStatement; function parenthesizeConditionalTypeMember(member) { - return member.kind === 171 ? ts.createParenthesizedType(member) : member; + return member.kind === 171 /* ConditionalType */ ? ts.createParenthesizedType(member) : member; } ts.parenthesizeConditionalTypeMember = parenthesizeConditionalTypeMember; function parenthesizeElementTypeMember(member) { switch (member.kind) { - case 169: - case 170: - case 163: - case 164: + case 169 /* UnionType */: + case 170 /* IntersectionType */: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: return ts.createParenthesizedType(member); } return parenthesizeConditionalTypeMember(member); @@ -50766,9 +58966,9 @@ var ts; ts.parenthesizeElementTypeMember = parenthesizeElementTypeMember; function parenthesizeArrayTypeMember(member) { switch (member.kind) { - case 165: - case 175: - case 172: + case 165 /* TypeQuery */: + case 175 /* TypeOperator */: + case 172 /* InferType */: return ts.createParenthesizedType(member); } return parenthesizeElementTypeMember(member); @@ -50794,24 +58994,25 @@ var ts; function getLeftmostExpression(node, stopAtCallExpressions) { while (true) { switch (node.kind) { - case 199: + case 199 /* PostfixUnaryExpression */: node = node.operand; continue; - case 200: + case 200 /* BinaryExpression */: node = node.left; continue; - case 201: + case 201 /* ConditionalExpression */: node = node.condition; continue; - case 187: + case 187 /* CallExpression */: if (stopAtCallExpressions) { return node; } - case 186: - case 185: + // falls through + case 186 /* ElementAccessExpression */: + case 185 /* PropertyAccessExpression */: node = node.expression; continue; - case 302: + case 302 /* PartiallyEmittedExpression */: node = node.expression; continue; } @@ -50819,7 +59020,7 @@ var ts; } } function parenthesizeConciseBody(body) { - if (!ts.isBlock(body) && getLeftmostExpression(body, false).kind === 184) { + if (!ts.isBlock(body) && getLeftmostExpression(body, /*stopAtCallExpressions*/ false).kind === 184 /* ObjectLiteralExpression */) { return ts.setTextRange(ts.createParen(body), body); } return body; @@ -50833,32 +59034,32 @@ var ts; OuterExpressionKinds[OuterExpressionKinds["All"] = 7] = "All"; })(OuterExpressionKinds = ts.OuterExpressionKinds || (ts.OuterExpressionKinds = {})); function isOuterExpression(node, kinds) { - if (kinds === void 0) { kinds = 7; } + if (kinds === void 0) { kinds = 7 /* All */; } switch (node.kind) { - case 191: - return (kinds & 1) !== 0; - case 190: - case 208: - case 209: - return (kinds & 2) !== 0; - case 302: - return (kinds & 4) !== 0; + case 191 /* ParenthesizedExpression */: + return (kinds & 1 /* Parentheses */) !== 0; + case 190 /* TypeAssertionExpression */: + case 208 /* AsExpression */: + case 209 /* NonNullExpression */: + return (kinds & 2 /* Assertions */) !== 0; + case 302 /* PartiallyEmittedExpression */: + return (kinds & 4 /* PartiallyEmittedExpressions */) !== 0; } return false; } ts.isOuterExpression = isOuterExpression; function skipOuterExpressions(node, kinds) { - if (kinds === void 0) { kinds = 7; } + if (kinds === void 0) { kinds = 7 /* All */; } var previousNode; do { previousNode = node; - if (kinds & 1) { + if (kinds & 1 /* Parentheses */) { node = ts.skipParentheses(node); } - if (kinds & 2) { + if (kinds & 2 /* Assertions */) { node = skipAssertions(node); } - if (kinds & 4) { + if (kinds & 4 /* PartiallyEmittedExpressions */) { node = ts.skipPartiallyEmittedExpressions(node); } } while (previousNode !== node); @@ -50866,7 +59067,7 @@ var ts; } ts.skipOuterExpressions = skipOuterExpressions; function skipAssertions(node) { - while (ts.isAssertionExpression(node) || node.kind === 209) { + while (ts.isAssertionExpression(node) || node.kind === 209 /* NonNullExpression */) { node = node.expression; } return node; @@ -50874,15 +59075,29 @@ var ts; ts.skipAssertions = skipAssertions; function updateOuterExpression(outerExpression, expression) { switch (outerExpression.kind) { - case 191: return ts.updateParen(outerExpression, expression); - case 190: return ts.updateTypeAssertion(outerExpression, outerExpression.type, expression); - case 208: return ts.updateAsExpression(outerExpression, expression, outerExpression.type); - case 209: return ts.updateNonNullExpression(outerExpression, expression); - case 302: return ts.updatePartiallyEmittedExpression(outerExpression, expression); + case 191 /* ParenthesizedExpression */: return ts.updateParen(outerExpression, expression); + case 190 /* TypeAssertionExpression */: return ts.updateTypeAssertion(outerExpression, outerExpression.type, expression); + case 208 /* AsExpression */: return ts.updateAsExpression(outerExpression, expression, outerExpression.type); + case 209 /* NonNullExpression */: return ts.updateNonNullExpression(outerExpression, expression); + case 302 /* PartiallyEmittedExpression */: return ts.updatePartiallyEmittedExpression(outerExpression, expression); } } + /** + * Determines whether a node is a parenthesized expression that can be ignored when recreating outer expressions. + * + * A parenthesized expression can be ignored when all of the following are true: + * + * - It's `pos` and `end` are not -1 + * - It does not have a custom source map range + * - It does not have a custom comment range + * - It does not have synthetic leading or trailing comments + * + * If an outermost parenthesized expression is ignored, but the containing expression requires a parentheses around + * the expression to maintain precedence, a new parenthesized expression should be created automatically when + * the containing expression is created/updated. + */ function isIgnorableParen(node) { - return node.kind === 191 + return node.kind === 191 /* ParenthesizedExpression */ && ts.nodeIsSynthesized(node) && ts.nodeIsSynthesized(ts.getSourceMapRange(node)) && ts.nodeIsSynthesized(ts.getCommentRange(node)) @@ -50890,7 +59105,7 @@ var ts; && !ts.some(ts.getSyntheticTrailingComments(node)); } function recreateOuterExpressions(outerExpression, innerExpression, kinds) { - if (kinds === void 0) { kinds = 7; } + if (kinds === void 0) { kinds = 7 /* All */; } if (outerExpression && isOuterExpression(outerExpression, kinds) && !isIgnorableParen(outerExpression)) { return updateOuterExpression(outerExpression, recreateOuterExpressions(outerExpression.expression, innerExpression)); } @@ -50898,7 +59113,7 @@ var ts; } ts.recreateOuterExpressions = recreateOuterExpressions; function startOnNewLine(node) { - return ts.setStartsOnNewLine(node, true); + return ts.setStartsOnNewLine(node, /*newLine*/ true); } ts.startOnNewLine = startOnNewLine; function getExternalHelpersModuleName(node) { @@ -50938,24 +59153,35 @@ var ts; } } ts.getOrCreateExternalHelpersModuleNameIfNeeded = getOrCreateExternalHelpersModuleNameIfNeeded; + /** + * Get the name of that target module from an import or export declaration + */ function getLocalNameForExternalImport(node, sourceFile) { var namespaceDeclaration = ts.getNamespaceDeclarationNode(node); if (namespaceDeclaration && !ts.isDefaultImport(node)) { var name = namespaceDeclaration.name; return ts.isGeneratedIdentifier(name) ? name : ts.createIdentifier(ts.getSourceTextOfNodeFromSourceFile(sourceFile, name) || ts.idText(name)); } - if (node.kind === 244 && node.importClause) { + if (node.kind === 244 /* ImportDeclaration */ && node.importClause) { return ts.getGeneratedNameForNode(node); } - if (node.kind === 250 && node.moduleSpecifier) { + if (node.kind === 250 /* ExportDeclaration */ && node.moduleSpecifier) { return ts.getGeneratedNameForNode(node); } return undefined; } ts.getLocalNameForExternalImport = getLocalNameForExternalImport; + /** + * Get the name of a target module from an import/export declaration as should be written in the emitted output. + * The emitted output name can be different from the input if: + * 1. The module has a /// + * 2. --out or --outFile is used, making the name relative to the rootDir + * 3- The containing SourceFile has an entry in renamedDependencies for the import as requested by some module loaders (e.g. System). + * Otherwise, a new StringLiteral node representing the module name will be returned. + */ function getExternalModuleNameLiteral(importNode, sourceFile, host, resolver, compilerOptions) { - var moduleName = ts.getExternalModuleName(importNode); - if (moduleName.kind === 9) { + var moduleName = ts.getExternalModuleName(importNode); // TODO: GH#18217 + if (moduleName.kind === 9 /* StringLiteral */) { return tryGetModuleNameFromDeclaration(importNode, host, resolver, compilerOptions) || tryRenameExternalModule(moduleName, sourceFile) || ts.getSynthesizedClone(moduleName); @@ -50963,10 +59189,21 @@ var ts; return undefined; } ts.getExternalModuleNameLiteral = getExternalModuleNameLiteral; + /** + * 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, sourceFile) { var rename = sourceFile.renamedDependencies && sourceFile.renamedDependencies.get(moduleName.text); return rename && ts.createLiteral(rename); } + /** + * Get the name of a module as should be written in the emitted output. + * The emitted output name can be different from the input if: + * 1. The module has a /// + * 2. --out or --outFile is used, making the name relative to the rootDir + * Otherwise, a new StringLiteral node representing the module name will be returned. + */ function tryGetModuleNameFromFile(file, host, options) { if (!file) { return undefined; @@ -50983,66 +59220,140 @@ var ts; function tryGetModuleNameFromDeclaration(declaration, host, resolver, compilerOptions) { return tryGetModuleNameFromFile(resolver.getExternalModuleFileFromDeclaration(declaration), host, compilerOptions); } + /** + * Gets the initializer of an BindingOrAssignmentElement. + */ function getInitializerOfBindingOrAssignmentElement(bindingElement) { if (ts.isDeclarationBindingElement(bindingElement)) { + // `1` in `let { a = 1 } = ...` + // `1` in `let { a: b = 1 } = ...` + // `1` in `let { a: {b} = 1 } = ...` + // `1` in `let { a: [b] = 1 } = ...` + // `1` in `let [a = 1] = ...` + // `1` in `let [{a} = 1] = ...` + // `1` in `let [[a] = 1] = ...` return bindingElement.initializer; } if (ts.isPropertyAssignment(bindingElement)) { + // `1` in `({ a: b = 1 } = ...)` + // `1` in `({ a: {b} = 1 } = ...)` + // `1` in `({ a: [b] = 1 } = ...)` var initializer = bindingElement.initializer; - return ts.isAssignmentExpression(initializer, true) + return ts.isAssignmentExpression(initializer, /*excludeCompoundAssignment*/ true) ? initializer.right : undefined; } if (ts.isShorthandPropertyAssignment(bindingElement)) { + // `1` in `({ a = 1 } = ...)` return bindingElement.objectAssignmentInitializer; } - if (ts.isAssignmentExpression(bindingElement, true)) { + if (ts.isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) { + // `1` in `[a = 1] = ...` + // `1` in `[{a} = 1] = ...` + // `1` in `[[a] = 1] = ...` return bindingElement.right; } if (ts.isSpreadElement(bindingElement)) { + // Recovery consistent with existing emit. return getInitializerOfBindingOrAssignmentElement(bindingElement.expression); } } ts.getInitializerOfBindingOrAssignmentElement = getInitializerOfBindingOrAssignmentElement; + /** + * Gets the name of an BindingOrAssignmentElement. + */ function getTargetOfBindingOrAssignmentElement(bindingElement) { if (ts.isDeclarationBindingElement(bindingElement)) { + // `a` in `let { a } = ...` + // `a` in `let { a = 1 } = ...` + // `b` in `let { a: b } = ...` + // `b` in `let { a: b = 1 } = ...` + // `a` in `let { ...a } = ...` + // `{b}` in `let { a: {b} } = ...` + // `{b}` in `let { a: {b} = 1 } = ...` + // `[b]` in `let { a: [b] } = ...` + // `[b]` in `let { a: [b] = 1 } = ...` + // `a` in `let [a] = ...` + // `a` in `let [a = 1] = ...` + // `a` in `let [...a] = ...` + // `{a}` in `let [{a}] = ...` + // `{a}` in `let [{a} = 1] = ...` + // `[a]` in `let [[a]] = ...` + // `[a]` in `let [[a] = 1] = ...` return bindingElement.name; } if (ts.isObjectLiteralElementLike(bindingElement)) { switch (bindingElement.kind) { - case 270: + case 270 /* PropertyAssignment */: + // `b` in `({ a: b } = ...)` + // `b` in `({ a: b = 1 } = ...)` + // `{b}` in `({ a: {b} } = ...)` + // `{b}` in `({ a: {b} = 1 } = ...)` + // `[b]` in `({ a: [b] } = ...)` + // `[b]` in `({ a: [b] = 1 } = ...)` + // `b.c` in `({ a: b.c } = ...)` + // `b.c` in `({ a: b.c = 1 } = ...)` + // `b[0]` in `({ a: b[0] } = ...)` + // `b[0]` in `({ a: b[0] = 1 } = ...)` return getTargetOfBindingOrAssignmentElement(bindingElement.initializer); - case 271: + case 271 /* ShorthandPropertyAssignment */: + // `a` in `({ a } = ...)` + // `a` in `({ a = 1 } = ...)` return bindingElement.name; - case 272: + case 272 /* SpreadAssignment */: + // `a` in `({ ...a } = ...)` return getTargetOfBindingOrAssignmentElement(bindingElement.expression); } + // no target return undefined; } - if (ts.isAssignmentExpression(bindingElement, true)) { + if (ts.isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) { + // `a` in `[a = 1] = ...` + // `{a}` in `[{a} = 1] = ...` + // `[a]` in `[[a] = 1] = ...` + // `a.b` in `[a.b = 1] = ...` + // `a[0]` in `[a[0] = 1] = ...` return getTargetOfBindingOrAssignmentElement(bindingElement.left); } if (ts.isSpreadElement(bindingElement)) { + // `a` in `[...a] = ...` return getTargetOfBindingOrAssignmentElement(bindingElement.expression); } + // `a` in `[a] = ...` + // `{a}` in `[{a}] = ...` + // `[a]` in `[[a]] = ...` + // `a.b` in `[a.b] = ...` + // `a[0]` in `[a[0]] = ...` return bindingElement; } ts.getTargetOfBindingOrAssignmentElement = getTargetOfBindingOrAssignmentElement; + /** + * Determines whether an BindingOrAssignmentElement is a rest element. + */ function getRestIndicatorOfBindingOrAssignmentElement(bindingElement) { switch (bindingElement.kind) { - case 149: - case 182: + case 149 /* Parameter */: + case 182 /* BindingElement */: + // `...` in `let [...a] = ...` return bindingElement.dotDotDotToken; - case 204: - case 272: + case 204 /* SpreadElement */: + case 272 /* SpreadAssignment */: + // `...` in `[...a] = ...` return bindingElement; } return undefined; } ts.getRestIndicatorOfBindingOrAssignmentElement = getRestIndicatorOfBindingOrAssignmentElement; + /** + * Gets the property name of a BindingOrAssignmentElement + */ function getPropertyNameOfBindingOrAssignmentElement(bindingElement) { switch (bindingElement.kind) { - case 182: + case 182 /* BindingElement */: + // `a` in `let { a: b } = ...` + // `[a]` in `let { [a]: b } = ...` + // `"a"` in `let { "a": b } = ...` + // `1` in `let { 1: b } = ...` if (bindingElement.propertyName) { var propertyName = bindingElement.propertyName; return ts.isComputedPropertyName(propertyName) && ts.isStringOrNumericLiteral(propertyName.expression) @@ -51050,7 +59361,11 @@ var ts; : propertyName; } break; - case 270: + case 270 /* PropertyAssignment */: + // `a` in `({ a: b } = ...)` + // `[a]` in `({ [a]: b } = ...)` + // `"a"` in `({ "a": b } = ...)` + // `1` in `({ 1: b } = ...)` if (bindingElement.name) { var propertyName = bindingElement.name; return ts.isComputedPropertyName(propertyName) && ts.isStringOrNumericLiteral(propertyName.expression) @@ -51058,7 +59373,8 @@ var ts; : propertyName; } break; - case 272: + case 272 /* SpreadAssignment */: + // `a` in `({ ...a } = ...)` return bindingElement.name; } var target = getTargetOfBindingOrAssignmentElement(bindingElement); @@ -51070,13 +59386,19 @@ var ts; ts.Debug.fail("Invalid property name for binding element."); } ts.getPropertyNameOfBindingOrAssignmentElement = getPropertyNameOfBindingOrAssignmentElement; + /** + * Gets the elements of a BindingOrAssignmentPattern + */ function getElementsOfBindingOrAssignmentPattern(name) { switch (name.kind) { - case 180: - case 181: - case 183: + case 180 /* ObjectBindingPattern */: + case 181 /* ArrayBindingPattern */: + case 183 /* ArrayLiteralExpression */: + // `a` in `{a}` + // `a` in `[a]` return name.elements; - case 184: + case 184 /* ObjectLiteralExpression */: + // `a` in `{a}` return name.properties; } } @@ -51115,11 +59437,11 @@ var ts; ts.convertToObjectAssignmentElement = convertToObjectAssignmentElement; function convertToAssignmentPattern(node) { switch (node.kind) { - case 181: - case 183: + case 181 /* ArrayBindingPattern */: + case 183 /* ArrayLiteralExpression */: return convertToArrayAssignmentPattern(node); - case 180: - case 184: + case 180 /* ObjectBindingPattern */: + case 184 /* ObjectLiteralExpression */: return convertToObjectAssignmentPattern(node); } } @@ -51176,11 +59498,21 @@ var ts; return visitedNode; } ts.visitNode = visitNode; + /** + * Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place. + * + * @param nodes The NodeArray to visit. + * @param visitor The callback used to visit a Node. + * @param test A node test to execute for each node. + * @param start An optional value indicating the starting offset at which to start visiting. + * @param count An optional value indicating the maximum number of nodes to visit. + */ function visitNodes(nodes, visitor, test, start, count) { if (nodes === undefined || visitor === undefined) { return nodes; } var updated; + // Ensure start and count have valid values var length = nodes.length; if (start === undefined || start < 0) { start = 0; @@ -51189,14 +59521,19 @@ var ts; count = length - start; } if (start > 0 || count < length) { - updated = ts.createNodeArray([], nodes.hasTrailingComma && start + count === length); + // If we are not visiting all of the original nodes, we must always create a new array. + // Since this is a fragment of a node array, we do not copy over the previous location + // and will only copy over `hasTrailingComma` if we are including the last element. + updated = ts.createNodeArray([], /*hasTrailingComma*/ nodes.hasTrailingComma && start + count === length); } + // Visit each original node. for (var i = 0; i < count; i++) { var node = nodes[i + start]; ts.aggregateTransformFlags(node); var visited = node !== undefined ? visitor(node) : undefined; if (updated !== undefined || visited === undefined || visited !== node) { if (updated === undefined) { + // Ensure we have a copy of `nodes`, up to the current index. updated = ts.createNodeArray(nodes.slice(0, i), nodes.hasTrailingComma); ts.setTextRange(updated, nodes); } @@ -51220,6 +59557,10 @@ var ts; return updated || nodes; } ts.visitNodes = visitNodes; + /** + * Starts a new lexical environment and visits a statement list, ending the lexical environment + * and merging hoisted declarations upon completion. + */ function visitLexicalEnvironment(statements, visitor, context, start, ensureUseStrict) { context.startLexicalEnvironment(); statements = visitNodes(statements, visitor, ts.isStatement, start); @@ -51230,6 +59571,10 @@ var ts; return ts.setTextRange(ts.createNodeArray(ts.concatenate(declarations, statements)), statements); } ts.visitLexicalEnvironment = visitLexicalEnvironment; + /** + * Starts a new lexical environment and visits a parameter list, suspending the lexical + * environment upon completion. + */ function visitParameterList(nodes, visitor, context, nodesVisitor) { if (nodesVisitor === void 0) { nodesVisitor = visitNodes; } context.startLexicalEnvironment(); @@ -51256,268 +59601,291 @@ var ts; return undefined; } var kind = node.kind; - if ((kind > 0 && kind <= 145) || kind === 174) { + // No need to visit nodes with no children. + if ((kind > 0 /* FirstToken */ && kind <= 145 /* LastToken */) || kind === 174 /* ThisType */) { return node; } switch (kind) { - case 71: + // Names + case 71 /* Identifier */: return ts.updateIdentifier(node, nodesVisitor(node.typeArguments, visitor, isTypeNodeOrTypeParameterDeclaration)); - case 146: + case 146 /* QualifiedName */: return ts.updateQualifiedName(node, visitNode(node.left, visitor, ts.isEntityName), visitNode(node.right, visitor, ts.isIdentifier)); - case 147: + case 147 /* ComputedPropertyName */: return ts.updateComputedPropertyName(node, visitNode(node.expression, visitor, ts.isExpression)); - case 148: + // Signature elements + case 148 /* TypeParameter */: return ts.updateTypeParameterDeclaration(node, visitNode(node.name, visitor, ts.isIdentifier), visitNode(node.constraint, visitor, ts.isTypeNode), visitNode(node.default, visitor, ts.isTypeNode)); - case 149: + case 149 /* Parameter */: return ts.updateParameter(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.dotDotDotToken, tokenVisitor, ts.isToken), visitNode(node.name, visitor, ts.isBindingName), visitNode(node.questionToken, tokenVisitor, ts.isToken), visitNode(node.type, visitor, ts.isTypeNode), visitNode(node.initializer, visitor, ts.isExpression)); - case 150: + case 150 /* Decorator */: return ts.updateDecorator(node, visitNode(node.expression, visitor, ts.isExpression)); - case 151: + // Type elements + case 151 /* PropertySignature */: return ts.updatePropertySignature(node, nodesVisitor(node.modifiers, visitor, ts.isToken), visitNode(node.name, visitor, ts.isPropertyName), visitNode(node.questionToken, tokenVisitor, ts.isToken), visitNode(node.type, visitor, ts.isTypeNode), visitNode(node.initializer, visitor, ts.isExpression)); - case 152: + case 152 /* PropertyDeclaration */: return ts.updateProperty(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isPropertyName), visitNode(node.questionToken, tokenVisitor, ts.isToken), visitNode(node.type, visitor, ts.isTypeNode), visitNode(node.initializer, visitor, ts.isExpression)); - case 153: + case 153 /* MethodSignature */: return ts.updateMethodSignature(node, nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), nodesVisitor(node.parameters, visitor, ts.isParameterDeclaration), visitNode(node.type, visitor, ts.isTypeNode), visitNode(node.name, visitor, ts.isPropertyName), visitNode(node.questionToken, tokenVisitor, ts.isToken)); - case 154: + case 154 /* MethodDeclaration */: return ts.updateMethod(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.asteriskToken, tokenVisitor, ts.isToken), visitNode(node.name, visitor, ts.isPropertyName), visitNode(node.questionToken, tokenVisitor, ts.isToken), nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), visitParameterList(node.parameters, visitor, context, nodesVisitor), visitNode(node.type, visitor, ts.isTypeNode), visitFunctionBody(node.body, visitor, context)); - case 155: + case 155 /* Constructor */: return ts.updateConstructor(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitParameterList(node.parameters, visitor, context, nodesVisitor), visitFunctionBody(node.body, visitor, context)); - case 156: + case 156 /* GetAccessor */: return ts.updateGetAccessor(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isPropertyName), visitParameterList(node.parameters, visitor, context, nodesVisitor), visitNode(node.type, visitor, ts.isTypeNode), visitFunctionBody(node.body, visitor, context)); - case 157: + case 157 /* SetAccessor */: return ts.updateSetAccessor(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isPropertyName), visitParameterList(node.parameters, visitor, context, nodesVisitor), visitFunctionBody(node.body, visitor, context)); - case 158: + case 158 /* CallSignature */: return ts.updateCallSignature(node, nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), nodesVisitor(node.parameters, visitor, ts.isParameterDeclaration), visitNode(node.type, visitor, ts.isTypeNode)); - case 159: + case 159 /* ConstructSignature */: return ts.updateConstructSignature(node, nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), nodesVisitor(node.parameters, visitor, ts.isParameterDeclaration), visitNode(node.type, visitor, ts.isTypeNode)); - case 160: + case 160 /* IndexSignature */: return ts.updateIndexSignature(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), nodesVisitor(node.parameters, visitor, ts.isParameterDeclaration), visitNode(node.type, visitor, ts.isTypeNode)); - case 161: + // Types + case 161 /* TypePredicate */: return ts.updateTypePredicateNode(node, visitNode(node.parameterName, visitor), visitNode(node.type, visitor, ts.isTypeNode)); - case 162: + case 162 /* TypeReference */: return ts.updateTypeReferenceNode(node, visitNode(node.typeName, visitor, ts.isEntityName), nodesVisitor(node.typeArguments, visitor, ts.isTypeNode)); - case 163: + case 163 /* FunctionType */: return ts.updateFunctionTypeNode(node, nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), nodesVisitor(node.parameters, visitor, ts.isParameterDeclaration), visitNode(node.type, visitor, ts.isTypeNode)); - case 164: + case 164 /* ConstructorType */: return ts.updateConstructorTypeNode(node, nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), nodesVisitor(node.parameters, visitor, ts.isParameterDeclaration), visitNode(node.type, visitor, ts.isTypeNode)); - case 165: + case 165 /* TypeQuery */: return ts.updateTypeQueryNode(node, visitNode(node.exprName, visitor, ts.isEntityName)); - case 166: + case 166 /* TypeLiteral */: return ts.updateTypeLiteralNode(node, nodesVisitor(node.members, visitor, ts.isTypeElement)); - case 167: + case 167 /* ArrayType */: return ts.updateArrayTypeNode(node, visitNode(node.elementType, visitor, ts.isTypeNode)); - case 168: + case 168 /* TupleType */: return ts.updateTypleTypeNode(node, nodesVisitor(node.elementTypes, visitor, ts.isTypeNode)); - case 169: + case 169 /* UnionType */: return ts.updateUnionTypeNode(node, nodesVisitor(node.types, visitor, ts.isTypeNode)); - case 170: + case 170 /* IntersectionType */: return ts.updateIntersectionTypeNode(node, nodesVisitor(node.types, visitor, ts.isTypeNode)); - case 171: + case 171 /* ConditionalType */: return ts.updateConditionalTypeNode(node, visitNode(node.checkType, visitor, ts.isTypeNode), visitNode(node.extendsType, visitor, ts.isTypeNode), visitNode(node.trueType, visitor, ts.isTypeNode), visitNode(node.falseType, visitor, ts.isTypeNode)); - case 172: + case 172 /* InferType */: return ts.updateInferTypeNode(node, visitNode(node.typeParameter, visitor, ts.isTypeParameterDeclaration)); - case 179: + case 179 /* ImportType */: return ts.updateImportTypeNode(node, visitNode(node.argument, visitor, ts.isTypeNode), visitNode(node.qualifier, visitor, ts.isEntityName), visitNodes(node.typeArguments, visitor, ts.isTypeNode), node.isTypeOf); - case 173: + case 173 /* ParenthesizedType */: return ts.updateParenthesizedType(node, visitNode(node.type, visitor, ts.isTypeNode)); - case 175: + case 175 /* TypeOperator */: return ts.updateTypeOperatorNode(node, visitNode(node.type, visitor, ts.isTypeNode)); - case 176: + case 176 /* IndexedAccessType */: return ts.updateIndexedAccessTypeNode(node, visitNode(node.objectType, visitor, ts.isTypeNode), visitNode(node.indexType, visitor, ts.isTypeNode)); - case 177: + case 177 /* MappedType */: return ts.updateMappedTypeNode(node, visitNode(node.readonlyToken, tokenVisitor, ts.isToken), visitNode(node.typeParameter, visitor, ts.isTypeParameterDeclaration), visitNode(node.questionToken, tokenVisitor, ts.isToken), visitNode(node.type, visitor, ts.isTypeNode)); - case 178: + case 178 /* LiteralType */: return ts.updateLiteralTypeNode(node, visitNode(node.literal, visitor, ts.isExpression)); - case 180: + // Binding patterns + case 180 /* ObjectBindingPattern */: return ts.updateObjectBindingPattern(node, nodesVisitor(node.elements, visitor, ts.isBindingElement)); - case 181: + case 181 /* ArrayBindingPattern */: return ts.updateArrayBindingPattern(node, nodesVisitor(node.elements, visitor, ts.isArrayBindingElement)); - case 182: + case 182 /* BindingElement */: return ts.updateBindingElement(node, visitNode(node.dotDotDotToken, tokenVisitor, ts.isToken), visitNode(node.propertyName, visitor, ts.isPropertyName), visitNode(node.name, visitor, ts.isBindingName), visitNode(node.initializer, visitor, ts.isExpression)); - case 183: + // Expression + case 183 /* ArrayLiteralExpression */: return ts.updateArrayLiteral(node, nodesVisitor(node.elements, visitor, ts.isExpression)); - case 184: + case 184 /* ObjectLiteralExpression */: return ts.updateObjectLiteral(node, nodesVisitor(node.properties, visitor, ts.isObjectLiteralElementLike)); - case 185: + case 185 /* PropertyAccessExpression */: return ts.updatePropertyAccess(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.name, visitor, ts.isIdentifier)); - case 186: + case 186 /* ElementAccessExpression */: return ts.updateElementAccess(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.argumentExpression, visitor, ts.isExpression)); - case 187: + case 187 /* CallExpression */: return ts.updateCall(node, visitNode(node.expression, visitor, ts.isExpression), nodesVisitor(node.typeArguments, visitor, ts.isTypeNode), nodesVisitor(node.arguments, visitor, ts.isExpression)); - case 188: + case 188 /* NewExpression */: return ts.updateNew(node, visitNode(node.expression, visitor, ts.isExpression), nodesVisitor(node.typeArguments, visitor, ts.isTypeNode), nodesVisitor(node.arguments, visitor, ts.isExpression)); - case 189: + case 189 /* TaggedTemplateExpression */: return ts.updateTaggedTemplate(node, visitNode(node.tag, visitor, ts.isExpression), visitNodes(node.typeArguments, visitor, ts.isExpression), visitNode(node.template, visitor, ts.isTemplateLiteral)); - case 190: + case 190 /* TypeAssertionExpression */: return ts.updateTypeAssertion(node, visitNode(node.type, visitor, ts.isTypeNode), visitNode(node.expression, visitor, ts.isExpression)); - case 191: + case 191 /* ParenthesizedExpression */: return ts.updateParen(node, visitNode(node.expression, visitor, ts.isExpression)); - case 192: + case 192 /* FunctionExpression */: return ts.updateFunctionExpression(node, nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.asteriskToken, tokenVisitor, ts.isToken), visitNode(node.name, visitor, ts.isIdentifier), nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), visitParameterList(node.parameters, visitor, context, nodesVisitor), visitNode(node.type, visitor, ts.isTypeNode), visitFunctionBody(node.body, visitor, context)); - case 193: + case 193 /* ArrowFunction */: return ts.updateArrowFunction(node, nodesVisitor(node.modifiers, visitor, ts.isModifier), nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), visitParameterList(node.parameters, visitor, context, nodesVisitor), visitNode(node.type, visitor, ts.isTypeNode), visitNode(node.equalsGreaterThanToken, visitor, ts.isToken), visitFunctionBody(node.body, visitor, context)); - case 194: + case 194 /* DeleteExpression */: return ts.updateDelete(node, visitNode(node.expression, visitor, ts.isExpression)); - case 195: + case 195 /* TypeOfExpression */: return ts.updateTypeOf(node, visitNode(node.expression, visitor, ts.isExpression)); - case 196: + case 196 /* VoidExpression */: return ts.updateVoid(node, visitNode(node.expression, visitor, ts.isExpression)); - case 197: + case 197 /* AwaitExpression */: return ts.updateAwait(node, visitNode(node.expression, visitor, ts.isExpression)); - case 198: + case 198 /* PrefixUnaryExpression */: return ts.updatePrefix(node, visitNode(node.operand, visitor, ts.isExpression)); - case 199: + case 199 /* PostfixUnaryExpression */: return ts.updatePostfix(node, visitNode(node.operand, visitor, ts.isExpression)); - case 200: + case 200 /* BinaryExpression */: return ts.updateBinary(node, visitNode(node.left, visitor, ts.isExpression), visitNode(node.right, visitor, ts.isExpression), visitNode(node.operatorToken, visitor, ts.isToken)); - case 201: + case 201 /* ConditionalExpression */: return ts.updateConditional(node, visitNode(node.condition, visitor, ts.isExpression), visitNode(node.questionToken, visitor, ts.isToken), visitNode(node.whenTrue, visitor, ts.isExpression), visitNode(node.colonToken, visitor, ts.isToken), visitNode(node.whenFalse, visitor, ts.isExpression)); - case 202: + case 202 /* TemplateExpression */: return ts.updateTemplateExpression(node, visitNode(node.head, visitor, ts.isTemplateHead), nodesVisitor(node.templateSpans, visitor, ts.isTemplateSpan)); - case 203: + case 203 /* YieldExpression */: return ts.updateYield(node, visitNode(node.asteriskToken, tokenVisitor, ts.isToken), visitNode(node.expression, visitor, ts.isExpression)); - case 204: + case 204 /* SpreadElement */: return ts.updateSpread(node, visitNode(node.expression, visitor, ts.isExpression)); - case 205: + case 205 /* ClassExpression */: return ts.updateClassExpression(node, nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isIdentifier), nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), nodesVisitor(node.heritageClauses, visitor, ts.isHeritageClause), nodesVisitor(node.members, visitor, ts.isClassElement)); - case 207: + case 207 /* ExpressionWithTypeArguments */: return ts.updateExpressionWithTypeArguments(node, nodesVisitor(node.typeArguments, visitor, ts.isTypeNode), visitNode(node.expression, visitor, ts.isExpression)); - case 208: + case 208 /* AsExpression */: return ts.updateAsExpression(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.type, visitor, ts.isTypeNode)); - case 209: + case 209 /* NonNullExpression */: return ts.updateNonNullExpression(node, visitNode(node.expression, visitor, ts.isExpression)); - case 210: + case 210 /* MetaProperty */: return ts.updateMetaProperty(node, visitNode(node.name, visitor, ts.isIdentifier)); - case 211: + // Misc + case 211 /* TemplateSpan */: return ts.updateTemplateSpan(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.literal, visitor, ts.isTemplateMiddleOrTemplateTail)); - case 213: + // Element + case 213 /* Block */: return ts.updateBlock(node, nodesVisitor(node.statements, visitor, ts.isStatement)); - case 214: + case 214 /* VariableStatement */: return ts.updateVariableStatement(node, nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.declarationList, visitor, ts.isVariableDeclarationList)); - case 216: + case 216 /* ExpressionStatement */: return ts.updateStatement(node, visitNode(node.expression, visitor, ts.isExpression)); - case 217: + case 217 /* IfStatement */: return ts.updateIf(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.thenStatement, visitor, ts.isStatement, ts.liftToBlock), visitNode(node.elseStatement, visitor, ts.isStatement, ts.liftToBlock)); - case 218: + case 218 /* DoStatement */: return ts.updateDo(node, visitNode(node.statement, visitor, ts.isStatement, ts.liftToBlock), visitNode(node.expression, visitor, ts.isExpression)); - case 219: + case 219 /* WhileStatement */: return ts.updateWhile(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.statement, visitor, ts.isStatement, ts.liftToBlock)); - case 220: + case 220 /* ForStatement */: return ts.updateFor(node, visitNode(node.initializer, visitor, ts.isForInitializer), visitNode(node.condition, visitor, ts.isExpression), visitNode(node.incrementor, visitor, ts.isExpression), visitNode(node.statement, visitor, ts.isStatement, ts.liftToBlock)); - case 221: + case 221 /* ForInStatement */: return ts.updateForIn(node, visitNode(node.initializer, visitor, ts.isForInitializer), visitNode(node.expression, visitor, ts.isExpression), visitNode(node.statement, visitor, ts.isStatement, ts.liftToBlock)); - case 222: + case 222 /* ForOfStatement */: return ts.updateForOf(node, visitNode(node.awaitModifier, visitor, ts.isToken), visitNode(node.initializer, visitor, ts.isForInitializer), visitNode(node.expression, visitor, ts.isExpression), visitNode(node.statement, visitor, ts.isStatement, ts.liftToBlock)); - case 223: + case 223 /* ContinueStatement */: return ts.updateContinue(node, visitNode(node.label, visitor, ts.isIdentifier)); - case 224: + case 224 /* BreakStatement */: return ts.updateBreak(node, visitNode(node.label, visitor, ts.isIdentifier)); - case 225: + case 225 /* ReturnStatement */: return ts.updateReturn(node, visitNode(node.expression, visitor, ts.isExpression)); - case 226: + case 226 /* WithStatement */: return ts.updateWith(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.statement, visitor, ts.isStatement, ts.liftToBlock)); - case 227: + case 227 /* SwitchStatement */: return ts.updateSwitch(node, visitNode(node.expression, visitor, ts.isExpression), visitNode(node.caseBlock, visitor, ts.isCaseBlock)); - case 228: + case 228 /* LabeledStatement */: return ts.updateLabel(node, visitNode(node.label, visitor, ts.isIdentifier), visitNode(node.statement, visitor, ts.isStatement, ts.liftToBlock)); - case 229: + case 229 /* ThrowStatement */: return ts.updateThrow(node, visitNode(node.expression, visitor, ts.isExpression)); - case 230: + case 230 /* TryStatement */: return ts.updateTry(node, visitNode(node.tryBlock, visitor, ts.isBlock), visitNode(node.catchClause, visitor, ts.isCatchClause), visitNode(node.finallyBlock, visitor, ts.isBlock)); - case 232: + case 232 /* VariableDeclaration */: return ts.updateVariableDeclaration(node, visitNode(node.name, visitor, ts.isBindingName), visitNode(node.type, visitor, ts.isTypeNode), visitNode(node.initializer, visitor, ts.isExpression)); - case 233: + case 233 /* VariableDeclarationList */: return ts.updateVariableDeclarationList(node, nodesVisitor(node.declarations, visitor, ts.isVariableDeclaration)); - case 234: + case 234 /* FunctionDeclaration */: return ts.updateFunctionDeclaration(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.asteriskToken, tokenVisitor, ts.isToken), visitNode(node.name, visitor, ts.isIdentifier), nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), visitParameterList(node.parameters, visitor, context, nodesVisitor), visitNode(node.type, visitor, ts.isTypeNode), visitFunctionBody(node.body, visitor, context)); - case 235: + case 235 /* ClassDeclaration */: return ts.updateClassDeclaration(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isIdentifier), nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), nodesVisitor(node.heritageClauses, visitor, ts.isHeritageClause), nodesVisitor(node.members, visitor, ts.isClassElement)); - case 236: + case 236 /* InterfaceDeclaration */: return ts.updateInterfaceDeclaration(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isIdentifier), nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), nodesVisitor(node.heritageClauses, visitor, ts.isHeritageClause), nodesVisitor(node.members, visitor, ts.isTypeElement)); - case 237: + case 237 /* TypeAliasDeclaration */: return ts.updateTypeAliasDeclaration(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isIdentifier), nodesVisitor(node.typeParameters, visitor, ts.isTypeParameterDeclaration), visitNode(node.type, visitor, ts.isTypeNode)); - case 238: + case 238 /* EnumDeclaration */: return ts.updateEnumDeclaration(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isIdentifier), nodesVisitor(node.members, visitor, ts.isEnumMember)); - case 239: + case 239 /* ModuleDeclaration */: return ts.updateModuleDeclaration(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isIdentifier), visitNode(node.body, visitor, ts.isModuleBody)); - case 240: + case 240 /* ModuleBlock */: return ts.updateModuleBlock(node, nodesVisitor(node.statements, visitor, ts.isStatement)); - case 241: + case 241 /* CaseBlock */: return ts.updateCaseBlock(node, nodesVisitor(node.clauses, visitor, ts.isCaseOrDefaultClause)); - case 242: + case 242 /* NamespaceExportDeclaration */: return ts.updateNamespaceExportDeclaration(node, visitNode(node.name, visitor, ts.isIdentifier)); - case 243: + case 243 /* ImportEqualsDeclaration */: return ts.updateImportEqualsDeclaration(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.name, visitor, ts.isIdentifier), visitNode(node.moduleReference, visitor, ts.isModuleReference)); - case 244: + case 244 /* ImportDeclaration */: return ts.updateImportDeclaration(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.importClause, visitor, ts.isImportClause), visitNode(node.moduleSpecifier, visitor, ts.isExpression)); - case 245: + case 245 /* ImportClause */: return ts.updateImportClause(node, visitNode(node.name, visitor, ts.isIdentifier), visitNode(node.namedBindings, visitor, ts.isNamedImportBindings)); - case 246: + case 246 /* NamespaceImport */: return ts.updateNamespaceImport(node, visitNode(node.name, visitor, ts.isIdentifier)); - case 247: + case 247 /* NamedImports */: return ts.updateNamedImports(node, nodesVisitor(node.elements, visitor, ts.isImportSpecifier)); - case 248: + case 248 /* ImportSpecifier */: return ts.updateImportSpecifier(node, visitNode(node.propertyName, visitor, ts.isIdentifier), visitNode(node.name, visitor, ts.isIdentifier)); - case 249: + case 249 /* ExportAssignment */: return ts.updateExportAssignment(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.expression, visitor, ts.isExpression)); - case 250: + case 250 /* ExportDeclaration */: return ts.updateExportDeclaration(node, nodesVisitor(node.decorators, visitor, ts.isDecorator), nodesVisitor(node.modifiers, visitor, ts.isModifier), visitNode(node.exportClause, visitor, ts.isNamedExports), visitNode(node.moduleSpecifier, visitor, ts.isExpression)); - case 251: + case 251 /* NamedExports */: return ts.updateNamedExports(node, nodesVisitor(node.elements, visitor, ts.isExportSpecifier)); - case 252: + case 252 /* ExportSpecifier */: return ts.updateExportSpecifier(node, visitNode(node.propertyName, visitor, ts.isIdentifier), visitNode(node.name, visitor, ts.isIdentifier)); - case 254: + // Module references + case 254 /* ExternalModuleReference */: return ts.updateExternalModuleReference(node, visitNode(node.expression, visitor, ts.isExpression)); - case 255: + // JSX + case 255 /* JsxElement */: return ts.updateJsxElement(node, visitNode(node.openingElement, visitor, ts.isJsxOpeningElement), nodesVisitor(node.children, visitor, ts.isJsxChild), visitNode(node.closingElement, visitor, ts.isJsxClosingElement)); - case 256: + case 256 /* JsxSelfClosingElement */: return ts.updateJsxSelfClosingElement(node, visitNode(node.tagName, visitor, ts.isJsxTagNameExpression), nodesVisitor(node.typeArguments, visitor, ts.isTypeNode), visitNode(node.attributes, visitor, ts.isJsxAttributes)); - case 257: + case 257 /* JsxOpeningElement */: return ts.updateJsxOpeningElement(node, visitNode(node.tagName, visitor, ts.isJsxTagNameExpression), nodesVisitor(node.typeArguments, visitor, ts.isTypeNode), visitNode(node.attributes, visitor, ts.isJsxAttributes)); - case 258: + case 258 /* JsxClosingElement */: return ts.updateJsxClosingElement(node, visitNode(node.tagName, visitor, ts.isJsxTagNameExpression)); - case 259: + case 259 /* JsxFragment */: return ts.updateJsxFragment(node, visitNode(node.openingFragment, visitor, ts.isJsxOpeningFragment), nodesVisitor(node.children, visitor, ts.isJsxChild), visitNode(node.closingFragment, visitor, ts.isJsxClosingFragment)); - case 262: + case 262 /* JsxAttribute */: return ts.updateJsxAttribute(node, visitNode(node.name, visitor, ts.isIdentifier), visitNode(node.initializer, visitor, ts.isStringLiteralOrJsxExpression)); - case 263: + case 263 /* JsxAttributes */: return ts.updateJsxAttributes(node, nodesVisitor(node.properties, visitor, ts.isJsxAttributeLike)); - case 264: + case 264 /* JsxSpreadAttribute */: return ts.updateJsxSpreadAttribute(node, visitNode(node.expression, visitor, ts.isExpression)); - case 265: + case 265 /* JsxExpression */: return ts.updateJsxExpression(node, visitNode(node.expression, visitor, ts.isExpression)); - case 266: + // Clauses + case 266 /* CaseClause */: return ts.updateCaseClause(node, visitNode(node.expression, visitor, ts.isExpression), nodesVisitor(node.statements, visitor, ts.isStatement)); - case 267: + case 267 /* DefaultClause */: return ts.updateDefaultClause(node, nodesVisitor(node.statements, visitor, ts.isStatement)); - case 268: + case 268 /* HeritageClause */: return ts.updateHeritageClause(node, nodesVisitor(node.types, visitor, ts.isExpressionWithTypeArguments)); - case 269: + case 269 /* CatchClause */: return ts.updateCatchClause(node, visitNode(node.variableDeclaration, visitor, ts.isVariableDeclaration), visitNode(node.block, visitor, ts.isBlock)); - case 270: + // Property assignments + case 270 /* PropertyAssignment */: return ts.updatePropertyAssignment(node, visitNode(node.name, visitor, ts.isPropertyName), visitNode(node.initializer, visitor, ts.isExpression)); - case 271: + case 271 /* ShorthandPropertyAssignment */: return ts.updateShorthandPropertyAssignment(node, visitNode(node.name, visitor, ts.isIdentifier), visitNode(node.objectAssignmentInitializer, visitor, ts.isExpression)); - case 272: + case 272 /* SpreadAssignment */: return ts.updateSpreadAssignment(node, visitNode(node.expression, visitor, ts.isExpression)); - case 273: + // Enum + case 273 /* EnumMember */: return ts.updateEnumMember(node, visitNode(node.name, visitor, ts.isPropertyName), visitNode(node.initializer, visitor, ts.isExpression)); - case 274: + // Top-level nodes + case 274 /* SourceFile */: return ts.updateSourceFileNode(node, visitLexicalEnvironment(node.statements, visitor, context)); - case 302: + // Transformation nodes + case 302 /* PartiallyEmittedExpression */: return ts.updatePartiallyEmittedExpression(node, visitNode(node.expression, visitor, ts.isExpression)); - case 303: + case 303 /* CommaListExpression */: return ts.updateCommaList(node, nodesVisitor(node.elements, visitor, ts.isExpression)); default: + // No need to visit nodes with no children. return node; } } ts.visitEachChild = visitEachChild; + /** + * Extracts the single node from a NodeArray. + * + * @param nodes The NodeArray. + */ function extractSingleNode(nodes) { ts.Debug.assert(nodes.length <= 1, "Too many nodes written to output."); return ts.singleOrUndefined(nodes); } })(ts || (ts = {})); +/* @internal */ (function (ts) { function reduceNode(node, f, initial) { return node ? f(initial, node) : initial; @@ -51525,6 +59893,14 @@ var ts; function reduceNodeArray(nodes, f, initial) { return nodes ? f(initial, nodes) : initial; } + /** + * Similar to `reduceLeft`, performs a reduction against each child of a node. + * NOTE: Unlike `forEachChild`, this does *not* visit every node. + * + * @param node The node containing the children to reduce. + * @param initial The initial value to supply to the reduction. + * @param f The callback function + */ function reduceEachChild(node, initial, cbNode, cbNodeArray) { if (node === undefined) { return initial; @@ -51532,52 +59908,59 @@ var ts; var reduceNodes = cbNodeArray ? reduceNodeArray : ts.reduceLeft; var cbNodes = cbNodeArray || cbNode; var kind = node.kind; - if ((kind > 0 && kind <= 145)) { + // No need to visit nodes with no children. + if ((kind > 0 /* FirstToken */ && kind <= 145 /* LastToken */)) { return initial; } - if ((kind >= 161 && kind <= 178)) { + // We do not yet support types. + if ((kind >= 161 /* TypePredicate */ && kind <= 178 /* LiteralType */)) { return initial; } var result = initial; switch (node.kind) { - case 212: - case 215: - case 206: - case 231: - case 301: + // Leaf nodes + case 212 /* SemicolonClassElement */: + case 215 /* EmptyStatement */: + case 206 /* OmittedExpression */: + case 231 /* DebuggerStatement */: + case 301 /* NotEmittedStatement */: + // No need to visit nodes with no children. break; - case 146: + // Names + case 146 /* QualifiedName */: result = reduceNode(node.left, cbNode, result); result = reduceNode(node.right, cbNode, result); break; - case 147: + case 147 /* ComputedPropertyName */: result = reduceNode(node.expression, cbNode, result); break; - case 149: + // Signature elements + case 149 /* Parameter */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); result = reduceNode(node.type, cbNode, result); result = reduceNode(node.initializer, cbNode, result); break; - case 150: + case 150 /* Decorator */: result = reduceNode(node.expression, cbNode, result); break; - case 151: + // Type member + case 151 /* PropertySignature */: result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); result = reduceNode(node.questionToken, cbNode, result); result = reduceNode(node.type, cbNode, result); result = reduceNode(node.initializer, cbNode, result); break; - case 152: + case 152 /* PropertyDeclaration */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); result = reduceNode(node.type, cbNode, result); result = reduceNode(node.initializer, cbNode, result); break; - case 154: + case 154 /* MethodDeclaration */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); @@ -51586,12 +59969,12 @@ var ts; result = reduceNode(node.type, cbNode, result); result = reduceNode(node.body, cbNode, result); break; - case 155: + case 155 /* Constructor */: result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNodes(node.parameters, cbNodes, result); result = reduceNode(node.body, cbNode, result); break; - case 156: + case 156 /* GetAccessor */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); @@ -51599,55 +59982,57 @@ var ts; result = reduceNode(node.type, cbNode, result); result = reduceNode(node.body, cbNode, result); break; - case 157: + case 157 /* SetAccessor */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); result = reduceNodes(node.parameters, cbNodes, result); result = reduceNode(node.body, cbNode, result); break; - case 180: - case 181: + // Binding patterns + case 180 /* ObjectBindingPattern */: + case 181 /* ArrayBindingPattern */: result = reduceNodes(node.elements, cbNodes, result); break; - case 182: + case 182 /* BindingElement */: result = reduceNode(node.propertyName, cbNode, result); result = reduceNode(node.name, cbNode, result); result = reduceNode(node.initializer, cbNode, result); break; - case 183: + // Expression + case 183 /* ArrayLiteralExpression */: result = reduceNodes(node.elements, cbNodes, result); break; - case 184: + case 184 /* ObjectLiteralExpression */: result = reduceNodes(node.properties, cbNodes, result); break; - case 185: + case 185 /* PropertyAccessExpression */: result = reduceNode(node.expression, cbNode, result); result = reduceNode(node.name, cbNode, result); break; - case 186: + case 186 /* ElementAccessExpression */: result = reduceNode(node.expression, cbNode, result); result = reduceNode(node.argumentExpression, cbNode, result); break; - case 187: + case 187 /* CallExpression */: result = reduceNode(node.expression, cbNode, result); result = reduceNodes(node.typeArguments, cbNodes, result); result = reduceNodes(node.arguments, cbNodes, result); break; - case 188: + case 188 /* NewExpression */: result = reduceNode(node.expression, cbNode, result); result = reduceNodes(node.typeArguments, cbNodes, result); result = reduceNodes(node.arguments, cbNodes, result); break; - case 189: + case 189 /* TaggedTemplateExpression */: result = reduceNode(node.tag, cbNode, result); result = reduceNode(node.template, cbNode, result); break; - case 190: + case 190 /* TypeAssertionExpression */: result = reduceNode(node.type, cbNode, result); result = reduceNode(node.expression, cbNode, result); break; - case 192: + case 192 /* FunctionExpression */: result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); result = reduceNodes(node.typeParameters, cbNodes, result); @@ -51655,121 +60040,123 @@ var ts; result = reduceNode(node.type, cbNode, result); result = reduceNode(node.body, cbNode, result); break; - case 193: + case 193 /* ArrowFunction */: result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNodes(node.typeParameters, cbNodes, result); result = reduceNodes(node.parameters, cbNodes, result); result = reduceNode(node.type, cbNode, result); result = reduceNode(node.body, cbNode, result); break; - case 191: - case 194: - case 195: - case 196: - case 197: - case 203: - case 204: - case 209: + case 191 /* ParenthesizedExpression */: + case 194 /* DeleteExpression */: + case 195 /* TypeOfExpression */: + case 196 /* VoidExpression */: + case 197 /* AwaitExpression */: + case 203 /* YieldExpression */: + case 204 /* SpreadElement */: + case 209 /* NonNullExpression */: result = reduceNode(node.expression, cbNode, result); break; - case 198: - case 199: + case 198 /* PrefixUnaryExpression */: + case 199 /* PostfixUnaryExpression */: result = reduceNode(node.operand, cbNode, result); break; - case 200: + case 200 /* BinaryExpression */: result = reduceNode(node.left, cbNode, result); result = reduceNode(node.right, cbNode, result); break; - case 201: + case 201 /* ConditionalExpression */: result = reduceNode(node.condition, cbNode, result); result = reduceNode(node.whenTrue, cbNode, result); result = reduceNode(node.whenFalse, cbNode, result); break; - case 202: + case 202 /* TemplateExpression */: result = reduceNode(node.head, cbNode, result); result = reduceNodes(node.templateSpans, cbNodes, result); break; - case 205: + case 205 /* ClassExpression */: result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); result = reduceNodes(node.typeParameters, cbNodes, result); result = reduceNodes(node.heritageClauses, cbNodes, result); result = reduceNodes(node.members, cbNodes, result); break; - case 207: + case 207 /* ExpressionWithTypeArguments */: result = reduceNode(node.expression, cbNode, result); result = reduceNodes(node.typeArguments, cbNodes, result); break; - case 208: + case 208 /* AsExpression */: result = reduceNode(node.expression, cbNode, result); result = reduceNode(node.type, cbNode, result); break; - case 211: + // Misc + case 211 /* TemplateSpan */: result = reduceNode(node.expression, cbNode, result); result = reduceNode(node.literal, cbNode, result); break; - case 213: + // Element + case 213 /* Block */: result = reduceNodes(node.statements, cbNodes, result); break; - case 214: + case 214 /* VariableStatement */: result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.declarationList, cbNode, result); break; - case 216: + case 216 /* ExpressionStatement */: result = reduceNode(node.expression, cbNode, result); break; - case 217: + case 217 /* IfStatement */: result = reduceNode(node.expression, cbNode, result); result = reduceNode(node.thenStatement, cbNode, result); result = reduceNode(node.elseStatement, cbNode, result); break; - case 218: + case 218 /* DoStatement */: result = reduceNode(node.statement, cbNode, result); result = reduceNode(node.expression, cbNode, result); break; - case 219: - case 226: + case 219 /* WhileStatement */: + case 226 /* WithStatement */: result = reduceNode(node.expression, cbNode, result); result = reduceNode(node.statement, cbNode, result); break; - case 220: + case 220 /* ForStatement */: result = reduceNode(node.initializer, cbNode, result); result = reduceNode(node.condition, cbNode, result); result = reduceNode(node.incrementor, cbNode, result); result = reduceNode(node.statement, cbNode, result); break; - case 221: - case 222: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: result = reduceNode(node.initializer, cbNode, result); result = reduceNode(node.expression, cbNode, result); result = reduceNode(node.statement, cbNode, result); break; - case 225: - case 229: + case 225 /* ReturnStatement */: + case 229 /* ThrowStatement */: result = reduceNode(node.expression, cbNode, result); break; - case 227: + case 227 /* SwitchStatement */: result = reduceNode(node.expression, cbNode, result); result = reduceNode(node.caseBlock, cbNode, result); break; - case 228: + case 228 /* LabeledStatement */: result = reduceNode(node.label, cbNode, result); result = reduceNode(node.statement, cbNode, result); break; - case 230: + case 230 /* TryStatement */: result = reduceNode(node.tryBlock, cbNode, result); result = reduceNode(node.catchClause, cbNode, result); result = reduceNode(node.finallyBlock, cbNode, result); break; - case 232: + case 232 /* VariableDeclaration */: result = reduceNode(node.name, cbNode, result); result = reduceNode(node.type, cbNode, result); result = reduceNode(node.initializer, cbNode, result); break; - case 233: + case 233 /* VariableDeclarationList */: result = reduceNodes(node.declarations, cbNodes, result); break; - case 234: + case 234 /* FunctionDeclaration */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); @@ -51778,7 +60165,7 @@ var ts; result = reduceNode(node.type, cbNode, result); result = reduceNode(node.body, cbNode, result); break; - case 235: + case 235 /* ClassDeclaration */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); @@ -51786,131 +60173,139 @@ var ts; result = reduceNodes(node.heritageClauses, cbNodes, result); result = reduceNodes(node.members, cbNodes, result); break; - case 238: + case 238 /* EnumDeclaration */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); result = reduceNodes(node.members, cbNodes, result); break; - case 239: + case 239 /* ModuleDeclaration */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); result = reduceNode(node.body, cbNode, result); break; - case 240: + case 240 /* ModuleBlock */: result = reduceNodes(node.statements, cbNodes, result); break; - case 241: + case 241 /* CaseBlock */: result = reduceNodes(node.clauses, cbNodes, result); break; - case 243: + case 243 /* ImportEqualsDeclaration */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.name, cbNode, result); result = reduceNode(node.moduleReference, cbNode, result); break; - case 244: + case 244 /* ImportDeclaration */: result = reduceNodes(node.decorators, cbNodes, result); result = reduceNodes(node.modifiers, cbNodes, result); result = reduceNode(node.importClause, cbNode, result); result = reduceNode(node.moduleSpecifier, cbNode, result); break; - case 245: + case 245 /* ImportClause */: result = reduceNode(node.name, cbNode, result); result = reduceNode(node.namedBindings, cbNode, result); break; - case 246: + case 246 /* NamespaceImport */: result = reduceNode(node.name, cbNode, result); break; - case 247: - case 251: + case 247 /* NamedImports */: + case 251 /* NamedExports */: result = reduceNodes(node.elements, cbNodes, result); break; - case 248: - case 252: + case 248 /* ImportSpecifier */: + case 252 /* ExportSpecifier */: result = reduceNode(node.propertyName, cbNode, result); result = reduceNode(node.name, cbNode, result); break; - case 249: + case 249 /* ExportAssignment */: result = ts.reduceLeft(node.decorators, cbNode, result); result = ts.reduceLeft(node.modifiers, cbNode, result); result = reduceNode(node.expression, cbNode, result); break; - case 250: + case 250 /* ExportDeclaration */: result = ts.reduceLeft(node.decorators, cbNode, result); result = ts.reduceLeft(node.modifiers, cbNode, result); result = reduceNode(node.exportClause, cbNode, result); result = reduceNode(node.moduleSpecifier, cbNode, result); break; - case 254: + // Module references + case 254 /* ExternalModuleReference */: result = reduceNode(node.expression, cbNode, result); break; - case 255: + // JSX + case 255 /* JsxElement */: result = reduceNode(node.openingElement, cbNode, result); result = ts.reduceLeft(node.children, cbNode, result); result = reduceNode(node.closingElement, cbNode, result); break; - case 259: + case 259 /* JsxFragment */: result = reduceNode(node.openingFragment, cbNode, result); result = ts.reduceLeft(node.children, cbNode, result); result = reduceNode(node.closingFragment, cbNode, result); break; - case 256: - case 257: + case 256 /* JsxSelfClosingElement */: + case 257 /* JsxOpeningElement */: result = reduceNode(node.tagName, cbNode, result); result = reduceNode(node.attributes, cbNode, result); break; - case 263: + case 263 /* JsxAttributes */: result = reduceNodes(node.properties, cbNodes, result); break; - case 258: + case 258 /* JsxClosingElement */: result = reduceNode(node.tagName, cbNode, result); break; - case 262: + case 262 /* JsxAttribute */: result = reduceNode(node.name, cbNode, result); result = reduceNode(node.initializer, cbNode, result); break; - case 264: + case 264 /* JsxSpreadAttribute */: result = reduceNode(node.expression, cbNode, result); break; - case 265: + case 265 /* JsxExpression */: result = reduceNode(node.expression, cbNode, result); break; - case 266: + // Clauses + case 266 /* CaseClause */: result = reduceNode(node.expression, cbNode, result); - case 267: + // falls through + case 267 /* DefaultClause */: result = reduceNodes(node.statements, cbNodes, result); break; - case 268: + case 268 /* HeritageClause */: result = reduceNodes(node.types, cbNodes, result); break; - case 269: + case 269 /* CatchClause */: result = reduceNode(node.variableDeclaration, cbNode, result); result = reduceNode(node.block, cbNode, result); break; - case 270: + // Property assignments + case 270 /* PropertyAssignment */: result = reduceNode(node.name, cbNode, result); result = reduceNode(node.initializer, cbNode, result); break; - case 271: + case 271 /* ShorthandPropertyAssignment */: result = reduceNode(node.name, cbNode, result); result = reduceNode(node.objectAssignmentInitializer, cbNode, result); break; - case 272: + case 272 /* SpreadAssignment */: result = reduceNode(node.expression, cbNode, result); break; - case 273: + // Enum + case 273 /* EnumMember */: result = reduceNode(node.name, cbNode, result); result = reduceNode(node.initializer, cbNode, result); break; - case 274: + // Top-level nodes + case 274 /* SourceFile */: result = reduceNodes(node.statements, cbNodes, result); break; - case 302: + // Transformation nodes + case 302 /* PartiallyEmittedExpression */: result = reduceNode(node.expression, cbNode, result); break; - case 303: + case 303 /* CommaListExpression */: result = reduceNodes(node.elements, cbNodes, result); break; default: @@ -51928,21 +60323,36 @@ var ts; : ts.prependStatements(statements, declarations); } ts.mergeLexicalEnvironment = mergeLexicalEnvironment; + /** + * Lifts a NodeArray containing only Statement nodes to a block. + * + * @param nodes The NodeArray. + */ function liftToBlock(nodes) { Debug.assert(ts.every(nodes, ts.isStatement), "Cannot lift nodes to a Block."); return ts.singleOrUndefined(nodes) || ts.createBlock(nodes); } ts.liftToBlock = liftToBlock; + /** + * Aggregates the TransformFlags for a Node and its subtree. + */ function aggregateTransformFlags(node) { aggregateTransformFlagsForNode(node); return node; } ts.aggregateTransformFlags = aggregateTransformFlags; + /** + * Aggregates the TransformFlags for a Node and its subtree. The flags for the subtree are + * computed first, then the transform flags for the current node are computed from the subtree + * flags and the state of the current node. Finally, the transform flags of the node are + * returned, excluding any flags that should not be included in its parent node's subtree + * flags. + */ function aggregateTransformFlagsForNode(node) { if (node === undefined) { - return 0; + return 0 /* None */; } - if (node.transformFlags & 536870912) { + if (node.transformFlags & 536870912 /* HasComputedFlags */) { return node.transformFlags & ~ts.getTransformFlagsSubtreeExclusions(node.kind); } var subtreeFlags = aggregateTransformFlagsForSubtree(node); @@ -51950,24 +60360,34 @@ var ts; } function aggregateTransformFlagsForNodeArray(nodes) { if (nodes === undefined) { - return 0; + return 0 /* None */; } - var subtreeFlags = 0; - var nodeArrayFlags = 0; + var subtreeFlags = 0 /* None */; + var nodeArrayFlags = 0 /* None */; for (var _i = 0, nodes_3 = nodes; _i < nodes_3.length; _i++) { var node = nodes_3[_i]; subtreeFlags |= aggregateTransformFlagsForNode(node); - nodeArrayFlags |= node.transformFlags & ~536870912; + nodeArrayFlags |= node.transformFlags & ~536870912 /* HasComputedFlags */; } - nodes.transformFlags = nodeArrayFlags | 536870912; + nodes.transformFlags = nodeArrayFlags | 536870912 /* HasComputedFlags */; return subtreeFlags; } + /** + * Aggregates the transform flags for the subtree of a node. + */ function aggregateTransformFlagsForSubtree(node) { - if (ts.hasModifier(node, 2) || (ts.isTypeNode(node) && node.kind !== 207)) { - return 0; + // We do not transform ambient declarations or types, so there is no need to + // recursively aggregate transform flags. + if (ts.hasModifier(node, 2 /* Ambient */) || (ts.isTypeNode(node) && node.kind !== 207 /* ExpressionWithTypeArguments */)) { + return 0 /* None */; } - return reduceEachChild(node, 0, aggregateTransformFlagsForChildNode, aggregateTransformFlagsForChildNodes); + // Aggregate the transform flags of each child. + return reduceEachChild(node, 0 /* None */, aggregateTransformFlagsForChildNode, aggregateTransformFlagsForChildNodes); } + /** + * Aggregates the TransformFlags of a child node with the TransformFlags of its + * siblings. + */ function aggregateTransformFlagsForChildNode(transformFlags, node) { return transformFlags | aggregateTransformFlagsForNode(node); } @@ -51981,30 +60401,34 @@ var ts; return Debug.fail((message || "Unexpected node.") + "\r\nNode " + ts.formatSyntaxKind(node.kind) + " was unexpected.", failBadSyntaxKind); } Debug.failBadSyntaxKind = failBadSyntaxKind; - Debug.assertEachNode = Debug.shouldAssert(1) + Debug.assertEachNode = Debug.shouldAssert(1 /* Normal */) ? function (nodes, test, message) { return Debug.assert(test === undefined || ts.every(nodes, test), message || "Unexpected node.", function () { return "Node array did not pass test '" + Debug.getFunctionName(test) + "'."; }, Debug.assertEachNode); } : ts.noop; - Debug.assertNode = Debug.shouldAssert(1) + Debug.assertNode = Debug.shouldAssert(1 /* Normal */) ? function (node, test, message) { return Debug.assert(test === undefined || test(node), message || "Unexpected node.", function () { return "Node " + ts.formatSyntaxKind(node.kind) + " did not pass test '" + Debug.getFunctionName(test) + "'."; }, Debug.assertNode); } : ts.noop; - Debug.assertOptionalNode = Debug.shouldAssert(1) + Debug.assertOptionalNode = Debug.shouldAssert(1 /* Normal */) ? function (node, test, message) { return Debug.assert(test === undefined || node === undefined || test(node), message || "Unexpected node.", function () { return "Node " + ts.formatSyntaxKind(node.kind) + " did not pass test '" + Debug.getFunctionName(test) + "'."; }, Debug.assertOptionalNode); } : ts.noop; - Debug.assertOptionalToken = Debug.shouldAssert(1) + Debug.assertOptionalToken = Debug.shouldAssert(1 /* Normal */) ? function (node, kind, message) { return Debug.assert(kind === undefined || node === undefined || node.kind === kind, message || "Unexpected node.", function () { return "Node " + ts.formatSyntaxKind(node.kind) + " was not a '" + ts.formatSyntaxKind(kind) + "' token."; }, Debug.assertOptionalToken); } : ts.noop; - Debug.assertMissingNode = Debug.shouldAssert(1) + Debug.assertMissingNode = Debug.shouldAssert(1 /* Normal */) ? function (node, message) { return Debug.assert(node === undefined, message || "Unexpected node.", function () { return "Node " + ts.formatSyntaxKind(node.kind) + " was unexpected'."; }, Debug.assertMissingNode); } : ts.noop; + /** + * Injects debug information into frequently used types. + */ function enableDebugInfo() { if (isDebugInfoEnabled) return; + // Add additional properties in debug mode to assist with debugging. Object.defineProperties(ts.objectAllocator.getSymbolConstructor().prototype, { __debugFlags: { get: function () { return ts.formatSymbolFlags(this.flags); } } }); Object.defineProperties(ts.objectAllocator.getTypeConstructor().prototype, { __debugFlags: { get: function () { return ts.formatTypeFlags(this.flags); } }, - __debugObjectFlags: { get: function () { return this.flags & 131072 ? ts.formatObjectFlags(this.objectFlags) : ""; } }, + __debugObjectFlags: { get: function () { return this.flags & 131072 /* Object */ ? ts.formatObjectFlags(this.objectFlags) : ""; } }, __debugTypeToString: { value: function () { return this.checker.typeToString(this); } }, }); var nodeConstructors = [ @@ -52038,6 +60462,7 @@ var ts; Debug.enableDebugInfo = enableDebugInfo; })(Debug = ts.Debug || (ts.Debug = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { function createSourceFileLikeCache(host) { @@ -52049,7 +60474,8 @@ var ts; } if (!host.fileExists || !host.readFile || !host.fileExists(path)) return; - var text = host.readFile(path); + // And failing that, check the disk + var text = host.readFile(path); // TODO: GH#18217 var file = { text: text, lineMap: undefined, @@ -52064,6 +60490,7 @@ var ts; } ts.createSourceFileLikeCache = createSourceFileLikeCache; })(ts || (ts = {})); +/* @internal */ (function (ts) { var sourcemaps; (function (sourcemaps) { @@ -52085,12 +60512,13 @@ var ts; return loc; var targetIndex = ts.binarySearch(maps, { sourcePath: loc.fileName, sourcePosition: loc.position }, ts.identity, compareProcessedPositionSourcePositions); if (targetIndex < 0 && maps.length > 0) { + // if no exact match, closest is 2's compliment of result targetIndex = ~targetIndex; } if (!maps[targetIndex] || ts.comparePaths(loc.fileName, maps[targetIndex].sourcePath, sourceRoot) !== 0) { return loc; } - return { fileName: ts.toPath(map.file, sourceRoot, host.getCanonicalFileName), position: maps[targetIndex].emittedPosition }; + return { fileName: ts.toPath(map.file, sourceRoot, host.getCanonicalFileName), position: maps[targetIndex].emittedPosition }; // Closest pos } function getOriginalPosition(loc) { var maps = getGeneratedOrderedMappings(); @@ -52098,13 +60526,16 @@ var ts; return loc; var targetIndex = ts.binarySearch(maps, { emittedPosition: loc.position }, ts.identity, compareProcessedPositionEmittedPositions); if (targetIndex < 0 && maps.length > 0) { + // if no exact match, closest is 2's compliment of result targetIndex = ~targetIndex; } - return { fileName: ts.toPath(maps[targetIndex].sourcePath, sourceRoot, host.getCanonicalFileName), position: maps[targetIndex].sourcePosition }; + return { fileName: ts.toPath(maps[targetIndex].sourcePath, sourceRoot, host.getCanonicalFileName), position: maps[targetIndex].sourcePosition }; // Closest pos } function getSourceFileLike(fileName, location) { + // Lookup file in program, if provided var file = program && program.getSourceFile(fileName); if (!file) { + // Otherwise check the cache (which may hit disk) var path = ts.toPath(fileName, location, host.getCanonicalFileName); return fallbackCache.get(path); } @@ -52143,6 +60574,7 @@ var ts; } } sourcemaps.decode = decode; + /*@internal*/ function decodeMappings(map) { var state = { encodedText: map.mappings, @@ -52197,56 +60629,79 @@ var ts; function decodeSinglePosition(state) { while (state.decodingIndex < state.encodedText.length) { var char = state.encodedText.charCodeAt(state.decodingIndex); - if (char === 59) { + if (char === 59 /* semicolon */) { + // New line state.currentEmittedLine++; state.currentEmittedColumn = 0; state.decodingIndex++; continue; } - if (char === 44) { + if (char === 44 /* comma */) { + // Next entry is on same line - no action needed state.decodingIndex++; continue; } + // Read the current position + // 1. Column offset from prev read jsColumn state.currentEmittedColumn += base64VLQFormatDecode(); + // Incorrect emittedColumn dont support this map if (createErrorIfCondition(state.currentEmittedColumn < 0, "Invalid emittedColumn found")) { return false; } + // Dont support reading mappings that dont have information about original source and its line numbers if (createErrorIfCondition(isSourceMappingSegmentEnd(state.encodedText, state.decodingIndex), "Unsupported Error Format: No entries after emitted column")) { return false; } + // 2. Relative sourceIndex state.currentSourceIndex += base64VLQFormatDecode(); + // Incorrect sourceIndex dont support this map if (createErrorIfCondition(state.currentSourceIndex < 0, "Invalid sourceIndex found")) { return false; } + // Dont support reading mappings that dont have information about original source position if (createErrorIfCondition(isSourceMappingSegmentEnd(state.encodedText, state.decodingIndex), "Unsupported Error Format: No entries after sourceIndex")) { return false; } + // 3. Relative sourceLine 0 based state.currentSourceLine += base64VLQFormatDecode(); + // Incorrect sourceLine dont support this map if (createErrorIfCondition(state.currentSourceLine < 0, "Invalid sourceLine found")) { return false; } + // Dont support reading mappings that dont have information about original source and its line numbers if (createErrorIfCondition(isSourceMappingSegmentEnd(state.encodedText, state.decodingIndex), "Unsupported Error Format: No entries after emitted Line")) { return false; } + // 4. Relative sourceColumn 0 based state.currentSourceColumn += base64VLQFormatDecode(); + // Incorrect sourceColumn dont support this map if (createErrorIfCondition(state.currentSourceColumn < 0, "Invalid sourceLine found")) { return false; } + // 5. Check if there is name: if (!isSourceMappingSegmentEnd(state.encodedText, state.decodingIndex)) { if (state.currentNameIndex === undefined) { state.currentNameIndex = 0; } state.currentNameIndex += base64VLQFormatDecode(); + // Incorrect nameIndex dont support this map + // TODO: If we start using `name`s, issue errors when they aren't correct in the sourcemap + // if (createErrorIfCondition(state.currentNameIndex < 0 || state.currentNameIndex >= state.sourceMapNamesLength, "Invalid name index for the source map entry")) { + // return; + // } } + // Dont support reading mappings that dont have information about original source and its line numbers if (createErrorIfCondition(!isSourceMappingSegmentEnd(state.encodedText, state.decodingIndex), "Unsupported Error Format: There are more entries after " + (state.currentNameIndex === undefined ? "sourceColumn" : "nameIndex"))) { return false; } + // Entry should be complete return true; } - createErrorIfCondition(true, "No encoded entry found"); + createErrorIfCondition(/*condition*/ true, "No encoded entry found"); return false; function createErrorIfCondition(condition, errormsg) { if (state.error) { + // An error was already reported return true; } if (condition) { @@ -52260,17 +60715,23 @@ var ts; var value = 0; for (; moreDigits; state.decodingIndex++) { if (createErrorIfCondition(state.decodingIndex >= state.encodedText.length, "Error in decoding base64VLQFormatDecode, past the mapping string")) { - return undefined; + return undefined; // TODO: GH#18217 } + // 6 digit number var currentByte = base64FormatDecode(state.encodedText.charAt(state.decodingIndex)); + // If msb is set, we still have more bits to continue moreDigits = (currentByte & 32) !== 0; + // least significant 5 bits are the next msbs in the final value. value = value | ((currentByte & 31) << shiftCount); shiftCount += 5; } + // Least significant bit if 1 represents negative and rest of the msb is actual absolute value if ((value & 1) === 0) { + // + number value = value >> 1; } else { + // - number value = value >> 1; value = -value; } @@ -52282,11 +60743,12 @@ var ts; } function isSourceMappingSegmentEnd(encodedText, pos) { return (pos === encodedText.length || - encodedText.charCodeAt(pos) === 44 || - encodedText.charCodeAt(pos) === 59); + encodedText.charCodeAt(pos) === 44 /* comma */ || + encodedText.charCodeAt(pos) === 59 /* semicolon */); } })(sourcemaps = ts.sourcemaps || (ts.sourcemaps = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { function getOriginalNodeId(node) { @@ -52302,12 +60764,12 @@ var ts; return ts.some(node.elements, isNamedDefaultReference); } function isNamedDefaultReference(e) { - return e.propertyName !== undefined && e.propertyName.escapedText === "default"; + return e.propertyName !== undefined && e.propertyName.escapedText === "default" /* Default */; } function chainBundle(transformSourceFile) { return transformSourceFileOrBundle; function transformSourceFileOrBundle(node) { - return node.kind === 274 ? transformSourceFile(node) : transformBundle(node); + return node.kind === 274 /* SourceFile */ ? transformSourceFile(node) : transformBundle(node); } function transformBundle(node) { return ts.createBundle(ts.map(node.sourceFiles, transformSourceFile), node.prepends); @@ -52331,11 +60793,13 @@ var ts; defaultRefCount++; } } + // Import star is required if there's default named refs mixed with non-default refs, or if theres non-default refs and it has a default import return (defaultRefCount > 0 && defaultRefCount !== bindings.elements.length) || (!!(bindings.elements.length - defaultRefCount) && ts.isDefaultImport(node)); } ts.getImportNeedsImportStarHelper = getImportNeedsImportStarHelper; function getImportNeedsImportDefaultHelper(node) { - return !getImportNeedsImportStarHelper(node) && (ts.isDefaultImport(node) || (!!node.importClause && ts.isNamedImports(node.importClause.namedBindings) && containsDefaultReference(node.importClause.namedBindings))); + // Import default is needed if there's a default import or a default ref and no other refs (meaning an import star helper wasn't requested) + return !getImportNeedsImportStarHelper(node) && (ts.isDefaultImport(node) || (!!node.importClause && ts.isNamedImports(node.importClause.namedBindings) && containsDefaultReference(node.importClause.namedBindings))); // TODO: GH#18217 } ts.getImportNeedsImportDefaultHelper = getImportNeedsImportDefaultHelper; function collectExternalModuleInfo(sourceFile, resolver, compilerOptions) { @@ -52351,26 +60815,34 @@ var ts; for (var _i = 0, _a = sourceFile.statements; _i < _a.length; _i++) { var node = _a[_i]; switch (node.kind) { - case 244: + case 244 /* ImportDeclaration */: + // import "mod" + // import x from "mod" + // import * as x from "mod" + // import { x, y } from "mod" externalImports.push(node); hasImportStarOrImportDefault = hasImportStarOrImportDefault || getImportNeedsImportStarHelper(node) || getImportNeedsImportDefaultHelper(node); break; - case 243: - if (node.moduleReference.kind === 254) { + case 243 /* ImportEqualsDeclaration */: + if (node.moduleReference.kind === 254 /* ExternalModuleReference */) { + // import x = require("mod") externalImports.push(node); } break; - case 250: + case 250 /* ExportDeclaration */: if (node.moduleSpecifier) { if (!node.exportClause) { + // export * from "mod" externalImports.push(node); hasExportStarsToExportValues = true; } else { + // export { x, y } from "mod" externalImports.push(node); } } else { + // export { x, y } for (var _b = 0, _c = node.exportClause.elements; _b < _c.length; _b++) { var specifier = _c[_b]; if (!uniqueExports.get(ts.idText(specifier.name))) { @@ -52387,28 +60859,31 @@ var ts; } } break; - case 249: + case 249 /* ExportAssignment */: if (node.isExportEquals && !exportEquals) { + // export = x exportEquals = node; } break; - case 214: - if (ts.hasModifier(node, 1)) { + case 214 /* VariableStatement */: + if (ts.hasModifier(node, 1 /* Export */)) { for (var _d = 0, _e = node.declarationList.declarations; _d < _e.length; _d++) { var decl = _e[_d]; exportedNames = collectExportedVariableInfo(decl, uniqueExports, exportedNames); } } break; - case 234: - if (ts.hasModifier(node, 1)) { - if (ts.hasModifier(node, 512)) { + case 234 /* FunctionDeclaration */: + if (ts.hasModifier(node, 1 /* Export */)) { + if (ts.hasModifier(node, 512 /* Default */)) { + // export default function() { } if (!hasExportDefault) { multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), ts.getDeclarationName(node)); hasExportDefault = true; } } else { + // export function x() { } var name = node.name; if (!uniqueExports.get(ts.idText(name))) { multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name); @@ -52418,15 +60893,17 @@ var ts; } } break; - case 235: - if (ts.hasModifier(node, 1)) { - if (ts.hasModifier(node, 512)) { + case 235 /* ClassDeclaration */: + if (ts.hasModifier(node, 1 /* Export */)) { + if (ts.hasModifier(node, 512 /* Default */)) { + // export default class { } if (!hasExportDefault) { multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), ts.getDeclarationName(node)); hasExportDefault = true; } } else { + // export class x { } var name = node.name; if (name && !uniqueExports.get(ts.idText(name))) { multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name); @@ -52439,9 +60916,11 @@ var ts; } } var externalHelpersModuleName = ts.getOrCreateExternalHelpersModuleNameIfNeeded(sourceFile, compilerOptions, hasExportStarsToExportValues, hasImportStarOrImportDefault); - var externalHelpersImportDeclaration = externalHelpersModuleName && ts.createImportDeclaration(undefined, undefined, ts.createImportClause(undefined, ts.createNamespaceImport(externalHelpersModuleName)), ts.createLiteral(ts.externalHelpersModuleNameText)); + var externalHelpersImportDeclaration = externalHelpersModuleName && ts.createImportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, ts.createImportClause(/*name*/ undefined, ts.createNamespaceImport(externalHelpersModuleName)), ts.createLiteral(ts.externalHelpersModuleNameText)); if (externalHelpersImportDeclaration) { - ts.addEmitFlags(externalHelpersImportDeclaration, 67108864); + ts.addEmitFlags(externalHelpersImportDeclaration, 67108864 /* NeverApplyImportHelper */); externalImports.unshift(externalHelpersImportDeclaration); } return { externalImports: externalImports, exportSpecifiers: exportSpecifiers, exportEquals: exportEquals, hasExportStarsToExportValues: hasExportStarsToExportValues, exportedBindings: exportedBindings, exportedNames: exportedNames, externalHelpersImportDeclaration: externalHelpersImportDeclaration }; @@ -52465,6 +60944,7 @@ var ts; } return exportedNames; } + /** Use a sparse array as a multi-map. */ function multiMapSparseArrayAdd(map, key, value) { var values = map[key]; if (values) { @@ -52475,13 +60955,22 @@ var ts; } return values; } + /** + * Used in the module transformer to check if an expression is reasonably without sideeffect, + * and thus better to copy into multiple places rather than to cache in a temporary variable + * - this is mostly subjective beyond the requirement that the expression not be sideeffecting + */ function isSimpleCopiableExpression(expression) { return ts.isStringLiteralLike(expression) || - expression.kind === 8 || + expression.kind === 8 /* NumericLiteral */ || ts.isKeyword(expression.kind) || ts.isIdentifier(expression); } ts.isSimpleCopiableExpression = isSimpleCopiableExpression; + /** + * @param input Template string input strings + * @param args Names which need to be made file-level unique + */ function helperString(input) { var args = []; for (var _i = 1; _i < arguments.length; _i++) { @@ -52499,6 +60988,7 @@ var ts; } ts.helperString = helperString; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { var FlattenLevel; @@ -52506,6 +60996,17 @@ var ts; FlattenLevel[FlattenLevel["All"] = 0] = "All"; FlattenLevel[FlattenLevel["ObjectRest"] = 1] = "ObjectRest"; })(FlattenLevel = ts.FlattenLevel || (ts.FlattenLevel = {})); + /** + * Flattens a DestructuringAssignment or a VariableDeclaration to an expression. + * + * @param node The node to flatten. + * @param visitor An optional visitor used to visit initializers. + * @param context The transformation context. + * @param level Indicates the extent to which flattening should occur. + * @param needsValue An optional value indicating whether the value from the right-hand-side of + * the destructuring assignment is needed as part of a larger expression. + * @param createAssignmentCallback An optional callback used to create the assignment expression. + */ function flattenDestructuringAssignment(node, visitor, context, level, needsValue, createAssignmentCallback) { var location = node; var value; @@ -52537,16 +61038,30 @@ var ts; if (value) { value = ts.visitNode(value, visitor, ts.isExpression); if (ts.isIdentifier(value) && bindingOrAssignmentElementAssignsToName(node, value.escapedText)) { - value = ensureIdentifier(flattenContext, value, false, location); + // If the right-hand value of the assignment is also an assignment target then + // we need to cache the right-hand value. + value = ensureIdentifier(flattenContext, value, /*reuseIdentifierExpressions*/ false, location); } else if (needsValue) { - value = ensureIdentifier(flattenContext, value, true, location); + // If the right-hand value of the destructuring assignment needs to be preserved (as + // is the case when the destructuring assignment is part of a larger expression), + // then we need to cache the right-hand value. + // + // The source map location for the assignment should point to the entire binary + // expression. + value = ensureIdentifier(flattenContext, value, /*reuseIdentifierExpressions*/ true, location); } else if (ts.nodeIsSynthesized(node)) { + // Generally, the source map location for a destructuring assignment is the root + // expression. + // + // However, if the root expression is synthesized (as in the case + // of the initializer when transforming a ForOfStatement), then the source map + // location should point to the right-hand value of the expression. location = value; } } - flattenBindingOrAssignmentElement(flattenContext, node, value, location, ts.isDestructuringAssignment(node)); + flattenBindingOrAssignmentElement(flattenContext, node, value, location, /*skipInitializer*/ ts.isDestructuringAssignment(node)); if (value && needsValue) { if (!ts.some(expressions)) { return value; @@ -52555,7 +61070,9 @@ var ts; } return ts.aggregateTransformFlags(ts.inlineExpressions(expressions)) || ts.createOmittedExpression(); function emitExpression(expression) { - ts.setEmitFlags(expression, 64); + // NOTE: this completely disables source maps, but aligns with the behavior of + // `emitAssignment` in the old emitter. + ts.setEmitFlags(expression, 64 /* NoNestedSourceMaps */); ts.aggregateTransformFlags(expression); expressions = ts.append(expressions, expression); } @@ -52570,7 +61087,7 @@ var ts; } ts.flattenDestructuringAssignment = flattenDestructuringAssignment; function bindingOrAssignmentElementAssignsToName(element, escapedName) { - var target = ts.getTargetOfBindingOrAssignmentElement(element); + var target = ts.getTargetOfBindingOrAssignmentElement(element); // TODO: GH#18217 if (ts.isBindingOrAssignmentPattern(target)) { return bindingOrAssignmentPatternAssignsToName(target, escapedName); } @@ -52589,6 +61106,17 @@ var ts; } return false; } + /** + * Flattens a VariableDeclaration or ParameterDeclaration to one or more variable declarations. + * + * @param node The node to flatten. + * @param visitor An optional visitor used to visit initializers. + * @param context The transformation context. + * @param boundValue The value bound to the declaration. + * @param skipInitializer A value indicating whether to ignore the initializer of `node`. + * @param hoistTempVariables Indicates whether temporary variables should not be recorded in-line. + * @param level Indicates the extent to which flattening should occur. + */ function flattenDestructuringBinding(node, visitor, context, level, rval, hoistTempVariables, skipInitializer) { if (hoistTempVariables === void 0) { hoistTempVariables = false; } var pendingExpressions; @@ -52609,17 +61137,19 @@ var ts; if (ts.isVariableDeclaration(node)) { var initializer = ts.getInitializerOfBindingOrAssignmentElement(node); if (initializer && ts.isIdentifier(initializer) && bindingOrAssignmentElementAssignsToName(node, initializer.escapedText)) { - initializer = ensureIdentifier(flattenContext, initializer, false, initializer); + // If the right-hand value of the assignment is also an assignment target then + // we need to cache the right-hand value. + initializer = ensureIdentifier(flattenContext, initializer, /*reuseIdentifierExpressions*/ false, initializer); node = ts.updateVariableDeclaration(node, node.name, node.type, initializer); } } flattenBindingOrAssignmentElement(flattenContext, node, rval, node, skipInitializer); if (pendingExpressions) { - var temp = ts.createTempVariable(undefined); + var temp = ts.createTempVariable(/*recordTempVariable*/ undefined); if (hoistTempVariables) { var value = ts.inlineExpressions(pendingExpressions); pendingExpressions = undefined; - emitBindingOrAssignment(temp, value, undefined, undefined); + emitBindingOrAssignment(temp, value, /*location*/ undefined, /*original*/ undefined); } else { context.hoistVariableDeclaration(temp); @@ -52631,11 +61161,12 @@ var ts; } for (var _i = 0, pendingDeclarations_1 = pendingDeclarations; _i < pendingDeclarations_1.length; _i++) { var _a = pendingDeclarations_1[_i], pendingExpressions_1 = _a.pendingExpressions, name = _a.name, value = _a.value, location = _a.location, original = _a.original; - var variable = ts.createVariableDeclaration(name, undefined, pendingExpressions_1 ? ts.inlineExpressions(ts.append(pendingExpressions_1, value)) : value); + var variable = ts.createVariableDeclaration(name, + /*type*/ undefined, pendingExpressions_1 ? ts.inlineExpressions(ts.append(pendingExpressions_1, value)) : value); variable.original = original; ts.setTextRange(variable, location); if (ts.isIdentifier(name)) { - ts.setEmitFlags(variable, 64); + ts.setEmitFlags(variable, 64 /* NoNestedSourceMaps */); } ts.aggregateTransformFlags(variable); declarations.push(variable); @@ -52654,17 +61185,29 @@ var ts; } } ts.flattenDestructuringBinding = flattenDestructuringBinding; + /** + * Flattens a BindingOrAssignmentElement into zero or more bindings or assignments. + * + * @param flattenContext Options used to control flattening. + * @param element The element to flatten. + * @param value The current RHS value to assign to the element. + * @param location The location to use for source maps and comments. + * @param skipInitializer An optional value indicating whether to include the initializer + * for the element. + */ function flattenBindingOrAssignmentElement(flattenContext, element, value, location, skipInitializer) { if (!skipInitializer) { var initializer = ts.visitNode(ts.getInitializerOfBindingOrAssignmentElement(element), flattenContext.visitor, ts.isExpression); if (initializer) { + // Combine value and initializer value = value ? createDefaultValueCheck(flattenContext, value, initializer, location) : initializer; } else if (!value) { + // Use 'void 0' in absence of value and initializer value = ts.createVoidZero(); } } - var bindingTarget = ts.getTargetOfBindingOrAssignmentElement(element); + var bindingTarget = ts.getTargetOfBindingOrAssignmentElement(element); // TODO: GH#18217 if (ts.isObjectBindingOrAssignmentPattern(bindingTarget)) { flattenObjectBindingOrAssignmentPattern(flattenContext, element, bindingTarget, value, location); } @@ -52672,13 +61215,26 @@ var ts; flattenArrayBindingOrAssignmentPattern(flattenContext, element, bindingTarget, value, location); } else { - flattenContext.emitBindingOrAssignment(bindingTarget, value, location, element); + flattenContext.emitBindingOrAssignment(bindingTarget, value, location, /*original*/ element); // TODO: GH#18217 } } + /** + * Flattens an ObjectBindingOrAssignmentPattern into zero or more bindings or assignments. + * + * @param flattenContext Options used to control flattening. + * @param parent The parent element of the pattern. + * @param pattern The ObjectBindingOrAssignmentPattern to flatten. + * @param value The current RHS value to assign to the element. + * @param location The location to use for source maps and comments. + */ function flattenObjectBindingOrAssignmentPattern(flattenContext, parent, pattern, value, location) { var elements = ts.getElementsOfBindingOrAssignmentPattern(pattern); var 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. var reuseIdentifierExpressions = !ts.isDeclarationBindingElement(parent) || numElements !== 0; value = ensureIdentifier(flattenContext, value, reuseIdentifierExpressions, location); } @@ -52688,9 +61244,9 @@ var ts; var element = elements[i]; if (!ts.getRestIndicatorOfBindingOrAssignmentElement(element)) { var propertyName = ts.getPropertyNameOfBindingOrAssignmentElement(element); - if (flattenContext.level >= 1 - && !(element.transformFlags & (524288 | 1048576)) - && !(ts.getTargetOfBindingOrAssignmentElement(element).transformFlags & (524288 | 1048576)) + if (flattenContext.level >= 1 /* ObjectRest */ + && !(element.transformFlags & (524288 /* ContainsRest */ | 1048576 /* ContainsObjectRest */)) + && !(ts.getTargetOfBindingOrAssignmentElement(element).transformFlags & (524288 /* ContainsRest */ | 1048576 /* ContainsObjectRest */)) && !ts.isComputedPropertyName(propertyName)) { bindingElements = ts.append(bindingElements, element); } @@ -52703,7 +61259,7 @@ var ts; if (ts.isComputedPropertyName(propertyName)) { computedTempVariables = ts.append(computedTempVariables, rhsValue.argumentExpression); } - flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, element); + flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, /*location*/ element); } } else if (i === numElements - 1) { @@ -52711,7 +61267,7 @@ var ts; flattenContext.emitBindingOrAssignment(flattenContext.createObjectBindingOrAssignmentPattern(bindingElements), value, location, pattern); bindingElements = undefined; } - var rhsValue = createRestCall(flattenContext.context, value, elements, computedTempVariables, pattern); + var rhsValue = createRestCall(flattenContext.context, value, elements, computedTempVariables, pattern); // TODO: GH#18217 flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, element); } } @@ -52719,16 +61275,33 @@ var ts; flattenContext.emitBindingOrAssignment(flattenContext.createObjectBindingOrAssignmentPattern(bindingElements), value, location, pattern); } } + /** + * Flattens an ArrayBindingOrAssignmentPattern into zero or more bindings or assignments. + * + * @param flattenContext Options used to control flattening. + * @param parent The parent element of the pattern. + * @param pattern The ArrayBindingOrAssignmentPattern to flatten. + * @param value The current RHS value to assign to the element. + * @param location The location to use for source maps and comments. + */ function flattenArrayBindingOrAssignmentPattern(flattenContext, parent, pattern, value, location) { var elements = ts.getElementsOfBindingOrAssignmentPattern(pattern); var numElements = elements.length; - if (flattenContext.level < 1 && flattenContext.downlevelIteration) { + if (flattenContext.level < 1 /* ObjectRest */ && flattenContext.downlevelIteration) { + // Read the elements of the iterable into an array value = ensureIdentifier(flattenContext, ts.createReadHelper(flattenContext.context, value, numElements > 0 && ts.getRestIndicatorOfBindingOrAssignmentElement(elements[numElements - 1]) ? undefined - : numElements, location), false, location); + : numElements, location), + /*reuseIdentifierExpressions*/ false, location); } - else if (numElements !== 1 && (flattenContext.level < 1 || numElements === 0) + else if (numElements !== 1 && (flattenContext.level < 1 /* ObjectRest */ || numElements === 0) || ts.every(elements, ts.isOmittedExpression)) { + // 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. + // Or all the elements of the binding pattern are omitted expression such as "var [,] = [1,2]", + // then we will create temporary variable. var reuseIdentifierExpressions = !ts.isDeclarationBindingElement(parent) || numElements !== 0; value = ensureIdentifier(flattenContext, value, reuseIdentifierExpressions, location); } @@ -52736,9 +61309,11 @@ var ts; var restContainingElements; for (var i = 0; i < numElements; i++) { var element = elements[i]; - if (flattenContext.level >= 1) { - if (element.transformFlags & 1048576) { - var temp = ts.createTempVariable(undefined); + if (flattenContext.level >= 1 /* ObjectRest */) { + // If an array pattern contains an ObjectRest, we must cache the result so that we + // can perform the ObjectRest destructuring in a different declaration + if (element.transformFlags & 1048576 /* ContainsObjectRest */) { + var temp = ts.createTempVariable(/*recordTempVariable*/ undefined); if (flattenContext.hoistTempVariables) { flattenContext.context.hoistVariableDeclaration(temp); } @@ -52754,11 +61329,11 @@ var ts; } else if (!ts.getRestIndicatorOfBindingOrAssignmentElement(element)) { var rhsValue = ts.createElementAccess(value, i); - flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, element); + flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, /*location*/ element); } else if (i === numElements - 1) { var rhsValue = ts.createArraySlice(value, i); - flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, element); + flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, /*location*/ element); } } if (bindingElements) { @@ -52771,13 +61346,31 @@ var ts; } } } + /** + * Creates an expression used to provide a default value if a value is `undefined` at runtime. + * + * @param flattenContext Options used to control flattening. + * @param value The RHS value to test. + * @param defaultValue The default value to use if `value` is `undefined` at runtime. + * @param location The location to use for source maps and comments. + */ function createDefaultValueCheck(flattenContext, value, defaultValue, location) { - value = ensureIdentifier(flattenContext, value, true, location); + value = ensureIdentifier(flattenContext, value, /*reuseIdentifierExpressions*/ true, location); return ts.createConditional(ts.createTypeCheck(value, "undefined"), defaultValue, value); } + /** + * Creates either a PropertyAccessExpression or an ElementAccessExpression for the + * right-hand side of a transformed destructuring assignment. + * + * @link https://tc39.github.io/ecma262/#sec-runtime-semantics-keyeddestructuringassignmentevaluation + * + * @param flattenContext Options used to control flattening. + * @param value The RHS value that is the source of the property. + * @param propertyName The destructuring property name. + */ function createDestructuringPropertyAccess(flattenContext, value, propertyName) { if (ts.isComputedPropertyName(propertyName)) { - var argumentExpression = ensureIdentifier(flattenContext, ts.visitNode(propertyName.expression, flattenContext.visitor), false, propertyName); + var argumentExpression = ensureIdentifier(flattenContext, ts.visitNode(propertyName.expression, flattenContext.visitor), /*reuseIdentifierExpressions*/ false, /*location*/ propertyName); return ts.createElementAccess(value, argumentExpression); } else if (ts.isStringOrNumericLiteral(propertyName)) { @@ -52790,18 +61383,29 @@ var ts; return ts.createPropertyAccess(value, name); } } + /** + * Ensures that there exists a declared identifier whose value holds the given expression. + * This function is useful to ensure that the expression's value can be read from in subsequent expressions. + * Unless 'reuseIdentifierExpressions' is false, 'value' will be returned if it is just an identifier. + * + * @param flattenContext Options used to control flattening. + * @param value the expression whose value needs to be bound. + * @param reuseIdentifierExpressions true if identifier expressions can simply be returned; + * false if it is necessary to always emit an identifier. + * @param location The location to use for source maps and comments. + */ function ensureIdentifier(flattenContext, value, reuseIdentifierExpressions, location) { if (ts.isIdentifier(value) && reuseIdentifierExpressions) { return value; } else { - var temp = ts.createTempVariable(undefined); + var temp = ts.createTempVariable(/*recordTempVariable*/ undefined); if (flattenContext.hoistTempVariables) { flattenContext.context.hoistVariableDeclaration(temp); flattenContext.emitExpression(ts.setTextRange(ts.createAssignment(temp, value), location)); } else { - flattenContext.emitBindingOrAssignment(temp, value, location, undefined); + flattenContext.emitBindingOrAssignment(temp, value, location, /*original*/ undefined); } return temp; } @@ -52821,7 +61425,7 @@ var ts; return ts.createObjectLiteral(ts.map(elements, ts.convertToObjectAssignmentElement)); } function makeBindingElement(name) { - return ts.createBindingElement(undefined, undefined, name); + return ts.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, name); } function makeAssignmentElement(name) { return name; @@ -52831,6 +61435,9 @@ var ts; scoped: false, text: "\n var __rest = (this && this.__rest) || function (s, e) {\n var t = {};\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\n t[p] = s[p];\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)\n t[p[i]] = s[p[i]];\n return t;\n };" }; + /** Given value: o, propName: p, pattern: { a, b, ...p } from the original statement + * `{ a, b, ...p } = o`, create `p = __rest(o, ["a", "b"]);` + */ function createRestCall(context, value, elements, computedTempVariables, location) { context.requestEmitHelper(restHelper); var propertyNames = []; @@ -52841,6 +61448,7 @@ var ts; if (ts.isComputedPropertyName(propertyName)) { var temp = computedTempVariables[computedTempVariableOffset]; computedTempVariableOffset++; + // typeof _tmp === "symbol" ? _tmp : _tmp + "" propertyNames.push(ts.createConditional(ts.createTypeCheck(temp, "symbol"), temp, ts.createAdd(temp, ts.createLiteral("")))); } else { @@ -52848,19 +61456,27 @@ var ts; } } } - return ts.createCall(ts.getHelperName("__rest"), undefined, [ + return ts.createCall(ts.getHelperName("__rest"), + /*typeArguments*/ undefined, [ value, ts.setTextRange(ts.createArrayLiteral(propertyNames), location) ]); } })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { + /** + * Indicates whether to emit type metadata in the new format. + */ var USE_NEW_TYPE_METADATA_FORMAT = false; var TypeScriptSubstitutionFlags; (function (TypeScriptSubstitutionFlags) { + /** Enables substitutions for decorated classes. */ TypeScriptSubstitutionFlags[TypeScriptSubstitutionFlags["ClassAliases"] = 1] = "ClassAliases"; + /** Enables substitutions for namespace exports. */ TypeScriptSubstitutionFlags[TypeScriptSubstitutionFlags["NamespaceExports"] = 2] = "NamespaceExports"; + /* Enables substitutions for unqualified enum members */ TypeScriptSubstitutionFlags[TypeScriptSubstitutionFlags["NonQualifiedEnumMembers"] = 8] = "NonQualifiedEnumMembers"; })(TypeScriptSubstitutionFlags || (TypeScriptSubstitutionFlags = {})); var ClassFacts; @@ -52886,36 +61502,61 @@ var ts; var strictNullChecks = ts.getStrictOptionValue(compilerOptions, "strictNullChecks"); var languageVersion = ts.getEmitScriptTarget(compilerOptions); var moduleKind = ts.getEmitModuleKind(compilerOptions); + // Save the previous transformation hooks. var previousOnEmitNode = context.onEmitNode; var previousOnSubstituteNode = context.onSubstituteNode; + // Set new transformation hooks. context.onEmitNode = onEmitNode; context.onSubstituteNode = onSubstituteNode; - context.enableSubstitution(185); - context.enableSubstitution(186); + // Enable substitution for property/element access to emit const enum values. + context.enableSubstitution(185 /* PropertyAccessExpression */); + context.enableSubstitution(186 /* ElementAccessExpression */); + // These variables contain state that changes as we descend into the tree. var currentSourceFile; var currentNamespace; var currentNamespaceContainerName; var currentScope; var currentScopeFirstDeclarationsOfName; + /** + * Keeps track of whether expression substitution has been enabled for specific edge cases. + * They are persisted between each SourceFile transformation and should not be reset. + */ var enabledSubstitutions; + /** + * A map that keeps track of aliases created for classes with decorators to avoid issues + * with the double-binding behavior of classes. + */ var classAliases; + /** + * Keeps track of whether we are within any containing namespaces when performing + * just-in-time substitution while printing an expression identifier. + */ var applicableSubstitutions; + /** + * Tracks what computed name expressions originating from elided names must be inlined + * at the next execution site, in document order + */ var pendingExpressions; return transformSourceFileOrBundle; function transformSourceFileOrBundle(node) { - if (node.kind === 275) { + if (node.kind === 275 /* Bundle */) { return transformBundle(node); } return transformSourceFile(node); } function transformBundle(node) { return ts.createBundle(node.sourceFiles.map(transformSourceFile), ts.mapDefined(node.prepends, function (prepend) { - if (prepend.kind === 277) { + if (prepend.kind === 277 /* InputFiles */) { return ts.createUnparsedSourceFile(prepend.javascriptText, prepend.javascriptMapPath, prepend.javascriptMapText); } return prepend; })); } + /** + * Transform TypeScript-specific syntax in a SourceFile. + * + * @param node A SourceFile node. + */ function transformSourceFile(node) { if (node.isDeclarationFile) { return node; @@ -52926,61 +61567,100 @@ var ts; currentSourceFile = undefined; return visited; } + /** + * Visits a node, saving and restoring state variables on the stack. + * + * @param node The node to visit. + */ function saveStateAndInvoke(node, f) { + // Save state var savedCurrentScope = currentScope; var savedCurrentScopeFirstDeclarationsOfName = currentScopeFirstDeclarationsOfName; + // Handle state changes before visiting a node. onBeforeVisitNode(node); var visited = f(node); + // Restore state if (currentScope !== savedCurrentScope) { currentScopeFirstDeclarationsOfName = savedCurrentScopeFirstDeclarationsOfName; } currentScope = savedCurrentScope; return visited; } + /** + * Performs actions that should always occur immediately before visiting a node. + * + * @param node The node to visit. + */ function onBeforeVisitNode(node) { switch (node.kind) { - case 274: - case 241: - case 240: - case 213: + case 274 /* SourceFile */: + case 241 /* CaseBlock */: + case 240 /* ModuleBlock */: + case 213 /* Block */: currentScope = node; currentScopeFirstDeclarationsOfName = undefined; break; - case 235: - case 234: - if (ts.hasModifier(node, 2)) { + case 235 /* ClassDeclaration */: + case 234 /* FunctionDeclaration */: + if (ts.hasModifier(node, 2 /* Ambient */)) { break; } + // Record these declarations provided that they have a name. if (node.name) { recordEmittedDeclarationInScope(node); } else { - ts.Debug.assert(node.kind === 235 || ts.hasModifier(node, 512)); + // These nodes should always have names unless they are default-exports; + // however, class declaration parsing allows for undefined names, so syntactically invalid + // programs may also have an undefined name. + ts.Debug.assert(node.kind === 235 /* ClassDeclaration */ || ts.hasModifier(node, 512 /* Default */)); } break; } } + /** + * General-purpose node visitor. + * + * @param node The node to visit. + */ function visitor(node) { return saveStateAndInvoke(node, visitorWorker); } + /** + * Visits and possibly transforms any node. + * + * @param node The node to visit. + */ function visitorWorker(node) { - if (node.transformFlags & 1) { + if (node.transformFlags & 1 /* TypeScript */) { + // This node is explicitly marked as TypeScript, so we should transform the node. return visitTypeScript(node); } - else if (node.transformFlags & 2) { + else if (node.transformFlags & 2 /* ContainsTypeScript */) { + // This node contains TypeScript, so we should visit its children. return ts.visitEachChild(node, visitor, context); } return node; } + /** + * Specialized visitor that visits the immediate children of a SourceFile. + * + * @param node The node to visit. + */ function sourceElementVisitor(node) { return saveStateAndInvoke(node, sourceElementVisitorWorker); } + /** + * Specialized visitor that visits the immediate children of a SourceFile. + * + * @param node The node to visit. + */ function sourceElementVisitorWorker(node) { switch (node.kind) { - case 244: - case 243: - case 249: - case 250: + case 244 /* ImportDeclaration */: + case 243 /* ImportEqualsDeclaration */: + case 249 /* ExportAssignment */: + case 250 /* ExportDeclaration */: return visitEllidableStatement(node); default: return visitorWorker(node); @@ -52989,168 +61669,265 @@ var ts; function visitEllidableStatement(node) { var parsed = ts.getParseTreeNode(node); if (parsed !== node) { - if (node.transformFlags & 2) { + // If the node has been transformed by a `before` transformer, perform no ellision on it + // As the type information we would attempt to lookup to perform ellision is potentially unavailable for the synthesized nodes + // We do not reuse `visitorWorker`, as the ellidable statement syntax kinds are technically unrecognized by the switch-case in `visitTypeScript`, + // and will trigger debug failures when debug verbosity is turned up + if (node.transformFlags & 2 /* ContainsTypeScript */) { + // This node contains TypeScript, so we should visit its children. return ts.visitEachChild(node, visitor, context); } + // Otherwise, we can just return the node return node; } switch (node.kind) { - case 244: + case 244 /* ImportDeclaration */: return visitImportDeclaration(node); - case 243: + case 243 /* ImportEqualsDeclaration */: return visitImportEqualsDeclaration(node); - case 249: + case 249 /* ExportAssignment */: return visitExportAssignment(node); - case 250: + case 250 /* ExportDeclaration */: return visitExportDeclaration(node); default: ts.Debug.fail("Unhandled ellided statement"); } } + /** + * Specialized visitor that visits the immediate children of a namespace. + * + * @param node The node to visit. + */ function namespaceElementVisitor(node) { return saveStateAndInvoke(node, namespaceElementVisitorWorker); } + /** + * Specialized visitor that visits the immediate children of a namespace. + * + * @param node The node to visit. + */ function namespaceElementVisitorWorker(node) { - if (node.kind === 250 || - node.kind === 244 || - node.kind === 245 || - (node.kind === 243 && - node.moduleReference.kind === 254)) { + if (node.kind === 250 /* ExportDeclaration */ || + node.kind === 244 /* ImportDeclaration */ || + node.kind === 245 /* ImportClause */ || + (node.kind === 243 /* ImportEqualsDeclaration */ && + node.moduleReference.kind === 254 /* ExternalModuleReference */)) { + // do not emit ES6 imports and exports since they are illegal inside a namespace return undefined; } - else if (node.transformFlags & 1 || ts.hasModifier(node, 1)) { + else if (node.transformFlags & 1 /* TypeScript */ || ts.hasModifier(node, 1 /* Export */)) { + // This node is explicitly marked as TypeScript, or is exported at the namespace + // level, so we should transform the node. return visitTypeScript(node); } - else if (node.transformFlags & 2) { + else if (node.transformFlags & 2 /* ContainsTypeScript */) { + // This node contains TypeScript, so we should visit its children. return ts.visitEachChild(node, visitor, context); } return node; } + /** + * Specialized visitor that visits the immediate children of a class with TypeScript syntax. + * + * @param node The node to visit. + */ function classElementVisitor(node) { return saveStateAndInvoke(node, classElementVisitorWorker); } + /** + * Specialized visitor that visits the immediate children of a class with TypeScript syntax. + * + * @param node The node to visit. + */ function classElementVisitorWorker(node) { switch (node.kind) { - case 155: + case 155 /* Constructor */: + // TypeScript constructors are transformed in `visitClassDeclaration`. + // We elide them here as `visitorWorker` checks transform flags, which could + // erronously include an ES6 constructor without TypeScript syntax. return undefined; - case 152: - case 160: - case 156: - case 157: - case 154: + case 152 /* PropertyDeclaration */: + case 160 /* IndexSignature */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 154 /* MethodDeclaration */: + // Fallback to the default visit behavior. return visitorWorker(node); - case 212: + case 212 /* SemicolonClassElement */: return node; default: return ts.Debug.failBadSyntaxKind(node); } } function modifierVisitor(node) { - if (ts.modifierToFlag(node.kind) & 2270) { + if (ts.modifierToFlag(node.kind) & 2270 /* TypeScriptModifier */) { return undefined; } - else if (currentNamespace && node.kind === 84) { + else if (currentNamespace && node.kind === 84 /* ExportKeyword */) { return undefined; } return node; } + /** + * Branching visitor, visits a TypeScript syntax node. + * + * @param node The node to visit. + */ function visitTypeScript(node) { - if (ts.hasModifier(node, 2) && ts.isStatement(node)) { + if (ts.hasModifier(node, 2 /* Ambient */) && ts.isStatement(node)) { + // TypeScript ambient declarations are elided, but some comments may be preserved. + // See the implementation of `getLeadingComments` in comments.ts for more details. return ts.createNotEmittedStatement(node); } switch (node.kind) { - case 84: - case 79: + case 84 /* ExportKeyword */: + case 79 /* DefaultKeyword */: + // ES6 export and default modifiers are elided when inside a namespace. return currentNamespace ? undefined : node; - case 114: - case 112: - case 113: - case 117: - case 76: - case 124: - case 132: - case 167: - case 168: - case 166: - case 161: - case 148: - case 119: - case 142: - case 122: - case 137: - case 134: - case 131: - case 105: - case 138: - case 164: - case 163: - case 165: - case 162: - case 169: - case 170: - case 171: - case 173: - case 174: - case 175: - case 176: - case 177: - case 178: - case 160: - case 150: - case 237: + case 114 /* PublicKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: + case 117 /* AbstractKeyword */: + case 76 /* ConstKeyword */: + case 124 /* DeclareKeyword */: + case 132 /* ReadonlyKeyword */: + // TypeScript accessibility and readonly modifiers are elided. + case 167 /* ArrayType */: + case 168 /* TupleType */: + case 166 /* TypeLiteral */: + case 161 /* TypePredicate */: + case 148 /* TypeParameter */: + case 119 /* AnyKeyword */: + case 142 /* UnknownKeyword */: + case 122 /* BooleanKeyword */: + case 137 /* StringKeyword */: + case 134 /* NumberKeyword */: + case 131 /* NeverKeyword */: + case 105 /* VoidKeyword */: + case 138 /* SymbolKeyword */: + case 164 /* ConstructorType */: + case 163 /* FunctionType */: + case 165 /* TypeQuery */: + case 162 /* TypeReference */: + case 169 /* UnionType */: + case 170 /* IntersectionType */: + case 171 /* ConditionalType */: + case 173 /* ParenthesizedType */: + case 174 /* ThisType */: + case 175 /* TypeOperator */: + case 176 /* IndexedAccessType */: + case 177 /* MappedType */: + case 178 /* LiteralType */: + // TypeScript type nodes are elided. + case 160 /* IndexSignature */: + // TypeScript index signatures are elided. + case 150 /* Decorator */: + // TypeScript decorators are elided. They will be emitted as part of visitClassDeclaration. + case 237 /* TypeAliasDeclaration */: + // TypeScript type-only declarations are elided. return undefined; - case 152: + case 152 /* PropertyDeclaration */: + // TypeScript property declarations are elided. However their names are still visited, and can potentially be retained if they could have sideeffects return visitPropertyDeclaration(node); - case 242: + case 242 /* NamespaceExportDeclaration */: + // TypeScript namespace export declarations are elided. return undefined; - case 155: + case 155 /* Constructor */: return visitConstructor(node); - case 236: + case 236 /* InterfaceDeclaration */: + // TypeScript interfaces are elided, but some comments may be preserved. + // See the implementation of `getLeadingComments` in comments.ts for more details. return ts.createNotEmittedStatement(node); - case 235: + case 235 /* 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 return visitClassDeclaration(node); - case 205: + case 205 /* 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 return visitClassExpression(node); - case 268: + case 268 /* HeritageClause */: + // This is a heritage clause with TypeScript syntax extensions. + // + // TypeScript heritage clause extensions include: + // - `implements` clause return visitHeritageClause(node); - case 207: + case 207 /* ExpressionWithTypeArguments */: + // TypeScript supports type arguments on an expression in an `extends` heritage clause. return visitExpressionWithTypeArguments(node); - case 154: + case 154 /* MethodDeclaration */: + // TypeScript method declarations may have decorators, modifiers + // or type annotations. return visitMethodDeclaration(node); - case 156: + case 156 /* GetAccessor */: + // Get Accessors can have TypeScript modifiers, decorators, and type annotations. return visitGetAccessor(node); - case 157: + case 157 /* SetAccessor */: + // Set Accessors can have TypeScript modifiers and type annotations. return visitSetAccessor(node); - case 234: + case 234 /* FunctionDeclaration */: + // Typescript function declarations can have modifiers, decorators, and type annotations. return visitFunctionDeclaration(node); - case 192: + case 192 /* FunctionExpression */: + // TypeScript function expressions can have modifiers and type annotations. return visitFunctionExpression(node); - case 193: + case 193 /* ArrowFunction */: + // TypeScript arrow functions can have modifiers and type annotations. return visitArrowFunction(node); - case 149: + case 149 /* 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 + // - this parameters return visitParameter(node); - case 191: + case 191 /* ParenthesizedExpression */: + // ParenthesizedExpressions are TypeScript if their expression is a + // TypeAssertion or AsExpression return visitParenthesizedExpression(node); - case 190: - case 208: + case 190 /* TypeAssertionExpression */: + case 208 /* AsExpression */: + // TypeScript type assertions are removed, but their subtrees are preserved. return visitAssertionExpression(node); - case 187: + case 187 /* CallExpression */: return visitCallExpression(node); - case 188: + case 188 /* NewExpression */: return visitNewExpression(node); - case 189: + case 189 /* TaggedTemplateExpression */: return visitTaggedTemplateExpression(node); - case 209: + case 209 /* NonNullExpression */: + // TypeScript non-null expressions are removed, but their subtrees are preserved. return visitNonNullExpression(node); - case 238: + case 238 /* EnumDeclaration */: + // TypeScript enum declarations do not exist in ES6 and must be rewritten. return visitEnumDeclaration(node); - case 214: + case 214 /* VariableStatement */: + // TypeScript namespace exports for variable statements must be transformed. return visitVariableStatement(node); - case 232: + case 232 /* VariableDeclaration */: return visitVariableDeclaration(node); - case 239: + case 239 /* ModuleDeclaration */: + // TypeScript namespace declarations must be transformed. return visitModuleDeclaration(node); - case 243: + case 243 /* ImportEqualsDeclaration */: + // TypeScript namespace or external module import. return visitImportEqualsDeclaration(node); default: return ts.Debug.failBadSyntaxKind(node); @@ -53160,8 +61937,11 @@ var ts; var alwaysStrict = ts.getStrictOptionValue(compilerOptions, "alwaysStrict") && !(ts.isExternalModule(node) && moduleKind >= ts.ModuleKind.ES2015) && !ts.isJsonSourceFile(node); - return ts.updateSourceFileNode(node, ts.visitLexicalEnvironment(node.statements, sourceElementVisitor, context, 0, alwaysStrict)); + return ts.updateSourceFileNode(node, ts.visitLexicalEnvironment(node.statements, sourceElementVisitor, context, /*start*/ 0, alwaysStrict)); } + /** + * Tests whether we should emit a __decorate call for a class declaration. + */ function shouldEmitDecorateCallForClass(node) { if (node.decorators && node.decorators.length > 0) { return true; @@ -53172,68 +61952,104 @@ var ts; } return false; } + /** + * Tests whether we should emit a __decorate call for a parameter declaration. + */ function shouldEmitDecorateCallForParameter(parameter) { return parameter.decorators !== undefined && parameter.decorators.length > 0; } function getClassFacts(node, staticProperties) { - var facts = 0; + var facts = 0 /* None */; if (ts.some(staticProperties)) - facts |= 1; + facts |= 1 /* HasStaticInitializedProperties */; var extendsClauseElement = ts.getClassExtendsHeritageClauseElement(node); - if (extendsClauseElement && ts.skipOuterExpressions(extendsClauseElement.expression).kind !== 95) - facts |= 64; + if (extendsClauseElement && ts.skipOuterExpressions(extendsClauseElement.expression).kind !== 95 /* NullKeyword */) + facts |= 64 /* IsDerivedClass */; if (shouldEmitDecorateCallForClass(node)) - facts |= 2; + facts |= 2 /* HasConstructorDecorators */; if (ts.childIsDecorated(node)) - facts |= 4; + facts |= 4 /* HasMemberDecorators */; if (isExportOfNamespace(node)) - facts |= 8; + facts |= 8 /* IsExportOfNamespace */; else if (isDefaultExternalModuleExport(node)) - facts |= 32; + facts |= 32 /* IsDefaultExternalExport */; else if (isNamedExternalModuleExport(node)) - facts |= 16; - if (languageVersion <= 1 && (facts & 7)) - facts |= 128; + facts |= 16 /* IsNamedExternalExport */; + if (languageVersion <= 1 /* ES5 */ && (facts & 7 /* MayNeedImmediatelyInvokedFunctionExpression */)) + facts |= 128 /* UseImmediatelyInvokedFunctionExpression */; return facts; } + /** + * Transforms a class declaration with TypeScript syntax into compatible ES6. + * + * 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. + * + * @param node The node to transform. + */ function visitClassDeclaration(node) { var savedPendingExpressions = pendingExpressions; pendingExpressions = undefined; - var staticProperties = getInitializedProperties(node, true); + var staticProperties = getInitializedProperties(node, /*isStatic*/ true); var facts = getClassFacts(node, staticProperties); - if (facts & 128) { + if (facts & 128 /* UseImmediatelyInvokedFunctionExpression */) { context.startLexicalEnvironment(); } - var name = node.name || (facts & 5 ? ts.getGeneratedNameForNode(node) : undefined); - var classStatement = facts & 2 + var name = node.name || (facts & 5 /* NeedsName */ ? ts.getGeneratedNameForNode(node) : undefined); + var classStatement = facts & 2 /* HasConstructorDecorators */ ? createClassDeclarationHeadWithDecorators(node, name, facts) : createClassDeclarationHeadWithoutDecorators(node, name, facts); var statements = [classStatement]; + // Write any pending expressions from elided or moved computed property names if (ts.some(pendingExpressions)) { statements.push(ts.createStatement(ts.inlineExpressions(pendingExpressions))); } pendingExpressions = savedPendingExpressions; - if (facts & 1) { - addInitializedPropertyStatements(statements, staticProperties, facts & 128 ? ts.getInternalName(node) : ts.getLocalName(node)); + // 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. + if (facts & 1 /* HasStaticInitializedProperties */) { + addInitializedPropertyStatements(statements, staticProperties, facts & 128 /* UseImmediatelyInvokedFunctionExpression */ ? ts.getInternalName(node) : ts.getLocalName(node)); } - addClassElementDecorationStatements(statements, node, false); - addClassElementDecorationStatements(statements, node, true); + // Write any decorators of the node. + addClassElementDecorationStatements(statements, node, /*isStatic*/ false); + addClassElementDecorationStatements(statements, node, /*isStatic*/ true); addConstructorDecorationStatement(statements, node); - if (facts & 128) { - var closingBraceLocation = ts.createTokenRange(ts.skipTrivia(currentSourceFile.text, node.members.end), 18); + if (facts & 128 /* UseImmediatelyInvokedFunctionExpression */) { + // When we emit a TypeScript class down to ES5, we must wrap it in an IIFE so that the + // 'es2015' transformer can properly nest static initializers and decorators. The result + // looks something like: + // + // var C = function () { + // class C { + // } + // C.static_prop = 1; + // return C; + // }(); + // + var closingBraceLocation = ts.createTokenRange(ts.skipTrivia(currentSourceFile.text, node.members.end), 18 /* CloseBraceToken */); var localName = ts.getInternalName(node); + // The following partially-emitted expression exists purely to align our sourcemap + // emit with the original emitter. var outer = ts.createPartiallyEmittedExpression(localName); outer.end = closingBraceLocation.end; - ts.setEmitFlags(outer, 1536); + ts.setEmitFlags(outer, 1536 /* NoComments */); var statement = ts.createReturn(outer); statement.pos = closingBraceLocation.pos; - ts.setEmitFlags(statement, 1536 | 384); + ts.setEmitFlags(statement, 1536 /* NoComments */ | 384 /* NoTokenSourceMaps */); statements.push(statement); ts.prependStatements(statements, context.endLexicalEnvironment()); var iife = ts.createImmediatelyInvokedArrowFunction(statements); - ts.setEmitFlags(iife, 33554432); - var varStatement = ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.createVariableDeclaration(ts.getLocalName(node, false, false), undefined, iife) + ts.setEmitFlags(iife, 33554432 /* TypeScriptClassWrapper */); + var varStatement = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(ts.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ false), + /*type*/ undefined, iife) ])); ts.setOriginalNode(varStatement, node); ts.setCommentRange(varStatement, node); @@ -53241,75 +62057,205 @@ var ts; ts.startOnNewLine(varStatement); statements = [varStatement]; } - if (facts & 8) { + // If the class is exported as part of a TypeScript namespace, emit the namespace export. + // Otherwise, if the class was exported at the top level and was decorated, emit an export + // declaration or export default for the class. + if (facts & 8 /* IsExportOfNamespace */) { addExportMemberAssignment(statements, node); } - else if (facts & 128 || facts & 2) { - if (facts & 32) { - statements.push(ts.createExportDefault(ts.getLocalName(node, false, true))); + else if (facts & 128 /* UseImmediatelyInvokedFunctionExpression */ || facts & 2 /* HasConstructorDecorators */) { + if (facts & 32 /* IsDefaultExternalExport */) { + statements.push(ts.createExportDefault(ts.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true))); } - else if (facts & 16) { - statements.push(ts.createExternalModuleExport(ts.getLocalName(node, false, true))); + else if (facts & 16 /* IsNamedExternalExport */) { + statements.push(ts.createExternalModuleExport(ts.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true))); } } if (statements.length > 1) { + // Add a DeclarationMarker as a marker for the end of the declaration statements.push(ts.createEndOfDeclarationMarker(node)); - ts.setEmitFlags(classStatement, ts.getEmitFlags(classStatement) | 4194304); + ts.setEmitFlags(classStatement, ts.getEmitFlags(classStatement) | 4194304 /* HasEndOfDeclarationMarker */); } return ts.singleOrMany(statements); } + /** + * Transforms a non-decorated class declaration and appends the resulting statements. + * + * @param node A ClassDeclaration node. + * @param name The name of the class. + * @param facts Precomputed facts about the class. + */ function createClassDeclarationHeadWithoutDecorators(node, name, facts) { - var modifiers = !(facts & 128) + // ${modifiers} class ${name} ${heritageClauses} { + // ${members} + // } + // we do not emit modifiers on the declaration if we are emitting an IIFE + var modifiers = !(facts & 128 /* UseImmediatelyInvokedFunctionExpression */) ? ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier) : undefined; - var classDeclaration = ts.createClassDeclaration(undefined, modifiers, name, undefined, ts.visitNodes(node.heritageClauses, visitor, ts.isHeritageClause), transformClassMembers(node, (facts & 64) !== 0)); + var classDeclaration = ts.createClassDeclaration( + /*decorators*/ undefined, modifiers, name, + /*typeParameters*/ undefined, ts.visitNodes(node.heritageClauses, visitor, ts.isHeritageClause), transformClassMembers(node, (facts & 64 /* IsDerivedClass */) !== 0)); + // To better align with the old emitter, we should not emit a trailing source map + // entry if the class has static properties. var emitFlags = ts.getEmitFlags(node); - if (facts & 1) { - emitFlags |= 32; + if (facts & 1 /* HasStaticInitializedProperties */) { + emitFlags |= 32 /* NoTrailingSourceMap */; } ts.setTextRange(classDeclaration, node); ts.setOriginalNode(classDeclaration, node); ts.setEmitFlags(classDeclaration, emitFlags); return classDeclaration; } + /** + * Transforms a decorated class declaration and appends the resulting statements. If + * the class requires an alias to avoid issues with double-binding, the alias is returned. + */ function createClassDeclarationHeadWithDecorators(node, name, facts) { + // When we emit an ES6 class that has a class decorator, we must tailor the + // emit to certain specific cases. + // + // In the simplest case, we emit the class declaration as a let declaration, and + // evaluate decorators after the close of the class body: + // + // [Example 1] + // --------------------------------------------------------------------- + // TypeScript | Javascript + // --------------------------------------------------------------------- + // @dec | let C = class C { + // class C { | } + // } | C = __decorate([dec], C); + // --------------------------------------------------------------------- + // @dec | let C = class C { + // export class C { | } + // } | C = __decorate([dec], C); + // | export { C }; + // --------------------------------------------------------------------- + // + // If a class declaration contains a reference to itself *inside* of the class body, + // this introduces two bindings to the class: One outside of the class body, and one + // inside of the class body. If we apply decorators as in [Example 1] above, there + // is the possibility that the decorator `dec` will return a new value for the + // constructor, which would result in the binding inside of the class no longer + // pointing to the same reference as the binding outside of the class. + // + // As a result, we must instead rewrite all references to the class *inside* of the + // class body to instead point to a local temporary alias for the class: + // + // [Example 2] + // --------------------------------------------------------------------- + // TypeScript | Javascript + // --------------------------------------------------------------------- + // @dec | let C = C_1 = class C { + // class C { | static x() { return C_1.y; } + // static x() { return C.y; } | } + // static y = 1; | C.y = 1; + // } | C = C_1 = __decorate([dec], C); + // | var C_1; + // --------------------------------------------------------------------- + // @dec | let C = class C { + // export class C { | static x() { return C_1.y; } + // static x() { return C.y; } | } + // static y = 1; | C.y = 1; + // } | C = C_1 = __decorate([dec], C); + // | export { C }; + // | var C_1; + // --------------------------------------------------------------------- + // + // If a class declaration is the default export of a module, we instead emit + // the export after the decorated declaration: + // + // [Example 3] + // --------------------------------------------------------------------- + // TypeScript | Javascript + // --------------------------------------------------------------------- + // @dec | let default_1 = class { + // export default class { | } + // } | default_1 = __decorate([dec], default_1); + // | export default default_1; + // --------------------------------------------------------------------- + // @dec | let C = class C { + // export default class C { | } + // } | C = __decorate([dec], C); + // | export default C; + // --------------------------------------------------------------------- + // + // If the class declaration is the default export and a reference to itself + // inside of the class body, we must emit both an alias for the class *and* + // move the export after the declaration: + // + // [Example 4] + // --------------------------------------------------------------------- + // TypeScript | Javascript + // --------------------------------------------------------------------- + // @dec | let C = class C { + // export default class C { | static x() { return C_1.y; } + // static x() { return C.y; } | } + // static y = 1; | C.y = 1; + // } | C = C_1 = __decorate([dec], C); + // | export default C; + // | var C_1; + // --------------------------------------------------------------------- + // var location = ts.moveRangePastDecorators(node); var classAlias = getClassAliasIfNeeded(node); - var declName = ts.getLocalName(node, false, true); + var declName = ts.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); + // ... = class ${name} ${heritageClauses} { + // ${members} + // } var heritageClauses = ts.visitNodes(node.heritageClauses, visitor, ts.isHeritageClause); - var members = transformClassMembers(node, (facts & 64) !== 0); - var classExpression = ts.createClassExpression(undefined, name, undefined, heritageClauses, members); + var members = transformClassMembers(node, (facts & 64 /* IsDerivedClass */) !== 0); + var classExpression = ts.createClassExpression(/*modifiers*/ undefined, name, /*typeParameters*/ undefined, heritageClauses, members); ts.setOriginalNode(classExpression, node); ts.setTextRange(classExpression, location); - var statement = ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.createVariableDeclaration(declName, undefined, classAlias ? ts.createAssignment(classAlias, classExpression) : classExpression) - ], 1)); + // let ${name} = ${classExpression} where name is either declaredName if the class doesn't contain self-reference + // or decoratedClassAlias if the class contain self-reference. + var statement = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(declName, + /*type*/ undefined, classAlias ? ts.createAssignment(classAlias, classExpression) : classExpression) + ], 1 /* Let */)); ts.setOriginalNode(statement, node); ts.setTextRange(statement, location); ts.setCommentRange(statement, node); return statement; } + /** + * Transforms a class expression with TypeScript syntax into compatible ES6. + * + * 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. + * + * @param node The node to transform. + */ function visitClassExpression(node) { var savedPendingExpressions = pendingExpressions; pendingExpressions = undefined; - var staticProperties = getInitializedProperties(node, true); + var staticProperties = getInitializedProperties(node, /*isStatic*/ true); var heritageClauses = ts.visitNodes(node.heritageClauses, visitor, ts.isHeritageClause); - var members = transformClassMembers(node, ts.some(heritageClauses, function (c) { return c.token === 85; })); - var classExpression = ts.createClassExpression(undefined, node.name, undefined, heritageClauses, members); + var members = transformClassMembers(node, ts.some(heritageClauses, function (c) { return c.token === 85 /* ExtendsKeyword */; })); + var classExpression = ts.createClassExpression( + /*modifiers*/ undefined, node.name, + /*typeParameters*/ undefined, heritageClauses, members); ts.setOriginalNode(classExpression, node); ts.setTextRange(classExpression, node); if (ts.some(staticProperties) || ts.some(pendingExpressions)) { var expressions = []; - var isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & 8388608; + var isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & 8388608 /* ClassWithConstructorReference */; var temp = ts.createTempVariable(hoistVariableDeclaration, !!isClassWithConstructorReference); if (isClassWithConstructorReference) { + // record an alias as the class name is not in scope for statics. enableSubstitutionForClassAliases(); var alias = ts.getSynthesizedClone(temp); - alias.autoGenerateFlags &= ~8; + alias.autoGenerateFlags &= ~8 /* ReservedInNestedScopes */; classAliases[ts.getOriginalNodeId(node)] = alias; } - ts.setEmitFlags(classExpression, 65536 | ts.getEmitFlags(classExpression)); + // To preserve the behavior of the old emitter, we explicitly indent + // the body of a class with static initializers. + ts.setEmitFlags(classExpression, 65536 /* Indented */ | ts.getEmitFlags(classExpression)); expressions.push(ts.startOnNewLine(ts.createAssignment(temp, classExpression))); + // Add any pending expressions leftover from elided or relocated computed property names ts.addRange(expressions, ts.map(pendingExpressions, ts.startOnNewLine)); pendingExpressions = savedPendingExpressions; ts.addRange(expressions, generateInitializedPropertyExpressions(staticProperties, temp)); @@ -53319,6 +62265,12 @@ var ts; pendingExpressions = savedPendingExpressions; return classExpression; } + /** + * Transforms the members of a class. + * + * @param node The current class. + * @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'. + */ function transformClassMembers(node, isDerivedClass) { var members = []; var constructor = transformConstructor(node, isDerivedClass); @@ -53326,52 +62278,137 @@ var ts; members.push(constructor); } ts.addRange(members, ts.visitNodes(node.members, classElementVisitor, ts.isClassElement)); - return ts.setTextRange(ts.createNodeArray(members), node.members); + return ts.setTextRange(ts.createNodeArray(members), /*location*/ node.members); } + /** + * Transforms (or creates) a constructor for a class. + * + * @param node The current class. + * @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'. + */ function transformConstructor(node, isDerivedClass) { + // 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 var hasInstancePropertyWithInitializer = ts.forEach(node.members, isInstanceInitializedProperty); - var hasParameterPropertyAssignments = node.transformFlags & 262144; + var hasParameterPropertyAssignments = node.transformFlags & 262144 /* ContainsParameterPropertyAssignments */; var constructor = ts.getFirstConstructorWithBody(node); + // If the class does not contain nodes that require a synthesized constructor, + // accept the current constructor if it exists. if (!hasInstancePropertyWithInitializer && !hasParameterPropertyAssignments) { return ts.visitEachChild(constructor, visitor, context); } var parameters = transformConstructorParameters(constructor); var body = transformConstructorBody(node, constructor, isDerivedClass); - return ts.startOnNewLine(ts.setOriginalNode(ts.setTextRange(ts.createConstructor(undefined, undefined, parameters, body), constructor || node), constructor)); + // constructor(${parameters}) { + // ${body} + // } + return ts.startOnNewLine(ts.setOriginalNode(ts.setTextRange(ts.createConstructor( + /*decorators*/ undefined, + /*modifiers*/ undefined, parameters, body), constructor || node), constructor)); } + /** + * Transforms (or creates) the parameters for the constructor of a class with + * parameter property assignments or instance property initializers. + * + * @param constructor The constructor declaration. + */ function transformConstructorParameters(constructor) { + // The ES2015 spec specifies in 14.5.14. Runtime Semantics: ClassDefinitionEvaluation: + // If constructor is empty, then + // If ClassHeritag_eopt is present and protoParent is not null, then + // Let constructor be the result of parsing the source text + // constructor(...args) { super (...args);} + // using the syntactic grammar with the goal symbol MethodDefinition[~Yield]. + // Else, + // Let constructor be the result of parsing the source text + // constructor( ){ } + // using the syntactic grammar with the goal symbol MethodDefinition[~Yield]. + // + // While we could emit the '...args' rest parameter, certain later tools in the pipeline might + // downlevel the '...args' portion less efficiently by naively copying the contents of 'arguments' to an array. + // Instead, we'll avoid using a rest parameter and spread into the super call as + // 'super(...arguments)' instead of 'super(...args)', as you can see in "transformConstructorBody". return ts.visitParameterList(constructor && constructor.parameters, visitor, context) || []; } + /** + * Transforms (or creates) a constructor body for a class with parameter property + * assignments or instance property initializers. + * + * @param node The current class. + * @param constructor The current class constructor. + * @param isDerivedClass A value indicating whether the class has an extends clause that does not extend 'null'. + */ function transformConstructorBody(node, constructor, isDerivedClass) { var statements = []; var indexOfFirstStatement = 0; resumeLexicalEnvironment(); if (constructor) { indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements); + // Add parameters with property assignments. Transforms this: + // + // constructor (public x, public y) { + // } + // + // Into this: + // + // constructor (x, y) { + // this.x = x; + // this.y = y; + // } + // var propertyAssignments = getParametersWithPropertyAssignments(constructor); ts.addRange(statements, ts.map(propertyAssignments, transformParameterWithPropertyAssignment)); } else if (isDerivedClass) { - statements.push(ts.createStatement(ts.createCall(ts.createSuper(), undefined, [ts.createSpread(ts.createIdentifier("arguments"))]))); + // Add a synthetic `super` call: + // + // super(...arguments); + // + statements.push(ts.createStatement(ts.createCall(ts.createSuper(), + /*typeArguments*/ undefined, [ts.createSpread(ts.createIdentifier("arguments"))]))); } - var properties = getInitializedProperties(node, false); + // Add the property initializers. Transforms this: + // + // public x = 1; + // + // Into this: + // + // constructor() { + // this.x = 1; + // } + // + var properties = getInitializedProperties(node, /*isStatic*/ false); addInitializedPropertyStatements(statements, properties, ts.createThis()); if (constructor) { + // The class already had a constructor, so we should add the existing statements, skipping the initial super call. ts.addRange(statements, ts.visitNodes(constructor.body.statements, visitor, ts.isStatement, indexOfFirstStatement)); } + // End the lexical environment. statements = ts.mergeLexicalEnvironment(statements, endLexicalEnvironment()); - return ts.setTextRange(ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), constructor ? constructor.body.statements : node.members), true), constructor ? constructor.body : undefined); + return ts.setTextRange(ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), + /*location*/ constructor ? constructor.body.statements : node.members), + /*multiLine*/ true), + /*location*/ constructor ? constructor.body : undefined); } + /** + * Adds super call and preceding prologue directives into the list of statements. + * + * @param ctor The constructor node. + * @returns index of the statement that follows super call + */ function addPrologueDirectivesAndInitialSuperCall(ctor, result) { if (ctor.body) { var statements = ctor.body.statements; - var index = ts.addPrologue(result, statements, false, visitor); + // add prologue directives to the list (if any) + var index = ts.addPrologue(result, statements, /*ensureUseStrict*/ false, visitor); if (index === statements.length) { + // list contains nothing but prologue directives (or empty) - exit return index; } var statement = statements[index]; - if (statement.kind === 216 && ts.isSuperCall(statement.expression)) { + if (statement.kind === 216 /* ExpressionStatement */ && ts.isSuperCall(statement.expression)) { result.push(ts.visitNode(statement, visitor, ts.isStatement)); return index + 1; } @@ -53379,36 +62416,79 @@ var ts; } return 0; } + /** + * Gets all parameters of a constructor that should be transformed into property assignments. + * + * @param node The constructor node. + */ function getParametersWithPropertyAssignments(node) { return ts.filter(node.parameters, isParameterWithPropertyAssignment); } + /** + * Determines whether a parameter should be transformed into a property assignment. + * + * @param parameter The parameter node. + */ function isParameterWithPropertyAssignment(parameter) { - return ts.hasModifier(parameter, 92) + return ts.hasModifier(parameter, 92 /* ParameterPropertyModifier */) && ts.isIdentifier(parameter.name); } + /** + * Transforms a parameter into a property assignment statement. + * + * @param node The parameter declaration. + */ function transformParameterWithPropertyAssignment(node) { ts.Debug.assert(ts.isIdentifier(node.name)); var name = node.name; var propertyName = ts.getMutableClone(name); - ts.setEmitFlags(propertyName, 1536 | 48); + ts.setEmitFlags(propertyName, 1536 /* NoComments */ | 48 /* NoSourceMap */); var localName = ts.getMutableClone(name); - ts.setEmitFlags(localName, 1536); - return ts.startOnNewLine(ts.setEmitFlags(ts.setTextRange(ts.createStatement(ts.createAssignment(ts.setTextRange(ts.createPropertyAccess(ts.createThis(), propertyName), node.name), localName)), ts.moveRangePos(node, -1)), 1536)); + ts.setEmitFlags(localName, 1536 /* NoComments */); + return ts.startOnNewLine(ts.setEmitFlags(ts.setTextRange(ts.createStatement(ts.createAssignment(ts.setTextRange(ts.createPropertyAccess(ts.createThis(), propertyName), node.name), localName)), ts.moveRangePos(node, -1)), 1536 /* NoComments */)); } + /** + * Gets all property declarations with initializers on either the static or instance side of a class. + * + * @param node The class node. + * @param isStatic A value indicating whether to get properties from the static or instance side of the class. + */ function getInitializedProperties(node, isStatic) { return ts.filter(node.members, isStatic ? isStaticInitializedProperty : isInstanceInitializedProperty); } + /** + * Gets a value indicating whether a class element is a static property declaration with an initializer. + * + * @param member The class element node. + */ function isStaticInitializedProperty(member) { - return isInitializedProperty(member, true); + return isInitializedProperty(member, /*isStatic*/ true); } + /** + * Gets a value indicating whether a class element is an instance property declaration with an initializer. + * + * @param member The class element node. + */ function isInstanceInitializedProperty(member) { - return isInitializedProperty(member, false); + return isInitializedProperty(member, /*isStatic*/ false); } + /** + * Gets a value indicating whether a class element is either a static or an instance property declaration with an initializer. + * + * @param member The class element node. + * @param isStatic A value indicating whether the member should be a static or instance member. + */ function isInitializedProperty(member, isStatic) { - return member.kind === 152 - && isStatic === ts.hasModifier(member, 32) + return member.kind === 152 /* PropertyDeclaration */ + && isStatic === ts.hasModifier(member, 32 /* Static */) && member.initializer !== undefined; } + /** + * Generates assignment statements for property initializers. + * + * @param properties An array of property declarations to transform. + * @param receiver The receiver on which each property should be assigned. + */ function addInitializedPropertyStatements(statements, properties, receiver) { for (var _i = 0, properties_10 = properties; _i < properties_10.length; _i++) { var property = properties_10[_i]; @@ -53418,6 +62498,12 @@ var ts; statements.push(statement); } } + /** + * Generates assignment expressions for property initializers. + * + * @param properties An array of property declarations to transform. + * @param receiver The receiver on which each property should be assigned. + */ function generateInitializedPropertyExpressions(properties, receiver) { var expressions = []; for (var _i = 0, properties_11 = properties; _i < properties_11.length; _i++) { @@ -53430,27 +62516,66 @@ var ts; } return expressions; } + /** + * Transforms a property initializer into an assignment statement. + * + * @param property The property declaration. + * @param receiver The object receiving the property assignment. + */ function transformInitializedProperty(property, receiver) { + // We generate a name here in order to reuse the value cached by the relocated computed name expression (which uses the same generated name) var propertyName = ts.isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression) ? ts.updateComputedPropertyName(property.name, ts.getGeneratedNameForNode(property.name)) : property.name; var initializer = ts.visitNode(property.initializer, visitor, ts.isExpression); - var memberAccess = ts.createMemberAccessForPropertyName(receiver, propertyName, propertyName); + var memberAccess = ts.createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName); return ts.createAssignment(memberAccess, initializer); } + /** + * Gets either the static or instance members of a class that are decorated, or have + * parameters that are decorated. + * + * @param node The class containing the member. + * @param isStatic A value indicating whether to retrieve static or instance members of + * the class. + */ function getDecoratedClassElements(node, isStatic) { return ts.filter(node.members, isStatic ? function (m) { return isStaticDecoratedClassElement(m, node); } : function (m) { return isInstanceDecoratedClassElement(m, node); }); } + /** + * Determines whether a class member is a static member of a class that is decorated, or + * has parameters that are decorated. + * + * @param member The class member. + */ function isStaticDecoratedClassElement(member, parent) { - return isDecoratedClassElement(member, true, parent); + return isDecoratedClassElement(member, /*isStatic*/ true, parent); } + /** + * Determines whether a class member is an instance member of a class that is decorated, + * or has parameters that are decorated. + * + * @param member The class member. + */ function isInstanceDecoratedClassElement(member, parent) { - return isDecoratedClassElement(member, false, parent); + return isDecoratedClassElement(member, /*isStatic*/ false, parent); } + /** + * Determines whether a class member is either a static or an instance member of a class + * that is decorated, or has parameters that are decorated. + * + * @param member The class member. + */ function isDecoratedClassElement(member, isStatic, parent) { return ts.nodeOrChildIsDecorated(member, parent) - && isStatic === ts.hasModifier(member, 32); + && isStatic === ts.hasModifier(member, 32 /* Static */); } + /** + * Gets an array of arrays of decorators for the parameters of a function-like node. + * The offset into the result array should correspond to the offset of the parameter. + * + * @param node The function-like node. + */ function getDecoratorsOfParameters(node) { var decorators; if (node) { @@ -53467,6 +62592,12 @@ var ts; } return decorators; } + /** + * Gets an AllDecorators object containing the decorators for the class and the decorators for the + * parameters of the constructor of the class. + * + * @param node The class node. + */ function getAllDecoratorsOfConstructor(node) { var decorators = node.decorators; var parameters = getDecoratorsOfParameters(ts.getFirstConstructorWithBody(node)); @@ -53478,19 +62609,31 @@ var ts; parameters: parameters }; } + /** + * Gets an AllDecorators object containing the decorators for the member and its parameters. + * + * @param node The class node that contains the member. + * @param member The class member. + */ function getAllDecoratorsOfClassElement(node, member) { switch (member.kind) { - case 156: - case 157: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return getAllDecoratorsOfAccessors(node, member); - case 154: + case 154 /* MethodDeclaration */: return getAllDecoratorsOfMethod(member); - case 152: + case 152 /* PropertyDeclaration */: return getAllDecoratorsOfProperty(member); default: return undefined; } } + /** + * Gets an AllDecorators object containing the decorators for the accessor and its parameters. + * + * @param node The class node that contains the accessor. + * @param accessor The class accessor member. + */ function getAllDecoratorsOfAccessors(node, accessor) { if (!accessor.body) { return undefined; @@ -53507,6 +62650,11 @@ var ts; } return { decorators: decorators, parameters: parameters }; } + /** + * Gets an AllDecorators object containing the decorators for the method and its parameters. + * + * @param method The class method member. + */ function getAllDecoratorsOfMethod(method) { if (!method.body) { return undefined; @@ -53518,6 +62666,11 @@ var ts; } return { decorators: decorators, parameters: parameters }; } + /** + * Gets an AllDecorators object containing the decorators for the property. + * + * @param property The class property member. + */ function getAllDecoratorsOfProperty(property) { var decorators = property.decorators; if (!decorators) { @@ -53525,6 +62678,12 @@ var ts; } return { decorators: decorators }; } + /** + * Transforms all of the decorators for a declaration into an array of expressions. + * + * @param node The declaration node. + * @param allDecorators An object containing all of the decorators for the declaration. + */ function transformAllDecoratorsOfDeclaration(node, container, allDecorators) { if (!allDecorators) { return undefined; @@ -53535,9 +62694,25 @@ var ts; addTypeMetadata(node, container, decoratorExpressions); return decoratorExpressions; } + /** + * Generates statements used to apply decorators to either the static or instance members + * of a class. + * + * @param node The class node. + * @param isStatic A value indicating whether to generate statements for static or + * instance members. + */ function addClassElementDecorationStatements(statements, node, isStatic) { ts.addRange(statements, ts.map(generateClassElementDecorationExpressions(node, isStatic), expressionToStatement)); } + /** + * Generates expressions used to apply decorators to either the static or instance members + * of a class. + * + * @param node The class node. + * @param isStatic A value indicating whether to generate expressions for static or + * instance members. + */ function generateClassElementDecorationExpressions(node, isStatic) { var members = getDecoratedClassElements(node, isStatic); var expressions; @@ -53555,29 +62730,79 @@ var ts; } return expressions; } + /** + * Generates an expression used to evaluate class element decorators at runtime. + * + * @param node The class node that contains the member. + * @param member The class member. + */ function generateClassElementDecorationExpression(node, member) { var allDecorators = getAllDecoratorsOfClassElement(node, member); var decoratorExpressions = transformAllDecoratorsOfDeclaration(member, node, allDecorators); if (!decoratorExpressions) { return undefined; } + // 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: + // + // __decorate([ + // dec, + // __param(0, dec2), + // __metadata("design:type", Function), + // __metadata("design:paramtypes", [Object]), + // __metadata("design:returntype", void 0) + // ], C.prototype, "method", null); + // + // The emit for an accessor is: + // + // __decorate([ + // dec + // ], C.prototype, "accessor", null); + // + // The emit for a property is: + // + // __decorate([ + // dec + // ], C.prototype, "prop"); + // var prefix = getClassMemberPrefix(node, member); - var memberName = getExpressionForPropertyName(member, true); - var descriptor = languageVersion > 0 - ? member.kind === 152 + var memberName = getExpressionForPropertyName(member, /*generateNameForComputedPropertyName*/ true); + var descriptor = languageVersion > 0 /* ES3 */ + ? member.kind === 152 /* PropertyDeclaration */ + // We emit `void 0` here to indicate to `__decorate` that it can invoke `Object.defineProperty` directly, but that it + // should not invoke `Object.getOwnPropertyDescriptor`. ? ts.createVoidZero() + // We emit `null` here to indicate to `__decorate` that it can invoke `Object.getOwnPropertyDescriptor` directly. + // We have this extra argument here so that we can inject an explicit property descriptor at a later date. : ts.createNull() : undefined; var helper = createDecorateHelper(context, decoratorExpressions, prefix, memberName, descriptor, ts.moveRangePastDecorators(member)); - ts.setEmitFlags(helper, 1536); + ts.setEmitFlags(helper, 1536 /* NoComments */); return helper; } + /** + * Generates a __decorate helper call for a class constructor. + * + * @param node The class node. + */ function addConstructorDecorationStatement(statements, node) { var expression = generateConstructorDecorationExpression(node); if (expression) { statements.push(ts.setOriginalNode(ts.createStatement(expression), node)); } } + /** + * Generates a __decorate helper call for a class constructor. + * + * @param node The class node. + */ function generateConstructorDecorationExpression(node) { var allDecorators = getAllDecoratorsOfConstructor(node); var decoratorExpressions = transformAllDecoratorsOfDeclaration(node, node, allDecorators); @@ -53585,29 +62810,47 @@ var ts; return undefined; } var classAlias = classAliases && classAliases[ts.getOriginalNodeId(node)]; - var localName = ts.getLocalName(node, false, true); + var localName = ts.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); var decorate = createDecorateHelper(context, decoratorExpressions, localName); var expression = ts.createAssignment(localName, classAlias ? ts.createAssignment(classAlias, decorate) : decorate); - ts.setEmitFlags(expression, 1536); + ts.setEmitFlags(expression, 1536 /* NoComments */); ts.setSourceMapRange(expression, ts.moveRangePastDecorators(node)); return expression; } + /** + * Transforms a decorator into an expression. + * + * @param decorator The decorator node. + */ function transformDecorator(decorator) { return ts.visitNode(decorator.expression, visitor, ts.isExpression); } + /** + * Transforms the decorators of a parameter. + * + * @param decorators The decorators for the parameter at the provided offset. + * @param parameterOffset The offset of the parameter. + */ function transformDecoratorsOfParameter(decorators, parameterOffset) { var expressions; if (decorators) { expressions = []; for (var _i = 0, decorators_1 = decorators; _i < decorators_1.length; _i++) { var decorator = decorators_1[_i]; - var helper = createParamHelper(context, transformDecorator(decorator), parameterOffset, decorator.expression); - ts.setEmitFlags(helper, 1536); + var helper = createParamHelper(context, transformDecorator(decorator), parameterOffset, + /*location*/ decorator.expression); + ts.setEmitFlags(helper, 1536 /* NoComments */); expressions.push(helper); } } return expressions; } + /** + * Adds optional type metadata for a declaration. + * + * @param node The declaration node. + * @param decoratorExpressions The destination array to which to add new decorator expressions. + */ function addTypeMetadata(node, container, decoratorExpressions) { if (USE_NEW_TYPE_METADATA_FORMAT) { addNewTypeMetadata(node, container, decoratorExpressions); @@ -53633,57 +62876,88 @@ var ts; if (compilerOptions.emitDecoratorMetadata) { var properties = void 0; if (shouldAddTypeMetadata(node)) { - (properties || (properties = [])).push(ts.createPropertyAssignment("type", ts.createArrowFunction(undefined, undefined, [], undefined, ts.createToken(36), serializeTypeOfNode(node)))); + (properties || (properties = [])).push(ts.createPropertyAssignment("type", ts.createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, ts.createToken(36 /* EqualsGreaterThanToken */), serializeTypeOfNode(node)))); } if (shouldAddParamTypesMetadata(node)) { - (properties || (properties = [])).push(ts.createPropertyAssignment("paramTypes", ts.createArrowFunction(undefined, undefined, [], undefined, ts.createToken(36), serializeParameterTypesOfNode(node, container)))); + (properties || (properties = [])).push(ts.createPropertyAssignment("paramTypes", ts.createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, ts.createToken(36 /* EqualsGreaterThanToken */), serializeParameterTypesOfNode(node, container)))); } if (shouldAddReturnTypeMetadata(node)) { - (properties || (properties = [])).push(ts.createPropertyAssignment("returnType", ts.createArrowFunction(undefined, undefined, [], undefined, ts.createToken(36), serializeReturnTypeOfNode(node)))); + (properties || (properties = [])).push(ts.createPropertyAssignment("returnType", ts.createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, ts.createToken(36 /* EqualsGreaterThanToken */), serializeReturnTypeOfNode(node)))); } if (properties) { - decoratorExpressions.push(createMetadataHelper(context, "design:typeinfo", ts.createObjectLiteral(properties, true))); + decoratorExpressions.push(createMetadataHelper(context, "design:typeinfo", ts.createObjectLiteral(properties, /*multiLine*/ true))); } } } + /** + * 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. + * + * @param node The node to test. + */ function shouldAddTypeMetadata(node) { var kind = node.kind; - return kind === 154 - || kind === 156 - || kind === 157 - || kind === 152; + return kind === 154 /* MethodDeclaration */ + || kind === 156 /* GetAccessor */ + || kind === 157 /* SetAccessor */ + || kind === 152 /* PropertyDeclaration */; } + /** + * 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. + * + * @param node The node to test. + */ function shouldAddReturnTypeMetadata(node) { - return node.kind === 154; + return node.kind === 154 /* MethodDeclaration */; } + /** + * 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. + * + * @param node The node to test. + */ function shouldAddParamTypesMetadata(node) { switch (node.kind) { - case 235: - case 205: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: return ts.getFirstConstructorWithBody(node) !== undefined; - case 154: - case 156: - case 157: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return true; } return false; } + /** + * Serializes the type of a node for use with decorator type metadata. + * + * @param node The node that should have its type serialized. + */ function serializeTypeOfNode(node) { switch (node.kind) { - case 152: - case 149: - case 156: + case 152 /* PropertyDeclaration */: + case 149 /* Parameter */: + case 156 /* GetAccessor */: return serializeTypeNode(node.type); - case 157: + case 157 /* SetAccessor */: return serializeTypeNode(ts.getSetAccessorTypeAnnotationNode(node)); - case 235: - case 205: - case 154: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 154 /* MethodDeclaration */: return ts.createIdentifier("Function"); default: return ts.createVoidZero(); } } + /** + * Serializes the types of the parameters of a node for use with decorator type metadata. + * + * @param node The node that should have its parameter types serialized. + */ function serializeParameterTypesOfNode(node, container) { var valueDeclaration = ts.isClassLike(node) ? ts.getFirstConstructorWithBody(node) @@ -53710,7 +62984,7 @@ var ts; return ts.createArrayLiteral(expressions); } function getParametersOfDecoratedDeclaration(node, container) { - if (container && node.kind === 156) { + if (container && node.kind === 156 /* GetAccessor */) { var setAccessor = ts.getAllAccessorDeclarations(container.members, node).setAccessor; if (setAccessor) { return setAccessor.parameters; @@ -53718,6 +62992,11 @@ var ts; } return node.parameters; } + /** + * Serializes the return type of a node for use with decorator type metadata. + * + * @param node The node that should have its return type serialized. + */ function serializeReturnTypeOfNode(node) { if (ts.isFunctionLike(node) && node.type) { return serializeTypeNode(node.type); @@ -53727,63 +63006,81 @@ var ts; } return ts.createVoidZero(); } + /** + * Serializes a type node for use with decorator type metadata. + * + * Types are serialized in the following fashion: + * - Void types point to "undefined" (e.g. "void 0") + * - Function and Constructor types point to the global "Function" constructor. + * - Interface types with a call or construct signature types point to the global + * "Function" constructor. + * - Array and Tuple types point to the global "Array" constructor. + * - Type predicates and booleans point to the global "Boolean" constructor. + * - String literal types and strings point to the global "String" constructor. + * - Enum and number types point to the global "Number" constructor. + * - Symbol types point to the global "Symbol" constructor. + * - Type references to classes (or class-like variables) point to the constructor for the class. + * - Anything else points to the global "Object" constructor. + * + * @param node The type node to serialize. + */ function serializeTypeNode(node) { if (node === undefined) { return ts.createIdentifier("Object"); } switch (node.kind) { - case 105: - case 140: - case 95: - case 131: + case 105 /* VoidKeyword */: + case 140 /* UndefinedKeyword */: + case 95 /* NullKeyword */: + case 131 /* NeverKeyword */: return ts.createVoidZero(); - case 173: + case 173 /* ParenthesizedType */: return serializeTypeNode(node.type); - case 163: - case 164: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: return ts.createIdentifier("Function"); - case 167: - case 168: + case 167 /* ArrayType */: + case 168 /* TupleType */: return ts.createIdentifier("Array"); - case 161: - case 122: + case 161 /* TypePredicate */: + case 122 /* BooleanKeyword */: return ts.createIdentifier("Boolean"); - case 137: + case 137 /* StringKeyword */: return ts.createIdentifier("String"); - case 135: + case 135 /* ObjectKeyword */: return ts.createIdentifier("Object"); - case 178: + case 178 /* LiteralType */: switch (node.literal.kind) { - case 9: + case 9 /* StringLiteral */: return ts.createIdentifier("String"); - case 8: + case 8 /* NumericLiteral */: return ts.createIdentifier("Number"); - case 101: - case 86: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: return ts.createIdentifier("Boolean"); default: return ts.Debug.failBadSyntaxKind(node.literal); } - case 134: + case 134 /* NumberKeyword */: return ts.createIdentifier("Number"); - case 138: - return languageVersion < 2 + case 138 /* SymbolKeyword */: + return languageVersion < 2 /* ES2015 */ ? getGlobalSymbolNameWithFallback() : ts.createIdentifier("Symbol"); - case 162: + case 162 /* TypeReference */: return serializeTypeReferenceNode(node); - case 170: - case 169: + case 170 /* IntersectionType */: + case 169 /* UnionType */: return serializeUnionOrIntersectionType(node); - case 165: - case 175: - case 176: - case 177: - case 166: - case 119: - case 142: - case 174: - case 179: + case 165 /* TypeQuery */: + case 175 /* TypeOperator */: + case 176 /* IndexedAccessType */: + case 177 /* MappedType */: + case 166 /* TypeLiteral */: + case 119 /* AnyKeyword */: + case 142 /* UnknownKeyword */: + case 174 /* ThisType */: + case 179 /* ImportType */: break; default: return ts.Debug.failBadSyntaxKind(node); @@ -53791,23 +63088,29 @@ var ts; return ts.createIdentifier("Object"); } function serializeUnionOrIntersectionType(node) { + // Note when updating logic here also update getEntityNameForDecoratorMetadata + // so that aliases can be marked as referenced var serializedUnion; for (var _i = 0, _a = node.types; _i < _a.length; _i++) { var typeNode = _a[_i]; - while (typeNode.kind === 173) { - typeNode = typeNode.type; + while (typeNode.kind === 173 /* ParenthesizedType */) { + typeNode = typeNode.type; // Skip parens if need be } - if (typeNode.kind === 131) { - continue; + if (typeNode.kind === 131 /* NeverKeyword */) { + continue; // Always elide `never` from the union/intersection if possible } - if (!strictNullChecks && (typeNode.kind === 95 || typeNode.kind === 140)) { - continue; + if (!strictNullChecks && (typeNode.kind === 95 /* NullKeyword */ || typeNode.kind === 140 /* UndefinedKeyword */)) { + continue; // Elide null and undefined from unions for metadata, just like what we did prior to the implementation of strict null checks } var serializedIndividual = serializeTypeNode(typeNode); if (ts.isIdentifier(serializedIndividual) && serializedIndividual.escapedText === "Object") { + // One of the individual is global object, return immediately return serializedIndividual; } + // If there exists union that is not void 0 expression, check if the the common type is identifier. + // anything more complex and we will just default to Object else if (serializedUnion) { + // Different types if (!ts.isIdentifier(serializedUnion) || !ts.isIdentifier(serializedIndividual) || serializedUnion.escapedText !== serializedIndividual.escapedText) { @@ -53815,20 +63118,28 @@ var ts; } } else { + // Initialize the union type serializedUnion = serializedIndividual; } } - return serializedUnion || ts.createVoidZero(); + // If we were able to find common type, use it + return serializedUnion || ts.createVoidZero(); // Fallback is only hit if all union constituients are null/undefined/never } + /** + * Serializes a TypeReferenceNode to an appropriate JS constructor value for use with + * decorator type metadata. + * + * @param node The type reference node. + */ function serializeTypeReferenceNode(node) { var kind = resolver.getTypeReferenceSerializationKind(node.typeName, currentScope); switch (kind) { case ts.TypeReferenceSerializationKind.Unknown: - var serialized = serializeEntityNameAsExpression(node.typeName, true); + var serialized = serializeEntityNameAsExpression(node.typeName, /*useFallback*/ true); var temp = ts.createTempVariable(hoistVariableDeclaration); return ts.createLogicalOr(ts.createLogicalAnd(ts.createTypeCheck(ts.createAssignment(temp, serialized), "function"), temp), ts.createIdentifier("Object")); case ts.TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue: - return serializeEntityNameAsExpression(node.typeName, false); + return serializeEntityNameAsExpression(node.typeName, /*useFallback*/ false); case ts.TypeReferenceSerializationKind.VoidNullableOrNeverType: return ts.createVoidZero(); case ts.TypeReferenceSerializationKind.BooleanType: @@ -53840,7 +63151,7 @@ var ts; case ts.TypeReferenceSerializationKind.ArrayLikeType: return ts.createIdentifier("Array"); case ts.TypeReferenceSerializationKind.ESSymbolType: - return languageVersion < 2 + return languageVersion < 2 /* ES2015 */ ? getGlobalSymbolNameWithFallback() : ts.createIdentifier("Symbol"); case ts.TypeReferenceSerializationKind.TypeWithCallSignature: @@ -53853,42 +63164,73 @@ var ts; return ts.Debug.assertNever(kind); } } + /** + * Serializes an entity name as an expression for decorator type metadata. + * + * @param node The entity name to serialize. + * @param useFallback A value indicating whether to use logical operators to test for the + * entity name at runtime. + */ function serializeEntityNameAsExpression(node, useFallback) { switch (node.kind) { - case 71: + case 71 /* Identifier */: + // Create a clone of the name with a new parent, and treat it as if it were + // a source tree node for the purposes of the checker. var name = ts.getMutableClone(node); - name.flags &= ~8; + name.flags &= ~8 /* Synthesized */; name.original = undefined; - name.parent = ts.getParseTreeNode(currentScope); + name.parent = ts.getParseTreeNode(currentScope); // ensure the parent is set to a parse tree node. if (useFallback) { return ts.createLogicalAnd(ts.createStrictInequality(ts.createTypeOf(name), ts.createLiteral("undefined")), name); } return name; - case 146: + case 146 /* QualifiedName */: return serializeQualifiedNameAsExpression(node, useFallback); } } + /** + * Serializes an qualified name as an expression for decorator type metadata. + * + * @param node The qualified name to serialize. + * @param useFallback A value indicating whether to use logical operators to test for the + * qualified name at runtime. + */ function serializeQualifiedNameAsExpression(node, useFallback) { var left; - if (node.left.kind === 71) { + if (node.left.kind === 71 /* Identifier */) { left = serializeEntityNameAsExpression(node.left, useFallback); } else if (useFallback) { var temp = ts.createTempVariable(hoistVariableDeclaration); - left = ts.createLogicalAnd(ts.createAssignment(temp, serializeEntityNameAsExpression(node.left, true)), temp); + left = ts.createLogicalAnd(ts.createAssignment(temp, serializeEntityNameAsExpression(node.left, /*useFallback*/ true)), temp); } else { - left = serializeEntityNameAsExpression(node.left, false); + left = serializeEntityNameAsExpression(node.left, /*useFallback*/ false); } return ts.createPropertyAccess(left, node.right); } + /** + * Gets an expression that points to the global "Symbol" constructor at runtime if it is + * available. + */ function getGlobalSymbolNameWithFallback() { return ts.createConditional(ts.createTypeCheck(ts.createIdentifier("Symbol"), "function"), ts.createIdentifier("Symbol"), ts.createIdentifier("Object")); } + /** + * A simple inlinable expression is an expression which can be copied into multiple locations + * without risk of repeating any sideeffects and whose value could not possibly change between + * any such locations + */ function isSimpleInlineableExpression(expression) { return !ts.isIdentifier(expression) && ts.isSimpleCopiableExpression(expression) || ts.isWellKnownSymbolSyntactically(expression); } + /** + * Gets an expression that represents a property name. For a computed property, a + * name is generated for the node. + * + * @param member The member whose name should be converted into an expression. + */ function getExpressionForPropertyName(member, generateNameForComputedPropertyName) { var name = member.name; if (ts.isComputedPropertyName(name)) { @@ -53903,6 +63245,12 @@ var ts; return ts.getSynthesizedClone(name); } } + /** + * If the name is a computed property, this function transforms it, then either returns an expression which caches the + * value of the result or the expression itself if the value is either unused or safe to inline into multiple locations + * @param shouldHoist Does the expression need to be reused? (ie, for an initializer or a decorator) + * @param omitSimple Should expressions with no observable side-effects be elided? (ie, the expression is not hoisted for a decorator or initializer and is a literal) + */ function getPropertyNameExpressionIfNeeded(name, shouldHoist, omitSimple) { if (ts.isComputedPropertyName(name)) { var expression = ts.visitNode(name.expression, visitor, ts.isExpression); @@ -53916,10 +63264,18 @@ var ts; return (omitSimple && (inlinable || ts.isIdentifier(innerExpression))) ? undefined : expression; } } + /** + * Visits the property name of a class element, for use when emitting property + * initializers. For a computed property on a node with decorators, a temporary + * value is stored for later use. + * + * @param member The member whose name should be visited. + */ function visitPropertyNameOfClassElement(member) { var name = member.name; - var expr = getPropertyNameExpressionIfNeeded(name, ts.some(member.decorators), false); - if (expr) { + var expr = getPropertyNameExpressionIfNeeded(name, ts.some(member.decorators), /*omitSimple*/ false); + if (expr) { // expr only exists if `name` is a computed property name + // Inline any pending expressions from previous elided or relocated computed property name expressions in order to preserve execution order if (ts.some(pendingExpressions)) { expr = ts.inlineExpressions(pendingExpressions.concat([expr])); pendingExpressions.length = 0; @@ -53930,21 +63286,45 @@ var ts; return name; } } + /** + * Transforms a HeritageClause with TypeScript syntax. + * + * 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 that should be visited, but only allow a single type. + * + * @param node The HeritageClause to transform. + */ function visitHeritageClause(node) { - if (node.token === 85) { + if (node.token === 85 /* ExtendsKeyword */) { var types = ts.visitNodes(node.types, visitor, ts.isExpressionWithTypeArguments, 0, 1); - return ts.setTextRange(ts.createHeritageClause(85, types), node); + return ts.setTextRange(ts.createHeritageClause(85 /* ExtendsKeyword */, types), node); } return undefined; } + /** + * Transforms an ExpressionWithTypeArguments with TypeScript syntax. + * + * This function will only be called when one of the following conditions are met: + * - The node contains type arguments that should be elided. + * + * @param node The ExpressionWithTypeArguments to transform. + */ function visitExpressionWithTypeArguments(node) { - return ts.updateExpressionWithTypeArguments(node, undefined, ts.visitNode(node.expression, visitor, ts.isLeftHandSideExpression)); + return ts.updateExpressionWithTypeArguments(node, + /*typeArguments*/ undefined, ts.visitNode(node.expression, visitor, ts.isLeftHandSideExpression)); } + /** + * Determines whether to emit a function-like declaration. We should not emit the + * declaration if it does not have a body. + * + * @param node The declaration node. + */ function shouldEmitFunctionLikeDeclaration(node) { return !ts.nodeIsMissing(node.body); } function visitPropertyDeclaration(node) { - var expr = getPropertyNameExpressionIfNeeded(node.name, ts.some(node.decorators) || !!node.initializer, true); + var expr = getPropertyNameExpressionIfNeeded(node.name, ts.some(node.decorators) || !!node.initializer, /*omitSimple*/ true); if (expr && !isSimpleInlineableExpression(expr)) { (pendingExpressions || (pendingExpressions = [])).push(expr); } @@ -53956,47 +63336,107 @@ var ts; } return ts.updateConstructor(node, ts.visitNodes(node.decorators, visitor, ts.isDecorator), ts.visitNodes(node.modifiers, visitor, ts.isModifier), ts.visitParameterList(node.parameters, visitor, context), ts.visitFunctionBody(node.body, visitor, context)); } + /** + * Visits a method declaration of a class. + * + * This function will be called when one of the following conditions are met: + * - The node is an overload + * - The node is marked as abstract, public, private, protected, or readonly + * - The node has a computed property name + * + * @param node The method node. + */ function visitMethodDeclaration(node) { if (!shouldEmitFunctionLikeDeclaration(node)) { return undefined; } - var updated = ts.updateMethod(node, undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), node.asteriskToken, visitPropertyNameOfClassElement(node), undefined, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, ts.visitFunctionBody(node.body, visitor, context)); + var updated = ts.updateMethod(node, + /*decorators*/ undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), node.asteriskToken, visitPropertyNameOfClassElement(node), + /*questionToken*/ undefined, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, ts.visitFunctionBody(node.body, visitor, context)); if (updated !== node) { + // While we emit the source map for the node after skipping decorators and modifiers, + // we need to emit the comments for the original range. ts.setCommentRange(updated, node); ts.setSourceMapRange(updated, ts.moveRangePastDecorators(node)); } return updated; } + /** + * Determines whether to emit an accessor declaration. We should not emit the + * declaration if it does not have a body and is abstract. + * + * @param node The declaration node. + */ function shouldEmitAccessorDeclaration(node) { - return !(ts.nodeIsMissing(node.body) && ts.hasModifier(node, 128)); + return !(ts.nodeIsMissing(node.body) && ts.hasModifier(node, 128 /* Abstract */)); } + /** + * Visits a get accessor declaration of a class. + * + * This function will be called when one of the following conditions are met: + * - The node is marked as abstract, public, private, or protected + * - The node has a computed property name + * + * @param node The get accessor node. + */ function visitGetAccessor(node) { if (!shouldEmitAccessorDeclaration(node)) { return undefined; } - var updated = ts.updateGetAccessor(node, undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), visitPropertyNameOfClassElement(node), ts.visitParameterList(node.parameters, visitor, context), undefined, ts.visitFunctionBody(node.body, visitor, context) || ts.createBlock([])); + var updated = ts.updateGetAccessor(node, + /*decorators*/ undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), visitPropertyNameOfClassElement(node), ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, ts.visitFunctionBody(node.body, visitor, context) || ts.createBlock([])); if (updated !== node) { + // While we emit the source map for the node after skipping decorators and modifiers, + // we need to emit the comments for the original range. ts.setCommentRange(updated, node); ts.setSourceMapRange(updated, ts.moveRangePastDecorators(node)); } return updated; } + /** + * Visits a set accessor declaration of a class. + * + * This function will be called when one of the following conditions are met: + * - The node is marked as abstract, public, private, or protected + * - The node has a computed property name + * + * @param node The set accessor node. + */ function visitSetAccessor(node) { if (!shouldEmitAccessorDeclaration(node)) { return undefined; } - var updated = ts.updateSetAccessor(node, undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), visitPropertyNameOfClassElement(node), ts.visitParameterList(node.parameters, visitor, context), ts.visitFunctionBody(node.body, visitor, context) || ts.createBlock([])); + var updated = ts.updateSetAccessor(node, + /*decorators*/ undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), visitPropertyNameOfClassElement(node), ts.visitParameterList(node.parameters, visitor, context), ts.visitFunctionBody(node.body, visitor, context) || ts.createBlock([])); if (updated !== node) { + // While we emit the source map for the node after skipping decorators and modifiers, + // we need to emit the comments for the original range. ts.setCommentRange(updated, node); ts.setSourceMapRange(updated, ts.moveRangePastDecorators(node)); } return updated; } + /** + * Visits a function declaration. + * + * This function will be called when one of the following conditions are met: + * - The node is an overload + * - The node is exported from a TypeScript namespace + * - The node has decorators + * + * @param node The function node. + */ function visitFunctionDeclaration(node) { if (!shouldEmitFunctionLikeDeclaration(node)) { return ts.createNotEmittedStatement(node); } - var updated = ts.updateFunctionDeclaration(node, undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), node.asteriskToken, node.name, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, ts.visitFunctionBody(node.body, visitor, context) || ts.createBlock([])); + var updated = ts.updateFunctionDeclaration(node, + /*decorators*/ undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), node.asteriskToken, node.name, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, ts.visitFunctionBody(node.body, visitor, context) || ts.createBlock([])); if (isExportOfNamespace(node)) { var statements = [updated]; addExportMemberAssignment(statements, node); @@ -54004,33 +63444,73 @@ var ts; } return updated; } + /** + * Visits a function expression node. + * + * This function will be called when one of the following conditions are met: + * - The node has type annotations + * + * @param node The function expression node. + */ function visitFunctionExpression(node) { if (!shouldEmitFunctionLikeDeclaration(node)) { return ts.createOmittedExpression(); } - var updated = ts.updateFunctionExpression(node, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), node.asteriskToken, node.name, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, ts.visitFunctionBody(node.body, visitor, context) || ts.createBlock([])); + var updated = ts.updateFunctionExpression(node, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), node.asteriskToken, node.name, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, ts.visitFunctionBody(node.body, visitor, context) || ts.createBlock([])); return updated; } + /** + * @remarks + * This function will be called when one of the following conditions are met: + * - The node has type annotations + */ function visitArrowFunction(node) { - var updated = ts.updateArrowFunction(node, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, node.equalsGreaterThanToken, ts.visitFunctionBody(node.body, visitor, context)); + var updated = ts.updateArrowFunction(node, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, node.equalsGreaterThanToken, ts.visitFunctionBody(node.body, visitor, context)); return updated; } + /** + * Visits a parameter declaration node. + * + * This function will be called when one of the following conditions are met: + * - The node has an accessibility modifier. + * - The node has a questionToken. + * - The node's kind is ThisKeyword. + * + * @param node The parameter declaration node. + */ function visitParameter(node) { if (ts.parameterIsThisKeyword(node)) { return undefined; } - var parameter = ts.createParameter(undefined, undefined, node.dotDotDotToken, ts.visitNode(node.name, visitor, ts.isBindingName), undefined, undefined, ts.visitNode(node.initializer, visitor, ts.isExpression)); + var parameter = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, node.dotDotDotToken, ts.visitNode(node.name, visitor, ts.isBindingName), + /*questionToken*/ undefined, + /*type*/ undefined, ts.visitNode(node.initializer, visitor, ts.isExpression)); + // While we emit the source map for the node after skipping decorators and modifiers, + // we need to emit the comments for the original range. ts.setOriginalNode(parameter, node); ts.setTextRange(parameter, ts.moveRangePastModifiers(node)); ts.setCommentRange(parameter, node); ts.setSourceMapRange(parameter, ts.moveRangePastModifiers(node)); - ts.setEmitFlags(parameter.name, 32); + ts.setEmitFlags(parameter.name, 32 /* NoTrailingSourceMap */); return parameter; } + /** + * Visits a variable statement in a namespace. + * + * This function will be called when one of the following conditions are met: + * - The node is exported from a TypeScript namespace. + */ function visitVariableStatement(node) { if (isExportOfNamespace(node)) { var variables = ts.getInitializedVariables(node.declarationList); if (variables.length === 0) { + // elide statement if there are no initialized variables. return undefined; } return ts.setTextRange(ts.createStatement(ts.inlineExpressions(ts.map(variables, transformInitializedVariable))), node); @@ -54042,19 +63522,45 @@ var ts; function transformInitializedVariable(node) { var name = node.name; if (ts.isBindingPattern(name)) { - return ts.flattenDestructuringAssignment(node, visitor, context, 0, false, createNamespaceExportExpression); + return ts.flattenDestructuringAssignment(node, visitor, context, 0 /* All */, + /*needsValue*/ false, createNamespaceExportExpression); } else { - return ts.setTextRange(ts.createAssignment(getNamespaceMemberNameWithSourceMapsAndWithoutComments(name), ts.visitNode(node.initializer, visitor, ts.isExpression)), node); + return ts.setTextRange(ts.createAssignment(getNamespaceMemberNameWithSourceMapsAndWithoutComments(name), ts.visitNode(node.initializer, visitor, ts.isExpression)), + /*location*/ node); } } function visitVariableDeclaration(node) { - return ts.updateVariableDeclaration(node, ts.visitNode(node.name, visitor, ts.isBindingName), undefined, ts.visitNode(node.initializer, visitor, ts.isExpression)); + return ts.updateVariableDeclaration(node, ts.visitNode(node.name, visitor, ts.isBindingName), + /*type*/ undefined, ts.visitNode(node.initializer, visitor, ts.isExpression)); } + /** + * Visits a parenthesized expression that contains either a type assertion or an `as` + * expression. + * + * @param node The parenthesized expression node. + */ function visitParenthesizedExpression(node) { - var innerExpression = ts.skipOuterExpressions(node.expression, ~2); + var innerExpression = ts.skipOuterExpressions(node.expression, ~2 /* Assertions */); if (ts.isAssertionExpression(innerExpression)) { + // Make sure we consider all nested cast expressions, e.g.: + // (-A).x; var expression = ts.visitNode(node.expression, visitor, ts.isExpression); + // We have an expression of the form: (SubExpr). Emitting this as (SubExpr) + // is really not desirable. We would like to emit the subexpression as-is. Omitting + // the parentheses, however, could cause change in the semantics of the generated + // code if the casted expression has a lower precedence than the rest of the + // expression. + // + // To preserve comments, we return a "PartiallyEmittedExpression" here which will + // preserve the position information of the original expression. + // + // Due to the auto-parenthesization rules used by the visitor and factory functions + // we can safely elide the parentheses here, as a new synthetic + // ParenthesizedExpression will be inserted if we remove parentheses too + // aggressively. + // HOWEVER - if there are leading comments on the expression itself, to handle ASI + // correctly for return and throw, we must keep the parenthesis if (ts.length(ts.getLeadingCommentRangesOfNode(expression, currentSourceFile))) { return ts.updateParen(node, expression); } @@ -54071,48 +63577,93 @@ var ts; return ts.createPartiallyEmittedExpression(expression, node); } function visitCallExpression(node) { - return ts.updateCall(node, ts.visitNode(node.expression, visitor, ts.isExpression), undefined, ts.visitNodes(node.arguments, visitor, ts.isExpression)); + return ts.updateCall(node, ts.visitNode(node.expression, visitor, ts.isExpression), + /*typeArguments*/ undefined, ts.visitNodes(node.arguments, visitor, ts.isExpression)); } function visitNewExpression(node) { - return ts.updateNew(node, ts.visitNode(node.expression, visitor, ts.isExpression), undefined, ts.visitNodes(node.arguments, visitor, ts.isExpression)); + return ts.updateNew(node, ts.visitNode(node.expression, visitor, ts.isExpression), + /*typeArguments*/ undefined, ts.visitNodes(node.arguments, visitor, ts.isExpression)); } function visitTaggedTemplateExpression(node) { - return ts.updateTaggedTemplate(node, ts.visitNode(node.tag, visitor, ts.isExpression), undefined, ts.visitNode(node.template, visitor, ts.isExpression)); + return ts.updateTaggedTemplate(node, ts.visitNode(node.tag, visitor, ts.isExpression), + /*typeArguments*/ undefined, ts.visitNode(node.template, visitor, ts.isExpression)); } + /** + * Determines whether to emit an enum declaration. + * + * @param node The enum declaration node. + */ function shouldEmitEnumDeclaration(node) { return !ts.isConst(node) || compilerOptions.preserveConstEnums || compilerOptions.isolatedModules; } + /** + * Visits an enum declaration. + * + * This function will be called any time a TypeScript enum is encountered. + * + * @param node The enum declaration node. + */ function visitEnumDeclaration(node) { if (!shouldEmitEnumDeclaration(node)) { return undefined; } var statements = []; - var emitFlags = 2; + // We request to be advised when the printer is about to print this node. This allows + // us to set up the correct state for later substitutions. + var emitFlags = 2 /* AdviseOnEmitNode */; + // If needed, we should emit a variable declaration for the enum. If we emit + // a leading variable declaration, we should not emit leading comments for the + // enum body. if (addVarForEnumOrModuleDeclaration(statements, node)) { + // We should still emit the comments if we are emitting a system module. if (moduleKind !== ts.ModuleKind.System || currentScope !== currentSourceFile) { - emitFlags |= 512; + emitFlags |= 512 /* NoLeadingComments */; } } + // `parameterName` is the declaration name used inside of the enum. var parameterName = getNamespaceParameterName(node); + // `containerName` is the expression used inside of the enum for assignments. var containerName = getNamespaceContainerName(node); - var exportName = ts.hasModifier(node, 1) - ? ts.getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, false, true) - : ts.getLocalName(node, false, true); + // `exportName` is the expression used within this node's container for any exported references. + var exportName = ts.hasModifier(node, 1 /* Export */) + ? ts.getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, /*allowComments*/ false, /*allowSourceMaps*/ true) + : ts.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); + // x || (x = {}) + // exports.x || (exports.x = {}) var moduleArg = ts.createLogicalOr(exportName, ts.createAssignment(exportName, ts.createObjectLiteral())); if (hasNamespaceQualifiedExportName(node)) { - var localName = ts.getLocalName(node, false, true); + // `localName` is the expression used within this node's containing scope for any local references. + var localName = ts.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); + // x = (exports.x || (exports.x = {})) moduleArg = ts.createAssignment(localName, moduleArg); } - var enumStatement = ts.createStatement(ts.createCall(ts.createFunctionExpression(undefined, undefined, undefined, undefined, [ts.createParameter(undefined, undefined, undefined, parameterName)], undefined, transformEnumBody(node, containerName)), undefined, [moduleArg])); + // (function (x) { + // x[x["y"] = 0] = "y"; + // ... + // })(x || (x = {})); + var enumStatement = ts.createStatement(ts.createCall(ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)], + /*type*/ undefined, transformEnumBody(node, containerName)), + /*typeArguments*/ undefined, [moduleArg])); ts.setOriginalNode(enumStatement, node); ts.setTextRange(enumStatement, node); ts.setEmitFlags(enumStatement, emitFlags); statements.push(enumStatement); + // Add a DeclarationMarker for the enum to preserve trailing comments and mark + // the end of the declaration. statements.push(ts.createEndOfDeclarationMarker(node)); return statements; } + /** + * Transforms the body of an enum declaration. + * + * @param node The enum declaration node. + */ function transformEnumBody(node, localName) { var savedCurrentNamespaceLocalName = currentNamespaceContainerName; currentNamespaceContainerName = localName; @@ -54122,17 +63673,31 @@ var ts; ts.prependStatements(statements, endLexicalEnvironment()); ts.addRange(statements, members); currentNamespaceContainerName = savedCurrentNamespaceLocalName; - return ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), node.members), true); + return ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), /*location*/ node.members), + /*multiLine*/ true); } + /** + * Transforms an enum member into a statement. + * + * @param member The enum member node. + */ function transformEnumMember(member) { - var name = getExpressionForPropertyName(member, false); + // enums don't support computed properties + // we pass false as 'generateNameForComputedPropertyName' for a backward compatibility purposes + // old emitter always generate 'expression' part of the name as-is. + var name = getExpressionForPropertyName(member, /*generateNameForComputedPropertyName*/ false); var valueExpression = transformEnumMemberDeclarationValue(member); var innerAssignment = ts.createAssignment(ts.createElementAccess(currentNamespaceContainerName, name), valueExpression); - var outerAssignment = valueExpression.kind === 9 ? + var outerAssignment = valueExpression.kind === 9 /* StringLiteral */ ? innerAssignment : ts.createAssignment(ts.createElementAccess(currentNamespaceContainerName, innerAssignment), name); return ts.setTextRange(ts.createStatement(ts.setTextRange(outerAssignment, member)), member); } + /** + * Transforms the value of an enum member. + * + * @param member The enum member node. + */ function transformEnumMemberDeclarationValue(member) { var value = resolver.getConstantValue(member); if (value !== undefined) { @@ -54148,9 +63713,18 @@ var ts; } } } + /** + * Determines whether to elide a module declaration. + * + * @param node The module declaration node. + */ function shouldEmitModuleDeclaration(node) { return ts.isInstantiatedModule(node, !!compilerOptions.preserveConstEnums || !!compilerOptions.isolatedModules); } + /** + * Determines whether an exported declaration will have a qualified export name (e.g. `f.x` + * or `exports.x`). + */ function hasNamespaceQualifiedExportName(node) { return isExportOfNamespace(node) || (isExternalModuleExport(node) @@ -54158,6 +63732,10 @@ var ts; && moduleKind !== ts.ModuleKind.ESNext && moduleKind !== ts.ModuleKind.System); } + /** + * Records that a declaration was emitted in the current scope, if it was the first + * declaration for the provided symbol. + */ function recordEmittedDeclarationInScope(node) { if (!currentScopeFirstDeclarationsOfName) { currentScopeFirstDeclarationsOfName = ts.createUnderscoreEscapedMap(); @@ -54167,6 +63745,10 @@ var ts; currentScopeFirstDeclarationsOfName.set(name, node); } } + /** + * Determines whether a declaration is the first declaration with + * the same name emitted in the current scope. + */ function isFirstEmittedDeclarationInScope(node) { if (currentScopeFirstDeclarationsOfName) { var name = declaredNameInScope(node); @@ -54178,31 +63760,67 @@ var ts; ts.Debug.assertNode(node.name, ts.isIdentifier); return node.name.escapedText; } + /** + * Adds a leading VariableStatement for a enum or module declaration. + */ function addVarForEnumOrModuleDeclaration(statements, node) { + // Emit a variable statement for the module. We emit top-level enums as a `var` + // declaration to avoid static errors in global scripts scripts due to redeclaration. + // enums in any other scope are emitted as a `let` declaration. var statement = ts.createVariableStatement(ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), ts.createVariableDeclarationList([ - ts.createVariableDeclaration(ts.getLocalName(node, false, true)) - ], currentScope.kind === 274 ? 0 : 1)); + ts.createVariableDeclaration(ts.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true)) + ], currentScope.kind === 274 /* SourceFile */ ? 0 /* None */ : 1 /* Let */)); ts.setOriginalNode(statement, node); recordEmittedDeclarationInScope(node); if (isFirstEmittedDeclarationInScope(node)) { - if (node.kind === 238) { + // Adjust the source map emit to match the old emitter. + if (node.kind === 238 /* EnumDeclaration */) { ts.setSourceMapRange(statement.declarationList, node); } else { ts.setSourceMapRange(statement, node); } + // Trailing comments for module declaration should be emitted after the function closure + // instead of the variable statement: + // + // /** Module comment*/ + // module m1 { + // function foo4Export() { + // } + // } // trailing comment module + // + // Should emit: + // + // /** Module comment*/ + // var m1; + // (function (m1) { + // function foo4Export() { + // } + // })(m1 || (m1 = {})); // trailing comment module + // ts.setCommentRange(statement, node); - ts.setEmitFlags(statement, 1024 | 4194304); + ts.setEmitFlags(statement, 1024 /* NoTrailingComments */ | 4194304 /* HasEndOfDeclarationMarker */); statements.push(statement); return true; } else { + // For an EnumDeclaration or ModuleDeclaration that merges with a preceeding + // declaration we do not emit a leading variable declaration. To preserve the + // begin/end semantics of the declararation and to properly handle exports + // we wrap the leading variable declaration in a `MergeDeclarationMarker`. var mergeMarker = ts.createMergeDeclarationMarker(statement); - ts.setEmitFlags(mergeMarker, 1536 | 4194304); + ts.setEmitFlags(mergeMarker, 1536 /* NoComments */ | 4194304 /* HasEndOfDeclarationMarker */); statements.push(mergeMarker); return false; } } + /** + * Visits a module declaration node. + * + * This function will be called any time a TypeScript namespace (ModuleDeclaration) is encountered. + * + * @param node The module declaration node. + */ function visitModuleDeclaration(node) { if (!shouldEmitModuleDeclaration(node)) { return ts.createNotEmittedStatement(node); @@ -54210,30 +63828,59 @@ var ts; ts.Debug.assertNode(node.name, ts.isIdentifier, "A TypeScript namespace should have an Identifier name."); enableSubstitutionForNamespaceExports(); var statements = []; - var emitFlags = 2; + // We request to be advised when the printer is about to print this node. This allows + // us to set up the correct state for later substitutions. + var emitFlags = 2 /* AdviseOnEmitNode */; + // If needed, we should emit a variable declaration for the module. If we emit + // a leading variable declaration, we should not emit leading comments for the + // module body. if (addVarForEnumOrModuleDeclaration(statements, node)) { + // We should still emit the comments if we are emitting a system module. if (moduleKind !== ts.ModuleKind.System || currentScope !== currentSourceFile) { - emitFlags |= 512; + emitFlags |= 512 /* NoLeadingComments */; } } + // `parameterName` is the declaration name used inside of the namespace. var parameterName = getNamespaceParameterName(node); + // `containerName` is the expression used inside of the namespace for exports. var containerName = getNamespaceContainerName(node); - var exportName = ts.hasModifier(node, 1) - ? ts.getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, false, true) - : ts.getLocalName(node, false, true); + // `exportName` is the expression used within this node's container for any exported references. + var exportName = ts.hasModifier(node, 1 /* Export */) + ? ts.getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, /*allowComments*/ false, /*allowSourceMaps*/ true) + : ts.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); + // x || (x = {}) + // exports.x || (exports.x = {}) var moduleArg = ts.createLogicalOr(exportName, ts.createAssignment(exportName, ts.createObjectLiteral())); if (hasNamespaceQualifiedExportName(node)) { - var localName = ts.getLocalName(node, false, true); + // `localName` is the expression used within this node's containing scope for any local references. + var localName = ts.getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true); + // x = (exports.x || (exports.x = {})) moduleArg = ts.createAssignment(localName, moduleArg); } - var moduleStatement = ts.createStatement(ts.createCall(ts.createFunctionExpression(undefined, undefined, undefined, undefined, [ts.createParameter(undefined, undefined, undefined, parameterName)], undefined, transformModuleBody(node, containerName)), undefined, [moduleArg])); + // (function (x_1) { + // x_1.y = ...; + // })(x || (x = {})); + var moduleStatement = ts.createStatement(ts.createCall(ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)], + /*type*/ undefined, transformModuleBody(node, containerName)), + /*typeArguments*/ undefined, [moduleArg])); ts.setOriginalNode(moduleStatement, node); ts.setTextRange(moduleStatement, node); ts.setEmitFlags(moduleStatement, emitFlags); statements.push(moduleStatement); + // Add a DeclarationMarker for the namespace to preserve trailing comments and mark + // the end of the declaration. statements.push(ts.createEndOfDeclarationMarker(node)); return statements; } + /** + * Transforms the body of a module declaration. + * + * @param node The module declaration node. + */ function transformModuleBody(node, namespaceLocalName) { var savedCurrentNamespaceContainerName = currentNamespaceContainerName; var savedCurrentNamespace = currentNamespace; @@ -54246,7 +63893,7 @@ var ts; var statementsLocation; var blockLocation; var body = node.body; - if (body.kind === 240) { + if (body.kind === 240 /* ModuleBlock */) { saveStateAndInvoke(body, function (body) { return ts.addRange(statements, ts.visitNodes(body.statements, namespaceElementVisitor, ts.isStatement)); }); statementsLocation = body.statements; blockLocation = body; @@ -54268,76 +63915,172 @@ var ts; currentNamespaceContainerName = savedCurrentNamespaceContainerName; currentNamespace = savedCurrentNamespace; currentScopeFirstDeclarationsOfName = savedCurrentScopeFirstDeclarationsOfName; - var block = ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), statementsLocation), true); + var block = ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), + /*location*/ statementsLocation), + /*multiLine*/ true); ts.setTextRange(block, blockLocation); - if (body.kind !== 240) { - ts.setEmitFlags(block, ts.getEmitFlags(block) | 1536); + // namespace hello.hi.world { + // function foo() {} + // + // // TODO, blah + // } + // + // should be emitted as + // + // var hello; + // (function (hello) { + // var hi; + // (function (hi) { + // var world; + // (function (world) { + // function foo() { } + // // TODO, blah + // })(world = hi.world || (hi.world = {})); + // })(hi = hello.hi || (hello.hi = {})); + // })(hello || (hello = {})); + // We only want to emit comment on the namespace which contains block body itself, not the containing namespaces. + if (body.kind !== 240 /* ModuleBlock */) { + ts.setEmitFlags(block, ts.getEmitFlags(block) | 1536 /* NoComments */); } return block; } function getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration) { - if (moduleDeclaration.body.kind === 239) { + if (moduleDeclaration.body.kind === 239 /* ModuleDeclaration */) { var recursiveInnerModule = getInnerMostModuleDeclarationFromDottedModule(moduleDeclaration.body); return recursiveInnerModule || moduleDeclaration.body; } } + /** + * Visits an import declaration, eliding it if it is not referenced. + * + * @param node The import declaration node. + */ function visitImportDeclaration(node) { if (!node.importClause) { + // Do not elide a side-effect only import declaration. + // import "foo"; return node; } + // Elide the declaration if the import clause was elided. var importClause = ts.visitNode(node.importClause, visitImportClause, ts.isImportClause); return importClause - ? ts.updateImportDeclaration(node, undefined, undefined, importClause, node.moduleSpecifier) + ? ts.updateImportDeclaration(node, + /*decorators*/ undefined, + /*modifiers*/ undefined, importClause, node.moduleSpecifier) : undefined; } + /** + * Visits an import clause, eliding it if it is not referenced. + * + * @param node The import clause node. + */ function visitImportClause(node) { + // Elide the import clause if we elide both its name and its named bindings. var name = resolver.isReferencedAliasDeclaration(node) ? node.name : undefined; var namedBindings = ts.visitNode(node.namedBindings, visitNamedImportBindings, ts.isNamedImportBindings); return (name || namedBindings) ? ts.updateImportClause(node, name, namedBindings) : undefined; } + /** + * Visits named import bindings, eliding it if it is not referenced. + * + * @param node The named import bindings node. + */ function visitNamedImportBindings(node) { - if (node.kind === 246) { + if (node.kind === 246 /* NamespaceImport */) { + // Elide a namespace import if it is not referenced. return resolver.isReferencedAliasDeclaration(node) ? node : undefined; } else { + // Elide named imports if all of its import specifiers are elided. var elements = ts.visitNodes(node.elements, visitImportSpecifier, ts.isImportSpecifier); return ts.some(elements) ? ts.updateNamedImports(node, elements) : undefined; } } + /** + * Visits an import specifier, eliding it if it is not referenced. + * + * @param node The import specifier node. + */ function visitImportSpecifier(node) { + // Elide an import specifier if it is not referenced. return resolver.isReferencedAliasDeclaration(node) ? node : undefined; } + /** + * Visits an export assignment, eliding it if it does not contain a clause that resolves + * to a value. + * + * @param node The export assignment node. + */ function visitExportAssignment(node) { + // Elide the export assignment if it does not reference a value. return resolver.isValueAliasDeclaration(node) ? ts.visitEachChild(node, visitor, context) : undefined; } + /** + * Visits an export declaration, eliding it if it does not contain a clause that resolves + * to a value. + * + * @param node The export declaration node. + */ function visitExportDeclaration(node) { if (!node.exportClause) { + // Elide a star export if the module it references does not export a value. return compilerOptions.isolatedModules || resolver.moduleExportsSomeValue(node.moduleSpecifier) ? node : undefined; } if (!resolver.isValueAliasDeclaration(node)) { + // Elide the export declaration if it does not export a value. return undefined; } + // Elide the export declaration if all of its named exports are elided. var exportClause = ts.visitNode(node.exportClause, visitNamedExports, ts.isNamedExports); return exportClause - ? ts.updateExportDeclaration(node, undefined, undefined, exportClause, node.moduleSpecifier) + ? ts.updateExportDeclaration(node, + /*decorators*/ undefined, + /*modifiers*/ undefined, exportClause, node.moduleSpecifier) : undefined; } + /** + * Visits named exports, eliding it if it does not contain an export specifier that + * resolves to a value. + * + * @param node The named exports node. + */ function visitNamedExports(node) { + // Elide the named exports if all of its export specifiers were elided. var elements = ts.visitNodes(node.elements, visitExportSpecifier, ts.isExportSpecifier); return ts.some(elements) ? ts.updateNamedExports(node, elements) : undefined; } + /** + * Visits an export specifier, eliding it if it does not resolve to a value. + * + * @param node The export specifier node. + */ function visitExportSpecifier(node) { + // Elide an export specifier if it does not reference a value. return resolver.isValueAliasDeclaration(node) ? node : undefined; } + /** + * Determines whether to emit an import equals declaration. + * + * @param node The import equals declaration node. + */ function shouldEmitImportEqualsDeclaration(node) { + // 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) || (!ts.isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node)); } + /** + * Visits an import equals declaration. + * + * @param node The import equals declaration node. + */ function visitImportEqualsDeclaration(node) { if (ts.isExternalModuleImportEqualsDeclaration(node)) { + // Elide external module `import=` if it is not referenced. return resolver.isReferencedAliasDeclaration(node) ? ts.visitEachChild(node, visitor, context) : undefined; @@ -54346,59 +64089,98 @@ var ts; return undefined; } var moduleReference = ts.createExpressionFromEntityName(node.moduleReference); - ts.setEmitFlags(moduleReference, 1536 | 2048); + ts.setEmitFlags(moduleReference, 1536 /* NoComments */ | 2048 /* NoNestedComments */); if (isNamedExternalModuleExport(node) || !isExportOfNamespace(node)) { + // export var ${name} = ${moduleReference}; + // var ${name} = ${moduleReference}; return ts.setOriginalNode(ts.setTextRange(ts.createVariableStatement(ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), ts.createVariableDeclarationList([ - ts.setOriginalNode(ts.createVariableDeclaration(node.name, undefined, moduleReference), node) + ts.setOriginalNode(ts.createVariableDeclaration(node.name, + /*type*/ undefined, moduleReference), node) ])), node), node); } else { + // exports.${name} = ${moduleReference}; return ts.setOriginalNode(createNamespaceExport(node.name, moduleReference, node), node); } } + /** + * Gets a value indicating whether the node is exported from a namespace. + * + * @param node The node to test. + */ function isExportOfNamespace(node) { - return currentNamespace !== undefined && ts.hasModifier(node, 1); + return currentNamespace !== undefined && ts.hasModifier(node, 1 /* Export */); } + /** + * Gets a value indicating whether the node is exported from an external module. + * + * @param node The node to test. + */ function isExternalModuleExport(node) { - return currentNamespace === undefined && ts.hasModifier(node, 1); + return currentNamespace === undefined && ts.hasModifier(node, 1 /* Export */); } + /** + * Gets a value indicating whether the node is a named export from an external module. + * + * @param node The node to test. + */ function isNamedExternalModuleExport(node) { return isExternalModuleExport(node) - && !ts.hasModifier(node, 512); + && !ts.hasModifier(node, 512 /* Default */); } + /** + * Gets a value indicating whether the node is the default export of an external module. + * + * @param node The node to test. + */ function isDefaultExternalModuleExport(node) { return isExternalModuleExport(node) - && ts.hasModifier(node, 512); + && ts.hasModifier(node, 512 /* Default */); } + /** + * Creates a statement for the provided expression. This is used in calls to `map`. + */ function expressionToStatement(expression) { return ts.createStatement(expression); } function addExportMemberAssignment(statements, node) { - var expression = ts.createAssignment(ts.getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, false, true), ts.getLocalName(node)); + var expression = ts.createAssignment(ts.getExternalModuleOrNamespaceExportName(currentNamespaceContainerName, node, /*allowComments*/ false, /*allowSourceMaps*/ true), ts.getLocalName(node)); ts.setSourceMapRange(expression, ts.createRange(node.name ? node.name.pos : node.pos, node.end)); var statement = ts.createStatement(expression); ts.setSourceMapRange(statement, ts.createRange(-1, node.end)); statements.push(statement); } function createNamespaceExport(exportName, exportValue, location) { - return ts.setTextRange(ts.createStatement(ts.createAssignment(ts.getNamespaceMemberName(currentNamespaceContainerName, exportName, false, true), exportValue)), location); + return ts.setTextRange(ts.createStatement(ts.createAssignment(ts.getNamespaceMemberName(currentNamespaceContainerName, exportName, /*allowComments*/ false, /*allowSourceMaps*/ true), exportValue)), location); } function createNamespaceExportExpression(exportName, exportValue, location) { return ts.setTextRange(ts.createAssignment(getNamespaceMemberNameWithSourceMapsAndWithoutComments(exportName), exportValue), location); } function getNamespaceMemberNameWithSourceMapsAndWithoutComments(name) { - return ts.getNamespaceMemberName(currentNamespaceContainerName, name, false, true); + return ts.getNamespaceMemberName(currentNamespaceContainerName, name, /*allowComments*/ false, /*allowSourceMaps*/ true); } + /** + * Gets the declaration name used inside of a namespace or enum. + */ function getNamespaceParameterName(node) { var name = ts.getGeneratedNameForNode(node); ts.setSourceMapRange(name, node.name); return name; } + /** + * Gets the expression used to refer to a namespace or enum within the body + * of its declaration. + */ function getNamespaceContainerName(node) { return ts.getGeneratedNameForNode(node); } + /** + * Gets a local alias for a class declaration if it is a decorated class with an internal + * reference to the static side of the class. This is necessary to avoid issues with + * double-binding semantics for the class name. + */ function getClassAliasIfNeeded(node) { - if (resolver.getNodeCheckFlags(node) & 8388608) { + if (resolver.getNodeCheckFlags(node) & 8388608 /* ClassWithConstructorReference */) { enableSubstitutionForClassAliases(); var classAlias = ts.createUniqueName(node.name && !ts.isGeneratedIdentifier(node.name) ? ts.idText(node.name) : "default"); classAliases[ts.getOriginalNodeId(node)] = classAlias; @@ -54410,56 +64192,75 @@ var ts; return ts.createPropertyAccess(ts.getDeclarationName(node), "prototype"); } function getClassMemberPrefix(node, member) { - return ts.hasModifier(member, 32) + return ts.hasModifier(member, 32 /* Static */) ? ts.getDeclarationName(node) : getClassPrototype(node); } function enableSubstitutionForNonQualifiedEnumMembers() { - if ((enabledSubstitutions & 8) === 0) { - enabledSubstitutions |= 8; - context.enableSubstitution(71); + if ((enabledSubstitutions & 8 /* NonQualifiedEnumMembers */) === 0) { + enabledSubstitutions |= 8 /* NonQualifiedEnumMembers */; + context.enableSubstitution(71 /* Identifier */); } } function enableSubstitutionForClassAliases() { - if ((enabledSubstitutions & 1) === 0) { - enabledSubstitutions |= 1; - context.enableSubstitution(71); + if ((enabledSubstitutions & 1 /* ClassAliases */) === 0) { + enabledSubstitutions |= 1 /* ClassAliases */; + // We need to enable substitutions for identifiers. This allows us to + // substitute class names inside of a class declaration. + context.enableSubstitution(71 /* Identifier */); + // Keep track of class aliases. classAliases = []; } } function enableSubstitutionForNamespaceExports() { - if ((enabledSubstitutions & 2) === 0) { - enabledSubstitutions |= 2; - context.enableSubstitution(71); - context.enableSubstitution(271); - context.enableEmitNotification(239); + if ((enabledSubstitutions & 2 /* NamespaceExports */) === 0) { + enabledSubstitutions |= 2 /* NamespaceExports */; + // We need to enable substitutions for identifiers and shorthand property assignments. This allows us to + // substitute the names of exported members of a namespace. + context.enableSubstitution(71 /* Identifier */); + context.enableSubstitution(271 /* ShorthandPropertyAssignment */); + // We need to be notified when entering and exiting namespaces. + context.enableEmitNotification(239 /* ModuleDeclaration */); } } function isTransformedModuleDeclaration(node) { - return ts.getOriginalNode(node).kind === 239; + return ts.getOriginalNode(node).kind === 239 /* ModuleDeclaration */; } function isTransformedEnumDeclaration(node) { - return ts.getOriginalNode(node).kind === 238; + return ts.getOriginalNode(node).kind === 238 /* EnumDeclaration */; } + /** + * Hook for node emit. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emit A callback used to emit the node in the printer. + */ function onEmitNode(hint, node, emitCallback) { var savedApplicableSubstitutions = applicableSubstitutions; var savedCurrentSourceFile = currentSourceFile; if (ts.isSourceFile(node)) { currentSourceFile = node; } - if (enabledSubstitutions & 2 && isTransformedModuleDeclaration(node)) { - applicableSubstitutions |= 2; + if (enabledSubstitutions & 2 /* NamespaceExports */ && isTransformedModuleDeclaration(node)) { + applicableSubstitutions |= 2 /* NamespaceExports */; } - if (enabledSubstitutions & 8 && isTransformedEnumDeclaration(node)) { - applicableSubstitutions |= 8; + if (enabledSubstitutions & 8 /* NonQualifiedEnumMembers */ && isTransformedEnumDeclaration(node)) { + applicableSubstitutions |= 8 /* NonQualifiedEnumMembers */; } previousOnEmitNode(hint, node, emitCallback); applicableSubstitutions = savedApplicableSubstitutions; currentSourceFile = savedCurrentSourceFile; } + /** + * Hooks node substitutions. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to substitute. + */ function onSubstituteNode(hint, node) { node = previousOnSubstituteNode(hint, node); - if (hint === 1) { + if (hint === 1 /* Expression */) { return substituteExpression(node); } else if (ts.isShorthandPropertyAssignment(node)) { @@ -54468,10 +64269,12 @@ var ts; return node; } function substituteShorthandPropertyAssignment(node) { - if (enabledSubstitutions & 2) { + if (enabledSubstitutions & 2 /* NamespaceExports */) { var name = node.name; var exportedName = trySubstituteNamespaceExportedName(name); if (exportedName) { + // A shorthand property with an assignment initializer is probably part of a + // destructuring assignment if (node.objectAssignmentInitializer) { var initializer = ts.createAssignment(exportedName, node.objectAssignmentInitializer); return ts.setTextRange(ts.createPropertyAssignment(name, initializer), node); @@ -54483,11 +64286,11 @@ var ts; } function substituteExpression(node) { switch (node.kind) { - case 71: + case 71 /* Identifier */: return substituteExpressionIdentifier(node); - case 185: + case 185 /* PropertyAccessExpression */: return substitutePropertyAccessExpression(node); - case 186: + case 186 /* ElementAccessExpression */: return substituteElementAccessExpression(node); } return node; @@ -54498,11 +64301,16 @@ var ts; || node; } function trySubstituteClassAlias(node) { - if (enabledSubstitutions & 1) { - if (resolver.getNodeCheckFlags(node) & 16777216) { + if (enabledSubstitutions & 1 /* ClassAliases */) { + if (resolver.getNodeCheckFlags(node) & 16777216 /* ConstructorReferenceInClass */) { + // Due to the emit for class decorators, any reference to the class from inside of the class body + // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind + // behavior of class names in ES6. + // Also, when emitting statics for class expressions, we must substitute a class alias for + // constructor references in static property initializers. var declaration = resolver.getReferencedValueDeclaration(node); if (declaration) { - var classAlias = classAliases[declaration.id]; + var classAlias = classAliases[declaration.id]; // TODO: GH#18217 if (classAlias) { var clone_1 = ts.getSynthesizedClone(classAlias); ts.setSourceMapRange(clone_1, node); @@ -54515,13 +64323,17 @@ var ts; return undefined; } function trySubstituteNamespaceExportedName(node) { + // If this is explicitly a local name, do not substitute. if (enabledSubstitutions & applicableSubstitutions && !ts.isGeneratedIdentifier(node) && !ts.isLocalName(node)) { - var container = resolver.getReferencedExportContainer(node, false); - if (container && container.kind !== 274) { - var substitute = (applicableSubstitutions & 2 && container.kind === 239) || - (applicableSubstitutions & 8 && container.kind === 238); + // If we are nested within a namespace declaration, we may need to qualifiy + // an identifier that is exported from a merged namespace. + var container = resolver.getReferencedExportContainer(node, /*prefixLocals*/ false); + if (container && container.kind !== 274 /* SourceFile */) { + var substitute = (applicableSubstitutions & 2 /* NamespaceExports */ && container.kind === 239 /* ModuleDeclaration */) || + (applicableSubstitutions & 8 /* NonQualifiedEnumMembers */ && container.kind === 238 /* EnumDeclaration */); if (substitute) { - return ts.setTextRange(ts.createPropertyAccess(ts.getGeneratedNameForNode(container), node), node); + return ts.setTextRange(ts.createPropertyAccess(ts.getGeneratedNameForNode(container), node), + /*location*/ node); } } } @@ -54536,13 +64348,14 @@ var ts; function substituteConstantValue(node) { var constantValue = tryGetConstEnumValue(node); if (constantValue !== undefined) { + // track the constant value on the node for the printer in needsDotDotForPropertyAccess ts.setConstantValue(node, constantValue); var substitute = ts.createLiteral(constantValue); if (!compilerOptions.removeComments) { var propertyName = ts.isPropertyAccessExpression(node) ? ts.declarationNameToString(node.name) : ts.getTextOfNode(node.argumentExpression); - ts.addSyntheticTrailingComment(substitute, 3, " " + propertyName + " "); + ts.addSyntheticTrailingComment(substitute, 3 /* MultiLineCommentTrivia */, " " + propertyName + " "); } return substitute; } @@ -54558,7 +64371,7 @@ var ts; ts.transformTypeScript = transformTypeScript; function createDecorateHelper(context, decoratorExpressions, target, memberName, descriptor, location) { var argumentsArray = []; - argumentsArray.push(ts.createArrayLiteral(decoratorExpressions, true)); + argumentsArray.push(ts.createArrayLiteral(decoratorExpressions, /*multiLine*/ true)); argumentsArray.push(target); if (memberName) { argumentsArray.push(memberName); @@ -54567,7 +64380,8 @@ var ts; } } context.requestEmitHelper(decorateHelper); - return ts.setTextRange(ts.createCall(ts.getHelperName("__decorate"), undefined, argumentsArray), location); + return ts.setTextRange(ts.createCall(ts.getHelperName("__decorate"), + /*typeArguments*/ undefined, argumentsArray), location); } var decorateHelper = { name: "typescript:decorate", @@ -54577,7 +64391,8 @@ var ts; }; function createMetadataHelper(context, metadataKey, metadataValue) { context.requestEmitHelper(metadataHelper); - return ts.createCall(ts.getHelperName("__metadata"), undefined, [ + return ts.createCall(ts.getHelperName("__metadata"), + /*typeArguments*/ undefined, [ ts.createLiteral(metadataKey), metadataValue ]); @@ -54590,7 +64405,8 @@ var ts; }; function createParamHelper(context, expression, parameterOffset, location) { context.requestEmitHelper(paramHelper); - return ts.setTextRange(ts.createCall(ts.getHelperName("__param"), undefined, [ + return ts.setTextRange(ts.createCall(ts.getHelperName("__param"), + /*typeArguments*/ undefined, [ ts.createLiteral(parameterOffset), expression ]), location); @@ -54602,10 +64418,12 @@ var ts; text: "\n var __param = (this && this.__param) || function (paramIndex, decorator) {\n return function (target, key) { decorator(target, key, paramIndex); }\n };" }; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { var ES2017SubstitutionFlags; (function (ES2017SubstitutionFlags) { + /** Enables substitutions for async methods with `super` calls. */ ES2017SubstitutionFlags[ES2017SubstitutionFlags["AsyncMethodsWithSuper"] = 1] = "AsyncMethodsWithSuper"; })(ES2017SubstitutionFlags || (ES2017SubstitutionFlags = {})); function transformES2017(context) { @@ -54613,11 +64431,21 @@ var ts; var resolver = context.getEmitResolver(); var compilerOptions = context.getCompilerOptions(); var languageVersion = ts.getEmitScriptTarget(compilerOptions); + /** + * Keeps track of whether expression substitution has been enabled for specific edge cases. + * They are persisted between each SourceFile transformation and should not be reset. + */ var enabledSubstitutions; + /** + * This keeps track of containers where `super` is valid, for use with + * just-in-time substitution for `super` expressions inside of async methods. + */ var enclosingSuperContainerFlags = 0; var enclosingFunctionParameterNames; + // Save the previous transformation hooks. var previousOnEmitNode = context.onEmitNode; var previousOnSubstituteNode = context.onSubstituteNode; + // Set new transformation hooks. context.onEmitNode = onEmitNode; context.onSubstituteNode = onSubstituteNode; return ts.chainBundle(transformSourceFile); @@ -54630,21 +64458,22 @@ var ts; return visited; } function visitor(node) { - if ((node.transformFlags & 16) === 0) { + if ((node.transformFlags & 16 /* ContainsES2017 */) === 0) { return node; } switch (node.kind) { - case 120: + case 120 /* AsyncKeyword */: + // ES2017 async modifier should be elided for targets < ES2017 return undefined; - case 197: + case 197 /* AwaitExpression */: return visitAwaitExpression(node); - case 154: + case 154 /* MethodDeclaration */: return visitMethodDeclaration(node); - case 234: + case 234 /* FunctionDeclaration */: return visitFunctionDeclaration(node); - case 192: + case 192 /* FunctionExpression */: return visitFunctionExpression(node); - case 193: + case 193 /* ArrowFunction */: return visitArrowFunction(node); default: return ts.visitEachChild(node, visitor, context); @@ -54653,27 +64482,27 @@ var ts; function asyncBodyVisitor(node) { if (ts.isNodeWithPossibleHoistedDeclaration(node)) { switch (node.kind) { - case 214: + case 214 /* VariableStatement */: return visitVariableStatementInAsyncBody(node); - case 220: + case 220 /* ForStatement */: return visitForStatementInAsyncBody(node); - case 221: + case 221 /* ForInStatement */: return visitForInStatementInAsyncBody(node); - case 222: + case 222 /* ForOfStatement */: return visitForOfStatementInAsyncBody(node); - case 269: + case 269 /* CatchClause */: return visitCatchClauseInAsyncBody(node); - case 213: - case 227: - case 241: - case 266: - case 267: - case 230: - case 218: - case 219: - case 217: - case 226: - case 228: + case 213 /* Block */: + case 227 /* SwitchStatement */: + case 241 /* CaseBlock */: + case 266 /* CaseClause */: + case 267 /* DefaultClause */: + case 230 /* TryStatement */: + case 218 /* DoStatement */: + case 219 /* WhileStatement */: + case 217 /* IfStatement */: + case 226 /* WithStatement */: + case 228 /* LabeledStatement */: return ts.visitEachChild(node, asyncBodyVisitor, context); default: return ts.Debug.assertNever(node, "Unhandled node."); @@ -54683,7 +64512,8 @@ var ts; } function visitCatchClauseInAsyncBody(node) { var catchClauseNames = ts.createUnderscoreEscapedMap(); - recordDeclarationName(node.variableDeclaration, catchClauseNames); + recordDeclarationName(node.variableDeclaration, catchClauseNames); // TODO: GH#18217 + // names declared in a catch variable are block scoped var catchClauseUnshadowedNames; catchClauseNames.forEach(function (_, escapedName) { if (enclosingFunctionParameterNames.has(escapedName)) { @@ -54706,47 +64536,98 @@ var ts; } function visitVariableStatementInAsyncBody(node) { if (isVariableDeclarationListWithCollidingName(node.declarationList)) { - var expression = visitVariableDeclarationListWithCollidingNames(node.declarationList, false); + var expression = visitVariableDeclarationListWithCollidingNames(node.declarationList, /*hasReceiver*/ false); return expression ? ts.createStatement(expression) : undefined; } return ts.visitEachChild(node, visitor, context); } function visitForInStatementInAsyncBody(node) { return ts.updateForIn(node, isVariableDeclarationListWithCollidingName(node.initializer) - ? visitVariableDeclarationListWithCollidingNames(node.initializer, true) + ? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ true) : ts.visitNode(node.initializer, visitor, ts.isForInitializer), ts.visitNode(node.expression, visitor, ts.isExpression), ts.visitNode(node.statement, asyncBodyVisitor, ts.isStatement, ts.liftToBlock)); } function visitForOfStatementInAsyncBody(node) { return ts.updateForOf(node, ts.visitNode(node.awaitModifier, visitor, ts.isToken), isVariableDeclarationListWithCollidingName(node.initializer) - ? visitVariableDeclarationListWithCollidingNames(node.initializer, true) + ? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ true) : ts.visitNode(node.initializer, visitor, ts.isForInitializer), ts.visitNode(node.expression, visitor, ts.isExpression), ts.visitNode(node.statement, asyncBodyVisitor, ts.isStatement, ts.liftToBlock)); } function visitForStatementInAsyncBody(node) { - var initializer = node.initializer; + var initializer = node.initializer; // TODO: GH#18217 return ts.updateFor(node, isVariableDeclarationListWithCollidingName(initializer) - ? visitVariableDeclarationListWithCollidingNames(initializer, false) + ? visitVariableDeclarationListWithCollidingNames(initializer, /*hasReceiver*/ false) : ts.visitNode(node.initializer, visitor, ts.isForInitializer), ts.visitNode(node.condition, visitor, ts.isExpression), ts.visitNode(node.incrementor, visitor, ts.isExpression), ts.visitNode(node.statement, asyncBodyVisitor, ts.isStatement, ts.liftToBlock)); } + /** + * Visits an AwaitExpression node. + * + * This function will be called any time a ES2017 await expression is encountered. + * + * @param node The node to visit. + */ function visitAwaitExpression(node) { - return ts.setOriginalNode(ts.setTextRange(ts.createYield(undefined, ts.visitNode(node.expression, visitor, ts.isExpression)), node), node); + return ts.setOriginalNode(ts.setTextRange(ts.createYield( + /*asteriskToken*/ undefined, ts.visitNode(node.expression, visitor, ts.isExpression)), node), node); } + /** + * Visits a MethodDeclaration node. + * + * This function will be called when one of the following conditions are met: + * - The node is marked as async + * + * @param node The node to visit. + */ function visitMethodDeclaration(node) { - return ts.updateMethod(node, undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), node.asteriskToken, node.name, undefined, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, ts.getFunctionFlags(node) & 2 + return ts.updateMethod(node, + /*decorators*/ undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), node.asteriskToken, node.name, + /*questionToken*/ undefined, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, ts.getFunctionFlags(node) & 2 /* Async */ ? transformAsyncFunctionBody(node) : ts.visitFunctionBody(node.body, visitor, context)); } + /** + * Visits a FunctionDeclaration node. + * + * This function will be called when one of the following conditions are met: + * - The node is marked async + * + * @param node The node to visit. + */ function visitFunctionDeclaration(node) { - return ts.updateFunctionDeclaration(node, undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), node.asteriskToken, node.name, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, ts.getFunctionFlags(node) & 2 + return ts.updateFunctionDeclaration(node, + /*decorators*/ undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), node.asteriskToken, node.name, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, ts.getFunctionFlags(node) & 2 /* Async */ ? transformAsyncFunctionBody(node) : ts.visitFunctionBody(node.body, visitor, context)); } + /** + * Visits a FunctionExpression node. + * + * This function will be called when one of the following conditions are met: + * - The node is marked async + * + * @param node The node to visit. + */ function visitFunctionExpression(node) { - return ts.updateFunctionExpression(node, ts.visitNodes(node.modifiers, visitor, ts.isModifier), node.asteriskToken, node.name, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, ts.getFunctionFlags(node) & 2 + return ts.updateFunctionExpression(node, ts.visitNodes(node.modifiers, visitor, ts.isModifier), node.asteriskToken, node.name, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, ts.getFunctionFlags(node) & 2 /* Async */ ? transformAsyncFunctionBody(node) : ts.visitFunctionBody(node.body, visitor, context)); } + /** + * Visits an ArrowFunction. + * + * This function will be called when one of the following conditions are met: + * - The node is marked async + * + * @param node The node to visit. + */ function visitArrowFunction(node) { - return ts.updateArrowFunction(node, ts.visitNodes(node.modifiers, visitor, ts.isModifier), undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, node.equalsGreaterThanToken, ts.getFunctionFlags(node) & 2 + return ts.updateArrowFunction(node, ts.visitNodes(node.modifiers, visitor, ts.isModifier), + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, node.equalsGreaterThanToken, ts.getFunctionFlags(node) & 2 /* Async */ ? transformAsyncFunctionBody(node) : ts.visitFunctionBody(node.body, visitor, context)); } @@ -54767,7 +64648,7 @@ var ts; function isVariableDeclarationListWithCollidingName(node) { return !!node && ts.isVariableDeclarationList(node) - && !(node.flags & 3) + && !(node.flags & 3 /* BlockScoped */) && node.declarations.some(collidesWithParameterName); } function visitVariableDeclarationListWithCollidingNames(node, hasReceiver) { @@ -54821,9 +64702,14 @@ var ts; resumeLexicalEnvironment(); var original = ts.getOriginalNode(node, ts.isFunctionLike); var nodeType = original.type; - var promiseConstructor = languageVersion < 2 ? getPromiseConstructor(nodeType) : undefined; - var isArrowFunction = node.kind === 193; - var hasLexicalArguments = (resolver.getNodeCheckFlags(node) & 8192) !== 0; + var promiseConstructor = languageVersion < 2 /* ES2015 */ ? getPromiseConstructor(nodeType) : undefined; + var isArrowFunction = node.kind === 193 /* ArrowFunction */; + var hasLexicalArguments = (resolver.getNodeCheckFlags(node) & 8192 /* CaptureArguments */) !== 0; + // 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. var savedEnclosingFunctionParameterNames = enclosingFunctionParameterNames; enclosingFunctionParameterNames = ts.createUnderscoreEscapedMap(); for (var _i = 0, _a = node.parameters; _i < _a.length; _i++) { @@ -54833,17 +64719,19 @@ var ts; var result; if (!isArrowFunction) { var statements = []; - var statementOffset = ts.addPrologue(statements, node.body.statements, false, visitor); + var statementOffset = ts.addPrologue(statements, node.body.statements, /*ensureUseStrict*/ false, visitor); statements.push(ts.createReturn(createAwaiterHelper(context, hasLexicalArguments, promiseConstructor, transformAsyncFunctionBodyWorker(node.body, statementOffset)))); ts.prependStatements(statements, endLexicalEnvironment()); - var block = ts.createBlock(statements, true); + var block = ts.createBlock(statements, /*multiLine*/ true); ts.setTextRange(block, node.body); - if (languageVersion >= 2) { - if (resolver.getNodeCheckFlags(node) & 4096) { + // Minor optimization, emit `_super` helper to capture `super` access in an arrow. + // This step isn't needed if we eventually transform this to ES5. + if (languageVersion >= 2 /* ES2015 */) { + if (resolver.getNodeCheckFlags(node) & 4096 /* AsyncMethodWithSuperBinding */) { enableSubstitutionForAsyncMethodsWithSuper(); ts.addEmitHelper(block, ts.advancedAsyncSuperHelper); } - else if (resolver.getNodeCheckFlags(node) & 2048) { + else if (resolver.getNodeCheckFlags(node) & 2048 /* AsyncMethodWithSuper */) { enableSubstitutionForAsyncMethodsWithSuper(); ts.addEmitHelper(block, ts.asyncSuperHelper); } @@ -54884,21 +64772,33 @@ var ts; return undefined; } function enableSubstitutionForAsyncMethodsWithSuper() { - if ((enabledSubstitutions & 1) === 0) { - enabledSubstitutions |= 1; - context.enableSubstitution(187); - context.enableSubstitution(185); - context.enableSubstitution(186); - context.enableEmitNotification(235); - context.enableEmitNotification(154); - context.enableEmitNotification(156); - context.enableEmitNotification(157); - context.enableEmitNotification(155); + if ((enabledSubstitutions & 1 /* AsyncMethodsWithSuper */) === 0) { + enabledSubstitutions |= 1 /* AsyncMethodsWithSuper */; + // We need to enable substitutions for call, property access, and element access + // if we need to rewrite super calls. + context.enableSubstitution(187 /* CallExpression */); + context.enableSubstitution(185 /* PropertyAccessExpression */); + context.enableSubstitution(186 /* ElementAccessExpression */); + // We need to be notified when entering and exiting declarations that bind super. + context.enableEmitNotification(235 /* ClassDeclaration */); + context.enableEmitNotification(154 /* MethodDeclaration */); + context.enableEmitNotification(156 /* GetAccessor */); + context.enableEmitNotification(157 /* SetAccessor */); + context.enableEmitNotification(155 /* Constructor */); } } + /** + * Hook for node emit. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emit A callback used to emit the node in the printer. + */ function onEmitNode(hint, node, emitCallback) { - if (enabledSubstitutions & 1 && isSuperContainer(node)) { - var superContainerFlags = resolver.getNodeCheckFlags(node) & (2048 | 4096); + // If we need to support substitutions for `super` in an async method, + // we should track it here. + if (enabledSubstitutions & 1 /* AsyncMethodsWithSuper */ && isSuperContainer(node)) { + var superContainerFlags = resolver.getNodeCheckFlags(node) & (2048 /* AsyncMethodWithSuper */ | 4096 /* AsyncMethodWithSuperBinding */); if (superContainerFlags !== enclosingSuperContainerFlags) { var savedEnclosingSuperContainerFlags = enclosingSuperContainerFlags; enclosingSuperContainerFlags = superContainerFlags; @@ -54909,32 +64809,38 @@ var ts; } previousOnEmitNode(hint, node, emitCallback); } + /** + * Hooks node substitutions. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to substitute. + */ function onSubstituteNode(hint, node) { node = previousOnSubstituteNode(hint, node); - if (hint === 1 && enclosingSuperContainerFlags) { + if (hint === 1 /* Expression */ && enclosingSuperContainerFlags) { return substituteExpression(node); } return node; } function substituteExpression(node) { switch (node.kind) { - case 185: + case 185 /* PropertyAccessExpression */: return substitutePropertyAccessExpression(node); - case 186: + case 186 /* ElementAccessExpression */: return substituteElementAccessExpression(node); - case 187: + case 187 /* CallExpression */: return substituteCallExpression(node); } return node; } function substitutePropertyAccessExpression(node) { - if (node.expression.kind === 97) { + if (node.expression.kind === 97 /* SuperKeyword */) { return createSuperAccessInAsyncMethod(ts.createLiteral(ts.idText(node.name)), node); } return node; } function substituteElementAccessExpression(node) { - if (node.expression.kind === 97) { + if (node.expression.kind === 97 /* SuperKeyword */) { return createSuperAccessInAsyncMethod(node.argumentExpression, node); } return node; @@ -54945,7 +64851,8 @@ var ts; var argumentExpression = ts.isPropertyAccessExpression(expression) ? substitutePropertyAccessExpression(expression) : substituteElementAccessExpression(expression); - return ts.createCall(ts.createPropertyAccess(argumentExpression, "call"), undefined, [ + return ts.createCall(ts.createPropertyAccess(argumentExpression, "call"), + /*typeArguments*/ undefined, [ ts.createThis() ].concat(node.arguments)); } @@ -54953,18 +64860,20 @@ var ts; } function isSuperContainer(node) { var kind = node.kind; - return kind === 235 - || kind === 155 - || kind === 154 - || kind === 156 - || kind === 157; + return kind === 235 /* ClassDeclaration */ + || kind === 155 /* Constructor */ + || kind === 154 /* MethodDeclaration */ + || kind === 156 /* GetAccessor */ + || kind === 157 /* SetAccessor */; } function createSuperAccessInAsyncMethod(argumentExpression, location) { - if (enclosingSuperContainerFlags & 4096) { - return ts.setTextRange(ts.createPropertyAccess(ts.createCall(ts.createFileLevelUniqueName("_super"), undefined, [argumentExpression]), "value"), location); + if (enclosingSuperContainerFlags & 4096 /* AsyncMethodWithSuperBinding */) { + return ts.setTextRange(ts.createPropertyAccess(ts.createCall(ts.createFileLevelUniqueName("_super"), + /*typeArguments*/ undefined, [argumentExpression]), "value"), location); } else { - return ts.setTextRange(ts.createCall(ts.createFileLevelUniqueName("_super"), undefined, [argumentExpression]), location); + return ts.setTextRange(ts.createCall(ts.createFileLevelUniqueName("_super"), + /*typeArguments*/ undefined, [argumentExpression]), location); } } } @@ -54977,9 +64886,16 @@ var ts; }; function createAwaiterHelper(context, hasLexicalArguments, promiseConstructor, body) { context.requestEmitHelper(awaiterHelper); - var generatorFunc = ts.createFunctionExpression(undefined, ts.createToken(39), undefined, undefined, [], undefined, body); - (generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= 262144 | 524288; - return ts.createCall(ts.getHelperName("__awaiter"), undefined, [ + var generatorFunc = ts.createFunctionExpression( + /*modifiers*/ undefined, ts.createToken(39 /* AsteriskToken */), + /*name*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ [], + /*type*/ undefined, body); + // Mark this node as originally an async function + (generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= 262144 /* AsyncFunctionBody */ | 524288 /* ReuseTempVariableScope */; + return ts.createCall(ts.getHelperName("__awaiter"), + /*typeArguments*/ undefined, [ ts.createThis(), hasLexicalArguments ? ts.createIdentifier("arguments") : ts.createVoidZero(), promiseConstructor ? ts.createExpressionFromEntityName(promiseConstructor) : ts.createVoidZero(), @@ -54997,10 +64913,12 @@ var ts; text: ts.helperString(__makeTemplateObject(["\n const ", " = (function (geti, seti) {\n const cache = Object.create(null);\n return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });\n })(name => super[name], (name, value) => super[name] = value);"], ["\n const ", " = (function (geti, seti) {\n const cache = Object.create(null);\n return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });\n })(name => super[name], (name, value) => super[name] = value);"]), "_super") }; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { var ESNextSubstitutionFlags; (function (ESNextSubstitutionFlags) { + /** Enables substitutions for async methods with `super` calls. */ ESNextSubstitutionFlags[ESNextSubstitutionFlags["AsyncMethodsWithSuper"] = 1] = "AsyncMethodsWithSuper"; })(ESNextSubstitutionFlags || (ESNextSubstitutionFlags = {})); function transformESNext(context) { @@ -55025,76 +64943,77 @@ var ts; return visited; } function visitor(node) { - return visitorWorker(node, false); + return visitorWorker(node, /*noDestructuringValue*/ false); } function visitorNoDestructuringValue(node) { - return visitorWorker(node, true); + return visitorWorker(node, /*noDestructuringValue*/ true); } function visitorNoAsyncModifier(node) { - if (node.kind === 120) { + if (node.kind === 120 /* AsyncKeyword */) { return undefined; } return node; } function visitorWorker(node, noDestructuringValue) { - if ((node.transformFlags & 8) === 0) { + if ((node.transformFlags & 8 /* ContainsESNext */) === 0) { return node; } switch (node.kind) { - case 197: + case 197 /* AwaitExpression */: return visitAwaitExpression(node); - case 203: + case 203 /* YieldExpression */: return visitYieldExpression(node); - case 225: + case 225 /* ReturnStatement */: return visitReturnStatement(node); - case 228: + case 228 /* LabeledStatement */: return visitLabeledStatement(node); - case 184: + case 184 /* ObjectLiteralExpression */: return visitObjectLiteralExpression(node); - case 200: + case 200 /* BinaryExpression */: return visitBinaryExpression(node, noDestructuringValue); - case 232: + case 232 /* VariableDeclaration */: return visitVariableDeclaration(node); - case 222: - return visitForOfStatement(node, undefined); - case 220: + case 222 /* ForOfStatement */: + return visitForOfStatement(node, /*outermostLabeledStatement*/ undefined); + case 220 /* ForStatement */: return visitForStatement(node); - case 196: + case 196 /* VoidExpression */: return visitVoidExpression(node); - case 155: + case 155 /* Constructor */: return visitConstructorDeclaration(node); - case 154: + case 154 /* MethodDeclaration */: return visitMethodDeclaration(node); - case 156: + case 156 /* GetAccessor */: return visitGetAccessorDeclaration(node); - case 157: + case 157 /* SetAccessor */: return visitSetAccessorDeclaration(node); - case 234: + case 234 /* FunctionDeclaration */: return visitFunctionDeclaration(node); - case 192: + case 192 /* FunctionExpression */: return visitFunctionExpression(node); - case 193: + case 193 /* ArrowFunction */: return visitArrowFunction(node); - case 149: + case 149 /* Parameter */: return visitParameter(node); - case 216: + case 216 /* ExpressionStatement */: return visitExpressionStatement(node); - case 191: + case 191 /* ParenthesizedExpression */: return visitParenthesizedExpression(node, noDestructuringValue); - case 269: + case 269 /* CatchClause */: return visitCatchClause(node); default: return ts.visitEachChild(node, visitor, context); } } function visitAwaitExpression(node) { - if (enclosingFunctionFlags & 2 && enclosingFunctionFlags & 1) { - return ts.setOriginalNode(ts.setTextRange(ts.createYield(createAwaitHelper(context, ts.visitNode(node.expression, visitor, ts.isExpression))), node), node); + if (enclosingFunctionFlags & 2 /* Async */ && enclosingFunctionFlags & 1 /* Generator */) { + return ts.setOriginalNode(ts.setTextRange(ts.createYield(createAwaitHelper(context, ts.visitNode(node.expression, visitor, ts.isExpression))), + /*location*/ node), node); } return ts.visitEachChild(node, visitor, context); } function visitYieldExpression(node) { - if (enclosingFunctionFlags & 2 && enclosingFunctionFlags & 1) { + if (enclosingFunctionFlags & 2 /* Async */ && enclosingFunctionFlags & 1 /* Generator */) { if (node.asteriskToken) { var expression = ts.visitNode(node.expression, visitor, ts.isExpression); return ts.setOriginalNode(ts.setTextRange(ts.createYield(createAwaitHelper(context, ts.updateYield(node, node.asteriskToken, createAsyncDelegatorHelper(context, createAsyncValuesHelper(context, expression, expression), expression)))), node), node); @@ -55106,15 +65025,15 @@ var ts; return ts.visitEachChild(node, visitor, context); } function visitReturnStatement(node) { - if (enclosingFunctionFlags & 2 && enclosingFunctionFlags & 1) { + if (enclosingFunctionFlags & 2 /* Async */ && enclosingFunctionFlags & 1 /* Generator */) { return ts.updateReturn(node, createDownlevelAwait(node.expression ? ts.visitNode(node.expression, visitor, ts.isExpression) : ts.createVoidZero())); } return ts.visitEachChild(node, visitor, context); } function visitLabeledStatement(node) { - if (enclosingFunctionFlags & 2) { + if (enclosingFunctionFlags & 2 /* Async */) { var statement = ts.unwrapInnermostStatementOfLabel(node); - if (statement.kind === 222 && statement.awaitModifier) { + if (statement.kind === 222 /* ForOfStatement */ && statement.awaitModifier) { return visitForOfStatement(statement, node); } return ts.restoreEnclosingLabel(ts.visitEachChild(statement, visitor, context), node); @@ -55126,7 +65045,7 @@ var ts; var objects = []; for (var _i = 0, elements_4 = elements; _i < elements_4.length; _i++) { var e = elements_4[_i]; - if (e.kind === 272) { + if (e.kind === 272 /* SpreadAssignment */) { if (chunkObject) { objects.push(ts.createObjectLiteral(chunkObject)); chunkObject = undefined; @@ -55135,7 +65054,7 @@ var ts; objects.push(ts.visitNode(target, visitor, ts.isExpression)); } else { - chunkObject = ts.append(chunkObject, e.kind === 270 + chunkObject = ts.append(chunkObject, e.kind === 270 /* PropertyAssignment */ ? ts.createPropertyAssignment(e.name, ts.visitNode(e.initializer, visitor, ts.isExpression)) : ts.visitNode(e, visitor, ts.isObjectLiteralElementLike)); } @@ -55146,9 +65065,14 @@ var ts; return objects; } function visitObjectLiteralExpression(node) { - if (node.transformFlags & 1048576) { + if (node.transformFlags & 1048576 /* ContainsObjectSpread */) { + // spread elements emit like so: + // non-spread elements are chunked together into object literals, and then all are passed to __assign: + // { a, ...o, b } => __assign({a}, o, {b}); + // If the first element is a spread element, then the first argument to __assign is {}: + // { ...o, a, b, ...o2 } => __assign({}, o, {a, b}, o2) var objects = chunkObjectLiteralElements(node.properties); - if (objects.length && objects[0].kind !== 184) { + if (objects.length && objects[0].kind !== 184 /* ObjectLiteralExpression */) { objects.unshift(ts.createObjectLiteral()); } return createAssignHelper(context, objects); @@ -55163,22 +65087,33 @@ var ts; } function visitCatchClause(node) { if (!node.variableDeclaration) { - return ts.updateCatchClause(node, ts.createVariableDeclaration(ts.createTempVariable(undefined)), ts.visitNode(node.block, visitor, ts.isBlock)); + return ts.updateCatchClause(node, ts.createVariableDeclaration(ts.createTempVariable(/*recordTempVariable*/ undefined)), ts.visitNode(node.block, visitor, ts.isBlock)); } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a BinaryExpression that contains a destructuring assignment. + * + * @param node A BinaryExpression node. + */ function visitBinaryExpression(node, noDestructuringValue) { - if (ts.isDestructuringAssignment(node) && node.left.transformFlags & 1048576) { - return ts.flattenDestructuringAssignment(node, visitor, context, 1, !noDestructuringValue); + if (ts.isDestructuringAssignment(node) && node.left.transformFlags & 1048576 /* ContainsObjectRest */) { + return ts.flattenDestructuringAssignment(node, visitor, context, 1 /* ObjectRest */, !noDestructuringValue); } - else if (node.operatorToken.kind === 26) { + else if (node.operatorToken.kind === 26 /* CommaToken */) { return ts.updateBinary(node, ts.visitNode(node.left, visitorNoDestructuringValue, ts.isExpression), ts.visitNode(node.right, noDestructuringValue ? visitorNoDestructuringValue : visitor, ts.isExpression)); } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a VariableDeclaration node with a binding pattern. + * + * @param node A VariableDeclaration node. + */ function visitVariableDeclaration(node) { - if (ts.isBindingPattern(node.name) && node.name.transformFlags & 1048576) { - return ts.flattenDestructuringBinding(node, visitor, context, 1); + // If we are here it is because the name contains a binding pattern with a rest somewhere in it. + if (ts.isBindingPattern(node.name) && node.name.transformFlags & 1048576 /* ContainsObjectRest */) { + return ts.flattenDestructuringBinding(node, visitor, context, 1 /* ObjectRest */); } return ts.visitEachChild(node, visitor, context); } @@ -55188,8 +65123,13 @@ var ts; function visitVoidExpression(node) { return ts.visitEachChild(node, visitorNoDestructuringValue, context); } + /** + * Visits a ForOfStatement and converts it into a ES2015-compatible ForOfStatement. + * + * @param node A ForOfStatement. + */ function visitForOfStatement(node, outermostLabeledStatement) { - if (node.initializer.transformFlags & 1048576) { + if (node.initializer.transformFlags & 1048576 /* ContainsObjectRest */) { node = transformForOfStatementWithObjectRest(node); } if (node.awaitModifier) { @@ -55204,7 +65144,7 @@ var ts; if (ts.isVariableDeclarationList(initializerWithoutParens) || ts.isAssignmentPattern(initializerWithoutParens)) { var bodyLocation = void 0; var statementsLocation = void 0; - var temp = ts.createTempVariable(undefined); + var temp = ts.createTempVariable(/*recordTempVariable*/ undefined); var statements = [ts.createForOfBindingStatement(initializerWithoutParens, temp)]; if (ts.isBlock(node.statement)) { ts.addRange(statements, node.statement.statements); @@ -55218,7 +65158,8 @@ var ts; } return ts.updateForOf(node, node.awaitModifier, ts.setTextRange(ts.createVariableDeclarationList([ ts.setTextRange(ts.createVariableDeclaration(temp), node.initializer) - ], 1), node.initializer), node.expression, ts.setTextRange(ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), statementsLocation), true), bodyLocation)); + ], 1 /* Let */), node.initializer), node.expression, ts.setTextRange(ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), statementsLocation), + /*multiLine*/ true), bodyLocation)); } return node; } @@ -55236,80 +65177,102 @@ var ts; else { statements.push(statement); } - return ts.setEmitFlags(ts.setTextRange(ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), statementsLocation), true), bodyLocation), 48 | 384); + return ts.setEmitFlags(ts.setTextRange(ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), statementsLocation), + /*multiLine*/ true), bodyLocation), 48 /* NoSourceMap */ | 384 /* NoTokenSourceMaps */); } function createDownlevelAwait(expression) { - return enclosingFunctionFlags & 1 - ? ts.createYield(undefined, createAwaitHelper(context, expression)) + return enclosingFunctionFlags & 1 /* Generator */ + ? ts.createYield(/*asteriskToken*/ undefined, createAwaitHelper(context, expression)) : ts.createAwait(expression); } function transformForAwaitOfStatement(node, outermostLabeledStatement) { var expression = ts.visitNode(node.expression, visitor, ts.isExpression); - var iterator = ts.isIdentifier(expression) ? ts.getGeneratedNameForNode(expression) : ts.createTempVariable(undefined); - var result = ts.isIdentifier(expression) ? ts.getGeneratedNameForNode(iterator) : ts.createTempVariable(undefined); + var iterator = ts.isIdentifier(expression) ? ts.getGeneratedNameForNode(expression) : ts.createTempVariable(/*recordTempVariable*/ undefined); + var result = ts.isIdentifier(expression) ? ts.getGeneratedNameForNode(iterator) : ts.createTempVariable(/*recordTempVariable*/ undefined); var errorRecord = ts.createUniqueName("e"); var catchVariable = ts.getGeneratedNameForNode(errorRecord); - var returnMethod = ts.createTempVariable(undefined); - var callValues = createAsyncValuesHelper(context, expression, node.expression); - var callNext = ts.createCall(ts.createPropertyAccess(iterator, "next"), undefined, []); + var returnMethod = ts.createTempVariable(/*recordTempVariable*/ undefined); + var callValues = createAsyncValuesHelper(context, expression, /*location*/ node.expression); + var callNext = ts.createCall(ts.createPropertyAccess(iterator, "next"), /*typeArguments*/ undefined, []); var getDone = ts.createPropertyAccess(result, "done"); var getValue = ts.createPropertyAccess(result, "value"); var callReturn = ts.createFunctionCall(returnMethod, iterator, []); hoistVariableDeclaration(errorRecord); hoistVariableDeclaration(returnMethod); - var forStatement = ts.setEmitFlags(ts.setTextRange(ts.createFor(ts.setEmitFlags(ts.setTextRange(ts.createVariableDeclarationList([ - ts.setTextRange(ts.createVariableDeclaration(iterator, undefined, callValues), node.expression), + var forStatement = ts.setEmitFlags(ts.setTextRange(ts.createFor( + /*initializer*/ ts.setEmitFlags(ts.setTextRange(ts.createVariableDeclarationList([ + ts.setTextRange(ts.createVariableDeclaration(iterator, /*type*/ undefined, callValues), node.expression), ts.createVariableDeclaration(result) - ]), node.expression), 2097152), ts.createComma(ts.createAssignment(result, createDownlevelAwait(callNext)), ts.createLogicalNot(getDone)), undefined, convertForOfStatementHead(node, getValue)), node), 256); + ]), node.expression), 2097152 /* NoHoisting */), + /*condition*/ ts.createComma(ts.createAssignment(result, createDownlevelAwait(callNext)), ts.createLogicalNot(getDone)), + /*incrementor*/ undefined, + /*statement*/ convertForOfStatementHead(node, getValue)), + /*location*/ node), 256 /* NoTokenTrailingSourceMaps */); return ts.createTry(ts.createBlock([ ts.restoreEnclosingLabel(forStatement, outermostLabeledStatement) ]), ts.createCatchClause(ts.createVariableDeclaration(catchVariable), ts.setEmitFlags(ts.createBlock([ ts.createStatement(ts.createAssignment(errorRecord, ts.createObjectLiteral([ ts.createPropertyAssignment("error", catchVariable) ]))) - ]), 1)), ts.createBlock([ - ts.createTry(ts.createBlock([ - ts.setEmitFlags(ts.createIf(ts.createLogicalAnd(ts.createLogicalAnd(result, ts.createLogicalNot(getDone)), ts.createAssignment(returnMethod, ts.createPropertyAccess(iterator, "return"))), ts.createStatement(createDownlevelAwait(callReturn))), 1) - ]), undefined, ts.setEmitFlags(ts.createBlock([ - ts.setEmitFlags(ts.createIf(errorRecord, ts.createThrow(ts.createPropertyAccess(errorRecord, "error"))), 1) - ]), 1)) + ]), 1 /* SingleLine */)), ts.createBlock([ + ts.createTry( + /*tryBlock*/ ts.createBlock([ + ts.setEmitFlags(ts.createIf(ts.createLogicalAnd(ts.createLogicalAnd(result, ts.createLogicalNot(getDone)), ts.createAssignment(returnMethod, ts.createPropertyAccess(iterator, "return"))), ts.createStatement(createDownlevelAwait(callReturn))), 1 /* SingleLine */) + ]), + /*catchClause*/ undefined, + /*finallyBlock*/ ts.setEmitFlags(ts.createBlock([ + ts.setEmitFlags(ts.createIf(errorRecord, ts.createThrow(ts.createPropertyAccess(errorRecord, "error"))), 1 /* SingleLine */) + ]), 1 /* SingleLine */)) ])); } function visitParameter(node) { - if (node.transformFlags & 1048576) { - return ts.updateParameter(node, undefined, undefined, node.dotDotDotToken, ts.getGeneratedNameForNode(node), undefined, undefined, ts.visitNode(node.initializer, visitor, ts.isExpression)); + if (node.transformFlags & 1048576 /* ContainsObjectRest */) { + // Binding patterns are converted into a generated name and are + // evaluated inside the function body. + return ts.updateParameter(node, + /*decorators*/ undefined, + /*modifiers*/ undefined, node.dotDotDotToken, ts.getGeneratedNameForNode(node), + /*questionToken*/ undefined, + /*type*/ undefined, ts.visitNode(node.initializer, visitor, ts.isExpression)); } return ts.visitEachChild(node, visitor, context); } function visitConstructorDeclaration(node) { var savedEnclosingFunctionFlags = enclosingFunctionFlags; - enclosingFunctionFlags = 0; - var updated = ts.updateConstructor(node, undefined, node.modifiers, ts.visitParameterList(node.parameters, visitor, context), transformFunctionBody(node)); + enclosingFunctionFlags = 0 /* Normal */; + var updated = ts.updateConstructor(node, + /*decorators*/ undefined, node.modifiers, ts.visitParameterList(node.parameters, visitor, context), transformFunctionBody(node)); enclosingFunctionFlags = savedEnclosingFunctionFlags; return updated; } function visitGetAccessorDeclaration(node) { var savedEnclosingFunctionFlags = enclosingFunctionFlags; - enclosingFunctionFlags = 0; - var updated = ts.updateGetAccessor(node, undefined, node.modifiers, ts.visitNode(node.name, visitor, ts.isPropertyName), ts.visitParameterList(node.parameters, visitor, context), undefined, transformFunctionBody(node)); + enclosingFunctionFlags = 0 /* Normal */; + var updated = ts.updateGetAccessor(node, + /*decorators*/ undefined, node.modifiers, ts.visitNode(node.name, visitor, ts.isPropertyName), ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, transformFunctionBody(node)); enclosingFunctionFlags = savedEnclosingFunctionFlags; return updated; } function visitSetAccessorDeclaration(node) { var savedEnclosingFunctionFlags = enclosingFunctionFlags; - enclosingFunctionFlags = 0; - var updated = ts.updateSetAccessor(node, undefined, node.modifiers, ts.visitNode(node.name, visitor, ts.isPropertyName), ts.visitParameterList(node.parameters, visitor, context), transformFunctionBody(node)); + enclosingFunctionFlags = 0 /* Normal */; + var updated = ts.updateSetAccessor(node, + /*decorators*/ undefined, node.modifiers, ts.visitNode(node.name, visitor, ts.isPropertyName), ts.visitParameterList(node.parameters, visitor, context), transformFunctionBody(node)); enclosingFunctionFlags = savedEnclosingFunctionFlags; return updated; } function visitMethodDeclaration(node) { var savedEnclosingFunctionFlags = enclosingFunctionFlags; enclosingFunctionFlags = ts.getFunctionFlags(node); - var updated = ts.updateMethod(node, undefined, enclosingFunctionFlags & 1 + var updated = ts.updateMethod(node, + /*decorators*/ undefined, enclosingFunctionFlags & 1 /* Generator */ ? ts.visitNodes(node.modifiers, visitorNoAsyncModifier, ts.isModifier) - : node.modifiers, enclosingFunctionFlags & 2 + : node.modifiers, enclosingFunctionFlags & 2 /* Async */ ? undefined - : node.asteriskToken, ts.visitNode(node.name, visitor, ts.isPropertyName), ts.visitNode(undefined, visitor, ts.isToken), undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, enclosingFunctionFlags & 2 && enclosingFunctionFlags & 1 + : node.asteriskToken, ts.visitNode(node.name, visitor, ts.isPropertyName), ts.visitNode(/*questionToken*/ undefined, visitor, ts.isToken), + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, enclosingFunctionFlags & 2 /* Async */ && enclosingFunctionFlags & 1 /* Generator */ ? transformAsyncGeneratorFunctionBody(node) : transformFunctionBody(node)); enclosingFunctionFlags = savedEnclosingFunctionFlags; @@ -55318,11 +65281,14 @@ var ts; function visitFunctionDeclaration(node) { var savedEnclosingFunctionFlags = enclosingFunctionFlags; enclosingFunctionFlags = ts.getFunctionFlags(node); - var updated = ts.updateFunctionDeclaration(node, undefined, enclosingFunctionFlags & 1 + var updated = ts.updateFunctionDeclaration(node, + /*decorators*/ undefined, enclosingFunctionFlags & 1 /* Generator */ ? ts.visitNodes(node.modifiers, visitorNoAsyncModifier, ts.isModifier) - : node.modifiers, enclosingFunctionFlags & 2 + : node.modifiers, enclosingFunctionFlags & 2 /* Async */ ? undefined - : node.asteriskToken, node.name, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, enclosingFunctionFlags & 2 && enclosingFunctionFlags & 1 + : node.asteriskToken, node.name, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, enclosingFunctionFlags & 2 /* Async */ && enclosingFunctionFlags & 1 /* Generator */ ? transformAsyncGeneratorFunctionBody(node) : transformFunctionBody(node)); enclosingFunctionFlags = savedEnclosingFunctionFlags; @@ -55331,18 +65297,22 @@ var ts; function visitArrowFunction(node) { var savedEnclosingFunctionFlags = enclosingFunctionFlags; enclosingFunctionFlags = ts.getFunctionFlags(node); - var updated = ts.updateArrowFunction(node, node.modifiers, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, node.equalsGreaterThanToken, transformFunctionBody(node)); + var updated = ts.updateArrowFunction(node, node.modifiers, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, node.equalsGreaterThanToken, transformFunctionBody(node)); enclosingFunctionFlags = savedEnclosingFunctionFlags; return updated; } function visitFunctionExpression(node) { var savedEnclosingFunctionFlags = enclosingFunctionFlags; enclosingFunctionFlags = ts.getFunctionFlags(node); - var updated = ts.updateFunctionExpression(node, enclosingFunctionFlags & 1 + var updated = ts.updateFunctionExpression(node, enclosingFunctionFlags & 1 /* Generator */ ? ts.visitNodes(node.modifiers, visitorNoAsyncModifier, ts.isModifier) - : node.modifiers, enclosingFunctionFlags & 2 + : node.modifiers, enclosingFunctionFlags & 2 /* Async */ ? undefined - : node.asteriskToken, node.name, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, enclosingFunctionFlags & 2 && enclosingFunctionFlags & 1 + : node.asteriskToken, node.name, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, enclosingFunctionFlags & 2 /* Async */ && enclosingFunctionFlags & 1 /* Generator */ ? transformAsyncGeneratorFunctionBody(node) : transformFunctionBody(node)); enclosingFunctionFlags = savedEnclosingFunctionFlags; @@ -55351,17 +65321,23 @@ var ts; function transformAsyncGeneratorFunctionBody(node) { resumeLexicalEnvironment(); var statements = []; - var statementOffset = ts.addPrologue(statements, node.body.statements, false, visitor); + var statementOffset = ts.addPrologue(statements, node.body.statements, /*ensureUseStrict*/ false, visitor); appendObjectRestAssignmentsIfNeeded(statements, node); - statements.push(ts.createReturn(createAsyncGeneratorHelper(context, ts.createFunctionExpression(undefined, ts.createToken(39), node.name && ts.getGeneratedNameForNode(node.name), undefined, [], undefined, ts.updateBlock(node.body, ts.visitLexicalEnvironment(node.body.statements, visitor, context, statementOffset)))))); + statements.push(ts.createReturn(createAsyncGeneratorHelper(context, ts.createFunctionExpression( + /*modifiers*/ undefined, ts.createToken(39 /* AsteriskToken */), node.name && ts.getGeneratedNameForNode(node.name), + /*typeParameters*/ undefined, + /*parameters*/ [], + /*type*/ undefined, ts.updateBlock(node.body, ts.visitLexicalEnvironment(node.body.statements, visitor, context, statementOffset)))))); ts.prependStatements(statements, endLexicalEnvironment()); var block = ts.updateBlock(node.body, statements); - if (languageVersion >= 2) { - if (resolver.getNodeCheckFlags(node) & 4096) { + // Minor optimization, emit `_super` helper to capture `super` access in an arrow. + // This step isn't needed if we eventually transform this to ES5. + if (languageVersion >= 2 /* ES2015 */) { + if (resolver.getNodeCheckFlags(node) & 4096 /* AsyncMethodWithSuperBinding */) { enableSubstitutionForAsyncMethodsWithSuper(); ts.addEmitHelper(block, ts.advancedAsyncSuperHelper); } - else if (resolver.getNodeCheckFlags(node) & 2048) { + else if (resolver.getNodeCheckFlags(node) & 2048 /* AsyncMethodWithSuper */) { enableSubstitutionForAsyncMethodsWithSuper(); ts.addEmitHelper(block, ts.asyncSuperHelper); } @@ -55374,12 +65350,12 @@ var ts; var statements = []; var body = ts.visitNode(node.body, visitor, ts.isConciseBody); if (ts.isBlock(body)) { - statementOffset = ts.addPrologue(statements, body.statements, false, visitor); + statementOffset = ts.addPrologue(statements, body.statements, /*ensureUseStrict*/ false, visitor); } - ts.addRange(statements, appendObjectRestAssignmentsIfNeeded(undefined, node)); + ts.addRange(statements, appendObjectRestAssignmentsIfNeeded(/*statements*/ undefined, node)); var leadingStatements = endLexicalEnvironment(); if (statementOffset > 0 || ts.some(statements) || ts.some(leadingStatements)) { - var block = ts.convertToFunctionBody(body, true); + var block = ts.convertToFunctionBody(body, /*multiLine*/ true); ts.prependStatements(statements, leadingStatements); ts.addRange(statements, block.statements.slice(statementOffset)); return ts.updateBlock(block, ts.setTextRange(ts.createNodeArray(statements), block.statements)); @@ -55389,12 +65365,15 @@ var ts; function appendObjectRestAssignmentsIfNeeded(statements, node) { for (var _i = 0, _a = node.parameters; _i < _a.length; _i++) { var parameter = _a[_i]; - if (parameter.transformFlags & 1048576) { + if (parameter.transformFlags & 1048576 /* ContainsObjectRest */) { var temp = ts.getGeneratedNameForNode(parameter); - var declarations = ts.flattenDestructuringBinding(parameter, visitor, context, 1, temp, false, true); + var declarations = ts.flattenDestructuringBinding(parameter, visitor, context, 1 /* ObjectRest */, temp, + /*doNotRecordTempVariablesInLine*/ false, + /*skipInitializer*/ true); if (ts.some(declarations)) { - var statement = ts.createVariableStatement(undefined, ts.createVariableDeclarationList(declarations)); - ts.setEmitFlags(statement, 1048576); + var statement = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList(declarations)); + ts.setEmitFlags(statement, 1048576 /* CustomPrologue */); statements = ts.append(statements, statement); } } @@ -55402,21 +65381,33 @@ var ts; return statements; } function enableSubstitutionForAsyncMethodsWithSuper() { - if ((enabledSubstitutions & 1) === 0) { - enabledSubstitutions |= 1; - context.enableSubstitution(187); - context.enableSubstitution(185); - context.enableSubstitution(186); - context.enableEmitNotification(235); - context.enableEmitNotification(154); - context.enableEmitNotification(156); - context.enableEmitNotification(157); - context.enableEmitNotification(155); + if ((enabledSubstitutions & 1 /* AsyncMethodsWithSuper */) === 0) { + enabledSubstitutions |= 1 /* AsyncMethodsWithSuper */; + // We need to enable substitutions for call, property access, and element access + // if we need to rewrite super calls. + context.enableSubstitution(187 /* CallExpression */); + context.enableSubstitution(185 /* PropertyAccessExpression */); + context.enableSubstitution(186 /* ElementAccessExpression */); + // We need to be notified when entering and exiting declarations that bind super. + context.enableEmitNotification(235 /* ClassDeclaration */); + context.enableEmitNotification(154 /* MethodDeclaration */); + context.enableEmitNotification(156 /* GetAccessor */); + context.enableEmitNotification(157 /* SetAccessor */); + context.enableEmitNotification(155 /* Constructor */); } } + /** + * Called by the printer just before a node is printed. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to be printed. + * @param emitCallback The callback used to emit the node. + */ function onEmitNode(hint, node, emitCallback) { - if (enabledSubstitutions & 1 && isSuperContainer(node)) { - var superContainerFlags = resolver.getNodeCheckFlags(node) & (2048 | 4096); + // If we need to support substitutions for `super` in an async method, + // we should track it here. + if (enabledSubstitutions & 1 /* AsyncMethodsWithSuper */ && isSuperContainer(node)) { + var superContainerFlags = resolver.getNodeCheckFlags(node) & (2048 /* AsyncMethodWithSuper */ | 4096 /* AsyncMethodWithSuperBinding */); if (superContainerFlags !== enclosingSuperContainerFlags) { var savedEnclosingSuperContainerFlags = enclosingSuperContainerFlags; enclosingSuperContainerFlags = superContainerFlags; @@ -55427,32 +65418,38 @@ var ts; } previousOnEmitNode(hint, node, emitCallback); } + /** + * Hooks node substitutions. + * + * @param hint The context for the emitter. + * @param node The node to substitute. + */ function onSubstituteNode(hint, node) { node = previousOnSubstituteNode(hint, node); - if (hint === 1 && enclosingSuperContainerFlags) { + if (hint === 1 /* Expression */ && enclosingSuperContainerFlags) { return substituteExpression(node); } return node; } function substituteExpression(node) { switch (node.kind) { - case 185: + case 185 /* PropertyAccessExpression */: return substitutePropertyAccessExpression(node); - case 186: + case 186 /* ElementAccessExpression */: return substituteElementAccessExpression(node); - case 187: + case 187 /* CallExpression */: return substituteCallExpression(node); } return node; } function substitutePropertyAccessExpression(node) { - if (node.expression.kind === 97) { + if (node.expression.kind === 97 /* SuperKeyword */) { return createSuperAccessInAsyncMethod(ts.createLiteral(ts.idText(node.name)), node); } return node; } function substituteElementAccessExpression(node) { - if (node.expression.kind === 97) { + if (node.expression.kind === 97 /* SuperKeyword */) { return createSuperAccessInAsyncMethod(node.argumentExpression, node); } return node; @@ -55463,7 +65460,8 @@ var ts; var argumentExpression = ts.isPropertyAccessExpression(expression) ? substitutePropertyAccessExpression(expression) : substituteElementAccessExpression(expression); - return ts.createCall(ts.createPropertyAccess(argumentExpression, "call"), undefined, [ + return ts.createCall(ts.createPropertyAccess(argumentExpression, "call"), + /*typeArguments*/ undefined, [ ts.createThis() ].concat(node.arguments)); } @@ -55471,18 +65469,20 @@ var ts; } function isSuperContainer(node) { var kind = node.kind; - return kind === 235 - || kind === 155 - || kind === 154 - || kind === 156 - || kind === 157; + return kind === 235 /* ClassDeclaration */ + || kind === 155 /* Constructor */ + || kind === 154 /* MethodDeclaration */ + || kind === 156 /* GetAccessor */ + || kind === 157 /* SetAccessor */; } function createSuperAccessInAsyncMethod(argumentExpression, location) { - if (enclosingSuperContainerFlags & 4096) { - return ts.setTextRange(ts.createPropertyAccess(ts.createCall(ts.createIdentifier("_super"), undefined, [argumentExpression]), "value"), location); + if (enclosingSuperContainerFlags & 4096 /* AsyncMethodWithSuperBinding */) { + return ts.setTextRange(ts.createPropertyAccess(ts.createCall(ts.createIdentifier("_super"), + /*typeArguments*/ undefined, [argumentExpression]), "value"), location); } else { - return ts.setTextRange(ts.createCall(ts.createIdentifier("_super"), undefined, [argumentExpression]), location); + return ts.setTextRange(ts.createCall(ts.createIdentifier("_super"), + /*typeArguments*/ undefined, [argumentExpression]), location); } } } @@ -55491,14 +65491,16 @@ var ts; name: "typescript:assign", scoped: false, priority: 1, - text: "\n var __assign = (this && this.__assign) || Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };" + text: "\n var __assign = (this && this.__assign) || function () {\n __assign = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign.apply(this, arguments);\n };" }; function createAssignHelper(context, attributesSegments) { - if (context.getCompilerOptions().target >= 2) { - return ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Object"), "assign"), undefined, attributesSegments); + if (context.getCompilerOptions().target >= 2 /* ES2015 */) { + return ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Object"), "assign"), + /*typeArguments*/ undefined, attributesSegments); } context.requestEmitHelper(assignHelper); - return ts.createCall(ts.getHelperName("__assign"), undefined, attributesSegments); + return ts.createCall(ts.getHelperName("__assign"), + /*typeArguments*/ undefined, attributesSegments); } ts.createAssignHelper = createAssignHelper; var awaitHelper = { @@ -55508,7 +65510,7 @@ var ts; }; function createAwaitHelper(context, expression) { context.requestEmitHelper(awaitHelper); - return ts.createCall(ts.getHelperName("__await"), undefined, [expression]); + return ts.createCall(ts.getHelperName("__await"), /*typeArguments*/ undefined, [expression]); } var asyncGeneratorHelper = { name: "typescript:asyncGenerator", @@ -55518,8 +65520,10 @@ var ts; function createAsyncGeneratorHelper(context, generatorFunc) { context.requestEmitHelper(awaitHelper); context.requestEmitHelper(asyncGeneratorHelper); - (generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= 262144; - return ts.createCall(ts.getHelperName("__asyncGenerator"), undefined, [ + // Mark this node as originally an async function + (generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= 262144 /* AsyncFunctionBody */; + return ts.createCall(ts.getHelperName("__asyncGenerator"), + /*typeArguments*/ undefined, [ ts.createThis(), ts.createIdentifier("arguments"), generatorFunc @@ -55533,7 +65537,8 @@ var ts; function createAsyncDelegatorHelper(context, expression, location) { context.requestEmitHelper(awaitHelper); context.requestEmitHelper(asyncDelegator); - return ts.setTextRange(ts.createCall(ts.getHelperName("__asyncDelegator"), undefined, [expression]), location); + return ts.setTextRange(ts.createCall(ts.getHelperName("__asyncDelegator"), + /*typeArguments*/ undefined, [expression]), location); } var asyncValues = { name: "typescript:asyncValues", @@ -55542,15 +65547,22 @@ var ts; }; function createAsyncValuesHelper(context, expression, location) { context.requestEmitHelper(asyncValues); - return ts.setTextRange(ts.createCall(ts.getHelperName("__asyncValues"), undefined, [expression]), location); + return ts.setTextRange(ts.createCall(ts.getHelperName("__asyncValues"), + /*typeArguments*/ undefined, [expression]), location); } })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { function transformJsx(context) { var compilerOptions = context.getCompilerOptions(); var currentSourceFile; return ts.chainBundle(transformSourceFile); + /** + * Transform JSX-specific syntax in a SourceFile. + * + * @param node A SourceFile node. + */ function transformSourceFile(node) { if (node.isDeclarationFile) { return node; @@ -55561,7 +65573,7 @@ var ts; return visited; } function visitor(node) { - if (node.transformFlags & 4) { + if (node.transformFlags & 4 /* ContainsJsx */) { return visitorWorker(node); } else { @@ -55570,13 +65582,13 @@ var ts; } function visitorWorker(node) { switch (node.kind) { - case 255: - return visitJsxElement(node, false); - case 256: - return visitJsxSelfClosingElement(node, false); - case 259: - return visitJsxFragment(node, false); - case 265: + case 255 /* JsxElement */: + return visitJsxElement(node, /*isChild*/ false); + case 256 /* JsxSelfClosingElement */: + return visitJsxSelfClosingElement(node, /*isChild*/ false); + case 259 /* JsxFragment */: + return visitJsxFragment(node, /*isChild*/ false); + case 265 /* JsxExpression */: return visitJsxExpression(node); default: return ts.visitEachChild(node, visitor, context); @@ -55584,56 +65596,65 @@ var ts; } function transformJsxChildToExpression(node) { switch (node.kind) { - case 10: + case 10 /* JsxText */: return visitJsxText(node); - case 265: + case 265 /* JsxExpression */: return visitJsxExpression(node); - case 255: - return visitJsxElement(node, true); - case 256: - return visitJsxSelfClosingElement(node, true); - case 259: - return visitJsxFragment(node, true); + case 255 /* JsxElement */: + return visitJsxElement(node, /*isChild*/ true); + case 256 /* JsxSelfClosingElement */: + return visitJsxSelfClosingElement(node, /*isChild*/ true); + case 259 /* JsxFragment */: + return visitJsxFragment(node, /*isChild*/ true); default: return ts.Debug.failBadSyntaxKind(node); } } function visitJsxElement(node, isChild) { - return visitJsxOpeningLikeElement(node.openingElement, node.children, isChild, node); + return visitJsxOpeningLikeElement(node.openingElement, node.children, isChild, /*location*/ node); } function visitJsxSelfClosingElement(node, isChild) { - return visitJsxOpeningLikeElement(node, undefined, isChild, node); + return visitJsxOpeningLikeElement(node, /*children*/ undefined, isChild, /*location*/ node); } function visitJsxFragment(node, isChild) { - return visitJsxOpeningFragment(node.openingFragment, node.children, isChild, node); + return visitJsxOpeningFragment(node.openingFragment, node.children, isChild, /*location*/ node); } function visitJsxOpeningLikeElement(node, children, isChild, location) { var tagName = getTagName(node); var objectProperties; var attrs = node.attributes.properties; if (attrs.length === 0) { + // When there are no attributes, React wants "null" objectProperties = ts.createNull(); } else { + // Map spans of JsxAttribute nodes into object literals and spans + // of JsxSpreadAttribute nodes into expressions. var segments = ts.flatten(ts.spanMap(attrs, ts.isJsxSpreadAttribute, function (attrs, isSpread) { return isSpread ? ts.map(attrs, transformJsxSpreadAttributeToExpression) : ts.createObjectLiteral(ts.map(attrs, transformJsxAttributeToObjectLiteralElement)); })); if (ts.isJsxSpreadAttribute(attrs[0])) { + // We must always emit at least one object literal before a spread + // argument. segments.unshift(ts.createObjectLiteral()); } + // Either emit one big object literal (no spread attribs), or + // a call to the __assign helper. objectProperties = ts.singleOrUndefined(segments); if (!objectProperties) { objectProperties = ts.createAssignHelper(context, segments); } } - var element = ts.createExpressionForJsxElement(context.getEmitResolver().getJsxFactoryEntity(currentSourceFile), compilerOptions.reactNamespace, tagName, objectProperties, ts.mapDefined(children, transformJsxChildToExpression), node, location); + var element = ts.createExpressionForJsxElement(context.getEmitResolver().getJsxFactoryEntity(currentSourceFile), compilerOptions.reactNamespace, // TODO: GH#18217 + tagName, objectProperties, ts.mapDefined(children, transformJsxChildToExpression), node, location); if (isChild) { ts.startOnNewLine(element); } return element; } function visitJsxOpeningFragment(node, children, isChild, location) { - var element = ts.createExpressionForJsxFragment(context.getEmitResolver().getJsxFactoryEntity(currentSourceFile), compilerOptions.reactNamespace, ts.mapDefined(children, transformJsxChildToExpression), node, location); + var element = ts.createExpressionForJsxFragment(context.getEmitResolver().getJsxFactoryEntity(currentSourceFile), compilerOptions.reactNamespace, // TODO: GH#18217 + ts.mapDefined(children, transformJsxChildToExpression), node, location); if (isChild) { ts.startOnNewLine(element); } @@ -55651,12 +65672,14 @@ var ts; if (node === undefined) { return ts.createTrue(); } - else if (node.kind === 9) { + else if (node.kind === 9 /* StringLiteral */) { + // Always recreate the literal to escape any escape sequences or newlines which may be in the original jsx string and which + // Need to be escaped to be handled correctly in a normal string var literal = ts.createLiteral(tryDecodeEntities(node.text) || node.text); literal.singleQuote = node.singleQuote !== undefined ? node.singleQuote : !ts.isStringDoubleQuoted(node, currentSourceFile); return ts.setTextRange(literal, node); } - else if (node.kind === 265) { + else if (node.kind === 265 /* JsxExpression */) { if (node.expression === undefined) { return ts.createTrue(); } @@ -55667,19 +65690,43 @@ var ts; } } function visitJsxText(node) { - var fixed = fixupWhitespaceAndDecodeEntities(ts.getTextOfNode(node, true)); + var fixed = fixupWhitespaceAndDecodeEntities(ts.getTextOfNode(node, /*includeTrivia*/ true)); return fixed === undefined ? undefined : ts.createLiteral(fixed); } + /** + * 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 + * See also https://www.w3.org/TR/html4/struct/text.html#h-9.1 and https://www.w3.org/TR/CSS2/text.html#white-space-model + * + * An equivalent algorithm would be: + * - If there is only one line, return it. + * - If there is only whitespace (but multiple lines), return `undefined`. + * - Split the text into lines. + * - 'trimRight' the first line, 'trimLeft' the last line, 'trim' middle lines. + * - Decode entities on each line (individually). + * - Remove empty lines and join the rest with " ". + */ function fixupWhitespaceAndDecodeEntities(text) { var acc; + // First non-whitespace character on this line. var firstNonWhitespace = 0; + // Last non-whitespace character on this line. var lastNonWhitespace = -1; + // These initial values are special because the first line is: + // firstNonWhitespace = 0 to indicate that we want leading whitsepace, + // but lastNonWhitespace = -1 as a special flag to indicate that we *don't* include the line if it's all whitespace. for (var i = 0; i < text.length; i++) { var c = text.charCodeAt(i); if (ts.isLineBreak(c)) { + // If we've seen any non-whitespace characters on this line, add the 'trim' of the line. + // (lastNonWhitespace === -1 is a special flag to detect whether the first line is all whitespace.) if (firstNonWhitespace !== -1 && lastNonWhitespace !== -1) { acc = addLineOfJsxText(acc, text.substr(firstNonWhitespace, lastNonWhitespace - firstNonWhitespace + 1)); } + // Reset firstNonWhitespace for the next line. + // Don't bother to reset lastNonWhitespace because we ignore it if firstNonWhitespace = -1. firstNonWhitespace = -1; } else if (!ts.isWhiteSpaceSingleLine(c)) { @@ -55690,13 +65737,21 @@ var ts; } } return firstNonWhitespace !== -1 + // Last line had a non-whitespace character. Emit the 'trimLeft', meaning keep trailing whitespace. ? addLineOfJsxText(acc, text.substr(firstNonWhitespace)) + // Last line was all whitespace, so ignore it : acc; } function addLineOfJsxText(acc, trimmedLine) { + // We do not escape the string here as that is handled by the printer + // when it emits the literal. We do, however, need to decode JSX entities. var decoded = decodeEntities(trimmedLine); return acc === undefined ? decoded : acc + " " + decoded; } + /** + * Replace entities like " ", "{", and "�" with the characters they encode. + * See https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references + */ function decodeEntities(text) { return text.replace(/&((#((\d+)|x([\da-fA-F]+)))|(\w+));/g, function (match, _all, _number, _digits, decimal, hex, word) { if (decimal) { @@ -55707,16 +65762,18 @@ var ts; } else { var ch = entities.get(word); + // If this is not a valid entity, then just use `match` (replace it with itself, i.e. don't replace) return ch ? String.fromCharCode(ch) : match; } }); } + /** Like `decodeEntities` but returns `undefined` if there were no entities to decode. */ function tryDecodeEntities(text) { var decoded = decodeEntities(text); return decoded === text ? undefined : decoded; } function getTagName(node) { - if (node.kind === 255) { + if (node.kind === 255 /* JsxElement */) { return getTagName(node.openingElement); } else { @@ -55729,6 +65786,11 @@ var ts; } } } + /** + * 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) { var name = node.name; var text = ts.idText(name); @@ -56000,6 +66062,7 @@ var ts; diams: 0x2666 }); })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { function transformES2016(context) { @@ -56012,11 +66075,11 @@ var ts; return ts.visitEachChild(node, visitor, context); } function visitor(node) { - if ((node.transformFlags & 32) === 0) { + if ((node.transformFlags & 32 /* ContainsES2016 */) === 0) { return node; } switch (node.kind) { - case 200: + case 200 /* BinaryExpression */: return visitBinaryExpression(node); default: return ts.visitEachChild(node, visitor, context); @@ -56024,9 +66087,9 @@ var ts; } function visitBinaryExpression(node) { switch (node.operatorToken.kind) { - case 62: + case 62 /* AsteriskAsteriskEqualsToken */: return visitExponentiationAssignmentExpression(node); - case 40: + case 40 /* AsteriskAsteriskToken */: return visitExponentiationExpression(node); default: return ts.visitEachChild(node, visitor, context); @@ -56038,35 +66101,42 @@ var ts; var left = ts.visitNode(node.left, visitor, ts.isExpression); var right = ts.visitNode(node.right, visitor, ts.isExpression); if (ts.isElementAccessExpression(left)) { + // Transforms `a[x] **= b` into `(_a = a)[_x = x] = Math.pow(_a[_x], b)` var expressionTemp = ts.createTempVariable(hoistVariableDeclaration); var argumentExpressionTemp = ts.createTempVariable(hoistVariableDeclaration); target = ts.setTextRange(ts.createElementAccess(ts.setTextRange(ts.createAssignment(expressionTemp, left.expression), left.expression), ts.setTextRange(ts.createAssignment(argumentExpressionTemp, left.argumentExpression), left.argumentExpression)), left); value = ts.setTextRange(ts.createElementAccess(expressionTemp, argumentExpressionTemp), left); } else if (ts.isPropertyAccessExpression(left)) { + // Transforms `a.x **= b` into `(_a = a).x = Math.pow(_a.x, b)` var expressionTemp = ts.createTempVariable(hoistVariableDeclaration); target = ts.setTextRange(ts.createPropertyAccess(ts.setTextRange(ts.createAssignment(expressionTemp, left.expression), left.expression), left.name), left); value = ts.setTextRange(ts.createPropertyAccess(expressionTemp, left.name), left); } else { + // Transforms `a **= b` into `a = Math.pow(a, b)` target = left; value = left; } - return ts.setTextRange(ts.createAssignment(target, ts.createMathPow(value, right, node)), node); + return ts.setTextRange(ts.createAssignment(target, ts.createMathPow(value, right, /*location*/ node)), node); } function visitExponentiationExpression(node) { + // Transforms `a ** b` into `Math.pow(a, b)` var left = ts.visitNode(node.left, visitor, ts.isExpression); var right = ts.visitNode(node.right, visitor, ts.isExpression); - return ts.createMathPow(left, right, node); + return ts.createMathPow(left, right, /*location*/ node); } } ts.transformES2016 = transformES2016; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { var ES2015SubstitutionFlags; (function (ES2015SubstitutionFlags) { + /** Enables substitutions for captured `this` */ ES2015SubstitutionFlags[ES2015SubstitutionFlags["CapturedThis"] = 1] = "CapturedThis"; + /** Enables substitutions for block-scoped bindings. */ ES2015SubstitutionFlags[ES2015SubstitutionFlags["BlockScopedBindings"] = 2] = "BlockScopedBindings"; })(ES2015SubstitutionFlags || (ES2015SubstitutionFlags = {})); var CopyDirection; @@ -56082,13 +66152,35 @@ var ts; })(Jump || (Jump = {})); var SuperCaptureResult; (function (SuperCaptureResult) { + /** + * A capture may have been added for calls to 'super', but + * the caller should emit subsequent statements normally. + */ SuperCaptureResult[SuperCaptureResult["NoReplacement"] = 0] = "NoReplacement"; + /** + * A call to 'super()' got replaced with a capturing statement like: + * + * var _this = _super.call(...) || this; + * + * Callers should skip the current statement. + */ SuperCaptureResult[SuperCaptureResult["ReplaceSuperCapture"] = 1] = "ReplaceSuperCapture"; + /** + * A call to 'super()' got replaced with a capturing statement like: + * + * return _super.call(...) || this; + * + * Callers should skip the current statement and avoid any returns of '_this'. + */ SuperCaptureResult[SuperCaptureResult["ReplaceWithReturn"] = 2] = "ReplaceWithReturn"; })(SuperCaptureResult || (SuperCaptureResult = {})); + // Facts we track as we traverse the tree var HierarchyFacts; (function (HierarchyFacts) { HierarchyFacts[HierarchyFacts["None"] = 0] = "None"; + // + // Ancestor facts + // HierarchyFacts[HierarchyFacts["Function"] = 1] = "Function"; HierarchyFacts[HierarchyFacts["ArrowFunction"] = 2] = "ArrowFunction"; HierarchyFacts[HierarchyFacts["AsyncFunctionBody"] = 4] = "AsyncFunctionBody"; @@ -56103,33 +66195,58 @@ var ts; HierarchyFacts[HierarchyFacts["ForInOrForOfStatement"] = 2048] = "ForInOrForOfStatement"; HierarchyFacts[HierarchyFacts["ConstructorWithCapturedSuper"] = 4096] = "ConstructorWithCapturedSuper"; HierarchyFacts[HierarchyFacts["ComputedPropertyName"] = 8192] = "ComputedPropertyName"; + // NOTE: do not add more ancestor flags without also updating AncestorFactsMask below. + // + // Ancestor masks + // HierarchyFacts[HierarchyFacts["AncestorFactsMask"] = 16383] = "AncestorFactsMask"; + // We are always in *some* kind of block scope, but only specific block-scope containers are + // top-level or Blocks. HierarchyFacts[HierarchyFacts["BlockScopeIncludes"] = 0] = "BlockScopeIncludes"; HierarchyFacts[HierarchyFacts["BlockScopeExcludes"] = 4032] = "BlockScopeExcludes"; + // A source file is a top-level block scope. HierarchyFacts[HierarchyFacts["SourceFileIncludes"] = 64] = "SourceFileIncludes"; HierarchyFacts[HierarchyFacts["SourceFileExcludes"] = 3968] = "SourceFileExcludes"; + // Functions, methods, and accessors are both new lexical scopes and new block scopes. HierarchyFacts[HierarchyFacts["FunctionIncludes"] = 65] = "FunctionIncludes"; HierarchyFacts[HierarchyFacts["FunctionExcludes"] = 16286] = "FunctionExcludes"; HierarchyFacts[HierarchyFacts["AsyncFunctionBodyIncludes"] = 69] = "AsyncFunctionBodyIncludes"; HierarchyFacts[HierarchyFacts["AsyncFunctionBodyExcludes"] = 16278] = "AsyncFunctionBodyExcludes"; + // Arrow functions are lexically scoped to their container, but are new block scopes. HierarchyFacts[HierarchyFacts["ArrowFunctionIncludes"] = 66] = "ArrowFunctionIncludes"; HierarchyFacts[HierarchyFacts["ArrowFunctionExcludes"] = 16256] = "ArrowFunctionExcludes"; + // Constructors are both new lexical scopes and new block scopes. Constructors are also + // always considered non-static members of a class. HierarchyFacts[HierarchyFacts["ConstructorIncludes"] = 73] = "ConstructorIncludes"; HierarchyFacts[HierarchyFacts["ConstructorExcludes"] = 16278] = "ConstructorExcludes"; + // 'do' and 'while' statements are not block scopes. We track that the subtree is contained + // within an IterationStatement to indicate whether the embedded statement is an + // IterationStatementBlock. HierarchyFacts[HierarchyFacts["DoOrWhileStatementIncludes"] = 256] = "DoOrWhileStatementIncludes"; HierarchyFacts[HierarchyFacts["DoOrWhileStatementExcludes"] = 0] = "DoOrWhileStatementExcludes"; + // 'for' statements are new block scopes and have special handling for 'let' declarations. HierarchyFacts[HierarchyFacts["ForStatementIncludes"] = 1280] = "ForStatementIncludes"; HierarchyFacts[HierarchyFacts["ForStatementExcludes"] = 3008] = "ForStatementExcludes"; + // 'for-in' and 'for-of' statements are new block scopes and have special handling for + // 'let' declarations. HierarchyFacts[HierarchyFacts["ForInOrForOfStatementIncludes"] = 2304] = "ForInOrForOfStatementIncludes"; HierarchyFacts[HierarchyFacts["ForInOrForOfStatementExcludes"] = 1984] = "ForInOrForOfStatementExcludes"; + // Blocks (other than function bodies) are new block scopes. HierarchyFacts[HierarchyFacts["BlockIncludes"] = 128] = "BlockIncludes"; HierarchyFacts[HierarchyFacts["BlockExcludes"] = 3904] = "BlockExcludes"; HierarchyFacts[HierarchyFacts["IterationStatementBlockIncludes"] = 512] = "IterationStatementBlockIncludes"; HierarchyFacts[HierarchyFacts["IterationStatementBlockExcludes"] = 4032] = "IterationStatementBlockExcludes"; + // Computed property names track subtree flags differently than their containing members. HierarchyFacts[HierarchyFacts["ComputedPropertyNameIncludes"] = 8192] = "ComputedPropertyNameIncludes"; HierarchyFacts[HierarchyFacts["ComputedPropertyNameExcludes"] = 0] = "ComputedPropertyNameExcludes"; + // + // Subtree facts + // HierarchyFacts[HierarchyFacts["NewTarget"] = 16384] = "NewTarget"; HierarchyFacts[HierarchyFacts["NewTargetInComputedPropertyName"] = 32768] = "NewTargetInComputedPropertyName"; + // + // Subtree masks + // HierarchyFacts[HierarchyFacts["SubtreeFactsMask"] = -16384] = "SubtreeFactsMask"; HierarchyFacts[HierarchyFacts["PropagateNewTargetMask"] = 49152] = "PropagateNewTargetMask"; })(HierarchyFacts || (HierarchyFacts = {})); @@ -56148,7 +66265,15 @@ var ts; function recordTaggedTemplateString(temp) { taggedTemplateStringDeclarations = ts.append(taggedTemplateStringDeclarations, ts.createVariableDeclaration(temp)); } + /** + * Used to track if we are emitting body of the converted loop + */ var convertedLoopState; + /** + * Keeps track of whether substitutions have been enabled for specific cases. + * They are persisted between each SourceFile transformation and should not + * be reset. + */ var enabledSubstitutions; return ts.chainBundle(transformSourceFile); function transformSourceFile(node) { @@ -56162,28 +66287,40 @@ var ts; currentSourceFile = undefined; currentText = undefined; taggedTemplateStringDeclarations = undefined; - hierarchyFacts = 0; + hierarchyFacts = 0 /* None */; return visited; } + /** + * Sets the `HierarchyFacts` for this node prior to visiting this node's subtree, returning the facts set prior to modification. + * @param excludeFacts The existing `HierarchyFacts` to reset before visiting the subtree. + * @param includeFacts The new `HierarchyFacts` to set before visiting the subtree. + */ function enterSubtree(excludeFacts, includeFacts) { var ancestorFacts = hierarchyFacts; - hierarchyFacts = (hierarchyFacts & ~excludeFacts | includeFacts) & 16383; + hierarchyFacts = (hierarchyFacts & ~excludeFacts | includeFacts) & 16383 /* AncestorFactsMask */; return ancestorFacts; } + /** + * Restores the `HierarchyFacts` for this node's ancestor after visiting this node's + * subtree, propagating specific facts from the subtree. + * @param ancestorFacts The `HierarchyFacts` of the ancestor to restore after visiting the subtree. + * @param excludeFacts The existing `HierarchyFacts` of the subtree that should not be propagated. + * @param includeFacts The new `HierarchyFacts` of the subtree that should be propagated. + */ function exitSubtree(ancestorFacts, excludeFacts, includeFacts) { - hierarchyFacts = (hierarchyFacts & ~excludeFacts | includeFacts) & -16384 | ancestorFacts; + hierarchyFacts = (hierarchyFacts & ~excludeFacts | includeFacts) & -16384 /* SubtreeFactsMask */ | ancestorFacts; } function isReturnVoidStatementInConstructorWithCapturedSuper(node) { - return (hierarchyFacts & 4096) !== 0 - && node.kind === 225 + return (hierarchyFacts & 4096 /* ConstructorWithCapturedSuper */) !== 0 + && node.kind === 225 /* ReturnStatement */ && !node.expression; } function shouldVisitNode(node) { - return (node.transformFlags & 128) !== 0 + return (node.transformFlags & 128 /* ContainsES2015 */) !== 0 || convertedLoopState !== undefined - || (hierarchyFacts & 4096 && (ts.isStatement(node) || (node.kind === 213))) - || (ts.isIterationStatement(node, false) && shouldConvertIterationStatementBody(node)) - || (ts.getEmitFlags(node) & 33554432) !== 0; + || (hierarchyFacts & 4096 /* ConstructorWithCapturedSuper */ && (ts.isStatement(node) || (node.kind === 213 /* Block */))) + || (ts.isIterationStatement(node, /*lookInLabeledStatements*/ false) && shouldConvertIterationStatementBody(node)) + || (ts.getEmitFlags(node) & 33554432 /* TypeScriptClassWrapper */) !== 0; } function visitor(node) { if (shouldVisitNode(node)) { @@ -56195,133 +66332,134 @@ var ts; } function functionBodyVisitor(node) { if (shouldVisitNode(node)) { - return visitBlock(node, true); + return visitBlock(node, /*isFunctionBody*/ true); } return node; } function callExpressionVisitor(node) { - if (node.kind === 97) { - return visitSuperKeyword(true); + if (node.kind === 97 /* SuperKeyword */) { + return visitSuperKeyword(/*isExpressionOfCall*/ true); } return visitor(node); } function visitJavaScript(node) { switch (node.kind) { - case 115: - return undefined; - case 235: + case 115 /* StaticKeyword */: + return undefined; // elide static keyword + case 235 /* ClassDeclaration */: return visitClassDeclaration(node); - case 205: + case 205 /* ClassExpression */: return visitClassExpression(node); - case 149: + case 149 /* Parameter */: return visitParameter(node); - case 234: + case 234 /* FunctionDeclaration */: return visitFunctionDeclaration(node); - case 193: + case 193 /* ArrowFunction */: return visitArrowFunction(node); - case 192: + case 192 /* FunctionExpression */: return visitFunctionExpression(node); - case 232: + case 232 /* VariableDeclaration */: return visitVariableDeclaration(node); - case 71: + case 71 /* Identifier */: return visitIdentifier(node); - case 233: + case 233 /* VariableDeclarationList */: return visitVariableDeclarationList(node); - case 227: + case 227 /* SwitchStatement */: return visitSwitchStatement(node); - case 241: + case 241 /* CaseBlock */: return visitCaseBlock(node); - case 213: - return visitBlock(node, false); - case 224: - case 223: + case 213 /* Block */: + return visitBlock(node, /*isFunctionBody*/ false); + case 224 /* BreakStatement */: + case 223 /* ContinueStatement */: return visitBreakOrContinueStatement(node); - case 228: + case 228 /* LabeledStatement */: return visitLabeledStatement(node); - case 218: - case 219: - return visitDoOrWhileStatement(node, undefined); - case 220: - return visitForStatement(node, undefined); - case 221: - return visitForInStatement(node, undefined); - case 222: - return visitForOfStatement(node, undefined); - case 216: + case 218 /* DoStatement */: + case 219 /* WhileStatement */: + return visitDoOrWhileStatement(node, /*outermostLabeledStatement*/ undefined); + case 220 /* ForStatement */: + return visitForStatement(node, /*outermostLabeledStatement*/ undefined); + case 221 /* ForInStatement */: + return visitForInStatement(node, /*outermostLabeledStatement*/ undefined); + case 222 /* ForOfStatement */: + return visitForOfStatement(node, /*outermostLabeledStatement*/ undefined); + case 216 /* ExpressionStatement */: return visitExpressionStatement(node); - case 184: + case 184 /* ObjectLiteralExpression */: return visitObjectLiteralExpression(node); - case 269: + case 269 /* CatchClause */: return visitCatchClause(node); - case 271: + case 271 /* ShorthandPropertyAssignment */: return visitShorthandPropertyAssignment(node); - case 147: + case 147 /* ComputedPropertyName */: return visitComputedPropertyName(node); - case 183: + case 183 /* ArrayLiteralExpression */: return visitArrayLiteralExpression(node); - case 187: + case 187 /* CallExpression */: return visitCallExpression(node); - case 188: + case 188 /* NewExpression */: return visitNewExpression(node); - case 191: - return visitParenthesizedExpression(node, true); - case 200: - return visitBinaryExpression(node, true); - case 13: - case 14: - case 15: - case 16: + case 191 /* ParenthesizedExpression */: + return visitParenthesizedExpression(node, /*needsDestructuringValue*/ true); + case 200 /* BinaryExpression */: + return visitBinaryExpression(node, /*needsDestructuringValue*/ true); + case 13 /* NoSubstitutionTemplateLiteral */: + case 14 /* TemplateHead */: + case 15 /* TemplateMiddle */: + case 16 /* TemplateTail */: return visitTemplateLiteral(node); - case 9: + case 9 /* StringLiteral */: return visitStringLiteral(node); - case 8: + case 8 /* NumericLiteral */: return visitNumericLiteral(node); - case 189: + case 189 /* TaggedTemplateExpression */: return visitTaggedTemplateExpression(node); - case 202: + case 202 /* TemplateExpression */: return visitTemplateExpression(node); - case 203: + case 203 /* YieldExpression */: return visitYieldExpression(node); - case 204: + case 204 /* SpreadElement */: return visitSpreadElement(node); - case 97: - return visitSuperKeyword(false); - case 99: + case 97 /* SuperKeyword */: + return visitSuperKeyword(/*isExpressionOfCall*/ false); + case 99 /* ThisKeyword */: return visitThisKeyword(node); - case 210: + case 210 /* MetaProperty */: return visitMetaProperty(node); - case 154: + case 154 /* MethodDeclaration */: return visitMethodDeclaration(node); - case 156: - case 157: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return visitAccessorDeclaration(node); - case 214: + case 214 /* VariableStatement */: return visitVariableStatement(node); - case 225: + case 225 /* ReturnStatement */: return visitReturnStatement(node); default: return ts.visitEachChild(node, visitor, context); } } function visitSourceFile(node) { - var ancestorFacts = enterSubtree(3968, 64); + var ancestorFacts = enterSubtree(3968 /* SourceFileExcludes */, 64 /* SourceFileIncludes */); var statements = []; startLexicalEnvironment(); - var statementOffset = ts.addStandardPrologue(statements, node.statements, false); + var statementOffset = ts.addStandardPrologue(statements, node.statements, /*ensureUseStrict*/ false); addCaptureThisForNodeIfNeeded(statements, node); statementOffset = ts.addCustomPrologue(statements, node.statements, statementOffset, visitor); ts.addRange(statements, ts.visitNodes(node.statements, visitor, ts.isStatement, statementOffset)); if (taggedTemplateStringDeclarations) { - statements.push(ts.createVariableStatement(undefined, ts.createVariableDeclarationList(taggedTemplateStringDeclarations))); + statements.push(ts.createVariableStatement(/*modifiers*/ undefined, ts.createVariableDeclarationList(taggedTemplateStringDeclarations))); } ts.prependStatements(statements, endLexicalEnvironment()); - exitSubtree(ancestorFacts, 0, 0); + exitSubtree(ancestorFacts, 0 /* None */, 0 /* None */); return ts.updateSourceFileNode(node, ts.setTextRange(ts.createNodeArray(statements), node.statements)); } function visitSwitchStatement(node) { if (convertedLoopState !== undefined) { var savedAllowedNonLabeledJumps = convertedLoopState.allowedNonLabeledJumps; - convertedLoopState.allowedNonLabeledJumps |= 2; + // for switch statement allow only non-labeled break + convertedLoopState.allowedNonLabeledJumps |= 2 /* Break */; var result = ts.visitEachChild(node, visitor, context); convertedLoopState.allowedNonLabeledJumps = savedAllowedNonLabeledJumps; return result; @@ -56329,9 +66467,9 @@ var ts; return ts.visitEachChild(node, visitor, context); } function visitCaseBlock(node) { - var ancestorFacts = enterSubtree(4032, 0); + var ancestorFacts = enterSubtree(4032 /* BlockScopeExcludes */, 0 /* BlockScopeIncludes */); var updated = ts.visitEachChild(node, visitor, context); - exitSubtree(ancestorFacts, 0, 0); + exitSubtree(ancestorFacts, 0 /* None */, 0 /* None */); return updated; } function returnCapturedThis(node) { @@ -56339,7 +66477,7 @@ var ts; } function visitReturnStatement(node) { if (convertedLoopState) { - convertedLoopState.nonLocalJumps |= 8; + convertedLoopState.nonLocalJumps |= 8 /* Return */; if (isReturnVoidStatementInConstructorWithCapturedSuper(node)) { node = returnCapturedThis(node); } @@ -56356,7 +66494,8 @@ var ts; } function visitThisKeyword(node) { if (convertedLoopState) { - if (hierarchyFacts & 2) { + if (hierarchyFacts & 2 /* ArrowFunction */) { + // if the enclosing function is an ArrowFunction then we use the captured 'this' keyword. convertedLoopState.containsLexicalThis = true; return node; } @@ -56378,30 +66517,35 @@ var ts; } function visitBreakOrContinueStatement(node) { if (convertedLoopState) { - var jump = node.kind === 224 ? 2 : 4; + // check if we can emit break/continue as is + // it is possible if either + // - break/continue is labeled and label is located inside the converted loop + // - break/continue is non-labeled and located in non-converted loop/switch statement + var jump = node.kind === 224 /* BreakStatement */ ? 2 /* Break */ : 4 /* Continue */; var canUseBreakOrContinue = (node.label && convertedLoopState.labels && convertedLoopState.labels.get(ts.idText(node.label))) || (!node.label && (convertedLoopState.allowedNonLabeledJumps & jump)); if (!canUseBreakOrContinue) { var labelMarker = void 0; var label = node.label; if (!label) { - if (node.kind === 224) { - convertedLoopState.nonLocalJumps |= 2; + if (node.kind === 224 /* BreakStatement */) { + convertedLoopState.nonLocalJumps |= 2 /* Break */; labelMarker = "break"; } else { - convertedLoopState.nonLocalJumps |= 4; + convertedLoopState.nonLocalJumps |= 4 /* Continue */; + // note: return value is emitted only to simplify debugging, call to converted loop body does not do any dispatching on it. labelMarker = "continue"; } } else { - if (node.kind === 224) { + if (node.kind === 224 /* BreakStatement */) { labelMarker = "break-" + label.escapedText; - setLabeledJump(convertedLoopState, true, ts.idText(label), labelMarker); + setLabeledJump(convertedLoopState, /*isBreak*/ true, ts.idText(label), labelMarker); } else { labelMarker = "continue-" + label.escapedText; - setLabeledJump(convertedLoopState, false, ts.idText(label), labelMarker); + setLabeledJump(convertedLoopState, /*isBreak*/ false, ts.idText(label), labelMarker); } } var returnExpression = ts.createLiteral(labelMarker); @@ -56409,167 +66553,305 @@ var ts; var outParams = convertedLoopState.loopOutParameters; var expr = void 0; for (var i = 0; i < outParams.length; i++) { - var copyExpr = copyOutParameter(outParams[i], 1); + var copyExpr = copyOutParameter(outParams[i], 1 /* ToOutParameter */); if (i === 0) { expr = copyExpr; } else { - expr = ts.createBinary(expr, 26, copyExpr); + expr = ts.createBinary(expr, 26 /* CommaToken */, copyExpr); } } - returnExpression = ts.createBinary(expr, 26, returnExpression); + returnExpression = ts.createBinary(expr, 26 /* CommaToken */, returnExpression); } return ts.createReturn(returnExpression); } } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a ClassDeclaration and transforms it into a variable statement. + * + * @param node A ClassDeclaration node. + */ function visitClassDeclaration(node) { - var variable = ts.createVariableDeclaration(ts.getLocalName(node, true), undefined, transformClassLikeDeclarationToExpression(node)); + // [source] + // class C { } + // + // [output] + // var C = (function () { + // function C() { + // } + // return C; + // }()); + var variable = ts.createVariableDeclaration(ts.getLocalName(node, /*allowComments*/ true), + /*type*/ undefined, transformClassLikeDeclarationToExpression(node)); ts.setOriginalNode(variable, node); var statements = []; - var statement = ts.createVariableStatement(undefined, ts.createVariableDeclarationList([variable])); + var statement = ts.createVariableStatement(/*modifiers*/ undefined, ts.createVariableDeclarationList([variable])); ts.setOriginalNode(statement, node); ts.setTextRange(statement, node); ts.startOnNewLine(statement); statements.push(statement); - if (ts.hasModifier(node, 1)) { - var exportStatement = ts.hasModifier(node, 512) + // Add an `export default` statement for default exports (for `--target es5 --module es6`) + if (ts.hasModifier(node, 1 /* Export */)) { + var exportStatement = ts.hasModifier(node, 512 /* Default */) ? ts.createExportDefault(ts.getLocalName(node)) : ts.createExternalModuleExport(ts.getLocalName(node)); ts.setOriginalNode(exportStatement, statement); statements.push(exportStatement); } var emitFlags = ts.getEmitFlags(node); - if ((emitFlags & 4194304) === 0) { + if ((emitFlags & 4194304 /* HasEndOfDeclarationMarker */) === 0) { + // Add a DeclarationMarker as a marker for the end of the declaration statements.push(ts.createEndOfDeclarationMarker(node)); - ts.setEmitFlags(statement, emitFlags | 4194304); + ts.setEmitFlags(statement, emitFlags | 4194304 /* HasEndOfDeclarationMarker */); } return ts.singleOrMany(statements); } + /** + * Visits a ClassExpression and transforms it into an expression. + * + * @param node A ClassExpression node. + */ function visitClassExpression(node) { + // [source] + // C = class { } + // + // [output] + // C = (function () { + // function class_1() { + // } + // return class_1; + // }()) return transformClassLikeDeclarationToExpression(node); } + /** + * Transforms a ClassExpression or ClassDeclaration into an expression. + * + * @param node A ClassExpression or ClassDeclaration node. + */ function transformClassLikeDeclarationToExpression(node) { + // [source] + // class C extends D { + // constructor() {} + // method() {} + // get prop() {} + // set prop(v) {} + // } + // + // [output] + // (function (_super) { + // __extends(C, _super); + // function C() { + // } + // C.prototype.method = function () {} + // Object.defineProperty(C.prototype, "prop", { + // get: function() {}, + // set: function() {}, + // enumerable: true, + // configurable: true + // }); + // return C; + // }(D)) if (node.name) { enableSubstitutionsForBlockScopedBindings(); } var extendsClauseElement = ts.getClassExtendsHeritageClauseElement(node); - var classFunction = ts.createFunctionExpression(undefined, undefined, undefined, undefined, extendsClauseElement ? [ts.createParameter(undefined, undefined, undefined, ts.createFileLevelUniqueName("_super"))] : [], undefined, transformClassBody(node, extendsClauseElement)); - ts.setEmitFlags(classFunction, (ts.getEmitFlags(node) & 65536) | 524288); + var classFunction = ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, extendsClauseElement ? [ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, ts.createFileLevelUniqueName("_super"))] : [], + /*type*/ undefined, transformClassBody(node, extendsClauseElement)); + // To preserve the behavior of the old emitter, we explicitly indent + // the body of the function here if it was requested in an earlier + // transformation. + ts.setEmitFlags(classFunction, (ts.getEmitFlags(node) & 65536 /* Indented */) | 524288 /* ReuseTempVariableScope */); + // "inner" and "outer" below are added purely to preserve source map locations from + // the old emitter var inner = ts.createPartiallyEmittedExpression(classFunction); inner.end = node.end; - ts.setEmitFlags(inner, 1536); + ts.setEmitFlags(inner, 1536 /* NoComments */); var outer = ts.createPartiallyEmittedExpression(inner); outer.end = ts.skipTrivia(currentText, node.pos); - ts.setEmitFlags(outer, 1536); - var result = ts.createParen(ts.createCall(outer, undefined, extendsClauseElement + ts.setEmitFlags(outer, 1536 /* NoComments */); + var result = ts.createParen(ts.createCall(outer, + /*typeArguments*/ undefined, extendsClauseElement ? [ts.visitNode(extendsClauseElement.expression, visitor, ts.isExpression)] : [])); - ts.addSyntheticLeadingComment(result, 3, "* @class "); + ts.addSyntheticLeadingComment(result, 3 /* MultiLineCommentTrivia */, "* @class "); return result; } + /** + * Transforms a ClassExpression or ClassDeclaration into a function body. + * + * @param node A ClassExpression or ClassDeclaration node. + * @param extendsClauseElement The expression for the class `extends` clause. + */ function transformClassBody(node, extendsClauseElement) { var statements = []; startLexicalEnvironment(); addExtendsHelperIfNeeded(statements, node, extendsClauseElement); addConstructor(statements, node, extendsClauseElement); addClassMembers(statements, node); - var closingBraceLocation = ts.createTokenRange(ts.skipTrivia(currentText, node.members.end), 18); + // Create a synthetic text range for the return statement. + var closingBraceLocation = ts.createTokenRange(ts.skipTrivia(currentText, node.members.end), 18 /* CloseBraceToken */); var localName = ts.getInternalName(node); + // The following partially-emitted expression exists purely to align our sourcemap + // emit with the original emitter. var outer = ts.createPartiallyEmittedExpression(localName); outer.end = closingBraceLocation.end; - ts.setEmitFlags(outer, 1536); + ts.setEmitFlags(outer, 1536 /* NoComments */); var statement = ts.createReturn(outer); statement.pos = closingBraceLocation.pos; - ts.setEmitFlags(statement, 1536 | 384); + ts.setEmitFlags(statement, 1536 /* NoComments */ | 384 /* NoTokenSourceMaps */); statements.push(statement); ts.prependStatements(statements, endLexicalEnvironment()); - var block = ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), node.members), true); - ts.setEmitFlags(block, 1536); + var block = ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), /*location*/ node.members), /*multiLine*/ true); + ts.setEmitFlags(block, 1536 /* NoComments */); return block; } + /** + * Adds a call to the `__extends` helper if needed for a class. + * + * @param statements The statements of the class body function. + * @param node The ClassExpression or ClassDeclaration node. + * @param extendsClauseElement The expression for the class `extends` clause. + */ function addExtendsHelperIfNeeded(statements, node, extendsClauseElement) { if (extendsClauseElement) { - statements.push(ts.setTextRange(ts.createStatement(createExtendsHelper(context, ts.getInternalName(node))), extendsClauseElement)); + statements.push(ts.setTextRange(ts.createStatement(createExtendsHelper(context, ts.getInternalName(node))), + /*location*/ extendsClauseElement)); } } + /** + * Adds the constructor of the class to a class body function. + * + * @param statements The statements of the class body function. + * @param node The ClassExpression or ClassDeclaration node. + * @param extendsClauseElement The expression for the class `extends` clause. + */ function addConstructor(statements, node, extendsClauseElement) { var savedConvertedLoopState = convertedLoopState; convertedLoopState = undefined; - var ancestorFacts = enterSubtree(16278, 73); + var ancestorFacts = enterSubtree(16278 /* ConstructorExcludes */, 73 /* ConstructorIncludes */); var constructor = ts.getFirstConstructorWithBody(node); var hasSynthesizedSuper = hasSynthesizedDefaultSuperCall(constructor, extendsClauseElement !== undefined); - var constructorFunction = ts.createFunctionDeclaration(undefined, undefined, undefined, ts.getInternalName(node), undefined, transformConstructorParameters(constructor, hasSynthesizedSuper), undefined, transformConstructorBody(constructor, node, extendsClauseElement, hasSynthesizedSuper)); + var constructorFunction = ts.createFunctionDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, ts.getInternalName(node), + /*typeParameters*/ undefined, transformConstructorParameters(constructor, hasSynthesizedSuper), + /*type*/ undefined, transformConstructorBody(constructor, node, extendsClauseElement, hasSynthesizedSuper)); ts.setTextRange(constructorFunction, constructor || node); if (extendsClauseElement) { - ts.setEmitFlags(constructorFunction, 8); + ts.setEmitFlags(constructorFunction, 8 /* CapturesThis */); } statements.push(constructorFunction); - exitSubtree(ancestorFacts, 49152, 0); + exitSubtree(ancestorFacts, 49152 /* PropagateNewTargetMask */, 0 /* None */); convertedLoopState = savedConvertedLoopState; } + /** + * Transforms the parameters of the constructor declaration of a class. + * + * @param constructor The constructor for the class. + * @param hasSynthesizedSuper A value indicating whether the constructor starts with a + * synthesized `super` call. + */ function transformConstructorParameters(constructor, hasSynthesizedSuper) { + // If the TypeScript transformer needed to synthesize a constructor for property + // initializers, it would have also added a synthetic `...args` parameter and + // `super` call. + // If this is the case, we do not include the synthetic `...args` parameter and + // will instead use the `arguments` object in ES5/3. return ts.visitParameterList(constructor && !hasSynthesizedSuper ? constructor.parameters : undefined, visitor, context) || []; } + /** + * Transforms the body of a constructor declaration of a class. + * + * @param constructor The constructor for the class. + * @param node The node which contains the constructor. + * @param extendsClauseElement The expression for the class `extends` clause. + * @param hasSynthesizedSuper A value indicating whether the constructor starts with a + * synthesized `super` call. + */ function transformConstructorBody(constructor, node, extendsClauseElement, hasSynthesizedSuper) { var statements = []; resumeLexicalEnvironment(); var statementOffset = -1; if (hasSynthesizedSuper) { + // If a super call has already been synthesized, + // we're going to assume that we should just transform everything after that. + // The assumption is that no prior step in the pipeline has added any prologue directives. statementOffset = 0; } else if (constructor) { - statementOffset = ts.addStandardPrologue(statements, constructor.body.statements, false); + statementOffset = ts.addStandardPrologue(statements, constructor.body.statements, /*ensureUseStrict*/ false); } if (constructor) { addDefaultValueAssignmentsIfNeeded(statements, constructor); addRestParameterIfNeeded(statements, constructor, hasSynthesizedSuper); if (!hasSynthesizedSuper) { + // If no super call has been synthesized, emit custom prologue directives. statementOffset = ts.addCustomPrologue(statements, constructor.body.statements, statementOffset, visitor); } ts.Debug.assert(statementOffset >= 0, "statementOffset not initialized correctly!"); } - var isDerivedClass = !!extendsClauseElement && ts.skipOuterExpressions(extendsClauseElement.expression).kind !== 95; + // determine whether the class is known syntactically to be a derived class (e.g. a + // class that extends a value that is not syntactically known to be `null`). + var isDerivedClass = !!extendsClauseElement && ts.skipOuterExpressions(extendsClauseElement.expression).kind !== 95 /* NullKeyword */; var superCaptureStatus = declareOrCaptureOrReturnThisForConstructorIfNeeded(statements, constructor, isDerivedClass, hasSynthesizedSuper, statementOffset); - if (superCaptureStatus === 1 || superCaptureStatus === 2) { + // The last statement expression was replaced. Skip it. + if (superCaptureStatus === 1 /* ReplaceSuperCapture */ || superCaptureStatus === 2 /* ReplaceWithReturn */) { statementOffset++; } if (constructor) { - if (superCaptureStatus === 1) { - hierarchyFacts |= 4096; + if (superCaptureStatus === 1 /* ReplaceSuperCapture */) { + hierarchyFacts |= 4096 /* ConstructorWithCapturedSuper */; } - ts.addRange(statements, ts.visitNodes(constructor.body.statements, visitor, ts.isStatement, statementOffset)); + ts.addRange(statements, ts.visitNodes(constructor.body.statements, visitor, ts.isStatement, /*start*/ statementOffset)); } + // Return `_this` unless we're sure enough that it would be pointless to add a return statement. + // If there's a constructor that we can tell returns in enough places, then we *do not* want to add a return. if (isDerivedClass - && superCaptureStatus !== 2 + && superCaptureStatus !== 2 /* ReplaceWithReturn */ && !(constructor && isSufficientlyCoveredByReturnStatements(constructor.body))) { statements.push(ts.createReturn(ts.createFileLevelUniqueName("_this"))); } ts.prependStatements(statements, endLexicalEnvironment()); if (constructor) { - prependCaptureNewTargetIfNeeded(statements, constructor, false); + prependCaptureNewTargetIfNeeded(statements, constructor, /*copyOnWrite*/ false); } - var block = ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), constructor ? constructor.body.statements : node.members), true); + var block = ts.createBlock(ts.setTextRange(ts.createNodeArray(statements), + /*location*/ constructor ? constructor.body.statements : node.members), + /*multiLine*/ true); ts.setTextRange(block, constructor ? constructor.body : node); if (!constructor) { - ts.setEmitFlags(block, 1536); + ts.setEmitFlags(block, 1536 /* NoComments */); } return block; } + /** + * We want to try to avoid emitting a return statement in certain cases if a user already returned something. + * It would generate obviously dead code, so we'll try to make things a little bit prettier + * by doing a minimal check on whether some common patterns always explicitly return. + */ function isSufficientlyCoveredByReturnStatements(statement) { - if (statement.kind === 225) { + // A return statement is considered covered. + if (statement.kind === 225 /* ReturnStatement */) { return true; } - else if (statement.kind === 217) { + // An if-statement with two covered branches is covered. + else if (statement.kind === 217 /* IfStatement */) { var ifStatement = statement; if (ifStatement.elseStatement) { return isSufficientlyCoveredByReturnStatements(ifStatement.thenStatement) && isSufficientlyCoveredByReturnStatements(ifStatement.elseStatement); } } - else if (statement.kind === 213) { + // A block is covered if it has a last statement which is covered. + else if (statement.kind === 213 /* Block */) { var lastStatement = ts.lastOrUndefined(statement.statements); if (lastStatement && isSufficientlyCoveredByReturnStatements(lastStatement)) { return true; @@ -56577,72 +66859,144 @@ var ts; } return false; } + /** + * Declares a `_this` variable for derived classes and for when arrow functions capture `this`. + * + * @returns The new statement offset into the `statements` array. + */ function declareOrCaptureOrReturnThisForConstructorIfNeeded(statements, ctor, isDerivedClass, hasSynthesizedSuper, statementOffset) { + // If this isn't a derived class, just capture 'this' for arrow functions if necessary. if (!isDerivedClass) { if (ctor) { addCaptureThisForNodeIfNeeded(statements, ctor); } - return 0; + return 0 /* NoReplacement */; } + // We must be here because the user didn't write a constructor + // but we needed to call 'super(...args)' anyway as per 14.5.14 of the ES2016 spec. + // If that's the case we can just immediately return the result of a 'super()' call. if (!ctor) { statements.push(ts.createReturn(createDefaultSuperCallOrThis())); - return 2; + return 2 /* ReplaceWithReturn */; } + // The constructor exists, but it and the 'super()' call it contains were generated + // for something like property initializers. + // Create a captured '_this' variable and assume it will subsequently be used. if (hasSynthesizedSuper) { captureThisForNode(statements, ctor, createDefaultSuperCallOrThis()); enableSubstitutionsForCapturedThis(); - return 1; + return 1 /* ReplaceSuperCapture */; } + // Most of the time, a 'super' call will be the first real statement in a constructor body. + // In these cases, we'd like to transform these into a *single* statement instead of a declaration + // followed by an assignment statement for '_this'. For instance, if we emitted without an initializer, + // we'd get: + // + // var _this; + // _this = _super.call(...) || this; + // + // instead of + // + // var _this = _super.call(...) || this; + // + // Additionally, if the 'super()' call is the last statement, we should just avoid capturing + // entirely and immediately return the result like so: + // + // return _super.call(...) || this; + // var firstStatement; var superCallExpression; var ctorStatements = ctor.body.statements; if (statementOffset < ctorStatements.length) { firstStatement = ctorStatements[statementOffset]; - if (firstStatement.kind === 216 && ts.isSuperCall(firstStatement.expression)) { + if (firstStatement.kind === 216 /* ExpressionStatement */ && ts.isSuperCall(firstStatement.expression)) { superCallExpression = visitImmediateSuperCallInBody(firstStatement.expression); } } + // Return the result if we have an immediate super() call on the last statement, + // but only if the constructor itself doesn't use 'this' elsewhere. if (superCallExpression && statementOffset === ctorStatements.length - 1 - && !(ctor.transformFlags & (16384 | 32768))) { + && !(ctor.transformFlags & (16384 /* ContainsLexicalThis */ | 32768 /* ContainsCapturedLexicalThis */))) { var returnStatement = ts.createReturn(superCallExpression); - if (superCallExpression.kind !== 200 - || superCallExpression.left.kind !== 187) { + if (superCallExpression.kind !== 200 /* BinaryExpression */ + || superCallExpression.left.kind !== 187 /* CallExpression */) { ts.Debug.fail("Assumed generated super call would have form 'super.call(...) || this'."); } - ts.setCommentRange(returnStatement, ts.getCommentRange(ts.setEmitFlags(superCallExpression.left, 1536))); + // Shift comments from the original super call to the return statement. + ts.setCommentRange(returnStatement, ts.getCommentRange(ts.setEmitFlags(superCallExpression.left, 1536 /* NoComments */))); statements.push(returnStatement); - return 2; + return 2 /* ReplaceWithReturn */; } + // Perform the capture. captureThisForNode(statements, ctor, superCallExpression || createActualThis(), firstStatement); + // If we're actually replacing the original statement, we need to signal this to the caller. if (superCallExpression) { - return 1; + return 1 /* ReplaceSuperCapture */; } - return 0; + return 0 /* NoReplacement */; } function createActualThis() { - return ts.setEmitFlags(ts.createThis(), 4); + return ts.setEmitFlags(ts.createThis(), 4 /* NoSubstitution */); } function createDefaultSuperCallOrThis() { return ts.createLogicalOr(ts.createLogicalAnd(ts.createStrictInequality(ts.createFileLevelUniqueName("_super"), ts.createNull()), ts.createFunctionApply(ts.createFileLevelUniqueName("_super"), createActualThis(), ts.createIdentifier("arguments"))), createActualThis()); } + /** + * Visits a parameter declaration. + * + * @param node A ParameterDeclaration node. + */ function visitParameter(node) { if (node.dotDotDotToken) { + // rest parameters are elided return undefined; } else if (ts.isBindingPattern(node.name)) { - return ts.setOriginalNode(ts.setTextRange(ts.createParameter(undefined, undefined, undefined, ts.getGeneratedNameForNode(node), undefined, undefined, undefined), node), node); + // Binding patterns are converted into a generated name and are + // evaluated inside the function body. + return ts.setOriginalNode(ts.setTextRange(ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, ts.getGeneratedNameForNode(node), + /*questionToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined), + /*location*/ node), + /*original*/ node); } else if (node.initializer) { - return ts.setOriginalNode(ts.setTextRange(ts.createParameter(undefined, undefined, undefined, node.name, undefined, undefined, undefined), node), node); + // Initializers are elided + return ts.setOriginalNode(ts.setTextRange(ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, node.name, + /*questionToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined), + /*location*/ node), + /*original*/ node); } else { return node; } } + /** + * Gets a value indicating whether we need to add default value assignments for a + * function-like node. + * + * @param node A function-like node. + */ function shouldAddDefaultValueAssignments(node) { - return (node.transformFlags & 131072) !== 0; + return (node.transformFlags & 131072 /* ContainsDefaultValueAssignments */) !== 0; } + /** + * Adds statements to the body of a function-like node if it contains parameters with + * binding patterns or initializers. + * + * @param statements The statements for the new function body. + * @param node A function-like node. + */ function addDefaultValueAssignmentsIfNeeded(statements, node) { if (!shouldAddDefaultValueAssignments(node)) { return; @@ -56650,6 +67004,8 @@ var ts; for (var _i = 0, _a = node.parameters; _i < _a.length; _i++) { var parameter = _a[_i]; var name = parameter.name, initializer = parameter.initializer, dotDotDotToken = parameter.dotDotDotToken; + // A rest parameter cannot have a binding pattern or an initializer, + // so let's just ignore it. if (dotDotDotToken) { continue; } @@ -56661,90 +67017,153 @@ var ts; } } } + /** + * Adds statements to the body of a function-like node for parameters with binding patterns + * + * @param statements The statements for the new function body. + * @param parameter The parameter for the function. + * @param name The name of the parameter. + * @param initializer The initializer for the parameter. + */ function addDefaultValueAssignmentForBindingPattern(statements, parameter, name, initializer) { var temp = ts.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. if (name.elements.length > 0) { - statements.push(ts.setEmitFlags(ts.createVariableStatement(undefined, ts.createVariableDeclarationList(ts.flattenDestructuringBinding(parameter, visitor, context, 0, temp))), 1048576)); + statements.push(ts.setEmitFlags(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList(ts.flattenDestructuringBinding(parameter, visitor, context, 0 /* All */, temp))), 1048576 /* CustomPrologue */)); } else if (initializer) { - statements.push(ts.setEmitFlags(ts.createStatement(ts.createAssignment(temp, ts.visitNode(initializer, visitor, ts.isExpression))), 1048576)); + statements.push(ts.setEmitFlags(ts.createStatement(ts.createAssignment(temp, ts.visitNode(initializer, visitor, ts.isExpression))), 1048576 /* CustomPrologue */)); } } + /** + * Adds statements to the body of a function-like node for parameters with initializers. + * + * @param statements The statements for the new function body. + * @param parameter The parameter for the function. + * @param name The name of the parameter. + * @param initializer The initializer for the parameter. + */ function addDefaultValueAssignmentForInitializer(statements, parameter, name, initializer) { initializer = ts.visitNode(initializer, visitor, ts.isExpression); var statement = ts.createIf(ts.createTypeCheck(ts.getSynthesizedClone(name), "undefined"), ts.setEmitFlags(ts.setTextRange(ts.createBlock([ - ts.createStatement(ts.setEmitFlags(ts.setTextRange(ts.createAssignment(ts.setEmitFlags(ts.getMutableClone(name), 48), ts.setEmitFlags(initializer, 48 | ts.getEmitFlags(initializer) | 1536)), parameter), 1536)) - ]), parameter), 1 | 32 | 384 | 1536)); + ts.createStatement(ts.setEmitFlags(ts.setTextRange(ts.createAssignment(ts.setEmitFlags(ts.getMutableClone(name), 48 /* NoSourceMap */), ts.setEmitFlags(initializer, 48 /* NoSourceMap */ | ts.getEmitFlags(initializer) | 1536 /* NoComments */)), parameter), 1536 /* NoComments */)) + ]), parameter), 1 /* SingleLine */ | 32 /* NoTrailingSourceMap */ | 384 /* NoTokenSourceMaps */ | 1536 /* NoComments */)); ts.startOnNewLine(statement); ts.setTextRange(statement, parameter); - ts.setEmitFlags(statement, 384 | 32 | 1048576 | 1536); + ts.setEmitFlags(statement, 384 /* NoTokenSourceMaps */ | 32 /* NoTrailingSourceMap */ | 1048576 /* CustomPrologue */ | 1536 /* NoComments */); statements.push(statement); } + /** + * Gets a value indicating whether we need to add statements to handle a rest parameter. + * + * @param node A ParameterDeclaration node. + * @param inConstructorWithSynthesizedSuper A value indicating whether the parameter is + * part of a constructor declaration with a + * synthesized call to `super` + */ function shouldAddRestParameter(node, inConstructorWithSynthesizedSuper) { - return node && node.dotDotDotToken && node.name.kind === 71 && !inConstructorWithSynthesizedSuper; + return node && node.dotDotDotToken && node.name.kind === 71 /* Identifier */ && !inConstructorWithSynthesizedSuper; } + /** + * Adds statements to the body of a function-like node if it contains a rest parameter. + * + * @param statements The statements for the new function body. + * @param node A function-like node. + * @param inConstructorWithSynthesizedSuper A value indicating whether the parameter is + * part of a constructor declaration with a + * synthesized call to `super` + */ function addRestParameterIfNeeded(statements, node, inConstructorWithSynthesizedSuper) { var parameter = ts.lastOrUndefined(node.parameters); if (!shouldAddRestParameter(parameter, inConstructorWithSynthesizedSuper)) { return; } + // `declarationName` is the name of the local declaration for the parameter. var declarationName = ts.getMutableClone(parameter.name); - ts.setEmitFlags(declarationName, 48); + ts.setEmitFlags(declarationName, 48 /* NoSourceMap */); + // `expressionName` is the name of the parameter used in expressions. var expressionName = ts.getSynthesizedClone(parameter.name); var restIndex = node.parameters.length - 1; var temp = ts.createLoopVariable(); - statements.push(ts.setEmitFlags(ts.setTextRange(ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.createVariableDeclaration(declarationName, undefined, ts.createArrayLiteral([])) - ])), parameter), 1048576)); + // var param = []; + statements.push(ts.setEmitFlags(ts.setTextRange(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(declarationName, + /*type*/ undefined, ts.createArrayLiteral([])) + ])), + /*location*/ parameter), 1048576 /* CustomPrologue */)); + // for (var _i = restIndex; _i < arguments.length; _i++) { + // param[_i - restIndex] = arguments[_i]; + // } var forStatement = ts.createFor(ts.setTextRange(ts.createVariableDeclarationList([ - ts.createVariableDeclaration(temp, undefined, ts.createLiteral(restIndex)) + ts.createVariableDeclaration(temp, /*type*/ undefined, ts.createLiteral(restIndex)) ]), parameter), ts.setTextRange(ts.createLessThan(temp, ts.createPropertyAccess(ts.createIdentifier("arguments"), "length")), parameter), ts.setTextRange(ts.createPostfixIncrement(temp), parameter), ts.createBlock([ ts.startOnNewLine(ts.setTextRange(ts.createStatement(ts.createAssignment(ts.createElementAccess(expressionName, restIndex === 0 ? temp - : ts.createSubtract(temp, ts.createLiteral(restIndex))), ts.createElementAccess(ts.createIdentifier("arguments"), temp))), parameter)) + : ts.createSubtract(temp, ts.createLiteral(restIndex))), ts.createElementAccess(ts.createIdentifier("arguments"), temp))), + /*location*/ parameter)) ])); - ts.setEmitFlags(forStatement, 1048576); + ts.setEmitFlags(forStatement, 1048576 /* CustomPrologue */); ts.startOnNewLine(forStatement); statements.push(forStatement); } + /** + * Adds a statement to capture the `this` of a function declaration if it is needed. + * + * @param statements The statements for the new function body. + * @param node A node. + */ function addCaptureThisForNodeIfNeeded(statements, node) { - if (node.transformFlags & 32768 && node.kind !== 193) { + if (node.transformFlags & 32768 /* ContainsCapturedLexicalThis */ && node.kind !== 193 /* ArrowFunction */) { captureThisForNode(statements, node, ts.createThis()); } } function captureThisForNode(statements, node, initializer, originalStatement) { enableSubstitutionsForCapturedThis(); - var captureThisStatement = ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.createVariableDeclaration(ts.createFileLevelUniqueName("_this"), undefined, initializer) + var captureThisStatement = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(ts.createFileLevelUniqueName("_this"), + /*type*/ undefined, initializer) ])); - ts.setEmitFlags(captureThisStatement, 1536 | 1048576); + ts.setEmitFlags(captureThisStatement, 1536 /* NoComments */ | 1048576 /* CustomPrologue */); ts.setTextRange(captureThisStatement, originalStatement); ts.setSourceMapRange(captureThisStatement, node); statements.push(captureThisStatement); } function prependCaptureNewTargetIfNeeded(statements, node, copyOnWrite) { - if (hierarchyFacts & 16384) { + if (hierarchyFacts & 16384 /* NewTarget */) { var newTarget = void 0; switch (node.kind) { - case 193: + case 193 /* ArrowFunction */: return statements; - case 154: - case 156: - case 157: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + // Methods and accessors cannot be constructors, so 'new.target' will + // always return 'undefined'. newTarget = ts.createVoidZero(); break; - case 155: - newTarget = ts.createPropertyAccess(ts.setEmitFlags(ts.createThis(), 4), "constructor"); + case 155 /* Constructor */: + // Class constructors can only be called with `new`, so `this.constructor` + // should be relatively safe to use. + newTarget = ts.createPropertyAccess(ts.setEmitFlags(ts.createThis(), 4 /* NoSubstitution */), "constructor"); break; - case 234: - case 192: - newTarget = ts.createConditional(ts.createLogicalAnd(ts.setEmitFlags(ts.createThis(), 4), ts.createBinary(ts.setEmitFlags(ts.createThis(), 4), 93, ts.getLocalName(node))), ts.createPropertyAccess(ts.setEmitFlags(ts.createThis(), 4), "constructor"), ts.createVoidZero()); + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + // Functions can be called or constructed, and may have a `this` due to + // being a member or when calling an imported function via `other_1.f()`. + newTarget = ts.createConditional(ts.createLogicalAnd(ts.setEmitFlags(ts.createThis(), 4 /* NoSubstitution */), ts.createBinary(ts.setEmitFlags(ts.createThis(), 4 /* NoSubstitution */), 93 /* InstanceOfKeyword */, ts.getLocalName(node))), ts.createPropertyAccess(ts.setEmitFlags(ts.createThis(), 4 /* NoSubstitution */), "constructor"), ts.createVoidZero()); break; default: return ts.Debug.failBadSyntaxKind(node); } - var captureNewTargetStatement = ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.createVariableDeclaration(ts.createFileLevelUniqueName("_newTarget"), undefined, newTarget) + var captureNewTargetStatement = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(ts.createFileLevelUniqueName("_newTarget"), + /*type*/ undefined, newTarget) ])); if (copyOnWrite) { return [captureNewTargetStatement].concat(statements); @@ -56753,24 +67172,32 @@ var ts; } return statements; } + /** + * Adds statements to the class body function for a class to define the members of the + * class. + * + * @param statements The statements for the class body function. + * @param node The ClassExpression or ClassDeclaration node. + */ function addClassMembers(statements, node) { for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var member = _a[_i]; switch (member.kind) { - case 212: + case 212 /* SemicolonClassElement */: statements.push(transformSemicolonClassElementToStatement(member)); break; - case 154: + case 154 /* MethodDeclaration */: statements.push(transformClassMethodDeclarationToStatement(getClassMemberPrefix(node, member), member, node)); break; - case 156: - case 157: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: var accessors = ts.getAllAccessorDeclarations(node.members, member); if (member === accessors.firstAccessor) { statements.push(transformAccessorsToStatement(getClassMemberPrefix(node, member), accessors, node)); } break; - case 155: + case 155 /* Constructor */: + // Constructors are handled in visitClassExpression/visitClassDeclaration break; default: ts.Debug.failBadSyntaxKind(node); @@ -56778,133 +67205,208 @@ var ts; } } } + /** + * Transforms a SemicolonClassElement into a statement for a class body function. + * + * @param member The SemicolonClassElement node. + */ function transformSemicolonClassElementToStatement(member) { return ts.setTextRange(ts.createEmptyStatement(), member); } + /** + * Transforms a MethodDeclaration into a statement for a class body function. + * + * @param receiver The receiver for the member. + * @param member The MethodDeclaration node. + */ function transformClassMethodDeclarationToStatement(receiver, member, container) { - var ancestorFacts = enterSubtree(0, 0); + var ancestorFacts = enterSubtree(0 /* None */, 0 /* None */); var commentRange = ts.getCommentRange(member); var sourceMapRange = ts.getSourceMapRange(member); - var memberName = ts.createMemberAccessForPropertyName(receiver, ts.visitNode(member.name, visitor, ts.isPropertyName), member.name); - var memberFunction = transformFunctionLikeToExpression(member, member, undefined, container); - ts.setEmitFlags(memberFunction, 1536); + var memberName = ts.createMemberAccessForPropertyName(receiver, ts.visitNode(member.name, visitor, ts.isPropertyName), /*location*/ member.name); + var memberFunction = transformFunctionLikeToExpression(member, /*location*/ member, /*name*/ undefined, container); + ts.setEmitFlags(memberFunction, 1536 /* NoComments */); ts.setSourceMapRange(memberFunction, sourceMapRange); - var statement = ts.setTextRange(ts.createStatement(ts.createAssignment(memberName, memberFunction)), member); + var statement = ts.setTextRange(ts.createStatement(ts.createAssignment(memberName, memberFunction)), + /*location*/ member); ts.setOriginalNode(statement, member); ts.setCommentRange(statement, commentRange); - ts.setEmitFlags(statement, 48); - exitSubtree(ancestorFacts, 49152, hierarchyFacts & 49152 ? 16384 : 0); + // The location for the statement is used to emit comments only. + // No source map should be emitted for this statement to align with the + // old emitter. + ts.setEmitFlags(statement, 48 /* NoSourceMap */); + exitSubtree(ancestorFacts, 49152 /* PropagateNewTargetMask */, hierarchyFacts & 49152 /* PropagateNewTargetMask */ ? 16384 /* NewTarget */ : 0 /* None */); return statement; } + /** + * Transforms a set of related of get/set accessors into a statement for a class body function. + * + * @param receiver The receiver for the member. + * @param accessors The set of related get/set accessors. + */ function transformAccessorsToStatement(receiver, accessors, container) { - var statement = ts.createStatement(transformAccessorsToExpression(receiver, accessors, container, false)); - ts.setEmitFlags(statement, 1536); + var statement = ts.createStatement(transformAccessorsToExpression(receiver, accessors, container, /*startsOnNewLine*/ false)); + // The location for the statement is used to emit source maps only. + // No comments should be emitted for this statement to align with the + // old emitter. + ts.setEmitFlags(statement, 1536 /* NoComments */); ts.setSourceMapRange(statement, ts.getSourceMapRange(accessors.firstAccessor)); return statement; } + /** + * Transforms a set of related get/set accessors into an expression for either a class + * body function or an ObjectLiteralExpression with computed properties. + * + * @param receiver The receiver for the member. + */ function transformAccessorsToExpression(receiver, _a, container, startsOnNewLine) { var firstAccessor = _a.firstAccessor, getAccessor = _a.getAccessor, setAccessor = _a.setAccessor; - var ancestorFacts = enterSubtree(0, 0); + var ancestorFacts = enterSubtree(0 /* None */, 0 /* None */); + // To align with source maps in the old emitter, the receiver and property name + // arguments are both mapped contiguously to the accessor name. var target = ts.getMutableClone(receiver); - ts.setEmitFlags(target, 1536 | 32); - ts.setSourceMapRange(target, firstAccessor.name); + ts.setEmitFlags(target, 1536 /* NoComments */ | 32 /* NoTrailingSourceMap */); + ts.setSourceMapRange(target, firstAccessor.name); // TODO: GH#18217 var propertyName = ts.createExpressionForPropertyName(ts.visitNode(firstAccessor.name, visitor, ts.isPropertyName)); - ts.setEmitFlags(propertyName, 1536 | 16); + ts.setEmitFlags(propertyName, 1536 /* NoComments */ | 16 /* NoLeadingSourceMap */); ts.setSourceMapRange(propertyName, firstAccessor.name); var properties = []; if (getAccessor) { - var getterFunction = transformFunctionLikeToExpression(getAccessor, undefined, undefined, container); + var getterFunction = transformFunctionLikeToExpression(getAccessor, /*location*/ undefined, /*name*/ undefined, container); ts.setSourceMapRange(getterFunction, ts.getSourceMapRange(getAccessor)); - ts.setEmitFlags(getterFunction, 512); + ts.setEmitFlags(getterFunction, 512 /* NoLeadingComments */); var getter = ts.createPropertyAssignment("get", getterFunction); ts.setCommentRange(getter, ts.getCommentRange(getAccessor)); properties.push(getter); } if (setAccessor) { - var setterFunction = transformFunctionLikeToExpression(setAccessor, undefined, undefined, container); + var setterFunction = transformFunctionLikeToExpression(setAccessor, /*location*/ undefined, /*name*/ undefined, container); ts.setSourceMapRange(setterFunction, ts.getSourceMapRange(setAccessor)); - ts.setEmitFlags(setterFunction, 512); + ts.setEmitFlags(setterFunction, 512 /* NoLeadingComments */); var setter = ts.createPropertyAssignment("set", setterFunction); ts.setCommentRange(setter, ts.getCommentRange(setAccessor)); properties.push(setter); } properties.push(ts.createPropertyAssignment("enumerable", ts.createTrue()), ts.createPropertyAssignment("configurable", ts.createTrue())); - var call = ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Object"), "defineProperty"), undefined, [ + var call = ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Object"), "defineProperty"), + /*typeArguments*/ undefined, [ target, propertyName, - ts.createObjectLiteral(properties, true) + ts.createObjectLiteral(properties, /*multiLine*/ true) ]); if (startsOnNewLine) { ts.startOnNewLine(call); } - exitSubtree(ancestorFacts, 49152, hierarchyFacts & 49152 ? 16384 : 0); + exitSubtree(ancestorFacts, 49152 /* PropagateNewTargetMask */, hierarchyFacts & 49152 /* PropagateNewTargetMask */ ? 16384 /* NewTarget */ : 0 /* None */); return call; } + /** + * Visits an ArrowFunction and transforms it into a FunctionExpression. + * + * @param node An ArrowFunction node. + */ function visitArrowFunction(node) { - if (node.transformFlags & 16384) { + if (node.transformFlags & 16384 /* ContainsLexicalThis */) { enableSubstitutionsForCapturedThis(); } var savedConvertedLoopState = convertedLoopState; convertedLoopState = undefined; - var ancestorFacts = enterSubtree(16256, 66); - var func = ts.createFunctionExpression(undefined, undefined, undefined, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, transformFunctionBody(node)); + var ancestorFacts = enterSubtree(16256 /* ArrowFunctionExcludes */, 66 /* ArrowFunctionIncludes */); + var func = ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, transformFunctionBody(node)); ts.setTextRange(func, node); ts.setOriginalNode(func, node); - ts.setEmitFlags(func, 8); - exitSubtree(ancestorFacts, 0, 0); + ts.setEmitFlags(func, 8 /* CapturesThis */); + exitSubtree(ancestorFacts, 0 /* None */, 0 /* None */); convertedLoopState = savedConvertedLoopState; return func; } + /** + * Visits a FunctionExpression node. + * + * @param node a FunctionExpression node. + */ function visitFunctionExpression(node) { - var ancestorFacts = ts.getEmitFlags(node) & 262144 - ? enterSubtree(16278, 69) - : enterSubtree(16286, 65); + var ancestorFacts = ts.getEmitFlags(node) & 262144 /* AsyncFunctionBody */ + ? enterSubtree(16278 /* AsyncFunctionBodyExcludes */, 69 /* AsyncFunctionBodyIncludes */) + : enterSubtree(16286 /* FunctionExcludes */, 65 /* FunctionIncludes */); var savedConvertedLoopState = convertedLoopState; convertedLoopState = undefined; var parameters = ts.visitParameterList(node.parameters, visitor, context); - var body = node.transformFlags & 64 + var body = node.transformFlags & 64 /* ES2015 */ ? transformFunctionBody(node) : visitFunctionBodyDownLevel(node); - var name = hierarchyFacts & 16384 + var name = hierarchyFacts & 16384 /* NewTarget */ ? ts.getLocalName(node) : node.name; - exitSubtree(ancestorFacts, 49152, 0); + exitSubtree(ancestorFacts, 49152 /* PropagateNewTargetMask */, 0 /* None */); convertedLoopState = savedConvertedLoopState; - return ts.updateFunctionExpression(node, undefined, node.asteriskToken, name, undefined, parameters, undefined, body); + return ts.updateFunctionExpression(node, + /*modifiers*/ undefined, node.asteriskToken, name, + /*typeParameters*/ undefined, parameters, + /*type*/ undefined, body); } + /** + * Visits a FunctionDeclaration node. + * + * @param node a FunctionDeclaration node. + */ function visitFunctionDeclaration(node) { var savedConvertedLoopState = convertedLoopState; convertedLoopState = undefined; - var ancestorFacts = enterSubtree(16286, 65); + var ancestorFacts = enterSubtree(16286 /* FunctionExcludes */, 65 /* FunctionIncludes */); var parameters = ts.visitParameterList(node.parameters, visitor, context); - var body = node.transformFlags & 64 + var body = node.transformFlags & 64 /* ES2015 */ ? transformFunctionBody(node) : visitFunctionBodyDownLevel(node); - var name = hierarchyFacts & 16384 + var name = hierarchyFacts & 16384 /* NewTarget */ ? ts.getLocalName(node) : node.name; - exitSubtree(ancestorFacts, 49152, 0); + exitSubtree(ancestorFacts, 49152 /* PropagateNewTargetMask */, 0 /* None */); convertedLoopState = savedConvertedLoopState; - return ts.updateFunctionDeclaration(node, undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), node.asteriskToken, name, undefined, parameters, undefined, body); + return ts.updateFunctionDeclaration(node, + /*decorators*/ undefined, ts.visitNodes(node.modifiers, visitor, ts.isModifier), node.asteriskToken, name, + /*typeParameters*/ undefined, parameters, + /*type*/ undefined, body); } + /** + * Transforms a function-like node into a FunctionExpression. + * + * @param node The function-like node to transform. + * @param location The source-map location for the new FunctionExpression. + * @param name The name of the new FunctionExpression. + */ function transformFunctionLikeToExpression(node, location, name, container) { var savedConvertedLoopState = convertedLoopState; convertedLoopState = undefined; - var ancestorFacts = container && ts.isClassLike(container) && !ts.hasModifier(node, 32) - ? enterSubtree(16286, 65 | 8) - : enterSubtree(16286, 65); + var ancestorFacts = container && ts.isClassLike(container) && !ts.hasModifier(node, 32 /* Static */) + ? enterSubtree(16286 /* FunctionExcludes */, 65 /* FunctionIncludes */ | 8 /* NonStaticClassElement */) + : enterSubtree(16286 /* FunctionExcludes */, 65 /* FunctionIncludes */); var parameters = ts.visitParameterList(node.parameters, visitor, context); var body = transformFunctionBody(node); - if (hierarchyFacts & 16384 && !name && (node.kind === 234 || node.kind === 192)) { + if (hierarchyFacts & 16384 /* NewTarget */ && !name && (node.kind === 234 /* FunctionDeclaration */ || node.kind === 192 /* FunctionExpression */)) { name = ts.getGeneratedNameForNode(node); } - exitSubtree(ancestorFacts, 49152, 0); + exitSubtree(ancestorFacts, 49152 /* PropagateNewTargetMask */, 0 /* None */); convertedLoopState = savedConvertedLoopState; - return ts.setOriginalNode(ts.setTextRange(ts.createFunctionExpression(undefined, node.asteriskToken, name, undefined, parameters, undefined, body), location), node); + return ts.setOriginalNode(ts.setTextRange(ts.createFunctionExpression( + /*modifiers*/ undefined, node.asteriskToken, name, + /*typeParameters*/ undefined, parameters, + /*type*/ undefined, body), location), + /*original*/ node); } + /** + * Transforms the body of a function-like node. + * + * @param node A function-like node. + */ function transformFunctionBody(node) { - var multiLine = false; - var singleLine = false; + var multiLine = false; // indicates whether the block *must* be emitted as multiple lines + var singleLine = false; // indicates whether the block *may* be emitted as a single line var statementsLocation; var closeBraceLocation; var leadingStatements = []; @@ -56913,21 +67415,29 @@ var ts; var statementOffset; resumeLexicalEnvironment(); if (ts.isBlock(body)) { - statementOffset = ts.addStandardPrologue(leadingStatements, body.statements, false); + // ensureUseStrict is false because no new prologue-directive should be added. + // addStandardPrologue will put already-existing directives at the beginning of the target statement-array + statementOffset = ts.addStandardPrologue(leadingStatements, body.statements, /*ensureUseStrict*/ false); } addCaptureThisForNodeIfNeeded(leadingStatements, node); addDefaultValueAssignmentsIfNeeded(leadingStatements, node); - addRestParameterIfNeeded(leadingStatements, node, false); + addRestParameterIfNeeded(leadingStatements, node, /*inConstructorWithSynthesizedSuper*/ false); if (ts.isBlock(body)) { + // addCustomPrologue puts already-existing directives at the beginning of the target statement-array statementOffset = ts.addCustomPrologue(leadingStatements, body.statements, statementOffset, visitor); statementsLocation = body.statements; ts.addRange(statements, ts.visitNodes(body.statements, visitor, ts.isStatement, statementOffset)); + // If the original body was a multi-line block, this must be a multi-line block. if (!multiLine && body.multiLine) { multiLine = true; } } else { - ts.Debug.assert(node.kind === 193); + ts.Debug.assert(node.kind === 193 /* ArrowFunction */); + // To align with the old emitter, we use a synthetic end position on the location + // for the statement list we synthesize when we down-level an arrow function with + // an expression function body. This prevents both comments and source maps from + // being emitted for the end position only. statementsLocation = ts.moveRangeEnd(body, -1); var equalsGreaterThanToken = node.equalsGreaterThanToken; if (!ts.nodeIsSynthesized(equalsGreaterThanToken) && !ts.nodeIsSynthesized(body)) { @@ -56942,72 +67452,103 @@ var ts; var returnStatement = ts.createReturn(expression); ts.setTextRange(returnStatement, body); ts.moveSyntheticComments(returnStatement, body); - ts.setEmitFlags(returnStatement, 384 | 32 | 1024); + ts.setEmitFlags(returnStatement, 384 /* NoTokenSourceMaps */ | 32 /* NoTrailingSourceMap */ | 1024 /* NoTrailingComments */); statements.push(returnStatement); + // To align with the source map emit for the old emitter, we set a custom + // source map location for the close brace. closeBraceLocation = body; } var lexicalEnvironment = context.endLexicalEnvironment(); ts.prependStatements(statements, lexicalEnvironment); - prependCaptureNewTargetIfNeeded(statements, node, false); + prependCaptureNewTargetIfNeeded(statements, node, /*copyOnWrite*/ false); + // If we added any final generated statements, this must be a multi-line block if (ts.some(leadingStatements) || ts.some(lexicalEnvironment)) { multiLine = true; } var block = ts.createBlock(ts.setTextRange(ts.createNodeArray(leadingStatements.concat(statements)), statementsLocation), multiLine); ts.setTextRange(block, node.body); if (!multiLine && singleLine) { - ts.setEmitFlags(block, 1); + ts.setEmitFlags(block, 1 /* SingleLine */); } if (closeBraceLocation) { - ts.setTokenSourceMapRange(block, 18, closeBraceLocation); + ts.setTokenSourceMapRange(block, 18 /* CloseBraceToken */, closeBraceLocation); } ts.setOriginalNode(block, node.body); return block; } function visitFunctionBodyDownLevel(node) { var updated = ts.visitFunctionBody(node.body, functionBodyVisitor, context); - return ts.updateBlock(updated, ts.setTextRange(ts.createNodeArray(prependCaptureNewTargetIfNeeded(updated.statements, node, true)), updated.statements)); + return ts.updateBlock(updated, ts.setTextRange(ts.createNodeArray(prependCaptureNewTargetIfNeeded(updated.statements, node, /*copyOnWrite*/ true)), + /*location*/ updated.statements)); } function visitBlock(node, isFunctionBody) { if (isFunctionBody) { + // A function body is not a block scope. return ts.visitEachChild(node, visitor, context); } - var ancestorFacts = hierarchyFacts & 256 - ? enterSubtree(4032, 512) - : enterSubtree(3904, 128); + var ancestorFacts = hierarchyFacts & 256 /* IterationStatement */ + ? enterSubtree(4032 /* IterationStatementBlockExcludes */, 512 /* IterationStatementBlockIncludes */) + : enterSubtree(3904 /* BlockExcludes */, 128 /* BlockIncludes */); var updated = ts.visitEachChild(node, visitor, context); - exitSubtree(ancestorFacts, 0, 0); + exitSubtree(ancestorFacts, 0 /* None */, 0 /* None */); return updated; } + /** + * Visits an ExpressionStatement that contains a destructuring assignment. + * + * @param node An ExpressionStatement node. + */ function visitExpressionStatement(node) { + // If we are here it is most likely because our expression is a destructuring assignment. switch (node.expression.kind) { - case 191: - return ts.updateStatement(node, visitParenthesizedExpression(node.expression, false)); - case 200: - return ts.updateStatement(node, visitBinaryExpression(node.expression, false)); + case 191 /* ParenthesizedExpression */: + return ts.updateStatement(node, visitParenthesizedExpression(node.expression, /*needsDestructuringValue*/ false)); + case 200 /* BinaryExpression */: + return ts.updateStatement(node, visitBinaryExpression(node.expression, /*needsDestructuringValue*/ false)); } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a ParenthesizedExpression that may contain a destructuring assignment. + * + * @param node A ParenthesizedExpression node. + * @param needsDestructuringValue A value indicating whether we need to hold onto the rhs + * of a destructuring assignment. + */ function visitParenthesizedExpression(node, needsDestructuringValue) { + // If we are here it is most likely because our expression is a destructuring assignment. if (!needsDestructuringValue) { + // By default we always emit the RHS at the end of a flattened destructuring + // expression. If we are in a state where we do not need the destructuring value, + // we pass that information along to the children that care about it. switch (node.expression.kind) { - case 191: - return ts.updateParen(node, visitParenthesizedExpression(node.expression, false)); - case 200: - return ts.updateParen(node, visitBinaryExpression(node.expression, false)); + case 191 /* ParenthesizedExpression */: + return ts.updateParen(node, visitParenthesizedExpression(node.expression, /*needsDestructuringValue*/ false)); + case 200 /* BinaryExpression */: + return ts.updateParen(node, visitBinaryExpression(node.expression, /*needsDestructuringValue*/ false)); } } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a BinaryExpression that contains a destructuring assignment. + * + * @param node A BinaryExpression node. + * @param needsDestructuringValue A value indicating whether we need to hold onto the rhs + * of a destructuring assignment. + */ function visitBinaryExpression(node, needsDestructuringValue) { + // If we are here it is because this is a destructuring assignment. if (ts.isDestructuringAssignment(node)) { - return ts.flattenDestructuringAssignment(node, visitor, context, 0, needsDestructuringValue); + return ts.flattenDestructuringAssignment(node, visitor, context, 0 /* All */, needsDestructuringValue); } return ts.visitEachChild(node, visitor, context); } function visitVariableStatement(node) { - var ancestorFacts = enterSubtree(0, ts.hasModifier(node, 1) ? 32 : 0); + var ancestorFacts = enterSubtree(0 /* None */, ts.hasModifier(node, 1 /* Export */) ? 32 /* ExportedVariableStatement */ : 0 /* None */); var updated; - if (convertedLoopState && (node.declarationList.flags & 3) === 0) { + if (convertedLoopState && (node.declarationList.flags & 3 /* BlockScoped */) === 0) { + // we are inside a converted loop - hoist variable declarations var assignments = void 0; for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) { var decl = _a[_i]; @@ -57015,10 +67556,10 @@ var ts; if (decl.initializer) { var assignment = void 0; if (ts.isBindingPattern(decl.name)) { - assignment = ts.flattenDestructuringAssignment(decl, visitor, context, 0); + assignment = ts.flattenDestructuringAssignment(decl, visitor, context, 0 /* All */); } else { - assignment = ts.createBinary(decl.name, 58, ts.visitNode(decl.initializer, visitor, ts.isExpression)); + assignment = ts.createBinary(decl.name, 58 /* EqualsToken */, ts.visitNode(decl.initializer, visitor, ts.isExpression)); ts.setTextRange(assignment, decl); } assignments = ts.append(assignments, assignment); @@ -57028,29 +67569,37 @@ var ts; updated = ts.setTextRange(ts.createStatement(ts.inlineExpressions(assignments)), node); } else { + // none of declarations has initializer - the entire variable statement can be deleted updated = undefined; } } else { updated = ts.visitEachChild(node, visitor, context); } - exitSubtree(ancestorFacts, 0, 0); + exitSubtree(ancestorFacts, 0 /* None */, 0 /* None */); return updated; } + /** + * Visits a VariableDeclarationList that is block scoped (e.g. `let` or `const`). + * + * @param node A VariableDeclarationList node. + */ function visitVariableDeclarationList(node) { - if (node.transformFlags & 64) { - if (node.flags & 3) { + if (node.transformFlags & 64 /* ES2015 */) { + if (node.flags & 3 /* BlockScoped */) { enableSubstitutionsForBlockScopedBindings(); } - var declarations = ts.flatMap(node.declarations, node.flags & 1 + var declarations = ts.flatMap(node.declarations, node.flags & 1 /* Let */ ? visitVariableDeclarationInLetDeclarationList : visitVariableDeclaration); var declarationList = ts.createVariableDeclarationList(declarations); ts.setOriginalNode(declarationList, node); ts.setTextRange(declarationList, node); ts.setCommentRange(declarationList, node); - if (node.transformFlags & 8388608 + if (node.transformFlags & 8388608 /* ContainsBindingPattern */ && (ts.isBindingPattern(node.declarations[0].name) || ts.isBindingPattern(ts.last(node.declarations).name))) { + // If the first or last declaration is a binding pattern, we need to modify + // the source map range for the declaration list. var firstDeclaration = ts.firstOrUndefined(declarations); if (firstDeclaration) { ts.setSourceMapRange(declarationList, ts.createRange(firstDeclaration.pos, ts.last(declarations).end)); @@ -57060,23 +67609,76 @@ var ts; } return ts.visitEachChild(node, visitor, context); } + /** + * Gets a value indicating whether we should emit an explicit initializer for a variable + * declaration in a `let` declaration list. + * + * @param node A VariableDeclaration node. + */ function shouldEmitExplicitInitializerForLetDeclaration(node) { + // Nested let bindings might need to be initialized explicitly to preserve + // ES6 semantic: + // + // { let x = 1; } + // { let x; } // x here should be undefined. not 1 + // + // Top level bindings never collide with anything and thus don't require + // explicit initialization. As for nested let bindings there are two cases: + // + // - Nested let bindings that were not renamed definitely should be + // initialized explicitly: + // + // { let x = 1; } + // { let x; if (some-condition) { x = 1}; if (x) { /*1*/ } } + // + // Without explicit initialization code in /*1*/ can be executed even if + // some-condition is evaluated to false. + // + // - Renaming introduces fresh name that should not collide with any + // existing names, however renamed bindings sometimes also should be + // explicitly initialized. One particular case: non-captured binding + // declared inside loop body (but not in loop initializer): + // + // let x; + // for (;;) { + // let x; + // } + // + // In downlevel codegen inner 'x' will be renamed so it won't collide + // with outer 'x' however it will should be reset on every iteration as + // if it was declared anew. + // + // * Why non-captured binding? + // - Because if loop contains block scoped binding captured in some + // function then loop body will be rewritten to have a fresh scope + // on every iteration so everything will just work. + // + // * Why loop initializer is excluded? + // - Since we've introduced a fresh name it already will be undefined. var flags = resolver.getNodeCheckFlags(node); - var isCapturedInFunction = flags & 131072; - var isDeclaredInLoop = flags & 262144; - var emittedAsTopLevel = (hierarchyFacts & 64) !== 0 + var isCapturedInFunction = flags & 131072 /* CapturedBlockScopedBinding */; + var isDeclaredInLoop = flags & 262144 /* BlockScopedBindingInLoop */; + var emittedAsTopLevel = (hierarchyFacts & 64 /* TopLevel */) !== 0 || (isCapturedInFunction && isDeclaredInLoop - && (hierarchyFacts & 512) !== 0); + && (hierarchyFacts & 512 /* IterationStatementBlock */) !== 0); var emitExplicitInitializer = !emittedAsTopLevel - && (hierarchyFacts & 2048) === 0 + && (hierarchyFacts & 2048 /* ForInOrForOfStatement */) === 0 && (!resolver.isDeclarationWithCollidingName(node) || (isDeclaredInLoop && !isCapturedInFunction - && (hierarchyFacts & (1024 | 2048)) === 0)); + && (hierarchyFacts & (1024 /* ForStatement */ | 2048 /* ForInOrForOfStatement */)) === 0)); return emitExplicitInitializer; } + /** + * Visits a VariableDeclaration in a `let` declaration list. + * + * @param node A VariableDeclaration node. + */ function visitVariableDeclarationInLetDeclarationList(node) { + // For binding pattern names that lack initializers there is no point to emit + // explicit initializer since downlevel codegen for destructuring will fail + // in the absence of initializer so all binding elements will say uninitialized var name = node.name; if (ts.isBindingPattern(name)) { return visitVariableDeclaration(node); @@ -57088,16 +67690,22 @@ var ts; } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a VariableDeclaration node with a binding pattern. + * + * @param node A VariableDeclaration node. + */ function visitVariableDeclaration(node) { - var ancestorFacts = enterSubtree(32, 0); + var ancestorFacts = enterSubtree(32 /* ExportedVariableStatement */, 0 /* None */); var updated; if (ts.isBindingPattern(node.name)) { - updated = ts.flattenDestructuringBinding(node, visitor, context, 0, undefined, (ancestorFacts & 32) !== 0); + updated = ts.flattenDestructuringBinding(node, visitor, context, 0 /* All */, + /*value*/ undefined, (ancestorFacts & 32 /* ExportedVariableStatement */) !== 0); } else { updated = ts.visitEachChild(node, visitor, context); } - exitSubtree(ancestorFacts, 0, 0); + exitSubtree(ancestorFacts, 0 /* None */, 0 /* None */); return updated; } function recordLabel(node) { @@ -57111,67 +67719,78 @@ var ts; convertedLoopState.labels = ts.createMap(); } var statement = ts.unwrapInnermostStatementOfLabel(node, convertedLoopState && recordLabel); - return ts.isIterationStatement(statement, false) - ? visitIterationStatement(statement, node) + return ts.isIterationStatement(statement, /*lookInLabeledStatements*/ false) + ? visitIterationStatement(statement, /*outermostLabeledStatement*/ node) : ts.restoreEnclosingLabel(ts.visitNode(statement, visitor, ts.isStatement), node, convertedLoopState && resetLabel); } function visitIterationStatement(node, outermostLabeledStatement) { switch (node.kind) { - case 218: - case 219: + case 218 /* DoStatement */: + case 219 /* WhileStatement */: return visitDoOrWhileStatement(node, outermostLabeledStatement); - case 220: + case 220 /* ForStatement */: return visitForStatement(node, outermostLabeledStatement); - case 221: + case 221 /* ForInStatement */: return visitForInStatement(node, outermostLabeledStatement); - case 222: + case 222 /* ForOfStatement */: return visitForOfStatement(node, outermostLabeledStatement); } } function visitIterationStatementWithFacts(excludeFacts, includeFacts, node, outermostLabeledStatement, convert) { var ancestorFacts = enterSubtree(excludeFacts, includeFacts); var updated = convertIterationStatementBodyIfNecessary(node, outermostLabeledStatement, convert); - exitSubtree(ancestorFacts, 0, 0); + exitSubtree(ancestorFacts, 0 /* None */, 0 /* None */); return updated; } function visitDoOrWhileStatement(node, outermostLabeledStatement) { - return visitIterationStatementWithFacts(0, 256, node, outermostLabeledStatement); + return visitIterationStatementWithFacts(0 /* DoOrWhileStatementExcludes */, 256 /* DoOrWhileStatementIncludes */, node, outermostLabeledStatement); } function visitForStatement(node, outermostLabeledStatement) { - return visitIterationStatementWithFacts(3008, 1280, node, outermostLabeledStatement); + return visitIterationStatementWithFacts(3008 /* ForStatementExcludes */, 1280 /* ForStatementIncludes */, node, outermostLabeledStatement); } function visitForInStatement(node, outermostLabeledStatement) { - return visitIterationStatementWithFacts(1984, 2304, node, outermostLabeledStatement); + return visitIterationStatementWithFacts(1984 /* ForInOrForOfStatementExcludes */, 2304 /* ForInOrForOfStatementIncludes */, node, outermostLabeledStatement); } function visitForOfStatement(node, outermostLabeledStatement) { - return visitIterationStatementWithFacts(1984, 2304, node, outermostLabeledStatement, compilerOptions.downlevelIteration ? convertForOfStatementForIterable : convertForOfStatementForArray); + return visitIterationStatementWithFacts(1984 /* ForInOrForOfStatementExcludes */, 2304 /* ForInOrForOfStatementIncludes */, node, outermostLabeledStatement, compilerOptions.downlevelIteration ? convertForOfStatementForIterable : convertForOfStatementForArray); } function convertForOfStatementHead(node, boundValue, convertedLoopBodyStatements) { var statements = []; var initializer = node.initializer; if (ts.isVariableDeclarationList(initializer)) { - if (node.initializer.flags & 3) { + if (node.initializer.flags & 3 /* BlockScoped */) { enableSubstitutionsForBlockScopedBindings(); } var firstOriginalDeclaration = ts.firstOrUndefined(initializer.declarations); if (firstOriginalDeclaration && ts.isBindingPattern(firstOriginalDeclaration.name)) { - var declarations = ts.flattenDestructuringBinding(firstOriginalDeclaration, visitor, context, 0, boundValue); + // This works whether the declaration is a var, let, or const. + // It will use rhsIterationValue _a[_i] as the initializer. + var declarations = ts.flattenDestructuringBinding(firstOriginalDeclaration, visitor, context, 0 /* All */, boundValue); var declarationList = ts.setTextRange(ts.createVariableDeclarationList(declarations), node.initializer); ts.setOriginalNode(declarationList, node.initializer); + // Adjust the source map range for the first declaration to align with the old + // emitter. ts.setSourceMapRange(declarationList, ts.createRange(declarations[0].pos, ts.last(declarations).end)); - statements.push(ts.createVariableStatement(undefined, declarationList)); + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, declarationList)); } else { - statements.push(ts.setTextRange(ts.createVariableStatement(undefined, ts.setOriginalNode(ts.setTextRange(ts.createVariableDeclarationList([ - ts.createVariableDeclaration(firstOriginalDeclaration ? firstOriginalDeclaration.name : ts.createTempVariable(undefined), undefined, boundValue) + // The following call does not include the initializer, so we have + // to emit it separately. + statements.push(ts.setTextRange(ts.createVariableStatement( + /*modifiers*/ undefined, ts.setOriginalNode(ts.setTextRange(ts.createVariableDeclarationList([ + ts.createVariableDeclaration(firstOriginalDeclaration ? firstOriginalDeclaration.name : ts.createTempVariable(/*recordTempVariable*/ undefined), + /*type*/ undefined, boundValue) ]), ts.moveRangePos(initializer, -1)), initializer)), ts.moveRangeEnd(initializer, -1))); } } else { + // Initializer is an expression. Emit the expression in the body, so that it's + // evaluated on every iteration. var assignment = ts.createAssignment(initializer, boundValue); if (ts.isDestructuringAssignment(assignment)) { ts.aggregateTransformFlags(assignment); - statements.push(ts.createStatement(visitBinaryExpression(assignment, false))); + statements.push(ts.createStatement(visitBinaryExpression(assignment, /*needsDestructuringValue*/ false))); } else { assignment.end = initializer.end; @@ -57193,62 +67812,111 @@ var ts; } } function createSyntheticBlockForConvertedStatements(statements) { - return ts.setEmitFlags(ts.createBlock(ts.createNodeArray(statements), true), 48 | 384); + return ts.setEmitFlags(ts.createBlock(ts.createNodeArray(statements), + /*multiLine*/ true), 48 /* NoSourceMap */ | 384 /* NoTokenSourceMaps */); } function convertForOfStatementForArray(node, outermostLabeledStatement, convertedLoopBodyStatements) { + // The following ES6 code: + // + // for (let v of expr) { } + // + // should be emitted as + // + // for (var _i = 0, _a = expr; _i < _a.length; _i++) { + // var 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. var expression = ts.visitNode(node.expression, visitor, ts.isExpression); + // 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. var counter = ts.createLoopVariable(); - var rhsReference = ts.isIdentifier(expression) ? ts.getGeneratedNameForNode(expression) : ts.createTempVariable(undefined); - ts.setEmitFlags(expression, 48 | ts.getEmitFlags(expression)); - var forStatement = ts.setTextRange(ts.createFor(ts.setEmitFlags(ts.setTextRange(ts.createVariableDeclarationList([ - ts.setTextRange(ts.createVariableDeclaration(counter, undefined, ts.createLiteral(0)), ts.moveRangePos(node.expression, -1)), - ts.setTextRange(ts.createVariableDeclaration(rhsReference, undefined, expression), node.expression) - ]), node.expression), 2097152), ts.setTextRange(ts.createLessThan(counter, ts.createPropertyAccess(rhsReference, "length")), node.expression), ts.setTextRange(ts.createPostfixIncrement(counter), node.expression), convertForOfStatementHead(node, ts.createElementAccess(rhsReference, counter), convertedLoopBodyStatements)), node); - ts.setEmitFlags(forStatement, 256); + var rhsReference = ts.isIdentifier(expression) ? ts.getGeneratedNameForNode(expression) : ts.createTempVariable(/*recordTempVariable*/ undefined); + // The old emitter does not emit source maps for the expression + ts.setEmitFlags(expression, 48 /* NoSourceMap */ | ts.getEmitFlags(expression)); + var forStatement = ts.setTextRange(ts.createFor( + /*initializer*/ ts.setEmitFlags(ts.setTextRange(ts.createVariableDeclarationList([ + ts.setTextRange(ts.createVariableDeclaration(counter, /*type*/ undefined, ts.createLiteral(0)), ts.moveRangePos(node.expression, -1)), + ts.setTextRange(ts.createVariableDeclaration(rhsReference, /*type*/ undefined, expression), node.expression) + ]), node.expression), 2097152 /* NoHoisting */), + /*condition*/ ts.setTextRange(ts.createLessThan(counter, ts.createPropertyAccess(rhsReference, "length")), node.expression), + /*incrementor*/ ts.setTextRange(ts.createPostfixIncrement(counter), node.expression), + /*statement*/ convertForOfStatementHead(node, ts.createElementAccess(rhsReference, counter), convertedLoopBodyStatements)), + /*location*/ node); + // Disable trailing source maps for the OpenParenToken to align source map emit with the old emitter. + ts.setEmitFlags(forStatement, 256 /* NoTokenTrailingSourceMaps */); ts.setTextRange(forStatement, node); return ts.restoreEnclosingLabel(forStatement, outermostLabeledStatement, convertedLoopState && resetLabel); } function convertForOfStatementForIterable(node, outermostLabeledStatement, convertedLoopBodyStatements) { var expression = ts.visitNode(node.expression, visitor, ts.isExpression); - var iterator = ts.isIdentifier(expression) ? ts.getGeneratedNameForNode(expression) : ts.createTempVariable(undefined); - var result = ts.isIdentifier(expression) ? ts.getGeneratedNameForNode(iterator) : ts.createTempVariable(undefined); + var iterator = ts.isIdentifier(expression) ? ts.getGeneratedNameForNode(expression) : ts.createTempVariable(/*recordTempVariable*/ undefined); + var result = ts.isIdentifier(expression) ? ts.getGeneratedNameForNode(iterator) : ts.createTempVariable(/*recordTempVariable*/ undefined); var errorRecord = ts.createUniqueName("e"); var catchVariable = ts.getGeneratedNameForNode(errorRecord); - var returnMethod = ts.createTempVariable(undefined); + var returnMethod = ts.createTempVariable(/*recordTempVariable*/ undefined); var values = ts.createValuesHelper(context, expression, node.expression); - var next = ts.createCall(ts.createPropertyAccess(iterator, "next"), undefined, []); + var next = ts.createCall(ts.createPropertyAccess(iterator, "next"), /*typeArguments*/ undefined, []); hoistVariableDeclaration(errorRecord); hoistVariableDeclaration(returnMethod); - var forStatement = ts.setEmitFlags(ts.setTextRange(ts.createFor(ts.setEmitFlags(ts.setTextRange(ts.createVariableDeclarationList([ - ts.setTextRange(ts.createVariableDeclaration(iterator, undefined, values), node.expression), - ts.createVariableDeclaration(result, undefined, next) - ]), node.expression), 2097152), ts.createLogicalNot(ts.createPropertyAccess(result, "done")), ts.createAssignment(result, next), convertForOfStatementHead(node, ts.createPropertyAccess(result, "value"), convertedLoopBodyStatements)), node), 256); + var forStatement = ts.setEmitFlags(ts.setTextRange(ts.createFor( + /*initializer*/ ts.setEmitFlags(ts.setTextRange(ts.createVariableDeclarationList([ + ts.setTextRange(ts.createVariableDeclaration(iterator, /*type*/ undefined, values), node.expression), + ts.createVariableDeclaration(result, /*type*/ undefined, next) + ]), node.expression), 2097152 /* NoHoisting */), + /*condition*/ ts.createLogicalNot(ts.createPropertyAccess(result, "done")), + /*incrementor*/ ts.createAssignment(result, next), + /*statement*/ convertForOfStatementHead(node, ts.createPropertyAccess(result, "value"), convertedLoopBodyStatements)), + /*location*/ node), 256 /* NoTokenTrailingSourceMaps */); return ts.createTry(ts.createBlock([ ts.restoreEnclosingLabel(forStatement, outermostLabeledStatement, convertedLoopState && resetLabel) ]), ts.createCatchClause(ts.createVariableDeclaration(catchVariable), ts.setEmitFlags(ts.createBlock([ ts.createStatement(ts.createAssignment(errorRecord, ts.createObjectLiteral([ ts.createPropertyAssignment("error", catchVariable) ]))) - ]), 1)), ts.createBlock([ - ts.createTry(ts.createBlock([ - ts.setEmitFlags(ts.createIf(ts.createLogicalAnd(ts.createLogicalAnd(result, ts.createLogicalNot(ts.createPropertyAccess(result, "done"))), ts.createAssignment(returnMethod, ts.createPropertyAccess(iterator, "return"))), ts.createStatement(ts.createFunctionCall(returnMethod, iterator, []))), 1), - ]), undefined, ts.setEmitFlags(ts.createBlock([ - ts.setEmitFlags(ts.createIf(errorRecord, ts.createThrow(ts.createPropertyAccess(errorRecord, "error"))), 1) - ]), 1)) + ]), 1 /* SingleLine */)), ts.createBlock([ + ts.createTry( + /*tryBlock*/ ts.createBlock([ + ts.setEmitFlags(ts.createIf(ts.createLogicalAnd(ts.createLogicalAnd(result, ts.createLogicalNot(ts.createPropertyAccess(result, "done"))), ts.createAssignment(returnMethod, ts.createPropertyAccess(iterator, "return"))), ts.createStatement(ts.createFunctionCall(returnMethod, iterator, []))), 1 /* SingleLine */), + ]), + /*catchClause*/ undefined, + /*finallyBlock*/ ts.setEmitFlags(ts.createBlock([ + ts.setEmitFlags(ts.createIf(errorRecord, ts.createThrow(ts.createPropertyAccess(errorRecord, "error"))), 1 /* SingleLine */) + ]), 1 /* SingleLine */)) ])); } + /** + * Visits an ObjectLiteralExpression with computed property names. + * + * @param node An ObjectLiteralExpression node. + */ function visitObjectLiteralExpression(node) { + // We are here because a ComputedPropertyName was used somewhere in the expression. var properties = node.properties; var numProperties = properties.length; + // Find the first computed property. + // Everything until that point can be emitted as part of the initial object literal. var numInitialProperties = numProperties; var numInitialPropertiesWithoutYield = numProperties; for (var i = 0; i < numProperties; i++) { var property = properties[i]; - if ((property.transformFlags & 16777216 && hierarchyFacts & 4) + if ((property.transformFlags & 16777216 /* ContainsYield */ && hierarchyFacts & 4 /* AsyncFunctionBody */) && i < numInitialPropertiesWithoutYield) { numInitialPropertiesWithoutYield = i; } - if (property.name.kind === 147) { + if (property.name.kind === 147 /* ComputedPropertyName */) { numInitialProperties = i; break; } @@ -57257,29 +67925,37 @@ var ts; if (numInitialPropertiesWithoutYield < numInitialProperties) { numInitialProperties = numInitialPropertiesWithoutYield; } + // 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. var temp = ts.createTempVariable(hoistVariableDeclaration); + // Write out the first non-computed properties, then emit the rest through indexing on the temp variable. var expressions = []; - var assignment = ts.createAssignment(temp, ts.setEmitFlags(ts.createObjectLiteral(ts.visitNodes(properties, visitor, ts.isObjectLiteralElementLike, 0, numInitialProperties), node.multiLine), 65536)); + var assignment = ts.createAssignment(temp, ts.setEmitFlags(ts.createObjectLiteral(ts.visitNodes(properties, visitor, ts.isObjectLiteralElementLike, 0, numInitialProperties), node.multiLine), 65536 /* Indented */)); if (node.multiLine) { ts.startOnNewLine(assignment); } expressions.push(assignment); addObjectLiteralMembers(expressions, node, temp, numInitialProperties); + // We need to clone the temporary identifier so that we can write it on a + // new line expressions.push(node.multiLine ? ts.startOnNewLine(ts.getMutableClone(temp)) : temp); return ts.inlineExpressions(expressions); } return ts.visitEachChild(node, visitor, context); } function shouldConvertIterationStatementBody(node) { - return (resolver.getNodeCheckFlags(node) & 65536) !== 0; + return (resolver.getNodeCheckFlags(node) & 65536 /* LoopWithCapturedBlockScopedBinding */) !== 0; } + /** + * Records constituents of name for the given variable to be hoisted in the outer scope. + */ function hoistVariableDeclarationDeclaredInConvertedLoop(state, node) { if (!state.hoistedLocalVariables) { state.hoistedLocalVariables = []; } visit(node.name); function visit(node) { - if (node.kind === 71) { + if (node.kind === 71 /* Identifier */) { state.hoistedLocalVariables.push(node); } else { @@ -57296,11 +67972,13 @@ var ts; if (!shouldConvertIterationStatementBody(node)) { var saveAllowedNonLabeledJumps = void 0; if (convertedLoopState) { + // we get here if we are trying to emit normal loop loop inside converted loop + // set allowedNonLabeledJumps to Break | Continue to mark that break\continue inside the loop should be emitted as is saveAllowedNonLabeledJumps = convertedLoopState.allowedNonLabeledJumps; - convertedLoopState.allowedNonLabeledJumps = 2 | 4; + convertedLoopState.allowedNonLabeledJumps = 2 /* Break */ | 4 /* Continue */; } var result = convert - ? convert(node, outermostLabeledStatement, undefined) + ? convert(node, outermostLabeledStatement, /*convertedLoopBodyStatements*/ undefined) : ts.restoreEnclosingLabel(ts.visitEachChild(node, visitor, context), outermostLabeledStatement, convertedLoopState && resetLabel); if (convertedLoopState) { convertedLoopState.allowedNonLabeledJumps = saveAllowedNonLabeledJumps; @@ -57310,18 +67988,20 @@ var ts; var functionName = ts.createUniqueName("_loop"); var loopInitializer; switch (node.kind) { - case 220: - case 221: - case 222: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: var initializer = node.initializer; - if (initializer && initializer.kind === 233) { + if (initializer && initializer.kind === 233 /* VariableDeclarationList */) { loopInitializer = initializer; } break; } + // variables that will be passed to the loop as parameters var loopParameters = []; + // variables declared in the loop initializer that will be changed inside the loop var loopOutParameters = []; - if (loopInitializer && (ts.getCombinedNodeFlags(loopInitializer) & 3)) { + if (loopInitializer && (ts.getCombinedNodeFlags(loopInitializer) & 3 /* BlockScoped */)) { for (var _i = 0, _a = loopInitializer.declarations; _i < _a.length; _i++) { var decl = _a[_i]; processLoopVariableDeclaration(decl, loopParameters, loopOutParameters); @@ -57330,13 +68010,21 @@ var ts; var outerConvertedLoopState = convertedLoopState; convertedLoopState = { loopOutParameters: loopOutParameters }; if (outerConvertedLoopState) { + // convertedOuterLoopState !== undefined means that this converted loop is nested in another converted loop. + // if outer converted loop has already accumulated some state - pass it through if (outerConvertedLoopState.argumentsName) { + // outer loop has already used 'arguments' so we've already have some name to alias it + // use the same name in all nested loops convertedLoopState.argumentsName = outerConvertedLoopState.argumentsName; } if (outerConvertedLoopState.thisName) { + // outer loop has already used 'this' so we've already have some name to alias it + // use the same name in all nested loops convertedLoopState.thisName = outerConvertedLoopState.thisName; } if (outerConvertedLoopState.hoistedLocalVariables) { + // we've already collected some non-block scoped variable declarations in enclosing loop + // use the same storage in nested loop convertedLoopState.hoistedLocalVariables = outerConvertedLoopState.hoistedLocalVariables; } } @@ -57348,61 +68036,83 @@ var ts; if (loopOutParameters.length || lexicalEnvironment) { var statements_4 = ts.isBlock(loopBody) ? loopBody.statements.slice() : [loopBody]; if (loopOutParameters.length) { - copyOutParameters(loopOutParameters, 1, statements_4); + copyOutParameters(loopOutParameters, 1 /* ToOutParameter */, statements_4); } ts.prependStatements(statements_4, lexicalEnvironment); - loopBody = ts.createBlock(statements_4, true); + loopBody = ts.createBlock(statements_4, /*multiline*/ true); } if (ts.isBlock(loopBody)) { loopBody.multiLine = true; } else { - loopBody = ts.createBlock([loopBody], true); + loopBody = ts.createBlock([loopBody], /*multiline*/ true); } - var containsYield = (node.statement.transformFlags & 16777216) !== 0; - var isAsyncBlockContainingAwait = containsYield && (hierarchyFacts & 4) !== 0; + var containsYield = (node.statement.transformFlags & 16777216 /* ContainsYield */) !== 0; + var isAsyncBlockContainingAwait = containsYield && (hierarchyFacts & 4 /* AsyncFunctionBody */) !== 0; var loopBodyFlags = 0; if (currentState.containsLexicalThis) { - loopBodyFlags |= 8; + loopBodyFlags |= 8 /* CapturesThis */; } if (isAsyncBlockContainingAwait) { - loopBodyFlags |= 262144; + loopBodyFlags |= 262144 /* AsyncFunctionBody */; } - var convertedLoopVariable = ts.createVariableStatement(undefined, ts.setEmitFlags(ts.createVariableDeclarationList([ - ts.createVariableDeclaration(functionName, undefined, ts.setEmitFlags(ts.createFunctionExpression(undefined, containsYield ? ts.createToken(39) : undefined, undefined, undefined, loopParameters, undefined, loopBody), loopBodyFlags)) - ]), 2097152)); + var convertedLoopVariable = ts.createVariableStatement( + /*modifiers*/ undefined, ts.setEmitFlags(ts.createVariableDeclarationList([ + ts.createVariableDeclaration(functionName, + /*type*/ undefined, ts.setEmitFlags(ts.createFunctionExpression( + /*modifiers*/ undefined, containsYield ? ts.createToken(39 /* AsteriskToken */) : undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, loopParameters, + /*type*/ undefined, loopBody), loopBodyFlags)) + ]), 2097152 /* NoHoisting */)); var statements = [convertedLoopVariable]; var extraVariableDeclarations; + // propagate state from the inner loop to the outer loop if necessary if (currentState.argumentsName) { + // if alias for arguments is set if (outerConvertedLoopState) { + // pass it to outer converted loop outerConvertedLoopState.argumentsName = currentState.argumentsName; } else { - (extraVariableDeclarations || (extraVariableDeclarations = [])).push(ts.createVariableDeclaration(currentState.argumentsName, undefined, ts.createIdentifier("arguments"))); + // this is top level converted loop and we need to create an alias for 'arguments' object + (extraVariableDeclarations || (extraVariableDeclarations = [])).push(ts.createVariableDeclaration(currentState.argumentsName, + /*type*/ undefined, ts.createIdentifier("arguments"))); } } if (currentState.thisName) { + // if alias for this is set if (outerConvertedLoopState) { + // pass it to outer converted loop outerConvertedLoopState.thisName = currentState.thisName; } else { - (extraVariableDeclarations || (extraVariableDeclarations = [])).push(ts.createVariableDeclaration(currentState.thisName, undefined, ts.createIdentifier("this"))); + // this is top level converted loop so we need to create an alias for 'this' here + // NOTE: + // if converted loops were all nested in arrow function then we'll always emit '_this' so convertedLoopState.thisName will not be set. + // If it is set this means that all nested loops are not nested in arrow function and it is safe to capture 'this'. + (extraVariableDeclarations || (extraVariableDeclarations = [])).push(ts.createVariableDeclaration(currentState.thisName, + /*type*/ undefined, ts.createIdentifier("this"))); } } if (currentState.hoistedLocalVariables) { + // if hoistedLocalVariables !== undefined this means that we've possibly collected some variable declarations to be hoisted later if (outerConvertedLoopState) { + // pass them to outer converted loop outerConvertedLoopState.hoistedLocalVariables = currentState.hoistedLocalVariables; } else { if (!extraVariableDeclarations) { extraVariableDeclarations = []; } + // hoist collected variable declarations for (var _b = 0, _c = currentState.hoistedLocalVariables; _b < _c.length; _b++) { var identifier = _c[_b]; extraVariableDeclarations.push(ts.createVariableDeclaration(identifier)); } } } + // add extra variables to hold out parameters if necessary if (loopOutParameters.length) { if (!extraVariableDeclarations) { extraVariableDeclarations = []; @@ -57412,8 +68122,10 @@ var ts; extraVariableDeclarations.push(ts.createVariableDeclaration(outParam.outParamName)); } } + // create variable statement to hold all introduced variable declarations if (extraVariableDeclarations) { - statements.push(ts.createVariableStatement(undefined, ts.createVariableDeclarationList(extraVariableDeclarations))); + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList(extraVariableDeclarations))); } var convertedLoopBodyStatements = generateCallToConvertedLoop(functionName, loopParameters, currentState, containsYield); var loop; @@ -57422,9 +68134,13 @@ var ts; } else { var clone_3 = ts.getMutableClone(node); + // clean statement part clone_3.statement = undefined; + // visit childnodes to transform initializer/condition/incrementor parts clone_3 = ts.visitEachChild(clone_3, visitor, context); - clone_3.statement = ts.createBlock(convertedLoopBodyStatements, true); + // set loop statement + clone_3.statement = ts.createBlock(convertedLoopBodyStatements, /*multiline*/ true); + // reset and re-aggregate the transform flags clone_3.transformFlags = 0; ts.aggregateTransformFlags(clone_3); loop = ts.restoreEnclosingLabel(clone_3, outermostLabeledStatement, convertedLoopState && resetLabel); @@ -57433,9 +68149,9 @@ var ts; return statements; } function copyOutParameter(outParam, copyDirection) { - var source = copyDirection === 0 ? outParam.outParamName : outParam.originalName; - var target = copyDirection === 0 ? outParam.originalName : outParam.outParamName; - return ts.createBinary(target, 58, source); + var source = copyDirection === 0 /* ToOriginal */ ? outParam.outParamName : outParam.originalName; + var target = copyDirection === 0 /* ToOriginal */ ? outParam.originalName : outParam.outParamName; + return ts.createBinary(target, 58 /* EqualsToken */, source); } function copyOutParameters(outParams, copyDirection, statements) { for (var _i = 0, outParams_1 = outParams; _i < outParams_1.length; _i++) { @@ -57446,40 +68162,44 @@ var ts; function generateCallToConvertedLoop(loopFunctionExpressionName, parameters, state, isAsyncBlockContainingAwait) { var outerConvertedLoopState = convertedLoopState; var statements = []; - var isSimpleLoop = !(state.nonLocalJumps & ~4) && + // loop is considered simple if it does not have any return statements or break\continue that transfer control outside of the loop + // simple loops are emitted as just 'loop()'; + // NOTE: if loop uses only 'continue' it still will be emitted as simple loop + var isSimpleLoop = !(state.nonLocalJumps & ~4 /* Continue */) && !state.labeledNonLocalBreaks && !state.labeledNonLocalContinues; - var call = ts.createCall(loopFunctionExpressionName, undefined, ts.map(parameters, function (p) { return p.name; })); + var call = ts.createCall(loopFunctionExpressionName, /*typeArguments*/ undefined, ts.map(parameters, function (p) { return p.name; })); var callResult = isAsyncBlockContainingAwait - ? ts.createYield(ts.createToken(39), ts.setEmitFlags(call, 8388608)) + ? ts.createYield(ts.createToken(39 /* AsteriskToken */), ts.setEmitFlags(call, 8388608 /* Iterator */)) : call; if (isSimpleLoop) { statements.push(ts.createStatement(callResult)); - copyOutParameters(state.loopOutParameters, 0, statements); + copyOutParameters(state.loopOutParameters, 0 /* ToOriginal */, statements); } else { var loopResultName = ts.createUniqueName("state"); - var stateVariable = ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(loopResultName, undefined, callResult)])); + var stateVariable = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(loopResultName, /*type*/ undefined, callResult)])); statements.push(stateVariable); - copyOutParameters(state.loopOutParameters, 0, statements); - if (state.nonLocalJumps & 8) { + copyOutParameters(state.loopOutParameters, 0 /* ToOriginal */, statements); + if (state.nonLocalJumps & 8 /* Return */) { var returnStatement = void 0; if (outerConvertedLoopState) { - outerConvertedLoopState.nonLocalJumps |= 8; + outerConvertedLoopState.nonLocalJumps |= 8 /* Return */; returnStatement = ts.createReturn(loopResultName); } else { returnStatement = ts.createReturn(ts.createPropertyAccess(loopResultName, "value")); } - statements.push(ts.createIf(ts.createBinary(ts.createTypeOf(loopResultName), 34, ts.createLiteral("object")), returnStatement)); + statements.push(ts.createIf(ts.createBinary(ts.createTypeOf(loopResultName), 34 /* EqualsEqualsEqualsToken */, ts.createLiteral("object")), returnStatement)); } - if (state.nonLocalJumps & 2) { - statements.push(ts.createIf(ts.createBinary(loopResultName, 34, ts.createLiteral("break")), ts.createBreak())); + if (state.nonLocalJumps & 2 /* Break */) { + statements.push(ts.createIf(ts.createBinary(loopResultName, 34 /* EqualsEqualsEqualsToken */, ts.createLiteral("break")), ts.createBreak())); } if (state.labeledNonLocalBreaks || state.labeledNonLocalContinues) { var caseClauses = []; - processLabeledJumps(state.labeledNonLocalBreaks, true, loopResultName, outerConvertedLoopState, caseClauses); - processLabeledJumps(state.labeledNonLocalContinues, false, loopResultName, outerConvertedLoopState, caseClauses); + processLabeledJumps(state.labeledNonLocalBreaks, /*isBreak*/ true, loopResultName, outerConvertedLoopState, caseClauses); + processLabeledJumps(state.labeledNonLocalContinues, /*isBreak*/ false, loopResultName, outerConvertedLoopState, caseClauses); statements.push(ts.createSwitch(loopResultName, ts.createCaseBlock(caseClauses))); } } @@ -57505,6 +68225,9 @@ var ts; } table.forEach(function (labelMarker, labelText) { var statements = []; + // if there are no outer converted loop or outer label in question is located inside outer converted loop + // then emit labeled break\continue + // otherwise propagate pair 'label -> marker' to outer converted loop and emit 'return labelMarker' so outer loop can later decide what to do if (!outerLoop || (outerLoop.labels && outerLoop.labels.get(labelText))) { var label = ts.createIdentifier(labelText); statements.push(isBreak ? ts.createBreak(label) : ts.createContinue(label)); @@ -57527,33 +68250,42 @@ var ts; } } else { - loopParameters.push(ts.createParameter(undefined, undefined, undefined, name)); - if (resolver.getNodeCheckFlags(decl) & 2097152) { + loopParameters.push(ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, name)); + if (resolver.getNodeCheckFlags(decl) & 2097152 /* NeedsLoopOutParameter */) { var outParamName = ts.createUniqueName("out_" + ts.idText(name)); loopOutParameters.push({ originalName: name, outParamName: outParamName }); } } } + /** + * Adds the members of an object literal to an array of expressions. + * + * @param expressions An array of expressions. + * @param node An ObjectLiteralExpression node. + * @param receiver The receiver for members of the ObjectLiteralExpression. + * @param numInitialNonComputedProperties The number of initial properties without + * computed property names. + */ function addObjectLiteralMembers(expressions, node, receiver, start) { var properties = node.properties; var numProperties = properties.length; for (var i = start; i < numProperties; i++) { var property = properties[i]; switch (property.kind) { - case 156: - case 157: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: var accessors = ts.getAllAccessorDeclarations(node.properties, property); if (property === accessors.firstAccessor) { expressions.push(transformAccessorsToExpression(receiver, accessors, node, !!node.multiLine)); } break; - case 154: + case 154 /* MethodDeclaration */: expressions.push(transformObjectLiteralMethodDeclarationToExpression(property, receiver, node, node.multiLine)); break; - case 270: + case 270 /* PropertyAssignment */: expressions.push(transformPropertyAssignmentToExpression(property, receiver, node.multiLine)); break; - case 271: + case 271 /* ShorthandPropertyAssignment */: expressions.push(transformShorthandPropertyAssignmentToExpression(property, receiver, node.multiLine)); break; default: @@ -57562,6 +68294,13 @@ var ts; } } } + /** + * Transforms a PropertyAssignment node into an expression. + * + * @param node The ObjectLiteralExpression that contains the PropertyAssignment. + * @param property The PropertyAssignment node. + * @param receiver The receiver for the assignment. + */ function transformPropertyAssignmentToExpression(property, receiver, startsOnNewLine) { var expression = ts.createAssignment(ts.createMemberAccessForPropertyName(receiver, ts.visitNode(property.name, visitor, ts.isPropertyName)), ts.visitNode(property.initializer, visitor, ts.isExpression)); ts.setTextRange(expression, property); @@ -57570,6 +68309,13 @@ var ts; } return expression; } + /** + * Transforms a ShorthandPropertyAssignment node into an expression. + * + * @param node The ObjectLiteralExpression that contains the ShorthandPropertyAssignment. + * @param property The ShorthandPropertyAssignment node. + * @param receiver The receiver for the assignment. + */ function transformShorthandPropertyAssignmentToExpression(property, receiver, startsOnNewLine) { var expression = ts.createAssignment(ts.createMemberAccessForPropertyName(receiver, ts.visitNode(property.name, visitor, ts.isPropertyName)), ts.getSynthesizedClone(property.name)); ts.setTextRange(expression, property); @@ -57578,103 +68324,201 @@ var ts; } return expression; } + /** + * Transforms a MethodDeclaration of an ObjectLiteralExpression into an expression. + * + * @param node The ObjectLiteralExpression that contains the MethodDeclaration. + * @param method The MethodDeclaration node. + * @param receiver The receiver for the assignment. + */ function transformObjectLiteralMethodDeclarationToExpression(method, receiver, container, startsOnNewLine) { - var ancestorFacts = enterSubtree(0, 0); - var expression = ts.createAssignment(ts.createMemberAccessForPropertyName(receiver, ts.visitNode(method.name, visitor, ts.isPropertyName)), transformFunctionLikeToExpression(method, method, undefined, container)); + var ancestorFacts = enterSubtree(0 /* None */, 0 /* None */); + var expression = ts.createAssignment(ts.createMemberAccessForPropertyName(receiver, ts.visitNode(method.name, visitor, ts.isPropertyName)), transformFunctionLikeToExpression(method, /*location*/ method, /*name*/ undefined, container)); ts.setTextRange(expression, method); if (startsOnNewLine) { ts.startOnNewLine(expression); } - exitSubtree(ancestorFacts, 49152, hierarchyFacts & 49152 ? 16384 : 0); + exitSubtree(ancestorFacts, 49152 /* PropagateNewTargetMask */, hierarchyFacts & 49152 /* PropagateNewTargetMask */ ? 16384 /* NewTarget */ : 0 /* None */); return expression; } function visitCatchClause(node) { - var ancestorFacts = enterSubtree(4032, 0); + var ancestorFacts = enterSubtree(4032 /* BlockScopeExcludes */, 0 /* BlockScopeIncludes */); var updated; ts.Debug.assert(!!node.variableDeclaration, "Catch clause variable should always be present when downleveling ES2015."); if (ts.isBindingPattern(node.variableDeclaration.name)) { - var temp = ts.createTempVariable(undefined); + var temp = ts.createTempVariable(/*recordTempVariable*/ undefined); var newVariableDeclaration = ts.createVariableDeclaration(temp); ts.setTextRange(newVariableDeclaration, node.variableDeclaration); - var vars = ts.flattenDestructuringBinding(node.variableDeclaration, visitor, context, 0, temp); + var vars = ts.flattenDestructuringBinding(node.variableDeclaration, visitor, context, 0 /* All */, temp); var list = ts.createVariableDeclarationList(vars); ts.setTextRange(list, node.variableDeclaration); - var destructure = ts.createVariableStatement(undefined, list); + var destructure = ts.createVariableStatement(/*modifiers*/ undefined, list); updated = ts.updateCatchClause(node, newVariableDeclaration, addStatementToStartOfBlock(node.block, destructure)); } else { updated = ts.visitEachChild(node, visitor, context); } - exitSubtree(ancestorFacts, 0, 0); + exitSubtree(ancestorFacts, 0 /* None */, 0 /* None */); return updated; } function addStatementToStartOfBlock(block, statement) { var transformedStatements = ts.visitNodes(block.statements, visitor, ts.isStatement); return ts.updateBlock(block, [statement].concat(transformedStatements)); } + /** + * Visits a MethodDeclaration of an ObjectLiteralExpression and transforms it into a + * PropertyAssignment. + * + * @param node A MethodDeclaration node. + */ function visitMethodDeclaration(node) { + // We should only get here for methods on an object literal with regular identifier names. + // Methods on classes are handled in visitClassDeclaration/visitClassExpression. + // Methods with computed property names are handled in visitObjectLiteralExpression. ts.Debug.assert(!ts.isComputedPropertyName(node.name)); - var functionExpression = transformFunctionLikeToExpression(node, ts.moveRangePos(node, -1), undefined, undefined); - ts.setEmitFlags(functionExpression, 512 | ts.getEmitFlags(functionExpression)); - return ts.setTextRange(ts.createPropertyAssignment(node.name, functionExpression), node); + var functionExpression = transformFunctionLikeToExpression(node, /*location*/ ts.moveRangePos(node, -1), /*name*/ undefined, /*container*/ undefined); + ts.setEmitFlags(functionExpression, 512 /* NoLeadingComments */ | ts.getEmitFlags(functionExpression)); + return ts.setTextRange(ts.createPropertyAssignment(node.name, functionExpression), + /*location*/ node); } + /** + * Visits an AccessorDeclaration of an ObjectLiteralExpression. + * + * @param node An AccessorDeclaration node. + */ function visitAccessorDeclaration(node) { ts.Debug.assert(!ts.isComputedPropertyName(node.name)); var savedConvertedLoopState = convertedLoopState; convertedLoopState = undefined; - var ancestorFacts = enterSubtree(16286, 65); + var ancestorFacts = enterSubtree(16286 /* FunctionExcludes */, 65 /* FunctionIncludes */); var updated; var parameters = ts.visitParameterList(node.parameters, visitor, context); - var body = node.transformFlags & (32768 | 128) + var body = node.transformFlags & (32768 /* ContainsCapturedLexicalThis */ | 128 /* ContainsES2015 */) ? transformFunctionBody(node) : visitFunctionBodyDownLevel(node); - if (node.kind === 156) { + if (node.kind === 156 /* GetAccessor */) { updated = ts.updateGetAccessor(node, node.decorators, node.modifiers, node.name, parameters, node.type, body); } else { updated = ts.updateSetAccessor(node, node.decorators, node.modifiers, node.name, parameters, body); } - exitSubtree(ancestorFacts, 49152, 0); + exitSubtree(ancestorFacts, 49152 /* PropagateNewTargetMask */, 0 /* None */); convertedLoopState = savedConvertedLoopState; return updated; } + /** + * Visits a ShorthandPropertyAssignment and transforms it into a PropertyAssignment. + * + * @param node A ShorthandPropertyAssignment node. + */ function visitShorthandPropertyAssignment(node) { - return ts.setTextRange(ts.createPropertyAssignment(node.name, ts.getSynthesizedClone(node.name)), node); + return ts.setTextRange(ts.createPropertyAssignment(node.name, ts.getSynthesizedClone(node.name)), + /*location*/ node); } function visitComputedPropertyName(node) { - var ancestorFacts = enterSubtree(0, 8192); + var ancestorFacts = enterSubtree(0 /* ComputedPropertyNameExcludes */, 8192 /* ComputedPropertyNameIncludes */); var updated = ts.visitEachChild(node, visitor, context); - exitSubtree(ancestorFacts, 49152, hierarchyFacts & 49152 ? 32768 : 0); + exitSubtree(ancestorFacts, 49152 /* PropagateNewTargetMask */, hierarchyFacts & 49152 /* PropagateNewTargetMask */ ? 32768 /* NewTargetInComputedPropertyName */ : 0 /* None */); return updated; } + /** + * Visits a YieldExpression node. + * + * @param node A YieldExpression node. + */ function visitYieldExpression(node) { + // `yield` expressions are transformed using the generators transformer. return ts.visitEachChild(node, visitor, context); } + /** + * Visits an ArrayLiteralExpression that contains a spread element. + * + * @param node An ArrayLiteralExpression node. + */ function visitArrayLiteralExpression(node) { - if (node.transformFlags & 64) { - return transformAndSpreadElements(node.elements, true, !!node.multiLine, !!node.elements.hasTrailingComma); + if (node.transformFlags & 64 /* ES2015 */) { + // We are here because we contain a SpreadElementExpression. + return transformAndSpreadElements(node.elements, /*needsUniqueCopy*/ true, !!node.multiLine, /*hasTrailingComma*/ !!node.elements.hasTrailingComma); } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a CallExpression that contains either a spread element or `super`. + * + * @param node a CallExpression. + */ function visitCallExpression(node) { - if (ts.getEmitFlags(node) & 33554432) { + if (ts.getEmitFlags(node) & 33554432 /* TypeScriptClassWrapper */) { return visitTypeScriptClassWrapper(node); } - if (node.transformFlags & 64) { - return visitCallExpressionWithPotentialCapturedThisAssignment(node, true); + if (node.transformFlags & 64 /* ES2015 */) { + return visitCallExpressionWithPotentialCapturedThisAssignment(node, /*assignToCapturedThis*/ true); } - return ts.updateCall(node, ts.visitNode(node.expression, callExpressionVisitor, ts.isExpression), undefined, ts.visitNodes(node.arguments, visitor, ts.isExpression)); + return ts.updateCall(node, ts.visitNode(node.expression, callExpressionVisitor, ts.isExpression), + /*typeArguments*/ undefined, ts.visitNodes(node.arguments, visitor, ts.isExpression)); } function visitTypeScriptClassWrapper(node) { + // This is a call to a class wrapper function (an IIFE) created by the 'ts' transformer. + // The wrapper has a form similar to: + // + // (function() { + // class C { // 1 + // } + // C.x = 1; // 2 + // return C; + // }()) + // + // When we transform the class, we end up with something like this: + // + // (function () { + // var C = (function () { // 3 + // function C() { + // } + // return C; // 4 + // }()); + // C.x = 1; + // return C; + // }()) + // + // We want to simplify the two nested IIFEs to end up with something like this: + // + // (function () { + // function C() { + // } + // C.x = 1; + // return C; + // }()) + // We skip any outer expressions in a number of places to get to the innermost + // expression, but we will restore them later to preserve comments and source maps. var body = ts.cast(ts.cast(ts.skipOuterExpressions(node.expression), ts.isArrowFunction).body, ts.isBlock); + // The class statements are the statements generated by visiting the first statement with initializer of the + // body (1), while all other statements are added to remainingStatements (2) var isVariableStatementWithInitializer = function (stmt) { return ts.isVariableStatement(stmt) && !!ts.first(stmt.declarationList.declarations).initializer; }; var bodyStatements = ts.visitNodes(body.statements, visitor, ts.isStatement); var classStatements = ts.filter(bodyStatements, isVariableStatementWithInitializer); var remainingStatements = ts.filter(bodyStatements, function (stmt) { return !isVariableStatementWithInitializer(stmt); }); var varStatement = ts.cast(ts.first(classStatements), ts.isVariableStatement); + // We know there is only one variable declaration here as we verified this in an + // earlier call to isTypeScriptClassWrapper var variable = varStatement.declarationList.declarations[0]; var initializer = ts.skipOuterExpressions(variable.initializer); + // Under certain conditions, the 'ts' transformer may introduce a class alias, which + // we see as an assignment, for example: + // + // (function () { + // var C_1; + // var C = C_1 = (function () { + // function C() { + // } + // C.x = function () { return C_1; } + // return C; + // }()); + // C = C_1 = __decorate([dec], C); + // return C; + // }()) + // var aliasAssignment = ts.tryCast(initializer, ts.isAssignmentExpression); + // The underlying call (3) is another IIFE that may contain a '_super' argument. var call = ts.cast(aliasAssignment ? ts.skipOuterExpressions(aliasAssignment.right) : initializer, ts.isCallExpression); var func = ts.cast(ts.skipOuterExpressions(call.expression), ts.isFunctionExpression); var funcStatements = func.body.statements; @@ -57682,47 +68526,92 @@ var ts; var classBodyEnd = -1; var statements = []; if (aliasAssignment) { + // If we have a class alias assignment, we need to move it to the down-level constructor + // function we generated for the class. var extendsCall = ts.tryCast(funcStatements[classBodyStart], ts.isExpressionStatement); if (extendsCall) { statements.push(extendsCall); classBodyStart++; } + // The next statement is the function declaration. statements.push(funcStatements[classBodyStart]); classBodyStart++; + // Add the class alias following the declaration. statements.push(ts.createStatement(ts.createAssignment(aliasAssignment.left, ts.cast(variable.name, ts.isIdentifier)))); } + // Find the trailing 'return' statement (4) while (!ts.isReturnStatement(ts.elementAt(funcStatements, classBodyEnd))) { classBodyEnd--; } + // When we extract the statements of the inner IIFE, we exclude the 'return' statement (4) + // as we already have one that has been introduced by the 'ts' transformer. ts.addRange(statements, funcStatements, classBodyStart, classBodyEnd); if (classBodyEnd < -1) { + // If there were any hoisted declarations following the return statement, we should + // append them. ts.addRange(statements, funcStatements, classBodyEnd + 1); } + // Add the remaining statements of the outer wrapper. ts.addRange(statements, remainingStatements); - ts.addRange(statements, classStatements, 1); - return ts.recreateOuterExpressions(node.expression, ts.recreateOuterExpressions(variable.initializer, ts.recreateOuterExpressions(aliasAssignment && aliasAssignment.right, ts.updateCall(call, ts.recreateOuterExpressions(call.expression, ts.updateFunctionExpression(func, undefined, undefined, undefined, undefined, func.parameters, undefined, ts.updateBlock(func.body, statements))), undefined, call.arguments)))); + // The 'es2015' class transform may add an end-of-declaration marker. If so we will add it + // after the remaining statements from the 'ts' transformer. + ts.addRange(statements, classStatements, /*start*/ 1); + // Recreate any outer parentheses or partially-emitted expressions to preserve source map + // and comment locations. + return ts.recreateOuterExpressions(node.expression, ts.recreateOuterExpressions(variable.initializer, ts.recreateOuterExpressions(aliasAssignment && aliasAssignment.right, ts.updateCall(call, ts.recreateOuterExpressions(call.expression, ts.updateFunctionExpression(func, + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, func.parameters, + /*type*/ undefined, ts.updateBlock(func.body, statements))), + /*typeArguments*/ undefined, call.arguments)))); } function visitImmediateSuperCallInBody(node) { - return visitCallExpressionWithPotentialCapturedThisAssignment(node, false); + return visitCallExpressionWithPotentialCapturedThisAssignment(node, /*assignToCapturedThis*/ false); } function visitCallExpressionWithPotentialCapturedThisAssignment(node, assignToCapturedThis) { - if (node.transformFlags & 524288 || - node.expression.kind === 97 || + // We are here either because SuperKeyword was used somewhere in the expression, or + // because we contain a SpreadElementExpression. + if (node.transformFlags & 524288 /* ContainsSpread */ || + node.expression.kind === 97 /* SuperKeyword */ || ts.isSuperProperty(ts.skipOuterExpressions(node.expression))) { var _a = ts.createCallBinding(node.expression, hoistVariableDeclaration), target = _a.target, thisArg = _a.thisArg; - if (node.expression.kind === 97) { - ts.setEmitFlags(thisArg, 4); + if (node.expression.kind === 97 /* SuperKeyword */) { + ts.setEmitFlags(thisArg, 4 /* NoSubstitution */); } var resultingCall = void 0; - if (node.transformFlags & 524288) { - resultingCall = ts.createFunctionApply(ts.visitNode(target, callExpressionVisitor, ts.isExpression), ts.visitNode(thisArg, visitor, ts.isExpression), transformAndSpreadElements(node.arguments, false, false, false)); + if (node.transformFlags & 524288 /* ContainsSpread */) { + // [source] + // f(...a, b) + // x.m(...a, b) + // super(...a, b) + // super.m(...a, b) // in static + // super.m(...a, b) // in instance + // + // [output] + // f.apply(void 0, a.concat([b])) + // (_a = x).m.apply(_a, a.concat([b])) + // _super.apply(this, a.concat([b])) + // _super.m.apply(this, a.concat([b])) + // _super.prototype.m.apply(this, a.concat([b])) + resultingCall = ts.createFunctionApply(ts.visitNode(target, callExpressionVisitor, ts.isExpression), ts.visitNode(thisArg, visitor, ts.isExpression), transformAndSpreadElements(node.arguments, /*needsUniqueCopy*/ false, /*multiLine*/ false, /*hasTrailingComma*/ false)); } else { - resultingCall = ts.createFunctionCall(ts.visitNode(target, callExpressionVisitor, ts.isExpression), ts.visitNode(thisArg, visitor, ts.isExpression), ts.visitNodes(node.arguments, visitor, ts.isExpression), node); + // [source] + // super(a) + // super.m(a) // in static + // super.m(a) // in instance + // + // [output] + // _super.call(this, a) + // _super.m.call(this, a) + // _super.prototype.m.call(this, a) + resultingCall = ts.createFunctionCall(ts.visitNode(target, callExpressionVisitor, ts.isExpression), ts.visitNode(thisArg, visitor, ts.isExpression), ts.visitNodes(node.arguments, visitor, ts.isExpression), + /*location*/ node); } - if (node.expression.kind === 97) { + if (node.expression.kind === 97 /* SuperKeyword */) { var actualThis = ts.createThis(); - ts.setEmitFlags(actualThis, 4); + ts.setEmitFlags(actualThis, 4 /* NoSubstitution */); var initializer = ts.createLogicalOr(resultingCall, actualThis); resultingCall = assignToCapturedThis ? ts.createAssignment(ts.createFileLevelUniqueName("_this"), initializer) @@ -57732,14 +68621,40 @@ var ts; } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a NewExpression that contains a spread element. + * + * @param node A NewExpression node. + */ function visitNewExpression(node) { - if (node.transformFlags & 524288) { + if (node.transformFlags & 524288 /* ContainsSpread */) { + // We are here because we contain a SpreadElementExpression. + // [source] + // new C(...a) + // + // [output] + // new ((_a = C).bind.apply(_a, [void 0].concat(a)))() var _a = ts.createCallBinding(ts.createPropertyAccess(node.expression, "bind"), hoistVariableDeclaration), target = _a.target, thisArg = _a.thisArg; - return ts.createNew(ts.createFunctionApply(ts.visitNode(target, visitor, ts.isExpression), thisArg, transformAndSpreadElements(ts.createNodeArray([ts.createVoidZero()].concat(node.arguments)), false, false, false)), undefined, []); + return ts.createNew(ts.createFunctionApply(ts.visitNode(target, visitor, ts.isExpression), thisArg, transformAndSpreadElements(ts.createNodeArray([ts.createVoidZero()].concat(node.arguments)), /*needsUniqueCopy*/ false, /*multiLine*/ false, /*hasTrailingComma*/ false)), + /*typeArguments*/ undefined, []); } return ts.visitEachChild(node, visitor, context); } + /** + * Transforms an array of Expression nodes that contains a SpreadExpression. + * + * @param elements The array of Expression nodes. + * @param needsUniqueCopy A value indicating whether to ensure that the result is a fresh array. + * @param multiLine A value indicating whether the result should be emitted on multiple lines. + */ function transformAndSpreadElements(elements, needsUniqueCopy, multiLine, hasTrailingComma) { + // [source] + // [a, ...b, c] + // + // [output] + // [a].concat(b, [c]) + // Map spans of spread expressions into their expressions and spans of other + // expressions into an array literal. var numElements = elements.length; var segments = ts.flatten(ts.spanMap(elements, partitionSpread, function (partition, visitPartition, _start, end) { return visitPartition(partition, multiLine, hasTrailingComma && end === numElements); @@ -57749,7 +68664,7 @@ var ts; var firstSegment = segments[0]; if (ts.isCallExpression(firstSegment) && ts.isIdentifier(firstSegment.expression) - && (ts.getEmitFlags(firstSegment.expression) & 4096) + && (ts.getEmitFlags(firstSegment.expression) & 4096 /* HelperName */) && firstSegment.expression.escapedText === "___spread") { return segments[0]; } @@ -57759,10 +68674,11 @@ var ts; else { if (segments.length === 1) { var firstElement = elements[0]; - return needsUniqueCopy && ts.isSpreadElement(firstElement) && firstElement.expression.kind !== 183 + return needsUniqueCopy && ts.isSpreadElement(firstElement) && firstElement.expression.kind !== 183 /* ArrayLiteralExpression */ ? ts.createArraySlice(segments[0]) : segments[0]; } + // Rewrite using the pattern .concat(, , ...) return ts.createArrayConcat(segments.shift(), segments); } } @@ -57780,26 +68696,55 @@ var ts; function visitSpreadElement(node) { return ts.visitNode(node.expression, visitor, ts.isExpression); } + /** + * Transforms the expression of a SpreadExpression node. + * + * @param node A SpreadExpression node. + */ function visitExpressionOfSpread(node) { return ts.visitNode(node.expression, visitor, ts.isExpression); } + /** + * Visits a template literal. + * + * @param node A template literal. + */ function visitTemplateLiteral(node) { return ts.setTextRange(ts.createLiteral(node.text), node); } + /** + * Visits a string literal with an extended unicode escape. + * + * @param node A string literal. + */ function visitStringLiteral(node) { if (node.hasExtendedUnicodeEscape) { return ts.setTextRange(ts.createLiteral(node.text), node); } return node; } + /** + * Visits a binary or octal (ES6) numeric literal. + * + * @param node A string literal. + */ function visitNumericLiteral(node) { - if (node.numericLiteralFlags & 384) { + if (node.numericLiteralFlags & 384 /* BinaryOrOctalSpecifier */) { return ts.setTextRange(ts.createNumericLiteral(node.text), node); } return node; } + /** + * Visits a TaggedTemplateExpression node. + * + * @param node A TaggedTemplateExpression node. + */ function visitTaggedTemplateExpression(node) { + // Visit the tag expression var tag = ts.visitNode(node.tag, visitor, ts.isExpression); + // Build up the template arguments and the raw and cooked strings for the template. + // We start out with 'undefined' for the first argument and revisit later + // to avoid walking over the template string twice and shifting all our arguments over after the fact. var templateArguments = [undefined]; var cookedStrings = []; var rawStrings = []; @@ -57819,6 +68764,9 @@ var ts; } } var helperCall = createTemplateObjectHelper(context, ts.createArrayLiteral(cookedStrings), ts.createArrayLiteral(rawStrings)); + // Create a variable to cache the template object if we're in a module. + // Do not do this in the global scope, as any variable we currently generate could conflict with + // variables from outside of the current compilation. In the future, we can revisit this behavior. if (ts.isExternalModule(currentSourceFile)) { var tempVar = ts.createUniqueName("templateObject"); recordTaggedTemplateString(tempVar); @@ -57827,19 +68775,48 @@ var ts; else { templateArguments[0] = helperCall; } - return ts.createCall(tag, undefined, templateArguments); + return ts.createCall(tag, /*typeArguments*/ undefined, templateArguments); } + /** + * Creates an ES5 compatible literal from an ES6 template literal. + * + * @param node The ES6 template literal. + */ function getRawLiteral(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". var text = ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node); - var isLast = node.kind === 13 || node.kind === 16; + // 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 "${" + var isLast = node.kind === 13 /* NoSubstitutionTemplateLiteral */ || node.kind === 16 /* 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"); return ts.setTextRange(ts.createLiteral(text), node); } + /** + * Visits a TemplateExpression node. + * + * @param node A TemplateExpression node. + */ function visitTemplateExpression(node) { var expressions = []; addTemplateHead(expressions, node); addTemplateSpans(expressions, node); + // createAdd will check if each expression binds less closely than binary '+'. + // If it does, it wraps 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) + "" var expression = ts.reduceLeft(expressions, ts.createAdd); if (ts.nodeIsSynthesized(expression)) { expression.pos = node.pos; @@ -57847,76 +68824,137 @@ var ts; } return expression; } + /** + * Gets a value indicating whether we need to include the head of a TemplateExpression. + * + * @param node A TemplateExpression node. + */ function shouldAddTemplateHead(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 }` + // 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() ts.Debug.assert(node.templateSpans.length !== 0); return node.head.text.length !== 0 || node.templateSpans[0].literal.text.length === 0; } + /** + * Adds the head of a TemplateExpression to an array of expressions. + * + * @param expressions An array of expressions. + * @param node A TemplateExpression node. + */ function addTemplateHead(expressions, node) { if (!shouldAddTemplateHead(node)) { return; } expressions.push(ts.createLiteral(node.head.text)); } + /** + * Visits and adds the template spans of a TemplateExpression to an array of expressions. + * + * @param expressions An array of expressions. + * @param node A TemplateExpression node. + */ function addTemplateSpans(expressions, node) { for (var _i = 0, _a = node.templateSpans; _i < _a.length; _i++) { var span = _a[_i]; expressions.push(ts.visitNode(span.expression, visitor, ts.isExpression)); + // 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 (span.literal.text.length !== 0) { expressions.push(ts.createLiteral(span.literal.text)); } } } + /** + * Visits the `super` keyword + */ function visitSuperKeyword(isExpressionOfCall) { - return hierarchyFacts & 8 + return hierarchyFacts & 8 /* NonStaticClassElement */ && !isExpressionOfCall ? ts.createPropertyAccess(ts.createFileLevelUniqueName("_super"), "prototype") : ts.createFileLevelUniqueName("_super"); } function visitMetaProperty(node) { - if (node.keywordToken === 94 && node.name.escapedText === "target") { - if (hierarchyFacts & 8192) { - hierarchyFacts |= 32768; + if (node.keywordToken === 94 /* NewKeyword */ && node.name.escapedText === "target") { + if (hierarchyFacts & 8192 /* ComputedPropertyName */) { + hierarchyFacts |= 32768 /* NewTargetInComputedPropertyName */; } else { - hierarchyFacts |= 16384; + hierarchyFacts |= 16384 /* NewTarget */; } return ts.createFileLevelUniqueName("_newTarget"); } return node; } + /** + * Called by the printer just before a node is printed. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to be printed. + * @param emitCallback The callback used to emit the node. + */ function onEmitNode(hint, node, emitCallback) { - if (enabledSubstitutions & 1 && ts.isFunctionLike(node)) { - var ancestorFacts = enterSubtree(16286, ts.getEmitFlags(node) & 8 - ? 65 | 16 - : 65); + if (enabledSubstitutions & 1 /* CapturedThis */ && ts.isFunctionLike(node)) { + // If we are tracking a captured `this`, keep track of the enclosing function. + var ancestorFacts = enterSubtree(16286 /* FunctionExcludes */, ts.getEmitFlags(node) & 8 /* CapturesThis */ + ? 65 /* FunctionIncludes */ | 16 /* CapturesThis */ + : 65 /* FunctionIncludes */); previousOnEmitNode(hint, node, emitCallback); - exitSubtree(ancestorFacts, 0, 0); + exitSubtree(ancestorFacts, 0 /* None */, 0 /* None */); return; } previousOnEmitNode(hint, node, emitCallback); } + /** + * Enables a more costly code path for substitutions when we determine a source file + * contains block-scoped bindings (e.g. `let` or `const`). + */ function enableSubstitutionsForBlockScopedBindings() { - if ((enabledSubstitutions & 2) === 0) { - enabledSubstitutions |= 2; - context.enableSubstitution(71); + if ((enabledSubstitutions & 2 /* BlockScopedBindings */) === 0) { + enabledSubstitutions |= 2 /* BlockScopedBindings */; + context.enableSubstitution(71 /* Identifier */); } } + /** + * Enables a more costly code path for substitutions when we determine a source file + * contains a captured `this`. + */ function enableSubstitutionsForCapturedThis() { - if ((enabledSubstitutions & 1) === 0) { - enabledSubstitutions |= 1; - context.enableSubstitution(99); - context.enableEmitNotification(155); - context.enableEmitNotification(154); - context.enableEmitNotification(156); - context.enableEmitNotification(157); - context.enableEmitNotification(193); - context.enableEmitNotification(192); - context.enableEmitNotification(234); + if ((enabledSubstitutions & 1 /* CapturedThis */) === 0) { + enabledSubstitutions |= 1 /* CapturedThis */; + context.enableSubstitution(99 /* ThisKeyword */); + context.enableEmitNotification(155 /* Constructor */); + context.enableEmitNotification(154 /* MethodDeclaration */); + context.enableEmitNotification(156 /* GetAccessor */); + context.enableEmitNotification(157 /* SetAccessor */); + context.enableEmitNotification(193 /* ArrowFunction */); + context.enableEmitNotification(192 /* FunctionExpression */); + context.enableEmitNotification(234 /* FunctionDeclaration */); } } + /** + * Hooks node substitutions. + * + * @param hint The context for the emitter. + * @param node The node to substitute. + */ function onSubstituteNode(hint, node) { node = previousOnSubstituteNode(hint, node); - if (hint === 1) { + if (hint === 1 /* Expression */) { return substituteExpression(node); } if (ts.isIdentifier(node)) { @@ -57924,8 +68962,13 @@ var ts; } return node; } + /** + * Hooks substitutions for non-expression identifiers. + */ function substituteIdentifier(node) { - if (enabledSubstitutions & 2 && !ts.isInternalName(node)) { + // Only substitute the identifier if we have enabled substitutions for block-scoped + // bindings. + if (enabledSubstitutions & 2 /* BlockScopedBindings */ && !ts.isInternalName(node)) { var original = ts.getParseTreeNode(node, ts.isIdentifier); if (original && isNameOfDeclarationWithCollidingName(original)) { return ts.setTextRange(ts.getGeneratedNameForNode(original), node); @@ -57933,28 +68976,44 @@ var ts; } return node; } + /** + * Determines whether a name is the name of a declaration with a colliding name. + * NOTE: This function expects to be called with an original source tree node. + * + * @param node An original source tree node. + */ function isNameOfDeclarationWithCollidingName(node) { switch (node.parent.kind) { - case 182: - case 235: - case 238: - case 232: + case 182 /* BindingElement */: + case 235 /* ClassDeclaration */: + case 238 /* EnumDeclaration */: + case 232 /* VariableDeclaration */: return node.parent.name === node && resolver.isDeclarationWithCollidingName(node.parent); } return false; } + /** + * Substitutes an expression. + * + * @param node An Expression node. + */ function substituteExpression(node) { switch (node.kind) { - case 71: + case 71 /* Identifier */: return substituteExpressionIdentifier(node); - case 99: + case 99 /* ThisKeyword */: return substituteThisKeyword(node); } return node; } + /** + * Substitutes an expression identifier. + * + * @param node An Identifier node. + */ function substituteExpressionIdentifier(node) { - if (enabledSubstitutions & 2 && !ts.isInternalName(node)) { + if (enabledSubstitutions & 2 /* BlockScopedBindings */ && !ts.isInternalName(node)) { var declaration = resolver.getReferencedDeclarationWithCollidingName(node); if (declaration && !(ts.isClassLike(declaration) && isPartOfClassBody(declaration, node))) { return ts.setTextRange(ts.getGeneratedNameForNode(ts.getNameOfDeclaration(declaration)), node); @@ -57965,11 +69024,17 @@ var ts; function isPartOfClassBody(declaration, node) { var currentNode = ts.getParseTreeNode(node); if (!currentNode || currentNode === declaration || currentNode.end <= declaration.pos || currentNode.pos >= declaration.end) { + // if the node has no correlation to a parse tree node, its definitely not + // part of the body. + // if the node is outside of the document range of the declaration, its + // definitely not part of the body. return false; } var blockScope = ts.getEnclosingBlockScopeContainer(declaration); while (currentNode) { if (currentNode === blockScope || currentNode === declaration) { + // if we are in the enclosing block scope of the declaration, we are definitely + // not inside the class body. return false; } if (ts.isClassElement(currentNode) && currentNode.parent === declaration) { @@ -57979,15 +69044,20 @@ var ts; } return false; } + /** + * Substitutes `this` when contained within an arrow function. + * + * @param node The ThisKeyword node. + */ function substituteThisKeyword(node) { - if (enabledSubstitutions & 1 - && hierarchyFacts & 16) { + if (enabledSubstitutions & 1 /* CapturedThis */ + && hierarchyFacts & 16 /* CapturesThis */) { return ts.setTextRange(ts.createFileLevelUniqueName("_this"), node); } return node; } function getClassMemberPrefix(node, member) { - return ts.hasModifier(member, 32) + return ts.hasModifier(member, 32 /* Static */) ? ts.getInternalName(node) : ts.createPropertyAccess(ts.getInternalName(node), "prototype"); } @@ -57999,19 +69069,19 @@ var ts; return false; } var statement = ts.firstOrUndefined(constructor.body.statements); - if (!statement || !ts.nodeIsSynthesized(statement) || statement.kind !== 216) { + if (!statement || !ts.nodeIsSynthesized(statement) || statement.kind !== 216 /* ExpressionStatement */) { return false; } var statementExpression = statement.expression; - if (!ts.nodeIsSynthesized(statementExpression) || statementExpression.kind !== 187) { + if (!ts.nodeIsSynthesized(statementExpression) || statementExpression.kind !== 187 /* CallExpression */) { return false; } var callTarget = statementExpression.expression; - if (!ts.nodeIsSynthesized(callTarget) || callTarget.kind !== 97) { + if (!ts.nodeIsSynthesized(callTarget) || callTarget.kind !== 97 /* SuperKeyword */) { return false; } var callArgument = ts.singleOrUndefined(statementExpression.arguments); - if (!callArgument || !ts.nodeIsSynthesized(callArgument) || callArgument.kind !== 204) { + if (!callArgument || !ts.nodeIsSynthesized(callArgument) || callArgument.kind !== 204 /* SpreadElement */) { return false; } var expression = callArgument.expression; @@ -58021,14 +69091,16 @@ var ts; ts.transformES2015 = transformES2015; function createExtendsHelper(context, name) { context.requestEmitHelper(extendsHelper); - return ts.createCall(ts.getHelperName("__extends"), undefined, [ + return ts.createCall(ts.getHelperName("__extends"), + /*typeArguments*/ undefined, [ name, ts.createFileLevelUniqueName("_super") ]); } function createTemplateObjectHelper(context, cooked, raw) { context.requestEmitHelper(templateObjectHelper); - return ts.createCall(ts.getHelperName("__makeTemplateObject"), undefined, [ + return ts.createCall(ts.getHelperName("__makeTemplateObject"), + /*typeArguments*/ undefined, [ cooked, raw ]); @@ -58037,7 +69109,7 @@ var ts; name: "typescript:extends", scoped: false, priority: 0, - text: "\n var __extends = (this && this.__extends) || (function () {\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n })();" + text: "\n var __extends = (this && this.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n }\n\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n })();" }; var templateObjectHelper = { name: "typescript:makeTemplateObject", @@ -58046,39 +69118,64 @@ var ts; text: "\n var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\n return cooked;\n };" }; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { + /** + * Transforms ES5 syntax into ES3 syntax. + * + * @param context Context and state information for the transformation. + */ function transformES5(context) { var compilerOptions = context.getCompilerOptions(); + // enable emit notification only if using --jsx preserve or react-native var previousOnEmitNode; var noSubstitution; - if (compilerOptions.jsx === 1 || compilerOptions.jsx === 3) { + if (compilerOptions.jsx === 1 /* Preserve */ || compilerOptions.jsx === 3 /* ReactNative */) { previousOnEmitNode = context.onEmitNode; context.onEmitNode = onEmitNode; - context.enableEmitNotification(257); - context.enableEmitNotification(258); - context.enableEmitNotification(256); + context.enableEmitNotification(257 /* JsxOpeningElement */); + context.enableEmitNotification(258 /* JsxClosingElement */); + context.enableEmitNotification(256 /* JsxSelfClosingElement */); noSubstitution = []; } var previousOnSubstituteNode = context.onSubstituteNode; context.onSubstituteNode = onSubstituteNode; - context.enableSubstitution(185); - context.enableSubstitution(270); + context.enableSubstitution(185 /* PropertyAccessExpression */); + context.enableSubstitution(270 /* PropertyAssignment */); return ts.chainBundle(transformSourceFile); + /** + * Transforms an ES5 source file to ES3. + * + * @param node A SourceFile + */ function transformSourceFile(node) { return node; } + /** + * Called by the printer just before a node is printed. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emitCallback A callback used to emit the node. + */ function onEmitNode(hint, node, emitCallback) { switch (node.kind) { - case 257: - case 258: - case 256: + case 257 /* JsxOpeningElement */: + case 258 /* JsxClosingElement */: + case 256 /* JsxSelfClosingElement */: var tagName = node.tagName; noSubstitution[ts.getOriginalNodeId(tagName)] = true; break; } previousOnEmitNode(hint, node, emitCallback); } + /** + * Hooks node substitutions. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to substitute. + */ function onSubstituteNode(hint, node) { if (node.id && noSubstitution && noSubstitution[node.id]) { return previousOnSubstituteNode(hint, node); @@ -58092,6 +69189,11 @@ var ts; } return node; } + /** + * Substitutes a PropertyAccessExpression whose name is a reserved word. + * + * @param node A PropertyAccessExpression + */ function substitutePropertyAccessExpression(node) { var literalName = trySubstituteReservedName(node.name); if (literalName) { @@ -58099,6 +69201,11 @@ var ts; } return node; } + /** + * Substitutes a PropertyAssignment whose name is a reserved word. + * + * @param node A PropertyAssignment + */ function substitutePropertyAssignment(node) { var literalName = ts.isIdentifier(node.name) && trySubstituteReservedName(node.name); if (literalName) { @@ -58106,9 +69213,14 @@ var ts; } return node; } + /** + * If an identifier name is a reserved word, returns a string literal for the name. + * + * @param name An Identifier + */ function trySubstituteReservedName(name) { var token = name.originalKeywordKind || (ts.nodeIsSynthesized(name) ? ts.stringToToken(ts.idText(name)) : undefined); - if (token !== undefined && token >= 72 && token <= 107) { + if (token !== undefined && token >= 72 /* FirstReservedWord */ && token <= 107 /* LastReservedWord */) { return ts.setTextRange(ts.createLiteral(name), name); } return undefined; @@ -58116,6 +69228,125 @@ var ts; } ts.transformES5 = transformES5; })(ts || (ts = {})); +// Transforms generator functions into a compatible ES5 representation with similar runtime +// semantics. This is accomplished by first transforming the body of each generator +// function into an intermediate representation that is the compiled into a JavaScript +// switch statement. +// +// Many functions in this transformer will contain comments indicating the expected +// intermediate representation. For illustrative purposes, the following intermediate +// language is used to define this intermediate representation: +// +// .nop - Performs no operation. +// .local NAME, ... - Define local variable declarations. +// .mark LABEL - Mark the location of a label. +// .br LABEL - Jump to a label. If jumping out of a protected +// region, all .finally blocks are executed. +// .brtrue LABEL, (x) - Jump to a label IIF the expression `x` is truthy. +// If jumping out of a protected region, all .finally +// blocks are executed. +// .brfalse LABEL, (x) - Jump to a label IIF the expression `x` is falsey. +// If jumping out of a protected region, all .finally +// blocks are executed. +// .yield (x) - Yield the value of the optional expression `x`. +// Resume at the next label. +// .yieldstar (x) - Delegate yield to the value of the optional +// expression `x`. Resume at the next label. +// NOTE: `x` must be an Iterator, not an Iterable. +// .loop CONTINUE, BREAK - Marks the beginning of a loop. Any "continue" or +// "break" abrupt completions jump to the CONTINUE or +// BREAK labels, respectively. +// .endloop - Marks the end of a loop. +// .with (x) - Marks the beginning of a WithStatement block, using +// the supplied expression. +// .endwith - Marks the end of a WithStatement. +// .switch - Marks the beginning of a SwitchStatement. +// .endswitch - Marks the end of a SwitchStatement. +// .labeled NAME - Marks the beginning of a LabeledStatement with the +// supplied name. +// .endlabeled - Marks the end of a LabeledStatement. +// .try TRY, CATCH, FINALLY, END - Marks the beginning of a protected region, and the +// labels for each block. +// .catch (x) - Marks the beginning of a catch block. +// .finally - Marks the beginning of a finally block. +// .endfinally - Marks the end of a finally block. +// .endtry - Marks the end of a protected region. +// .throw (x) - Throws the value of the expression `x`. +// .return (x) - Returns the value of the expression `x`. +// +// In addition, the illustrative intermediate representation introduces some special +// variables: +// +// %sent% - Either returns the next value sent to the generator, +// returns the result of a delegated yield, or throws +// the exception sent to the generator. +// %error% - Returns the value of the current exception in a +// catch block. +// +// This intermediate representation is then compiled into JavaScript syntax. The resulting +// compilation output looks something like the following: +// +// function f() { +// var /*locals*/; +// /*functions*/ +// return __generator(function (state) { +// switch (state.label) { +// /*cases per label*/ +// } +// }); +// } +// +// Each of the above instructions corresponds to JavaScript emit similar to the following: +// +// .local NAME | var NAME; +// -------------------------------|---------------------------------------------- +// .mark LABEL | case LABEL: +// -------------------------------|---------------------------------------------- +// .br LABEL | return [3 /*break*/, LABEL]; +// -------------------------------|---------------------------------------------- +// .brtrue LABEL, (x) | if (x) return [3 /*break*/, LABEL]; +// -------------------------------|---------------------------------------------- +// .brfalse LABEL, (x) | if (!(x)) return [3, /*break*/, LABEL]; +// -------------------------------|---------------------------------------------- +// .yield (x) | return [4 /*yield*/, x]; +// .mark RESUME | case RESUME: +// a = %sent%; | a = state.sent(); +// -------------------------------|---------------------------------------------- +// .yieldstar (x) | return [5 /*yield**/, x]; +// .mark RESUME | case RESUME: +// a = %sent%; | a = state.sent(); +// -------------------------------|---------------------------------------------- +// .with (_a) | with (_a) { +// a(); | a(); +// | } +// | state.label = LABEL; +// .mark LABEL | case LABEL: +// | with (_a) { +// b(); | b(); +// | } +// .endwith | +// -------------------------------|---------------------------------------------- +// | case 0: +// | state.trys = []; +// | ... +// .try TRY, CATCH, FINALLY, END | +// .mark TRY | case TRY: +// | state.trys.push([TRY, CATCH, FINALLY, END]); +// .nop | +// a(); | a(); +// .br END | return [3 /*break*/, END]; +// .catch (e) | +// .mark CATCH | case CATCH: +// | e = state.sent(); +// b(); | b(); +// .br END | return [3 /*break*/, END]; +// .finally | +// .mark FINALLY | case FINALLY: +// c(); | c(); +// .endfinally | return [7 /*endfinally*/]; +// .endtry | +// .mark END | case END: +/*@internal*/ var ts; (function (ts) { var OpCode; @@ -58130,13 +69361,15 @@ var ts; OpCode[OpCode["YieldStar"] = 7] = "YieldStar"; OpCode[OpCode["Return"] = 8] = "Return"; OpCode[OpCode["Throw"] = 9] = "Throw"; - OpCode[OpCode["Endfinally"] = 10] = "Endfinally"; + OpCode[OpCode["Endfinally"] = 10] = "Endfinally"; // Marks the end of a `finally` block })(OpCode || (OpCode = {})); + // whether a generated code block is opening or closing at the current operation for a FunctionBuilder var BlockAction; (function (BlockAction) { BlockAction[BlockAction["Open"] = 0] = "Open"; BlockAction[BlockAction["Close"] = 1] = "Close"; })(BlockAction || (BlockAction = {})); + // the kind for a generated code block in a FunctionBuilder var CodeBlockKind; (function (CodeBlockKind) { CodeBlockKind[CodeBlockKind["Exception"] = 0] = "Exception"; @@ -58145,6 +69378,7 @@ var ts; CodeBlockKind[CodeBlockKind["Loop"] = 3] = "Loop"; CodeBlockKind[CodeBlockKind["Labeled"] = 4] = "Labeled"; })(CodeBlockKind || (CodeBlockKind = {})); + // the state for a generated code exception block var ExceptionBlockState; (function (ExceptionBlockState) { ExceptionBlockState[ExceptionBlockState["Try"] = 0] = "Try"; @@ -58152,6 +69386,7 @@ var ts; ExceptionBlockState[ExceptionBlockState["Finally"] = 2] = "Finally"; ExceptionBlockState[ExceptionBlockState["Done"] = 3] = "Done"; })(ExceptionBlockState || (ExceptionBlockState = {})); + // NOTE: changes to this enum should be reflected in the __generator helper. var Instruction; (function (Instruction) { Instruction[Instruction["Next"] = 0] = "Next"; @@ -58165,12 +69400,12 @@ var ts; })(Instruction || (Instruction = {})); function getInstructionName(instruction) { switch (instruction) { - case 2: return "return"; - case 3: return "break"; - case 4: return "yield"; - case 5: return "yield*"; - case 7: return "endfinally"; - default: return undefined; + case 2 /* Return */: return "return"; + case 3 /* Break */: return "break"; + case 4 /* Yield */: return "yield"; + case 5 /* YieldStar */: return "yield*"; + case 7 /* Endfinally */: return "endfinally"; + default: return undefined; // TODO: GH#18217 } } function transformGenerators(context) { @@ -58184,36 +69419,57 @@ var ts; var renamedCatchVariableDeclarations; var inGeneratorFunctionBody; var inStatementContainingYield; - var blocks; - var blockOffsets; - var blockActions; - var blockStack; - var labelOffsets; - var labelExpressions; - var nextLabelId = 1; - var operations; - var operationArguments; - var operationLocations; - var state; - var blockIndex = 0; - var labelNumber = 0; + // The following three arrays store information about generated code blocks. + // All three arrays are correlated by their index. This approach is used over allocating + // objects to store the same information to avoid GC overhead. + // + var blocks; // Information about the code block + var blockOffsets; // The operation offset at which a code block begins or ends + var blockActions; // Whether the code block is opened or closed + var blockStack; // A stack of currently open code blocks + // Labels are used to mark locations in the code that can be the target of a Break (jump) + // operation. These are translated into case clauses in a switch statement. + // The following two arrays are correlated by their index. This approach is used over + // allocating objects to store the same information to avoid GC overhead. + // + var labelOffsets; // The operation offset at which the label is defined. + var labelExpressions; // The NumericLiteral nodes bound to each label. + var nextLabelId = 1; // The next label id to use. + // Operations store information about generated code for the function body. This + // Includes things like statements, assignments, breaks (jumps), and yields. + // The following three arrays are correlated by their index. This approach is used over + // allocating objects to store the same information to avoid GC overhead. + // + var operations; // The operation to perform. + var operationArguments; // The arguments to the operation. + var operationLocations; // The source map location for the operation. + var state; // The name of the state object used by the generator at runtime. + // The following variables store information used by the `build` function: + // + var blockIndex = 0; // The index of the current block. + var labelNumber = 0; // The current label number. var labelNumbers; - var lastOperationWasAbrupt; - var lastOperationWasCompletion; - var clauses; - var statements; - var exceptionBlockStack; - var currentExceptionBlock; - var withBlockStack; + var lastOperationWasAbrupt; // Indicates whether the last operation was abrupt (break/continue). + var lastOperationWasCompletion; // Indicates whether the last operation was a completion (return/throw). + var clauses; // The case clauses generated for labels. + var statements; // The statements for the current label. + var exceptionBlockStack; // A stack of containing exception blocks. + var currentExceptionBlock; // The current exception block. + var withBlockStack; // A stack containing `with` blocks. return ts.chainBundle(transformSourceFile); function transformSourceFile(node) { - if (node.isDeclarationFile || (node.transformFlags & 512) === 0) { + if (node.isDeclarationFile || (node.transformFlags & 512 /* ContainsGenerator */) === 0) { return node; } var visited = ts.visitEachChild(node, visitor, context); ts.addEmitHelpers(visited, context.readEmitHelpers()); return visited; } + /** + * Visits a node. + * + * @param node The node to visit. + */ function visitor(node) { var transformFlags = node.transformFlags; if (inStatementContainingYield) { @@ -58222,56 +69478,66 @@ var ts; else if (inGeneratorFunctionBody) { return visitJavaScriptInGeneratorFunctionBody(node); } - else if (transformFlags & 256) { + else if (transformFlags & 256 /* Generator */) { return visitGenerator(node); } - else if (transformFlags & 512) { + else if (transformFlags & 512 /* ContainsGenerator */) { return ts.visitEachChild(node, visitor, context); } else { return node; } } + /** + * Visits a node that is contained within a statement that contains yield. + * + * @param node The node to visit. + */ function visitJavaScriptInStatementContainingYield(node) { switch (node.kind) { - case 218: + case 218 /* DoStatement */: return visitDoStatement(node); - case 219: + case 219 /* WhileStatement */: return visitWhileStatement(node); - case 227: + case 227 /* SwitchStatement */: return visitSwitchStatement(node); - case 228: + case 228 /* LabeledStatement */: return visitLabeledStatement(node); default: return visitJavaScriptInGeneratorFunctionBody(node); } } + /** + * Visits a node that is contained within a generator function. + * + * @param node The node to visit. + */ function visitJavaScriptInGeneratorFunctionBody(node) { switch (node.kind) { - case 234: + case 234 /* FunctionDeclaration */: return visitFunctionDeclaration(node); - case 192: + case 192 /* FunctionExpression */: return visitFunctionExpression(node); - case 156: - case 157: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return visitAccessorDeclaration(node); - case 214: + case 214 /* VariableStatement */: return visitVariableStatement(node); - case 220: + case 220 /* ForStatement */: return visitForStatement(node); - case 221: + case 221 /* ForInStatement */: return visitForInStatement(node); - case 224: + case 224 /* BreakStatement */: return visitBreakStatement(node); - case 223: + case 223 /* ContinueStatement */: return visitContinueStatement(node); - case 225: + case 225 /* ReturnStatement */: return visitReturnStatement(node); default: - if (node.transformFlags & 16777216) { + if (node.transformFlags & 16777216 /* ContainsYield */) { return visitJavaScriptContainingYield(node); } - else if (node.transformFlags & (512 | 33554432)) { + else if (node.transformFlags & (512 /* ContainsGenerator */ | 33554432 /* ContainsHoistedDeclarationOrCompletion */)) { return ts.visitEachChild(node, visitor, context); } else { @@ -58279,41 +69545,66 @@ var ts; } } } + /** + * Visits a node that contains a YieldExpression. + * + * @param node The node to visit. + */ function visitJavaScriptContainingYield(node) { switch (node.kind) { - case 200: + case 200 /* BinaryExpression */: return visitBinaryExpression(node); - case 201: + case 201 /* ConditionalExpression */: return visitConditionalExpression(node); - case 203: + case 203 /* YieldExpression */: return visitYieldExpression(node); - case 183: + case 183 /* ArrayLiteralExpression */: return visitArrayLiteralExpression(node); - case 184: + case 184 /* ObjectLiteralExpression */: return visitObjectLiteralExpression(node); - case 186: + case 186 /* ElementAccessExpression */: return visitElementAccessExpression(node); - case 187: + case 187 /* CallExpression */: return visitCallExpression(node); - case 188: + case 188 /* NewExpression */: return visitNewExpression(node); default: return ts.visitEachChild(node, visitor, context); } } + /** + * Visits a generator function. + * + * @param node The node to visit. + */ function visitGenerator(node) { switch (node.kind) { - case 234: + case 234 /* FunctionDeclaration */: return visitFunctionDeclaration(node); - case 192: + case 192 /* FunctionExpression */: return visitFunctionExpression(node); default: return ts.Debug.failBadSyntaxKind(node); } } + /** + * Visits a function declaration. + * + * This will be called when one of the following conditions are met: + * - The function declaration is a generator function. + * - The function declaration is contained within the body of a generator function. + * + * @param node The node to visit. + */ function visitFunctionDeclaration(node) { + // Currently, we only support generators that were originally async functions. if (node.asteriskToken) { - node = ts.setOriginalNode(ts.setTextRange(ts.createFunctionDeclaration(undefined, node.modifiers, undefined, node.name, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, transformGeneratorFunctionBody(node.body)), node), node); + node = ts.setOriginalNode(ts.setTextRange(ts.createFunctionDeclaration( + /*decorators*/ undefined, node.modifiers, + /*asteriskToken*/ undefined, node.name, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, transformGeneratorFunctionBody(node.body)), + /*location*/ node), node); } else { var savedInGeneratorFunctionBody = inGeneratorFunctionBody; @@ -58325,6 +69616,8 @@ var ts; inStatementContainingYield = savedInStatementContainingYield; } if (inGeneratorFunctionBody) { + // Function declarations in a generator function body are hoisted + // to the top of the lexical scope and elided from the current statement. hoistFunctionDeclaration(node); return undefined; } @@ -58332,9 +69625,24 @@ var ts; return node; } } + /** + * Visits a function expression. + * + * This will be called when one of the following conditions are met: + * - The function expression is a generator function. + * - The function expression is contained within the body of a generator function. + * + * @param node The node to visit. + */ function visitFunctionExpression(node) { + // Currently, we only support generators that were originally async functions. if (node.asteriskToken) { - node = ts.setOriginalNode(ts.setTextRange(ts.createFunctionExpression(undefined, undefined, node.name, undefined, ts.visitParameterList(node.parameters, visitor, context), undefined, transformGeneratorFunctionBody(node.body)), node), node); + node = ts.setOriginalNode(ts.setTextRange(ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, node.name, + /*typeParameters*/ undefined, ts.visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, transformGeneratorFunctionBody(node.body)), + /*location*/ node), node); } else { var savedInGeneratorFunctionBody = inGeneratorFunctionBody; @@ -58347,6 +69655,14 @@ var ts; } return node; } + /** + * Visits a get or set accessor declaration. + * + * This will be called when one of the following conditions are met: + * - The accessor is contained within the body of a generator function. + * + * @param node The node to visit. + */ function visitAccessorDeclaration(node) { var savedInGeneratorFunctionBody = inGeneratorFunctionBody; var savedInStatementContainingYield = inStatementContainingYield; @@ -58357,7 +69673,13 @@ var ts; inStatementContainingYield = savedInStatementContainingYield; return node; } + /** + * Transforms the body of a generator function declaration. + * + * @param node The function body to transform. + */ function transformGeneratorFunctionBody(body) { + // Save existing generator state var statements = []; var savedInGeneratorFunctionBody = inGeneratorFunctionBody; var savedInStatementContainingYield = inStatementContainingYield; @@ -58372,6 +69694,7 @@ var ts; var savedOperationArguments = operationArguments; var savedOperationLocations = operationLocations; var savedState = state; + // Initialize generator state inGeneratorFunctionBody = true; inStatementContainingYield = false; blocks = undefined; @@ -58384,13 +69707,15 @@ var ts; operations = undefined; operationArguments = undefined; operationLocations = undefined; - state = ts.createTempVariable(undefined); + state = ts.createTempVariable(/*recordTempVariable*/ undefined); + // Build the generator resumeLexicalEnvironment(); - var statementOffset = ts.addPrologue(statements, body.statements, false, visitor); + var statementOffset = ts.addPrologue(statements, body.statements, /*ensureUseStrict*/ false, visitor); transformAndEmitStatements(body.statements, statementOffset); var buildResult = build(); ts.prependStatements(statements, endLexicalEnvironment()); statements.push(ts.createReturn(buildResult)); + // Restore previous generator state inGeneratorFunctionBody = savedInGeneratorFunctionBody; inStatementContainingYield = savedInStatementContainingYield; blocks = savedBlocks; @@ -58406,13 +69731,22 @@ var ts; state = savedState; return ts.setTextRange(ts.createBlock(statements, body.multiLine), body); } + /** + * Visits a variable statement. + * + * This will be called when one of the following conditions are met: + * - The variable statement is contained within the body of a generator function. + * + * @param node The node to visit. + */ function visitVariableStatement(node) { - if (node.transformFlags & 16777216) { + if (node.transformFlags & 16777216 /* ContainsYield */) { transformAndEmitVariableDeclarationList(node.declarationList); return undefined; } else { - if (ts.getEmitFlags(node) & 1048576) { + // Do not hoist custom prologues. + if (ts.getEmitFlags(node) & 1048576 /* CustomPrologue */) { return node; } for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) { @@ -58426,46 +69760,78 @@ var ts; return ts.setSourceMapRange(ts.createStatement(ts.inlineExpressions(ts.map(variables, transformInitializedVariable))), node); } } + /** + * Visits a binary expression. + * + * This will be called when one of the following conditions are met: + * - The node contains a YieldExpression. + * + * @param node The node to visit. + */ function visitBinaryExpression(node) { var assoc = ts.getExpressionAssociativity(node); switch (assoc) { - case 0: + case 0 /* Left */: return visitLeftAssociativeBinaryExpression(node); - case 1: + case 1 /* Right */: return visitRightAssociativeBinaryExpression(node); default: return ts.Debug.assertNever(assoc); } } function isCompoundAssignment(kind) { - return kind >= 59 - && kind <= 70; + return kind >= 59 /* FirstCompoundAssignment */ + && kind <= 70 /* LastCompoundAssignment */; } function getOperatorForCompoundAssignment(kind) { switch (kind) { - case 59: return 37; - case 60: return 38; - case 61: return 39; - case 62: return 40; - case 63: return 41; - case 64: return 42; - case 65: return 45; - case 66: return 46; - case 67: return 47; - case 68: return 48; - case 69: return 49; - case 70: return 50; + case 59 /* PlusEqualsToken */: return 37 /* PlusToken */; + case 60 /* MinusEqualsToken */: return 38 /* MinusToken */; + case 61 /* AsteriskEqualsToken */: return 39 /* AsteriskToken */; + case 62 /* AsteriskAsteriskEqualsToken */: return 40 /* AsteriskAsteriskToken */; + case 63 /* SlashEqualsToken */: return 41 /* SlashToken */; + case 64 /* PercentEqualsToken */: return 42 /* PercentToken */; + case 65 /* LessThanLessThanEqualsToken */: return 45 /* LessThanLessThanToken */; + case 66 /* GreaterThanGreaterThanEqualsToken */: return 46 /* GreaterThanGreaterThanToken */; + case 67 /* GreaterThanGreaterThanGreaterThanEqualsToken */: return 47 /* GreaterThanGreaterThanGreaterThanToken */; + case 68 /* AmpersandEqualsToken */: return 48 /* AmpersandToken */; + case 69 /* BarEqualsToken */: return 49 /* BarToken */; + case 70 /* CaretEqualsToken */: return 50 /* CaretToken */; } } + /** + * Visits a right-associative binary expression containing `yield`. + * + * @param node The node to visit. + */ function visitRightAssociativeBinaryExpression(node) { var left = node.left, right = node.right; if (containsYield(right)) { var target = void 0; switch (left.kind) { - case 185: + case 185 /* PropertyAccessExpression */: + // [source] + // a.b = yield; + // + // [intermediate] + // .local _a + // _a = a; + // .yield resumeLabel + // .mark resumeLabel + // _a.b = %sent%; target = ts.updatePropertyAccess(left, cacheExpression(ts.visitNode(left.expression, visitor, ts.isLeftHandSideExpression)), left.name); break; - case 186: + case 186 /* ElementAccessExpression */: + // [source] + // a[b] = yield; + // + // [intermediate] + // .local _a, _b + // _a = a; + // _b = b; + // .yield resumeLabel + // .mark resumeLabel + // _a[_b] = %sent%; target = ts.updateElementAccess(left, cacheExpression(ts.visitNode(left.expression, visitor, ts.isLeftHandSideExpression)), cacheExpression(ts.visitNode(left.argumentExpression, visitor, ts.isExpression))); break; default: @@ -58487,9 +69853,17 @@ var ts; if (ts.isLogicalOperator(node.operatorToken.kind)) { return visitLogicalBinaryExpression(node); } - else if (node.operatorToken.kind === 26) { + else if (node.operatorToken.kind === 26 /* CommaToken */) { return visitCommaExpression(node); } + // [source] + // a() + (yield) + c() + // + // [intermediate] + // .local _a + // _a = a(); + // .yield resumeLabel + // _a + %sent% + c() var clone_4 = ts.getMutableClone(node); clone_4.left = cacheExpression(ts.visitNode(node.left, visitor, ts.isExpression)); clone_4.right = ts.visitNode(node.right, visitor, ts.isExpression); @@ -58497,73 +69871,176 @@ var ts; } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a logical binary expression containing `yield`. + * + * @param node A node to visit. + */ function visitLogicalBinaryExpression(node) { + // Logical binary expressions (`&&` and `||`) are shortcutting expressions and need + // to be transformed as such: + // + // [source] + // x = a() && yield; + // + // [intermediate] + // .local _a + // _a = a(); + // .brfalse resultLabel, (_a) + // .yield resumeLabel + // .mark resumeLabel + // _a = %sent%; + // .mark resultLabel + // x = _a; + // + // [source] + // x = a() || yield; + // + // [intermediate] + // .local _a + // _a = a(); + // .brtrue resultLabel, (_a) + // .yield resumeLabel + // .mark resumeLabel + // _a = %sent%; + // .mark resultLabel + // x = _a; var resultLabel = defineLabel(); var resultLocal = declareLocal(); - emitAssignment(resultLocal, ts.visitNode(node.left, visitor, ts.isExpression), node.left); - if (node.operatorToken.kind === 53) { - emitBreakWhenFalse(resultLabel, resultLocal, node.left); + emitAssignment(resultLocal, ts.visitNode(node.left, visitor, ts.isExpression), /*location*/ node.left); + if (node.operatorToken.kind === 53 /* AmpersandAmpersandToken */) { + // Logical `&&` shortcuts when the left-hand operand is falsey. + emitBreakWhenFalse(resultLabel, resultLocal, /*location*/ node.left); } else { - emitBreakWhenTrue(resultLabel, resultLocal, node.left); + // Logical `||` shortcuts when the left-hand operand is truthy. + emitBreakWhenTrue(resultLabel, resultLocal, /*location*/ node.left); } - emitAssignment(resultLocal, ts.visitNode(node.right, visitor, ts.isExpression), node.right); + emitAssignment(resultLocal, ts.visitNode(node.right, visitor, ts.isExpression), /*location*/ node.right); markLabel(resultLabel); return resultLocal; } + /** + * Visits a comma expression containing `yield`. + * + * @param node The node to visit. + */ function visitCommaExpression(node) { + // [source] + // x = a(), yield, b(); + // + // [intermediate] + // a(); + // .yield resumeLabel + // .mark resumeLabel + // x = %sent%, b(); var pendingExpressions = []; visit(node.left); visit(node.right); return ts.inlineExpressions(pendingExpressions); function visit(node) { - if (ts.isBinaryExpression(node) && node.operatorToken.kind === 26) { + if (ts.isBinaryExpression(node) && node.operatorToken.kind === 26 /* CommaToken */) { visit(node.left); visit(node.right); } else { if (containsYield(node) && pendingExpressions.length > 0) { - emitWorker(1, [ts.createStatement(ts.inlineExpressions(pendingExpressions))]); + emitWorker(1 /* Statement */, [ts.createStatement(ts.inlineExpressions(pendingExpressions))]); pendingExpressions = []; } pendingExpressions.push(ts.visitNode(node, visitor, ts.isExpression)); } } } + /** + * Visits a conditional expression containing `yield`. + * + * @param node The node to visit. + */ function visitConditionalExpression(node) { + // [source] + // x = a() ? yield : b(); + // + // [intermediate] + // .local _a + // .brfalse whenFalseLabel, (a()) + // .yield resumeLabel + // .mark resumeLabel + // _a = %sent%; + // .br resultLabel + // .mark whenFalseLabel + // _a = b(); + // .mark resultLabel + // x = _a; + // We only need to perform a specific transformation if a `yield` expression exists + // in either the `whenTrue` or `whenFalse` branches. + // A `yield` in the condition will be handled by the normal visitor. if (containsYield(node.whenTrue) || containsYield(node.whenFalse)) { var whenFalseLabel = defineLabel(); var resultLabel = defineLabel(); var resultLocal = declareLocal(); - emitBreakWhenFalse(whenFalseLabel, ts.visitNode(node.condition, visitor, ts.isExpression), node.condition); - emitAssignment(resultLocal, ts.visitNode(node.whenTrue, visitor, ts.isExpression), node.whenTrue); + emitBreakWhenFalse(whenFalseLabel, ts.visitNode(node.condition, visitor, ts.isExpression), /*location*/ node.condition); + emitAssignment(resultLocal, ts.visitNode(node.whenTrue, visitor, ts.isExpression), /*location*/ node.whenTrue); emitBreak(resultLabel); markLabel(whenFalseLabel); - emitAssignment(resultLocal, ts.visitNode(node.whenFalse, visitor, ts.isExpression), node.whenFalse); + emitAssignment(resultLocal, ts.visitNode(node.whenFalse, visitor, ts.isExpression), /*location*/ node.whenFalse); markLabel(resultLabel); return resultLocal; } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a `yield` expression. + * + * @param node The node to visit. + */ function visitYieldExpression(node) { + // [source] + // x = yield a(); + // + // [intermediate] + // .yield resumeLabel, (a()) + // .mark resumeLabel + // x = %sent%; var resumeLabel = defineLabel(); var expression = ts.visitNode(node.expression, visitor, ts.isExpression); if (node.asteriskToken) { - var iterator = (ts.getEmitFlags(node.expression) & 8388608) === 0 - ? ts.createValuesHelper(context, expression, node) + var iterator = (ts.getEmitFlags(node.expression) & 8388608 /* Iterator */) === 0 + ? ts.createValuesHelper(context, expression, /*location*/ node) : expression; - emitYieldStar(iterator, node); + emitYieldStar(iterator, /*location*/ node); } else { - emitYield(expression, node); + emitYield(expression, /*location*/ node); } markLabel(resumeLabel); - return createGeneratorResume(node); + return createGeneratorResume(/*location*/ node); } + /** + * Visits an ArrayLiteralExpression that contains a YieldExpression. + * + * @param node The node to visit. + */ function visitArrayLiteralExpression(node) { - return visitElements(node.elements, undefined, undefined, node.multiLine); + return visitElements(node.elements, /*leadingElement*/ undefined, /*location*/ undefined, node.multiLine); } + /** + * Visits an array of expressions containing one or more YieldExpression nodes + * and returns an expression for the resulting value. + * + * @param elements The elements to visit. + * @param multiLine Whether array literals created should be emitted on multiple lines. + */ function visitElements(elements, leadingElement, location, multiLine) { + // [source] + // ar = [1, yield, 2]; + // + // [intermediate] + // .local _a + // _a = [1]; + // .yield resumeLabel + // .mark resumeLabel + // ar = _a.concat([%sent%, 2]); var numInitialElements = countInitialNodesWithoutYield(elements); var temp; if (numInitialElements > 0) { @@ -58594,6 +70071,23 @@ var ts; } } function visitObjectLiteralExpression(node) { + // [source] + // o = { + // a: 1, + // b: yield, + // c: 2 + // }; + // + // [intermediate] + // .local _a + // _a = { + // a: 1 + // }; + // .yield resumeLabel + // .mark resumeLabel + // o = (_a.b = %sent%, + // _a.c = 2, + // _a); var properties = node.properties; var multiLine = node.multiLine; var numInitialProperties = countInitialNodesWithoutYield(properties); @@ -58618,8 +70112,22 @@ var ts; return expressions; } } + /** + * Visits an ElementAccessExpression that contains a YieldExpression. + * + * @param node The node to visit. + */ function visitElementAccessExpression(node) { if (containsYield(node.argumentExpression)) { + // [source] + // a = x[yield]; + // + // [intermediate] + // .local _a + // _a = x; + // .yield resumeLabel + // .mark resumeLabel + // a = _a[%sent%] var clone_5 = ts.getMutableClone(node); clone_5.expression = cacheExpression(ts.visitNode(node.expression, visitor, ts.isLeftHandSideExpression)); clone_5.argumentExpression = ts.visitNode(node.argumentExpression, visitor, ts.isExpression); @@ -58629,15 +70137,38 @@ var ts; } function visitCallExpression(node) { if (!ts.isImportCall(node) && ts.forEach(node.arguments, containsYield)) { - var _a = ts.createCallBinding(node.expression, hoistVariableDeclaration, languageVersion, true), target = _a.target, thisArg = _a.thisArg; - return ts.setOriginalNode(ts.createFunctionApply(cacheExpression(ts.visitNode(target, visitor, ts.isLeftHandSideExpression)), thisArg, visitElements(node.arguments), node), node); + // [source] + // a.b(1, yield, 2); + // + // [intermediate] + // .local _a, _b, _c + // _b = (_a = a).b; + // _c = [1]; + // .yield resumeLabel + // .mark resumeLabel + // _b.apply(_a, _c.concat([%sent%, 2])); + var _a = ts.createCallBinding(node.expression, hoistVariableDeclaration, languageVersion, /*cacheIdentifiers*/ true), target = _a.target, thisArg = _a.thisArg; + return ts.setOriginalNode(ts.createFunctionApply(cacheExpression(ts.visitNode(target, visitor, ts.isLeftHandSideExpression)), thisArg, visitElements(node.arguments), + /*location*/ node), node); } return ts.visitEachChild(node, visitor, context); } function visitNewExpression(node) { if (ts.forEach(node.arguments, containsYield)) { + // [source] + // new a.b(1, yield, 2); + // + // [intermediate] + // .local _a, _b, _c + // _b = (_a = a.b).bind; + // _c = [1]; + // .yield resumeLabel + // .mark resumeLabel + // new (_b.apply(_a, _c.concat([%sent%, 2]))); var _a = ts.createCallBinding(ts.createPropertyAccess(node.expression, "bind"), hoistVariableDeclaration), target = _a.target, thisArg = _a.thisArg; - return ts.setOriginalNode(ts.setTextRange(ts.createNew(ts.createFunctionApply(cacheExpression(ts.visitNode(target, visitor, ts.isExpression)), thisArg, visitElements(node.arguments, ts.createVoidZero())), undefined, []), node), node); + return ts.setOriginalNode(ts.setTextRange(ts.createNew(ts.createFunctionApply(cacheExpression(ts.visitNode(target, visitor, ts.isExpression)), thisArg, visitElements(node.arguments, + /*leadingElement*/ ts.createVoidZero())), + /*typeArguments*/ undefined, []), node), node); } return ts.visitEachChild(node, visitor, context); } @@ -58666,35 +70197,35 @@ var ts; } function transformAndEmitStatementWorker(node) { switch (node.kind) { - case 213: + case 213 /* Block */: return transformAndEmitBlock(node); - case 216: + case 216 /* ExpressionStatement */: return transformAndEmitExpressionStatement(node); - case 217: + case 217 /* IfStatement */: return transformAndEmitIfStatement(node); - case 218: + case 218 /* DoStatement */: return transformAndEmitDoStatement(node); - case 219: + case 219 /* WhileStatement */: return transformAndEmitWhileStatement(node); - case 220: + case 220 /* ForStatement */: return transformAndEmitForStatement(node); - case 221: + case 221 /* ForInStatement */: return transformAndEmitForInStatement(node); - case 223: + case 223 /* ContinueStatement */: return transformAndEmitContinueStatement(node); - case 224: + case 224 /* BreakStatement */: return transformAndEmitBreakStatement(node); - case 225: + case 225 /* ReturnStatement */: return transformAndEmitReturnStatement(node); - case 226: + case 226 /* WithStatement */: return transformAndEmitWithStatement(node); - case 227: + case 227 /* SwitchStatement */: return transformAndEmitSwitchStatement(node); - case 228: + case 228 /* LabeledStatement */: return transformAndEmitLabeledStatement(node); - case 229: + case 229 /* ThrowStatement */: return transformAndEmitThrowStatement(node); - case 230: + case 230 /* TryStatement */: return transformAndEmitTryStatement(node); default: return emitStatement(ts.visitNode(node, visitor, ts.isStatement)); @@ -58743,10 +70274,23 @@ var ts; } function transformAndEmitIfStatement(node) { if (containsYield(node)) { + // [source] + // if (x) + // /*thenStatement*/ + // else + // /*elseStatement*/ + // + // [intermediate] + // .brfalse elseLabel, (x) + // /*thenStatement*/ + // .br endLabel + // .mark elseLabel + // /*elseStatement*/ + // .mark endLabel if (containsYield(node.thenStatement) || containsYield(node.elseStatement)) { var endLabel = defineLabel(); var elseLabel = node.elseStatement ? defineLabel() : undefined; - emitBreakWhenFalse(node.elseStatement ? elseLabel : endLabel, ts.visitNode(node.expression, visitor, ts.isExpression), node.expression); + emitBreakWhenFalse(node.elseStatement ? elseLabel : endLabel, ts.visitNode(node.expression, visitor, ts.isExpression), /*location*/ node.expression); transformAndEmitEmbeddedStatement(node.thenStatement); if (node.elseStatement) { emitBreak(endLabel); @@ -58765,9 +70309,23 @@ var ts; } function transformAndEmitDoStatement(node) { if (containsYield(node)) { + // [source] + // do { + // /*body*/ + // } + // while (i < 10); + // + // [intermediate] + // .loop conditionLabel, endLabel + // .mark loopLabel + // /*body*/ + // .mark conditionLabel + // .brtrue loopLabel, (i < 10) + // .endloop + // .mark endLabel var conditionLabel = defineLabel(); var loopLabel = defineLabel(); - beginLoopBlock(conditionLabel); + beginLoopBlock(/*continueLabel*/ conditionLabel); markLabel(loopLabel); transformAndEmitEmbeddedStatement(node.statement); markLabel(conditionLabel); @@ -58791,6 +70349,19 @@ var ts; } function transformAndEmitWhileStatement(node) { if (containsYield(node)) { + // [source] + // while (i < 10) { + // /*body*/ + // } + // + // [intermediate] + // .loop loopLabel, endLabel + // .mark loopLabel + // .brfalse endLabel, (i < 10) + // /*body*/ + // .br loopLabel + // .endloop + // .mark endLabel var loopLabel = defineLabel(); var endLabel = beginLoopBlock(loopLabel); markLabel(loopLabel); @@ -58816,6 +70387,23 @@ var ts; } function transformAndEmitForStatement(node) { if (containsYield(node)) { + // [source] + // for (var i = 0; i < 10; i++) { + // /*body*/ + // } + // + // [intermediate] + // .local i + // i = 0; + // .loop incrementLabel, endLoopLabel + // .mark conditionLabel + // .brfalse endLoopLabel, (i < 10) + // /*body*/ + // .mark incrementLabel + // i++; + // .br conditionLabel + // .endloop + // .mark endLoopLabel var conditionLabel = defineLabel(); var incrementLabel = defineLabel(); var endLabel = beginLoopBlock(incrementLabel); @@ -58868,14 +70456,36 @@ var ts; return node; } function transformAndEmitForInStatement(node) { + // TODO(rbuckton): Source map locations if (containsYield(node)) { - var keysArray = declareLocal(); - var key = declareLocal(); - var keysIndex = ts.createLoopVariable(); + // [source] + // for (var p in o) { + // /*body*/ + // } + // + // [intermediate] + // .local _a, _b, _i + // _a = []; + // for (_b in o) _a.push(_b); + // _i = 0; + // .loop incrementLabel, endLoopLabel + // .mark conditionLabel + // .brfalse endLoopLabel, (_i < _a.length) + // p = _a[_i]; + // /*body*/ + // .mark incrementLabel + // _b++; + // .br conditionLabel + // .endloop + // .mark endLoopLabel + var keysArray = declareLocal(); // _a + var key = declareLocal(); // _b + var keysIndex = ts.createLoopVariable(); // _i var initializer = node.initializer; hoistVariableDeclaration(keysIndex); emitAssignment(keysArray, ts.createArrayLiteral()); - emitStatement(ts.createForIn(key, ts.visitNode(node.expression, visitor, ts.isExpression), ts.createStatement(ts.createCall(ts.createPropertyAccess(keysArray, "push"), undefined, [key])))); + emitStatement(ts.createForIn(key, ts.visitNode(node.expression, visitor, ts.isExpression), ts.createStatement(ts.createCall(ts.createPropertyAccess(keysArray, "push"), + /*typeArguments*/ undefined, [key])))); emitAssignment(keysIndex, ts.createLiteral(0)); var conditionLabel = defineLabel(); var incrementLabel = defineLabel(); @@ -58906,6 +70516,18 @@ var ts; } } function visitForInStatement(node) { + // [source] + // for (var x in a) { + // /*body*/ + // } + // + // [intermediate] + // .local x + // .loop + // for (x in a) { + // /*body*/ + // } + // .endloop if (inStatementContainingYield) { beginScriptLoopBlock(); } @@ -58928,9 +70550,10 @@ var ts; function transformAndEmitContinueStatement(node) { var label = findContinueTarget(node.label ? ts.idText(node.label) : undefined); if (label > 0) { - emitBreak(label, node); + emitBreak(label, /*location*/ node); } else { + // invalid continue without a containing loop. Leave the node as is, per #17875. emitStatement(node); } } @@ -58938,7 +70561,7 @@ var ts; if (inStatementContainingYield) { var label = findContinueTarget(node.label && ts.idText(node.label)); if (label > 0) { - return createInlineBreak(label, node); + return createInlineBreak(label, /*location*/ node); } } return ts.visitEachChild(node, visitor, context); @@ -58946,9 +70569,10 @@ var ts; function transformAndEmitBreakStatement(node) { var label = findBreakTarget(node.label ? ts.idText(node.label) : undefined); if (label > 0) { - emitBreak(label, node); + emitBreak(label, /*location*/ node); } else { + // invalid break without a containing loop, switch, or labeled statement. Leave the node as is, per #17875. emitStatement(node); } } @@ -58956,19 +70580,30 @@ var ts; if (inStatementContainingYield) { var label = findBreakTarget(node.label && ts.idText(node.label)); if (label > 0) { - return createInlineBreak(label, node); + return createInlineBreak(label, /*location*/ node); } } return ts.visitEachChild(node, visitor, context); } function transformAndEmitReturnStatement(node) { - emitReturn(ts.visitNode(node.expression, visitor, ts.isExpression), node); + emitReturn(ts.visitNode(node.expression, visitor, ts.isExpression), + /*location*/ node); } function visitReturnStatement(node) { - return createInlineReturn(ts.visitNode(node.expression, visitor, ts.isExpression), node); + return createInlineReturn(ts.visitNode(node.expression, visitor, ts.isExpression), + /*location*/ node); } function transformAndEmitWithStatement(node) { if (containsYield(node)) { + // [source] + // with (x) { + // /*body*/ + // } + // + // [intermediate] + // .with (x) + // /*body*/ + // .endwith beginWithBlock(cacheExpression(ts.visitNode(node.expression, visitor, ts.isExpression))); transformAndEmitEmbeddedStatement(node.statement); endWithBlock(); @@ -58979,31 +70614,66 @@ var ts; } function transformAndEmitSwitchStatement(node) { if (containsYield(node.caseBlock)) { + // [source] + // switch (x) { + // case a: + // /*caseStatements*/ + // case b: + // /*caseStatements*/ + // default: + // /*defaultStatements*/ + // } + // + // [intermediate] + // .local _a + // .switch endLabel + // _a = x; + // switch (_a) { + // case a: + // .br clauseLabels[0] + // } + // switch (_a) { + // case b: + // .br clauseLabels[1] + // } + // .br clauseLabels[2] + // .mark clauseLabels[0] + // /*caseStatements*/ + // .mark clauseLabels[1] + // /*caseStatements*/ + // .mark clauseLabels[2] + // /*caseStatements*/ + // .endswitch + // .mark endLabel var caseBlock = node.caseBlock; var numClauses = caseBlock.clauses.length; var endLabel = beginSwitchBlock(); var expression = cacheExpression(ts.visitNode(node.expression, visitor, ts.isExpression)); + // Create labels for each clause and find the index of the first default clause. var clauseLabels = []; var defaultClauseIndex = -1; for (var i = 0; i < numClauses; i++) { var clause = caseBlock.clauses[i]; clauseLabels.push(defineLabel()); - if (clause.kind === 267 && defaultClauseIndex === -1) { + if (clause.kind === 267 /* DefaultClause */ && defaultClauseIndex === -1) { defaultClauseIndex = i; } } + // Emit switch statements for each run of case clauses either from the first case + // clause or the next case clause with a `yield` in its expression, up to the next + // case clause with a `yield` in its expression. var clausesWritten = 0; var pendingClauses = []; while (clausesWritten < numClauses) { var defaultClausesSkipped = 0; for (var i = clausesWritten; i < numClauses; i++) { var clause = caseBlock.clauses[i]; - if (clause.kind === 266) { + if (clause.kind === 266 /* CaseClause */) { if (containsYield(clause.expression) && pendingClauses.length > 0) { break; } pendingClauses.push(ts.createCaseClause(ts.visitNode(clause.expression, visitor, ts.isExpression), [ - createInlineBreak(clauseLabels[i], clause.expression) + createInlineBreak(clauseLabels[i], /*location*/ clause.expression) ])); } else { @@ -59048,6 +70718,16 @@ var ts; } function transformAndEmitLabeledStatement(node) { if (containsYield(node)) { + // [source] + // x: { + // /*body*/ + // } + // + // [intermediate] + // .labeled "x", endLabel + // /*body*/ + // .endlabeled + // .mark endLabel beginLabeledBlock(ts.idText(node.label)); transformAndEmitEmbeddedStatement(node.statement); endLabeledBlock(); @@ -59067,14 +70747,44 @@ var ts; return node; } function transformAndEmitThrowStatement(node) { - emitThrow(ts.visitNode(node.expression, visitor, ts.isExpression), node); + emitThrow(ts.visitNode(node.expression, visitor, ts.isExpression), + /*location*/ node); } function transformAndEmitTryStatement(node) { if (containsYield(node)) { + // [source] + // try { + // /*tryBlock*/ + // } + // catch (e) { + // /*catchBlock*/ + // } + // finally { + // /*finallyBlock*/ + // } + // + // [intermediate] + // .local _a + // .try tryLabel, catchLabel, finallyLabel, endLabel + // .mark tryLabel + // .nop + // /*tryBlock*/ + // .br endLabel + // .catch + // .mark catchLabel + // _a = %error%; + // /*catchBlock*/ + // .br endLabel + // .finally + // .mark finallyLabel + // /*finallyBlock*/ + // .endfinally + // .endtry + // .mark endLabel beginExceptionBlock(); transformAndEmitEmbeddedStatement(node.tryBlock); if (node.catchClause) { - beginCatchBlock(node.catchClause.variableDeclaration); + beginCatchBlock(node.catchClause.variableDeclaration); // TODO: GH#18217 transformAndEmitEmbeddedStatement(node.catchClause.block); } if (node.finallyBlock) { @@ -59088,7 +70798,7 @@ var ts; } } function containsYield(node) { - return !!node && (node.transformFlags & 16777216) !== 0; + return !!node && (node.transformFlags & 16777216 /* ContainsYield */) !== 0; } function countInitialNodesWithoutYield(nodes) { var numNodes = nodes.length; @@ -59101,7 +70811,7 @@ var ts; } function onSubstituteNode(hint, node) { node = previousOnSubstituteNode(hint, node); - if (hint === 1) { + if (hint === 1 /* Expression */) { return substituteExpression(node); } return node; @@ -59132,20 +70842,23 @@ var ts; } function cacheExpression(node) { var temp; - if (ts.isGeneratedIdentifier(node) || ts.getEmitFlags(node) & 4096) { + if (ts.isGeneratedIdentifier(node) || ts.getEmitFlags(node) & 4096 /* HelperName */) { return node; } temp = ts.createTempVariable(hoistVariableDeclaration); - emitAssignment(temp, node, node); + emitAssignment(temp, node, /*location*/ node); return temp; } function declareLocal(name) { var temp = name ? ts.createUniqueName(name) - : ts.createTempVariable(undefined); + : ts.createTempVariable(/*recordTempVariable*/ undefined); hoistVariableDeclaration(temp); return temp; } + /** + * Defines a label, uses as the target of a Break operation. + */ function defineLabel() { if (!labelOffsets) { labelOffsets = []; @@ -59155,10 +70868,18 @@ var ts; labelOffsets[label] = -1; return label; } + /** + * Marks the current operation with the specified label. + */ function markLabel(label) { ts.Debug.assert(labelOffsets !== undefined, "No labels were defined."); labelOffsets[label] = operations ? operations.length : 0; } + /** + * Begins a block operation (With, Break/Continue, Try/Catch/Finally) + * + * @param block Information about the block. + */ function beginBlock(block) { if (!blocks) { blocks = []; @@ -59167,61 +70888,87 @@ var ts; blockStack = []; } var index = blockActions.length; - blockActions[index] = 0; + blockActions[index] = 0 /* Open */; blockOffsets[index] = operations ? operations.length : 0; blocks[index] = block; blockStack.push(block); return index; } + /** + * Ends the current block operation. + */ function endBlock() { var block = peekBlock(); if (block === undefined) return ts.Debug.fail("beginBlock was never called."); var index = blockActions.length; - blockActions[index] = 1; + blockActions[index] = 1 /* Close */; blockOffsets[index] = operations ? operations.length : 0; blocks[index] = block; blockStack.pop(); return block; } + /** + * Gets the current open block. + */ function peekBlock() { return ts.lastOrUndefined(blockStack); } + /** + * Gets the kind of the current open block. + */ function peekBlockKind() { var block = peekBlock(); return block && block.kind; } + /** + * Begins a code block for a generated `with` statement. + * + * @param expression An identifier representing expression for the `with` block. + */ function beginWithBlock(expression) { var startLabel = defineLabel(); var endLabel = defineLabel(); markLabel(startLabel); beginBlock({ - kind: 1, + kind: 1 /* With */, expression: expression, startLabel: startLabel, endLabel: endLabel }); } + /** + * Ends a code block for a generated `with` statement. + */ function endWithBlock() { - ts.Debug.assert(peekBlockKind() === 1); + ts.Debug.assert(peekBlockKind() === 1 /* With */); var block = endBlock(); markLabel(block.endLabel); } + /** + * Begins a code block for a generated `try` statement. + */ function beginExceptionBlock() { var startLabel = defineLabel(); var endLabel = defineLabel(); markLabel(startLabel); beginBlock({ - kind: 0, - state: 0, + kind: 0 /* Exception */, + state: 0 /* Try */, startLabel: startLabel, endLabel: endLabel }); emitNop(); return endLabel; } + /** + * Enters the `catch` clause of a generated `try` statement. + * + * @param variable The catch variable. + */ function beginCatchBlock(variable) { - ts.Debug.assert(peekBlockKind() === 0); + ts.Debug.assert(peekBlockKind() === 0 /* Exception */); + // generated identifiers should already be unique within a file var name; if (ts.isGeneratedIdentifier(variable.name)) { name = variable.name; @@ -59233,39 +70980,45 @@ var ts; if (!renamedCatchVariables) { renamedCatchVariables = ts.createMap(); renamedCatchVariableDeclarations = []; - context.enableSubstitution(71); + context.enableSubstitution(71 /* Identifier */); } renamedCatchVariables.set(text, true); renamedCatchVariableDeclarations[ts.getOriginalNodeId(variable)] = name; } var exception = peekBlock(); - ts.Debug.assert(exception.state < 1); + ts.Debug.assert(exception.state < 1 /* Catch */); var endLabel = exception.endLabel; emitBreak(endLabel); var catchLabel = defineLabel(); markLabel(catchLabel); - exception.state = 1; + exception.state = 1 /* Catch */; exception.catchVariable = name; exception.catchLabel = catchLabel; - emitAssignment(name, ts.createCall(ts.createPropertyAccess(state, "sent"), undefined, [])); + emitAssignment(name, ts.createCall(ts.createPropertyAccess(state, "sent"), /*typeArguments*/ undefined, [])); emitNop(); } + /** + * Enters the `finally` block of a generated `try` statement. + */ function beginFinallyBlock() { - ts.Debug.assert(peekBlockKind() === 0); + ts.Debug.assert(peekBlockKind() === 0 /* Exception */); var exception = peekBlock(); - ts.Debug.assert(exception.state < 2); + ts.Debug.assert(exception.state < 2 /* Finally */); var endLabel = exception.endLabel; emitBreak(endLabel); var finallyLabel = defineLabel(); markLabel(finallyLabel); - exception.state = 2; + exception.state = 2 /* Finally */; exception.finallyLabel = finallyLabel; } + /** + * Ends the code block for a generated `try` statement. + */ function endExceptionBlock() { - ts.Debug.assert(peekBlockKind() === 0); + ts.Debug.assert(peekBlockKind() === 0 /* Exception */); var exception = endBlock(); var state = exception.state; - if (state < 2) { + if (state < 2 /* Finally */) { emitBreak(exception.endLabel); } else { @@ -59273,52 +71026,83 @@ var ts; } markLabel(exception.endLabel); emitNop(); - exception.state = 3; + exception.state = 3 /* Done */; } + /** + * Begins a code block that supports `break` or `continue` statements that are defined in + * the source tree and not from generated code. + * + * @param labelText Names from containing labeled statements. + */ function beginScriptLoopBlock() { beginBlock({ - kind: 3, + kind: 3 /* Loop */, isScript: true, breakLabel: -1, continueLabel: -1 }); } + /** + * Begins a code block that supports `break` or `continue` statements that are defined in + * generated code. Returns a label used to mark the operation to which to jump when a + * `break` statement targets this block. + * + * @param continueLabel A Label used to mark the operation to which to jump when a + * `continue` statement targets this block. + */ function beginLoopBlock(continueLabel) { var breakLabel = defineLabel(); beginBlock({ - kind: 3, + kind: 3 /* Loop */, isScript: false, breakLabel: breakLabel, continueLabel: continueLabel, }); return breakLabel; } + /** + * Ends a code block that supports `break` or `continue` statements that are defined in + * generated code or in the source tree. + */ function endLoopBlock() { - ts.Debug.assert(peekBlockKind() === 3); + ts.Debug.assert(peekBlockKind() === 3 /* Loop */); var block = endBlock(); var breakLabel = block.breakLabel; if (!block.isScript) { markLabel(breakLabel); } } + /** + * Begins a code block that supports `break` statements that are defined in the source + * tree and not from generated code. + * + */ function beginScriptSwitchBlock() { beginBlock({ - kind: 2, + kind: 2 /* Switch */, isScript: true, breakLabel: -1 }); } + /** + * Begins a code block that supports `break` statements that are defined in generated code. + * Returns a label used to mark the operation to which to jump when a `break` statement + * targets this block. + */ function beginSwitchBlock() { var breakLabel = defineLabel(); beginBlock({ - kind: 2, + kind: 2 /* Switch */, isScript: false, breakLabel: breakLabel, }); return breakLabel; } + /** + * Ends a code block that supports `break` statements that are defined in generated code. + */ function endSwitchBlock() { - ts.Debug.assert(peekBlockKind() === 2); + ts.Debug.assert(peekBlockKind() === 2 /* Switch */); var block = endBlock(); var breakLabel = block.breakLabel; if (!block.isScript) { @@ -59327,7 +71111,7 @@ var ts; } function beginScriptLabeledBlock(labelText) { beginBlock({ - kind: 4, + kind: 4 /* Labeled */, isScript: true, labelText: labelText, breakLabel: -1 @@ -59336,28 +71120,43 @@ var ts; function beginLabeledBlock(labelText) { var breakLabel = defineLabel(); beginBlock({ - kind: 4, + kind: 4 /* Labeled */, isScript: false, labelText: labelText, breakLabel: breakLabel }); } function endLabeledBlock() { - ts.Debug.assert(peekBlockKind() === 4); + ts.Debug.assert(peekBlockKind() === 4 /* Labeled */); var block = endBlock(); if (!block.isScript) { markLabel(block.breakLabel); } } + /** + * Indicates whether the provided block supports `break` statements. + * + * @param block A code block. + */ function supportsUnlabeledBreak(block) { - return block.kind === 2 - || block.kind === 3; + return block.kind === 2 /* Switch */ + || block.kind === 3 /* Loop */; } + /** + * Indicates whether the provided block supports `break` statements with labels. + * + * @param block A code block. + */ function supportsLabeledBreakOrContinue(block) { - return block.kind === 4; + return block.kind === 4 /* Labeled */; } + /** + * Indicates whether the provided block supports `continue` statements. + * + * @param block A code block. + */ function supportsUnlabeledContinue(block) { - return block.kind === 3; + return block.kind === 3 /* Loop */; } function hasImmediateContainingLabeledBlock(labelText, start) { for (var j = start; j >= 0; j--) { @@ -59373,6 +71172,11 @@ var ts; } return false; } + /** + * Finds the label that is the target for a `break` statement. + * + * @param labelText An optional name of a containing labeled statement. + */ function findBreakTarget(labelText) { if (blockStack) { if (labelText) { @@ -59397,6 +71201,11 @@ var ts; } return 0; } + /** + * Finds the label that is the target for a `continue` statement. + * + * @param labelText An optional name of a containing labeled statement. + */ function findContinueTarget(labelText) { if (blockStack) { if (labelText) { @@ -59418,6 +71227,11 @@ var ts; } return 0; } + /** + * Creates an expression that can be used to indicate the value for a label. + * + * @param label A label. + */ function createLabel(label) { if (label !== undefined && label > 0) { if (labelExpressions === undefined) { @@ -59434,64 +71248,153 @@ var ts; } return ts.createOmittedExpression(); } + /** + * Creates a numeric literal for the provided instruction. + */ function createInstruction(instruction) { var literal = ts.createLiteral(instruction); - ts.addSyntheticTrailingComment(literal, 3, getInstructionName(instruction)); + ts.addSyntheticTrailingComment(literal, 3 /* MultiLineCommentTrivia */, getInstructionName(instruction)); return literal; } + /** + * Creates a statement that can be used indicate a Break operation to the provided label. + * + * @param label A label. + * @param location An optional source map location for the statement. + */ function createInlineBreak(label, location) { ts.Debug.assertLessThan(0, label, "Invalid label"); return ts.setTextRange(ts.createReturn(ts.createArrayLiteral([ - createInstruction(3), + createInstruction(3 /* Break */), createLabel(label) ])), location); } + /** + * Creates a statement that can be used indicate a Return operation. + * + * @param expression The expression for the return statement. + * @param location An optional source map location for the statement. + */ function createInlineReturn(expression, location) { return ts.setTextRange(ts.createReturn(ts.createArrayLiteral(expression - ? [createInstruction(2), expression] - : [createInstruction(2)])), location); + ? [createInstruction(2 /* Return */), expression] + : [createInstruction(2 /* Return */)])), location); } + /** + * Creates an expression that can be used to resume from a Yield operation. + */ function createGeneratorResume(location) { - return ts.setTextRange(ts.createCall(ts.createPropertyAccess(state, "sent"), undefined, []), location); + return ts.setTextRange(ts.createCall(ts.createPropertyAccess(state, "sent"), + /*typeArguments*/ undefined, []), location); } + /** + * Emits an empty instruction. + */ function emitNop() { - emitWorker(0); + emitWorker(0 /* Nop */); } + /** + * Emits a Statement. + * + * @param node A statement. + */ function emitStatement(node) { if (node) { - emitWorker(1, [node]); + emitWorker(1 /* Statement */, [node]); } else { emitNop(); } } + /** + * Emits an Assignment operation. + * + * @param left The left-hand side of the assignment. + * @param right The right-hand side of the assignment. + * @param location An optional source map location for the assignment. + */ function emitAssignment(left, right, location) { - emitWorker(2, [left, right], location); + emitWorker(2 /* Assign */, [left, right], location); } + /** + * Emits a Break operation to the specified label. + * + * @param label A label. + * @param location An optional source map location for the assignment. + */ function emitBreak(label, location) { - emitWorker(3, [label], location); + emitWorker(3 /* Break */, [label], location); } + /** + * Emits a Break operation to the specified label when a condition evaluates to a truthy + * value at runtime. + * + * @param label A label. + * @param condition The condition. + * @param location An optional source map location for the assignment. + */ function emitBreakWhenTrue(label, condition, location) { - emitWorker(4, [label, condition], location); + emitWorker(4 /* BreakWhenTrue */, [label, condition], location); } + /** + * Emits a Break to the specified label when a condition evaluates to a falsey value at + * runtime. + * + * @param label A label. + * @param condition The condition. + * @param location An optional source map location for the assignment. + */ function emitBreakWhenFalse(label, condition, location) { - emitWorker(5, [label, condition], location); + emitWorker(5 /* BreakWhenFalse */, [label, condition], location); } + /** + * Emits a YieldStar operation for the provided expression. + * + * @param expression An optional value for the yield operation. + * @param location An optional source map location for the assignment. + */ function emitYieldStar(expression, location) { - emitWorker(7, [expression], location); + emitWorker(7 /* YieldStar */, [expression], location); } + /** + * Emits a Yield operation for the provided expression. + * + * @param expression An optional value for the yield operation. + * @param location An optional source map location for the assignment. + */ function emitYield(expression, location) { - emitWorker(6, [expression], location); + emitWorker(6 /* Yield */, [expression], location); } + /** + * Emits a Return operation for the provided expression. + * + * @param expression An optional value for the operation. + * @param location An optional source map location for the assignment. + */ function emitReturn(expression, location) { - emitWorker(8, [expression], location); + emitWorker(8 /* Return */, [expression], location); } + /** + * Emits a Throw operation for the provided expression. + * + * @param expression A value for the operation. + * @param location An optional source map location for the assignment. + */ function emitThrow(expression, location) { - emitWorker(9, [expression], location); + emitWorker(9 /* Throw */, [expression], location); } + /** + * Emits an Endfinally operation. This is used to handle `finally` block semantics. + */ function emitEndfinally() { - emitWorker(10); + emitWorker(10 /* Endfinally */); } + /** + * Emits an operation. + * + * @param code The OpCode for the operation. + * @param args The optional arguments for the operation. + */ function emitWorker(code, args, location) { if (operations === undefined) { operations = []; @@ -59499,6 +71402,7 @@ var ts; operationLocations = []; } if (labelOffsets === undefined) { + // mark entry point markLabel(defineLabel()); } var operationIndex = operations.length; @@ -59506,6 +71410,9 @@ var ts; operationArguments[operationIndex] = args; operationLocations[operationIndex] = location; } + /** + * Builds the generator function body. + */ function build() { blockIndex = 0; labelNumber = 0; @@ -59518,8 +71425,17 @@ var ts; currentExceptionBlock = undefined; withBlockStack = undefined; var buildResult = buildStatements(); - return createGeneratorHelper(context, ts.setEmitFlags(ts.createFunctionExpression(undefined, undefined, undefined, undefined, [ts.createParameter(undefined, undefined, undefined, state)], undefined, ts.createBlock(buildResult, buildResult.length > 0)), 524288)); + return createGeneratorHelper(context, ts.setEmitFlags(ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, state)], + /*type*/ undefined, ts.createBlock(buildResult, + /*multiLine*/ buildResult.length > 0)), 524288 /* ReuseTempVariableScope */)); } + /** + * Builds the statements for the generator function body. + */ function buildStatements() { if (operations) { for (var operationIndex = 0; operationIndex < operations.length; operationIndex++) { @@ -59540,33 +71456,49 @@ var ts; } return []; } + /** + * Flush the current label and advance to a new label. + */ function flushLabel() { if (!statements) { return; } - appendLabel(!lastOperationWasAbrupt); + appendLabel(/*markLabelEnd*/ !lastOperationWasAbrupt); lastOperationWasAbrupt = false; lastOperationWasCompletion = false; labelNumber++; } + /** + * Flush the final label of the generator function body. + */ function flushFinalLabel(operationIndex) { if (isFinalLabelReachable(operationIndex)) { tryEnterLabel(operationIndex); withBlockStack = undefined; - writeReturn(undefined, undefined); + writeReturn(/*expression*/ undefined, /*operationLocation*/ undefined); } if (statements && clauses) { - appendLabel(false); + appendLabel(/*markLabelEnd*/ false); } updateLabelExpressions(); } + /** + * Tests whether the final label of the generator function body + * is reachable by user code. + */ function isFinalLabelReachable(operationIndex) { + // if the last operation was *not* a completion (return/throw) then + // the final label is reachable. if (!lastOperationWasCompletion) { return true; } + // if there are no labels defined or referenced, then the final label is + // not reachable. if (!labelOffsets || !labelExpressions) { return false; } + // if the label for this offset is referenced, then the final label + // is reachable. for (var label = 0; label < labelOffsets.length; label++) { if (labelOffsets[label] === operationIndex && labelExpressions[label]) { return true; @@ -59574,20 +71506,33 @@ var ts; } return false; } + /** + * Appends a case clause for the last label and sets the new label. + * + * @param markLabelEnd Indicates that the transition between labels was a fall-through + * from a previous case clause and the change in labels should be + * reflected on the `state` object. + */ function appendLabel(markLabelEnd) { if (!clauses) { clauses = []; } if (statements) { if (withBlockStack) { + // The previous label was nested inside one or more `with` blocks, so we + // surround the statements in generated `with` blocks to create the same environment. for (var i = withBlockStack.length - 1; i >= 0; i--) { var withBlock = withBlockStack[i]; statements = [ts.createWith(withBlock.expression, ts.createBlock(statements))]; } } if (currentExceptionBlock) { + // The previous label was nested inside of an exception block, so we must + // indicate entry into a protected region by pushing the label numbers + // for each block in the protected region. var startLabel = currentExceptionBlock.startLabel, catchLabel = currentExceptionBlock.catchLabel, finallyLabel = currentExceptionBlock.finallyLabel, endLabel = currentExceptionBlock.endLabel; - statements.unshift(ts.createStatement(ts.createCall(ts.createPropertyAccess(ts.createPropertyAccess(state, "trys"), "push"), undefined, [ + statements.unshift(ts.createStatement(ts.createCall(ts.createPropertyAccess(ts.createPropertyAccess(state, "trys"), "push"), + /*typeArguments*/ undefined, [ ts.createArrayLiteral([ createLabel(startLabel), createLabel(catchLabel), @@ -59598,12 +71543,17 @@ var ts; currentExceptionBlock = undefined; } if (markLabelEnd) { + // The case clause for the last label falls through to this label, so we + // add an assignment statement to reflect the change in labels. statements.push(ts.createStatement(ts.createAssignment(ts.createPropertyAccess(state, "label"), ts.createLiteral(labelNumber + 1)))); } } clauses.push(ts.createCaseClause(ts.createLiteral(labelNumber), statements || [])); statements = undefined; } + /** + * Tries to enter into a new label at the current operation index. + */ function tryEnterLabel(operationIndex) { if (!labelOffsets) { return; @@ -59623,6 +71573,9 @@ var ts; } } } + /** + * Updates literal expressions for labels with actual label numbers. + */ function updateLabelExpressions() { if (labelExpressions !== undefined && labelNumbers !== undefined) { for (var labelNumber_1 = 0; labelNumber_1 < labelNumbers.length; labelNumber_1++) { @@ -59642,14 +71595,17 @@ var ts; } } } + /** + * Tries to enter or leave a code block. + */ function tryEnterOrLeaveBlock(operationIndex) { if (blocks) { for (; blockIndex < blockActions.length && blockOffsets[blockIndex] <= operationIndex; blockIndex++) { var block = blocks[blockIndex]; var blockAction = blockActions[blockIndex]; switch (block.kind) { - case 0: - if (blockAction === 0) { + case 0 /* Exception */: + if (blockAction === 0 /* Open */) { if (!exceptionBlockStack) { exceptionBlockStack = []; } @@ -59659,64 +71615,76 @@ var ts; exceptionBlockStack.push(currentExceptionBlock); currentExceptionBlock = block; } - else if (blockAction === 1) { + else if (blockAction === 1 /* Close */) { currentExceptionBlock = exceptionBlockStack.pop(); } break; - case 1: - if (blockAction === 0) { + case 1 /* With */: + if (blockAction === 0 /* Open */) { if (!withBlockStack) { withBlockStack = []; } withBlockStack.push(block); } - else if (blockAction === 1) { + else if (blockAction === 1 /* Close */) { withBlockStack.pop(); } break; + // default: do nothing } } } } + /** + * Writes an operation as a statement to the current label's statement list. + * + * @param operation The OpCode of the operation + */ function writeOperation(operationIndex) { tryEnterLabel(operationIndex); tryEnterOrLeaveBlock(operationIndex); + // early termination, nothing else to process in this label if (lastOperationWasAbrupt) { return; } lastOperationWasAbrupt = false; lastOperationWasCompletion = false; var opcode = operations[operationIndex]; - if (opcode === 0) { + if (opcode === 0 /* Nop */) { return; } - else if (opcode === 10) { + else if (opcode === 10 /* Endfinally */) { return writeEndfinally(); } var args = operationArguments[operationIndex]; - if (opcode === 1) { + if (opcode === 1 /* Statement */) { return writeStatement(args[0]); } var location = operationLocations[operationIndex]; switch (opcode) { - case 2: + case 2 /* Assign */: return writeAssign(args[0], args[1], location); - case 3: + case 3 /* Break */: return writeBreak(args[0], location); - case 4: + case 4 /* BreakWhenTrue */: return writeBreakWhenTrue(args[0], args[1], location); - case 5: + case 5 /* BreakWhenFalse */: return writeBreakWhenFalse(args[0], args[1], location); - case 6: + case 6 /* Yield */: return writeYield(args[0], location); - case 7: + case 7 /* YieldStar */: return writeYieldStar(args[0], location); - case 8: + case 8 /* Return */: return writeReturn(args[0], location); - case 9: + case 9 /* Throw */: return writeThrow(args[0], location); } } + /** + * Writes a statement to the current label's statement list. + * + * @param statement A statement to write. + */ function writeStatement(statement) { if (statement) { if (!statements) { @@ -59727,65 +71695,179 @@ var ts; } } } + /** + * Writes an Assign operation to the current label's statement list. + * + * @param left The left-hand side of the assignment. + * @param right The right-hand side of the assignment. + * @param operationLocation The source map location for the operation. + */ function writeAssign(left, right, operationLocation) { writeStatement(ts.setTextRange(ts.createStatement(ts.createAssignment(left, right)), operationLocation)); } + /** + * Writes a Throw operation to the current label's statement list. + * + * @param expression The value to throw. + * @param operationLocation The source map location for the operation. + */ function writeThrow(expression, operationLocation) { lastOperationWasAbrupt = true; lastOperationWasCompletion = true; writeStatement(ts.setTextRange(ts.createThrow(expression), operationLocation)); } + /** + * Writes a Return operation to the current label's statement list. + * + * @param expression The value to return. + * @param operationLocation The source map location for the operation. + */ function writeReturn(expression, operationLocation) { lastOperationWasAbrupt = true; lastOperationWasCompletion = true; writeStatement(ts.setEmitFlags(ts.setTextRange(ts.createReturn(ts.createArrayLiteral(expression - ? [createInstruction(2), expression] - : [createInstruction(2)])), operationLocation), 384)); + ? [createInstruction(2 /* Return */), expression] + : [createInstruction(2 /* Return */)])), operationLocation), 384 /* NoTokenSourceMaps */)); } + /** + * Writes a Break operation to the current label's statement list. + * + * @param label The label for the Break. + * @param operationLocation The source map location for the operation. + */ function writeBreak(label, operationLocation) { lastOperationWasAbrupt = true; writeStatement(ts.setEmitFlags(ts.setTextRange(ts.createReturn(ts.createArrayLiteral([ - createInstruction(3), + createInstruction(3 /* Break */), createLabel(label) - ])), operationLocation), 384)); + ])), operationLocation), 384 /* NoTokenSourceMaps */)); } + /** + * Writes a BreakWhenTrue operation to the current label's statement list. + * + * @param label The label for the Break. + * @param condition The condition for the Break. + * @param operationLocation The source map location for the operation. + */ function writeBreakWhenTrue(label, condition, operationLocation) { writeStatement(ts.setEmitFlags(ts.createIf(condition, ts.setEmitFlags(ts.setTextRange(ts.createReturn(ts.createArrayLiteral([ - createInstruction(3), + createInstruction(3 /* Break */), createLabel(label) - ])), operationLocation), 384)), 1)); + ])), operationLocation), 384 /* NoTokenSourceMaps */)), 1 /* SingleLine */)); } + /** + * Writes a BreakWhenFalse operation to the current label's statement list. + * + * @param label The label for the Break. + * @param condition The condition for the Break. + * @param operationLocation The source map location for the operation. + */ function writeBreakWhenFalse(label, condition, operationLocation) { writeStatement(ts.setEmitFlags(ts.createIf(ts.createLogicalNot(condition), ts.setEmitFlags(ts.setTextRange(ts.createReturn(ts.createArrayLiteral([ - createInstruction(3), + createInstruction(3 /* Break */), createLabel(label) - ])), operationLocation), 384)), 1)); + ])), operationLocation), 384 /* NoTokenSourceMaps */)), 1 /* SingleLine */)); } + /** + * Writes a Yield operation to the current label's statement list. + * + * @param expression The expression to yield. + * @param operationLocation The source map location for the operation. + */ function writeYield(expression, operationLocation) { lastOperationWasAbrupt = true; writeStatement(ts.setEmitFlags(ts.setTextRange(ts.createReturn(ts.createArrayLiteral(expression - ? [createInstruction(4), expression] - : [createInstruction(4)])), operationLocation), 384)); + ? [createInstruction(4 /* Yield */), expression] + : [createInstruction(4 /* Yield */)])), operationLocation), 384 /* NoTokenSourceMaps */)); } + /** + * Writes a YieldStar instruction to the current label's statement list. + * + * @param expression The expression to yield. + * @param operationLocation The source map location for the operation. + */ function writeYieldStar(expression, operationLocation) { lastOperationWasAbrupt = true; writeStatement(ts.setEmitFlags(ts.setTextRange(ts.createReturn(ts.createArrayLiteral([ - createInstruction(5), + createInstruction(5 /* YieldStar */), expression - ])), operationLocation), 384)); + ])), operationLocation), 384 /* NoTokenSourceMaps */)); } + /** + * Writes an Endfinally instruction to the current label's statement list. + */ function writeEndfinally() { lastOperationWasAbrupt = true; writeStatement(ts.createReturn(ts.createArrayLiteral([ - createInstruction(7) + createInstruction(7 /* Endfinally */) ]))); } } ts.transformGenerators = transformGenerators; function createGeneratorHelper(context, body) { context.requestEmitHelper(generatorHelper); - return ts.createCall(ts.getHelperName("__generator"), undefined, [ts.createThis(), body]); + return ts.createCall(ts.getHelperName("__generator"), + /*typeArguments*/ undefined, [ts.createThis(), body]); } + // The __generator helper is used by down-level transformations to emulate the runtime + // semantics of an ES2015 generator function. When called, this helper returns an + // object that implements the Iterator protocol, in that it has `next`, `return`, and + // `throw` methods that step through the generator when invoked. + // + // parameters: + // @param thisArg The value to use as the `this` binding for the transformed generator body. + // @param body A function that acts as the transformed generator body. + // + // variables: + // _ Persistent state for the generator that is shared between the helper and the + // generator body. The state object has the following members: + // sent() - A method that returns or throws the current completion value. + // label - The next point at which to resume evaluation of the generator body. + // trys - A stack of protected regions (try/catch/finally blocks). + // ops - A stack of pending instructions when inside of a finally block. + // f A value indicating whether the generator is executing. + // y An iterator to delegate for a yield*. + // t A temporary variable that holds one of the following values (note that these + // cases do not overlap): + // - The completion value when resuming from a `yield` or `yield*`. + // - The error value for a catch block. + // - The current protected region (array of try/catch/finally/end labels). + // - The verb (`next`, `throw`, or `return` method) to delegate to the expression + // of a `yield*`. + // - The result of evaluating the verb delegated to the expression of a `yield*`. + // + // functions: + // verb(n) Creates a bound callback to the `step` function for opcode `n`. + // step(op) Evaluates opcodes in a generator body until execution is suspended or + // completed. + // + // The __generator helper understands a limited set of instructions: + // 0: next(value?) - Start or resume the generator with the specified value. + // 1: throw(error) - Resume the generator with an exception. If the generator is + // suspended inside of one or more protected regions, evaluates + // any intervening finally blocks between the current label and + // the nearest catch block or function boundary. If uncaught, the + // exception is thrown to the caller. + // 2: return(value?) - Resume the generator as if with a return. If the generator is + // suspended inside of one or more protected regions, evaluates any + // intervening finally blocks. + // 3: break(label) - Jump to the specified label. If the label is outside of the + // current protected region, evaluates any intervening finally + // blocks. + // 4: yield(value?) - Yield execution to the caller with an optional value. When + // resumed, the generator will continue at the next label. + // 5: yield*(value) - Delegates evaluation to the supplied iterator. When + // delegation completes, the generator will continue at the next + // label. + // 6: catch(error) - Handles an exception thrown from within the generator body. If + // the current label is inside of one or more protected regions, + // evaluates any intervening finally blocks between the current + // label and the nearest catch block or function boundary. If + // uncaught, the exception is thrown to the caller. + // 7: endfinally - Ends a finally block, resuming the last instruction prior to + // entering a finally block. + // + // For examples of how these are used, see the comments in ./transformers/generators.ts var generatorHelper = { name: "typescript:generator", scoped: false, @@ -59793,6 +71875,7 @@ var ts; text: "\n var __generator = (this && this.__generator) || function (thisArg, body) {\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n function verb(n) { return function (v) { return step([n, v]); }; }\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n while (_) try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [op[0] & 2, t.value];\n switch (op[0]) {\n case 0: case 1: t = op; break;\n case 4: _.label++; return { value: op[1], done: false };\n case 5: _.label++; y = op[1]; op = [0]; continue;\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n if (t[2]) _.ops.pop();\n _.trys.pop(); continue;\n }\n op = body.call(thisArg, _);\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n }\n };" }; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { function transformModule(context) { @@ -59813,26 +71896,32 @@ var ts; var previousOnEmitNode = context.onEmitNode; context.onSubstituteNode = onSubstituteNode; context.onEmitNode = onEmitNode; - context.enableSubstitution(71); - context.enableSubstitution(200); - context.enableSubstitution(198); - context.enableSubstitution(199); - context.enableSubstitution(271); - context.enableEmitNotification(274); - var moduleInfoMap = []; - var deferredExports = []; - var currentSourceFile; - var currentModuleInfo; - var noSubstitution; + context.enableSubstitution(71 /* Identifier */); // Substitutes expression identifiers with imported/exported symbols. + context.enableSubstitution(200 /* BinaryExpression */); // Substitutes assignments to exported symbols. + context.enableSubstitution(198 /* PrefixUnaryExpression */); // Substitutes updates to exported symbols. + context.enableSubstitution(199 /* PostfixUnaryExpression */); // Substitutes updates to exported symbols. + context.enableSubstitution(271 /* ShorthandPropertyAssignment */); // Substitutes shorthand property assignments for imported/exported symbols. + context.enableEmitNotification(274 /* SourceFile */); // Restore state when substituting nodes in a file. + var moduleInfoMap = []; // The ExternalModuleInfo for each file. + var deferredExports = []; // Exports to defer until an EndOfDeclarationMarker is found. + var currentSourceFile; // The current file. + var currentModuleInfo; // The ExternalModuleInfo for the current file. + var noSubstitution; // Set of nodes for which substitution rules should be ignored. var needUMDDynamicImportHelper; return ts.chainBundle(transformSourceFile); + /** + * Transforms the module aspects of a SourceFile. + * + * @param node The SourceFile node. + */ function transformSourceFile(node) { - if (node.isDeclarationFile || !(ts.isEffectiveExternalModule(node, compilerOptions) || node.transformFlags & 67108864)) { + if (node.isDeclarationFile || !(ts.isEffectiveExternalModule(node, compilerOptions) || node.transformFlags & 67108864 /* ContainsDynamicImport */)) { return node; } currentSourceFile = node; currentModuleInfo = ts.collectExternalModuleInfo(node, resolver, compilerOptions); moduleInfoMap[ts.getOriginalNodeId(node)] = currentModuleInfo; + // Perform the transformation. var transformModule = getTransformModuleDelegate(moduleKind); var updated = transformModule(node); currentSourceFile = undefined; @@ -59846,6 +71935,11 @@ var ts; } return false; } + /** + * Transforms a SourceFile into a CommonJS module. + * + * @param node The SourceFile node. + */ function transformCommonJSModule(node) { startLexicalEnvironment(); var statements = []; @@ -59856,48 +71950,105 @@ var ts; } ts.append(statements, ts.visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, ts.isStatement)); ts.addRange(statements, ts.visitNodes(node.statements, sourceElementVisitor, ts.isStatement, statementOffset)); - addExportEqualsIfNeeded(statements, false); + addExportEqualsIfNeeded(statements, /*emitAsReturn*/ false); ts.prependStatements(statements, endLexicalEnvironment()); var updated = ts.updateSourceFileNode(node, ts.setTextRange(ts.createNodeArray(statements), node.statements)); if (currentModuleInfo.hasExportStarsToExportValues && !compilerOptions.importHelpers) { + // If we have any `export * from ...` declarations + // we need to inform the emitter to add the __export helper. ts.addEmitHelper(updated, exportStarHelper); } ts.addEmitHelpers(updated, context.readEmitHelpers()); return updated; } + /** + * Transforms a SourceFile into an AMD module. + * + * @param node The SourceFile node. + */ function transformAMDModule(node) { var define = ts.createIdentifier("define"); var moduleName = ts.tryGetModuleNameFromFile(node, host, compilerOptions); - var _a = collectAsynchronousDependencies(node, true), aliasedModuleNames = _a.aliasedModuleNames, unaliasedModuleNames = _a.unaliasedModuleNames, importAliasNames = _a.importAliasNames; + // An AMD define function has the following shape: + // + // define(id?, dependencies?, factory); + // + // This has the shape of the following: + // + // define(name, ["module1", "module2"], function (module1Alias) { ... } + // + // The location of the alias in the parameter list in the factory function needs to + // match the position of the module name in the dependency list. + // + // To ensure this is true in cases of modules with no aliases, e.g.: + // + // import "module" + // + // or + // + // /// + // + // we need to add modules without alias names to the end of the dependencies list + var _a = collectAsynchronousDependencies(node, /*includeNonAmdDependencies*/ true), aliasedModuleNames = _a.aliasedModuleNames, unaliasedModuleNames = _a.unaliasedModuleNames, importAliasNames = _a.importAliasNames; + // Create an updated SourceFile: + // + // define(moduleName?, ["module1", "module2"], function ... var updated = ts.updateSourceFileNode(node, ts.setTextRange(ts.createNodeArray([ - ts.createStatement(ts.createCall(define, undefined, (moduleName ? [moduleName] : []).concat([ + ts.createStatement(ts.createCall(define, + /*typeArguments*/ undefined, (moduleName ? [moduleName] : []).concat([ + // Add the dependency array argument: + // + // ["require", "exports", module1", "module2", ...] ts.createArrayLiteral([ ts.createLiteral("require"), ts.createLiteral("exports") ].concat(aliasedModuleNames, unaliasedModuleNames)), - ts.createFunctionExpression(undefined, undefined, undefined, undefined, [ - ts.createParameter(undefined, undefined, undefined, "require"), - ts.createParameter(undefined, undefined, undefined, "exports") - ].concat(importAliasNames), undefined, transformAsynchronousModuleBody(node)) + // Add the module body function argument: + // + // function (require, exports, module1, module2) ... + ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ + ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "require"), + ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "exports") + ].concat(importAliasNames), + /*type*/ undefined, transformAsynchronousModuleBody(node)) ]))) - ]), node.statements)); + ]), + /*location*/ node.statements)); ts.addEmitHelpers(updated, context.readEmitHelpers()); return updated; } + /** + * Transforms a SourceFile into a UMD module. + * + * @param node The SourceFile node. + */ function transformUMDModule(node) { - var _a = collectAsynchronousDependencies(node, false), aliasedModuleNames = _a.aliasedModuleNames, unaliasedModuleNames = _a.unaliasedModuleNames, importAliasNames = _a.importAliasNames; + var _a = collectAsynchronousDependencies(node, /*includeNonAmdDependencies*/ false), aliasedModuleNames = _a.aliasedModuleNames, unaliasedModuleNames = _a.unaliasedModuleNames, importAliasNames = _a.importAliasNames; var moduleName = ts.tryGetModuleNameFromFile(node, host, compilerOptions); - var umdHeader = ts.createFunctionExpression(undefined, undefined, undefined, undefined, [ts.createParameter(undefined, undefined, undefined, "factory")], undefined, ts.setTextRange(ts.createBlock([ + var umdHeader = ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "factory")], + /*type*/ undefined, ts.setTextRange(ts.createBlock([ ts.createIf(ts.createLogicalAnd(ts.createTypeCheck(ts.createIdentifier("module"), "object"), ts.createTypeCheck(ts.createPropertyAccess(ts.createIdentifier("module"), "exports"), "object")), ts.createBlock([ - ts.createVariableStatement(undefined, [ - ts.createVariableDeclaration("v", undefined, ts.createCall(ts.createIdentifier("factory"), undefined, [ + ts.createVariableStatement( + /*modifiers*/ undefined, [ + ts.createVariableDeclaration("v", + /*type*/ undefined, ts.createCall(ts.createIdentifier("factory"), + /*typeArguments*/ undefined, [ ts.createIdentifier("require"), ts.createIdentifier("exports") ])) ]), - ts.setEmitFlags(ts.createIf(ts.createStrictInequality(ts.createIdentifier("v"), ts.createIdentifier("undefined")), ts.createStatement(ts.createAssignment(ts.createPropertyAccess(ts.createIdentifier("module"), "exports"), ts.createIdentifier("v")))), 1) + ts.setEmitFlags(ts.createIf(ts.createStrictInequality(ts.createIdentifier("v"), ts.createIdentifier("undefined")), ts.createStatement(ts.createAssignment(ts.createPropertyAccess(ts.createIdentifier("module"), "exports"), ts.createIdentifier("v")))), 1 /* SingleLine */) ]), ts.createIf(ts.createLogicalAnd(ts.createTypeCheck(ts.createIdentifier("define"), "function"), ts.createPropertyAccess(ts.createIdentifier("define"), "amd")), ts.createBlock([ - ts.createStatement(ts.createCall(ts.createIdentifier("define"), undefined, (moduleName ? [moduleName] : []).concat([ + ts.createStatement(ts.createCall(ts.createIdentifier("define"), + /*typeArguments*/ undefined, (moduleName ? [moduleName] : []).concat([ ts.createArrayLiteral([ ts.createLiteral("require"), ts.createLiteral("exports") @@ -59905,27 +72056,62 @@ var ts; ts.createIdentifier("factory") ]))) ]))) - ], true), undefined)); + ], + /*multiLine*/ true), + /*location*/ undefined)); + // Create an updated SourceFile: + // + // (function (factory) { + // if (typeof module === "object" && typeof module.exports === "object") { + // var v = factory(require, exports); + // if (v !== undefined) module.exports = v; + // } + // else if (typeof define === 'function' && define.amd) { + // define(["require", "exports"], factory); + // } + // })(function ...) var updated = ts.updateSourceFileNode(node, ts.setTextRange(ts.createNodeArray([ - ts.createStatement(ts.createCall(umdHeader, undefined, [ - ts.createFunctionExpression(undefined, undefined, undefined, undefined, [ - ts.createParameter(undefined, undefined, undefined, "require"), - ts.createParameter(undefined, undefined, undefined, "exports") - ].concat(importAliasNames), undefined, transformAsynchronousModuleBody(node)) + ts.createStatement(ts.createCall(umdHeader, + /*typeArguments*/ undefined, [ + // Add the module body function argument: + // + // function (require, exports) ... + ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ + ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "require"), + ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "exports") + ].concat(importAliasNames), + /*type*/ undefined, transformAsynchronousModuleBody(node)) ])) - ]), node.statements)); + ]), + /*location*/ node.statements)); ts.addEmitHelpers(updated, context.readEmitHelpers()); return updated; } + /** + * Collect the additional asynchronous dependencies for the module. + * + * @param node The source file. + * @param includeNonAmdDependencies A value indicating whether to include non-AMD dependencies. + */ function collectAsynchronousDependencies(node, includeNonAmdDependencies) { + // names of modules with corresponding parameter in the factory function var aliasedModuleNames = []; + // names of modules with no corresponding parameters in factory function var unaliasedModuleNames = []; + // names of the parameters in the factory function; these + // parameters need to match the indexes of the corresponding + // module names in aliasedModuleNames. var importAliasNames = []; + // Fill in amd-dependency tags for (var _i = 0, _a = node.amdDependencies; _i < _a.length; _i++) { var amdDependency = _a[_i]; if (amdDependency.name) { aliasedModuleNames.push(ts.createLiteral(amdDependency.path)); - importAliasNames.push(ts.createParameter(undefined, undefined, undefined, amdDependency.name)); + importAliasNames.push(ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, amdDependency.name)); } else { unaliasedModuleNames.push(ts.createLiteral(amdDependency.path)); @@ -59933,13 +72119,20 @@ var ts; } for (var _b = 0, _c = currentModuleInfo.externalImports; _b < _c.length; _b++) { var importNode = _c[_b]; + // Find the name of the external module var externalModuleName = ts.getExternalModuleNameLiteral(importNode, currentSourceFile, host, resolver, compilerOptions); + // Find the name of the module alias, if there is one var importAliasName = ts.getLocalNameForExternalImport(importNode, currentSourceFile); + // It is possible that externalModuleName is undefined if it is not string literal. + // This can happen in the invalid import syntax. + // E.g : "import * from alias from 'someLib';" if (externalModuleName) { if (includeNonAmdDependencies && importAliasName) { - ts.setEmitFlags(importAliasName, 4); + // Set emitFlags on the name of the classDeclaration + // This is so that when printer will not substitute the identifier + ts.setEmitFlags(importAliasName, 4 /* NoSubstitution */); aliasedModuleNames.push(externalModuleName); - importAliasNames.push(ts.createParameter(undefined, undefined, undefined, importAliasName)); + importAliasNames.push(ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, importAliasName)); } else { unaliasedModuleNames.push(externalModuleName); @@ -59952,29 +72145,40 @@ var ts; if (ts.isImportEqualsDeclaration(node) || ts.isExportDeclaration(node) || !ts.getExternalModuleNameLiteral(node, currentSourceFile, host, resolver, compilerOptions)) { return undefined; } - var name = ts.getLocalNameForExternalImport(node, currentSourceFile); + var name = ts.getLocalNameForExternalImport(node, currentSourceFile); // TODO: GH#18217 var expr = getHelperExpressionForImport(node, name); if (expr === name) { return undefined; } return ts.createStatement(ts.createAssignment(name, expr)); } + /** + * Transforms a SourceFile into an AMD or UMD module body. + * + * @param node The SourceFile node. + */ function transformAsynchronousModuleBody(node) { startLexicalEnvironment(); var statements = []; - var statementOffset = ts.addPrologue(statements, node.statements, !compilerOptions.noImplicitUseStrict, sourceElementVisitor); + var statementOffset = ts.addPrologue(statements, node.statements, /*ensureUseStrict*/ !compilerOptions.noImplicitUseStrict, sourceElementVisitor); if (shouldEmitUnderscoreUnderscoreESModule()) { ts.append(statements, createUnderscoreUnderscoreESModule()); } + // Visit each statement of the module body. ts.append(statements, ts.visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, ts.isStatement)); if (moduleKind === ts.ModuleKind.AMD) { ts.addRange(statements, ts.mapDefined(currentModuleInfo.externalImports, getAMDImportExpressionForImport)); } ts.addRange(statements, ts.visitNodes(node.statements, sourceElementVisitor, ts.isStatement, statementOffset)); - addExportEqualsIfNeeded(statements, true); + // Append the 'export =' statement if provided. + addExportEqualsIfNeeded(statements, /*emitAsReturn*/ true); + // End the lexical environment for the module body + // and merge any new lexical declarations. ts.prependStatements(statements, endLexicalEnvironment()); - var body = ts.createBlock(statements, true); + var body = ts.createBlock(statements, /*multiLine*/ true); if (currentModuleInfo.hasExportStarsToExportValues && !compilerOptions.importHelpers) { + // If we have any `export * from ...` declarations + // we need to inform the emitter to add the __export helper. ts.addEmitHelper(body, exportStarHelper); } if (needUMDDynamicImportHelper) { @@ -59982,6 +72186,14 @@ var ts; } return body; } + /** + * Adds the down-level representation of `export=` to the statement list if one exists + * in the source file. + * + * @param statements The Statement list to modify. + * @param emitAsReturn A value indicating whether to emit the `export=` statement as a + * return statement. + */ function addExportEqualsIfNeeded(statements, emitAsReturn) { if (currentModuleInfo.exportEquals) { var expressionResult = ts.visitNode(currentModuleInfo.exportEquals.expression, moduleExpressionElementVisitor); @@ -59989,50 +72201,60 @@ var ts; if (emitAsReturn) { var statement = ts.createReturn(expressionResult); ts.setTextRange(statement, currentModuleInfo.exportEquals); - ts.setEmitFlags(statement, 384 | 1536); + ts.setEmitFlags(statement, 384 /* NoTokenSourceMaps */ | 1536 /* NoComments */); statements.push(statement); } else { var statement = ts.createStatement(ts.createAssignment(ts.createPropertyAccess(ts.createIdentifier("module"), "exports"), expressionResult)); ts.setTextRange(statement, currentModuleInfo.exportEquals); - ts.setEmitFlags(statement, 1536); + ts.setEmitFlags(statement, 1536 /* NoComments */); statements.push(statement); } } } } + // + // Top-Level Source Element Visitors + // + /** + * Visits a node at the top level of the source file. + * + * @param node The node to visit. + */ function sourceElementVisitor(node) { switch (node.kind) { - case 244: + case 244 /* ImportDeclaration */: return visitImportDeclaration(node); - case 243: + case 243 /* ImportEqualsDeclaration */: return visitImportEqualsDeclaration(node); - case 250: + case 250 /* ExportDeclaration */: return visitExportDeclaration(node); - case 249: + case 249 /* ExportAssignment */: return visitExportAssignment(node); - case 214: + case 214 /* VariableStatement */: return visitVariableStatement(node); - case 234: + case 234 /* FunctionDeclaration */: return visitFunctionDeclaration(node); - case 235: + case 235 /* ClassDeclaration */: return visitClassDeclaration(node); - case 304: + case 304 /* MergeDeclarationMarker */: return visitMergeDeclarationMarker(node); - case 305: + case 305 /* EndOfDeclarationMarker */: return visitEndOfDeclarationMarker(node); default: return ts.visitEachChild(node, moduleExpressionElementVisitor, context); } } function moduleExpressionElementVisitor(node) { - if (!(node.transformFlags & 67108864) && !(node.transformFlags & 2048)) { + // This visitor does not need to descend into the tree if there is no dynamic import or destructuring assignment, + // as export/import statements are only transformed at the top level of a file. + if (!(node.transformFlags & 67108864 /* ContainsDynamicImport */) && !(node.transformFlags & 2048 /* ContainsDestructuringAssignment */)) { return node; } if (ts.isImportCall(node)) { return visitImportCallExpression(node); } - else if (node.transformFlags & 1024 && ts.isBinaryExpression(node)) { + else if (node.transformFlags & 1024 /* DestructuringAssignment */ && ts.isBinaryExpression(node)) { return visitDestructuringAssignment(node); } else { @@ -60044,24 +72266,24 @@ var ts; for (var _i = 0, _a = node.properties; _i < _a.length; _i++) { var elem = _a[_i]; switch (elem.kind) { - case 270: + case 270 /* PropertyAssignment */: if (destructuringNeedsFlattening(elem.initializer)) { return true; } break; - case 271: + case 271 /* ShorthandPropertyAssignment */: if (destructuringNeedsFlattening(elem.name)) { return true; } break; - case 272: + case 272 /* SpreadAssignment */: if (destructuringNeedsFlattening(elem.expression)) { return true; } break; - case 154: - case 156: - case 157: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return false; default: ts.Debug.assertNever(elem, "Unhandled object member kind"); } @@ -60087,13 +72309,13 @@ var ts; } function visitDestructuringAssignment(node) { if (destructuringNeedsFlattening(node.left)) { - return ts.flattenDestructuringAssignment(node, moduleExpressionElementVisitor, context, 0, false, createAllExportExpressions); + return ts.flattenDestructuringAssignment(node, moduleExpressionElementVisitor, context, 0 /* All */, /*needsValue*/ false, createAllExportExpressions); } return ts.visitEachChild(node, moduleExpressionElementVisitor, context); } function visitImportCallExpression(node) { var argument = ts.visitNode(ts.firstOrUndefined(node.arguments), moduleExpressionElementVisitor); - var containsLexicalThis = !!(node.transformFlags & 16384); + var containsLexicalThis = !!(node.transformFlags & 16384 /* ContainsLexicalThis */); switch (compilerOptions.module) { case ts.ModuleKind.AMD: return createImportCallExpressionAMD(argument, containsLexicalThis); @@ -60105,103 +72327,181 @@ var ts; } } function createImportCallExpressionUMD(arg, containsLexicalThis) { + // (function (factory) { + // ... (regular UMD) + // } + // })(function (require, exports, useSyncRequire) { + // "use strict"; + // Object.defineProperty(exports, "__esModule", { value: true }); + // var __syncRequire = typeof module === "object" && typeof module.exports === "object"; + // var __resolved = new Promise(function (resolve) { resolve(); }); + // ..... + // __syncRequire + // ? __resolved.then(function () { return require(x); }) /*CommonJs Require*/ + // : new Promise(function (_a, _b) { require([x], _a, _b); }); /*Amd Require*/ + // }); needUMDDynamicImportHelper = true; if (ts.isSimpleCopiableExpression(arg)) { - var argClone = ts.isGeneratedIdentifier(arg) ? arg : ts.isStringLiteral(arg) ? ts.createLiteral(arg) : ts.setEmitFlags(ts.setTextRange(ts.getSynthesizedClone(arg), arg), 1536); - return ts.createConditional(ts.createIdentifier("__syncRequire"), createImportCallExpressionCommonJS(arg, containsLexicalThis), createImportCallExpressionAMD(argClone, containsLexicalThis)); + var argClone = ts.isGeneratedIdentifier(arg) ? arg : ts.isStringLiteral(arg) ? ts.createLiteral(arg) : ts.setEmitFlags(ts.setTextRange(ts.getSynthesizedClone(arg), arg), 1536 /* NoComments */); + return ts.createConditional( + /*condition*/ ts.createIdentifier("__syncRequire"), + /*whenTrue*/ createImportCallExpressionCommonJS(arg, containsLexicalThis), + /*whenFalse*/ createImportCallExpressionAMD(argClone, containsLexicalThis)); } else { var temp = ts.createTempVariable(hoistVariableDeclaration); - return ts.createComma(ts.createAssignment(temp, arg), ts.createConditional(ts.createIdentifier("__syncRequire"), createImportCallExpressionCommonJS(temp, containsLexicalThis), createImportCallExpressionAMD(temp, containsLexicalThis))); + return ts.createComma(ts.createAssignment(temp, arg), ts.createConditional( + /*condition*/ ts.createIdentifier("__syncRequire"), + /*whenTrue*/ createImportCallExpressionCommonJS(temp, containsLexicalThis), + /*whenFalse*/ createImportCallExpressionAMD(temp, containsLexicalThis))); } } function createImportCallExpressionAMD(arg, containsLexicalThis) { + // improt("./blah") + // emit as + // define(["require", "exports", "blah"], function (require, exports) { + // ... + // new Promise(function (_a, _b) { require([x], _a, _b); }); /*Amd Require*/ + // }); var resolve = ts.createUniqueName("resolve"); var reject = ts.createUniqueName("reject"); var parameters = [ - ts.createParameter(undefined, undefined, undefined, resolve), - ts.createParameter(undefined, undefined, undefined, reject) + ts.createParameter(/*decorator*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ resolve), + ts.createParameter(/*decorator*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ reject) ]; var body = ts.createBlock([ - ts.createStatement(ts.createCall(ts.createIdentifier("require"), undefined, [ts.createArrayLiteral([arg || ts.createOmittedExpression()]), resolve, reject])) + ts.createStatement(ts.createCall(ts.createIdentifier("require"), + /*typeArguments*/ undefined, [ts.createArrayLiteral([arg || ts.createOmittedExpression()]), resolve, reject])) ]); var func; - if (languageVersion >= 2) { - func = ts.createArrowFunction(undefined, undefined, parameters, undefined, undefined, body); + if (languageVersion >= 2 /* ES2015 */) { + func = ts.createArrowFunction( + /*modifiers*/ undefined, + /*typeParameters*/ undefined, parameters, + /*type*/ undefined, + /*equalsGreaterThanToken*/ undefined, body); } else { - func = ts.createFunctionExpression(undefined, undefined, undefined, undefined, parameters, undefined, body); + func = ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, parameters, + /*type*/ undefined, body); + // if there is a lexical 'this' in the import call arguments, ensure we indicate + // that this new function expression indicates it captures 'this' so that the + // es2015 transformer will properly substitute 'this' with '_this'. if (containsLexicalThis) { - ts.setEmitFlags(func, 8); + ts.setEmitFlags(func, 8 /* CapturesThis */); } } - var promise = ts.createNew(ts.createIdentifier("Promise"), undefined, [func]); + var promise = ts.createNew(ts.createIdentifier("Promise"), /*typeArguments*/ undefined, [func]); if (compilerOptions.esModuleInterop) { context.requestEmitHelper(importStarHelper); - return ts.createCall(ts.createPropertyAccess(promise, ts.createIdentifier("then")), undefined, [ts.getHelperName("__importStar")]); + return ts.createCall(ts.createPropertyAccess(promise, ts.createIdentifier("then")), /*typeArguments*/ undefined, [ts.getHelperName("__importStar")]); } return promise; } function createImportCallExpressionCommonJS(arg, containsLexicalThis) { - var promiseResolveCall = ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Promise"), "resolve"), undefined, []); - var requireCall = ts.createCall(ts.createIdentifier("require"), undefined, arg ? [arg] : []); + // import("./blah") + // emit as + // Promise.resolve().then(function () { return require(x); }) /*CommonJs Require*/ + // We have to wrap require in then callback so that require is done in asynchronously + // if we simply do require in resolve callback in Promise constructor. We will execute the loading immediately + var promiseResolveCall = ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Promise"), "resolve"), /*typeArguments*/ undefined, /*argumentsArray*/ []); + var requireCall = ts.createCall(ts.createIdentifier("require"), /*typeArguments*/ undefined, arg ? [arg] : []); if (compilerOptions.esModuleInterop) { context.requestEmitHelper(importStarHelper); - requireCall = ts.createCall(ts.getHelperName("__importStar"), undefined, [requireCall]); + requireCall = ts.createCall(ts.getHelperName("__importStar"), /*typeArguments*/ undefined, [requireCall]); } var func; - if (languageVersion >= 2) { - func = ts.createArrowFunction(undefined, undefined, [], undefined, undefined, requireCall); + if (languageVersion >= 2 /* ES2015 */) { + func = ts.createArrowFunction( + /*modifiers*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ [], + /*type*/ undefined, + /*equalsGreaterThanToken*/ undefined, requireCall); } else { - func = ts.createFunctionExpression(undefined, undefined, undefined, undefined, [], undefined, ts.createBlock([ts.createReturn(requireCall)])); + func = ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ [], + /*type*/ undefined, ts.createBlock([ts.createReturn(requireCall)])); + // if there is a lexical 'this' in the import call arguments, ensure we indicate + // that this new function expression indicates it captures 'this' so that the + // es2015 transformer will properly substitute 'this' with '_this'. if (containsLexicalThis) { - ts.setEmitFlags(func, 8); + ts.setEmitFlags(func, 8 /* CapturesThis */); } } - return ts.createCall(ts.createPropertyAccess(promiseResolveCall, "then"), undefined, [func]); + return ts.createCall(ts.createPropertyAccess(promiseResolveCall, "then"), /*typeArguments*/ undefined, [func]); } function getHelperExpressionForImport(node, innerExpr) { - if (!compilerOptions.esModuleInterop || ts.getEmitFlags(node) & 67108864) { + if (!compilerOptions.esModuleInterop || ts.getEmitFlags(node) & 67108864 /* NeverApplyImportHelper */) { return innerExpr; } if (ts.getImportNeedsImportStarHelper(node)) { context.requestEmitHelper(importStarHelper); - return ts.createCall(ts.getHelperName("__importStar"), undefined, [innerExpr]); + return ts.createCall(ts.getHelperName("__importStar"), /*typeArguments*/ undefined, [innerExpr]); } if (ts.getImportNeedsImportDefaultHelper(node)) { context.requestEmitHelper(importDefaultHelper); - return ts.createCall(ts.getHelperName("__importDefault"), undefined, [innerExpr]); + return ts.createCall(ts.getHelperName("__importDefault"), /*typeArguments*/ undefined, [innerExpr]); } return innerExpr; } + /** + * Visits an ImportDeclaration node. + * + * @param node The node to visit. + */ function visitImportDeclaration(node) { var statements; var namespaceDeclaration = ts.getNamespaceDeclarationNode(node); if (moduleKind !== ts.ModuleKind.AMD) { if (!node.importClause) { + // import "mod"; return ts.setTextRange(ts.createStatement(createRequireCall(node)), node); } else { var variables = []; if (namespaceDeclaration && !ts.isDefaultImport(node)) { - variables.push(ts.createVariableDeclaration(ts.getSynthesizedClone(namespaceDeclaration.name), undefined, getHelperExpressionForImport(node, createRequireCall(node)))); + // import * as n from "mod"; + variables.push(ts.createVariableDeclaration(ts.getSynthesizedClone(namespaceDeclaration.name), + /*type*/ undefined, getHelperExpressionForImport(node, createRequireCall(node)))); } else { - variables.push(ts.createVariableDeclaration(ts.getGeneratedNameForNode(node), undefined, getHelperExpressionForImport(node, createRequireCall(node)))); + // import d from "mod"; + // import { x, y } from "mod"; + // import d, { x, y } from "mod"; + // import d, * as n from "mod"; + variables.push(ts.createVariableDeclaration(ts.getGeneratedNameForNode(node), + /*type*/ undefined, getHelperExpressionForImport(node, createRequireCall(node)))); if (namespaceDeclaration && ts.isDefaultImport(node)) { - variables.push(ts.createVariableDeclaration(ts.getSynthesizedClone(namespaceDeclaration.name), undefined, ts.getGeneratedNameForNode(node))); + variables.push(ts.createVariableDeclaration(ts.getSynthesizedClone(namespaceDeclaration.name), + /*type*/ undefined, ts.getGeneratedNameForNode(node))); } } - statements = ts.append(statements, ts.setTextRange(ts.createVariableStatement(undefined, ts.createVariableDeclarationList(variables, languageVersion >= 2 ? 2 : 0)), node)); + statements = ts.append(statements, ts.setTextRange(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList(variables, languageVersion >= 2 /* ES2015 */ ? 2 /* Const */ : 0 /* None */)), + /*location*/ node)); } } else if (namespaceDeclaration && ts.isDefaultImport(node)) { - statements = ts.append(statements, ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.setTextRange(ts.createVariableDeclaration(ts.getSynthesizedClone(namespaceDeclaration.name), undefined, ts.getGeneratedNameForNode(node)), node) - ], languageVersion >= 2 ? 2 : 0))); + // import d, * as n from "mod"; + statements = ts.append(statements, ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.setTextRange(ts.createVariableDeclaration(ts.getSynthesizedClone(namespaceDeclaration.name), + /*type*/ undefined, ts.getGeneratedNameForNode(node)), + /*location*/ node) + ], languageVersion >= 2 /* ES2015 */ ? 2 /* Const */ : 0 /* None */))); } if (hasAssociatedEndOfDeclarationMarker(node)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfImportDeclaration(deferredExports[id], node); } @@ -60210,33 +72510,47 @@ var ts; } return ts.singleOrMany(statements); } + /** + * Creates a `require()` call to import an external module. + * + * @param importNode The declararation to import. + */ function createRequireCall(importNode) { var moduleName = ts.getExternalModuleNameLiteral(importNode, currentSourceFile, host, resolver, compilerOptions); var args = []; if (moduleName) { args.push(moduleName); } - return ts.createCall(ts.createIdentifier("require"), undefined, args); + return ts.createCall(ts.createIdentifier("require"), /*typeArguments*/ undefined, args); } + /** + * Visits an ImportEqualsDeclaration node. + * + * @param node The node to visit. + */ function visitImportEqualsDeclaration(node) { ts.Debug.assert(ts.isExternalModuleImportEqualsDeclaration(node), "import= for internal module references should be handled in an earlier transformer."); var statements; if (moduleKind !== ts.ModuleKind.AMD) { - if (ts.hasModifier(node, 1)) { + if (ts.hasModifier(node, 1 /* Export */)) { statements = ts.append(statements, ts.setTextRange(ts.createStatement(createExportExpression(node.name, createRequireCall(node))), node)); } else { - statements = ts.append(statements, ts.setTextRange(ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.createVariableDeclaration(ts.getSynthesizedClone(node.name), undefined, createRequireCall(node)) - ], languageVersion >= 2 ? 2 : 0)), node)); + statements = ts.append(statements, ts.setTextRange(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(ts.getSynthesizedClone(node.name), + /*type*/ undefined, createRequireCall(node)) + ], + /*flags*/ languageVersion >= 2 /* ES2015 */ ? 2 /* Const */ : 0 /* None */)), node)); } } else { - if (ts.hasModifier(node, 1)) { + if (ts.hasModifier(node, 1 /* Export */)) { statements = ts.append(statements, ts.setTextRange(ts.createStatement(createExportExpression(ts.getExportName(node), ts.getLocalName(node))), node)); } } if (hasAssociatedEndOfDeclarationMarker(node)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfImportEqualsDeclaration(deferredExports[id], node); } @@ -60245,17 +72559,28 @@ var ts; } return ts.singleOrMany(statements); } + /** + * Visits an ExportDeclaration node. + * + * @param The node to visit. + */ function visitExportDeclaration(node) { if (!node.moduleSpecifier) { + // Elide export declarations with no module specifier as they are handled + // elsewhere. return undefined; } var generatedName = ts.getGeneratedNameForNode(node); if (node.exportClause) { var statements = []; + // export { x, y } from "mod"; if (moduleKind !== ts.ModuleKind.AMD) { - statements.push(ts.setTextRange(ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.createVariableDeclaration(generatedName, undefined, createRequireCall(node)) - ])), node)); + statements.push(ts.setTextRange(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(generatedName, + /*type*/ undefined, createRequireCall(node)) + ])), + /*location*/ node)); } for (var _i = 0, _a = node.exportClause.elements; _i < _a.length; _i++) { var specifier = _a[_i]; @@ -60265,9 +72590,15 @@ var ts; return ts.singleOrMany(statements); } else { + // export * from "mod"; return ts.setTextRange(ts.createStatement(createExportStarHelper(context, moduleKind !== ts.ModuleKind.AMD ? createRequireCall(node) : generatedName)), node); } } + /** + * Visits an ExportAssignment node. + * + * @param node The node to visit. + */ function visitExportAssignment(node) { if (node.isExportEquals) { return undefined; @@ -60275,23 +72606,35 @@ var ts; var statements; var original = node.original; if (original && hasAssociatedEndOfDeclarationMarker(original)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); - deferredExports[id] = appendExportStatement(deferredExports[id], ts.createIdentifier("default"), ts.visitNode(node.expression, moduleExpressionElementVisitor), node, true); + deferredExports[id] = appendExportStatement(deferredExports[id], ts.createIdentifier("default"), ts.visitNode(node.expression, moduleExpressionElementVisitor), /*location*/ node, /*allowComments*/ true); } else { - statements = appendExportStatement(statements, ts.createIdentifier("default"), ts.visitNode(node.expression, moduleExpressionElementVisitor), node, true); + statements = appendExportStatement(statements, ts.createIdentifier("default"), ts.visitNode(node.expression, moduleExpressionElementVisitor), /*location*/ node, /*allowComments*/ true); } return ts.singleOrMany(statements); } + /** + * Visits a FunctionDeclaration node. + * + * @param node The node to visit. + */ function visitFunctionDeclaration(node) { var statements; - if (ts.hasModifier(node, 1)) { - statements = ts.append(statements, ts.setOriginalNode(ts.setTextRange(ts.createFunctionDeclaration(undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), node.asteriskToken, ts.getDeclarationName(node, true, true), undefined, ts.visitNodes(node.parameters, moduleExpressionElementVisitor), undefined, ts.visitEachChild(node.body, moduleExpressionElementVisitor, context)), node), node)); + if (ts.hasModifier(node, 1 /* Export */)) { + statements = ts.append(statements, ts.setOriginalNode(ts.setTextRange(ts.createFunctionDeclaration( + /*decorators*/ undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), node.asteriskToken, ts.getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true), + /*typeParameters*/ undefined, ts.visitNodes(node.parameters, moduleExpressionElementVisitor), + /*type*/ undefined, ts.visitEachChild(node.body, moduleExpressionElementVisitor, context)), + /*location*/ node), + /*original*/ node)); } else { statements = ts.append(statements, ts.visitEachChild(node, moduleExpressionElementVisitor, context)); } if (hasAssociatedEndOfDeclarationMarker(node)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfHoistedDeclaration(deferredExports[id], node); } @@ -60300,15 +72643,23 @@ var ts; } return ts.singleOrMany(statements); } + /** + * Visits a ClassDeclaration node. + * + * @param node The node to visit. + */ function visitClassDeclaration(node) { var statements; - if (ts.hasModifier(node, 1)) { - statements = ts.append(statements, ts.setOriginalNode(ts.setTextRange(ts.createClassDeclaration(undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), ts.getDeclarationName(node, true, true), undefined, ts.visitNodes(node.heritageClauses, moduleExpressionElementVisitor), ts.visitNodes(node.members, moduleExpressionElementVisitor)), node), node)); + if (ts.hasModifier(node, 1 /* Export */)) { + statements = ts.append(statements, ts.setOriginalNode(ts.setTextRange(ts.createClassDeclaration( + /*decorators*/ undefined, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), ts.getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true), + /*typeParameters*/ undefined, ts.visitNodes(node.heritageClauses, moduleExpressionElementVisitor), ts.visitNodes(node.members, moduleExpressionElementVisitor)), node), node)); } else { statements = ts.append(statements, ts.visitEachChild(node, moduleExpressionElementVisitor, context)); } if (hasAssociatedEndOfDeclarationMarker(node)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfHoistedDeclaration(deferredExports[id], node); } @@ -60317,12 +72668,19 @@ var ts; } return ts.singleOrMany(statements); } + /** + * Visits a VariableStatement node. + * + * @param node The node to visit. + */ function visitVariableStatement(node) { var statements; var variables; var expressions; - if (ts.hasModifier(node, 1)) { + if (ts.hasModifier(node, 1 /* Export */)) { var modifiers = void 0; + // If we're exporting these variables, then these just become assignments to 'exports.x'. + // We only want to emit assignments for variables with initializers. for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) { var variable = _a[_i]; if (ts.isIdentifier(variable.name) && ts.isLocalName(variable.name)) { @@ -60346,6 +72704,7 @@ var ts; statements = ts.append(statements, ts.visitEachChild(node, moduleExpressionElementVisitor, context)); } if (hasAssociatedEndOfDeclarationMarker(node)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfVariableStatement(deferredExports[id], node); } @@ -60357,35 +72716,72 @@ var ts; function createAllExportExpressions(name, value, location) { var exportedNames = getExports(name); if (exportedNames) { + // For each additional export of the declaration, apply an export assignment. var expression = ts.isExportName(name) ? value : ts.createAssignment(name, value); for (var _i = 0, exportedNames_1 = exportedNames; _i < exportedNames_1.length; _i++) { var exportName = exportedNames_1[_i]; - ts.setEmitFlags(expression, 4); - expression = createExportExpression(exportName, expression, location); + // Mark the node to prevent triggering substitution. + ts.setEmitFlags(expression, 4 /* NoSubstitution */); + expression = createExportExpression(exportName, expression, /*location*/ location); } return expression; } return ts.createAssignment(name, value); } + /** + * Transforms an exported variable with an initializer into an expression. + * + * @param node The node to transform. + */ function transformInitializedVariable(node) { if (ts.isBindingPattern(node.name)) { - return ts.flattenDestructuringAssignment(ts.visitNode(node, moduleExpressionElementVisitor), undefined, context, 0, false, createAllExportExpressions); + return ts.flattenDestructuringAssignment(ts.visitNode(node, moduleExpressionElementVisitor), + /*visitor*/ undefined, context, 0 /* All */, + /*needsValue*/ false, createAllExportExpressions); } else { - return ts.createAssignment(ts.setTextRange(ts.createPropertyAccess(ts.createIdentifier("exports"), node.name), node.name), ts.visitNode(node.initializer, moduleExpressionElementVisitor)); + return ts.createAssignment(ts.setTextRange(ts.createPropertyAccess(ts.createIdentifier("exports"), node.name), + /*location*/ node.name), ts.visitNode(node.initializer, moduleExpressionElementVisitor)); } } + /** + * Visits a MergeDeclarationMarker used as a placeholder for the beginning of a merged + * and transformed declaration. + * + * @param node The node to visit. + */ function visitMergeDeclarationMarker(node) { - if (hasAssociatedEndOfDeclarationMarker(node) && node.original.kind === 214) { + // For an EnumDeclaration or ModuleDeclaration that merges with a preceeding + // declaration we do not emit a leading variable declaration. To preserve the + // begin/end semantics of the declararation and to properly handle exports + // we wrapped the leading variable declaration in a `MergeDeclarationMarker`. + // + // To balance the declaration, add the exports of the elided variable + // statement. + if (hasAssociatedEndOfDeclarationMarker(node) && node.original.kind === 214 /* VariableStatement */) { var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfVariableStatement(deferredExports[id], node.original); } return node; } + /** + * Determines whether a node has an associated EndOfDeclarationMarker. + * + * @param node The node to test. + */ function hasAssociatedEndOfDeclarationMarker(node) { - return (ts.getEmitFlags(node) & 4194304) !== 0; + return (ts.getEmitFlags(node) & 4194304 /* HasEndOfDeclarationMarker */) !== 0; } + /** + * Visits a DeclarationMarker used as a placeholder for the end of a transformed + * declaration. + * + * @param node The node to visit. + */ function visitEndOfDeclarationMarker(node) { + // For some transformations we emit an `EndOfDeclarationMarker` to mark the actual + // end of the transformed declaration. We use this marker to emit any deferred exports + // of the declaration. var id = ts.getOriginalNodeId(node); var statements = deferredExports[id]; if (statements) { @@ -60394,6 +72790,15 @@ var ts; } return node; } + /** + * Appends the exports of an ImportDeclaration to a statement list, returning the + * statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param decl The declaration whose exports are to be recorded. + */ function appendExportsOfImportDeclaration(statements, decl) { if (currentModuleInfo.exportEquals) { return statements; @@ -60408,10 +72813,10 @@ var ts; var namedBindings = importClause.namedBindings; if (namedBindings) { switch (namedBindings.kind) { - case 246: + case 246 /* NamespaceImport */: statements = appendExportsOfDeclaration(statements, namedBindings); break; - case 247: + case 247 /* NamedImports */: for (var _i = 0, _a = namedBindings.elements; _i < _a.length; _i++) { var importBinding = _a[_i]; statements = appendExportsOfDeclaration(statements, importBinding); @@ -60421,12 +72826,30 @@ var ts; } return statements; } + /** + * Appends the exports of an ImportEqualsDeclaration to a statement list, returning the + * statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param decl The declaration whose exports are to be recorded. + */ function appendExportsOfImportEqualsDeclaration(statements, decl) { if (currentModuleInfo.exportEquals) { return statements; } return appendExportsOfDeclaration(statements, decl); } + /** + * Appends the exports of a VariableStatement to a statement list, returning the statement + * list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param node The VariableStatement whose exports are to be recorded. + */ function appendExportsOfVariableStatement(statements, node) { if (currentModuleInfo.exportEquals) { return statements; @@ -60437,6 +72860,15 @@ var ts; } return statements; } + /** + * Appends the exports of a VariableDeclaration or BindingElement to a statement list, + * returning the statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param decl The declaration whose exports are to be recorded. + */ function appendExportsOfBindingElement(statements, decl) { if (currentModuleInfo.exportEquals) { return statements; @@ -60454,72 +72886,136 @@ var ts; } return statements; } + /** + * Appends the exports of a ClassDeclaration or FunctionDeclaration to a statement list, + * returning the statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param decl The declaration whose exports are to be recorded. + */ function appendExportsOfHoistedDeclaration(statements, decl) { if (currentModuleInfo.exportEquals) { return statements; } - if (ts.hasModifier(decl, 1)) { - var exportName = ts.hasModifier(decl, 512) ? ts.createIdentifier("default") : ts.getDeclarationName(decl); - statements = appendExportStatement(statements, exportName, ts.getLocalName(decl), decl); + if (ts.hasModifier(decl, 1 /* Export */)) { + var exportName = ts.hasModifier(decl, 512 /* Default */) ? ts.createIdentifier("default") : ts.getDeclarationName(decl); + statements = appendExportStatement(statements, exportName, ts.getLocalName(decl), /*location*/ decl); } if (decl.name) { statements = appendExportsOfDeclaration(statements, decl); } return statements; } + /** + * Appends the exports of a declaration to a statement list, returning the statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param decl The declaration to export. + */ function appendExportsOfDeclaration(statements, decl) { var name = ts.getDeclarationName(decl); var exportSpecifiers = currentModuleInfo.exportSpecifiers.get(ts.idText(name)); if (exportSpecifiers) { for (var _i = 0, exportSpecifiers_1 = exportSpecifiers; _i < exportSpecifiers_1.length; _i++) { var exportSpecifier = exportSpecifiers_1[_i]; - statements = appendExportStatement(statements, exportSpecifier.name, name, exportSpecifier.name); + statements = appendExportStatement(statements, exportSpecifier.name, name, /*location*/ exportSpecifier.name); } } return statements; } + /** + * Appends the down-level representation of an export to a statement list, returning the + * statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param exportName The name of the export. + * @param expression The expression to export. + * @param location The location to use for source maps and comments for the export. + * @param allowComments Whether to allow comments on the export. + */ function appendExportStatement(statements, exportName, expression, location, allowComments) { statements = ts.append(statements, createExportStatement(exportName, expression, location, allowComments)); return statements; } function createUnderscoreUnderscoreESModule() { var statement; - if (languageVersion === 0) { - statement = ts.createStatement(createExportExpression(ts.createIdentifier("__esModule"), ts.createLiteral(true))); + if (languageVersion === 0 /* ES3 */) { + statement = ts.createStatement(createExportExpression(ts.createIdentifier("__esModule"), ts.createLiteral(/*value*/ true))); } else { - statement = ts.createStatement(ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Object"), "defineProperty"), undefined, [ + statement = ts.createStatement(ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Object"), "defineProperty"), + /*typeArguments*/ undefined, [ ts.createIdentifier("exports"), ts.createLiteral("__esModule"), ts.createObjectLiteral([ - ts.createPropertyAssignment("value", ts.createLiteral(true)) + ts.createPropertyAssignment("value", ts.createLiteral(/*value*/ true)) ]) ])); } - ts.setEmitFlags(statement, 1048576); + ts.setEmitFlags(statement, 1048576 /* CustomPrologue */); return statement; } + /** + * Creates a call to the current file's export function to export a value. + * + * @param name The bound name of the export. + * @param value The exported value. + * @param location The location to use for source maps and comments for the export. + * @param allowComments An optional value indicating whether to emit comments for the statement. + */ function createExportStatement(name, value, location, allowComments) { var statement = ts.setTextRange(ts.createStatement(createExportExpression(name, value)), location); ts.startOnNewLine(statement); if (!allowComments) { - ts.setEmitFlags(statement, 1536); + ts.setEmitFlags(statement, 1536 /* NoComments */); } return statement; } + /** + * Creates a call to the current file's export function to export a value. + * + * @param name The bound name of the export. + * @param value The exported value. + * @param location The location to use for source maps and comments for the export. + */ function createExportExpression(name, value, location) { return ts.setTextRange(ts.createAssignment(ts.createPropertyAccess(ts.createIdentifier("exports"), ts.getSynthesizedClone(name)), value), location); } + // + // Modifier Visitors + // + /** + * Visit nodes to elide module-specific modifiers. + * + * @param node The node to visit. + */ function modifierVisitor(node) { + // Elide module-specific modifiers. switch (node.kind) { - case 84: - case 79: + case 84 /* ExportKeyword */: + case 79 /* DefaultKeyword */: return undefined; } return node; } + // + // Emit Notification + // + /** + * Hook for node emit notifications. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emit A callback used to emit the node in the printer. + */ function onEmitNode(hint, node, emitCallback) { - if (node.kind === 274) { + if (node.kind === 274 /* SourceFile */) { currentSourceFile = node; currentModuleInfo = moduleInfoMap[ts.getOriginalNodeId(currentSourceFile)]; noSubstitution = []; @@ -60532,12 +73028,21 @@ var ts; previousOnEmitNode(hint, node, emitCallback); } } + // + // Substitutions + // + /** + * Hooks node substitutions. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to substitute. + */ function onSubstituteNode(hint, node) { node = previousOnSubstituteNode(hint, node); if (node.id && noSubstitution[node.id]) { return node; } - if (hint === 1) { + if (hint === 1 /* Expression */) { return substituteExpression(node); } else if (ts.isShorthandPropertyAssignment(node)) { @@ -60545,10 +73050,18 @@ var ts; } return node; } + /** + * Substitution for a ShorthandPropertyAssignment whose declaration name is an imported + * or exported symbol. + * + * @param node The node to substitute. + */ function substituteShorthandPropertyAssignment(node) { var name = node.name; var exportedOrImportedName = substituteExpressionIdentifier(name); if (exportedOrImportedName !== name) { + // A shorthand property with an assignment initializer is probably part of a + // destructuring assignment if (node.objectAssignmentInitializer) { var initializer = ts.createAssignment(exportedOrImportedName, node.objectAssignmentInitializer); return ts.setTextRange(ts.createPropertyAssignment(name, initializer), node); @@ -60557,20 +73070,31 @@ var ts; } return node; } + /** + * Substitution for an Expression that may contain an imported or exported symbol. + * + * @param node The node to substitute. + */ function substituteExpression(node) { switch (node.kind) { - case 71: + case 71 /* Identifier */: return substituteExpressionIdentifier(node); - case 200: + case 200 /* BinaryExpression */: return substituteBinaryExpression(node); - case 199: - case 198: + case 199 /* PostfixUnaryExpression */: + case 198 /* PrefixUnaryExpression */: return substituteUnaryExpression(node); } return node; } + /** + * Substitution for an Identifier expression that may contain an imported or exported + * symbol. + * + * @param node The node to substitute. + */ function substituteExpressionIdentifier(node) { - if (ts.getEmitFlags(node) & 4096) { + if (ts.getEmitFlags(node) & 4096 /* HelperName */) { var externalHelpersModuleName = ts.getExternalHelpersModuleName(currentSourceFile); if (externalHelpersModuleName) { return ts.createPropertyAccess(externalHelpersModuleName, node); @@ -60579,23 +73103,39 @@ var ts; } if (!ts.isGeneratedIdentifier(node) && !ts.isLocalName(node)) { var exportContainer = resolver.getReferencedExportContainer(node, ts.isExportName(node)); - if (exportContainer && exportContainer.kind === 274) { - return ts.setTextRange(ts.createPropertyAccess(ts.createIdentifier("exports"), ts.getSynthesizedClone(node)), node); + if (exportContainer && exportContainer.kind === 274 /* SourceFile */) { + return ts.setTextRange(ts.createPropertyAccess(ts.createIdentifier("exports"), ts.getSynthesizedClone(node)), + /*location*/ node); } var importDeclaration = resolver.getReferencedImportDeclaration(node); if (importDeclaration) { if (ts.isImportClause(importDeclaration)) { - return ts.setTextRange(ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent), ts.createIdentifier("default")), node); + return ts.setTextRange(ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent), ts.createIdentifier("default")), + /*location*/ node); } else if (ts.isImportSpecifier(importDeclaration)) { var name = importDeclaration.propertyName || importDeclaration.name; - return ts.setTextRange(ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent.parent.parent), ts.getSynthesizedClone(name)), node); + return ts.setTextRange(ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent.parent.parent), ts.getSynthesizedClone(name)), + /*location*/ node); } } } return node; } + /** + * Substitution for a BinaryExpression that may contain an imported or exported symbol. + * + * @param node The node to substitute. + */ function substituteBinaryExpression(node) { + // When we see an assignment expression whose left-hand side is an exported symbol, + // we should ensure all exports of that symbol are updated with the correct value. + // + // - We do not substitute generated identifiers for any reason. + // - We do not substitute identifiers tagged with the LocalName flag. + // - We do not substitute identifiers that were originally the name of an enum or + // namespace due to how they are transformed in TypeScript. + // - We only substitute identifiers that are exported at the top level. if (ts.isAssignmentOperator(node.operatorToken.kind) && ts.isIdentifier(node.left) && !ts.isGeneratedIdentifier(node.left) @@ -60603,30 +73143,48 @@ var ts; && !ts.isDeclarationNameOfEnumOrNamespace(node.left)) { var exportedNames = getExports(node.left); if (exportedNames) { + // For each additional export of the declaration, apply an export assignment. var expression = node; for (var _i = 0, exportedNames_2 = exportedNames; _i < exportedNames_2.length; _i++) { var exportName = exportedNames_2[_i]; + // Mark the node to prevent triggering this rule again. noSubstitution[ts.getNodeId(expression)] = true; - expression = createExportExpression(exportName, expression, node); + expression = createExportExpression(exportName, expression, /*location*/ node); } return expression; } } return node; } + /** + * Substitution for a UnaryExpression that may contain an imported or exported symbol. + * + * @param node The node to substitute. + */ function substituteUnaryExpression(node) { - if ((node.operator === 43 || node.operator === 44) + // When we see a prefix or postfix increment expression whose operand is an exported + // symbol, we should ensure all exports of that symbol are updated with the correct + // value. + // + // - We do not substitute generated identifiers for any reason. + // - We do not substitute identifiers tagged with the LocalName flag. + // - We do not substitute identifiers that were originally the name of an enum or + // namespace due to how they are transformed in TypeScript. + // - We only substitute identifiers that are exported at the top level. + if ((node.operator === 43 /* PlusPlusToken */ || node.operator === 44 /* MinusMinusToken */) && ts.isIdentifier(node.operand) && !ts.isGeneratedIdentifier(node.operand) && !ts.isLocalName(node.operand) && !ts.isDeclarationNameOfEnumOrNamespace(node.operand)) { var exportedNames = getExports(node.operand); if (exportedNames) { - var expression = node.kind === 199 - ? ts.setTextRange(ts.createBinary(node.operand, ts.createToken(node.operator === 43 ? 59 : 60), ts.createLiteral(1)), node) + var expression = node.kind === 199 /* PostfixUnaryExpression */ + ? ts.setTextRange(ts.createBinary(node.operand, ts.createToken(node.operator === 43 /* PlusPlusToken */ ? 59 /* PlusEqualsToken */ : 60 /* MinusEqualsToken */), ts.createLiteral(1)), + /*location*/ node) : node; for (var _i = 0, exportedNames_3 = exportedNames; _i < exportedNames_3.length; _i++) { var exportName = exportedNames_3[_i]; + // Mark the node to prevent triggering this rule again. noSubstitution[ts.getNodeId(expression)] = true; expression = createExportExpression(exportName, expression); } @@ -60635,6 +73193,11 @@ var ts; } return node; } + /** + * Gets the additional exports of a name. + * + * @param name The name. + */ function getExports(name) { if (!ts.isGeneratedIdentifier(name)) { var valueDeclaration = resolver.getReferencedImportDeclaration(name) @@ -60647,6 +73210,7 @@ var ts; } } ts.transformModule = transformModule; + // emit output for the __export helper function var exportStarHelper = { name: "typescript:export-star", scoped: true, @@ -60655,25 +73219,29 @@ var ts; function createExportStarHelper(context, module) { var compilerOptions = context.getCompilerOptions(); return compilerOptions.importHelpers - ? ts.createCall(ts.getHelperName("__exportStar"), undefined, [module, ts.createIdentifier("exports")]) - : ts.createCall(ts.createIdentifier("__export"), undefined, [module]); + ? ts.createCall(ts.getHelperName("__exportStar"), /*typeArguments*/ undefined, [module, ts.createIdentifier("exports")]) + : ts.createCall(ts.createIdentifier("__export"), /*typeArguments*/ undefined, [module]); } + // emit helper for dynamic import var dynamicImportUMDHelper = { name: "typescript:dynamicimport-sync-require", scoped: true, text: "\n var __syncRequire = typeof module === \"object\" && typeof module.exports === \"object\";" }; + // emit helper for `import * as Name from "foo"` var importStarHelper = { name: "typescript:commonjsimportstar", scoped: false, text: "\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];\n result[\"default\"] = mod;\n return result;\n};" }; + // emit helper for `import Name from "foo"` var importDefaultHelper = { name: "typescript:commonjsimportdefault", scoped: false, text: "\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};" }; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { function transformSystemModule(context) { @@ -60685,48 +73253,78 @@ var ts; var previousOnEmitNode = context.onEmitNode; context.onSubstituteNode = onSubstituteNode; context.onEmitNode = onEmitNode; - context.enableSubstitution(71); - context.enableSubstitution(271); - context.enableSubstitution(200); - context.enableSubstitution(198); - context.enableSubstitution(199); - context.enableEmitNotification(274); - var moduleInfoMap = []; - var deferredExports = []; - var exportFunctionsMap = []; - var noSubstitutionMap = []; - var currentSourceFile; - var moduleInfo; - var exportFunction; - var contextObject; + context.enableSubstitution(71 /* Identifier */); // Substitutes expression identifiers for imported symbols. + context.enableSubstitution(271 /* ShorthandPropertyAssignment */); // Substitutes expression identifiers for imported symbols + context.enableSubstitution(200 /* BinaryExpression */); // Substitutes assignments to exported symbols. + context.enableSubstitution(198 /* PrefixUnaryExpression */); // Substitutes updates to exported symbols. + context.enableSubstitution(199 /* PostfixUnaryExpression */); // Substitutes updates to exported symbols. + context.enableEmitNotification(274 /* SourceFile */); // Restore state when substituting nodes in a file. + var moduleInfoMap = []; // The ExternalModuleInfo for each file. + var deferredExports = []; // Exports to defer until an EndOfDeclarationMarker is found. + var exportFunctionsMap = []; // The export function associated with a source file. + var noSubstitutionMap = []; // Set of nodes for which substitution rules should be ignored for each file. + var currentSourceFile; // The current file. + var moduleInfo; // ExternalModuleInfo for the current file. + var exportFunction; // The export function for the current file. + var contextObject; // The context object for the current file. var hoistedStatements; var enclosingBlockScopedContainer; - var noSubstitution; + var noSubstitution; // Set of nodes for which substitution rules should be ignored. return ts.chainBundle(transformSourceFile); + /** + * Transforms the module aspects of a SourceFile. + * + * @param node The SourceFile node. + */ function transformSourceFile(node) { - if (node.isDeclarationFile || !(ts.isEffectiveExternalModule(node, compilerOptions) || node.transformFlags & 67108864)) { + if (node.isDeclarationFile || !(ts.isEffectiveExternalModule(node, compilerOptions) || node.transformFlags & 67108864 /* ContainsDynamicImport */)) { return node; } var id = ts.getOriginalNodeId(node); currentSourceFile = node; enclosingBlockScopedContainer = node; + // System modules have the following shape: + // + // System.register(['dep-1', ... 'dep-n'], function(exports) {/* module body function */}) + // + // The parameter 'exports' here is a callback '(name: string, value: T) => T' that + // is used to publish exported values. 'exports' returns its 'value' argument so in + // most cases expressions that mutate exported values can be rewritten as: + // + // expr -> exports('name', expr) + // + // The only exception in this rule is postfix unary operators, + // see comment to 'substitutePostfixUnaryExpression' for more details + // Collect information about the external module and dependency groups. moduleInfo = moduleInfoMap[id] = ts.collectExternalModuleInfo(node, resolver, compilerOptions); + // Make sure that the name of the 'exports' function does not conflict with + // existing identifiers. exportFunction = ts.createUniqueName("exports"); exportFunctionsMap[id] = exportFunction; contextObject = ts.createUniqueName("context"); + // Add the body of the module. var dependencyGroups = collectDependencyGroups(moduleInfo.externalImports); var moduleBodyBlock = createSystemModuleBody(node, dependencyGroups); - var moduleBodyFunction = ts.createFunctionExpression(undefined, undefined, undefined, undefined, [ - ts.createParameter(undefined, undefined, undefined, exportFunction), - ts.createParameter(undefined, undefined, undefined, contextObject) - ], undefined, moduleBodyBlock); + var moduleBodyFunction = ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ + ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, exportFunction), + ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, contextObject) + ], + /*type*/ undefined, moduleBodyBlock); + // Write the call to `System.register` + // Clear the emit-helpers flag for later passes since we'll have already used it in the module body + // So the helper will be emit at the correct position instead of at the top of the source-file var moduleName = ts.tryGetModuleNameFromFile(node, host, compilerOptions); var dependencies = ts.createArrayLiteral(ts.map(dependencyGroups, function (dependencyGroup) { return dependencyGroup.name; })); var updated = ts.setEmitFlags(ts.updateSourceFileNode(node, ts.setTextRange(ts.createNodeArray([ - ts.createStatement(ts.createCall(ts.createPropertyAccess(ts.createIdentifier("System"), "register"), undefined, moduleName + ts.createStatement(ts.createCall(ts.createPropertyAccess(ts.createIdentifier("System"), "register"), + /*typeArguments*/ undefined, moduleName ? [moduleName, dependencies, moduleBodyFunction] : [dependencies, moduleBodyFunction])) - ]), node.statements)), 1024); + ]), node.statements)), 1024 /* NoTrailingComments */); if (!(compilerOptions.outFile || compilerOptions.out)) { ts.moveEmitHelpers(updated, moduleBodyBlock, function (helper) { return !helper.scoped; }); } @@ -60742,6 +73340,11 @@ var ts; enclosingBlockScopedContainer = undefined; return ts.aggregateTransformFlags(updated); } + /** + * Collects the dependency groups for this files imports. + * + * @param externalImports The imports for the file. + */ function collectDependencyGroups(externalImports) { var groupIndices = ts.createMap(); var dependencyGroups = []; @@ -60752,6 +73355,7 @@ var ts; var text = externalModuleName.text; var groupIndex = groupIndices.get(text); if (groupIndex !== undefined) { + // deduplicate/group entries in dependency list by the dependency name dependencyGroups[groupIndex].externalImports.push(externalImport); } else { @@ -60765,42 +73369,124 @@ var ts; } return dependencyGroups; } + /** + * Adds the statements for the module body function for the source file. + * + * @param node The source file for the module. + * @param dependencyGroups The grouped dependencies of the module. + */ function createSystemModuleBody(node, dependencyGroups) { + // Shape of the body in system modules: + // + // function (exports) { + // + // + // + // return { + // setters: [ + // + // ], + // execute: function() { + // + // } + // } + // + // } + // + // i.e: + // + // import {x} from 'file1' + // var y = 1; + // export function foo() { return y + x(); } + // console.log(y); + // + // Will be transformed to: + // + // function(exports) { + // function foo() { return y + file_1.x(); } + // exports("foo", foo); + // var file_1, y; + // return { + // setters: [ + // function(v) { file_1 = v } + // ], + // execute(): function() { + // y = 1; + // console.log(y); + // } + // }; + // } var statements = []; + // We start a new lexical environment in this function body, but *not* in the + // body of the execute function. This allows us to emit temporary declarations + // only in the outer module body and not in the inner one. startLexicalEnvironment(); + // Add any prologue directives. var ensureUseStrict = ts.getStrictOptionValue(compilerOptions, "alwaysStrict") || (!compilerOptions.noImplicitUseStrict && ts.isExternalModule(currentSourceFile)); var statementOffset = ts.addPrologue(statements, node.statements, ensureUseStrict, sourceElementVisitor); - statements.push(ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.createVariableDeclaration("__moduleName", undefined, ts.createLogicalAnd(contextObject, ts.createPropertyAccess(contextObject, "id"))) + // var __moduleName = context_1 && context_1.id; + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration("__moduleName", + /*type*/ undefined, ts.createLogicalAnd(contextObject, ts.createPropertyAccess(contextObject, "id"))) ]))); + // Visit the synthetic external helpers import declaration if present ts.visitNode(moduleInfo.externalHelpersImportDeclaration, sourceElementVisitor, ts.isStatement); + // Visit the statements of the source file, emitting any transformations into + // the `executeStatements` array. We do this *before* we fill the `setters` array + // as we both emit transformations as well as aggregate some data used when creating + // setters. This allows us to reduce the number of times we need to loop through the + // statements of the source file. var executeStatements = ts.visitNodes(node.statements, sourceElementVisitor, ts.isStatement, statementOffset); + // Emit early exports for function declarations. ts.addRange(statements, hoistedStatements); + // We emit hoisted variables early to align roughly with our previous emit output. + // Two key differences in this approach are: + // - Temporary variables will appear at the top rather than at the bottom of the file ts.prependStatements(statements, endLexicalEnvironment()); - var exportStarFunction = addExportStarIfNeeded(statements); + var exportStarFunction = addExportStarIfNeeded(statements); // TODO: GH#18217 var moduleObject = ts.createObjectLiteral([ ts.createPropertyAssignment("setters", createSettersArray(exportStarFunction, dependencyGroups)), - ts.createPropertyAssignment("execute", ts.createFunctionExpression(undefined, undefined, undefined, undefined, [], undefined, ts.createBlock(executeStatements, true))) + ts.createPropertyAssignment("execute", ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ [], + /*type*/ undefined, ts.createBlock(executeStatements, /*multiLine*/ true))) ]); moduleObject.multiLine = true; statements.push(ts.createReturn(moduleObject)); - return ts.createBlock(statements, true); + return ts.createBlock(statements, /*multiLine*/ true); } + /** + * Adds an exportStar function to a statement list if it is needed for the file. + * + * @param statements A statement list. + */ function addExportStarIfNeeded(statements) { if (!moduleInfo.hasExportStarsToExportValues) { return; } + // 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. + // this set is used to filter names brought by star expors. + // local names set should only be added if we have anything exported if (!moduleInfo.exportedNames && moduleInfo.exportSpecifiers.size === 0) { + // no exported declarations (export var ...) or export specifiers (export {x}) + // check if we have any non star export declarations. var hasExportDeclarationWithExportClause = false; for (var _i = 0, _a = moduleInfo.externalImports; _i < _a.length; _i++) { var externalImport = _a[_i]; - if (externalImport.kind === 250 && externalImport.exportClause) { + if (externalImport.kind === 250 /* ExportDeclaration */ && externalImport.exportClause) { hasExportDeclarationWithExportClause = true; break; } } if (!hasExportDeclarationWithExportClause) { - var exportStarFunction_1 = createExportStarFunction(undefined); + // we still need to emit exportStar helper + var exportStarFunction_1 = createExportStarFunction(/*localNames*/ undefined); statements.push(exportStarFunction_1); return exportStarFunction_1.name; } @@ -60812,30 +73498,42 @@ var ts; if (exportedLocalName.escapedText === "default") { continue; } + // write name of exported declaration, i.e 'export var x...' exportedNames.push(ts.createPropertyAssignment(ts.createLiteral(exportedLocalName), ts.createTrue())); } } for (var _d = 0, _e = moduleInfo.externalImports; _d < _e.length; _d++) { var externalImport = _e[_d]; - if (externalImport.kind !== 250) { + if (externalImport.kind !== 250 /* ExportDeclaration */) { continue; } if (!externalImport.exportClause) { + // export * from ... continue; } for (var _f = 0, _g = externalImport.exportClause.elements; _f < _g.length; _f++) { var element = _g[_f]; + // write name of indirectly exported entry, i.e. 'export {x} from ...' exportedNames.push(ts.createPropertyAssignment(ts.createLiteral(ts.idText(element.name || element.propertyName)), ts.createTrue())); } } var exportedNamesStorageRef = ts.createUniqueName("exportedNames"); - statements.push(ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.createVariableDeclaration(exportedNamesStorageRef, undefined, ts.createObjectLiteral(exportedNames, true)) + statements.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(exportedNamesStorageRef, + /*type*/ undefined, ts.createObjectLiteral(exportedNames, /*multiline*/ true)) ]))); var exportStarFunction = createExportStarFunction(exportedNamesStorageRef); statements.push(exportStarFunction); return exportStarFunction.name; } + /** + * Creates an exportStar function for the file, with an optional set of excluded local + * names. + * + * @param localNames An optional reference to an object containing a set of excluded local + * names. + */ function createExportStarFunction(localNames) { var exportStarFunction = ts.createUniqueName("exportStar"); var m = ts.createIdentifier("m"); @@ -60843,79 +73541,135 @@ var ts; var exports = ts.createIdentifier("exports"); var condition = ts.createStrictInequality(n, ts.createLiteral("default")); if (localNames) { - condition = ts.createLogicalAnd(condition, ts.createLogicalNot(ts.createCall(ts.createPropertyAccess(localNames, "hasOwnProperty"), undefined, [n]))); + condition = ts.createLogicalAnd(condition, ts.createLogicalNot(ts.createCall(ts.createPropertyAccess(localNames, "hasOwnProperty"), + /*typeArguments*/ undefined, [n]))); } - return ts.createFunctionDeclaration(undefined, undefined, undefined, exportStarFunction, undefined, [ts.createParameter(undefined, undefined, undefined, m)], undefined, ts.createBlock([ - ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ - ts.createVariableDeclaration(exports, undefined, ts.createObjectLiteral([])) + return ts.createFunctionDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, exportStarFunction, + /*typeParameters*/ undefined, [ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, m)], + /*type*/ undefined, ts.createBlock([ + ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ + ts.createVariableDeclaration(exports, + /*type*/ undefined, ts.createObjectLiteral([])) ])), ts.createForIn(ts.createVariableDeclarationList([ - ts.createVariableDeclaration(n, undefined) + ts.createVariableDeclaration(n, /*type*/ undefined) ]), m, ts.createBlock([ - ts.setEmitFlags(ts.createIf(condition, ts.createStatement(ts.createAssignment(ts.createElementAccess(exports, n), ts.createElementAccess(m, n)))), 1) + ts.setEmitFlags(ts.createIf(condition, ts.createStatement(ts.createAssignment(ts.createElementAccess(exports, n), ts.createElementAccess(m, n)))), 1 /* SingleLine */) ])), - ts.createStatement(ts.createCall(exportFunction, undefined, [exports])) - ], true)); + ts.createStatement(ts.createCall(exportFunction, + /*typeArguments*/ undefined, [exports])) + ], /*multiline*/ true)); } + /** + * Creates an array setter callbacks for each dependency group. + * + * @param exportStarFunction A reference to an exportStarFunction for the file. + * @param dependencyGroups An array of grouped dependencies. + */ function createSettersArray(exportStarFunction, dependencyGroups) { var setters = []; for (var _i = 0, dependencyGroups_1 = dependencyGroups; _i < dependencyGroups_1.length; _i++) { var group_1 = dependencyGroups_1[_i]; + // derive a unique name for parameter from the first named entry in the group var localName = ts.forEach(group_1.externalImports, function (i) { return ts.getLocalNameForExternalImport(i, currentSourceFile); }); var parameterName = localName ? ts.getGeneratedNameForNode(localName) : ts.createUniqueName(""); var statements = []; for (var _a = 0, _b = group_1.externalImports; _a < _b.length; _a++) { var entry = _b[_a]; - var importVariableName = ts.getLocalNameForExternalImport(entry, currentSourceFile); + var importVariableName = ts.getLocalNameForExternalImport(entry, currentSourceFile); // TODO: GH#18217 switch (entry.kind) { - case 244: + case 244 /* ImportDeclaration */: if (!entry.importClause) { + // 'import "..."' case + // module is imported only for side-effects, no emit required break; } - case 243: + // falls through + case 243 /* ImportEqualsDeclaration */: ts.Debug.assert(importVariableName !== undefined); + // save import into the local statements.push(ts.createStatement(ts.createAssignment(importVariableName, parameterName))); break; - case 250: + case 250 /* ExportDeclaration */: ts.Debug.assert(importVariableName !== undefined); if (entry.exportClause) { + // export {a, b as c} from 'foo' + // + // emit as: + // + // exports_({ + // "a": _["a"], + // "c": _["b"] + // }); var properties = []; for (var _c = 0, _d = entry.exportClause.elements; _c < _d.length; _c++) { var e = _d[_c]; properties.push(ts.createPropertyAssignment(ts.createLiteral(ts.idText(e.name)), ts.createElementAccess(parameterName, ts.createLiteral(ts.idText(e.propertyName || e.name))))); } - statements.push(ts.createStatement(ts.createCall(exportFunction, undefined, [ts.createObjectLiteral(properties, true)]))); + statements.push(ts.createStatement(ts.createCall(exportFunction, + /*typeArguments*/ undefined, [ts.createObjectLiteral(properties, /*multiline*/ true)]))); } else { - statements.push(ts.createStatement(ts.createCall(exportStarFunction, undefined, [parameterName]))); + // export * from 'foo' + // + // emit as: + // + // exportStar(foo_1_1); + statements.push(ts.createStatement(ts.createCall(exportStarFunction, + /*typeArguments*/ undefined, [parameterName]))); } break; } } - setters.push(ts.createFunctionExpression(undefined, undefined, undefined, undefined, [ts.createParameter(undefined, undefined, undefined, parameterName)], undefined, ts.createBlock(statements, true))); + setters.push(ts.createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, [ts.createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)], + /*type*/ undefined, ts.createBlock(statements, /*multiLine*/ true))); } - return ts.createArrayLiteral(setters, true); + return ts.createArrayLiteral(setters, /*multiLine*/ true); } + // + // Top-level Source Element Visitors + // + /** + * Visit source elements at the top-level of a module. + * + * @param node The node to visit. + */ function sourceElementVisitor(node) { switch (node.kind) { - case 244: + case 244 /* ImportDeclaration */: return visitImportDeclaration(node); - case 243: + case 243 /* ImportEqualsDeclaration */: return visitImportEqualsDeclaration(node); - case 250: + case 250 /* ExportDeclaration */: + // ExportDeclarations are elided as they are handled via + // `appendExportsOfDeclaration`. return undefined; - case 249: + case 249 /* ExportAssignment */: return visitExportAssignment(node); default: return nestedElementVisitor(node); } } + /** + * Visits an ImportDeclaration node. + * + * @param node The node to visit. + */ function visitImportDeclaration(node) { var statements; if (node.importClause) { - hoistVariableDeclaration(ts.getLocalNameForExternalImport(node, currentSourceFile)); + hoistVariableDeclaration(ts.getLocalNameForExternalImport(node, currentSourceFile)); // TODO: GH#18217 } if (hasAssociatedEndOfDeclarationMarker(node)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfImportDeclaration(deferredExports[id], node); } @@ -60924,11 +73678,17 @@ var ts; } return ts.singleOrMany(statements); } + /** + * Visits an ImportEqualsDeclaration node. + * + * @param node The node to visit. + */ function visitImportEqualsDeclaration(node) { ts.Debug.assert(ts.isExternalModuleImportEqualsDeclaration(node), "import= for internal module references should be handled in an earlier transformer."); var statements; - hoistVariableDeclaration(ts.getLocalNameForExternalImport(node, currentSourceFile)); + hoistVariableDeclaration(ts.getLocalNameForExternalImport(node, currentSourceFile)); // TODO: GH#18217 if (hasAssociatedEndOfDeclarationMarker(node)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfImportEqualsDeclaration(deferredExports[id], node); } @@ -60937,28 +73697,43 @@ var ts; } return ts.singleOrMany(statements); } + /** + * Visits an ExportAssignment node. + * + * @param node The node to visit. + */ function visitExportAssignment(node) { if (node.isExportEquals) { + // Elide `export=` as it is illegal in a SystemJS module. return undefined; } var expression = ts.visitNode(node.expression, destructuringAndImportCallVisitor, ts.isExpression); var original = node.original; if (original && hasAssociatedEndOfDeclarationMarker(original)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); - deferredExports[id] = appendExportStatement(deferredExports[id], ts.createIdentifier("default"), expression, true); + deferredExports[id] = appendExportStatement(deferredExports[id], ts.createIdentifier("default"), expression, /*allowComments*/ true); } else { - return createExportStatement(ts.createIdentifier("default"), expression, true); + return createExportStatement(ts.createIdentifier("default"), expression, /*allowComments*/ true); } } + /** + * Visits a FunctionDeclaration, hoisting it to the outer module body function. + * + * @param node The node to visit. + */ function visitFunctionDeclaration(node) { - if (ts.hasModifier(node, 1)) { - hoistedStatements = ts.append(hoistedStatements, ts.updateFunctionDeclaration(node, node.decorators, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), node.asteriskToken, ts.getDeclarationName(node, true, true), undefined, ts.visitNodes(node.parameters, destructuringAndImportCallVisitor, ts.isParameterDeclaration), undefined, ts.visitNode(node.body, destructuringAndImportCallVisitor, ts.isBlock))); + if (ts.hasModifier(node, 1 /* Export */)) { + hoistedStatements = ts.append(hoistedStatements, ts.updateFunctionDeclaration(node, node.decorators, ts.visitNodes(node.modifiers, modifierVisitor, ts.isModifier), node.asteriskToken, ts.getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true), + /*typeParameters*/ undefined, ts.visitNodes(node.parameters, destructuringAndImportCallVisitor, ts.isParameterDeclaration), + /*type*/ undefined, ts.visitNode(node.body, destructuringAndImportCallVisitor, ts.isBlock))); } else { hoistedStatements = ts.append(hoistedStatements, ts.visitEachChild(node, destructuringAndImportCallVisitor, context)); } if (hasAssociatedEndOfDeclarationMarker(node)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfHoistedDeclaration(deferredExports[id], node); } @@ -60967,12 +73742,22 @@ var ts; } return undefined; } + /** + * Visits a ClassDeclaration, hoisting its name to the outer module body function. + * + * @param node The node to visit. + */ function visitClassDeclaration(node) { var statements; + // Hoist the name of the class declaration to the outer module body function. var name = ts.getLocalName(node); hoistVariableDeclaration(name); - statements = ts.append(statements, ts.setTextRange(ts.createStatement(ts.createAssignment(name, ts.setTextRange(ts.createClassExpression(undefined, node.name, undefined, ts.visitNodes(node.heritageClauses, destructuringAndImportCallVisitor, ts.isHeritageClause), ts.visitNodes(node.members, destructuringAndImportCallVisitor, ts.isClassElement)), node))), node)); + // Rewrite the class declaration into an assignment of a class expression. + statements = ts.append(statements, ts.setTextRange(ts.createStatement(ts.createAssignment(name, ts.setTextRange(ts.createClassExpression( + /*modifiers*/ undefined, node.name, + /*typeParameters*/ undefined, ts.visitNodes(node.heritageClauses, destructuringAndImportCallVisitor, ts.isHeritageClause), ts.visitNodes(node.members, destructuringAndImportCallVisitor, ts.isClassElement)), node))), node)); if (hasAssociatedEndOfDeclarationMarker(node)) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfHoistedDeclaration(deferredExports[id], node); } @@ -60981,12 +73766,18 @@ var ts; } return ts.singleOrMany(statements); } + /** + * Visits a variable statement, hoisting declared names to the top-level module body. + * Each declaration is rewritten into an assignment expression. + * + * @param node The node to visit. + */ function visitVariableStatement(node) { if (!shouldHoistVariableDeclarationList(node.declarationList)) { return ts.visitNode(node, destructuringAndImportCallVisitor, ts.isStatement); } var expressions; - var isExportedDeclaration = ts.hasModifier(node, 1); + var isExportedDeclaration = ts.hasModifier(node, 1 /* Export */); var isMarkedDeclaration = hasAssociatedEndOfDeclarationMarker(node); for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) { var variable = _a[_i]; @@ -61002,14 +73793,20 @@ var ts; statements = ts.append(statements, ts.setTextRange(ts.createStatement(ts.inlineExpressions(expressions)), node)); } if (isMarkedDeclaration) { + // Defer exports until we encounter an EndOfDeclarationMarker node var id = ts.getOriginalNodeId(node); deferredExports[id] = appendExportsOfVariableStatement(deferredExports[id], node, isExportedDeclaration); } else { - statements = appendExportsOfVariableStatement(statements, node, false); + statements = appendExportsOfVariableStatement(statements, node, /*exportSelf*/ false); } return ts.singleOrMany(statements); } + /** + * Hoists the declared names of a VariableDeclaration or BindingElement. + * + * @param node The declaration to hoist. + */ function hoistBindingElement(node) { if (ts.isBindingPattern(node.name)) { for (var _i = 0, _a = node.name.elements; _i < _a.length; _i++) { @@ -61023,41 +73820,103 @@ var ts; hoistVariableDeclaration(ts.getSynthesizedClone(node.name)); } } + /** + * Determines whether a VariableDeclarationList should be hoisted. + * + * @param node The node to test. + */ function shouldHoistVariableDeclarationList(node) { - return (ts.getEmitFlags(node) & 2097152) === 0 - && (enclosingBlockScopedContainer.kind === 274 - || (ts.getOriginalNode(node).flags & 3) === 0); + // hoist only non-block scoped declarations or block scoped declarations parented by source file + return (ts.getEmitFlags(node) & 2097152 /* NoHoisting */) === 0 + && (enclosingBlockScopedContainer.kind === 274 /* SourceFile */ + || (ts.getOriginalNode(node).flags & 3 /* BlockScoped */) === 0); } + /** + * Transform an initialized variable declaration into an expression. + * + * @param node The node to transform. + * @param isExportedDeclaration A value indicating whether the variable is exported. + */ function transformInitializedVariable(node, isExportedDeclaration) { var createAssignment = isExportedDeclaration ? createExportedVariableAssignment : createNonExportedVariableAssignment; return ts.isBindingPattern(node.name) - ? ts.flattenDestructuringAssignment(node, destructuringAndImportCallVisitor, context, 0, false, createAssignment) + ? ts.flattenDestructuringAssignment(node, destructuringAndImportCallVisitor, context, 0 /* All */, + /*needsValue*/ false, createAssignment) : node.initializer ? createAssignment(node.name, ts.visitNode(node.initializer, destructuringAndImportCallVisitor, ts.isExpression)) : node.name; } + /** + * Creates an assignment expression for an exported variable declaration. + * + * @param name The name of the variable. + * @param value The value of the variable's initializer. + * @param location The source map location for the assignment. + */ function createExportedVariableAssignment(name, value, location) { - return createVariableAssignment(name, value, location, true); + return createVariableAssignment(name, value, location, /*isExportedDeclaration*/ true); } + /** + * Creates an assignment expression for a non-exported variable declaration. + * + * @param name The name of the variable. + * @param value The value of the variable's initializer. + * @param location The source map location for the assignment. + */ function createNonExportedVariableAssignment(name, value, location) { - return createVariableAssignment(name, value, location, false); + return createVariableAssignment(name, value, location, /*isExportedDeclaration*/ false); } + /** + * Creates an assignment expression for a variable declaration. + * + * @param name The name of the variable. + * @param value The value of the variable's initializer. + * @param location The source map location for the assignment. + * @param isExportedDeclaration A value indicating whether the variable is exported. + */ function createVariableAssignment(name, value, location, isExportedDeclaration) { hoistVariableDeclaration(ts.getSynthesizedClone(name)); return isExportedDeclaration ? createExportExpression(name, preventSubstitution(ts.setTextRange(ts.createAssignment(name, value), location))) : preventSubstitution(ts.setTextRange(ts.createAssignment(name, value), location)); } + /** + * Visits a MergeDeclarationMarker used as a placeholder for the beginning of a merged + * and transformed declaration. + * + * @param node The node to visit. + */ function visitMergeDeclarationMarker(node) { - if (hasAssociatedEndOfDeclarationMarker(node) && node.original.kind === 214) { + // For an EnumDeclaration or ModuleDeclaration that merges with a preceeding + // declaration we do not emit a leading variable declaration. To preserve the + // begin/end semantics of the declararation and to properly handle exports + // we wrapped the leading variable declaration in a `MergeDeclarationMarker`. + // + // To balance the declaration, we defer the exports of the elided variable + // statement until we visit this declaration's `EndOfDeclarationMarker`. + if (hasAssociatedEndOfDeclarationMarker(node) && node.original.kind === 214 /* VariableStatement */) { var id = ts.getOriginalNodeId(node); - var isExportedDeclaration = ts.hasModifier(node.original, 1); + var isExportedDeclaration = ts.hasModifier(node.original, 1 /* Export */); deferredExports[id] = appendExportsOfVariableStatement(deferredExports[id], node.original, isExportedDeclaration); } return node; } + /** + * Determines whether a node has an associated EndOfDeclarationMarker. + * + * @param node The node to test. + */ function hasAssociatedEndOfDeclarationMarker(node) { - return (ts.getEmitFlags(node) & 4194304) !== 0; + return (ts.getEmitFlags(node) & 4194304 /* HasEndOfDeclarationMarker */) !== 0; } + /** + * Visits a DeclarationMarker used as a placeholder for the end of a transformed + * declaration. + * + * @param node The node to visit. + */ function visitEndOfDeclarationMarker(node) { + // For some transformations we emit an `EndOfDeclarationMarker` to mark the actual + // end of the transformed declaration. We use this marker to emit any deferred exports + // of the declaration. var id = ts.getOriginalNodeId(node); var statements = deferredExports[id]; if (statements) { @@ -61072,6 +73931,15 @@ var ts; } return node; } + /** + * Appends the exports of an ImportDeclaration to a statement list, returning the + * statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param decl The declaration whose exports are to be recorded. + */ function appendExportsOfImportDeclaration(statements, decl) { if (moduleInfo.exportEquals) { return statements; @@ -61086,10 +73954,10 @@ var ts; var namedBindings = importClause.namedBindings; if (namedBindings) { switch (namedBindings.kind) { - case 246: + case 246 /* NamespaceImport */: statements = appendExportsOfDeclaration(statements, namedBindings); break; - case 247: + case 247 /* NamedImports */: for (var _i = 0, _a = namedBindings.elements; _i < _a.length; _i++) { var importBinding = _a[_i]; statements = appendExportsOfDeclaration(statements, importBinding); @@ -61099,12 +73967,32 @@ var ts; } return statements; } + /** + * Appends the export of an ImportEqualsDeclaration to a statement list, returning the + * statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param decl The declaration whose exports are to be recorded. + */ function appendExportsOfImportEqualsDeclaration(statements, decl) { if (moduleInfo.exportEquals) { return statements; } return appendExportsOfDeclaration(statements, decl); } + /** + * Appends the exports of a VariableStatement to a statement list, returning the statement + * list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param node The VariableStatement whose exports are to be recorded. + * @param exportSelf A value indicating whether to also export each VariableDeclaration of + * `nodes` declaration list. + */ function appendExportsOfVariableStatement(statements, node, exportSelf) { if (moduleInfo.exportEquals) { return statements; @@ -61117,6 +74005,16 @@ var ts; } return statements; } + /** + * Appends the exports of a VariableDeclaration or BindingElement to a statement list, + * returning the statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param decl The declaration whose exports are to be recorded. + * @param exportSelf A value indicating whether to also export the declaration itself. + */ function appendExportsOfBindingElement(statements, decl, exportSelf) { if (moduleInfo.exportEquals) { return statements; @@ -61139,13 +74037,22 @@ var ts; } return statements; } + /** + * Appends the exports of a ClassDeclaration or FunctionDeclaration to a statement list, + * returning the statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param decl The declaration whose exports are to be recorded. + */ function appendExportsOfHoistedDeclaration(statements, decl) { if (moduleInfo.exportEquals) { return statements; } var excludeName; - if (ts.hasModifier(decl, 1)) { - var exportName = ts.hasModifier(decl, 512) ? ts.createLiteral("default") : decl.name; + if (ts.hasModifier(decl, 1 /* Export */)) { + var exportName = ts.hasModifier(decl, 512 /* Default */) ? ts.createLiteral("default") : decl.name; statements = appendExportStatement(statements, exportName, ts.getLocalName(decl)); excludeName = ts.getTextOfIdentifierOrLiteral(exportName); } @@ -61154,6 +74061,15 @@ var ts; } return statements; } + /** + * Appends the exports of a declaration to a statement list, returning the statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param decl The declaration to export. + * @param excludeName An optional name to exclude from exports. + */ function appendExportsOfDeclaration(statements, decl, excludeName) { if (moduleInfo.exportEquals) { return statements; @@ -61170,67 +74086,104 @@ var ts; } return statements; } + /** + * Appends the down-level representation of an export to a statement list, returning the + * statement list. + * + * @param statements A statement list to which the down-level export statements are to be + * appended. If `statements` is `undefined`, a new array is allocated if statements are + * appended. + * @param exportName The name of the export. + * @param expression The expression to export. + * @param allowComments Whether to allow comments on the export. + */ function appendExportStatement(statements, exportName, expression, allowComments) { statements = ts.append(statements, createExportStatement(exportName, expression, allowComments)); return statements; } + /** + * Creates a call to the current file's export function to export a value. + * + * @param name The bound name of the export. + * @param value The exported value. + * @param allowComments An optional value indicating whether to emit comments for the statement. + */ function createExportStatement(name, value, allowComments) { var statement = ts.createStatement(createExportExpression(name, value)); ts.startOnNewLine(statement); if (!allowComments) { - ts.setEmitFlags(statement, 1536); + ts.setEmitFlags(statement, 1536 /* NoComments */); } return statement; } + /** + * Creates a call to the current file's export function to export a value. + * + * @param name The bound name of the export. + * @param value The exported value. + */ function createExportExpression(name, value) { var exportName = ts.isIdentifier(name) ? ts.createLiteral(name) : name; - ts.setEmitFlags(value, ts.getEmitFlags(value) | 1536); - return ts.setCommentRange(ts.createCall(exportFunction, undefined, [exportName, value]), value); + ts.setEmitFlags(value, ts.getEmitFlags(value) | 1536 /* NoComments */); + return ts.setCommentRange(ts.createCall(exportFunction, /*typeArguments*/ undefined, [exportName, value]), value); } + // + // Top-Level or Nested Source Element Visitors + // + /** + * Visit nested elements at the top-level of a module. + * + * @param node The node to visit. + */ function nestedElementVisitor(node) { switch (node.kind) { - case 214: + case 214 /* VariableStatement */: return visitVariableStatement(node); - case 234: + case 234 /* FunctionDeclaration */: return visitFunctionDeclaration(node); - case 235: + case 235 /* ClassDeclaration */: return visitClassDeclaration(node); - case 220: + case 220 /* ForStatement */: return visitForStatement(node); - case 221: + case 221 /* ForInStatement */: return visitForInStatement(node); - case 222: + case 222 /* ForOfStatement */: return visitForOfStatement(node); - case 218: + case 218 /* DoStatement */: return visitDoStatement(node); - case 219: + case 219 /* WhileStatement */: return visitWhileStatement(node); - case 228: + case 228 /* LabeledStatement */: return visitLabeledStatement(node); - case 226: + case 226 /* WithStatement */: return visitWithStatement(node); - case 227: + case 227 /* SwitchStatement */: return visitSwitchStatement(node); - case 241: + case 241 /* CaseBlock */: return visitCaseBlock(node); - case 266: + case 266 /* CaseClause */: return visitCaseClause(node); - case 267: + case 267 /* DefaultClause */: return visitDefaultClause(node); - case 230: + case 230 /* TryStatement */: return visitTryStatement(node); - case 269: + case 269 /* CatchClause */: return visitCatchClause(node); - case 213: + case 213 /* Block */: return visitBlock(node); - case 304: + case 304 /* MergeDeclarationMarker */: return visitMergeDeclarationMarker(node); - case 305: + case 305 /* EndOfDeclarationMarker */: return visitEndOfDeclarationMarker(node); default: return destructuringAndImportCallVisitor(node); } } + /** + * Visits the body of a ForStatement to hoist declarations. + * + * @param node The node to visit. + */ function visitForStatement(node) { var savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer; enclosingBlockScopedContainer = node; @@ -61238,6 +74191,11 @@ var ts; enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer; return node; } + /** + * Visits the body of a ForInStatement to hoist declarations. + * + * @param node The node to visit. + */ function visitForInStatement(node) { var savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer; enclosingBlockScopedContainer = node; @@ -61245,6 +74203,11 @@ var ts; enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer; return node; } + /** + * Visits the body of a ForOfStatement to hoist declarations. + * + * @param node The node to visit. + */ function visitForOfStatement(node) { var savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer; enclosingBlockScopedContainer = node; @@ -61252,16 +74215,27 @@ var ts; enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer; return node; } + /** + * Determines whether to hoist the initializer of a ForStatement, ForInStatement, or + * ForOfStatement. + * + * @param node The node to test. + */ function shouldHoistForInitializer(node) { return ts.isVariableDeclarationList(node) && shouldHoistVariableDeclarationList(node); } + /** + * Visits the initializer of a ForStatement, ForInStatement, or ForOfStatement + * + * @param node The node to visit. + */ function visitForInitializer(node) { if (shouldHoistForInitializer(node)) { var expressions = void 0; for (var _i = 0, _a = node.declarations; _i < _a.length; _i++) { var variable = _a[_i]; - expressions = ts.append(expressions, transformInitializedVariable(variable, false)); + expressions = ts.append(expressions, transformInitializedVariable(variable, /*isExportedDeclaration*/ false)); if (!variable.initializer) { hoistBindingElement(variable); } @@ -61272,21 +74246,51 @@ var ts; return ts.visitEachChild(node, nestedElementVisitor, context); } } + /** + * Visits the body of a DoStatement to hoist declarations. + * + * @param node The node to visit. + */ function visitDoStatement(node) { return ts.updateDo(node, ts.visitNode(node.statement, nestedElementVisitor, ts.isStatement, ts.liftToBlock), ts.visitNode(node.expression, destructuringAndImportCallVisitor, ts.isExpression)); } + /** + * Visits the body of a WhileStatement to hoist declarations. + * + * @param node The node to visit. + */ function visitWhileStatement(node) { return ts.updateWhile(node, ts.visitNode(node.expression, destructuringAndImportCallVisitor, ts.isExpression), ts.visitNode(node.statement, nestedElementVisitor, ts.isStatement, ts.liftToBlock)); } + /** + * Visits the body of a LabeledStatement to hoist declarations. + * + * @param node The node to visit. + */ function visitLabeledStatement(node) { return ts.updateLabel(node, node.label, ts.visitNode(node.statement, nestedElementVisitor, ts.isStatement, ts.liftToBlock)); } + /** + * Visits the body of a WithStatement to hoist declarations. + * + * @param node The node to visit. + */ function visitWithStatement(node) { return ts.updateWith(node, ts.visitNode(node.expression, destructuringAndImportCallVisitor, ts.isExpression), ts.visitNode(node.statement, nestedElementVisitor, ts.isStatement, ts.liftToBlock)); } + /** + * Visits the body of a SwitchStatement to hoist declarations. + * + * @param node The node to visit. + */ function visitSwitchStatement(node) { return ts.updateSwitch(node, ts.visitNode(node.expression, destructuringAndImportCallVisitor, ts.isExpression), ts.visitNode(node.caseBlock, nestedElementVisitor, ts.isCaseBlock)); } + /** + * Visits the body of a CaseBlock to hoist declarations. + * + * @param node The node to visit. + */ function visitCaseBlock(node) { var savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer; enclosingBlockScopedContainer = node; @@ -61294,15 +74298,35 @@ var ts; enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer; return node; } + /** + * Visits the body of a CaseClause to hoist declarations. + * + * @param node The node to visit. + */ function visitCaseClause(node) { return ts.updateCaseClause(node, ts.visitNode(node.expression, destructuringAndImportCallVisitor, ts.isExpression), ts.visitNodes(node.statements, nestedElementVisitor, ts.isStatement)); } + /** + * Visits the body of a DefaultClause to hoist declarations. + * + * @param node The node to visit. + */ function visitDefaultClause(node) { return ts.visitEachChild(node, nestedElementVisitor, context); } + /** + * Visits the body of a TryStatement to hoist declarations. + * + * @param node The node to visit. + */ function visitTryStatement(node) { return ts.visitEachChild(node, nestedElementVisitor, context); } + /** + * Visits the body of a CatchClause to hoist declarations. + * + * @param node The node to visit. + */ function visitCatchClause(node) { var savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer; enclosingBlockScopedContainer = node; @@ -61310,6 +74334,11 @@ var ts; enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer; return node; } + /** + * Visits the body of a Block to hoist declarations. + * + * @param node The node to visit. + */ function visitBlock(node) { var savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer; enclosingBlockScopedContainer = node; @@ -61317,15 +74346,23 @@ var ts; enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer; return node; } + // + // Destructuring Assignment Visitors + // + /** + * Visit nodes to flatten destructuring assignments to exported symbols. + * + * @param node The node to visit. + */ function destructuringAndImportCallVisitor(node) { - if (node.transformFlags & 1024 - && node.kind === 200) { + if (node.transformFlags & 1024 /* DestructuringAssignment */ + && node.kind === 200 /* BinaryExpression */) { return visitDestructuringAssignment(node); } else if (ts.isImportCall(node)) { return visitImportCallExpression(node); } - else if ((node.transformFlags & 2048) || (node.transformFlags & 67108864)) { + else if ((node.transformFlags & 2048 /* ContainsDestructuringAssignment */) || (node.transformFlags & 67108864 /* ContainsDynamicImport */)) { return ts.visitEachChild(node, destructuringAndImportCallVisitor, context); } else { @@ -61333,16 +74370,38 @@ var ts; } } function visitImportCallExpression(node) { - return ts.createCall(ts.createPropertyAccess(contextObject, ts.createIdentifier("import")), undefined, ts.some(node.arguments) ? [ts.visitNode(node.arguments[0], destructuringAndImportCallVisitor)] : []); + // import("./blah") + // emit as + // System.register([], function (_export, _context) { + // return { + // setters: [], + // execute: () => { + // _context.import('./blah'); + // } + // }; + // }); + return ts.createCall(ts.createPropertyAccess(contextObject, ts.createIdentifier("import")), + /*typeArguments*/ undefined, ts.some(node.arguments) ? [ts.visitNode(node.arguments[0], destructuringAndImportCallVisitor)] : []); } + /** + * Visits a DestructuringAssignment to flatten destructuring to exported symbols. + * + * @param node The node to visit. + */ function visitDestructuringAssignment(node) { if (hasExportedReferenceInDestructuringTarget(node.left)) { - return ts.flattenDestructuringAssignment(node, destructuringAndImportCallVisitor, context, 0, true); + return ts.flattenDestructuringAssignment(node, destructuringAndImportCallVisitor, context, 0 /* All */, + /*needsValue*/ true); } return ts.visitEachChild(node, destructuringAndImportCallVisitor, context); } + /** + * Determines whether the target of a destructuring assigment refers to an exported symbol. + * + * @param node The destructuring target. + */ function hasExportedReferenceInDestructuringTarget(node) { - if (ts.isAssignmentExpression(node, true)) { + if (ts.isAssignmentExpression(node, /*excludeCompoundAssignment*/ true)) { return hasExportedReferenceInDestructuringTarget(node.left); } else if (ts.isSpreadElement(node)) { @@ -61362,22 +74421,40 @@ var ts; } else if (ts.isIdentifier(node)) { var container = resolver.getReferencedExportContainer(node); - return container !== undefined && container.kind === 274; + return container !== undefined && container.kind === 274 /* SourceFile */; } else { return false; } } + // + // Modifier Visitors + // + /** + * Visit nodes to elide module-specific modifiers. + * + * @param node The node to visit. + */ function modifierVisitor(node) { switch (node.kind) { - case 84: - case 79: + case 84 /* ExportKeyword */: + case 79 /* DefaultKeyword */: return undefined; } return node; } + // + // Emit Notification + // + /** + * Hook for node emit notifications. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emitCallback A callback used to emit the node in the printer. + */ function onEmitNode(hint, node, emitCallback) { - if (node.kind === 274) { + if (node.kind === 274 /* SourceFile */) { var id = ts.getOriginalNodeId(node); currentSourceFile = node; moduleInfo = moduleInfoMap[id]; @@ -61396,75 +74473,127 @@ var ts; previousOnEmitNode(hint, node, emitCallback); } } + // + // Substitutions + // + /** + * Hooks node substitutions. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to substitute. + */ function onSubstituteNode(hint, node) { node = previousOnSubstituteNode(hint, node); if (isSubstitutionPrevented(node)) { return node; } - if (hint === 1) { + if (hint === 1 /* Expression */) { return substituteExpression(node); } - else if (hint === 4) { + else if (hint === 4 /* Unspecified */) { return substituteUnspecified(node); } return node; } + /** + * Substitute the node, if necessary. + * + * @param node The node to substitute. + */ function substituteUnspecified(node) { switch (node.kind) { - case 271: + case 271 /* ShorthandPropertyAssignment */: return substituteShorthandPropertyAssignment(node); } return node; } + /** + * Substitution for a ShorthandPropertyAssignment whose name that may contain an imported or exported symbol. + * + * @param node The node to substitute. + */ function substituteShorthandPropertyAssignment(node) { var name = node.name; if (!ts.isGeneratedIdentifier(name) && !ts.isLocalName(name)) { var importDeclaration = resolver.getReferencedImportDeclaration(name); if (importDeclaration) { if (ts.isImportClause(importDeclaration)) { - return ts.setTextRange(ts.createPropertyAssignment(ts.getSynthesizedClone(name), ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent), ts.createIdentifier("default"))), node); + return ts.setTextRange(ts.createPropertyAssignment(ts.getSynthesizedClone(name), ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent), ts.createIdentifier("default"))), + /*location*/ node); } else if (ts.isImportSpecifier(importDeclaration)) { - return ts.setTextRange(ts.createPropertyAssignment(ts.getSynthesizedClone(name), ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent.parent.parent), ts.getSynthesizedClone(importDeclaration.propertyName || importDeclaration.name))), node); + return ts.setTextRange(ts.createPropertyAssignment(ts.getSynthesizedClone(name), ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent.parent.parent), ts.getSynthesizedClone(importDeclaration.propertyName || importDeclaration.name))), + /*location*/ node); } } } return node; } + /** + * Substitute the expression, if necessary. + * + * @param node The node to substitute. + */ function substituteExpression(node) { switch (node.kind) { - case 71: + case 71 /* Identifier */: return substituteExpressionIdentifier(node); - case 200: + case 200 /* BinaryExpression */: return substituteBinaryExpression(node); - case 198: - case 199: + case 198 /* PrefixUnaryExpression */: + case 199 /* PostfixUnaryExpression */: return substituteUnaryExpression(node); } return node; } + /** + * Substitution for an Identifier expression that may contain an imported or exported symbol. + * + * @param node The node to substitute. + */ function substituteExpressionIdentifier(node) { - if (ts.getEmitFlags(node) & 4096) { + if (ts.getEmitFlags(node) & 4096 /* HelperName */) { var externalHelpersModuleName = ts.getExternalHelpersModuleName(currentSourceFile); if (externalHelpersModuleName) { return ts.createPropertyAccess(externalHelpersModuleName, node); } return node; } + // When we see an identifier in an expression position that + // points to an imported symbol, we should substitute a qualified + // reference to the imported symbol if one is needed. + // + // - We do not substitute generated identifiers for any reason. + // - We do not substitute identifiers tagged with the LocalName flag. if (!ts.isGeneratedIdentifier(node) && !ts.isLocalName(node)) { var importDeclaration = resolver.getReferencedImportDeclaration(node); if (importDeclaration) { if (ts.isImportClause(importDeclaration)) { - return ts.setTextRange(ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent), ts.createIdentifier("default")), node); + return ts.setTextRange(ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent), ts.createIdentifier("default")), + /*location*/ node); } else if (ts.isImportSpecifier(importDeclaration)) { - return ts.setTextRange(ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent.parent.parent), ts.getSynthesizedClone(importDeclaration.propertyName || importDeclaration.name)), node); + return ts.setTextRange(ts.createPropertyAccess(ts.getGeneratedNameForNode(importDeclaration.parent.parent.parent), ts.getSynthesizedClone(importDeclaration.propertyName || importDeclaration.name)), + /*location*/ node); } } } return node; } + /** + * Substitution for a BinaryExpression that may contain an imported or exported symbol. + * + * @param node The node to substitute. + */ function substituteBinaryExpression(node) { + // When we see an assignment expression whose left-hand side is an exported symbol, + // we should ensure all exports of that symbol are updated with the correct value. + // + // - We do not substitute generated identifiers for any reason. + // - We do not substitute identifiers tagged with the LocalName flag. + // - We do not substitute identifiers that were originally the name of an enum or + // namespace due to how they are transformed in TypeScript. + // - We only substitute identifiers that are exported at the top level. if (ts.isAssignmentOperator(node.operatorToken.kind) && ts.isIdentifier(node.left) && !ts.isGeneratedIdentifier(node.left) @@ -61472,6 +74601,7 @@ var ts; && !ts.isDeclarationNameOfEnumOrNamespace(node.left)) { var exportedNames = getExports(node.left); if (exportedNames) { + // For each additional export of the declaration, apply an export assignment. var expression = node; for (var _i = 0, exportedNames_4 = exportedNames; _i < exportedNames_4.length; _i++) { var exportName = exportedNames_4[_i]; @@ -61482,23 +74612,37 @@ var ts; } return node; } + /** + * Substitution for a UnaryExpression that may contain an imported or exported symbol. + * + * @param node The node to substitute. + */ function substituteUnaryExpression(node) { - if ((node.operator === 43 || node.operator === 44) + // When we see a prefix or postfix increment expression whose operand is an exported + // symbol, we should ensure all exports of that symbol are updated with the correct + // value. + // + // - We do not substitute generated identifiers for any reason. + // - We do not substitute identifiers tagged with the LocalName flag. + // - We do not substitute identifiers that were originally the name of an enum or + // namespace due to how they are transformed in TypeScript. + // - We only substitute identifiers that are exported at the top level. + if ((node.operator === 43 /* PlusPlusToken */ || node.operator === 44 /* MinusMinusToken */) && ts.isIdentifier(node.operand) && !ts.isGeneratedIdentifier(node.operand) && !ts.isLocalName(node.operand) && !ts.isDeclarationNameOfEnumOrNamespace(node.operand)) { var exportedNames = getExports(node.operand); if (exportedNames) { - var expression = node.kind === 199 + var expression = node.kind === 199 /* PostfixUnaryExpression */ ? ts.setTextRange(ts.createPrefix(node.operator, node.operand), node) : node; for (var _i = 0, exportedNames_5 = exportedNames; _i < exportedNames_5.length; _i++) { var exportName = exportedNames_5[_i]; expression = createExportExpression(exportName, preventSubstitution(expression)); } - if (node.kind === 199) { - expression = node.operator === 43 + if (node.kind === 199 /* PostfixUnaryExpression */) { + expression = node.operator === 43 /* PlusPlusToken */ ? ts.createSubtract(preventSubstitution(expression), ts.createLiteral(1)) : ts.createAdd(preventSubstitution(expression), ts.createLiteral(1)); } @@ -61507,14 +74651,19 @@ var ts; } return node; } + /** + * Gets the exports of a name. + * + * @param name The name. + */ function getExports(name) { var exportedNames; if (!ts.isGeneratedIdentifier(name)) { var valueDeclaration = resolver.getReferencedImportDeclaration(name) || resolver.getReferencedValueDeclaration(name); if (valueDeclaration) { - var exportContainer = resolver.getReferencedExportContainer(name, false); - if (exportContainer && exportContainer.kind === 274) { + var exportContainer = resolver.getReferencedExportContainer(name, /*prefixLocals*/ false); + if (exportContainer && exportContainer.kind === 274 /* SourceFile */) { exportedNames = ts.append(exportedNames, ts.getDeclarationName(valueDeclaration)); } exportedNames = ts.addRange(exportedNames, moduleInfo && moduleInfo.exportedBindings[ts.getOriginalNodeId(valueDeclaration)]); @@ -61522,18 +74671,29 @@ var ts; } return exportedNames; } + /** + * Prevent substitution of a node for this transformer. + * + * @param node The node which should not be substituted. + */ function preventSubstitution(node) { if (noSubstitution === undefined) noSubstitution = []; noSubstitution[ts.getNodeId(node)] = true; return node; } + /** + * Determines whether a node should not be substituted. + * + * @param node The node to test. + */ function isSubstitutionPrevented(node) { return noSubstitution && node.id && noSubstitution[node.id]; } } ts.transformSystemModule = transformSystemModule; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { function transformES2015Module(context) { @@ -61542,8 +74702,8 @@ var ts; var previousOnSubstituteNode = context.onSubstituteNode; context.onEmitNode = onEmitNode; context.onSubstituteNode = onSubstituteNode; - context.enableEmitNotification(274); - context.enableSubstitution(71); + context.enableEmitNotification(274 /* SourceFile */); + context.enableSubstitution(71 /* Identifier */); var currentSourceFile; return ts.chainBundle(transformSourceFile); function transformSourceFile(node) { @@ -61555,8 +74715,10 @@ var ts; if (externalHelpersModuleName) { var statements = []; var statementOffset = ts.addPrologue(statements, node.statements); - var tslibImport = ts.createImportDeclaration(undefined, undefined, ts.createImportClause(undefined, ts.createNamespaceImport(externalHelpersModuleName)), ts.createLiteral(ts.externalHelpersModuleNameText)); - ts.addEmitFlags(tslibImport, 67108864); + var tslibImport = ts.createImportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, ts.createImportClause(/*name*/ undefined, ts.createNamespaceImport(externalHelpersModuleName)), ts.createLiteral(ts.externalHelpersModuleNameText)); + ts.addEmitFlags(tslibImport, 67108864 /* NeverApplyImportHelper */); ts.append(statements, tslibImport); ts.addRange(statements, ts.visitNodes(node.statements, visitor, ts.isStatement, statementOffset)); return ts.updateSourceFileNode(node, ts.setTextRange(ts.createNodeArray(statements), node.statements)); @@ -61569,16 +74731,28 @@ var ts; } function visitor(node) { switch (node.kind) { - case 243: + case 243 /* ImportEqualsDeclaration */: + // Elide `import=` as it is not legal with --module ES6 return undefined; - case 249: + case 249 /* ExportAssignment */: return visitExportAssignment(node); } return node; } function visitExportAssignment(node) { + // Elide `export=` as it is not legal with --module ES6 return node.isExportEquals ? undefined : node; } + // + // Emit Notification + // + /** + * Hook for node emit. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emit A callback used to emit the node in the printer. + */ function onEmitNode(hint, node, emitCallback) { if (ts.isSourceFile(node)) { currentSourceFile = node; @@ -61589,15 +74763,24 @@ var ts; previousOnEmitNode(hint, node, emitCallback); } } + // + // Substitutions + // + /** + * Hooks node substitutions. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to substitute. + */ function onSubstituteNode(hint, node) { node = previousOnSubstituteNode(hint, node); - if (ts.isIdentifier(node) && hint === 1) { + if (ts.isIdentifier(node) && hint === 1 /* Expression */) { return substituteExpressionIdentifier(node); } return node; } function substituteExpressionIdentifier(node) { - if (ts.getEmitFlags(node) & 4096) { + if (ts.getEmitFlags(node) & 4096 /* HelperName */) { var externalHelpersModuleName = ts.getExternalHelpersModuleName(currentSourceFile); if (externalHelpersModuleName) { return ts.createPropertyAccess(externalHelpersModuleName, node); @@ -61608,6 +74791,7 @@ var ts; } ts.transformES2015Module = transformES2015Module; })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { function canProduceDiagnostics(node) { @@ -61650,16 +74834,16 @@ var ts; } : undefined; } function getAccessorNameVisibilityDiagnosticMessage(symbolAccessibilityResult) { - if (ts.hasModifier(node, 32)) { + if (ts.hasModifier(node, 32 /* Static */)) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1; } - else if (node.parent.kind === 235) { + else if (node.parent.kind === 235 /* ClassDeclaration */) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1; @@ -61679,16 +74863,16 @@ var ts; } : undefined; } function getMethodNameVisibilityDiagnosticMessage(symbolAccessibilityResult) { - if (ts.hasModifier(node, 32)) { + if (ts.hasModifier(node, 32 /* Static */)) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Public_static_method_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Public_static_method_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Public_static_method_0_of_exported_class_has_or_is_using_private_name_1; } - else if (node.parent.kind === 235) { + else if (node.parent.kind === 235 /* ClassDeclaration */) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Public_method_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Public_method_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Public_method_0_of_exported_class_has_or_is_using_private_name_1; @@ -61712,7 +74896,7 @@ var ts; return getReturnTypeVisibilityError; } else if (ts.isParameter(node)) { - if (ts.isParameterPropertyDeclaration(node) && ts.hasModifier(node.parent, 8)) { + if (ts.isParameterPropertyDeclaration(node) && ts.hasModifier(node.parent, 8 /* Private */)) { return getVariableDeclarationTypeVisibilityError; } return getParameterDeclarationTypeVisibilityError; @@ -61733,30 +74917,34 @@ var ts; return ts.Debug.assertNever(node, "Attempted to set a declaration diagnostic context for unhandled node kind: " + ts.SyntaxKind[node.kind]); } function getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult) { - if (node.kind === 232 || node.kind === 182) { + if (node.kind === 232 /* VariableDeclaration */ || node.kind === 182 /* BindingElement */) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Exported_variable_0_has_or_is_using_private_name_1; } - else if (node.kind === 152 || node.kind === 151 || - (node.kind === 149 && ts.hasModifier(node.parent, 8))) { - if (ts.hasModifier(node, 32)) { + // This check is to ensure we don't report error on constructor parameter property as that error would be reported during parameter emit + // The only exception here is if the constructor was marked as private. we are not emitting the constructor parameters at all. + else if (node.kind === 152 /* PropertyDeclaration */ || node.kind === 151 /* PropertySignature */ || + (node.kind === 149 /* Parameter */ && ts.hasModifier(node.parent, 8 /* Private */))) { + // TODO(jfreeman): Deal with computed properties in error reporting. + if (ts.hasModifier(node, 32 /* Static */)) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1; } - else if (node.parent.kind === 235 || node.kind === 149) { + else if (node.parent.kind === 235 /* ClassDeclaration */ || node.kind === 149 /* Parameter */) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1; } else { + // Interfaces cannot have types that cannot be named return symbolAccessibilityResult.errorModuleName ? ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_private_name_1; @@ -61773,8 +74961,10 @@ var ts; } function getAccessorDeclarationTypeVisibilityError(symbolAccessibilityResult) { var diagnosticMessage; - if (node.kind === 157) { - if (ts.hasModifier(node, 32)) { + if (node.kind === 157 /* SetAccessor */) { + // Getters can infer the return type from the returned expression, but setters cannot, so the + // "_from_external_module_1_but_cannot_be_named" case cannot occur. + if (ts.hasModifier(node, 32 /* Static */)) { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? ts.Diagnostics.Parameter_type_of_public_static_setter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_type_of_public_static_setter_0_from_exported_class_has_or_is_using_private_name_1; @@ -61786,16 +74976,16 @@ var ts; } } else { - if (ts.hasModifier(node, 32)) { + if (ts.hasModifier(node, 32 /* Static */)) { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_private_name_1; } else { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_private_name_1; @@ -61810,46 +75000,50 @@ var ts; function getReturnTypeVisibilityError(symbolAccessibilityResult) { var diagnosticMessage; switch (node.kind) { - case 159: + case 159 /* ConstructSignature */: + // Interfaces cannot have return types that cannot be named diagnosticMessage = symbolAccessibilityResult.errorModuleName ? ts.Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_0; break; - case 158: + case 158 /* CallSignature */: + // Interfaces cannot have return types that cannot be named diagnosticMessage = symbolAccessibilityResult.errorModuleName ? ts.Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_name_0; break; - case 160: + case 160 /* IndexSignature */: + // Interfaces cannot have return types that cannot be named diagnosticMessage = symbolAccessibilityResult.errorModuleName ? ts.Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_name_0; break; - case 154: - case 153: - if (ts.hasModifier(node, 32)) { + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + if (ts.hasModifier(node, 32 /* Static */)) { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_name_0; } - else if (node.parent.kind === 235) { + else if (node.parent.kind === 235 /* ClassDeclaration */) { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_private_name_0; } else { + // Interfaces cannot have return types that cannot be named diagnosticMessage = symbolAccessibilityResult.errorModuleName ? ts.Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_private_name_0; } break; - case 234: + case 234 /* FunctionDeclaration */: diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_private_module_1 : ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_private_name_0; @@ -61872,50 +75066,54 @@ var ts; } function getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult) { switch (node.parent.kind) { - case 155: + case 155 /* Constructor */: return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1; - case 159: - case 164: + case 159 /* ConstructSignature */: + case 164 /* ConstructorType */: + // Interfaces cannot have parameter types that cannot be named return symbolAccessibilityResult.errorModuleName ? ts.Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; - case 158: + case 158 /* CallSignature */: + // Interfaces cannot have parameter types that cannot be named return symbolAccessibilityResult.errorModuleName ? ts.Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1; - case 160: + case 160 /* IndexSignature */: + // Interfaces cannot have parameter types that cannot be named return symbolAccessibilityResult.errorModuleName ? ts.Diagnostics.Parameter_0_of_index_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_index_signature_from_exported_interface_has_or_is_using_private_name_1; - case 154: - case 153: - if (ts.hasModifier(node.parent, 32)) { + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + if (ts.hasModifier(node.parent, 32 /* Static */)) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; } - else if (node.parent.parent.kind === 235) { + else if (node.parent.parent.kind === 235 /* ClassDeclaration */) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; } else { + // Interfaces cannot have parameter types that cannot be named return symbolAccessibilityResult.errorModuleName ? ts.Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1; } - case 234: - case 163: + case 234 /* FunctionDeclaration */: + case 163 /* FunctionType */: return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === 2 ? + symbolAccessibilityResult.accessibility === 2 /* CannotBeNamed */ ? ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2 : ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_private_name_1; @@ -61924,36 +75122,37 @@ var ts; } } function getTypeParameterConstraintVisibilityError() { + // Type parameter constraints are named by user so we should always be able to name it var diagnosticMessage; switch (node.parent.kind) { - case 235: + case 235 /* ClassDeclaration */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_class_has_or_is_using_private_name_1; break; - case 236: + case 236 /* InterfaceDeclaration */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1; break; - case 159: + case 159 /* ConstructSignature */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; break; - case 158: + case 158 /* CallSignature */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1; break; - case 154: - case 153: - if (ts.hasModifier(node.parent, 32)) { + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + if (ts.hasModifier(node.parent, 32 /* Static */)) { diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; } - else if (node.parent.parent.kind === 235) { + else if (node.parent.parent.kind === 235 /* ClassDeclaration */) { diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; } else { diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1; } break; - case 234: + case 234 /* FunctionDeclaration */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_function_has_or_is_using_private_name_1; break; - case 237: + case 237 /* TypeAliasDeclaration */: diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_type_alias_has_or_is_using_private_name_1; break; default: @@ -61967,12 +75166,15 @@ var ts; } function getHeritageClauseVisibilityError() { var diagnosticMessage; - if (node.parent.parent.kind === 235) { - diagnosticMessage = node.parent.token === 108 ? + // Heritage clause is written by user so it can always be named + if (node.parent.parent.kind === 235 /* ClassDeclaration */) { + // Class or Interface implemented/extended is inaccessible + diagnosticMessage = node.parent.token === 108 /* ImplementsKeyword */ ? ts.Diagnostics.Implements_clause_of_exported_class_0_has_or_is_using_private_name_1 : ts.Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1; } else { + // interface is inaccessible diagnosticMessage = ts.Diagnostics.extends_clause_of_exported_interface_0_has_or_is_using_private_name_1; } return { @@ -61998,23 +75200,30 @@ var ts; } ts.createGetSymbolAccessibilityDiagnosticForNode = createGetSymbolAccessibilityDiagnosticForNode; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { function getDeclarationDiagnostics(host, resolver, file) { if (file && ts.isSourceFileJavaScript(file)) { - return []; + return []; // No declaration diagnostics for js for now } var compilerOptions = host.getCompilerOptions(); - var result = ts.transformNodes(resolver, host, compilerOptions, file ? [file] : ts.filter(host.getSourceFiles(), ts.isSourceFileNotJavaScript), [transformDeclarations], false); + var result = ts.transformNodes(resolver, host, compilerOptions, file ? [file] : ts.filter(host.getSourceFiles(), ts.isSourceFileNotJavaScript), [transformDeclarations], /*allowDtsFiles*/ false); return result.diagnostics; } ts.getDeclarationDiagnostics = getDeclarationDiagnostics; - var declarationEmitNodeBuilderFlags = 1024 | - 2048 | - 4096 | - 8 | - 524288 | - 4; + var declarationEmitNodeBuilderFlags = 1024 /* MultilineObjectLiterals */ | + 2048 /* WriteClassExpressionAsTypeLiteral */ | + 4096 /* UseTypeOfFunction */ | + 8 /* UseStructuralFallback */ | + 524288 /* AllowEmptyTuple */ | + 4 /* GenerateNamesForShadowedTypeParams */; + /** + * Transforms a ts file into a .d.ts file + * This process requires type information, which is retrieved through the emit resolver. Because of this, + * in many places this transformer assumes it will be operating on parse tree nodes directly. + * This means that _no transforms should be allowed to occur before this one_. + */ function transformDeclarations(context) { var throwDiagnostic = function () { return ts.Debug.fail("Diagnostic emitted without context"); }; var getSymbolAccessibilityDiagnostic = throwDiagnostic; @@ -62060,7 +75269,8 @@ var ts; refs.set("" + ts.getOriginalNodeId(container), container); } function handleSymbolAccessibilityError(symbolAccessibilityResult) { - if (symbolAccessibilityResult.accessibility === 0) { + if (symbolAccessibilityResult.accessibility === 0 /* Accessible */) { + // Add aliases back onto the possible imports list if they're not there so we can try them again with updated visibility info if (symbolAccessibilityResult && symbolAccessibilityResult.aliasesToMakeVisible) { if (!lateMarkedStatements) { lateMarkedStatements = symbolAccessibilityResult.aliasesToMakeVisible; @@ -62072,8 +75282,10 @@ var ts; } } } + // TODO: Do all these accessibility checks inside/after the first pass in the checker when declarations are enabled, if possible } else { + // Report error var errorInfo = getSymbolAccessibilityDiagnostic(symbolAccessibilityResult); if (errorInfo) { if (errorInfo.typeName) { @@ -62086,9 +75298,9 @@ var ts; } } function trackSymbol(symbol, enclosingDeclaration, meaning) { - if (symbol.flags & 262144) + if (symbol.flags & 262144 /* TypeParameter */) return; - handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning, true)); + handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning, /*shouldComputeAliasesToMakeVisible*/ true)); recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForSymbol(symbol, meaning)); } function reportPrivateInBaseOfClassExpression(propertyName) { @@ -62107,16 +75319,16 @@ var ts; } } function transformRoot(node) { - if (node.kind === 274 && (node.isDeclarationFile || ts.isSourceFileJavaScript(node))) { + if (node.kind === 274 /* SourceFile */ && (node.isDeclarationFile || ts.isSourceFileJavaScript(node))) { return node; } - if (node.kind === 275) { + if (node.kind === 275 /* Bundle */) { isBundledEmit = true; var refs_1 = ts.createMap(); var hasNoDefaultLib_1 = false; var bundle = ts.createBundle(ts.map(node.sourceFiles, function (sourceFile) { if (sourceFile.isDeclarationFile || ts.isSourceFileJavaScript(sourceFile)) - return undefined; + return undefined; // Omit declaration files from bundle results, too // TODO: GH#18217 hasNoDefaultLib_1 = hasNoDefaultLib_1 || sourceFile.hasNoDefaultLib; currentSourceFile = sourceFile; enclosingDeclaration = sourceFile; @@ -62128,28 +75340,29 @@ var ts; resultHasScopeMarker = false; collectReferences(sourceFile, refs_1); if (ts.isExternalModule(sourceFile)) { - resultHasExternalModuleIndicator = false; + resultHasExternalModuleIndicator = false; // unused in external module bundle emit (all external modules are within module blocks, therefore are known to be modules) needsDeclare = false; var statements_5 = ts.visitNodes(sourceFile.statements, visitDeclarationStatements); - var newFile = ts.updateSourceFileNode(sourceFile, [ts.createModuleDeclaration([], [ts.createModifier(124)], ts.createLiteral(ts.getResolvedExternalModuleName(context.getEmitHost(), sourceFile)), ts.createModuleBlock(ts.setTextRange(ts.createNodeArray(transformAndReplaceLatePaintedStatements(statements_5)), sourceFile.statements)))], true, [], [], false, []); + var newFile = ts.updateSourceFileNode(sourceFile, [ts.createModuleDeclaration([], [ts.createModifier(124 /* DeclareKeyword */)], ts.createLiteral(ts.getResolvedExternalModuleName(context.getEmitHost(), sourceFile)), ts.createModuleBlock(ts.setTextRange(ts.createNodeArray(transformAndReplaceLatePaintedStatements(statements_5)), sourceFile.statements)))], /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false, /*libReferences*/ []); return newFile; } needsDeclare = true; var updated = ts.visitNodes(sourceFile.statements, visitDeclarationStatements); - return ts.updateSourceFileNode(sourceFile, transformAndReplaceLatePaintedStatements(updated), true, [], [], false, []); + return ts.updateSourceFileNode(sourceFile, transformAndReplaceLatePaintedStatements(updated), /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false, /*libReferences*/ []); }), ts.mapDefined(node.prepends, function (prepend) { - if (prepend.kind === 277) { + if (prepend.kind === 277 /* InputFiles */) { return ts.createUnparsedSourceFile(prepend.declarationText, prepend.declarationMapPath, prepend.declarationMapText); } })); bundle.syntheticFileReferences = []; bundle.syntheticTypeReferences = getFileReferencesForUsedTypeReferences(); bundle.hasNoDefaultLib = hasNoDefaultLib_1; - var outputFilePath_1 = ts.getDirectoryPath(ts.normalizeSlashes(ts.getOutputPathsFor(node, host, true).declarationFilePath)); + var outputFilePath_1 = ts.getDirectoryPath(ts.normalizeSlashes(ts.getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath)); var referenceVisitor_1 = mapReferencesIntoArray(bundle.syntheticFileReferences, outputFilePath_1); refs_1.forEach(referenceVisitor_1); return bundle; } + // Single source file needsDeclare = true; needsScopeFixMarker = false; resultHasScopeMarker = false; @@ -62164,21 +75377,22 @@ var ts; necessaryTypeRefernces = undefined; refs = collectReferences(currentSourceFile, ts.createMap()); var references = []; - var outputFilePath = ts.getDirectoryPath(ts.normalizeSlashes(ts.getOutputPathsFor(node, host, true).declarationFilePath)); + var outputFilePath = ts.getDirectoryPath(ts.normalizeSlashes(ts.getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath)); var referenceVisitor = mapReferencesIntoArray(references, outputFilePath); var statements = ts.visitNodes(node.statements, visitDeclarationStatements); var combinedStatements = ts.setTextRange(ts.createNodeArray(transformAndReplaceLatePaintedStatements(statements)), node.statements); refs.forEach(referenceVisitor); var emittedImports = ts.filter(combinedStatements, ts.isAnyImportSyntax); if (ts.isExternalModule(node) && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker))) { - combinedStatements = ts.setTextRange(ts.createNodeArray(combinedStatements.concat([ts.createExportDeclaration(undefined, undefined, ts.createNamedExports([]), undefined)])), combinedStatements); + combinedStatements = ts.setTextRange(ts.createNodeArray(combinedStatements.concat([ts.createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, ts.createNamedExports([]), /*moduleSpecifier*/ undefined)])), combinedStatements); } - var updated = ts.updateSourceFileNode(node, combinedStatements, true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib); + var updated = ts.updateSourceFileNode(node, combinedStatements, /*isDeclarationFile*/ true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib); return updated; function getFileReferencesForUsedTypeReferences() { return necessaryTypeRefernces ? ts.mapDefined(ts.arrayFrom(necessaryTypeRefernces.keys()), getFileReferenceForTypeName) : []; } function getFileReferenceForTypeName(typeName) { + // Elide type references for which we have imports if (emittedImports) { for (var _i = 0, emittedImports_1 = emittedImports; _i < emittedImports_1.length; _i++) { var importStatement = emittedImports_1[_i]; @@ -62198,17 +75412,18 @@ var ts; function mapReferencesIntoArray(references, outputFilePath) { return function (file) { var declFileName; - if (file.isDeclarationFile) { + if (file.isDeclarationFile) { // Neither decl files or js should have their refs changed declFileName = file.fileName; } else { if (isBundledEmit && ts.contains(node.sourceFiles, file)) - return; - var paths = ts.getOutputPathsFor(file, host, true); + return; // Omit references to files which are being merged + var paths = ts.getOutputPathsFor(file, host, /*forceDtsPaths*/ true); declFileName = paths.declarationFilePath || paths.jsFilePath; } if (declFileName) { - var fileName = ts.getRelativePathToDirectoryOrUrl(outputFilePath, declFileName, host.getCurrentDirectory(), host.getCanonicalFileName, false); + var fileName = ts.getRelativePathToDirectoryOrUrl(outputFilePath, declFileName, host.getCurrentDirectory(), host.getCanonicalFileName, + /*isAbsolutePathAnUrl*/ false); if (ts.startsWith(fileName, "./") && ts.hasExtension(fileName)) { fileName = fileName.substring(2); } @@ -62229,11 +75444,11 @@ var ts; return ret; } function filterBindingPatternInitializers(name) { - if (name.kind === 71) { + if (name.kind === 71 /* Identifier */) { return name; } else { - if (name.kind === 181) { + if (name.kind === 181 /* ArrayBindingPattern */) { return ts.updateArrayBindingPattern(name, ts.visitNodes(name.elements, visitBindingElement)); } else { @@ -62241,7 +75456,7 @@ var ts; } } function visitBindingElement(elem) { - if (elem.kind === 206) { + if (elem.kind === 206 /* OmittedExpression */) { return elem; } return ts.updateBindingElement(elem, elem.dotDotDotToken, elem.propertyName, filterBindingPatternInitializers(elem.name), shouldPrintWithInitializer(elem) ? elem.initializer : undefined); @@ -62253,39 +75468,45 @@ var ts; oldDiag = getSymbolAccessibilityDiagnostic; getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNode(p); } - var newParam = ts.updateParameter(p, undefined, maskModifiers(p, modifierMask), p.dotDotDotToken, filterBindingPatternInitializers(p.name), resolver.isOptionalParameter(p) ? (p.questionToken || ts.createToken(55)) : undefined, ensureType(p, p.type, true), ensureNoInitializer(p)); + var newParam = ts.updateParameter(p, + /*decorators*/ undefined, maskModifiers(p, modifierMask), p.dotDotDotToken, filterBindingPatternInitializers(p.name), resolver.isOptionalParameter(p) ? (p.questionToken || ts.createToken(55 /* QuestionToken */)) : undefined, ensureType(p, p.type, /*ignorePrivate*/ true), // Ignore private param props, since this type is going straight back into a param + ensureNoInitializer(p)); if (!suppressNewDiagnosticContexts) { getSymbolAccessibilityDiagnostic = oldDiag; } return newParam; } function shouldPrintWithInitializer(node) { - return canHaveLiteralInitializer(node) && resolver.isLiteralConstDeclaration(ts.getParseTreeNode(node)); + return canHaveLiteralInitializer(node) && resolver.isLiteralConstDeclaration(ts.getParseTreeNode(node)); // TODO: Make safe } function ensureNoInitializer(node) { if (shouldPrintWithInitializer(node)) { - return resolver.createLiteralConstValue(ts.getParseTreeNode(node)); + return resolver.createLiteralConstValue(ts.getParseTreeNode(node)); // TODO: Make safe } return undefined; } function ensureType(node, type, ignorePrivate) { - if (!ignorePrivate && ts.hasModifier(node, 8)) { + if (!ignorePrivate && ts.hasModifier(node, 8 /* Private */)) { + // Private nodes emit no types (except private parameter properties, whose parameter types are actually visible) return; } if (shouldPrintWithInitializer(node)) { + // Literal const declarations will have an initializer ensured rather than a type return; } - var shouldUseResolverType = node.kind === 149 && + var shouldUseResolverType = node.kind === 149 /* Parameter */ && (resolver.isRequiredInitializedParameter(node) || resolver.isOptionalUninitializedParameterProperty(node)); if (type && !shouldUseResolverType) { return ts.visitNode(type, visitDeclarationSubtree); } if (!ts.getParseTreeNode(node)) { - return type ? ts.visitNode(type, visitDeclarationSubtree) : ts.createKeywordTypeNode(119); + return type ? ts.visitNode(type, visitDeclarationSubtree) : ts.createKeywordTypeNode(119 /* AnyKeyword */); } - if (node.kind === 157) { - return ts.createKeywordTypeNode(119); + if (node.kind === 157 /* SetAccessor */) { + // Set accessors with no associated type node (from it's param or get accessor return) are `any` since they are never contextually typed right now + // (The inferred type here will be void, but the old declaration emitter printed `any`, so this replicates that) + return ts.createKeywordTypeNode(119 /* AnyKeyword */); } errorNameNode = node.name; var oldDiag; @@ -62293,12 +75514,12 @@ var ts; oldDiag = getSymbolAccessibilityDiagnostic; getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNode(node); } - if (node.kind === 232 || node.kind === 182) { + if (node.kind === 232 /* VariableDeclaration */ || node.kind === 182 /* BindingElement */) { return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker)); } - if (node.kind === 149 - || node.kind === 152 - || node.kind === 151) { + if (node.kind === 149 /* Parameter */ + || node.kind === 152 /* PropertyDeclaration */ + || node.kind === 151 /* PropertySignature */) { if (!node.initializer) return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker, shouldUseResolverType)); return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker, shouldUseResolverType) || resolver.createTypeOfExpression(node.initializer, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker)); @@ -62309,25 +75530,26 @@ var ts; if (!suppressNewDiagnosticContexts) { getSymbolAccessibilityDiagnostic = oldDiag; } - return returnValue || ts.createKeywordTypeNode(119); + return returnValue || ts.createKeywordTypeNode(119 /* AnyKeyword */); } } function isDeclarationAndNotVisible(node) { node = ts.getParseTreeNode(node); switch (node.kind) { - case 234: - case 239: - case 236: - case 235: - case 237: - case 238: + case 234 /* FunctionDeclaration */: + case 239 /* ModuleDeclaration */: + case 236 /* InterfaceDeclaration */: + case 235 /* ClassDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 238 /* EnumDeclaration */: return !resolver.isDeclarationVisible(node); - case 232: + // The following should be doing their own visibility checks based on filtering their members + case 232 /* VariableDeclaration */: return !getBindingNameVisible(node); - case 243: - case 244: - case 250: - case 249: + case 243 /* ImportEqualsDeclaration */: + case 244 /* ImportDeclaration */: + case 250 /* ExportDeclaration */: + case 249 /* ExportAssignment */: return false; } return false; @@ -62337,6 +75559,7 @@ var ts; return false; } if (ts.isBindingPattern(elem.name)) { + // If any child binding pattern element has been marked visible (usually by collect linked aliases), then this is visible return ts.some(elem.name.elements, getBindingNameVisible); } else { @@ -62344,17 +75567,17 @@ var ts; } } function updateParamsList(node, params, modifierMask) { - if (ts.hasModifier(node, 8)) { - return undefined; + if (ts.hasModifier(node, 8 /* Private */)) { + return undefined; // TODO: GH#18217 } var newParams = ts.map(params, function (p) { return ensureParameter(p, modifierMask); }); if (!newParams) { - return undefined; + return undefined; // TODO: GH#18217 } return ts.createNodeArray(newParams, params.hasTrailingComma); } function ensureTypeParams(node, params) { - return ts.hasModifier(node, 8) ? undefined : ts.visitNodes(params, visitDeclarationSubtree); + return ts.hasModifier(node, 8 /* Private */) ? undefined : ts.visitNodes(params, visitDeclarationSubtree); } function isEnclosingDeclaration(node) { return ts.isSourceFile(node) @@ -62379,9 +75602,9 @@ var ts; } function rewriteModuleSpecifier(parent, input) { if (!input) - return undefined; - resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || (parent.kind !== 239 && parent.kind !== 179); - if (input.kind === 9 && isBundledEmit) { + return undefined; // TODO: GH#18217 + resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || (parent.kind !== 239 /* ModuleDeclaration */ && parent.kind !== 179 /* ImportType */); + if (input.kind === 9 /* StringLiteral */ && isBundledEmit) { var newName = ts.getExternalModuleNameFromDeclaration(context.getEmitHost(), resolver, parent); if (newName) { return ts.createLiteral(newName); @@ -62392,9 +75615,11 @@ var ts; function transformImportEqualsDeclaration(decl) { if (!resolver.isDeclarationVisible(decl)) return; - if (decl.moduleReference.kind === 254) { + if (decl.moduleReference.kind === 254 /* ExternalModuleReference */) { + // Rewrite external module names if necessary var specifier = ts.getExternalModuleImportEqualsDeclarationExpression(decl); - return ts.updateImportEqualsDeclaration(decl, undefined, decl.modifiers, decl.name, ts.updateExternalModuleReference(decl.moduleReference, rewriteModuleSpecifier(decl, specifier))); + return ts.updateImportEqualsDeclaration(decl, + /*decorators*/ undefined, decl.modifiers, decl.name, ts.updateExternalModuleReference(decl.moduleReference, rewriteModuleSpecifier(decl, specifier))); } else { var oldDiag = getSymbolAccessibilityDiagnostic; @@ -62406,30 +75631,55 @@ var ts; } function transformImportDeclaration(decl) { if (!decl.importClause) { - return ts.updateImportDeclaration(decl, undefined, decl.modifiers, decl.importClause, rewriteModuleSpecifier(decl, decl.moduleSpecifier)); + // import "mod" - possibly needed for side effects? (global interface patches, module augmentations, etc) + return ts.updateImportDeclaration(decl, + /*decorators*/ undefined, decl.modifiers, decl.importClause, rewriteModuleSpecifier(decl, decl.moduleSpecifier)); } + // The `importClause` visibility corresponds to the default's visibility. var visibleDefaultBinding = decl.importClause && decl.importClause.name && resolver.isDeclarationVisible(decl.importClause) ? decl.importClause.name : undefined; if (!decl.importClause.namedBindings) { - return visibleDefaultBinding && ts.updateImportDeclaration(decl, undefined, decl.modifiers, ts.updateImportClause(decl.importClause, visibleDefaultBinding, undefined), rewriteModuleSpecifier(decl, decl.moduleSpecifier)); + // No named bindings (either namespace or list), meaning the import is just default or should be elided + return visibleDefaultBinding && ts.updateImportDeclaration(decl, /*decorators*/ undefined, decl.modifiers, ts.updateImportClause(decl.importClause, visibleDefaultBinding, + /*namedBindings*/ undefined), rewriteModuleSpecifier(decl, decl.moduleSpecifier)); } - if (decl.importClause.namedBindings.kind === 246) { - var namedBindings = resolver.isDeclarationVisible(decl.importClause.namedBindings) ? decl.importClause.namedBindings : undefined; - return visibleDefaultBinding || namedBindings ? ts.updateImportDeclaration(decl, undefined, decl.modifiers, ts.updateImportClause(decl.importClause, visibleDefaultBinding, namedBindings), rewriteModuleSpecifier(decl, decl.moduleSpecifier)) : undefined; + if (decl.importClause.namedBindings.kind === 246 /* NamespaceImport */) { + // Namespace import (optionally with visible default) + var namedBindings = resolver.isDeclarationVisible(decl.importClause.namedBindings) ? decl.importClause.namedBindings : /*namedBindings*/ undefined; + return visibleDefaultBinding || namedBindings ? ts.updateImportDeclaration(decl, /*decorators*/ undefined, decl.modifiers, ts.updateImportClause(decl.importClause, visibleDefaultBinding, namedBindings), rewriteModuleSpecifier(decl, decl.moduleSpecifier)) : undefined; } + // Named imports (optionally with visible default) var bindingList = ts.mapDefined(decl.importClause.namedBindings.elements, function (b) { return resolver.isDeclarationVisible(b) ? b : undefined; }); if ((bindingList && bindingList.length) || visibleDefaultBinding) { - return ts.updateImportDeclaration(decl, undefined, decl.modifiers, ts.updateImportClause(decl.importClause, visibleDefaultBinding, bindingList && bindingList.length ? ts.updateNamedImports(decl.importClause.namedBindings, bindingList) : undefined), rewriteModuleSpecifier(decl, decl.moduleSpecifier)); + return ts.updateImportDeclaration(decl, + /*decorators*/ undefined, decl.modifiers, ts.updateImportClause(decl.importClause, visibleDefaultBinding, bindingList && bindingList.length ? ts.updateNamedImports(decl.importClause.namedBindings, bindingList) : undefined), rewriteModuleSpecifier(decl, decl.moduleSpecifier)); } + // Nothing visible } function transformAndReplaceLatePaintedStatements(statements) { + // This is a `while` loop because `handleSymbolAccessibilityError` can see additional import aliases marked as visible during + // error handling which must now be included in the output and themselves checked for errors. + // For example: + // ``` + // module A { + // export module Q {} + // import B = Q; + // import C = B; + // export import D = C; + // } + // ``` + // In such a scenario, only Q and D are initially visible, but we don't consider imports as private names - instead we say they if they are referenced they must + // be recorded. So while checking D's visibility we mark C as visible, then we must check C which in turn marks B, completing the chain of + // dependent imports and allowing a valid declaration file output. Today, this dependent alias marking only happens for internal import aliases. while (ts.length(lateMarkedStatements)) { var i = lateMarkedStatements.shift(); if (!ts.isLateVisibilityPaintedStatement(i)) { return ts.Debug.fail("Late replaced statement was found which is not handled by the declaration transformer!: " + (ts.SyntaxKind ? ts.SyntaxKind[i.kind] : i.kind)); } - var result = transformTopLevelDeclaration(i, true); + var result = transformTopLevelDeclaration(i, /*privateDeclaration*/ true); lateStatementReplacementMap.set("" + ts.getOriginalNodeId(i), result); } + // And lastly, we need to get the final form of all those indetermine import declarations from before and add them to the output list + // (and remove them from the set to examine for outter declarations) return ts.visitNodes(statements, visitLateVisibilityMarkedStatements); function visitLateVisibilityMarkedStatements(statement) { if (ts.isLateVisibilityPaintedStatement(statement)) { @@ -62439,6 +75689,7 @@ var ts; lateStatementReplacementMap.delete(key); if (result && ts.isSourceFile(statement.parent)) { if (ts.isArray(result) ? ts.some(result, needsScopeMarker) : needsScopeMarker(result)) { + // Top-level declarations in .d.ts files are always considered exported even without a modifier unless there's an export assignment or specifier needsScopeFixMarker = true; } if (ts.isArray(result) ? ts.some(result, isExternalModuleIndicator) : isExternalModuleIndicator(result)) { @@ -62452,10 +75703,11 @@ var ts; } } function isExternalModuleIndicator(result) { - return ts.isAnyImportOrReExport(result) || ts.isExportAssignment(result) || ts.hasModifier(result, 1); + // Exported top-level member indicates moduleness + return ts.isAnyImportOrReExport(result) || ts.isExportAssignment(result) || ts.hasModifier(result, 1 /* Export */); } function needsScopeMarker(result) { - return !ts.isAnyImportOrReExport(result) && !ts.isExportAssignment(result) && !ts.hasModifier(result, 1) && !ts.isAmbientModule(result); + return !ts.isAnyImportOrReExport(result) && !ts.isExportAssignment(result) && !ts.hasModifier(result, 1 /* Export */) && !ts.isAmbientModule(result); } function visitDeclarationSubtree(input) { if (shouldStripInternal(input)) @@ -62467,8 +75719,10 @@ var ts; return; } } + // Elide implementation signatures from overload sets if (ts.isFunctionLike(input) && resolver.isImplementationOfOverload(input)) return; + // Elide semicolon class statements if (ts.isSemicolonClassElement(input)) return; var previousEnclosingDeclaration; @@ -62477,11 +75731,12 @@ var ts; enclosingDeclaration = input; } var oldDiag = getSymbolAccessibilityDiagnostic; + // Emit methods which are private as properties with no type information if (ts.isMethodDeclaration(input) || ts.isMethodSignature(input)) { - if (ts.hasModifier(input, 8)) { + if (ts.hasModifier(input, 8 /* Private */)) { if (input.symbol && input.symbol.declarations && input.symbol.declarations[0] !== input) - return; - return cleanup(ts.createProperty(undefined, ensureModifiers(input), input.name, undefined, undefined, undefined)); + return; // Elide all but the first overload + return cleanup(ts.createProperty(/*decorators*/ undefined, ensureModifiers(input), input.name, /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined)); } } var canProdiceDiagnostic = ts.canProduceDiagnostics(input); @@ -62492,75 +75747,84 @@ var ts; checkEntityNameVisibility(input.exprName, enclosingDeclaration); } var oldWithinObjectLiteralType = suppressNewDiagnosticContexts; - var shouldEnterSuppressNewDiagnosticsContextContext = ((input.kind === 166 || input.kind === 177) && input.parent.kind !== 237); + var shouldEnterSuppressNewDiagnosticsContextContext = ((input.kind === 166 /* TypeLiteral */ || input.kind === 177 /* MappedType */) && input.parent.kind !== 237 /* TypeAliasDeclaration */); if (shouldEnterSuppressNewDiagnosticsContextContext) { + // We stop making new diagnostic contexts within object literal types. Unless it's an object type on the RHS of a type alias declaration. Then we do. suppressNewDiagnosticContexts = true; } if (isProcessedComponent(input)) { switch (input.kind) { - case 207: { + case 207 /* ExpressionWithTypeArguments */: { if ((ts.isEntityName(input.expression) || ts.isEntityNameExpression(input.expression))) { checkEntityNameVisibility(input.expression, enclosingDeclaration); } var node = ts.visitEachChild(input, visitDeclarationSubtree, context); return cleanup(ts.updateExpressionWithTypeArguments(node, ts.parenthesizeTypeParameters(node.typeArguments), node.expression)); } - case 162: { + case 162 /* TypeReference */: { checkEntityNameVisibility(input.typeName, enclosingDeclaration); var node = ts.visitEachChild(input, visitDeclarationSubtree, context); return cleanup(ts.updateTypeReferenceNode(node, node.typeName, ts.parenthesizeTypeParameters(node.typeArguments))); } - case 159: + case 159 /* ConstructSignature */: return cleanup(ts.updateConstructSignature(input, ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type))); - case 155: { - var isPrivate = ts.hasModifier(input, 8); - var ctor = ts.createSignatureDeclaration(155, isPrivate ? undefined : ensureTypeParams(input, input.typeParameters), isPrivate ? undefined : updateParamsList(input, input.parameters, 0), undefined); + case 155 /* Constructor */: { + var isPrivate = ts.hasModifier(input, 8 /* Private */); + // A constructor declaration may not have a type annotation + var ctor = ts.createSignatureDeclaration(155 /* Constructor */, isPrivate ? undefined : ensureTypeParams(input, input.typeParameters), + // TODO: GH#18217 + isPrivate ? undefined : updateParamsList(input, input.parameters, 0 /* None */), + /*type*/ undefined); ctor.modifiers = ts.createNodeArray(ensureModifiers(input)); return cleanup(ctor); } - case 154: { - var sig = ts.createSignatureDeclaration(153, ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type)); + case 154 /* MethodDeclaration */: { + var sig = ts.createSignatureDeclaration(153 /* MethodSignature */, ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type)); sig.name = input.name; sig.modifiers = ts.createNodeArray(ensureModifiers(input)); sig.questionToken = input.questionToken; return cleanup(sig); } - case 156: { + case 156 /* GetAccessor */: { var newNode = ensureAccessor(input); return cleanup(newNode); } - case 157: { + case 157 /* SetAccessor */: { var newNode = ensureAccessor(input); return cleanup(newNode); } - case 152: - return cleanup(ts.updateProperty(input, undefined, ensureModifiers(input), input.name, input.questionToken, !ts.hasModifier(input, 8) ? ensureType(input, input.type) : undefined, ensureNoInitializer(input))); - case 151: - return cleanup(ts.updatePropertySignature(input, ensureModifiers(input), input.name, input.questionToken, !ts.hasModifier(input, 8) ? ensureType(input, input.type) : undefined, ensureNoInitializer(input))); - case 153: { + case 152 /* PropertyDeclaration */: + return cleanup(ts.updateProperty(input, + /*decorators*/ undefined, ensureModifiers(input), input.name, input.questionToken, !ts.hasModifier(input, 8 /* Private */) ? ensureType(input, input.type) : undefined, ensureNoInitializer(input))); + case 151 /* PropertySignature */: + return cleanup(ts.updatePropertySignature(input, ensureModifiers(input), input.name, input.questionToken, !ts.hasModifier(input, 8 /* Private */) ? ensureType(input, input.type) : undefined, ensureNoInitializer(input))); + case 153 /* MethodSignature */: { return cleanup(ts.updateMethodSignature(input, ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type), input.name, input.questionToken)); } - case 158: { + case 158 /* CallSignature */: { return cleanup(ts.updateCallSignature(input, ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type))); } - case 160: { - return cleanup(ts.updateIndexSignature(input, undefined, ensureModifiers(input), updateParamsList(input, input.parameters), ts.visitNode(input.type, visitDeclarationSubtree) || ts.createKeywordTypeNode(119))); + case 160 /* IndexSignature */: { + return cleanup(ts.updateIndexSignature(input, + /*decorators*/ undefined, ensureModifiers(input), updateParamsList(input, input.parameters), ts.visitNode(input.type, visitDeclarationSubtree) || ts.createKeywordTypeNode(119 /* AnyKeyword */))); } - case 232: { + case 232 /* VariableDeclaration */: { if (ts.isBindingPattern(input.name)) { return recreateBindingPattern(input.name); } shouldEnterSuppressNewDiagnosticsContextContext = true; - suppressNewDiagnosticContexts = true; + suppressNewDiagnosticContexts = true; // Variable declaration types also suppress new diagnostic contexts, provided the contexts wouldn't be made for binding pattern types return cleanup(ts.updateVariableDeclaration(input, input.name, ensureType(input, input.type), ensureNoInitializer(input))); } - case 148: { + case 148 /* TypeParameter */: { if (isPrivateMethodTypeParameter(input) && (input.default || input.constraint)) { - return cleanup(ts.updateTypeParameterDeclaration(input, input.name, undefined, undefined)); + return cleanup(ts.updateTypeParameterDeclaration(input, input.name, /*constraint*/ undefined, /*defaultType*/ undefined)); } return cleanup(ts.visitEachChild(input, visitDeclarationSubtree, context)); } - case 171: { + case 171 /* ConditionalType */: { + // We have to process conditional types in a special way because for visibility purposes we need to push a new enclosingDeclaration + // just for the `infer` types in the true branch. It's an implicit declaration scope that only applies to _part_ of the type. var checkType = ts.visitNode(input.checkType, visitDeclarationSubtree); var extendsType = ts.visitNode(input.extendsType, visitDeclarationSubtree); var oldEnclosingDecl = enclosingDeclaration; @@ -62570,13 +75834,13 @@ var ts; var falseType = ts.visitNode(input.falseType, visitDeclarationSubtree); return cleanup(ts.updateConditionalTypeNode(input, checkType, extendsType, trueType, falseType)); } - case 163: { + case 163 /* FunctionType */: { return cleanup(ts.updateFunctionTypeNode(input, ts.visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), ts.visitNode(input.type, visitDeclarationSubtree))); } - case 164: { + case 164 /* ConstructorType */: { return cleanup(ts.updateConstructorTypeNode(input, ts.visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), ts.visitNode(input.type, visitDeclarationSubtree))); } - case 179: { + case 179 /* ImportType */: { if (!ts.isLiteralImportTypeNode(input)) return cleanup(input); return cleanup(ts.updateImportTypeNode(input, ts.updateLiteralTypeNode(input.argument, rewriteModuleSpecifier(input, input.argument.literal)), input.qualifier, ts.visitNodes(input.typeArguments, visitDeclarationSubtree, ts.isTypeNode), input.isTypeOf)); @@ -62605,28 +75869,32 @@ var ts; } } function isPrivateMethodTypeParameter(node) { - return node.parent.kind === 154 && ts.hasModifier(node.parent, 8); + return node.parent.kind === 154 /* MethodDeclaration */ && ts.hasModifier(node.parent, 8 /* Private */); } function visitDeclarationStatements(input) { if (!isPreservedDeclarationStatement(input)) { + // return undefined for unmatched kinds to omit them from the tree return; } if (shouldStripInternal(input)) return; switch (input.kind) { - case 250: { + case 250 /* ExportDeclaration */: { if (ts.isSourceFile(input.parent)) { resultHasExternalModuleIndicator = true; resultHasScopeMarker = true; } - return ts.updateExportDeclaration(input, undefined, input.modifiers, input.exportClause, rewriteModuleSpecifier(input, input.moduleSpecifier)); + // Always visible if the parent node isn't dropped for being not visible + // Rewrite external module names if necessary + return ts.updateExportDeclaration(input, /*decorators*/ undefined, input.modifiers, input.exportClause, rewriteModuleSpecifier(input, input.moduleSpecifier)); } - case 249: { + case 249 /* ExportAssignment */: { + // Always visible if the parent node isn't dropped for being not visible if (ts.isSourceFile(input.parent)) { resultHasExternalModuleIndicator = true; resultHasScopeMarker = true; } - if (input.expression.kind === 71) { + if (input.expression.kind === 71 /* Identifier */) { return input; } else { @@ -62635,13 +75903,14 @@ var ts; diagnosticMessage: ts.Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0, errorNode: input }); }; - var varDecl = ts.createVariableDeclaration(newId, resolver.createTypeOfExpression(input.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), undefined); - var statement = ts.createVariableStatement(needsDeclare ? [ts.createModifier(124)] : [], ts.createVariableDeclarationList([varDecl], 2)); + var varDecl = ts.createVariableDeclaration(newId, resolver.createTypeOfExpression(input.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined); + var statement = ts.createVariableStatement(needsDeclare ? [ts.createModifier(124 /* DeclareKeyword */)] : [], ts.createVariableDeclarationList([varDecl], 2 /* Const */)); return [statement, ts.updateExportAssignment(input, input.decorators, input.modifiers, newId)]; } } } var result = transformTopLevelDeclaration(input); + // Don't actually transform yet; just leave as original node - will be elided/swapped by late pass lateStatementReplacementMap.set("" + ts.getOriginalNodeId(input), result); return input; } @@ -62649,15 +75918,16 @@ var ts; if (shouldStripInternal(input)) return; switch (input.kind) { - case 243: { + case 243 /* ImportEqualsDeclaration */: { return transformImportEqualsDeclaration(input); } - case 244: { + case 244 /* ImportDeclaration */: { return transformImportDeclaration(input); } } if (ts.isDeclaration(input) && isDeclarationAndNotVisible(input)) return; + // Elide implementation signatures from overload sets if (ts.isFunctionLike(input) && resolver.isImplementationOfOverload(input)) return; var previousEnclosingDeclaration; @@ -62672,36 +75942,45 @@ var ts; } var previousNeedsDeclare = needsDeclare; switch (input.kind) { - case 237: - return cleanup(ts.updateTypeAliasDeclaration(input, undefined, ensureModifiers(input, isPrivate), input.name, ts.visitNodes(input.typeParameters, visitDeclarationSubtree, ts.isTypeParameterDeclaration), ts.visitNode(input.type, visitDeclarationSubtree, ts.isTypeNode))); - case 236: { - return cleanup(ts.updateInterfaceDeclaration(input, undefined, ensureModifiers(input, isPrivate), input.name, ensureTypeParams(input, input.typeParameters), transformHeritageClauses(input.heritageClauses), ts.visitNodes(input.members, visitDeclarationSubtree))); + case 237 /* TypeAliasDeclaration */: // Type aliases get `declare`d if need be (for legacy support), but that's all + return cleanup(ts.updateTypeAliasDeclaration(input, + /*decorators*/ undefined, ensureModifiers(input, isPrivate), input.name, ts.visitNodes(input.typeParameters, visitDeclarationSubtree, ts.isTypeParameterDeclaration), ts.visitNode(input.type, visitDeclarationSubtree, ts.isTypeNode))); + case 236 /* InterfaceDeclaration */: { + return cleanup(ts.updateInterfaceDeclaration(input, + /*decorators*/ undefined, ensureModifiers(input, isPrivate), input.name, ensureTypeParams(input, input.typeParameters), transformHeritageClauses(input.heritageClauses), ts.visitNodes(input.members, visitDeclarationSubtree))); } - case 234: { - return cleanup(ts.updateFunctionDeclaration(input, undefined, ensureModifiers(input, isPrivate), undefined, input.name, ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type), undefined)); + case 234 /* FunctionDeclaration */: { + // Generators lose their generator-ness, excepting their return type + return cleanup(ts.updateFunctionDeclaration(input, + /*decorators*/ undefined, ensureModifiers(input, isPrivate), + /*asteriskToken*/ undefined, input.name, ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type), + /*body*/ undefined)); } - case 239: { + case 239 /* ModuleDeclaration */: { needsDeclare = false; var inner = input.body; - if (inner && inner.kind === 240) { + if (inner && inner.kind === 240 /* ModuleBlock */) { var statements = ts.visitNodes(inner.statements, visitDeclarationStatements); var body = ts.updateModuleBlock(inner, transformAndReplaceLatePaintedStatements(statements)); needsDeclare = previousNeedsDeclare; var mods = ensureModifiers(input, isPrivate); - return cleanup(ts.updateModuleDeclaration(input, undefined, mods, ts.isExternalModuleAugmentation(input) ? rewriteModuleSpecifier(input, input.name) : input.name, body)); + return cleanup(ts.updateModuleDeclaration(input, + /*decorators*/ undefined, mods, ts.isExternalModuleAugmentation(input) ? rewriteModuleSpecifier(input, input.name) : input.name, body)); } else { needsDeclare = previousNeedsDeclare; var mods = ensureModifiers(input, isPrivate); needsDeclare = false; ts.visitNode(inner, visitDeclarationStatements); - var id = "" + ts.getOriginalNodeId(inner); + // eagerly transform nested namespaces (the nesting doesn't need any elision or painting done) + var id = "" + ts.getOriginalNodeId(inner); // TODO: GH#18217 var body = lateStatementReplacementMap.get(id); lateStatementReplacementMap.delete(id); - return cleanup(ts.updateModuleDeclaration(input, undefined, mods, input.name, body)); + return cleanup(ts.updateModuleDeclaration(input, + /*decorators*/ undefined, mods, input.name, body)); } } - case 235: { + case 235 /* ClassDeclaration */: { var modifiers = ts.createNodeArray(ensureModifiers(input, isPrivate)); var typeParameters = ensureTypeParams(input, input.typeParameters); var ctor = ts.getFirstConstructorWithBody(input); @@ -62709,13 +75988,15 @@ var ts; if (ctor) { var oldDiag_1 = getSymbolAccessibilityDiagnostic; parameterProperties = ts.compact(ts.flatMap(ctor.parameters, function (param) { - if (!ts.hasModifier(param, 92)) + if (!ts.hasModifier(param, 92 /* ParameterPropertyModifier */)) return; getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNode(param); - if (param.name.kind === 71) { - return preserveJsDoc(ts.createProperty(undefined, ensureModifiers(param), param.name, param.questionToken, ensureType(param, param.type), ensureNoInitializer(param)), param); + if (param.name.kind === 71 /* Identifier */) { + return preserveJsDoc(ts.createProperty( + /*decorators*/ undefined, ensureModifiers(param), param.name, param.questionToken, ensureType(param, param.type), ensureNoInitializer(param)), param); } else { + // Pattern - this is currently an error, but we emit declarations for it somewhat correctly return walkBindingPattern(param.name); } function walkBindingPattern(pattern) { @@ -62728,7 +76009,10 @@ var ts; elems = ts.concatenate(elems, walkBindingPattern(elem.name)); } elems = elems || []; - elems.push(ts.createProperty(undefined, ensureModifiers(param), elem.name, undefined, ensureType(elem, undefined), undefined)); + elems.push(ts.createProperty( + /*decorators*/ undefined, ensureModifiers(param), elem.name, + /*questionToken*/ undefined, ensureType(elem, /*type*/ undefined), + /*initializer*/ undefined)); } return elems; } @@ -62737,44 +76021,49 @@ var ts; } var members = ts.createNodeArray(ts.concatenate(parameterProperties, ts.visitNodes(input.members, visitDeclarationSubtree))); var extendsClause_1 = ts.getClassExtendsHeritageClauseElement(input); - if (extendsClause_1 && !ts.isEntityNameExpression(extendsClause_1.expression) && extendsClause_1.expression.kind !== 95) { - var newId_1 = ts.createOptimisticUniqueName(ts.unescapeLeadingUnderscores(input.name.escapedText) + "_base"); + if (extendsClause_1 && !ts.isEntityNameExpression(extendsClause_1.expression) && extendsClause_1.expression.kind !== 95 /* NullKeyword */) { + // We must add a temporary declaration for the extends clause expression + var newId_1 = ts.createOptimisticUniqueName(ts.unescapeLeadingUnderscores(input.name.escapedText) + "_base"); // TODO: GH#18217 getSymbolAccessibilityDiagnostic = function () { return ({ diagnosticMessage: ts.Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1, errorNode: extendsClause_1, typeName: input.name }); }; - var varDecl = ts.createVariableDeclaration(newId_1, resolver.createTypeOfExpression(extendsClause_1.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), undefined); - var statement = ts.createVariableStatement(needsDeclare ? [ts.createModifier(124)] : [], ts.createVariableDeclarationList([varDecl], 2)); + var varDecl = ts.createVariableDeclaration(newId_1, resolver.createTypeOfExpression(extendsClause_1.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined); + var statement = ts.createVariableStatement(needsDeclare ? [ts.createModifier(124 /* DeclareKeyword */)] : [], ts.createVariableDeclarationList([varDecl], 2 /* Const */)); var heritageClauses = ts.createNodeArray(ts.map(input.heritageClauses, function (clause) { - if (clause.token === 85) { + if (clause.token === 85 /* ExtendsKeyword */) { var oldDiag_2 = getSymbolAccessibilityDiagnostic; getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNode(clause.types[0]); var newClause = ts.updateHeritageClause(clause, ts.map(clause.types, function (t) { return ts.updateExpressionWithTypeArguments(t, ts.visitNodes(t.typeArguments, visitDeclarationSubtree), newId_1); })); getSymbolAccessibilityDiagnostic = oldDiag_2; return newClause; } - return ts.updateHeritageClause(clause, ts.visitNodes(ts.createNodeArray(ts.filter(clause.types, function (t) { return ts.isEntityNameExpression(t.expression) || t.expression.kind === 95; })), visitDeclarationSubtree)); + return ts.updateHeritageClause(clause, ts.visitNodes(ts.createNodeArray(ts.filter(clause.types, function (t) { return ts.isEntityNameExpression(t.expression) || t.expression.kind === 95 /* NullKeyword */; })), visitDeclarationSubtree)); })); - return [statement, cleanup(ts.updateClassDeclaration(input, undefined, modifiers, input.name, typeParameters, heritageClauses, members))]; + return [statement, cleanup(ts.updateClassDeclaration(input, + /*decorators*/ undefined, modifiers, input.name, typeParameters, heritageClauses, members))]; // TODO: GH#18217 } else { var heritageClauses = transformHeritageClauses(input.heritageClauses); - return cleanup(ts.updateClassDeclaration(input, undefined, modifiers, input.name, typeParameters, heritageClauses, members)); + return cleanup(ts.updateClassDeclaration(input, + /*decorators*/ undefined, modifiers, input.name, typeParameters, heritageClauses, members)); } } - case 214: { + case 214 /* VariableStatement */: { return cleanup(transformVariableStatement(input, isPrivate)); } - case 238: { - return cleanup(ts.updateEnumDeclaration(input, undefined, ts.createNodeArray(ensureModifiers(input, isPrivate)), input.name, ts.createNodeArray(ts.mapDefined(input.members, function (m) { + case 238 /* EnumDeclaration */: { + return cleanup(ts.updateEnumDeclaration(input, /*decorators*/ undefined, ts.createNodeArray(ensureModifiers(input, isPrivate)), input.name, ts.createNodeArray(ts.mapDefined(input.members, function (m) { if (shouldStripInternal(m)) return; + // Rewrite enum values to their constants, if available var constValue = resolver.getConstantValue(m); return preserveJsDoc(ts.updateEnumMember(m, m.name, constValue !== undefined ? ts.createLiteral(constValue) : undefined), m); })))); } } + // Anything left unhandled is an error, so this should be unreachable return ts.Debug.assertNever(input, "Unhandled top-level node in declaration emit: " + ts.SyntaxKind[input.kind]); function cleanup(node) { if (isEnclosingDeclaration(input)) { @@ -62783,7 +76072,7 @@ var ts; if (canProdiceDiagnostic) { getSymbolAccessibilityDiagnostic = oldDiag; } - if (input.kind === 239) { + if (input.kind === 239 /* ModuleDeclaration */) { needsDeclare = previousNeedsDeclare; } if (node === input) { @@ -62804,7 +76093,7 @@ var ts; return ts.flatten(ts.mapDefined(d.elements, function (e) { return recreateBindingElement(e); })); } function recreateBindingElement(e) { - if (e.kind === 206) { + if (e.kind === 206 /* OmittedExpression */) { return; } if (e.name) { @@ -62814,7 +76103,7 @@ var ts; return recreateBindingPattern(e.name); } else { - return ts.createVariableDeclaration(e.name, ensureType(e, undefined), undefined); + return ts.createVariableDeclaration(e.name, ensureType(e, /*type*/ undefined), /*initializer*/ undefined); } } } @@ -62825,7 +76114,7 @@ var ts; getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNodeName(node); } errorNameNode = node.name; - ts.Debug.assert(resolver.isLateBound(ts.getParseTreeNode(node))); + ts.Debug.assert(resolver.isLateBound(ts.getParseTreeNode(node))); // Should only be called with dynamic names var decl = node; var entityName = decl.name.expression; checkEntityNameVisibility(entityName, enclosingDeclaration); @@ -62856,12 +76145,12 @@ var ts; return ts.createModifiersFromModifierFlags(newFlags); } function ensureModifierFlags(node, privateDeclaration) { - var mask = 3071 ^ (4 | 256); - var additions = (needsDeclare && !isAlwaysType(node)) ? 2 : 0; - var parentIsFile = node.parent.kind === 274; + var mask = 3071 /* All */ ^ (4 /* Public */ | 256 /* Async */); // No async modifiers in declaration files + var additions = (needsDeclare && !isAlwaysType(node)) ? 2 /* Ambient */ : 0 /* None */; + var parentIsFile = node.parent.kind === 274 /* SourceFile */; if (!parentIsFile || (isBundledEmit && parentIsFile && ts.isExternalModule(node.parent))) { - mask ^= ((privateDeclaration || (isBundledEmit && parentIsFile) ? 0 : 1) | 512 | 2); - additions = 0; + mask ^= ((privateDeclaration || (isBundledEmit && parentIsFile) ? 0 : 1 /* Export */) | 512 /* Default */ | 2 /* Ambient */); + additions = 0 /* None */; } return maskModifierFlags(node, mask, additions); } @@ -62873,13 +76162,14 @@ var ts; var accessorType = getTypeAnnotationFromAccessor(node); if (!accessorType && accessors.secondAccessor) { accessorType = getTypeAnnotationFromAccessor(accessors.secondAccessor); + // If we end up pulling the type from the second accessor, we also need to change the diagnostic context to get the expected error message getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNode(accessors.secondAccessor); } - var prop = ts.createProperty(undefined, maskModifiers(node, undefined, (!accessors.setAccessor) ? 64 : 0), node.name, node.questionToken, ensureType(node, accessorType), undefined); + var prop = ts.createProperty(/*decorators*/ undefined, maskModifiers(node, /*mask*/ undefined, (!accessors.setAccessor) ? 64 /* Readonly */ : 0 /* None */), node.name, node.questionToken, ensureType(node, accessorType), /*initializer*/ undefined); var leadingsSyntheticCommentRanges = accessors.secondAccessor && ts.getLeadingCommentRangesOfNode(accessors.secondAccessor, currentSourceFile); if (leadingsSyntheticCommentRanges) { var _loop_10 = function (range) { - if (range.kind === 3) { + if (range.kind === 3 /* MultiLineCommentTrivia */) { var text = currentSourceFile.text.slice(range.pos + 2, range.end - 2); var lines = text.split(/\r\n?|\n/g); if (lines.length > 1) { @@ -62899,90 +76189,92 @@ var ts; } function transformHeritageClauses(nodes) { return ts.createNodeArray(ts.filter(ts.map(nodes, function (clause) { return ts.updateHeritageClause(clause, ts.visitNodes(ts.createNodeArray(ts.filter(clause.types, function (t) { - return ts.isEntityNameExpression(t.expression) || (clause.token === 85 && t.expression.kind === 95); + return ts.isEntityNameExpression(t.expression) || (clause.token === 85 /* ExtendsKeyword */ && t.expression.kind === 95 /* NullKeyword */); })), visitDeclarationSubtree)); }), function (clause) { return clause.types && !!clause.types.length; })); } } ts.transformDeclarations = transformDeclarations; function isAlwaysType(node) { - if (node.kind === 236) { + if (node.kind === 236 /* InterfaceDeclaration */) { return true; } return false; } + // Elide "public" modifier, as it is the default function maskModifiers(node, modifierMask, modifierAdditions) { return ts.createModifiersFromModifierFlags(maskModifierFlags(node, modifierMask, modifierAdditions)); } function maskModifierFlags(node, modifierMask, modifierAdditions) { - if (modifierMask === void 0) { modifierMask = 3071 ^ 4; } - if (modifierAdditions === void 0) { modifierAdditions = 0; } + if (modifierMask === void 0) { modifierMask = 3071 /* All */ ^ 4 /* Public */; } + if (modifierAdditions === void 0) { modifierAdditions = 0 /* None */; } var flags = (ts.getModifierFlags(node) & modifierMask) | modifierAdditions; - if (flags & 512 && flags & 2) { - flags ^= 2; + if (flags & 512 /* Default */ && flags & 2 /* Ambient */) { + flags ^= 2 /* Ambient */; // `declare` is never required alongside `default` (and would be an error if printed) } return flags; } function getTypeAnnotationFromAccessor(accessor) { if (accessor) { - return accessor.kind === 156 - ? accessor.type + return accessor.kind === 156 /* GetAccessor */ + ? accessor.type // Getter - return type : accessor.parameters.length > 0 - ? accessor.parameters[0].type + ? accessor.parameters[0].type // Setter parameter type : undefined; } } function canHaveLiteralInitializer(node) { switch (node.kind) { - case 232: - case 152: - case 151: - case 149: + case 232 /* VariableDeclaration */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 149 /* Parameter */: return true; } return false; } function isPreservedDeclarationStatement(node) { switch (node.kind) { - case 234: - case 239: - case 243: - case 236: - case 235: - case 237: - case 238: - case 214: - case 244: - case 250: - case 249: + case 234 /* FunctionDeclaration */: + case 239 /* ModuleDeclaration */: + case 243 /* ImportEqualsDeclaration */: + case 236 /* InterfaceDeclaration */: + case 235 /* ClassDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 238 /* EnumDeclaration */: + case 214 /* VariableStatement */: + case 244 /* ImportDeclaration */: + case 250 /* ExportDeclaration */: + case 249 /* ExportAssignment */: return true; } return false; } function isProcessedComponent(node) { switch (node.kind) { - case 159: - case 155: - case 154: - case 156: - case 157: - case 152: - case 151: - case 153: - case 158: - case 160: - case 232: - case 148: - case 207: - case 162: - case 171: - case 163: - case 164: - case 179: + case 159 /* ConstructSignature */: + case 155 /* Constructor */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 153 /* MethodSignature */: + case 158 /* CallSignature */: + case 160 /* IndexSignature */: + case 232 /* VariableDeclaration */: + case 148 /* TypeParameter */: + case 207 /* ExpressionWithTypeArguments */: + case 162 /* TypeReference */: + case 171 /* ConditionalType */: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 179 /* ImportType */: return true; } return false; } })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { function getModuleTransformer(moduleKind) { @@ -63015,32 +76307,44 @@ var ts; var transformers = []; ts.addRange(transformers, customTransformers && customTransformers.before); transformers.push(ts.transformTypeScript); - if (jsx === 2) { + if (jsx === 2 /* React */) { transformers.push(ts.transformJsx); } - if (languageVersion < 6) { + if (languageVersion < 6 /* ESNext */) { transformers.push(ts.transformESNext); } - if (languageVersion < 4) { + if (languageVersion < 4 /* ES2017 */) { transformers.push(ts.transformES2017); } - if (languageVersion < 3) { + if (languageVersion < 3 /* ES2016 */) { transformers.push(ts.transformES2016); } - if (languageVersion < 2) { + if (languageVersion < 2 /* ES2015 */) { transformers.push(ts.transformES2015); transformers.push(ts.transformGenerators); } transformers.push(getModuleTransformer(moduleKind)); - if (languageVersion < 1) { + // The ES5 transformer is last so that it can substitute expressions like `exports.default` + // for ES3. + if (languageVersion < 1 /* ES5 */) { transformers.push(ts.transformES5); } ts.addRange(transformers, customTransformers && customTransformers.after); return transformers; } ts.getTransformers = getTransformers; + /** + * Transforms an array of SourceFiles by passing them through each transformer. + * + * @param resolver The emit resolver provided by the checker. + * @param host The emit host object used to interact with the file system. + * @param options Compiler options to surface in the `TransformationContext`. + * @param nodes An array of nodes to transform. + * @param transforms An array of `TransformerFactory` callbacks. + * @param allowDtsFiles A value indicating whether to allow the transformation of .d.ts files. + */ function transformNodes(resolver, host, options, nodes, transformers, allowDtsFiles) { - var enabledSyntaxKindFeatures = new Array(306); + var enabledSyntaxKindFeatures = new Array(306 /* Count */); var lexicalEnvironmentVariableDeclarations; var lexicalEnvironmentFunctionDeclarations; var lexicalEnvironmentVariableDeclarationsStack = []; @@ -63050,8 +76354,10 @@ var ts; var emitHelpers; var onSubstituteNode = function (_, node) { return node; }; var onEmitNode = function (hint, node, callback) { return callback(hint, node); }; - var state = 0; + var state = 0 /* Uninitialized */; var diagnostics = []; + // The transformation context is provided to each transformer as part of transformer + // initialization. var context = { getCompilerOptions: function () { return options; }, getEmitResolver: function () { return resolver; }, @@ -63070,13 +76376,13 @@ var ts; isEmitNotificationEnabled: isEmitNotificationEnabled, get onSubstituteNode() { return onSubstituteNode; }, set onSubstituteNode(value) { - ts.Debug.assert(state < 1, "Cannot modify transformation hooks after initialization has completed."); + ts.Debug.assert(state < 1 /* Initialized */, "Cannot modify transformation hooks after initialization has completed."); ts.Debug.assert(value !== undefined, "Value must not be 'undefined'"); onSubstituteNode = value; }, get onEmitNode() { return onEmitNode; }, set onEmitNode(value) { - ts.Debug.assert(state < 1, "Cannot modify transformation hooks after initialization has completed."); + ts.Debug.assert(state < 1 /* Initialized */, "Cannot modify transformation hooks after initialization has completed."); ts.Debug.assert(value !== undefined, "Value must not be 'undefined'"); onEmitNode = value; }, @@ -63084,15 +76390,20 @@ var ts; diagnostics.push(diag); } }; + // Ensure the parse tree is clean before applying transformations for (var _i = 0, nodes_4 = nodes; _i < nodes_4.length; _i++) { var node = nodes_4[_i]; ts.disposeEmitNodes(ts.getSourceFileOfNode(ts.getParseTreeNode(node))); } ts.performance.mark("beforeTransform"); + // Chain together and initialize each transformer. var transformation = ts.chain.apply(void 0, transformers)(context); - state = 1; + // prevent modification of transformation hooks. + state = 1 /* Initialized */; + // Transform each node. var transformed = ts.map(nodes, allowDtsFiles ? transformation : transformRoot); - state = 2; + // prevent modification of the lexical environment. + state = 2 /* Completed */; ts.performance.mark("afterTransform"); ts.performance.measure("transformTime", "beforeTransform", "afterTransform"); return { @@ -63105,28 +76416,55 @@ var ts; function transformRoot(node) { return node && (!ts.isSourceFile(node) || !node.isDeclarationFile) ? transformation(node) : node; } + /** + * Enables expression substitutions in the pretty printer for the provided SyntaxKind. + */ function enableSubstitution(kind) { - ts.Debug.assert(state < 2, "Cannot modify the transformation context after transformation has completed."); - enabledSyntaxKindFeatures[kind] |= 1; + ts.Debug.assert(state < 2 /* Completed */, "Cannot modify the transformation context after transformation has completed."); + enabledSyntaxKindFeatures[kind] |= 1 /* Substitution */; } + /** + * Determines whether expression substitutions are enabled for the provided node. + */ function isSubstitutionEnabled(node) { - return (enabledSyntaxKindFeatures[node.kind] & 1) !== 0 - && (ts.getEmitFlags(node) & 4) === 0; + return (enabledSyntaxKindFeatures[node.kind] & 1 /* Substitution */) !== 0 + && (ts.getEmitFlags(node) & 4 /* NoSubstitution */) === 0; } + /** + * Emits a node with possible substitution. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emitCallback The callback used to emit the node or its substitute. + */ function substituteNode(hint, node) { - ts.Debug.assert(state < 3, "Cannot substitute a node after the result is disposed."); + ts.Debug.assert(state < 3 /* Disposed */, "Cannot substitute a node after the result is disposed."); return node && isSubstitutionEnabled(node) && onSubstituteNode(hint, node) || node; } + /** + * Enables before/after emit notifications in the pretty printer for the provided SyntaxKind. + */ function enableEmitNotification(kind) { - ts.Debug.assert(state < 2, "Cannot modify the transformation context after transformation has completed."); - enabledSyntaxKindFeatures[kind] |= 2; + ts.Debug.assert(state < 2 /* Completed */, "Cannot modify the transformation context after transformation has completed."); + enabledSyntaxKindFeatures[kind] |= 2 /* EmitNotifications */; } + /** + * Determines whether before/after emit notifications should be raised in the pretty + * printer when it emits a node. + */ function isEmitNotificationEnabled(node) { - return (enabledSyntaxKindFeatures[node.kind] & 2) !== 0 - || (ts.getEmitFlags(node) & 2) !== 0; + return (enabledSyntaxKindFeatures[node.kind] & 2 /* EmitNotifications */) !== 0 + || (ts.getEmitFlags(node) & 2 /* AdviseOnEmitNode */) !== 0; } + /** + * Emits a node with possible emit notification. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emitCallback The callback used to emit the node. + */ function emitNodeWithNotification(hint, node, emitCallback) { - ts.Debug.assert(state < 3, "Cannot invoke TransformationResult callbacks after the result is disposed."); + ts.Debug.assert(state < 3 /* Disposed */, "Cannot invoke TransformationResult callbacks after the result is disposed."); if (node) { if (isEmitNotificationEnabled(node)) { onEmitNode(hint, node, emitCallback); @@ -63136,10 +76474,13 @@ var ts; } } } + /** + * Records a hoisted variable declaration for the provided name within a lexical environment. + */ function hoistVariableDeclaration(name) { - ts.Debug.assert(state > 0, "Cannot modify the lexical environment during initialization."); - ts.Debug.assert(state < 2, "Cannot modify the lexical environment after transformation has completed."); - var decl = ts.setEmitFlags(ts.createVariableDeclaration(name), 64); + ts.Debug.assert(state > 0 /* Uninitialized */, "Cannot modify the lexical environment during initialization."); + ts.Debug.assert(state < 2 /* Completed */, "Cannot modify the lexical environment after transformation has completed."); + var decl = ts.setEmitFlags(ts.createVariableDeclaration(name), 64 /* NoNestedSourceMaps */); if (!lexicalEnvironmentVariableDeclarations) { lexicalEnvironmentVariableDeclarations = [decl]; } @@ -63147,9 +76488,12 @@ var ts; lexicalEnvironmentVariableDeclarations.push(decl); } } + /** + * Records a hoisted function declaration within a lexical environment. + */ function hoistFunctionDeclaration(func) { - ts.Debug.assert(state > 0, "Cannot modify the lexical environment during initialization."); - ts.Debug.assert(state < 2, "Cannot modify the lexical environment after transformation has completed."); + ts.Debug.assert(state > 0 /* Uninitialized */, "Cannot modify the lexical environment during initialization."); + ts.Debug.assert(state < 2 /* Completed */, "Cannot modify the lexical environment after transformation has completed."); if (!lexicalEnvironmentFunctionDeclarations) { lexicalEnvironmentFunctionDeclarations = [func]; } @@ -63157,31 +76501,45 @@ var ts; lexicalEnvironmentFunctionDeclarations.push(func); } } + /** + * Starts a new lexical environment. Any existing hoisted variable or function declarations + * are pushed onto a stack, and the related storage variables are reset. + */ function startLexicalEnvironment() { - ts.Debug.assert(state > 0, "Cannot modify the lexical environment during initialization."); - ts.Debug.assert(state < 2, "Cannot modify the lexical environment after transformation has completed."); + ts.Debug.assert(state > 0 /* Uninitialized */, "Cannot modify the lexical environment during initialization."); + ts.Debug.assert(state < 2 /* Completed */, "Cannot modify the lexical environment after transformation has completed."); ts.Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended."); + // Save the current lexical environment. Rather than resizing the array we adjust the + // stack size variable. This allows us to reuse existing array slots we've + // already allocated between transformations to avoid allocation and GC overhead during + // transformation. lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentVariableDeclarations; lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentFunctionDeclarations; lexicalEnvironmentStackOffset++; lexicalEnvironmentVariableDeclarations = undefined; lexicalEnvironmentFunctionDeclarations = undefined; } + /** Suspends the current lexical environment, usually after visiting a parameter list. */ function suspendLexicalEnvironment() { - ts.Debug.assert(state > 0, "Cannot modify the lexical environment during initialization."); - ts.Debug.assert(state < 2, "Cannot modify the lexical environment after transformation has completed."); + ts.Debug.assert(state > 0 /* Uninitialized */, "Cannot modify the lexical environment during initialization."); + ts.Debug.assert(state < 2 /* Completed */, "Cannot modify the lexical environment after transformation has completed."); ts.Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is already suspended."); lexicalEnvironmentSuspended = true; } + /** Resumes a suspended lexical environment, usually before visiting a function body. */ function resumeLexicalEnvironment() { - ts.Debug.assert(state > 0, "Cannot modify the lexical environment during initialization."); - ts.Debug.assert(state < 2, "Cannot modify the lexical environment after transformation has completed."); + ts.Debug.assert(state > 0 /* Uninitialized */, "Cannot modify the lexical environment during initialization."); + ts.Debug.assert(state < 2 /* Completed */, "Cannot modify the lexical environment after transformation has completed."); ts.Debug.assert(lexicalEnvironmentSuspended, "Lexical environment is not suspended."); lexicalEnvironmentSuspended = false; } + /** + * Ends a lexical environment. The previous set of hoisted declarations are restored and + * any hoisted declarations added in this environment are returned. + */ function endLexicalEnvironment() { - ts.Debug.assert(state > 0, "Cannot modify the lexical environment during initialization."); - ts.Debug.assert(state < 2, "Cannot modify the lexical environment after transformation has completed."); + ts.Debug.assert(state > 0 /* Uninitialized */, "Cannot modify the lexical environment during initialization."); + ts.Debug.assert(state < 2 /* Completed */, "Cannot modify the lexical environment after transformation has completed."); ts.Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended."); var statements; if (lexicalEnvironmentVariableDeclarations || lexicalEnvironmentFunctionDeclarations) { @@ -63189,7 +76547,8 @@ var ts; statements = lexicalEnvironmentFunctionDeclarations.slice(); } if (lexicalEnvironmentVariableDeclarations) { - var statement = ts.createVariableStatement(undefined, ts.createVariableDeclarationList(lexicalEnvironmentVariableDeclarations)); + var statement = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList(lexicalEnvironmentVariableDeclarations)); if (!statements) { statements = [statement]; } @@ -63198,6 +76557,7 @@ var ts; } } } + // Restore the previous lexical environment. lexicalEnvironmentStackOffset--; lexicalEnvironmentVariableDeclarations = lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset]; lexicalEnvironmentFunctionDeclarations = lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset]; @@ -63208,24 +76568,26 @@ var ts; return statements; } function requestEmitHelper(helper) { - ts.Debug.assert(state > 0, "Cannot modify the transformation context during initialization."); - ts.Debug.assert(state < 2, "Cannot modify the transformation context after transformation has completed."); + ts.Debug.assert(state > 0 /* Uninitialized */, "Cannot modify the transformation context during initialization."); + ts.Debug.assert(state < 2 /* Completed */, "Cannot modify the transformation context after transformation has completed."); ts.Debug.assert(!helper.scoped, "Cannot request a scoped emit helper."); emitHelpers = ts.append(emitHelpers, helper); } function readEmitHelpers() { - ts.Debug.assert(state > 0, "Cannot modify the transformation context during initialization."); - ts.Debug.assert(state < 2, "Cannot modify the transformation context after transformation has completed."); + ts.Debug.assert(state > 0 /* Uninitialized */, "Cannot modify the transformation context during initialization."); + ts.Debug.assert(state < 2 /* Completed */, "Cannot modify the transformation context after transformation has completed."); var helpers = emitHelpers; emitHelpers = undefined; return helpers; } function dispose() { - if (state < 3) { + if (state < 3 /* Disposed */) { + // Clean up emit nodes on parse tree for (var _i = 0, nodes_5 = nodes; _i < nodes_5.length; _i++) { var node = nodes_5[_i]; ts.disposeEmitNodes(ts.getSourceFileOfNode(ts.getParseTreeNode(node))); } + // Release references to external entries for GC purposes. lexicalEnvironmentVariableDeclarations = undefined; lexicalEnvironmentVariableDeclarationsStack = undefined; lexicalEnvironmentFunctionDeclarations = undefined; @@ -63233,14 +76595,17 @@ var ts; onSubstituteNode = undefined; onEmitNode = undefined; emitHelpers = undefined; - state = 3; + // Prevent further use of the transformation result. + state = 3 /* Disposed */; } } } ts.transformNodes = transformNodes; })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { + // Used for initialize lastEncodedSourceMapSpan and reset lastEncodedSourceMapSpan when updateLastEncodedAndRecordedSpans var defaultLastEncodedSourceMapSpan = { emittedLine: 0, emittedColumn: 0, @@ -63253,11 +76618,14 @@ var ts; var extendedDiagnostics = compilerOptions.extendedDiagnostics; var currentSource; var currentSourceText; - var sourceMapDir; + var sourceMapDir; // The directory in which sourcemap will be + // Current source map file and its index in the sources list var sourceMapSourceIndex; + // Last recorded and encoded spans var lastRecordedSourceMapSpan; var lastEncodedSourceMapSpan; var lastEncodedNameIndex; + // Source map data var sourceMapData; var sourceMapDataList; var disabled = !(compilerOptions.sourceMap || compilerOptions.inlineSourceMap); @@ -63271,11 +76639,21 @@ var ts; getText: getText, getSourceMappingURL: getSourceMappingURL, }; + /** + * Skips trivia such as comments and white-space that can optionally overriden by the source map source + */ function skipSourceTrivia(pos) { return currentSource.skipTrivia ? currentSource.skipTrivia(pos) : ts.skipTrivia(currentSourceText, pos); } + /** + * Initialize the SourceMapWriter for a new output file. + * + * @param filePath The path to the generated output file. + * @param sourceMapFilePath The path to the output source map file. + * @param sourceFileOrBundle The input source file or bundle for the program. + */ function initialize(filePath, sourceMapFilePath, sourceFileOrBundle, outputSourceMapDataList) { - if (disabled || ts.fileExtensionIs(filePath, ".json")) { + if (disabled || ts.fileExtensionIs(filePath, ".json" /* Json */)) { return; } if (sourceMapData) { @@ -63284,10 +76662,13 @@ var ts; sourceMapDataList = outputSourceMapDataList; currentSource = undefined; currentSourceText = undefined; + // Current source map file and its index in the sources list sourceMapSourceIndex = -1; + // Last recorded and encoded spans lastRecordedSourceMapSpan = undefined; lastEncodedSourceMapSpan = defaultLastEncodedSourceMapSpan; lastEncodedNameIndex = 0; + // Initialize source map data sourceMapData = { sourceMapFilePath: sourceMapFilePath, jsSourceMappingURL: !compilerOptions.inlineSourceMap ? ts.getBaseFileName(ts.normalizeSlashes(sourceMapFilePath)) : undefined, @@ -63300,18 +76681,26 @@ var ts; sourceMapSourcesContent: compilerOptions.inlineSources ? [] : undefined, sourceMapDecodedMappings: [] }; + // Normalize source root and make sure it has trailing "/" so that it can be used to combine paths with the + // relative paths of the sources list in the sourcemap sourceMapData.sourceMapSourceRoot = ts.normalizeSlashes(sourceMapData.sourceMapSourceRoot); - if (sourceMapData.sourceMapSourceRoot.length && sourceMapData.sourceMapSourceRoot.charCodeAt(sourceMapData.sourceMapSourceRoot.length - 1) !== 47) { + if (sourceMapData.sourceMapSourceRoot.length && sourceMapData.sourceMapSourceRoot.charCodeAt(sourceMapData.sourceMapSourceRoot.length - 1) !== 47 /* slash */) { sourceMapData.sourceMapSourceRoot += ts.directorySeparator; } if (compilerOptions.mapRoot) { sourceMapDir = ts.normalizeSlashes(compilerOptions.mapRoot); - if (sourceFileOrBundle.kind === 274) { + if (sourceFileOrBundle.kind === 274 /* SourceFile */) { // emitting single module file + // For modules or multiple emit files the mapRoot will have directory structure like the sources + // So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map sourceMapDir = ts.getDirectoryPath(ts.getSourceFilePathInNewDir(sourceFileOrBundle, host, sourceMapDir)); } if (!ts.isRootedDiskPath(sourceMapDir) && !ts.isUrl(sourceMapDir)) { + // The relative paths are relative to the common directory sourceMapDir = ts.combinePaths(host.getCommonSourceDirectory(), sourceMapDir); - sourceMapData.jsSourceMappingURL = ts.getRelativePathToDirectoryOrUrl(ts.getDirectoryPath(ts.normalizePath(filePath)), ts.combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), host.getCurrentDirectory(), host.getCanonicalFileName, true); + sourceMapData.jsSourceMappingURL = ts.getRelativePathToDirectoryOrUrl(ts.getDirectoryPath(ts.normalizePath(filePath)), // get the relative sourceMapDir path based on jsFilePath + ts.combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), // this is where user expects to see sourceMap + host.getCurrentDirectory(), host.getCanonicalFileName, + /*isAbsolutePathAnUrl*/ true); } else { sourceMapData.jsSourceMappingURL = ts.combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL); @@ -63321,10 +76710,14 @@ var ts; sourceMapDir = ts.getDirectoryPath(ts.normalizePath(filePath)); } } + /** + * Reset the SourceMapWriter to an empty state. + */ function reset() { if (disabled) { return; } + // Record source map data for the test harness. if (sourceMapDataList) { sourceMapDataList.push(sourceMapData); } @@ -63348,6 +76741,7 @@ var ts; sourcesContent: sourceMapData.sourceMapSourcesContent, }; } + // Encoding for sourcemap span function encodeLastRecordedSourceMapSpan() { if (!lastRecordedSourceMapSpan || lastRecordedSourceMapSpan === lastEncodedSourceMapSpan) { return; @@ -63357,21 +76751,29 @@ var ts; ts.Debug.assert(lastRecordedSourceMapSpan.sourceLine >= 0, "lastEncodedSourceMapSpan.sourceLine was negative"); ts.Debug.assert(lastRecordedSourceMapSpan.sourceColumn >= 0, "lastEncodedSourceMapSpan.sourceColumn was negative"); var prevEncodedEmittedColumn = lastEncodedSourceMapSpan.emittedColumn; + // Line/Comma delimiters if (lastEncodedSourceMapSpan.emittedLine === lastRecordedSourceMapSpan.emittedLine) { + // Emit comma to separate the entry if (sourceMapData.sourceMapMappings) { sourceMapData.sourceMapMappings += ","; } } else { + // Emit line delimiters for (var encodedLine = lastEncodedSourceMapSpan.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) { sourceMapData.sourceMapMappings += ";"; } prevEncodedEmittedColumn = 0; } + // 1. Relative Column 0 based sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.emittedColumn - prevEncodedEmittedColumn); + // 2. Relative sourceIndex sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceIndex - lastEncodedSourceMapSpan.sourceIndex); + // 3. Relative sourceLine 0 based sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceLine - lastEncodedSourceMapSpan.sourceLine); + // 4. Relative sourceColumn 0 based sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceColumn - lastEncodedSourceMapSpan.sourceColumn); + // 5. Relative namePosition 0 based if (lastRecordedSourceMapSpan.nameIndex >= 0) { ts.Debug.assert(false, "We do not support name index right now, Make sure to update updateLastEncodedAndRecordedSpans when we start using this"); sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.nameIndex - lastEncodedNameIndex); @@ -63380,6 +76782,14 @@ var ts; lastEncodedSourceMapSpan = lastRecordedSourceMapSpan; sourceMapData.sourceMapDecodedMappings.push(lastEncodedSourceMapSpan); } + /** + * Emits a mapping. + * + * If the position is synthetic (undefined or a negative value), no mapping will be + * created. + * + * @param pos The position. + */ function emitPos(pos) { if (disabled || ts.positionIsSynthesized(pos) || isJsonSourceMapSource(currentSource)) { return; @@ -63390,13 +76800,16 @@ var ts; var sourceLinePos = ts.getLineAndCharacterOfPosition(currentSource, pos); var emittedLine = writer.getLine(); var emittedColumn = writer.getColumn(); + // If this location wasn't recorded or the location in source is going backwards, record the span if (!lastRecordedSourceMapSpan || lastRecordedSourceMapSpan.emittedLine !== emittedLine || lastRecordedSourceMapSpan.emittedColumn !== emittedColumn || (lastRecordedSourceMapSpan.sourceIndex === sourceMapSourceIndex && (lastRecordedSourceMapSpan.sourceLine > sourceLinePos.line || (lastRecordedSourceMapSpan.sourceLine === sourceLinePos.line && lastRecordedSourceMapSpan.sourceColumn > sourceLinePos.character)))) { + // Encode the last recordedSpan before assigning new encodeLastRecordedSourceMapSpan(); + // New span lastRecordedSourceMapSpan = { emittedLine: emittedLine, emittedColumn: emittedColumn, @@ -63406,6 +76819,7 @@ var ts; }; } else { + // Take the new pos instead since there is no change in emittedLine and column since last location lastRecordedSourceMapSpan.sourceLine = sourceLinePos.line; lastRecordedSourceMapSpan.sourceColumn = sourceLinePos.character; lastRecordedSourceMapSpan.sourceIndex = sourceMapSourceIndex; @@ -63418,6 +76832,13 @@ var ts; function isPossiblySourceMap(x) { return typeof x === "object" && !!x.mappings && typeof x.mappings === "string" && !!x.sources; } + /** + * Emits a node with possible leading and trailing source maps. + * + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emitCallback The callback used to emit the node. + */ function emitNodeWithSourceMap(hint, node, emitCallback) { if (disabled || ts.isInJsonFile(node)) { return emitCallback(hint, node); @@ -63430,29 +76851,40 @@ var ts; parsed = JSON.parse(text); } catch (_a) { + // empty } if (!parsed || !isPossiblySourceMap(parsed)) { return emitCallback(hint, node); } var offsetLine_1 = writer.getLine(); var firstLineColumnOffset_1 = writer.getColumn(); + // First, decode the old component sourcemap var originalMap_1 = parsed; + var sourcesDirectoryPath_1 = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir; + var resolvedPathCache_1 = ts.createMap(); ts.sourcemaps.calculateDecodedMappings(originalMap_1, function (raw) { + // Apply offsets to each position and fixup source entries var rawPath = originalMap_1.sources[raw.sourceIndex]; var relativePath = originalMap_1.sourceRoot ? ts.combinePaths(originalMap_1.sourceRoot, rawPath) : rawPath; var combinedPath = ts.combinePaths(ts.getDirectoryPath(node.sourceMapPath), relativePath); - var sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir; - var resolvedPath = ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, combinedPath, host.getCurrentDirectory(), host.getCanonicalFileName, true); - var absolutePath = ts.getNormalizedAbsolutePath(resolvedPath, sourcesDirectoryPath); - setupSourceEntry(absolutePath, originalMap_1.sourcesContent ? originalMap_1.sourcesContent[raw.sourceIndex] : null); + if (!resolvedPathCache_1.has(combinedPath)) { + resolvedPathCache_1.set(combinedPath, ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath_1, combinedPath, host.getCurrentDirectory(), host.getCanonicalFileName, + /*isAbsolutePathAnUrl*/ true)); + } + var resolvedPath = resolvedPathCache_1.get(combinedPath); + var absolutePath = ts.getNormalizedAbsolutePath(resolvedPath, sourcesDirectoryPath_1); + // tslint:disable-next-line:no-null-keyword + setupSourceEntry(absolutePath, originalMap_1.sourcesContent ? originalMap_1.sourcesContent[raw.sourceIndex] : null); // TODO: Lookup content for inlining? var newIndex = sourceMapData.sourceMapSources.indexOf(resolvedPath); + // Then reencode all the updated spans into the overall map encodeLastRecordedSourceMapSpan(); lastRecordedSourceMapSpan = __assign({}, raw, { emittedLine: raw.emittedLine + offsetLine_1, emittedColumn: raw.emittedLine === 0 ? (raw.emittedColumn + firstLineColumnOffset_1) : raw.emittedColumn, sourceIndex: newIndex }); }); + // And actually emit the text these sourcemaps are for return emitCallback(hint, node); } var emitNode = node.emitNode; - var emitFlags = emitNode && emitNode.flags || 0; + var emitFlags = emitNode && emitNode.flags || 0 /* None */; var range = emitNode && emitNode.sourceMapRange; var _b = range || node, pos = _b.pos, end = _b.end; var source = range && range.source; @@ -63461,14 +76893,14 @@ var ts; source = undefined; if (source) setSourceFile(source); - if (node.kind !== 301 - && (emitFlags & 16) === 0 + if (node.kind !== 301 /* NotEmittedStatement */ + && (emitFlags & 16 /* NoLeadingSourceMap */) === 0 && pos >= 0) { emitPos(skipSourceTrivia(pos)); } if (source) setSourceFile(oldSource); - if (emitFlags & 64) { + if (emitFlags & 64 /* NoNestedSourceMaps */) { disabled = true; emitCallback(hint, node); disabled = false; @@ -63478,8 +76910,8 @@ var ts; } if (source) setSourceFile(source); - if (node.kind !== 301 - && (emitFlags & 32) === 0 + if (node.kind !== 301 /* NotEmittedStatement */ + && (emitFlags & 32 /* NoTrailingSourceMap */) === 0 && end >= 0) { emitPos(end); } @@ -63487,28 +76919,41 @@ var ts; setSourceFile(oldSource); } } + /** + * Emits a token of a node with possible leading and trailing source maps. + * + * @param node The node containing the token. + * @param token The token to emit. + * @param tokenStartPos The start pos of the token. + * @param emitCallback The callback used to emit the token. + */ function emitTokenWithSourceMap(node, token, writer, tokenPos, emitCallback) { if (disabled || ts.isInJsonFile(node)) { return emitCallback(token, writer, tokenPos); } var emitNode = node && node.emitNode; - var emitFlags = emitNode && emitNode.flags || 0; + var emitFlags = emitNode && emitNode.flags || 0 /* None */; var range = emitNode && emitNode.tokenSourceMapRanges && emitNode.tokenSourceMapRanges[token]; tokenPos = skipSourceTrivia(range ? range.pos : tokenPos); - if ((emitFlags & 128) === 0 && tokenPos >= 0) { + if ((emitFlags & 128 /* NoTokenLeadingSourceMaps */) === 0 && tokenPos >= 0) { emitPos(tokenPos); } tokenPos = emitCallback(token, writer, tokenPos); if (range) tokenPos = range.end; - if ((emitFlags & 256) === 0 && tokenPos >= 0) { + if ((emitFlags & 256 /* NoTokenTrailingSourceMaps */) === 0 && tokenPos >= 0) { emitPos(tokenPos); } return tokenPos; } function isJsonSourceMapSource(sourceFile) { - return ts.fileExtensionIs(sourceFile.fileName, ".json"); + return ts.fileExtensionIs(sourceFile.fileName, ".json" /* Json */); } + /** + * Set the current source file. + * + * @param sourceFile The source file. + */ function setSourceFile(sourceFile) { if (disabled) { return; @@ -63521,30 +76966,42 @@ var ts; setupSourceEntry(sourceFile.fileName, sourceFile.text); } function setupSourceEntry(fileName, content) { + // Add the file to tsFilePaths + // If sourceroot option: Use the relative path corresponding to the common directory path + // otherwise source locations relative to map file location var sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir; - var source = ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, fileName, host.getCurrentDirectory(), host.getCanonicalFileName, true); + var source = ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, fileName, host.getCurrentDirectory(), host.getCanonicalFileName, + /*isAbsolutePathAnUrl*/ true); sourceMapSourceIndex = sourceMapData.sourceMapSources.indexOf(source); if (sourceMapSourceIndex === -1) { sourceMapSourceIndex = sourceMapData.sourceMapSources.length; sourceMapData.sourceMapSources.push(source); + // The one that can be used from program to get the actual source file sourceMapData.inputSourceFileNames.push(fileName); if (compilerOptions.inlineSources) { sourceMapData.sourceMapSourcesContent.push(content); } } } + /** + * Gets the text for the source map. + */ function getText() { if (disabled || isJsonSourceMapSource(currentSource)) { - return undefined; + return undefined; // TODO: GH#18217 } encodeLastRecordedSourceMapSpan(); return JSON.stringify(captureSection()); } + /** + * Gets the SourceMappingURL for the source map. + */ function getSourceMappingURL() { if (disabled || isJsonSourceMapSource(currentSource)) { - return undefined; + return undefined; // TODO: GH#18217 } if (compilerOptions.inlineSourceMap) { + // Encode the sourceMap into the sourceMap url var base64SourceMapText = ts.base64encode(ts.sys, getText()); return sourceMapData.jsSourceMappingURL = "data:application/json;base64," + base64SourceMapText; } @@ -63562,17 +77019,24 @@ var ts; throw TypeError(inValue + ": not a 64 based value"); } function base64VLQFormatEncode(inValue) { + // Add a new least significant bit that has the sign of the value. + // if negative number the least significant bit that gets added to the number has value 1 + // else least significant bit value that gets added is 0 + // eg. -1 changes to binary : 01 [1] => 3 + // +1 changes to binary : 01 [0] => 2 if (inValue < 0) { inValue = ((-inValue) << 1) + 1; } else { inValue = inValue << 1; } + // Encode 5 bits at a time starting from least significant bits var encodedStr = ""; do { - var currentDigit = inValue & 31; + var currentDigit = inValue & 31; // 11111 inValue = inValue >> 5; if (inValue > 0) { + // There are still more digits to decode, set the msb (6th bit) currentDigit = currentDigit | 32; } encodedStr = encodedStr + base64FormatEncode(currentDigit); @@ -63580,6 +77044,7 @@ var ts; return encodedStr; } })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { function createCommentWriter(printerOptions, emitPos) { @@ -63615,18 +77080,24 @@ var ts; var emitFlags = emitNode && emitNode.flags || 0; var _a = emitNode && emitNode.commentRange || node, pos = _a.pos, end = _a.end; if ((pos < 0 && end < 0) || (pos === end)) { + // Both pos and end are synthesized, so just emit the node without comments. emitNodeWithSynthesizedComments(hint, node, emitNode, emitFlags, emitCallback); } else { if (extendedDiagnostics) { ts.performance.mark("preEmitNodeWithComment"); } - var isEmittedNode = node.kind !== 301; - var skipLeadingComments = pos < 0 || (emitFlags & 512) !== 0 || node.kind === 10; - var skipTrailingComments = end < 0 || (emitFlags & 1024) !== 0 || node.kind === 10; + var isEmittedNode = node.kind !== 301 /* NotEmittedStatement */; + // We have to explicitly check that the node is JsxText because if the compilerOptions.jsx is "preserve" we will not do any transformation. + // It is expensive to walk entire tree just to set one kind of node to have no comments. + var skipLeadingComments = pos < 0 || (emitFlags & 512 /* NoLeadingComments */) !== 0 || node.kind === 10 /* JsxText */; + var skipTrailingComments = end < 0 || (emitFlags & 1024 /* NoTrailingComments */) !== 0 || node.kind === 10 /* JsxText */; + // Emit leading comments if the position is not synthesized and the node + // has not opted out from emitting leading comments. if (!skipLeadingComments) { emitLeadingComments(pos, isEmittedNode); } + // Save current container state on the stack. var savedContainerPos = containerPos; var savedContainerEnd = containerEnd; var savedDeclarationListContainerEnd = declarationListContainerEnd; @@ -63635,7 +77106,9 @@ var ts; } if (!skipTrailingComments) { containerEnd = end; - if (node.kind === 233) { + // To avoid invalid comment emit in a down-level binding pattern, we + // keep track of the last declaration list container's end + if (node.kind === 233 /* VariableDeclarationList */) { declarationListContainerEnd = end; } } @@ -63646,9 +77119,12 @@ var ts; if (extendedDiagnostics) { ts.performance.mark("postEmitNodeWithComment"); } + // Restore previous container state. containerPos = savedContainerPos; containerEnd = savedContainerEnd; declarationListContainerEnd = savedDeclarationListContainerEnd; + // Emit trailing comments if the position is not synthesized and the node + // has not opted out from emitting leading comments and is an emitted node. if (!skipTrailingComments && isEmittedNode) { emitTrailingComments(end); } @@ -63682,11 +77158,11 @@ var ts; } } function emitLeadingSynthesizedComment(comment) { - if (comment.kind === 2) { + if (comment.kind === 2 /* SingleLineCommentTrivia */) { writer.writeLine(); } writeSynthesizedComment(comment); - if (comment.hasTrailingNewLine || comment.kind === 2) { + if (comment.hasTrailingNewLine || comment.kind === 2 /* SingleLineCommentTrivia */) { writer.writeLine(); } else { @@ -63704,16 +77180,16 @@ var ts; } function writeSynthesizedComment(comment) { var text = formatSynthesizedComment(comment); - var lineMap = comment.kind === 3 ? ts.computeLineStarts(text) : undefined; + var lineMap = comment.kind === 3 /* MultiLineCommentTrivia */ ? ts.computeLineStarts(text) : undefined; ts.writeCommentRange(text, lineMap, writer, 0, text.length, newLine); } function formatSynthesizedComment(comment) { - return comment.kind === 3 + return comment.kind === 3 /* MultiLineCommentTrivia */ ? "/*" + comment.text + "*/" : "//" + comment.text; } function emitNodeWithNestedComments(hint, node, emitFlags, emitCallback) { - if (emitFlags & 2048) { + if (emitFlags & 2048 /* NoNestedComments */) { disabled = true; emitCallback(hint, node); disabled = false; @@ -63728,15 +77204,15 @@ var ts; } var pos = detachedRange.pos, end = detachedRange.end; var emitFlags = ts.getEmitFlags(node); - var skipLeadingComments = pos < 0 || (emitFlags & 512) !== 0; - var skipTrailingComments = disabled || end < 0 || (emitFlags & 1024) !== 0; + var skipLeadingComments = pos < 0 || (emitFlags & 512 /* NoLeadingComments */) !== 0; + var skipTrailingComments = disabled || end < 0 || (emitFlags & 1024 /* NoTrailingComments */) !== 0; if (!skipLeadingComments) { emitDetachedCommentsAndUpdateCommentsInfo(detachedRange); } if (extendedDiagnostics) { ts.performance.measure("commentTime", "preEmitBodyWithDetachedComments"); } - if (emitFlags & 2048 && !disabled) { + if (emitFlags & 2048 /* NoNestedComments */ && !disabled) { disabled = true; emitCallback(node); disabled = false; @@ -63748,7 +77224,7 @@ var ts; ts.performance.mark("beginEmitBodyWithDetachedCommetns"); } if (!skipTrailingComments) { - emitLeadingComments(detachedRange.end, true); + emitLeadingComments(detachedRange.end, /*isEmittedNode*/ true); if (hasWrittenComment && !writer.isAtStartOfLine()) { writer.writeLine(); } @@ -63763,6 +77239,14 @@ var ts; forEachLeadingCommentToEmit(pos, emitLeadingComment); } else if (pos === 0) { + // If the node will not be emitted in JS, remove all the comments(normal, pinned and ///) associated with the node, + // unless it is a triple slash comment at the top of the file. + // For Example: + // /// + // declare var x; + // /// + // interface F {} + // The first /// will NOT be removed while the second one will be removed even though both node will not be emitted forEachLeadingCommentToEmit(pos, emitTripleSlashLeadingComment); } } @@ -63784,6 +77268,7 @@ var ts; ts.emitNewLineBeforeLeadingCommentOfPosition(currentLineMap, writer, rangePos, commentPos); hasWrittenComment = true; } + // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space if (emitPos) emitPos(commentPos); ts.writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine); @@ -63792,7 +77277,7 @@ var ts; if (hasTrailingNewLine) { writer.writeLine(); } - else if (kind === 3) { + else if (kind === 3 /* MultiLineCommentTrivia */) { writer.write(" "); } } @@ -63800,7 +77285,7 @@ var ts; if (disabled || pos === -1) { return; } - emitLeadingComments(pos, true); + emitLeadingComments(pos, /*isEmittedNode*/ true); } function emitTrailingComments(pos) { forEachTrailingCommentToEmit(pos, emitTrailingComment); @@ -63808,6 +77293,7 @@ var ts; function emitTrailingComment(commentPos, commentEnd, _kind, hasTrailingNewLine) { if (!shouldWriteComment(currentText, commentPos)) return; + // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment2*/ if (!writer.isAtStartOfLine()) { writer.write(" "); } @@ -63833,6 +77319,7 @@ var ts; } } function emitTrailingCommentOfPosition(commentPos, commentEnd, _kind, hasTrailingNewLine) { + // trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space if (emitPos) emitPos(commentPos); ts.writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine); @@ -63846,16 +77333,18 @@ var ts; } } function forEachLeadingCommentToEmit(pos, cb) { + // Emit the leading comments only if the container's pos doesn't match because the container should take care of emitting these comments if (containerPos === -1 || pos !== containerPos) { if (hasDetachedComments(pos)) { forEachLeadingCommentWithoutDetachedComments(cb); } else { - ts.forEachLeadingCommentRange(currentText, pos, cb, pos); + ts.forEachLeadingCommentRange(currentText, pos, cb, /*state*/ pos); } } } function forEachTrailingCommentToEmit(end, cb) { + // Emit the trailing comments only if the container's end doesn't match because the container should take care of emitting these comments if (containerEnd === -1 || (end !== containerEnd && end !== declarationListContainerEnd)) { ts.forEachTrailingCommentRange(currentText, end, cb); } @@ -63879,6 +77368,7 @@ var ts; return detachedCommentsInfo !== undefined && ts.last(detachedCommentsInfo).nodePos === pos; } function forEachLeadingCommentWithoutDetachedComments(cb) { + // get the leading comments from detachedPos var pos = ts.last(detachedCommentsInfo).detachedCommentEndPos; if (detachedCommentsInfo.length - 1) { detachedCommentsInfo.pop(); @@ -63886,7 +77376,7 @@ var ts; else { detachedCommentsInfo = undefined; } - ts.forEachLeadingCommentRange(currentText, pos, cb, pos); + ts.forEachLeadingCommentRange(currentText, pos, cb, /*state*/ pos); } function emitDetachedCommentsAndUpdateCommentsInfo(range) { var currentDetachedCommentInfo = ts.emitDetachedComments(currentText, currentLineMap, writer, writeComment, range, newLine, disabled); @@ -63908,6 +77398,11 @@ var ts; if (emitPos) emitPos(commentEnd); } + /** + * Determine if the given comment is a triple-slash + * + * @return true if the comment is a triple-slash comment else false + */ function isTripleSlashComment(commentPos, commentEnd) { return ts.isRecognizedTripleSlashComment(currentText, commentPos, commentEnd); } @@ -63918,6 +77413,16 @@ var ts; (function (ts) { var infoExtension = ".tsbundleinfo"; var brackets = createBracketsMap(); + /*@internal*/ + /** + * Iterates over the source files that are expected to have an emit output. + * + * @param host An EmitHost. + * @param action The action to execute. + * @param sourceFilesOrTargetSourceFile + * If an array, the full list of source files to emit. + * Else, calls `getSourceFilesToEmit` with the (optional) target source file to determine the list of source files to emit. + */ function forEachEmittedFile(host, action, sourceFilesOrTargetSourceFile, emitOnlyDtsFiles) { if (emitOnlyDtsFiles === void 0) { emitOnlyDtsFiles = false; } var sourceFiles = ts.isArray(sourceFilesOrTargetSourceFile) ? sourceFilesOrTargetSourceFile : ts.getSourceFilesToEmit(host, sourceFilesOrTargetSourceFile); @@ -63942,12 +77447,13 @@ var ts; } } ts.forEachEmittedFile = forEachEmittedFile; + /*@internal*/ function getOutputPathsFor(sourceFile, host, forceDtsPaths) { var options = host.getCompilerOptions(); - if (sourceFile.kind === 275) { + if (sourceFile.kind === 275 /* Bundle */) { var jsFilePath = options.outFile || options.out; var sourceMapFilePath = getSourceMapFilePath(jsFilePath, options); - var declarationFilePath = (forceDtsPaths || options.declaration) ? ts.removeFileExtension(jsFilePath) + ".d.ts" : undefined; + var declarationFilePath = (forceDtsPaths || options.declaration) ? ts.removeFileExtension(jsFilePath) + ".d.ts" /* Dts */ : undefined; var declarationMapPath = ts.getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined; var bundleInfoPath = options.references && jsFilePath ? (ts.removeFileExtension(jsFilePath) + infoExtension) : undefined; return { jsFilePath: jsFilePath, sourceMapFilePath: sourceMapFilePath, declarationFilePath: declarationFilePath, declarationMapPath: declarationMapPath, bundleInfoPath: bundleInfoPath }; @@ -63955,6 +77461,7 @@ var ts; else { var jsFilePath = ts.getOwnEmitOutputFilePath(sourceFile, host, getOutputExtension(sourceFile, options)); var sourceMapFilePath = ts.isJsonSourceFile(sourceFile) ? undefined : getSourceMapFilePath(jsFilePath, options); + // For legacy reasons (ie, we have baselines capturing the behavior), js files don't report a .d.ts output path - this would only matter if `declaration` and `allowJs` were both on, which is currently an error var isJs = ts.isSourceFileJavaScript(sourceFile); var declarationFilePath = ((forceDtsPaths || options.declaration) && !isJs) ? ts.getDeclarationEmitOutputFilePath(sourceFile, host) : undefined; var declarationMapPath = ts.getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined; @@ -63971,23 +77478,30 @@ var ts; totalLength: -1 }; } + // JavaScript files are always LanguageVariant.JSX, as JSX syntax is allowed in .js files also. + // So for JavaScript files, '.jsx' is only emitted if the input was '.jsx', and JsxEmit.Preserve. + // For TypeScript, the only time to emit with a '.jsx' extension, is on JSX input, and JsxEmit.Preserve + /* @internal */ function getOutputExtension(sourceFile, options) { if (ts.isJsonSourceFile(sourceFile)) { - return ".json"; + return ".json" /* Json */; } - if (options.jsx === 1) { + if (options.jsx === 1 /* Preserve */) { if (ts.isSourceFileJavaScript(sourceFile)) { - if (ts.fileExtensionIs(sourceFile.fileName, ".jsx")) { - return ".jsx"; + if (ts.fileExtensionIs(sourceFile.fileName, ".jsx" /* Jsx */)) { + return ".jsx" /* Jsx */; } } - else if (sourceFile.languageVariant === 1) { - return ".jsx"; + else if (sourceFile.languageVariant === 1 /* JSX */) { + // TypeScript source file preserving JSX syntax + return ".jsx" /* Jsx */; } } - return ".js"; + return ".js" /* Js */; } ts.getOutputExtension = getOutputExtension; + /*@internal*/ + // targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature function emitFiles(resolver, host, targetSourceFile, emitOnlyDtsFiles, transformers, declarationTransformers) { var compilerOptions = host.getCompilerOptions(); var sourceMapDataList = (compilerOptions.sourceMap || compilerOptions.inlineSourceMap || ts.getAreDeclarationMapsEnabled(compilerOptions)) ? [] : undefined; @@ -64004,6 +77518,7 @@ var ts; }); var bundleInfo = createDefaultBundleInfo(); var emitSkipped = false; + // Emit each output file ts.performance.mark("beforePrint"); forEachEmittedFile(host, emitSourceFileOrBundle, ts.getSourceFilesToEmit(host, targetSourceFile), emitOnlyDtsFiles); ts.performance.measure("printTime", "beforePrint"); @@ -64033,6 +77548,7 @@ var ts; } } function emitJsFileOrBundle(sourceFileOrBundle, jsFilePath, sourceMapFilePath, bundleInfoPath) { + // Make sure not to write js file and source map file if any of them cannot be written if (host.isEmitBlocked(jsFilePath) || compilerOptions.noEmit || compilerOptions.emitDeclarationOnly) { emitSkipped = true; return; @@ -64040,18 +77556,25 @@ var ts; if (emitOnlyDtsFiles) { return; } - var transform = ts.transformNodes(resolver, host, compilerOptions, [sourceFileOrBundle], transformers, false); + // Transform the source files + var transform = ts.transformNodes(resolver, host, compilerOptions, [sourceFileOrBundle], transformers, /*allowDtsFiles*/ false); + // Create a printer to print the nodes var printer = createPrinter(__assign({}, compilerOptions, { noEmitHelpers: compilerOptions.noEmitHelpers }), { + // resolver hooks hasGlobalName: resolver.hasGlobalName, + // transform hooks onEmitNode: transform.emitNodeWithNotification, substituteNode: transform.substituteNode, + // sourcemap hooks onEmitSourceMapOfNode: sourceMap.emitNodeWithSourceMap, onEmitSourceMapOfToken: sourceMap.emitTokenWithSourceMap, onEmitSourceMapOfPosition: sourceMap.emitPos, + // emitter hooks onSetSourceFile: setSourceFile, }); ts.Debug.assert(transform.transformed.length === 1, "Should only see one output from the transform"); printSourceFileOrBundle(jsFilePath, sourceMapFilePath, transform.transformed[0], bundleInfoPath, printer, sourceMap); + // Clean up emit nodes on parse tree transform.dispose(); } function emitDeclarationFileOrBundle(sourceFileOrBundle, declarationFilePath, declarationMapPath) { @@ -64059,9 +77582,10 @@ var ts; return; } var sourceFiles = ts.isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : sourceFileOrBundle.sourceFiles; + // Setup and perform the transformation to retrieve declarations from the input files var nonJsFiles = ts.filter(sourceFiles, ts.isSourceFileNotJavaScript); var inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [ts.createBundle(nonJsFiles, !ts.isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : nonJsFiles; - var declarationTransform = ts.transformNodes(resolver, host, compilerOptions, inputListOrBundle, ts.concatenate([ts.transformDeclarations], declarationTransformers), false); + var declarationTransform = ts.transformNodes(resolver, host, compilerOptions, inputListOrBundle, ts.concatenate([ts.transformDeclarations], declarationTransformers), /*allowDtsFiles*/ false); if (ts.length(declarationTransform.diagnostics)) { for (var _a = 0, _b = declarationTransform.diagnostics; _a < _b.length; _a++) { var diagnostic = _b[_a]; @@ -64069,11 +77593,14 @@ var ts; } } var declarationPrinter = createPrinter(__assign({}, compilerOptions, { onlyPrintJsDocStyle: true, noEmitHelpers: true }), { + // resolver hooks hasGlobalName: resolver.hasGlobalName, + // sourcemap hooks onEmitSourceMapOfNode: declarationSourceMap.emitNodeWithSourceMap, onEmitSourceMapOfToken: declarationSourceMap.emitTokenWithSourceMap, onEmitSourceMapOfPosition: declarationSourceMap.emitPos, onSetSourceFile: setSourceFileForDeclarationSourceMaps, + // transform hooks onEmitNode: declarationTransform.emitNodeWithNotification, substituteNode: declarationTransform.substituteNode, }); @@ -64081,13 +77608,13 @@ var ts; emitSkipped = emitSkipped || declBlocked; if (!declBlocked || emitOnlyDtsFiles) { ts.Debug.assert(declarationTransform.transformed.length === 1, "Should only see one output from the decl transform"); - printSourceFileOrBundle(declarationFilePath, declarationMapPath, declarationTransform.transformed[0], undefined, declarationPrinter, declarationSourceMap); + printSourceFileOrBundle(declarationFilePath, declarationMapPath, declarationTransform.transformed[0], /* bundleInfopath*/ undefined, declarationPrinter, declarationSourceMap); } declarationTransform.dispose(); } function printSourceFileOrBundle(jsFilePath, sourceMapFilePath, sourceFileOrBundle, bundleInfoPath, printer, mapRecorder) { - var bundle = sourceFileOrBundle.kind === 275 ? sourceFileOrBundle : undefined; - var sourceFile = sourceFileOrBundle.kind === 274 ? sourceFileOrBundle : undefined; + var bundle = sourceFileOrBundle.kind === 275 /* Bundle */ ? sourceFileOrBundle : undefined; + var sourceFile = sourceFileOrBundle.kind === 274 /* SourceFile */ ? sourceFileOrBundle : undefined; var sourceFiles = bundle ? bundle.sourceFiles : [sourceFile]; mapRecorder.initialize(jsFilePath, sourceMapFilePath || "", sourceFileOrBundle, sourceMapDataList); if (bundle) { @@ -64099,16 +77626,20 @@ var ts; writer.writeLine(); var sourceMappingURL = mapRecorder.getSourceMappingURL(); if (sourceMappingURL) { - writer.write("//# " + "sourceMappingURL" + "=" + sourceMappingURL); + writer.write("//# " + "sourceMappingURL" + "=" + sourceMappingURL); // Sometimes tools can sometimes see this line as a source mapping url comment } + // Write the source map if (sourceMapFilePath) { - ts.writeFile(host, emitterDiagnostics, sourceMapFilePath, mapRecorder.getText(), false, sourceFiles); + ts.writeFile(host, emitterDiagnostics, sourceMapFilePath, mapRecorder.getText(), /*writeByteOrderMark*/ false, sourceFiles); } + // Write the output file ts.writeFile(host, emitterDiagnostics, jsFilePath, writer.getText(), !!compilerOptions.emitBOM, sourceFiles); + // Write bundled offset information if applicable if (bundleInfoPath) { bundleInfo.totalLength = writer.getTextPos(); - ts.writeFile(host, emitterDiagnostics, bundleInfoPath, JSON.stringify(bundleInfo, undefined, 2), false); + ts.writeFile(host, emitterDiagnostics, bundleInfoPath, JSON.stringify(bundleInfo, undefined, 2), /*writeByteOrderMark*/ false); } + // Reset state mapRecorder.reset(); writer.clear(); bundleInfo = createDefaultBundleInfo(); @@ -64136,13 +77667,13 @@ var ts; var comments = ts.createCommentWriter(printerOptions, onEmitSourceMapOfPosition); var emitNodeWithComments = comments.emitNodeWithComments, emitBodyWithDetachedComments = comments.emitBodyWithDetachedComments, emitTrailingCommentsOfPosition = comments.emitTrailingCommentsOfPosition, emitLeadingCommentsOfPosition = comments.emitLeadingCommentsOfPosition; var currentSourceFile; - var nodeIdToGeneratedName; - var autoGeneratedIdToGeneratedName; - var generatedNames; - var tempFlagsStack; - var tempFlags; - var reservedNamesStack; - var reservedNames; + var nodeIdToGeneratedName; // Map of generated names for specific nodes. + var autoGeneratedIdToGeneratedName; // Map of generated names for temp and loop variables. + var generatedNames; // Set of names generated by the NameGenerator. + var tempFlagsStack; // Stack of enclosing name generation scopes. + var tempFlags; // TempFlags for the current name generation scope. + var reservedNamesStack; // Stack of TempFlags reserved in enclosing name generation scopes. + var reservedNames; // TempFlags to reserve in nested name generation scopes. var writer; var ownWriter; var write = writeBase; @@ -64159,10 +77690,12 @@ var ts; var isOwnFileEmit; reset(); return { + // public API printNode: printNode, printList: printList, printFile: printFile, printBundle: printBundle, + // internal API writeNode: writeNode, writeList: writeList, writeFile: writeFile, @@ -64170,20 +77703,20 @@ var ts; }; function printNode(hint, node, sourceFile) { switch (hint) { - case 0: + case 0 /* SourceFile */: ts.Debug.assert(ts.isSourceFile(node), "Expected a SourceFile node."); break; - case 2: + case 2 /* IdentifierName */: ts.Debug.assert(ts.isIdentifier(node), "Expected an Identifier node."); break; - case 1: + case 1 /* Expression */: ts.Debug.assert(ts.isExpression(node), "Expected an Expression node."); break; } switch (node.kind) { - case 274: return printFile(node); - case 275: return printBundle(node); - case 276: return printUnparsedSource(node); + case 274 /* SourceFile */: return printFile(node); + case 275 /* Bundle */: return printBundle(node); + case 276 /* UnparsedSource */: return printUnparsedSource(node); } writeNode(hint, node, sourceFile, beginPrint()); return endPrint(); @@ -64231,7 +77764,7 @@ var ts; emitSyntheticTripleSlashReferencesIfNeeded(bundle); for (var _a = 0, _b = bundle.prepends; _a < _b.length; _a++) { var prepend = _b[_a]; - print(4, prepend, undefined); + print(4 /* Unspecified */, prepend, /*sourceFile*/ undefined); writeLine(); } if (bundleInfo) { @@ -64239,7 +77772,7 @@ var ts; } for (var _c = 0, _d = bundle.sourceFiles; _c < _d.length; _c++) { var sourceFile = _d[_c]; - print(0, sourceFile, sourceFile); + print(0 /* SourceFile */, sourceFile, sourceFile); } reset(); writer = previousWriter; @@ -64247,7 +77780,7 @@ var ts; function writeUnparsedSource(unparsed, output) { var previousWriter = writer; setWriter(output); - print(4, unparsed, undefined); + print(4 /* Unspecified */, unparsed, /*sourceFile*/ undefined); reset(); writer = previousWriter; } @@ -64257,7 +77790,7 @@ var ts; setWriter(output); emitShebangIfNeeded(sourceFile); emitPrologueDirectivesIfNeeded(sourceFile); - print(0, sourceFile, sourceFile); + print(0 /* SourceFile */, sourceFile, sourceFile); reset(); writer = previousWriter; } @@ -64273,7 +77806,7 @@ var ts; if (sourceFile) { setSourceFile(sourceFile); } - var pipelinePhase = getPipelinePhase(0, hint); + var pipelinePhase = getPipelinePhase(0 /* Notification */, hint); pipelinePhase(hint, node); } function setSourceFile(sourceFile) { @@ -64284,7 +77817,7 @@ var ts; } } function setWriter(output) { - writer = output; + writer = output; // TODO: GH#18217 comments.setWriter(output); } function reset() { @@ -64292,45 +77825,47 @@ var ts; autoGeneratedIdToGeneratedName = []; generatedNames = ts.createMap(); tempFlagsStack = []; - tempFlags = 0; + tempFlags = 0 /* Auto */; reservedNamesStack = []; comments.reset(); - setWriter(undefined); + setWriter(/*output*/ undefined); } function emit(node) { if (!node) return; - var pipelinePhase = getPipelinePhase(0, 4); - pipelinePhase(4, node); + var pipelinePhase = getPipelinePhase(0 /* Notification */, 4 /* Unspecified */); + pipelinePhase(4 /* Unspecified */, node); } function emitIdentifierName(node) { if (!node) return; - var pipelinePhase = getPipelinePhase(0, 2); - pipelinePhase(2, node); + var pipelinePhase = getPipelinePhase(0 /* Notification */, 2 /* IdentifierName */); + pipelinePhase(2 /* IdentifierName */, node); } function emitExpression(node) { if (!node) return; - var pipelinePhase = getPipelinePhase(0, 1); - pipelinePhase(1, node); + var pipelinePhase = getPipelinePhase(0 /* Notification */, 1 /* Expression */); + pipelinePhase(1 /* Expression */, node); } function getPipelinePhase(phase, hint) { switch (phase) { - case 0: + case 0 /* Notification */: if (onEmitNode) { return pipelineEmitWithNotification; } - case 1: - if (emitNodeWithComments && hint !== 0) { + // falls through + case 1 /* Comments */: + if (emitNodeWithComments && hint !== 0 /* SourceFile */) { return pipelineEmitWithComments; } return pipelineEmitWithoutComments; - case 2: - if (onEmitSourceMapOfNode && hint !== 0 && hint !== 2) { + case 2 /* SourceMaps */: + if (onEmitSourceMapOfNode && hint !== 0 /* SourceFile */ && hint !== 2 /* IdentifierName */) { return pipelineEmitWithSourceMap; } - case 3: + // falls through + case 3 /* Emit */: return pipelineEmitWithHint; default: return ts.Debug.assertNever(phase, "Unexpected value for PipelinePhase: " + phase); @@ -64340,341 +77875,365 @@ var ts; return getPipelinePhase(currentPhase + 1, hint); } function pipelineEmitWithNotification(hint, node) { - ts.Debug.assertDefined(onEmitNode)(hint, node, getNextPipelinePhase(0, hint)); + ts.Debug.assertDefined(onEmitNode)(hint, node, getNextPipelinePhase(0 /* Notification */, hint)); } function pipelineEmitWithComments(hint, node) { ts.Debug.assertDefined(emitNodeWithComments); - ts.Debug.assert(hint !== 0); - emitNodeWithComments(hint, trySubstituteNode(hint, node), getNextPipelinePhase(1, hint)); + ts.Debug.assert(hint !== 0 /* SourceFile */); + emitNodeWithComments(hint, trySubstituteNode(hint, node), getNextPipelinePhase(1 /* Comments */, hint)); } function pipelineEmitWithoutComments(hint, node) { - var pipelinePhase = getNextPipelinePhase(1, hint); + var pipelinePhase = getNextPipelinePhase(1 /* Comments */, hint); pipelinePhase(hint, trySubstituteNode(hint, node)); } function pipelineEmitWithSourceMap(hint, node) { - ts.Debug.assert(hint !== 0 && hint !== 2); + ts.Debug.assert(hint !== 0 /* SourceFile */ && hint !== 2 /* IdentifierName */); ts.Debug.assertDefined(onEmitSourceMapOfNode)(hint, node, pipelineEmitWithHint); } function pipelineEmitWithHint(hint, node) { - if (hint === 0) + if (hint === 0 /* SourceFile */) return emitSourceFile(ts.cast(node, ts.isSourceFile)); - if (hint === 2) + if (hint === 2 /* IdentifierName */) return emitIdentifier(ts.cast(node, ts.isIdentifier)); - if (hint === 3) + if (hint === 3 /* MappedTypeParameter */) return emitMappedTypeParameter(ts.cast(node, ts.isTypeParameterDeclaration)); - if (hint === 4) { + if (hint === 4 /* Unspecified */) { if (ts.isKeyword(node.kind)) return writeTokenNode(node, writeKeyword); switch (node.kind) { - case 14: - case 15: - case 16: + // Pseudo-literals + case 14 /* TemplateHead */: + case 15 /* TemplateMiddle */: + case 16 /* TemplateTail */: return emitLiteral(node); - case 276: + case 276 /* UnparsedSource */: return emitUnparsedSource(node); - case 71: + // Identifiers + case 71 /* Identifier */: return emitIdentifier(node); - case 146: + // Parse tree nodes + // Names + case 146 /* QualifiedName */: return emitQualifiedName(node); - case 147: + case 147 /* ComputedPropertyName */: return emitComputedPropertyName(node); - case 148: + // Signature elements + case 148 /* TypeParameter */: return emitTypeParameter(node); - case 149: + case 149 /* Parameter */: return emitParameter(node); - case 150: + case 150 /* Decorator */: return emitDecorator(node); - case 151: + // Type members + case 151 /* PropertySignature */: return emitPropertySignature(node); - case 152: + case 152 /* PropertyDeclaration */: return emitPropertyDeclaration(node); - case 153: + case 153 /* MethodSignature */: return emitMethodSignature(node); - case 154: + case 154 /* MethodDeclaration */: return emitMethodDeclaration(node); - case 155: + case 155 /* Constructor */: return emitConstructor(node); - case 156: - case 157: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return emitAccessorDeclaration(node); - case 158: + case 158 /* CallSignature */: return emitCallSignature(node); - case 159: + case 159 /* ConstructSignature */: return emitConstructSignature(node); - case 160: + case 160 /* IndexSignature */: return emitIndexSignature(node); - case 161: + // Types + case 161 /* TypePredicate */: return emitTypePredicate(node); - case 162: + case 162 /* TypeReference */: return emitTypeReference(node); - case 163: + case 163 /* FunctionType */: return emitFunctionType(node); - case 284: + case 284 /* JSDocFunctionType */: return emitJSDocFunctionType(node); - case 164: + case 164 /* ConstructorType */: return emitConstructorType(node); - case 165: + case 165 /* TypeQuery */: return emitTypeQuery(node); - case 166: + case 166 /* TypeLiteral */: return emitTypeLiteral(node); - case 167: + case 167 /* ArrayType */: return emitArrayType(node); - case 168: + case 168 /* TupleType */: return emitTupleType(node); - case 169: + case 169 /* UnionType */: return emitUnionType(node); - case 170: + case 170 /* IntersectionType */: return emitIntersectionType(node); - case 171: + case 171 /* ConditionalType */: return emitConditionalType(node); - case 172: + case 172 /* InferType */: return emitInferType(node); - case 173: + case 173 /* ParenthesizedType */: return emitParenthesizedType(node); - case 207: + case 207 /* ExpressionWithTypeArguments */: return emitExpressionWithTypeArguments(node); - case 174: + case 174 /* ThisType */: return emitThisType(); - case 175: + case 175 /* TypeOperator */: return emitTypeOperator(node); - case 176: + case 176 /* IndexedAccessType */: return emitIndexedAccessType(node); - case 177: + case 177 /* MappedType */: return emitMappedType(node); - case 178: + case 178 /* LiteralType */: return emitLiteralType(node); - case 179: + case 179 /* ImportType */: return emitImportTypeNode(node); - case 279: + case 279 /* JSDocAllType */: write("*"); return; - case 280: + case 280 /* JSDocUnknownType */: write("?"); return; - case 281: + case 281 /* JSDocNullableType */: return emitJSDocNullableType(node); - case 282: + case 282 /* JSDocNonNullableType */: return emitJSDocNonNullableType(node); - case 283: + case 283 /* JSDocOptionalType */: return emitJSDocOptionalType(node); - case 285: + case 285 /* JSDocVariadicType */: return emitJSDocVariadicType(node); - case 180: + // Binding patterns + case 180 /* ObjectBindingPattern */: return emitObjectBindingPattern(node); - case 181: + case 181 /* ArrayBindingPattern */: return emitArrayBindingPattern(node); - case 182: + case 182 /* BindingElement */: return emitBindingElement(node); - case 211: + // Misc + case 211 /* TemplateSpan */: return emitTemplateSpan(node); - case 212: + case 212 /* SemicolonClassElement */: return emitSemicolonClassElement(); - case 213: + // Statements + case 213 /* Block */: return emitBlock(node); - case 214: + case 214 /* VariableStatement */: return emitVariableStatement(node); - case 215: + case 215 /* EmptyStatement */: return emitEmptyStatement(); - case 216: + case 216 /* ExpressionStatement */: return emitExpressionStatement(node); - case 217: + case 217 /* IfStatement */: return emitIfStatement(node); - case 218: + case 218 /* DoStatement */: return emitDoStatement(node); - case 219: + case 219 /* WhileStatement */: return emitWhileStatement(node); - case 220: + case 220 /* ForStatement */: return emitForStatement(node); - case 221: + case 221 /* ForInStatement */: return emitForInStatement(node); - case 222: + case 222 /* ForOfStatement */: return emitForOfStatement(node); - case 223: + case 223 /* ContinueStatement */: return emitContinueStatement(node); - case 224: + case 224 /* BreakStatement */: return emitBreakStatement(node); - case 225: + case 225 /* ReturnStatement */: return emitReturnStatement(node); - case 226: + case 226 /* WithStatement */: return emitWithStatement(node); - case 227: + case 227 /* SwitchStatement */: return emitSwitchStatement(node); - case 228: + case 228 /* LabeledStatement */: return emitLabeledStatement(node); - case 229: + case 229 /* ThrowStatement */: return emitThrowStatement(node); - case 230: + case 230 /* TryStatement */: return emitTryStatement(node); - case 231: + case 231 /* DebuggerStatement */: return emitDebuggerStatement(node); - case 232: + // Declarations + case 232 /* VariableDeclaration */: return emitVariableDeclaration(node); - case 233: + case 233 /* VariableDeclarationList */: return emitVariableDeclarationList(node); - case 234: + case 234 /* FunctionDeclaration */: return emitFunctionDeclaration(node); - case 235: + case 235 /* ClassDeclaration */: return emitClassDeclaration(node); - case 236: + case 236 /* InterfaceDeclaration */: return emitInterfaceDeclaration(node); - case 237: + case 237 /* TypeAliasDeclaration */: return emitTypeAliasDeclaration(node); - case 238: + case 238 /* EnumDeclaration */: return emitEnumDeclaration(node); - case 239: + case 239 /* ModuleDeclaration */: return emitModuleDeclaration(node); - case 240: + case 240 /* ModuleBlock */: return emitModuleBlock(node); - case 241: + case 241 /* CaseBlock */: return emitCaseBlock(node); - case 242: + case 242 /* NamespaceExportDeclaration */: return emitNamespaceExportDeclaration(node); - case 243: + case 243 /* ImportEqualsDeclaration */: return emitImportEqualsDeclaration(node); - case 244: + case 244 /* ImportDeclaration */: return emitImportDeclaration(node); - case 245: + case 245 /* ImportClause */: return emitImportClause(node); - case 246: + case 246 /* NamespaceImport */: return emitNamespaceImport(node); - case 247: + case 247 /* NamedImports */: return emitNamedImports(node); - case 248: + case 248 /* ImportSpecifier */: return emitImportSpecifier(node); - case 249: + case 249 /* ExportAssignment */: return emitExportAssignment(node); - case 250: + case 250 /* ExportDeclaration */: return emitExportDeclaration(node); - case 251: + case 251 /* NamedExports */: return emitNamedExports(node); - case 252: + case 252 /* ExportSpecifier */: return emitExportSpecifier(node); - case 253: + case 253 /* MissingDeclaration */: return; - case 254: + // Module references + case 254 /* ExternalModuleReference */: return emitExternalModuleReference(node); - case 10: + // JSX (non-expression) + case 10 /* JsxText */: return emitJsxText(node); - case 257: - case 260: + case 257 /* JsxOpeningElement */: + case 260 /* JsxOpeningFragment */: return emitJsxOpeningElementOrFragment(node); - case 258: - case 261: + case 258 /* JsxClosingElement */: + case 261 /* JsxClosingFragment */: return emitJsxClosingElementOrFragment(node); - case 262: + case 262 /* JsxAttribute */: return emitJsxAttribute(node); - case 263: + case 263 /* JsxAttributes */: return emitJsxAttributes(node); - case 264: + case 264 /* JsxSpreadAttribute */: return emitJsxSpreadAttribute(node); - case 265: + case 265 /* JsxExpression */: return emitJsxExpression(node); - case 266: + // Clauses + case 266 /* CaseClause */: return emitCaseClause(node); - case 267: + case 267 /* DefaultClause */: return emitDefaultClause(node); - case 268: + case 268 /* HeritageClause */: return emitHeritageClause(node); - case 269: + case 269 /* CatchClause */: return emitCatchClause(node); - case 270: + // Property assignments + case 270 /* PropertyAssignment */: return emitPropertyAssignment(node); - case 271: + case 271 /* ShorthandPropertyAssignment */: return emitShorthandPropertyAssignment(node); - case 272: + case 272 /* SpreadAssignment */: return emitSpreadAssignment(node); - case 273: + // Enum + case 273 /* EnumMember */: return emitEnumMember(node); + // JSDoc nodes (ignored) + // Transformation nodes (ignored) } if (ts.isExpression(node)) { - hint = 1; - node = trySubstituteNode(1, node); + hint = 1 /* Expression */; + node = trySubstituteNode(1 /* Expression */, node); } else if (ts.isToken(node)) { return writeTokenNode(node, writePunctuation); } } - if (hint === 1) { + if (hint === 1 /* Expression */) { switch (node.kind) { - case 8: + // Literals + case 8 /* NumericLiteral */: return emitNumericLiteral(node); - case 9: - case 12: - case 13: + case 9 /* StringLiteral */: + case 12 /* RegularExpressionLiteral */: + case 13 /* NoSubstitutionTemplateLiteral */: return emitLiteral(node); - case 71: + // Identifiers + case 71 /* Identifier */: return emitIdentifier(node); - case 86: - case 95: - case 97: - case 101: - case 99: - case 91: + // Reserved words + case 86 /* FalseKeyword */: + case 95 /* NullKeyword */: + case 97 /* SuperKeyword */: + case 101 /* TrueKeyword */: + case 99 /* ThisKeyword */: + case 91 /* ImportKeyword */: writeTokenNode(node, writeKeyword); return; - case 183: + // Expressions + case 183 /* ArrayLiteralExpression */: return emitArrayLiteralExpression(node); - case 184: + case 184 /* ObjectLiteralExpression */: return emitObjectLiteralExpression(node); - case 185: + case 185 /* PropertyAccessExpression */: return emitPropertyAccessExpression(node); - case 186: + case 186 /* ElementAccessExpression */: return emitElementAccessExpression(node); - case 187: + case 187 /* CallExpression */: return emitCallExpression(node); - case 188: + case 188 /* NewExpression */: return emitNewExpression(node); - case 189: + case 189 /* TaggedTemplateExpression */: return emitTaggedTemplateExpression(node); - case 190: + case 190 /* TypeAssertionExpression */: return emitTypeAssertionExpression(node); - case 191: + case 191 /* ParenthesizedExpression */: return emitParenthesizedExpression(node); - case 192: + case 192 /* FunctionExpression */: return emitFunctionExpression(node); - case 193: + case 193 /* ArrowFunction */: return emitArrowFunction(node); - case 194: + case 194 /* DeleteExpression */: return emitDeleteExpression(node); - case 195: + case 195 /* TypeOfExpression */: return emitTypeOfExpression(node); - case 196: + case 196 /* VoidExpression */: return emitVoidExpression(node); - case 197: + case 197 /* AwaitExpression */: return emitAwaitExpression(node); - case 198: + case 198 /* PrefixUnaryExpression */: return emitPrefixUnaryExpression(node); - case 199: + case 199 /* PostfixUnaryExpression */: return emitPostfixUnaryExpression(node); - case 200: + case 200 /* BinaryExpression */: return emitBinaryExpression(node); - case 201: + case 201 /* ConditionalExpression */: return emitConditionalExpression(node); - case 202: + case 202 /* TemplateExpression */: return emitTemplateExpression(node); - case 203: + case 203 /* YieldExpression */: return emitYieldExpression(node); - case 204: + case 204 /* SpreadElement */: return emitSpreadExpression(node); - case 205: + case 205 /* ClassExpression */: return emitClassExpression(node); - case 206: + case 206 /* OmittedExpression */: return; - case 208: + case 208 /* AsExpression */: return emitAsExpression(node); - case 209: + case 209 /* NonNullExpression */: return emitNonNullExpression(node); - case 210: + case 210 /* MetaProperty */: return emitMetaProperty(node); - case 255: + // JSX + case 255 /* JsxElement */: return emitJsxElement(node); - case 256: + case 256 /* JsxSelfClosingElement */: return emitJsxSelfClosingElement(node); - case 259: + case 259 /* JsxFragment */: return emitJsxFragment(node); - case 302: + // Transformation nodes + case 302 /* PartiallyEmittedExpression */: return emitPartiallyEmittedExpression(node); - case 303: + case 303 /* CommaListExpression */: return emitCommaList(node); } } @@ -64691,7 +78250,7 @@ var ts; } function emitHelpers(node) { var helpersEmitted = false; - var bundle = node.kind === 275 ? node : undefined; + var bundle = node.kind === 275 /* Bundle */ ? node : undefined; if (bundle && moduleKind === ts.ModuleKind.None) { return; } @@ -64706,8 +78265,13 @@ var ts; for (var _a = 0, _b = ts.stableSort(helpers, ts.compareEmitHelpers); _a < _b.length; _a++) { var helper = _b[_a]; if (!helper.scoped) { + // Skip the helper if it can be skipped and the noEmitHelpers compiler + // option is set, or if it can be imported and the importHelpers compiler + // option is set. if (shouldSkip) continue; + // Skip the helper if it can be bundled but hasn't already been emitted and we + // are emitting a bundled module. if (shouldBundle) { if (bundledHelpers.get(helper.name)) { continue; @@ -64716,6 +78280,7 @@ var ts; } } else if (bundle) { + // Skip the helper if it is scoped and we are emitting bundled helpers continue; } if (typeof helper.text === "string") { @@ -64730,34 +78295,52 @@ var ts; } return helpersEmitted; } + // + // Literals/Pseudo-literals + // + // SyntaxKind.NumericLiteral function emitNumericLiteral(node) { emitLiteral(node); } + // SyntaxKind.StringLiteral + // SyntaxKind.RegularExpressionLiteral + // SyntaxKind.NoSubstitutionTemplateLiteral + // SyntaxKind.TemplateHead + // SyntaxKind.TemplateMiddle + // SyntaxKind.TemplateTail function emitLiteral(node) { var text = getLiteralTextOfNode(node); if ((printerOptions.sourceMap || printerOptions.inlineSourceMap) - && (node.kind === 9 || ts.isTemplateLiteralKind(node.kind))) { + && (node.kind === 9 /* StringLiteral */ || ts.isTemplateLiteralKind(node.kind))) { writeLiteral(text); } else { + // Quick info expects all literals to be called with writeStringLiteral, as there's no specific type for numberLiterals writeStringLiteral(text); } } + // SyntaxKind.UnparsedSource function emitUnparsedSource(unparsed) { writer.rawWrite(unparsed.text); } + // + // Identifiers + // function emitIdentifier(node) { var writeText = node.symbol ? writeSymbol : write; - writeText(getTextOfNode(node, false), node.symbol); - emitList(node, node.typeArguments, 26896); + writeText(getTextOfNode(node, /*includeTrivia*/ false), node.symbol); + emitList(node, node.typeArguments, 26896 /* TypeParameters */); // Call emitList directly since it could be an array of TypeParameterDeclarations _or_ type arguments } + // + // Names + // function emitQualifiedName(node) { emitEntityName(node.left); writePunctuation("."); emit(node.right); } function emitEntityName(node) { - if (node.kind === 71) { + if (node.kind === 71 /* Identifier */) { emitExpression(node); } else { @@ -64769,6 +78352,9 @@ var ts; emitExpression(node.expression); writePunctuation("]"); } + // + // Signature elements + // function emitTypeParameter(node) { emit(node.name); if (node.constraint) { @@ -64790,18 +78376,22 @@ var ts; emit(node.dotDotDotToken); emitNodeWithWriter(node.name, writeParameter); emit(node.questionToken); - if (node.parent && node.parent.kind === 284 && !node.name) { + if (node.parent && node.parent.kind === 284 /* JSDocFunctionType */ && !node.name) { emit(node.type); } else { emitTypeAnnotation(node.type); } + // The comment position has to fallback to any present node within the parameterdeclaration because as it turns out, the parser can make parameter declarations with _just_ an initializer. emitInitializer(node.initializer, node.type ? node.type.end : node.questionToken ? node.questionToken.end : node.name ? node.name.end : node.modifiers ? node.modifiers.end : node.decorators ? node.decorators.end : node.pos, node); } function emitDecorator(decorator) { writePunctuation("@"); emitExpression(decorator.expression); } + // + // Type members + // function emitPropertySignature(node) { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); @@ -64848,7 +78438,7 @@ var ts; function emitAccessorDeclaration(node) { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); - writeKeyword(node.kind === 156 ? "get" : "set"); + writeKeyword(node.kind === 156 /* GetAccessor */ ? "get" : "set"); writeSpace(); emit(node.name); emitSignatureAndBody(node, emitSignatureHead); @@ -64885,6 +78475,9 @@ var ts; function emitSemicolonClassElement() { writeSemicolon(); } + // + // Types + // function emitTypePredicate(node) { emit(node.parameterName); writeSpace(); @@ -64943,8 +78536,8 @@ var ts; } function emitTypeLiteral(node) { writePunctuation("{"); - var flags = ts.getEmitFlags(node) & 1 ? 384 : 16449; - emitList(node, node.members, flags | 262144); + var flags = ts.getEmitFlags(node) & 1 /* SingleLine */ ? 384 /* SingleLineTypeLiteralMembers */ : 16449 /* MultiLineTypeLiteralMembers */; + emitList(node, node.members, flags | 262144 /* NoSpaceIfEmpty */); writePunctuation("}"); } function emitArrayType(node) { @@ -64958,14 +78551,14 @@ var ts; } function emitTupleType(node) { writePunctuation("["); - emitList(node, node.elementTypes, 272); + emitList(node, node.elementTypes, 272 /* TupleTypeElements */); writePunctuation("]"); } function emitUnionType(node) { - emitList(node, node.types, 260); + emitList(node, node.types, 260 /* UnionTypeConstituents */); } function emitIntersectionType(node) { - emitList(node, node.types, 264); + emitList(node, node.types, 264 /* IntersectionTypeConstituents */); } function emitConditionalType(node) { emit(node.checkType); @@ -65009,7 +78602,7 @@ var ts; function emitMappedType(node) { var emitFlags = ts.getEmitFlags(node); writePunctuation("{"); - if (emitFlags & 1) { + if (emitFlags & 1 /* SingleLine */) { writeSpace(); } else { @@ -65018,18 +78611,18 @@ var ts; } if (node.readonlyToken) { emit(node.readonlyToken); - if (node.readonlyToken.kind !== 132) { + if (node.readonlyToken.kind !== 132 /* ReadonlyKeyword */) { writeKeyword("readonly"); } writeSpace(); } writePunctuation("["); - var pipelinePhase = getPipelinePhase(0, 3); - pipelinePhase(3, node.typeParameter); + var pipelinePhase = getPipelinePhase(0 /* Notification */, 3 /* MappedTypeParameter */); + pipelinePhase(3 /* MappedTypeParameter */, node.typeParameter); writePunctuation("]"); if (node.questionToken) { emit(node.questionToken); - if (node.questionToken.kind !== 55) { + if (node.questionToken.kind !== 55 /* QuestionToken */) { writePunctuation("?"); } } @@ -65037,7 +78630,7 @@ var ts; writeSpace(); emit(node.type); writeSemicolon(); - if (emitFlags & 1) { + if (emitFlags & 1 /* SingleLine */) { writeSpace(); } else { @@ -65064,14 +78657,17 @@ var ts; } emitTypeArguments(node, node.typeArguments); } + // + // Binding patterns + // function emitObjectBindingPattern(node) { writePunctuation("{"); - emitList(node, node.elements, 262576); + emitList(node, node.elements, 262576 /* ObjectBindingPatternElements */); writePunctuation("}"); } function emitArrayBindingPattern(node) { writePunctuation("["); - emitList(node, node.elements, 262448); + emitList(node, node.elements, 262448 /* ArrayBindingPatternElements */); writePunctuation("]"); } function emitBindingElement(node) { @@ -65084,20 +78680,23 @@ var ts; emit(node.name); emitInitializer(node.initializer, node.name.end, node); } + // + // Expressions + // function emitArrayLiteralExpression(node) { var elements = node.elements; - var preferNewLine = node.multiLine ? 32768 : 0; - emitExpressionList(node, elements, 4466 | preferNewLine); + var preferNewLine = node.multiLine ? 32768 /* PreferNewLine */ : 0 /* None */; + emitExpressionList(node, elements, 4466 /* ArrayLiteralExpressionElements */ | preferNewLine); } function emitObjectLiteralExpression(node) { ts.forEach(node.properties, generateMemberNames); - var indentedFlag = ts.getEmitFlags(node) & 65536; + var indentedFlag = ts.getEmitFlags(node) & 65536 /* Indented */; if (indentedFlag) { increaseIndent(); } - var preferNewLine = node.multiLine ? 32768 : 0; - var allowTrailingComma = currentSourceFile.languageVersion >= 1 && !ts.isJsonSourceFile(currentSourceFile) ? 32 : 0; - emitList(node, node.properties, 263122 | allowTrailingComma | preferNewLine); + var preferNewLine = node.multiLine ? 32768 /* PreferNewLine */ : 0 /* None */; + var allowTrailingComma = currentSourceFile.languageVersion >= 1 /* ES5 */ && !ts.isJsonSourceFile(currentSourceFile) ? 32 /* AllowTrailingComma */ : 0 /* None */; + emitList(node, node.properties, 263122 /* ObjectLiteralExpressionProperties */ | allowTrailingComma | preferNewLine); if (indentedFlag) { decreaseIndent(); } @@ -65105,10 +78704,10 @@ var ts; function emitPropertyAccessExpression(node) { var indentBeforeDot = false; var indentAfterDot = false; - if (!(ts.getEmitFlags(node) & 131072)) { + if (!(ts.getEmitFlags(node) & 131072 /* NoIndentation */)) { var dotRangeStart = node.expression.end; var dotRangeEnd = ts.skipTrivia(currentSourceFile.text, node.expression.end) + 1; - var dotToken = ts.createToken(23); + var dotToken = ts.createToken(23 /* DotToken */); dotToken.pos = dotRangeStart; dotToken.end = dotRangeEnd; indentBeforeDot = needsIndentation(node, node.expression, dotToken); @@ -65120,20 +78719,25 @@ var ts; if (shouldEmitDotDot) { writePunctuation("."); } - emitTokenWithComment(23, node.expression.end, writePunctuation, node); + emitTokenWithComment(23 /* DotToken */, node.expression.end, writePunctuation, node); increaseIndentIf(indentAfterDot); emit(node.name); decreaseIndentIf(indentBeforeDot, indentAfterDot); } + // 1..toString is a valid property access, emit a dot after the literal + // Also emit a dot if expression is a integer const enum value - it will appear in generated code as numeric literal function needsDotDotForPropertyAccess(expression) { expression = ts.skipPartiallyEmittedExpressions(expression); if (ts.isNumericLiteral(expression)) { + // check if numeric literal is a decimal literal that was originally written with a dot var text = getLiteralTextOfNode(expression); return !expression.numericLiteralFlags - && !ts.stringContains(text, ts.tokenToString(23)); + && !ts.stringContains(text, ts.tokenToString(23 /* DotToken */)); } else if (ts.isPropertyAccessExpression(expression) || ts.isElementAccessExpression(expression)) { + // check if constant enum value is integer var constantValue = ts.getConstantValue(expression); + // isFinite handles cases when constantValue is undefined return typeof constantValue === "number" && isFinite(constantValue) && Math.floor(constantValue) === constantValue && printerOptions.removeComments; @@ -65141,21 +78745,21 @@ var ts; } function emitElementAccessExpression(node) { emitExpression(node.expression); - emitTokenWithComment(21, node.expression.end, writePunctuation, node); + emitTokenWithComment(21 /* OpenBracketToken */, node.expression.end, writePunctuation, node); emitExpression(node.argumentExpression); - emitTokenWithComment(22, node.argumentExpression.end, writePunctuation, node); + emitTokenWithComment(22 /* CloseBracketToken */, node.argumentExpression.end, writePunctuation, node); } function emitCallExpression(node) { emitExpression(node.expression); emitTypeArguments(node, node.typeArguments); - emitExpressionList(node, node.arguments, 1296); + emitExpressionList(node, node.arguments, 1296 /* CallExpressionArguments */); } function emitNewExpression(node) { - emitTokenWithComment(94, node.pos, writeKeyword, node); + emitTokenWithComment(94 /* NewKeyword */, node.pos, writeKeyword, node); writeSpace(); emitExpression(node.expression); emitTypeArguments(node, node.typeArguments); - emitExpressionList(node, node.arguments, 9488); + emitExpressionList(node, node.arguments, 9488 /* NewExpressionArguments */); } function emitTaggedTemplateExpression(node) { emitExpression(node.tag); @@ -65170,9 +78774,9 @@ var ts; emitExpression(node.expression); } function emitParenthesizedExpression(node) { - var openParenPos = emitTokenWithComment(19, node.pos, writePunctuation, node); + var openParenPos = emitTokenWithComment(19 /* OpenParenToken */, node.pos, writePunctuation, node); emitExpression(node.expression); - emitTokenWithComment(20, node.expression ? node.expression.end : openParenPos, writePunctuation, node); + emitTokenWithComment(20 /* CloseParenToken */, node.expression ? node.expression.end : openParenPos, writePunctuation, node); } function emitFunctionExpression(node) { generateNameIfNeeded(node.name); @@ -65191,22 +78795,22 @@ var ts; emit(node.equalsGreaterThanToken); } function emitDeleteExpression(node) { - emitTokenWithComment(80, node.pos, writeKeyword, node); + emitTokenWithComment(80 /* DeleteKeyword */, node.pos, writeKeyword, node); writeSpace(); emitExpression(node.expression); } function emitTypeOfExpression(node) { - emitTokenWithComment(103, node.pos, writeKeyword, node); + emitTokenWithComment(103 /* TypeOfKeyword */, node.pos, writeKeyword, node); writeSpace(); emitExpression(node.expression); } function emitVoidExpression(node) { - emitTokenWithComment(105, node.pos, writeKeyword, node); + emitTokenWithComment(105 /* VoidKeyword */, node.pos, writeKeyword, node); writeSpace(); emitExpression(node.expression); } function emitAwaitExpression(node) { - emitTokenWithComment(121, node.pos, writeKeyword, node); + emitTokenWithComment(121 /* AwaitKeyword */, node.pos, writeKeyword, node); writeSpace(); emitExpression(node.expression); } @@ -65218,24 +78822,36 @@ var ts; emitExpression(node.operand); } function shouldEmitWhitespaceBeforeOperand(node) { + // In some cases, we need to emit a space between the operator and the operand. One obvious case + // is when the operator is an identifier, like delete or typeof. We also need to do this for plus + // and minus expressions in certain cases. Specifically, consider the following two cases (parens + // are just for clarity of exposition, and not part of the source code): + // + // (+(+1)) + // (+(++1)) + // + // We need to emit a space in both cases. In the first case, the absence of a space will make + // the resulting expression a prefix increment operation. And in the second, it will make the resulting + // expression a prefix increment whose operand is a plus expression - (++(+x)) + // The same is true of minus of course. var operand = node.operand; - return operand.kind === 198 - && ((node.operator === 37 && (operand.operator === 37 || operand.operator === 43)) - || (node.operator === 38 && (operand.operator === 38 || operand.operator === 44))); + return operand.kind === 198 /* PrefixUnaryExpression */ + && ((node.operator === 37 /* PlusToken */ && (operand.operator === 37 /* PlusToken */ || operand.operator === 43 /* PlusPlusToken */)) + || (node.operator === 38 /* MinusToken */ && (operand.operator === 38 /* MinusToken */ || operand.operator === 44 /* MinusMinusToken */))); } function emitPostfixUnaryExpression(node) { emitExpression(node.operand); writeTokenText(node.operator, writeOperator); } function emitBinaryExpression(node) { - var isCommaOperator = node.operatorToken.kind !== 26; + var isCommaOperator = node.operatorToken.kind !== 26 /* CommaToken */; var indentBeforeOperator = needsIndentation(node, node.left, node.operatorToken); var indentAfterOperator = needsIndentation(node, node.operatorToken, node.right); emitExpression(node.left); increaseIndentIf(indentBeforeOperator, isCommaOperator ? " " : undefined); emitLeadingCommentsOfPosition(node.operatorToken.pos); writeTokenNode(node.operatorToken, writeOperator); - emitTrailingCommentsOfPosition(node.operatorToken.end, true); + emitTrailingCommentsOfPosition(node.operatorToken.end, /*prefixSpace*/ true); // Binary operators should have a space before the comment starts increaseIndentIf(indentAfterOperator, " "); emitExpression(node.right); decreaseIndentIf(indentBeforeOperator, indentAfterOperator); @@ -65259,10 +78875,10 @@ var ts; } function emitTemplateExpression(node) { emit(node.head); - emitList(node, node.templateSpans, 131072); + emitList(node, node.templateSpans, 131072 /* TemplateExpressionSpans */); } function emitYieldExpression(node) { - emitTokenWithComment(116, node.pos, writeKeyword, node); + emitTokenWithComment(116 /* YieldKeyword */, node.pos, writeKeyword, node); emit(node.asteriskToken); emitExpressionWithLeadingSpace(node.expression); } @@ -65296,18 +78912,24 @@ var ts; writePunctuation("."); emit(node.name); } + // + // Misc + // function emitTemplateSpan(node) { emitExpression(node.expression); emit(node.literal); } + // + // Statements + // function emitBlock(node) { - emitBlockStatements(node, !node.multiLine && isEmptyBlock(node)); + emitBlockStatements(node, /*forceSingleLine*/ !node.multiLine && isEmptyBlock(node)); } function emitBlockStatements(node, forceSingleLine) { - emitTokenWithComment(17, node.pos, writePunctuation, node); - var format = forceSingleLine || ts.getEmitFlags(node) & 1 ? 384 : 65; + emitTokenWithComment(17 /* OpenBraceToken */, node.pos, writePunctuation, /*contextNode*/ node); + var format = forceSingleLine || ts.getEmitFlags(node) & 1 /* SingleLine */ ? 384 /* SingleLineBlockStatements */ : 65 /* MultiLineBlockStatements */; emitList(node, node.statements, format); - emitTokenWithComment(18, node.statements.end, writePunctuation, node, !!(format & 1)); + emitTokenWithComment(18 /* CloseBraceToken */, node.statements.end, writePunctuation, /*contextNode*/ node, /*indentLeading*/ !!(format & 1 /* MultiLine */)); } function emitVariableStatement(node) { emitModifiers(node, node.modifiers); @@ -65324,16 +78946,16 @@ var ts; } } function emitIfStatement(node) { - var openParenPos = emitTokenWithComment(90, node.pos, writeKeyword, node); + var openParenPos = emitTokenWithComment(90 /* IfKeyword */, node.pos, writeKeyword, node); writeSpace(); - emitTokenWithComment(19, openParenPos, writePunctuation, node); + emitTokenWithComment(19 /* OpenParenToken */, openParenPos, writePunctuation, node); emitExpression(node.expression); - emitTokenWithComment(20, node.expression.end, writePunctuation, node); + emitTokenWithComment(20 /* CloseParenToken */, node.expression.end, writePunctuation, node); emitEmbeddedStatement(node, node.thenStatement); if (node.elseStatement) { writeLineOrSpace(node); - emitTokenWithComment(82, node.thenStatement.end, writeKeyword, node); - if (node.elseStatement.kind === 217) { + emitTokenWithComment(82 /* ElseKeyword */, node.thenStatement.end, writeKeyword, node); + if (node.elseStatement.kind === 217 /* IfStatement */) { writeSpace(); emit(node.elseStatement); } @@ -65343,14 +78965,14 @@ var ts; } } function emitWhileClause(node, startPos) { - var openParenPos = emitTokenWithComment(106, startPos, writeKeyword, node); + var openParenPos = emitTokenWithComment(106 /* WhileKeyword */, startPos, writeKeyword, node); writeSpace(); - emitTokenWithComment(19, openParenPos, writePunctuation, node); + emitTokenWithComment(19 /* OpenParenToken */, openParenPos, writePunctuation, node); emitExpression(node.expression); - emitTokenWithComment(20, node.expression.end, writePunctuation, node); + emitTokenWithComment(20 /* CloseParenToken */, node.expression.end, writePunctuation, node); } function emitDoStatement(node) { - emitTokenWithComment(81, node.pos, writeKeyword, node); + emitTokenWithComment(81 /* DoKeyword */, node.pos, writeKeyword, node); emitEmbeddedStatement(node, node.statement); if (ts.isBlock(node.statement)) { writeSpace(); @@ -65366,45 +78988,45 @@ var ts; emitEmbeddedStatement(node, node.statement); } function emitForStatement(node) { - var openParenPos = emitTokenWithComment(88, node.pos, writeKeyword, node); + var openParenPos = emitTokenWithComment(88 /* ForKeyword */, node.pos, writeKeyword, node); writeSpace(); - var pos = emitTokenWithComment(19, openParenPos, writePunctuation, node); + var pos = emitTokenWithComment(19 /* OpenParenToken */, openParenPos, writePunctuation, /*contextNode*/ node); emitForBinding(node.initializer); - pos = emitTokenWithComment(25, node.initializer ? node.initializer.end : pos, writeSemicolon, node); + pos = emitTokenWithComment(25 /* SemicolonToken */, node.initializer ? node.initializer.end : pos, writeSemicolon, node); emitExpressionWithLeadingSpace(node.condition); - pos = emitTokenWithComment(25, node.condition ? node.condition.end : pos, writeSemicolon, node); + pos = emitTokenWithComment(25 /* SemicolonToken */, node.condition ? node.condition.end : pos, writeSemicolon, node); emitExpressionWithLeadingSpace(node.incrementor); - emitTokenWithComment(20, node.incrementor ? node.incrementor.end : pos, writePunctuation, node); + emitTokenWithComment(20 /* CloseParenToken */, node.incrementor ? node.incrementor.end : pos, writePunctuation, node); emitEmbeddedStatement(node, node.statement); } function emitForInStatement(node) { - var openParenPos = emitTokenWithComment(88, node.pos, writeKeyword, node); + var openParenPos = emitTokenWithComment(88 /* ForKeyword */, node.pos, writeKeyword, node); writeSpace(); - emitTokenWithComment(19, openParenPos, writePunctuation, node); + emitTokenWithComment(19 /* OpenParenToken */, openParenPos, writePunctuation, node); emitForBinding(node.initializer); writeSpace(); - emitTokenWithComment(92, node.initializer.end, writeKeyword, node); + emitTokenWithComment(92 /* InKeyword */, node.initializer.end, writeKeyword, node); writeSpace(); emitExpression(node.expression); - emitTokenWithComment(20, node.expression.end, writePunctuation, node); + emitTokenWithComment(20 /* CloseParenToken */, node.expression.end, writePunctuation, node); emitEmbeddedStatement(node, node.statement); } function emitForOfStatement(node) { - var openParenPos = emitTokenWithComment(88, node.pos, writeKeyword, node); + var openParenPos = emitTokenWithComment(88 /* ForKeyword */, node.pos, writeKeyword, node); writeSpace(); emitWithTrailingSpace(node.awaitModifier); - emitTokenWithComment(19, openParenPos, writePunctuation, node); + emitTokenWithComment(19 /* OpenParenToken */, openParenPos, writePunctuation, node); emitForBinding(node.initializer); writeSpace(); - emitTokenWithComment(145, node.initializer.end, writeKeyword, node); + emitTokenWithComment(145 /* OfKeyword */, node.initializer.end, writeKeyword, node); writeSpace(); emitExpression(node.expression); - emitTokenWithComment(20, node.expression.end, writePunctuation, node); + emitTokenWithComment(20 /* CloseParenToken */, node.expression.end, writePunctuation, node); emitEmbeddedStatement(node, node.statement); } function emitForBinding(node) { if (node !== undefined) { - if (node.kind === 233) { + if (node.kind === 233 /* VariableDeclarationList */) { emit(node); } else { @@ -65413,12 +79035,12 @@ var ts; } } function emitContinueStatement(node) { - emitTokenWithComment(77, node.pos, writeKeyword, node); + emitTokenWithComment(77 /* ContinueKeyword */, node.pos, writeKeyword, node); emitWithLeadingSpace(node.label); writeSemicolon(); } function emitBreakStatement(node) { - emitTokenWithComment(72, node.pos, writeKeyword, node); + emitTokenWithComment(72 /* BreakKeyword */, node.pos, writeKeyword, node); emitWithLeadingSpace(node.label); writeSemicolon(); } @@ -65441,45 +79063,45 @@ var ts; } pos = writeTokenText(token, writer, pos); if (emitTrailingCommentsOfPosition && isSimilarNode && contextNode.end !== pos) { - emitTrailingCommentsOfPosition(pos, true); + emitTrailingCommentsOfPosition(pos, /*prefixSpace*/ true); } return pos; } function emitReturnStatement(node) { - emitTokenWithComment(96, node.pos, writeKeyword, node); + emitTokenWithComment(96 /* ReturnKeyword */, node.pos, writeKeyword, /*contextNode*/ node); emitExpressionWithLeadingSpace(node.expression); writeSemicolon(); } function emitWithStatement(node) { - var openParenPos = emitTokenWithComment(107, node.pos, writeKeyword, node); + var openParenPos = emitTokenWithComment(107 /* WithKeyword */, node.pos, writeKeyword, node); writeSpace(); - emitTokenWithComment(19, openParenPos, writePunctuation, node); + emitTokenWithComment(19 /* OpenParenToken */, openParenPos, writePunctuation, node); emitExpression(node.expression); - emitTokenWithComment(20, node.expression.end, writePunctuation, node); + emitTokenWithComment(20 /* CloseParenToken */, node.expression.end, writePunctuation, node); emitEmbeddedStatement(node, node.statement); } function emitSwitchStatement(node) { - var openParenPos = emitTokenWithComment(98, node.pos, writeKeyword, node); + var openParenPos = emitTokenWithComment(98 /* SwitchKeyword */, node.pos, writeKeyword, node); writeSpace(); - emitTokenWithComment(19, openParenPos, writePunctuation, node); + emitTokenWithComment(19 /* OpenParenToken */, openParenPos, writePunctuation, node); emitExpression(node.expression); - emitTokenWithComment(20, node.expression.end, writePunctuation, node); + emitTokenWithComment(20 /* CloseParenToken */, node.expression.end, writePunctuation, node); writeSpace(); emit(node.caseBlock); } function emitLabeledStatement(node) { emit(node.label); - emitTokenWithComment(56, node.label.end, writePunctuation, node); + emitTokenWithComment(56 /* ColonToken */, node.label.end, writePunctuation, node); writeSpace(); emit(node.statement); } function emitThrowStatement(node) { - emitTokenWithComment(100, node.pos, writeKeyword, node); + emitTokenWithComment(100 /* ThrowKeyword */, node.pos, writeKeyword, node); emitExpressionWithLeadingSpace(node.expression); writeSemicolon(); } function emitTryStatement(node) { - emitTokenWithComment(102, node.pos, writeKeyword, node); + emitTokenWithComment(102 /* TryKeyword */, node.pos, writeKeyword, node); writeSpace(); emit(node.tryBlock); if (node.catchClause) { @@ -65488,15 +79110,18 @@ var ts; } if (node.finallyBlock) { writeLineOrSpace(node); - emitTokenWithComment(87, (node.catchClause || node.tryBlock).end, writeKeyword, node); + emitTokenWithComment(87 /* FinallyKeyword */, (node.catchClause || node.tryBlock).end, writeKeyword, node); writeSpace(); emit(node.finallyBlock); } } function emitDebuggerStatement(node) { - writeToken(78, node.pos, writeKeyword); + writeToken(78 /* DebuggerKeyword */, node.pos, writeKeyword); writeSemicolon(); } + // + // Declarations + // function emitVariableDeclaration(node) { emit(node.name); emitTypeAnnotation(node.type); @@ -65505,7 +79130,7 @@ var ts; function emitVariableDeclarationList(node) { writeKeyword(ts.isLet(node) ? "let" : ts.isConst(node) ? "const" : "var"); writeSpace(); - emitList(node, node.declarations, 272); + emitList(node, node.declarations, 272 /* VariableDeclarationList */); } function emitFunctionDeclaration(node) { emitFunctionDeclarationOrExpression(node); @@ -65516,7 +79141,7 @@ var ts; writeKeyword("function"); emit(node.asteriskToken); writeSpace(); - emitIdentifierName(node.name); + emitIdentifierName(node.name); // TODO: GH#18217 emitSignatureAndBody(node, emitSignatureHead); } function emitBlockCallback(_hint, body) { @@ -65526,7 +79151,7 @@ var ts; var body = node.body; if (body) { if (ts.isBlock(body)) { - var indentedFlag = ts.getEmitFlags(node) & 65536; + var indentedFlag = ts.getEmitFlags(node) & 65536 /* Indented */; if (indentedFlag) { increaseIndent(); } @@ -65535,7 +79160,7 @@ var ts; generateNames(node.body); emitSignatureHead(node); if (onEmitNode) { - onEmitNode(4, body, emitBlockCallback); + onEmitNode(4 /* Unspecified */, body, emitBlockCallback); } else { emitBlockFunctionBody(body); @@ -65562,7 +79187,13 @@ var ts; emitTypeAnnotation(node.type); } function shouldEmitBlockFunctionBodyOnSingleLine(body) { - if (ts.getEmitFlags(body) & 1) { + // We must emit a function body as a single-line body in the following case: + // * The body has NodeEmitFlags.SingleLine specified. + // We must emit a function body as a multi-line body in the following cases: + // * The body is explicitly marked as multi-line. + // * A non-synthesized body's start and end position are on different lines. + // * Any statement in the body starts on a new line. + if (ts.getEmitFlags(body) & 1 /* SingleLine */) { return true; } if (body.multiLine) { @@ -65571,14 +79202,14 @@ var ts; if (!ts.nodeIsSynthesized(body) && !ts.rangeIsOnSingleLine(body, currentSourceFile)) { return false; } - if (shouldWriteLeadingLineTerminator(body, body.statements, 2) - || shouldWriteClosingLineTerminator(body, body.statements, 2)) { + if (shouldWriteLeadingLineTerminator(body, body.statements, 2 /* PreserveLines */) + || shouldWriteClosingLineTerminator(body, body.statements, 2 /* PreserveLines */)) { return false; } var previousStatement; for (var _a = 0, _b = body.statements; _a < _b.length; _a++) { var statement = _b[_a]; - if (shouldWriteSeparatingLineTerminator(previousStatement, statement, 2)) { + if (shouldWriteSeparatingLineTerminator(previousStatement, statement, 2 /* PreserveLines */)) { return false; } previousStatement = statement; @@ -65599,22 +79230,23 @@ var ts; emitBlockFunctionBody(body); } decreaseIndent(); - writeToken(18, body.statements.end, writePunctuation, body); + writeToken(18 /* CloseBraceToken */, body.statements.end, writePunctuation, body); } function emitBlockFunctionBodyOnSingleLine(body) { - emitBlockFunctionBodyWorker(body, true); + emitBlockFunctionBodyWorker(body, /*emitBlockFunctionBodyOnSingleLine*/ true); } function emitBlockFunctionBodyWorker(body, emitBlockFunctionBodyOnSingleLine) { - var statementOffset = emitPrologueDirectives(body.statements, true); + // Emit all the prologue directives (like "use strict"). + var statementOffset = emitPrologueDirectives(body.statements, /*startWithNewLine*/ true); var pos = writer.getTextPos(); emitHelpers(body); if (statementOffset === 0 && pos === writer.getTextPos() && emitBlockFunctionBodyOnSingleLine) { decreaseIndent(); - emitList(body, body.statements, 384); + emitList(body, body.statements, 384 /* SingleLineFunctionBodyStatements */); increaseIndent(); } else { - emitList(body, body.statements, 1, statementOffset); + emitList(body, body.statements, 1 /* MultiLineFunctionBodyStatements */, statementOffset); } } function emitClassDeclaration(node) { @@ -65629,15 +79261,15 @@ var ts; writeSpace(); emitIdentifierName(node.name); } - var indentedFlag = ts.getEmitFlags(node) & 65536; + var indentedFlag = ts.getEmitFlags(node) & 65536 /* Indented */; if (indentedFlag) { increaseIndent(); } emitTypeParameters(node, node.typeParameters); - emitList(node, node.heritageClauses, 0); + emitList(node, node.heritageClauses, 0 /* ClassHeritageClauses */); writeSpace(); writePunctuation("{"); - emitList(node, node.members, 65); + emitList(node, node.members, 65 /* ClassMembers */); writePunctuation("}"); if (indentedFlag) { decreaseIndent(); @@ -65650,10 +79282,10 @@ var ts; writeSpace(); emit(node.name); emitTypeParameters(node, node.typeParameters); - emitList(node, node.heritageClauses, 256); + emitList(node, node.heritageClauses, 256 /* HeritageClauses */); writeSpace(); writePunctuation("{"); - emitList(node, node.members, 65); + emitList(node, node.members, 65 /* InterfaceMembers */); writePunctuation("}"); } function emitTypeAliasDeclaration(node) { @@ -65676,20 +79308,20 @@ var ts; emit(node.name); writeSpace(); writePunctuation("{"); - emitList(node, node.members, 81); + emitList(node, node.members, 81 /* EnumMembers */); writePunctuation("}"); } function emitModuleDeclaration(node) { emitModifiers(node, node.modifiers); - if (~node.flags & 512) { - writeKeyword(node.flags & 16 ? "namespace" : "module"); + if (~node.flags & 512 /* GlobalAugmentation */) { + writeKeyword(node.flags & 16 /* Namespace */ ? "namespace" : "module"); writeSpace(); } emit(node.name); var body = node.body; if (!body) return writeSemicolon(); - while (body.kind === 239) { + while (body.kind === 239 /* ModuleDeclaration */) { writePunctuation("."); emit(body.name); body = body.body; @@ -65700,27 +79332,27 @@ var ts; function emitModuleBlock(node) { pushNameGenerationScope(node); ts.forEach(node.statements, generateNames); - emitBlockStatements(node, isEmptyBlock(node)); + emitBlockStatements(node, /*forceSingleLine*/ isEmptyBlock(node)); popNameGenerationScope(node); } function emitCaseBlock(node) { - emitTokenWithComment(17, node.pos, writePunctuation, node); - emitList(node, node.clauses, 65); - emitTokenWithComment(18, node.clauses.end, writePunctuation, node, true); + emitTokenWithComment(17 /* OpenBraceToken */, node.pos, writePunctuation, node); + emitList(node, node.clauses, 65 /* CaseBlockClauses */); + emitTokenWithComment(18 /* CloseBraceToken */, node.clauses.end, writePunctuation, node, /*indentLeading*/ true); } function emitImportEqualsDeclaration(node) { emitModifiers(node, node.modifiers); - emitTokenWithComment(91, node.modifiers ? node.modifiers.end : node.pos, writeKeyword, node); + emitTokenWithComment(91 /* ImportKeyword */, node.modifiers ? node.modifiers.end : node.pos, writeKeyword, node); writeSpace(); emit(node.name); writeSpace(); - emitTokenWithComment(58, node.name.end, writePunctuation, node); + emitTokenWithComment(58 /* EqualsToken */, node.name.end, writePunctuation, node); writeSpace(); emitModuleReference(node.moduleReference); writeSemicolon(); } function emitModuleReference(node) { - if (node.kind === 71) { + if (node.kind === 71 /* Identifier */) { emitExpression(node); } else { @@ -65729,12 +79361,12 @@ var ts; } function emitImportDeclaration(node) { emitModifiers(node, node.modifiers); - emitTokenWithComment(91, node.modifiers ? node.modifiers.end : node.pos, writeKeyword, node); + emitTokenWithComment(91 /* ImportKeyword */, node.modifiers ? node.modifiers.end : node.pos, writeKeyword, node); writeSpace(); if (node.importClause) { emit(node.importClause); writeSpace(); - emitTokenWithComment(143, node.importClause.end, writeKeyword, node); + emitTokenWithComment(143 /* FromKeyword */, node.importClause.end, writeKeyword, node); writeSpace(); } emitExpression(node.moduleSpecifier); @@ -65743,15 +79375,15 @@ var ts; function emitImportClause(node) { emit(node.name); if (node.name && node.namedBindings) { - emitTokenWithComment(26, node.name.end, writePunctuation, node); + emitTokenWithComment(26 /* CommaToken */, node.name.end, writePunctuation, node); writeSpace(); } emit(node.namedBindings); } function emitNamespaceImport(node) { - var asPos = emitTokenWithComment(39, node.pos, writePunctuation, node); + var asPos = emitTokenWithComment(39 /* AsteriskToken */, node.pos, writePunctuation, node); writeSpace(); - emitTokenWithComment(118, asPos, writeKeyword, node); + emitTokenWithComment(118 /* AsKeyword */, asPos, writeKeyword, node); writeSpace(); emit(node.name); } @@ -65762,42 +79394,42 @@ var ts; emitImportOrExportSpecifier(node); } function emitExportAssignment(node) { - var nextPos = emitTokenWithComment(84, node.pos, writeKeyword, node); + var nextPos = emitTokenWithComment(84 /* ExportKeyword */, node.pos, writeKeyword, node); writeSpace(); if (node.isExportEquals) { - emitTokenWithComment(58, nextPos, writeOperator, node); + emitTokenWithComment(58 /* EqualsToken */, nextPos, writeOperator, node); } else { - emitTokenWithComment(79, nextPos, writeKeyword, node); + emitTokenWithComment(79 /* DefaultKeyword */, nextPos, writeKeyword, node); } writeSpace(); emitExpression(node.expression); writeSemicolon(); } function emitExportDeclaration(node) { - var nextPos = emitTokenWithComment(84, node.pos, writeKeyword, node); + var nextPos = emitTokenWithComment(84 /* ExportKeyword */, node.pos, writeKeyword, node); writeSpace(); if (node.exportClause) { emit(node.exportClause); } else { - nextPos = emitTokenWithComment(39, nextPos, writePunctuation, node); + nextPos = emitTokenWithComment(39 /* AsteriskToken */, nextPos, writePunctuation, node); } if (node.moduleSpecifier) { writeSpace(); var fromPos = node.exportClause ? node.exportClause.end : nextPos; - emitTokenWithComment(143, fromPos, writeKeyword, node); + emitTokenWithComment(143 /* FromKeyword */, fromPos, writeKeyword, node); writeSpace(); emitExpression(node.moduleSpecifier); } writeSemicolon(); } function emitNamespaceExportDeclaration(node) { - var nextPos = emitTokenWithComment(84, node.pos, writeKeyword, node); + var nextPos = emitTokenWithComment(84 /* ExportKeyword */, node.pos, writeKeyword, node); writeSpace(); - nextPos = emitTokenWithComment(118, nextPos, writeKeyword, node); + nextPos = emitTokenWithComment(118 /* AsKeyword */, nextPos, writeKeyword, node); writeSpace(); - nextPos = emitTokenWithComment(130, nextPos, writeKeyword, node); + nextPos = emitTokenWithComment(130 /* NamespaceKeyword */, nextPos, writeKeyword, node); writeSpace(); emit(node.name); writeSemicolon(); @@ -65810,27 +79442,33 @@ var ts; } function emitNamedImportsOrExports(node) { writePunctuation("{"); - emitList(node, node.elements, 262576); + emitList(node, node.elements, 262576 /* NamedImportsOrExportsElements */); writePunctuation("}"); } function emitImportOrExportSpecifier(node) { if (node.propertyName) { emit(node.propertyName); writeSpace(); - emitTokenWithComment(118, node.propertyName.end, writeKeyword, node); + emitTokenWithComment(118 /* AsKeyword */, node.propertyName.end, writeKeyword, node); writeSpace(); } emit(node.name); } + // + // Module references + // function emitExternalModuleReference(node) { writeKeyword("require"); writePunctuation("("); emitExpression(node.expression); writePunctuation(")"); } + // + // JSX + // function emitJsxElement(node) { emit(node.openingElement); - emitList(node, node.children, 131072); + emitList(node, node.children, 131072 /* JsxElementOrFragmentChildren */); emit(node.closingElement); } function emitJsxSelfClosingElement(node) { @@ -65842,7 +79480,7 @@ var ts; } function emitJsxFragment(node) { emit(node.openingFragment); - emitList(node, node.children, 131072); + emitList(node, node.children, 131072 /* JsxElementOrFragmentChildren */); emit(node.closingFragment); } function emitJsxOpeningElementOrFragment(node) { @@ -65858,7 +79496,7 @@ var ts; } function emitJsxText(node) { commitPendingSemicolon(); - writer.writeLiteral(getTextOfNode(node, true)); + writer.writeLiteral(getTextOfNode(node, /*includeTrivia*/ true)); } function emitJsxClosingElementOrFragment(node) { writePunctuation(""); } function emitJsxAttributes(node) { - emitList(node, node.properties, 131328); + emitList(node, node.properties, 131328 /* JsxElementAttributes */); } function emitJsxAttribute(node) { emit(node.name); - emitNodeWithPrefix("=", writePunctuation, node.initializer, emit); + emitNodeWithPrefix("=", writePunctuation, node.initializer, emit); // TODO: GH#18217 } function emitJsxSpreadAttribute(node) { writePunctuation("{..."); @@ -65888,36 +79526,41 @@ var ts; } } function emitJsxTagName(node) { - if (node.kind === 71) { + if (node.kind === 71 /* Identifier */) { emitExpression(node); } else { emit(node); } } + // + // Clauses + // function emitCaseClause(node) { - emitTokenWithComment(73, node.pos, writeKeyword, node); + emitTokenWithComment(73 /* CaseKeyword */, node.pos, writeKeyword, node); writeSpace(); emitExpression(node.expression); emitCaseOrDefaultClauseRest(node, node.statements, node.expression.end); } function emitDefaultClause(node) { - var pos = emitTokenWithComment(79, node.pos, writeKeyword, node); + var pos = emitTokenWithComment(79 /* DefaultKeyword */, node.pos, writeKeyword, node); emitCaseOrDefaultClauseRest(node, node.statements, pos); } function emitCaseOrDefaultClauseRest(parentNode, statements, colonPos) { var emitAsSingleStatement = statements.length === 1 && - (ts.nodeIsSynthesized(parentNode) || + ( + // treat synthesized nodes as located on the same line for emit purposes + ts.nodeIsSynthesized(parentNode) || ts.nodeIsSynthesized(statements[0]) || ts.rangeStartPositionsAreOnSameLine(parentNode, statements[0], currentSourceFile)); - var format = 81985; + var format = 81985 /* CaseOrDefaultClauseStatements */; if (emitAsSingleStatement) { - writeToken(56, colonPos, writePunctuation, parentNode); + writeToken(56 /* ColonToken */, colonPos, writePunctuation, parentNode); writeSpace(); - format &= ~(1 | 64); + format &= ~(1 /* MultiLine */ | 64 /* Indented */); } else { - emitTokenWithComment(56, colonPos, writePunctuation, parentNode); + emitTokenWithComment(56 /* ColonToken */, colonPos, writePunctuation, parentNode); } emitList(parentNode, statements, format); } @@ -65925,25 +79568,35 @@ var ts; writeSpace(); writeTokenText(node.token, writeKeyword); writeSpace(); - emitList(node, node.types, 272); + emitList(node, node.types, 272 /* HeritageClauseTypes */); } function emitCatchClause(node) { - var openParenPos = emitTokenWithComment(74, node.pos, writeKeyword, node); + var openParenPos = emitTokenWithComment(74 /* CatchKeyword */, node.pos, writeKeyword, node); writeSpace(); if (node.variableDeclaration) { - emitTokenWithComment(19, openParenPos, writePunctuation, node); + emitTokenWithComment(19 /* OpenParenToken */, openParenPos, writePunctuation, node); emit(node.variableDeclaration); - emitTokenWithComment(20, node.variableDeclaration.end, writePunctuation, node); + emitTokenWithComment(20 /* CloseParenToken */, node.variableDeclaration.end, writePunctuation, node); writeSpace(); } emit(node.block); } + // + // Property assignments + // function emitPropertyAssignment(node) { emit(node.name); writePunctuation(":"); writeSpace(); + // This is to ensure that we emit comment in the following case: + // For example: + // obj = { + // id: /*comment1*/ ()=>void + // } + // "comment1" is not considered to be leading comment for node.initializer + // but rather a trailing comment on the previous node. var initializer = node.initializer; - if (emitTrailingCommentsOfPosition && (ts.getEmitFlags(initializer) & 512) === 0) { + if (emitTrailingCommentsOfPosition && (ts.getEmitFlags(initializer) & 512 /* NoLeadingComments */) === 0) { var commentRange = ts.getCommentRange(initializer); emitTrailingCommentsOfPosition(commentRange.pos); } @@ -65964,14 +79617,22 @@ var ts; emitExpression(node.expression); } } + // + // Enum + // function emitEnumMember(node) { emit(node.name); emitInitializer(node.initializer, node.name.end, node); } + // + // Top-level nodes + // function emitSourceFile(node) { writeLine(); var statements = node.statements; if (emitBodyWithDetachedComments) { + // Emit detached comment if there are no prologue directives or if the first node is synthesized. + // The synthesized node will have no leading comment so some comments may be missed. var shouldEmitDetachedComment = statements.length === 0 || !ts.isPrologueDirective(statements[0]) || ts.nodeIsSynthesized(statements[0]); @@ -66028,15 +79689,20 @@ var ts; emitHelpers(node); var index = ts.findIndex(statements, function (statement) { return !ts.isPrologueDirective(statement); }); emitTripleSlashDirectivesIfNeeded(node); - emitList(node, statements, 1, index === -1 ? statements.length : index); + emitList(node, statements, 1 /* MultiLine */, index === -1 ? statements.length : index); popNameGenerationScope(node); } + // Transformation nodes function emitPartiallyEmittedExpression(node) { emitExpression(node.expression); } function emitCommaList(node) { - emitExpressionList(node, node.elements, 272); + emitExpressionList(node, node.elements, 272 /* CommaListElements */); } + /** + * Emits any prologue directives at the start of a Statement list, returning the + * number of prologue directives written to the output. + */ function emitPrologueDirectives(statements, startWithNewLine, seenPrologueDirectives) { for (var i = 0; i < statements.length; i++) { var statement = statements[i]; @@ -66053,6 +79719,7 @@ var ts; } } else { + // return index of the first non prologue directive return i; } } @@ -66068,7 +79735,7 @@ var ts; for (var _a = 0, _b = sourceFileOrBundle.sourceFiles; _a < _b.length; _a++) { var sourceFile = _b[_a]; setSourceFile(sourceFile); - emitPrologueDirectives(sourceFile.statements, true, seenPrologueDirectives); + emitPrologueDirectives(sourceFile.statements, /*startWithNewLine*/ true, seenPrologueDirectives); } } } @@ -66084,12 +79751,16 @@ var ts; else { for (var _a = 0, _b = sourceFileOrBundle.sourceFiles; _a < _b.length; _a++) { var sourceFile = _b[_a]; + // Emit only the first encountered shebang if (emitShebangIfNeeded(sourceFile)) { break; } } } } + // + // Helpers + // function emitNodeWithWriter(node, writer) { if (!node) return; @@ -66100,7 +79771,7 @@ var ts; } function emitModifiers(node, modifiers) { if (modifiers && modifiers.length) { - emitList(node, modifiers, 131328); + emitList(node, modifiers, 131328 /* Modifiers */); writeSpace(); } } @@ -66114,7 +79785,7 @@ var ts; function emitInitializer(node, equalCommentStartPos, container) { if (node) { writeSpace(); - emitTokenWithComment(58, equalCommentStartPos, writeOperator, container); + emitTokenWithComment(58 /* EqualsToken */, equalCommentStartPos, writeOperator, container); writeSpace(); emitExpression(node); } @@ -66144,7 +79815,7 @@ var ts; } } function emitEmbeddedStatement(parent, node) { - if (ts.isBlock(node) || ts.getEmitFlags(parent) & 1) { + if (ts.isBlock(node) || ts.getEmitFlags(parent) & 1 /* SingleLine */) { writeSpace(); emit(node); } @@ -66156,65 +79827,65 @@ var ts; } } function emitDecorators(parentNode, decorators) { - emitList(parentNode, decorators, 24577); + emitList(parentNode, decorators, 24577 /* Decorators */); } function emitTypeArguments(parentNode, typeArguments) { - emitList(parentNode, typeArguments, 26896); + emitList(parentNode, typeArguments, 26896 /* TypeArguments */); } function emitTypeParameters(parentNode, typeParameters) { - if (ts.isFunctionLike(parentNode) && parentNode.typeArguments) { + if (ts.isFunctionLike(parentNode) && parentNode.typeArguments) { // Quick info uses type arguments in place of type parameters on instantiated signatures return emitTypeArguments(parentNode, parentNode.typeArguments); } - emitList(parentNode, typeParameters, 26896); + emitList(parentNode, typeParameters, 26896 /* TypeParameters */); } function emitParameters(parentNode, parameters) { - emitList(parentNode, parameters, 1296); + emitList(parentNode, parameters, 1296 /* Parameters */); } function canEmitSimpleArrowHead(parentNode, parameters) { var parameter = ts.singleOrUndefined(parameters); return parameter - && parameter.pos === parentNode.pos - && !(ts.isArrowFunction(parentNode) && parentNode.type) - && !ts.some(parentNode.decorators) - && !ts.some(parentNode.modifiers) - && !ts.some(parentNode.typeParameters) - && !ts.some(parameter.decorators) - && !ts.some(parameter.modifiers) - && !parameter.dotDotDotToken - && !parameter.questionToken - && !parameter.type - && !parameter.initializer - && ts.isIdentifier(parameter.name); + && parameter.pos === parentNode.pos // may not have parsed tokens between parent and parameter + && !(ts.isArrowFunction(parentNode) && parentNode.type) // arrow function may not have return type annotation + && !ts.some(parentNode.decorators) // parent may not have decorators + && !ts.some(parentNode.modifiers) // parent may not have modifiers + && !ts.some(parentNode.typeParameters) // parent may not have type parameters + && !ts.some(parameter.decorators) // parameter may not have decorators + && !ts.some(parameter.modifiers) // parameter may not have modifiers + && !parameter.dotDotDotToken // parameter may not be rest + && !parameter.questionToken // parameter may not be optional + && !parameter.type // parameter may not have a type annotation + && !parameter.initializer // parameter may not have an initializer + && ts.isIdentifier(parameter.name); // parameter name must be identifier } function emitParametersForArrow(parentNode, parameters) { if (canEmitSimpleArrowHead(parentNode, parameters)) { - emitList(parentNode, parameters, 1296 & ~1024); + emitList(parentNode, parameters, 1296 /* Parameters */ & ~1024 /* Parenthesis */); } else { emitParameters(parentNode, parameters); } } function emitParametersForIndexSignature(parentNode, parameters) { - emitList(parentNode, parameters, 4432); + emitList(parentNode, parameters, 4432 /* IndexSignatureParameters */); } function emitList(parentNode, children, format, start, count) { emitNodeList(emit, parentNode, children, format, start, count); } function emitExpressionList(parentNode, children, format, start, count) { - emitNodeList(emitExpression, parentNode, children, format, start, count); + emitNodeList(emitExpression, parentNode, children, format, start, count); // TODO: GH#18217 } function writeDelimiter(format) { - switch (format & 28) { - case 0: + switch (format & 28 /* DelimitersMask */) { + case 0 /* None */: break; - case 16: + case 16 /* CommaDelimited */: writePunctuation(","); break; - case 4: + case 4 /* BarDelimited */: writeSpace(); writePunctuation("|"); break; - case 8: + case 8 /* AmpersandDelimited */: writeSpace(); writePunctuation("&"); break; @@ -66224,11 +79895,11 @@ var ts; if (start === void 0) { start = 0; } if (count === void 0) { count = children ? children.length - start : 0; } var isUndefined = children === undefined; - if (isUndefined && format & 8192) { + if (isUndefined && format & 8192 /* OptionalIfUndefined */) { return; } var isEmpty = children === undefined || start >= children.length || count === 0; - if (isEmpty && format & 16384) { + if (isEmpty && format & 16384 /* OptionalIfEmpty */) { if (onBeforeEmitNodeArray) { onBeforeEmitNodeArray(children); } @@ -66237,57 +79908,73 @@ var ts; } return; } - if (format & 7680) { + if (format & 7680 /* BracketsMask */) { writePunctuation(getOpeningBracket(format)); if (isEmpty && !isUndefined) { - emitTrailingCommentsOfPosition(children.pos, true); + // TODO: GH#18217 + emitTrailingCommentsOfPosition(children.pos, /*prefixSpace*/ true); // Emit comments within empty bracketed lists } } if (onBeforeEmitNodeArray) { onBeforeEmitNodeArray(children); } if (isEmpty) { - if (format & 1) { + // Write a line terminator if the parent node was multi-line + if (format & 1 /* MultiLine */) { writeLine(); } - else if (format & 128 && !(format & 262144)) { + else if (format & 128 /* SpaceBetweenBraces */ && !(format & 262144 /* NoSpaceIfEmpty */)) { writeSpace(); } } else { - var mayEmitInterveningComments = (format & 131072) === 0; + // Write the opening line terminator or leading whitespace. + var mayEmitInterveningComments = (format & 131072 /* NoInterveningComments */) === 0; var shouldEmitInterveningComments = mayEmitInterveningComments; - if (shouldWriteLeadingLineTerminator(parentNode, children, format)) { + if (shouldWriteLeadingLineTerminator(parentNode, children, format)) { // TODO: GH#18217 writeLine(); shouldEmitInterveningComments = false; } - else if (format & 128) { + else if (format & 128 /* SpaceBetweenBraces */) { writeSpace(); } - if (format & 64) { + // Increase the indent, if requested. + if (format & 64 /* Indented */) { increaseIndent(); } + // Emit each child. var previousSibling = void 0; var shouldDecreaseIndentAfterEmit = false; for (var i = 0; i < count; i++) { var child = children[start + i]; + // Write the delimiter if this is not the first node. if (previousSibling) { - if (format & 28 && previousSibling.end !== parentNode.end) { + // i.e + // function commentedParameters( + // /* Parameter a */ + // a + // /* End of parameter a */ -> this comment isn't considered to be trailing comment of parameter "a" due to newline + // , + if (format & 28 /* DelimitersMask */ && previousSibling.end !== parentNode.end) { emitLeadingCommentsOfPosition(previousSibling.end); } writeDelimiter(format); + // Write either a line terminator or whitespace to separate the elements. if (shouldWriteSeparatingLineTerminator(previousSibling, child, format)) { - if ((format & (3 | 64)) === 0) { + // If a synthesized node in a single-line list starts on a new + // line, we should increase the indent. + if ((format & (3 /* LinesMask */ | 64 /* Indented */)) === 0 /* SingleLine */) { increaseIndent(); shouldDecreaseIndentAfterEmit = true; } writeLine(); shouldEmitInterveningComments = false; } - else if (previousSibling && format & 256) { + else if (previousSibling && format & 256 /* SpaceBetweenSiblings */) { writeSpace(); } } + // Emit this child. if (shouldEmitInterveningComments) { if (emitTrailingCommentsOfPosition) { var commentRange = ts.getCommentRange(child); @@ -66304,29 +79991,39 @@ var ts; } previousSibling = child; } - var hasTrailingComma = (format & 32) && children.hasTrailingComma; - if (format & 16 && hasTrailingComma) { + // Write a trailing comma, if requested. + var hasTrailingComma = (format & 32 /* AllowTrailingComma */) && children.hasTrailingComma; + if (format & 16 /* CommaDelimited */ && hasTrailingComma) { writePunctuation(","); } - if (previousSibling && format & 28 && previousSibling.end !== parentNode.end && !(ts.getEmitFlags(previousSibling) & 1024)) { + // Emit any trailing comment of the last element in the list + // i.e + // var array = [... + // 2 + // /* end of element 2 */ + // ]; + if (previousSibling && format & 28 /* DelimitersMask */ && previousSibling.end !== parentNode.end && !(ts.getEmitFlags(previousSibling) & 1024 /* NoTrailingComments */)) { emitLeadingCommentsOfPosition(previousSibling.end); } - if (format & 64) { + // Decrease the indent, if requested. + if (format & 64 /* Indented */) { decreaseIndent(); } + // Write the closing line terminator or closing whitespace. if (shouldWriteClosingLineTerminator(parentNode, children, format)) { writeLine(); } - else if (format & 128) { + else if (format & 128 /* SpaceBetweenBraces */) { writeSpace(); } } if (onAfterEmitNodeArray) { onAfterEmitNodeArray(children); } - if (format & 7680) { + if (format & 7680 /* BracketsMask */) { if (isEmpty && !isUndefined) { - emitLeadingCommentsOfPosition(children.end); + // TODO: GH#18217 + emitLeadingCommentsOfPosition(children.end); // Emit leading comments within empty lists } writePunctuation(getClosingBracket(format)); } @@ -66415,7 +80112,7 @@ var ts; return pos < 0 ? pos : pos + tokenString.length; } function writeLineOrSpace(node) { - if (ts.getEmitFlags(node) & 1) { + if (ts.getEmitFlags(node) & 1 /* SingleLine */) { writeSpace(); } else { @@ -66444,6 +80141,10 @@ var ts; write(valueToWriteWhenNotIndenting); } } + // Helper function to decrease the indent if we previously indented. Allows multiple + // previous indent values to be considered at a time. This also allows caller to just + // call this once, passing in all their appropriate indent values, instead of needing + // to call this helper function multiple times. function decreaseIndentIf(value1, value2) { if (value1) { decreaseIndent(); @@ -66453,11 +80154,11 @@ var ts; } } function shouldWriteLeadingLineTerminator(parentNode, children, format) { - if (format & 1) { + if (format & 1 /* MultiLine */) { return true; } - if (format & 2) { - if (format & 32768) { + if (format & 2 /* PreserveLines */) { + if (format & 32768 /* PreferNewLine */) { return true; } var firstChild = children[0]; @@ -66476,10 +80177,10 @@ var ts; } } function shouldWriteSeparatingLineTerminator(previousNode, nextNode, format) { - if (format & 1) { + if (format & 1 /* MultiLine */) { return true; } - else if (format & 2) { + else if (format & 2 /* PreserveLines */) { if (previousNode === undefined || nextNode === undefined) { return false; } @@ -66495,11 +80196,11 @@ var ts; } } function shouldWriteClosingLineTerminator(parentNode, children, format) { - if (format & 1) { - return (format & 65536) === 0; + if (format & 1 /* MultiLine */) { + return (format & 65536 /* NoTrailingNewLine */) === 0; } - else if (format & 2) { - if (format & 32768) { + else if (format & 2 /* PreserveLines */) { + if (format & 32768 /* PreferNewLine */) { return true; } var lastChild = ts.lastOrUndefined(children); @@ -66521,16 +80222,17 @@ var ts; if (ts.nodeIsSynthesized(node)) { var startsOnNewLine = ts.getStartsOnNewLine(node); if (startsOnNewLine === undefined) { - return (format & 32768) !== 0; + return (format & 32768 /* PreferNewLine */) !== 0; } return startsOnNewLine; } - return (format & 32768) !== 0; + return (format & 32768 /* PreferNewLine */) !== 0; } function needsIndentation(parent, node1, node2) { parent = skipSynthesizedParentheses(parent); node1 = skipSynthesizedParentheses(node1); node2 = skipSynthesizedParentheses(node2); + // Always use a newline for synthesized code if the synthesizer desires it. if (ts.getStartsOnNewLine(node2)) { return true; } @@ -66544,7 +80246,7 @@ var ts; && ts.rangeEndIsOnSameLineAsRangeStart(block, block, currentSourceFile); } function skipSynthesizedParentheses(node) { - while (node.kind === 191 && ts.nodeIsSynthesized(node)) { + while (node.kind === 191 /* ParenthesizedExpression */ && ts.nodeIsSynthesized(node)) { node = node.expression; } return node; @@ -66556,7 +80258,7 @@ var ts; else if (ts.isIdentifier(node) && (ts.nodeIsSynthesized(node) || !node.parent || !currentSourceFile || (node.parent && currentSourceFile && ts.getSourceFileOfNode(node) !== ts.getOriginalNode(currentSourceFile)))) { return ts.idText(node); } - else if (node.kind === 9 && node.textSourceNode) { + else if (node.kind === 9 /* StringLiteral */ && node.textSourceNode) { return getTextOfNode(node.textSourceNode, includeTrivia); } else if (ts.isLiteralExpression(node) && (ts.nodeIsSynthesized(node) || !node.parent)) { @@ -66565,10 +80267,10 @@ var ts; return ts.getSourceTextOfNodeFromSourceFile(currentSourceFile, node, includeTrivia); } function getLiteralTextOfNode(node) { - if (node.kind === 9 && node.textSourceNode) { + if (node.kind === 9 /* StringLiteral */ && node.textSourceNode) { var textSourceNode = node.textSourceNode; if (ts.isIdentifier(textSourceNode)) { - return ts.getEmitFlags(node) & 16777216 ? + return ts.getEmitFlags(node) & 16777216 /* NoAsciiEscaping */ ? "\"" + ts.escapeString(getTextOfNode(textSourceNode)) + "\"" : "\"" + ts.escapeNonAsciiString(getTextOfNode(textSourceNode)) + "\""; } @@ -66578,16 +80280,22 @@ var ts; } return ts.getLiteralText(node, currentSourceFile); } + /** + * Push a new name generation scope. + */ function pushNameGenerationScope(node) { - if (node && ts.getEmitFlags(node) & 524288) { + if (node && ts.getEmitFlags(node) & 524288 /* ReuseTempVariableScope */) { return; } tempFlagsStack.push(tempFlags); tempFlags = 0; reservedNamesStack.push(reservedNames); } + /** + * Pop the current name generation scope. + */ function popNameGenerationScope(node) { - if (node && ts.getEmitFlags(node) & 524288) { + if (node && ts.getEmitFlags(node) & 524288 /* ReuseTempVariableScope */) { return; } tempFlags = tempFlagsStack.pop(); @@ -66603,81 +80311,81 @@ var ts; if (!node) return; switch (node.kind) { - case 213: + case 213 /* Block */: ts.forEach(node.statements, generateNames); break; - case 228: - case 226: - case 218: - case 219: + case 228 /* LabeledStatement */: + case 226 /* WithStatement */: + case 218 /* DoStatement */: + case 219 /* WhileStatement */: generateNames(node.statement); break; - case 217: + case 217 /* IfStatement */: generateNames(node.thenStatement); generateNames(node.elseStatement); break; - case 220: - case 222: - case 221: + case 220 /* ForStatement */: + case 222 /* ForOfStatement */: + case 221 /* ForInStatement */: generateNames(node.initializer); generateNames(node.statement); break; - case 227: + case 227 /* SwitchStatement */: generateNames(node.caseBlock); break; - case 241: + case 241 /* CaseBlock */: ts.forEach(node.clauses, generateNames); break; - case 266: - case 267: + case 266 /* CaseClause */: + case 267 /* DefaultClause */: ts.forEach(node.statements, generateNames); break; - case 230: + case 230 /* TryStatement */: generateNames(node.tryBlock); generateNames(node.catchClause); generateNames(node.finallyBlock); break; - case 269: + case 269 /* CatchClause */: generateNames(node.variableDeclaration); generateNames(node.block); break; - case 214: + case 214 /* VariableStatement */: generateNames(node.declarationList); break; - case 233: + case 233 /* VariableDeclarationList */: ts.forEach(node.declarations, generateNames); break; - case 232: - case 149: - case 182: - case 235: + case 232 /* VariableDeclaration */: + case 149 /* Parameter */: + case 182 /* BindingElement */: + case 235 /* ClassDeclaration */: generateNameIfNeeded(node.name); break; - case 234: + case 234 /* FunctionDeclaration */: generateNameIfNeeded(node.name); - if (ts.getEmitFlags(node) & 524288) { + if (ts.getEmitFlags(node) & 524288 /* ReuseTempVariableScope */) { ts.forEach(node.parameters, generateNames); generateNames(node.body); } break; - case 180: - case 181: + case 180 /* ObjectBindingPattern */: + case 181 /* ArrayBindingPattern */: ts.forEach(node.elements, generateNames); break; - case 244: + case 244 /* ImportDeclaration */: generateNames(node.importClause); break; - case 245: + case 245 /* ImportClause */: generateNameIfNeeded(node.name); generateNames(node.namedBindings); break; - case 246: + case 246 /* NamespaceImport */: generateNameIfNeeded(node.name); break; - case 247: + case 247 /* NamedImports */: ts.forEach(node.elements, generateNames); break; - case 248: + case 248 /* ImportSpecifier */: generateNameIfNeeded(node.propertyName || node.name); break; } @@ -66686,12 +80394,12 @@ var ts; if (!node) return; switch (node.kind) { - case 270: - case 271: - case 152: - case 154: - case 156: - case 157: + case 270 /* PropertyAssignment */: + case 271 /* ShorthandPropertyAssignment */: + case 152 /* PropertyDeclaration */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: generateNameIfNeeded(node.name); break; } @@ -66706,11 +80414,18 @@ var ts; } } } + /** + * Generate the text for a generated identifier. + */ function generateName(name) { - if ((name.autoGenerateFlags & 7) === 4) { + if ((name.autoGenerateFlags & 7 /* KindMask */) === 4 /* Node */) { + // Node names generate unique names based on their original node + // and are cached based on that node's id. return generateNameCached(getNodeForGeneratedName(name), name.autoGenerateFlags); } else { + // Auto, Loop, and Unique names are cached based on their unique + // autoGenerateId. var autoGenerateId = name.autoGenerateId; return autoGeneratedIdToGeneratedName[autoGenerateId] || (autoGeneratedIdToGeneratedName[autoGenerateId] = makeName(name)); } @@ -66719,28 +80434,44 @@ var ts; var nodeId = ts.getNodeId(node); return nodeIdToGeneratedName[nodeId] || (nodeIdToGeneratedName[nodeId] = generateNameForNode(node, flags)); } + /** + * Returns a value indicating whether a name is unique globally, within the current file, + * or within the NameGenerator. + */ function isUniqueName(name) { return isFileLevelUniqueName(name) && !generatedNames.has(name) && !(reservedNames && reservedNames.has(name)); } + /** + * Returns a value indicating whether a name is unique globally or within the current file. + */ function isFileLevelUniqueName(name) { return currentSourceFile ? ts.isFileLevelUniqueName(currentSourceFile, name, hasGlobalName) : true; } + /** + * Returns a value indicating whether a name is unique within a container. + */ function isUniqueLocalName(name, container) { for (var node = container; ts.isNodeDescendantOf(node, container); node = node.nextContainer) { if (node.locals) { var local = node.locals.get(ts.escapeLeadingUnderscores(name)); - if (local && local.flags & (67216319 | 1048576 | 2097152)) { + // We conservatively include alias symbols to cover cases where they're emitted as locals + if (local && local.flags & (67216319 /* Value */ | 1048576 /* ExportValue */ | 2097152 /* Alias */)) { return false; } } } return true; } + /** + * Return the next available name in the pattern _a ... _z, _0, _1, ... + * TempFlags._i or TempFlags._n may be used to express a preference for that dedicated name. + * Note that names generated by makeTempVariableName and makeUniqueName will never conflict. + */ function makeTempVariableName(flags, reservedInNestedScopes) { if (flags && !(tempFlags & flags)) { - var name = flags === 268435456 ? "_i" : "_n"; + var name = flags === 268435456 /* _i */ ? "_i" : "_n"; if (isUniqueName(name)) { tempFlags |= flags; if (reservedInNestedScopes) { @@ -66750,11 +80481,12 @@ var ts; } } while (true) { - var count = tempFlags & 268435455; + var count = tempFlags & 268435455 /* CountMask */; tempFlags++; + // Skip over 'i' and 'n' if (count !== 8 && count !== 13) { var name = count < 26 - ? "_" + String.fromCharCode(97 + count) + ? "_" + String.fromCharCode(97 /* a */ + count) : "_" + (count - 26); if (isUniqueName(name)) { if (reservedInNestedScopes) { @@ -66765,6 +80497,13 @@ var ts; } } } + /** + * Generate a name that is unique within the current file and doesn't conflict with any names + * in global scope. The name is formed by adding an '_n' suffix to the specified base name, + * where n is a positive integer. Note that names generated by makeTempVariableName and + * makeUniqueName are guaranteed to never conflict. + * If `optimistic` is set, the first instance will use 'baseName' verbatim instead of 'baseName_1' + */ function makeUniqueName(baseName, checkFn, optimistic, scoped) { if (checkFn === void 0) { checkFn = isUniqueName; } if (optimistic) { @@ -66778,7 +80517,8 @@ var ts; return baseName; } } - if (baseName.charCodeAt(baseName.length - 1) !== 95) { + // Find the first unique 'name_n', where n is a positive number + if (baseName.charCodeAt(baseName.length - 1) !== 95 /* _ */) { baseName += "_"; } var i = 1; @@ -66797,21 +80537,34 @@ var ts; } } function makeFileLevelOptmiisticUniqueName(name) { - return makeUniqueName(name, isFileLevelUniqueName, true); + return makeUniqueName(name, isFileLevelUniqueName, /*optimistic*/ true); } + /** + * Generates a unique name for a ModuleDeclaration or EnumDeclaration. + */ function generateNameForModuleOrEnum(node) { var name = getTextOfNode(node.name); + // Use module/enum name itself if it is unique, otherwise make a unique variation return isUniqueLocalName(name, node) ? name : makeUniqueName(name); } + /** + * Generates a unique name for an ImportDeclaration or ExportDeclaration. + */ function generateNameForImportOrExportDeclaration(node) { - var expr = ts.getExternalModuleName(node); + var expr = ts.getExternalModuleName(node); // TODO: GH#18217 var baseName = ts.isStringLiteral(expr) ? ts.makeIdentifierFromModuleName(expr.text) : "module"; return makeUniqueName(baseName); } + /** + * Generates a unique name for a default export. + */ function generateNameForExportDefault() { return makeUniqueName("default"); } + /** + * Generates a unique name for a class expression. + */ function generateNameForClassExpression() { return makeUniqueName("class"); } @@ -66819,74 +80572,87 @@ var ts; if (ts.isIdentifier(node.name)) { return generateNameCached(node.name); } - return makeTempVariableName(0); + return makeTempVariableName(0 /* Auto */); } + /** + * Generates a unique name from a node. + */ function generateNameForNode(node, flags) { switch (node.kind) { - case 71: - return makeUniqueName(getTextOfNode(node), isUniqueName, !!(flags & 16), !!(flags & 8)); - case 239: - case 238: + case 71 /* Identifier */: + return makeUniqueName(getTextOfNode(node), isUniqueName, !!(flags & 16 /* Optimistic */), !!(flags & 8 /* ReservedInNestedScopes */)); + case 239 /* ModuleDeclaration */: + case 238 /* EnumDeclaration */: return generateNameForModuleOrEnum(node); - case 244: - case 250: + case 244 /* ImportDeclaration */: + case 250 /* ExportDeclaration */: return generateNameForImportOrExportDeclaration(node); - case 234: - case 235: - case 249: + case 234 /* FunctionDeclaration */: + case 235 /* ClassDeclaration */: + case 249 /* ExportAssignment */: return generateNameForExportDefault(); - case 205: + case 205 /* ClassExpression */: return generateNameForClassExpression(); - case 154: - case 156: - case 157: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: return generateNameForMethodOrAccessor(node); default: - return makeTempVariableName(0); + return makeTempVariableName(0 /* Auto */); } } + /** + * Generates a unique identifier for a node. + */ function makeName(name) { - switch (name.autoGenerateFlags & 7) { - case 1: - return makeTempVariableName(0, !!(name.autoGenerateFlags & 8)); - case 2: - return makeTempVariableName(268435456, !!(name.autoGenerateFlags & 8)); - case 3: - return makeUniqueName(ts.idText(name), (name.autoGenerateFlags & 32) ? isFileLevelUniqueName : isUniqueName, !!(name.autoGenerateFlags & 16), !!(name.autoGenerateFlags & 8)); + switch (name.autoGenerateFlags & 7 /* KindMask */) { + case 1 /* Auto */: + return makeTempVariableName(0 /* Auto */, !!(name.autoGenerateFlags & 8 /* ReservedInNestedScopes */)); + case 2 /* Loop */: + return makeTempVariableName(268435456 /* _i */, !!(name.autoGenerateFlags & 8 /* ReservedInNestedScopes */)); + case 3 /* Unique */: + return makeUniqueName(ts.idText(name), (name.autoGenerateFlags & 32 /* FileLevel */) ? isFileLevelUniqueName : isUniqueName, !!(name.autoGenerateFlags & 16 /* Optimistic */), !!(name.autoGenerateFlags & 8 /* ReservedInNestedScopes */)); } return ts.Debug.fail("Unsupported GeneratedIdentifierKind."); } + /** + * Gets the node from which a name should be generated. + */ function getNodeForGeneratedName(name) { var autoGenerateId = name.autoGenerateId; var node = name; var original = node.original; while (original) { node = original; + // if "node" is a different generated name (having a different + // "autoGenerateId"), use it and stop traversing. if (ts.isIdentifier(node) - && !!(node.autoGenerateFlags & 4) + && !!(node.autoGenerateFlags & 4 /* Node */) && node.autoGenerateId !== autoGenerateId) { break; } original = node.original; } + // otherwise, return the original node for the source; return node; } } ts.createPrinter = createPrinter; function createBracketsMap() { var brackets = []; - brackets[512] = ["{", "}"]; - brackets[1024] = ["(", ")"]; - brackets[2048] = ["<", ">"]; - brackets[4096] = ["[", "]"]; + brackets[512 /* Braces */] = ["{", "}"]; + brackets[1024 /* Parenthesis */] = ["(", ")"]; + brackets[2048 /* AngleBrackets */] = ["<", ">"]; + brackets[4096 /* SquareBrackets */] = ["[", "]"]; return brackets; } function getOpeningBracket(format) { - return brackets[format & 7680][0]; + return brackets[format & 7680 /* BracketsMask */][0]; } function getClosingBracket(format) { - return brackets[format & 7680][1]; + return brackets[format & 7680 /* BracketsMask */][1]; } + // Flags enum to track count of temp variables and a few dedicated names var TempFlags; (function (TempFlags) { TempFlags[TempFlags["Auto"] = 0] = "Auto"; @@ -66894,6 +80660,7 @@ var ts; TempFlags[TempFlags["_i"] = 268435456] = "_i"; })(TempFlags || (TempFlags = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { function createCachedDirectoryStructureHost(host, currentDirectory, useCaseSensitiveFileNames) { @@ -66929,12 +80696,17 @@ var ts; } function createCachedFileSystemEntries(rootDir, rootDirPath) { var resultFromHost = { - files: ts.map(host.readDirectory(rootDir, undefined, undefined, ["*.*"]), getBaseNameOfFileName) || [], + files: ts.map(host.readDirectory(rootDir, /*extensions*/ undefined, /*exclude*/ undefined, /*include*/ ["*.*"]), getBaseNameOfFileName) || [], directories: host.getDirectories(rootDir) || [] }; cachedReadDirectoryResult.set(ts.ensureTrailingDirectorySeparator(rootDirPath), resultFromHost); return resultFromHost; } + /** + * If the readDirectory result was already cached, it returns that + * Otherwise gets result from host and caches it. + * The host request is done under try catch block to avoid caching incorrect result + */ function tryReadDirectory(rootDir, rootDirPath) { rootDirPath = ts.ensureTrailingDirectorySeparator(rootDirPath); var cachedResult = getCachedFileSystemEntries(rootDirPath); @@ -66945,6 +80717,7 @@ var ts; return createCachedFileSystemEntries(rootDir, rootDirPath); } catch (_e) { + // If there is exception to read directories, dont cache the result and direct the calls to host ts.Debug.assert(!cachedReadDirectoryResult.has(ts.ensureTrailingDirectorySeparator(rootDirPath))); return undefined; } @@ -66969,7 +80742,7 @@ var ts; var path = toPath(fileName); var result = getCachedFileSystemEntriesForBaseDir(path); if (result) { - updateFilesOfFileSystemEntry(result, getBaseNameOfFileName(fileName), true); + updateFilesOfFileSystemEntry(result, getBaseNameOfFileName(fileName), /*fileExists*/ true); } return host.writeFile(fileName, data, writeByteOrderMark); } @@ -66988,7 +80761,7 @@ var ts; var result = getCachedFileSystemEntriesForBaseDir(path); var baseFileName = getBaseNameOfFileName(dirPath); if (result) { - updateFileSystemEntry(result.directories, baseFileName, true); + updateFileSystemEntry(result.directories, baseFileName, /*isValid*/ true); } host.createDirectory(dirPath); } @@ -67018,6 +80791,8 @@ var ts; function addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath) { var existingResult = getCachedFileSystemEntries(fileOrDirectoryPath); if (existingResult) { + // Just clear the cache for now + // For now just clear the cache, since this could mean that multiple level entries might need to be re-evaluated clearCache(); return undefined; } @@ -67025,7 +80800,10 @@ var ts; if (!parentResult) { return undefined; } + // This was earlier a file (hence not in cached directory contents) + // or we never cached the directory containing it if (!host.directoryExists) { + // Since host doesnt support directory exists, clear the cache as otherwise it might not be same clearCache(); return undefined; } @@ -67035,9 +80813,11 @@ var ts; directoryExists: host.directoryExists(fileOrDirectoryPath) }; if (fsQueryResult.directoryExists || hasEntry(parentResult.directories, baseName)) { + // Folder added or removed, clear the cache instead of updating the folder and its structure clearCache(); } else { + // No need to update the directory structure, just files updateFilesOfFileSystemEntry(parentResult, baseName, fsQueryResult.fileExists); } return fsQueryResult; @@ -67062,31 +80842,51 @@ var ts; var ConfigFileProgramReloadLevel; (function (ConfigFileProgramReloadLevel) { ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["None"] = 0] = "None"; + /** Update the file name list from the disk */ ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Partial"] = 1] = "Partial"; + /** Reload completely by re-reading contents of config file from disk and updating program */ ConfigFileProgramReloadLevel[ConfigFileProgramReloadLevel["Full"] = 2] = "Full"; })(ConfigFileProgramReloadLevel = ts.ConfigFileProgramReloadLevel || (ts.ConfigFileProgramReloadLevel = {})); + /** + * Updates the existing missing file watches with the new set of missing files after new program is created + */ function updateMissingFilePathsWatch(program, missingFileWatches, createMissingFileWatch) { var missingFilePaths = program.getMissingFilePaths(); var newMissingFilePathMap = ts.arrayToSet(missingFilePaths); + // Update the missing file paths watcher ts.mutateMap(missingFileWatches, newMissingFilePathMap, { + // Watch the missing files createNewValue: createMissingFileWatch, + // Files that are no longer missing (e.g. because they are no longer required) + // should no longer be watched. onDeleteValue: ts.closeFileWatcher }); } ts.updateMissingFilePathsWatch = updateMissingFilePathsWatch; + /** + * Updates the existing wild card directory watches with the new set of wild card directories from the config file + * after new program is created because the config file was reloaded or program was created first time from the config file + * Note that there is no need to call this function when the program is updated with additional files without reloading config files, + * as wildcard directories wont change unless reloading config file + */ function updateWatchingWildcardDirectories(existingWatchedForWildcards, wildcardDirectories, watchDirectory) { ts.mutateMap(existingWatchedForWildcards, wildcardDirectories, { + // Create new watch and recursive info createNewValue: createWildcardDirectoryWatcher, + // Close existing watch thats not needed any more onDeleteValue: closeFileWatcherOf, + // Close existing watch that doesnt match in the flags onExistingValue: updateWildcardDirectoryWatcher }); function createWildcardDirectoryWatcher(directory, flags) { + // Create new watch and recursive info return { watcher: watchDirectory(directory, flags), flags: flags }; } function updateWildcardDirectoryWatcher(existingWatcher, flags, directory) { + // Watcher needs to be updated if the recursive flags dont match if (existingWatcher.flags === flags) { return; } @@ -67118,13 +80918,13 @@ var ts; var createDirectoryWatcher = getCreateFileWatcher(watchLogLevel, watchDirectory); return { watchFile: function (host, file, callback, pollingInterval, detailInfo1, detailInfo2) { - return createFileWatcher(host, file, callback, pollingInterval, undefined, detailInfo1, detailInfo2, watchFile, log, "FileWatcher", getDetailWatchInfo); + return createFileWatcher(host, file, callback, pollingInterval, /*passThrough*/ undefined, detailInfo1, detailInfo2, watchFile, log, "FileWatcher", getDetailWatchInfo); }, watchFilePath: function (host, file, callback, pollingInterval, path, detailInfo1, detailInfo2) { return createFilePathWatcher(host, file, callback, pollingInterval, path, detailInfo1, detailInfo2, watchFile, log, "FileWatcher", getDetailWatchInfo); }, watchDirectory: function (host, directory, callback, flags, detailInfo1, detailInfo2) { - return createDirectoryWatcher(host, directory, callback, flags, undefined, detailInfo1, detailInfo2, watchDirectory, log, "DirectoryWatcher", getDetailWatchInfo); + return createDirectoryWatcher(host, directory, callback, flags, /*passThrough*/ undefined, detailInfo1, detailInfo2, watchDirectory, log, "DirectoryWatcher", getDetailWatchInfo); } }; function watchFilePath(host, file, callback, pollingInterval, path) { @@ -67135,7 +80935,7 @@ var ts; return host.watchFile(file, callback, pollingInterval); } function watchDirectory(host, directory, callback, flags) { - return host.watchDirectory(directory, callback, (flags & 1) !== 0); + return host.watchDirectory(directory, callback, (flags & 1 /* Recursive */) !== 0); } function getCreateFileWatcher(watchLogLevel, addWatch) { switch (watchLogLevel) { @@ -67192,12 +80992,15 @@ var ts; return ts.normalizePath(referencedFileName); } ts.resolveTripleslashReference = resolveTripleslashReference; + /* @internal */ function computeCommonSourceDirectoryOfFilenames(fileNames, currentDirectory, getCanonicalFileName) { var commonPathComponents; var failed = ts.forEach(fileNames, function (sourceFile) { + // Each file contributes into common source file path var sourcePathComponents = ts.getNormalizedPathComponents(sourceFile, currentDirectory); - sourcePathComponents.pop(); + sourcePathComponents.pop(); // The base file name is not part of the common directory path if (!commonPathComponents) { + // first file commonPathComponents = sourcePathComponents; return; } @@ -67205,20 +81008,24 @@ var ts; for (var i = 0; i < n; i++) { if (getCanonicalFileName(commonPathComponents[i]) !== getCanonicalFileName(sourcePathComponents[i])) { if (i === 0) { + // Failed to find any common path component return true; } + // New common path found that is 0 -> i-1 commonPathComponents.length = i; break; } } + // If the sourcePathComponents was shorter than the commonPathComponents, truncate to the sourcePathComponents if (sourcePathComponents.length < commonPathComponents.length) { commonPathComponents.length = sourcePathComponents.length; } }); + // A common path can not be found when paths span multiple drives on windows, for example if (failed) { return ""; } - if (!commonPathComponents) { + if (!commonPathComponents) { // Can happen when all input files are .d.ts files return currentDirectory; } return ts.getPathFromPathComponents(commonPathComponents); @@ -67227,6 +81034,8 @@ var ts; function createCompilerHost(options, setParentNodes) { var existingDirectories = ts.createMap(); function getCanonicalFileName(fileName) { + // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form. + // otherwise use toLowerCase as a canonical form. return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); } function getSourceFile(fileName, languageVersion, onError) { @@ -67267,10 +81076,11 @@ var ts; if (!outputFingerprints) { outputFingerprints = ts.createMap(); } - var hash = ts.sys.createHash(data); - var mtimeBefore = ts.sys.getModifiedTime(fileName); + var hash = ts.sys.createHash(data); // TODO: GH#18217 + var mtimeBefore = ts.sys.getModifiedTime(fileName); // TODO: GH#18217 if (mtimeBefore) { var fingerprint = outputFingerprints.get(fileName); + // If output has not been changed, and the file has no external modification if (fingerprint && fingerprint.byteOrderMark === writeByteOrderMark && fingerprint.hash === hash && @@ -67279,7 +81089,7 @@ var ts; } } ts.sys.writeFile(fileName, data, writeByteOrderMark); - var mtimeAfter = ts.sys.getModifiedTime(fileName); + var mtimeAfter = ts.sys.getModifiedTime(fileName); // TODO: GH#18217 outputFingerprints.set(fileName, { hash: hash, byteOrderMark: writeByteOrderMark, @@ -67353,7 +81163,7 @@ var ts; function formatDiagnostic(diagnostic, host) { var errorMessage = ts.diagnosticCategoryName(diagnostic) + " TS" + diagnostic.code + ": " + flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine()) + host.getNewLine(); if (diagnostic.file) { - var _a = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start), line = _a.line, character = _a.character; + var _a = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start), line = _a.line, character = _a.character; // TODO: GH#18217 var fileName = diagnostic.file.fileName; var relativeFileName = ts.convertToRelativePath(fileName, host.getCurrentDirectory(), function (fileName) { return host.getCanonicalFileName(fileName); }); return relativeFileName + "(" + (line + 1) + "," + (character + 1) + "): " + errorMessage; @@ -67361,6 +81171,7 @@ var ts; return errorMessage; } ts.formatDiagnostic = formatDiagnostic; + /** @internal */ var ForegroundColorEscapeSequences; (function (ForegroundColorEscapeSequences) { ForegroundColorEscapeSequences["Grey"] = "\u001B[90m"; @@ -67383,6 +81194,7 @@ var ts; case ts.DiagnosticCategory.Message: return ForegroundColorEscapeSequences.Blue; } } + /** @internal */ function formatColorAndReset(text, formatStyle) { return formatStyle + text + resetEscapeSequence; } @@ -67405,6 +81217,8 @@ var ts; var context = ""; for (var i = firstLine; i <= lastLine; i++) { context += host.getNewLine(); + // If the error spans over 5 lines, we'll only show the first 2 and last 2 lines, + // so we'll skip ahead to the second-to-last line. if (hasMoreThanFiveLines && firstLine + 1 < i && i < lastLine - 1) { context += indent + formatColorAndReset(padLeft(ellipsis, gutterWidth), gutterStyleSequence) + gutterSeparator + host.getNewLine(); i = lastLine - 1; @@ -67412,13 +81226,17 @@ var ts; var lineStart = ts.getPositionOfLineAndCharacter(file, i, 0); var lineEnd = i < lastLineInFile ? ts.getPositionOfLineAndCharacter(file, i + 1, 0) : file.text.length; var lineContent = file.text.slice(lineStart, lineEnd); - lineContent = lineContent.replace(/\s+$/g, ""); - lineContent = lineContent.replace("\t", " "); + lineContent = lineContent.replace(/\s+$/g, ""); // trim from end + lineContent = lineContent.replace("\t", " "); // convert tabs to single spaces + // Output the gutter and the actual contents of the line. context += indent + formatColorAndReset(padLeft(i + 1 + "", gutterWidth), gutterStyleSequence) + gutterSeparator; context += lineContent + host.getNewLine(); + // Output the gutter and the error span for the line using tildes. context += indent + formatColorAndReset(padLeft("", gutterWidth), gutterStyleSequence) + gutterSeparator; context += squiggleColor; if (i === firstLine) { + // If we're on the last line, then limit it to the last character of the last line. + // Otherwise, we'll just squiggle the rest of the line, giving 'slice' no end position. var lastCharForLine = i === lastLine ? lastLineChar : undefined; context += lineContent.slice(0, firstLineChar).replace(/\S/g, " "); context += lineContent.slice(firstLineChar, lastCharForLine).replace(/./g, "~"); @@ -67427,6 +81245,7 @@ var ts; context += lineContent.slice(0, lastLineChar).replace(/./g, "~"); } else { + // Squiggle the entire line. context += lineContent.replace(/./g, "~"); } context += resetEscapeSequence; @@ -67434,7 +81253,7 @@ var ts; return context; } function formatLocation(file, start, host) { - var _a = ts.getLineAndCharacterOfPosition(file, start), firstLine = _a.line, firstLineChar = _a.character; + var _a = ts.getLineAndCharacterOfPosition(file, start), firstLine = _a.line, firstLineChar = _a.character; // TODO: GH#18217 var relativeFileName = host ? ts.convertToRelativePath(file.fileName, host.getCurrentDirectory(), function (fileName) { return host.getCanonicalFileName(fileName); }) : file.fileName; var output = ""; output += formatColorAndReset(relativeFileName, ForegroundColorEscapeSequences.Cyan); @@ -67450,7 +81269,7 @@ var ts; var diagnostic = diagnostics_2[_i]; if (diagnostic.file) { var file = diagnostic.file, start = diagnostic.start; - output += formatLocation(file, start, host); + output += formatLocation(file, start, host); // TODO: GH#18217 output += " - "; } output += formatColorAndReset(ts.diagnosticCategoryName(diagnostic), getCategoryFormat(diagnostic.category)); @@ -67458,15 +81277,15 @@ var ts; output += flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine()); if (diagnostic.file) { output += host.getNewLine(); - output += formatCodeSpan(diagnostic.file, diagnostic.start, diagnostic.length, "", getCategoryFormat(diagnostic.category), host); + output += formatCodeSpan(diagnostic.file, diagnostic.start, diagnostic.length, "", getCategoryFormat(diagnostic.category), host); // TODO: GH#18217 if (diagnostic.relatedInformation) { output += host.getNewLine(); for (var _a = 0, _b = diagnostic.relatedInformation; _a < _b.length; _a++) { var _c = _b[_a], file = _c.file, start = _c.start, length_4 = _c.length, messageText = _c.messageText; if (file) { output += host.getNewLine(); - output += halfIndent + formatLocation(file, start, host); - output += formatCodeSpan(file, start, length_4, indent, ForegroundColorEscapeSequences.Cyan, host); + output += halfIndent + formatLocation(file, start, host); // TODO: GH#18217 + output += formatCodeSpan(file, start, length_4, indent, ForegroundColorEscapeSequences.Cyan, host); // TODO: GH#18217 } output += host.getNewLine(); output += indent + flattenDiagnosticMessageText(messageText, host.getNewLine()); @@ -67520,23 +81339,34 @@ var ts; } return resolutions; } + /** + * Determines if program structure is upto date or needs to be recreated + */ + /* @internal */ function isProgramUptoDate(program, rootFileNames, newOptions, getSourceVersion, fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames) { + // If we haven't created a program yet or have changed automatic type directives, then it is not up-to-date if (!program || hasChangedAutomaticTypeDirectiveNames) { return false; } + // If number of files in the program do not match, it is not up-to-date if (program.getRootFileNames().length !== rootFileNames.length) { return false; } + // If any file is not up-to-date, then the whole program is not up-to-date if (program.getSourceFiles().some(sourceFileNotUptoDate)) { return false; } + // If any of the missing file paths are now created if (program.getMissingFilePaths().some(fileExists)) { return false; } var currentOptions = program.getCompilerOptions(); + // If the compilation settings do no match, then the program is not up-to-date if (!ts.compareDataObjects(currentOptions, newOptions)) { return false; } + // If everything matches but the text of config file is changed, + // error locations can change for program options, so update the program if (currentOptions.configFile && newOptions.configFile) { return currentOptions.configFile.text === newOptions.configFile.text; } @@ -67552,7 +81382,12 @@ var ts; configFileParseResult.errors; } ts.getConfigFileParsingDiagnostics = getConfigFileParsingDiagnostics; + /** + * Determined if source file needs to be re-created even if its text hasn't changed + */ function shouldProgramCreateNewSourceFiles(program, newOptions) { + // If any of these options change, we can't reuse old source file even if version match + // The change in options like these could result in change in syntax tree change var oldOptions = program && program.getCompilerOptions(); return oldOptions && (oldOptions.target !== newOptions.target || oldOptions.module !== newOptions.module || @@ -67574,7 +81409,7 @@ var ts; }; } function createProgram(rootNamesOrOptions, _options, _host, _oldProgram, _configFileParsingDiagnostics) { - var createProgramOptions = ts.isArray(rootNamesOrOptions) ? createCreateProgramOptions(rootNamesOrOptions, _options, _host, _oldProgram, _configFileParsingDiagnostics) : rootNamesOrOptions; + var createProgramOptions = ts.isArray(rootNamesOrOptions) ? createCreateProgramOptions(rootNamesOrOptions, _options, _host, _oldProgram, _configFileParsingDiagnostics) : rootNamesOrOptions; // TODO: GH#18217 var rootNames = createProgramOptions.rootNames, options = createProgramOptions.options, configFileParsingDiagnostics = createProgramOptions.configFileParsingDiagnostics, projectReferences = createProgramOptions.projectReferences; var oldProgram = createProgramOptions.oldProgram; var program; @@ -67590,9 +81425,19 @@ var ts; var cachedDeclarationDiagnosticsForFile = {}; var resolvedTypeReferenceDirectives = ts.createMap(); var fileProcessingDiagnostics = ts.createDiagnosticCollection(); + // The below settings are to track if a .js file should be add to the program if loaded via searching under node_modules. + // This works as imported modules are discovered recursively in a depth first manner, specifically: + // - For each root file, findSourceFile is called. + // - This calls processImportedModules for each module imported in the source file. + // - This calls resolveModuleNames, and then calls findSourceFile for each resolved module. + // As all these operations happen - and are nested - within the createProgram call, they close over the below variables. + // The current resolution depth is tracked by incrementing/decrementing as the depth first search progresses. var maxNodeModuleJsDepth = typeof options.maxNodeModuleJsDepth === "number" ? options.maxNodeModuleJsDepth : 0; var currentNodeModulesDepth = 0; + // If a module has some of its imports skipped due to being at the depth limit under node_modules, then track + // this, as it may be imported at a shallower depth later, and then it will need its skipped imports processed. var modulesWithElidedImports = ts.createMap(); + // Track source files that are source files found by searching under node_modules, as these shouldn't be compiled. var sourceFilesFoundSearchingNodeModules = ts.createMap(); ts.performance.mark("beforeProgram"); var host = createProgramOptions.host || createCompilerHost(options); @@ -67603,6 +81448,7 @@ var ts; var programDiagnostics = ts.createDiagnosticCollection(); var currentDirectory = host.getCurrentDirectory(); var supportedExtensions = ts.getSupportedExtensions(options); + // Map storing if there is emit blocking diagnostics for given input var hasEmitBlockingDiagnostics = ts.createMap(); var _compilerOptionsObjectLiteralSyntax; var _referencesArrayLiteralSyntax; @@ -67611,6 +81457,7 @@ var ts; var hasInvalidatedResolution = host.hasInvalidatedResolution || ts.returnFalse; if (host.resolveModuleNames) { resolveModuleNamesWorker = function (moduleNames, containingFile, reusedNames) { return host.resolveModuleNames(ts.Debug.assertEachDefined(moduleNames), containingFile, reusedNames).map(function (resolved) { + // An older host may have omitted extension, in which case we should infer it from the file extension of resolvedFileName. if (!resolved || resolved.extension !== undefined) { return resolved; } @@ -67621,7 +81468,7 @@ var ts; } else { moduleResolutionCache = ts.createModuleResolutionCache(currentDirectory, function (x) { return host.getCanonicalFileName(x); }); - var loader_1 = function (moduleName, containingFile) { return ts.resolveModuleName(moduleName, containingFile, options, host, moduleResolutionCache).resolvedModule; }; + var loader_1 = function (moduleName, containingFile) { return ts.resolveModuleName(moduleName, containingFile, options, host, moduleResolutionCache).resolvedModule; }; // TODO: GH#18217 resolveModuleNamesWorker = function (moduleNames, containingFile) { return loadWithLocalCache(ts.Debug.assertEachDefined(moduleNames), containingFile, loader_1); }; } var resolveTypeReferenceDirectiveNamesWorker; @@ -67629,20 +81476,27 @@ var ts; resolveTypeReferenceDirectiveNamesWorker = function (typeDirectiveNames, containingFile) { return host.resolveTypeReferenceDirectives(ts.Debug.assertEachDefined(typeDirectiveNames), containingFile); }; } else { - var loader_2 = function (typesRef, containingFile) { return ts.resolveTypeReferenceDirective(typesRef, containingFile, options, host).resolvedTypeReferenceDirective; }; + var loader_2 = function (typesRef, containingFile) { return ts.resolveTypeReferenceDirective(typesRef, containingFile, options, host).resolvedTypeReferenceDirective; }; // TODO: GH#18217 resolveTypeReferenceDirectiveNamesWorker = function (typeReferenceDirectiveNames, containingFile) { return loadWithLocalCache(ts.Debug.assertEachDefined(typeReferenceDirectiveNames), containingFile, loader_2); }; } + // Map from a stringified PackageId to the source file with that id. + // Only one source file may have a given packageId. Others become redirects (see createRedirectSourceFile). + // `packageIdToSourceFile` is only used while building the program, while `sourceFileToPackageName` and `isSourceFileTargetOfRedirect` are kept around. var packageIdToSourceFile = ts.createMap(); + // Maps from a SourceFile's `.path` to the name of the package it was imported with. var sourceFileToPackageName = ts.createMap(); var redirectTargetsSet = ts.createMap(); var filesByName = ts.createMap(); var missingFilePaths; + // stores 'filename -> file association' ignoring case + // used to track cases when two file names differ only in casing var filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? ts.createMap() : undefined; + // A parallel array to projectReferences storing the results of reading in the referenced tsconfig files var resolvedProjectReferences = projectReferences ? [] : undefined; var projectReferenceRedirects = ts.createMap(); var shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options); var structuralIsReused = tryReuseStructureFromOldProgram(); - if (structuralIsReused !== 2) { + if (structuralIsReused !== 2 /* Completely */) { processingDefaultLibFiles = []; processingOtherFiles = []; if (projectReferences) { @@ -67653,15 +81507,17 @@ var ts; if (parsedRef) { if (parsedRef.commandLine.options.outFile) { var dtsOutfile = ts.changeExtension(parsedRef.commandLine.options.outFile, ".d.ts"); - processSourceFile(dtsOutfile, false, false, undefined); + processSourceFile(dtsOutfile, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined); } addProjectReferenceRedirects(parsedRef.commandLine, projectReferenceRedirects); } } } - ts.forEach(rootNames, function (name) { return processRootFile(name, false, false); }); + ts.forEach(rootNames, function (name) { return processRootFile(name, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false); }); + // load type declarations specified via 'types' argument or implicitly from types/ and node_modules/@types folders var typeReferences = ts.getAutomaticTypeDirectiveNames(options, host); if (typeReferences.length) { + // This containingFilename needs to match with the one used in managed-side var containingDirectory = options.configFilePath ? ts.getDirectoryPath(options.configFilePath) : host.getCurrentDirectory(); var containingFilename = ts.combinePaths(containingDirectory, "__inferred type names__.ts"); var resolutions = resolveTypeReferenceDirectiveNamesWorker(typeReferences, containingFilename); @@ -67669,14 +81525,20 @@ var ts; processTypeReferenceDirective(typeReferences[i], resolutions[i]); } } + // Do not process the default library if: + // - The '--noLib' flag is used. + // - A 'no-default-lib' reference comment is encountered in + // processing the root files. if (!skipDefaultLib) { + // If '--lib' is not specified, include default library file according to '--target' + // otherwise, using options specified in '--lib' instead of '--target' default library file var defaultLibraryFileName = getDefaultLibraryFileName(); if (!options.lib && defaultLibraryFileName) { - processRootFile(defaultLibraryFileName, true, false); + processRootFile(defaultLibraryFileName, /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ false); } else { ts.forEach(options.lib, function (libFileName) { - processRootFile(ts.combinePaths(defaultLibraryPath, libFileName), true, false); + processRootFile(ts.combinePaths(defaultLibraryPath, libFileName), /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ false); }); } } @@ -67686,6 +81548,8 @@ var ts; processingOtherFiles = undefined; } ts.Debug.assert(!!missingFilePaths); + // Release any files we have acquired in the old program but are + // not part of the new program. if (oldProgram && host.onReleaseOldSourceFile) { var oldSourceFiles = oldProgram.getSourceFiles(); for (var _a = 0, oldSourceFiles_1 = oldSourceFiles; _a < oldSourceFiles_1.length; _a++) { @@ -67695,6 +81559,7 @@ var ts; } } } + // unconditionally set oldProgram to undefined to prevent it from being captured in closure oldProgram = undefined; program = { getRootFileNames: function () { return rootNames; }, @@ -67741,7 +81606,7 @@ var ts; return ts.compareValues(getDefaultLibFilePriority(a), getDefaultLibFilePriority(b)); } function getDefaultLibFilePriority(a) { - if (ts.containsPath(defaultLibraryPath, a.fileName, false)) { + if (ts.containsPath(defaultLibraryPath, a.fileName, /*ignoreCase*/ false)) { var basename = ts.getBaseFileName(a.fileName); if (basename === "lib.d.ts" || basename === "lib.es6.d.ts") return 0; @@ -67762,16 +81627,21 @@ var ts; if (commonSourceDirectory === undefined) { var emittedFiles = ts.filter(files, function (file) { return ts.sourceFileMayBeEmitted(file, options, isSourceFileFromExternalLibrary); }); if (options.rootDir && checkSourceFilesBelongToPath(emittedFiles, options.rootDir)) { + // If a rootDir is specified use it as the commonSourceDirectory commonSourceDirectory = ts.getNormalizedAbsolutePath(options.rootDir, currentDirectory); } else if (options.composite) { - commonSourceDirectory = ts.getDirectoryPath(ts.normalizeSlashes(options.configFilePath)); + // Project compilations never infer their root from the input source paths + commonSourceDirectory = ts.getDirectoryPath(ts.normalizeSlashes(options.configFilePath)); // TODO: GH#18217 checkSourceFilesBelongToPath(emittedFiles, commonSourceDirectory); } else { commonSourceDirectory = computeCommonSourceDirectory(emittedFiles); } if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== ts.directorySeparator) { + // Make sure directory path ends with directory separator so this string can directly + // used to replace with "" to get the relative path of the source file and the relative path doesn't + // start with / making it rooted path commonSourceDirectory += ts.directorySeparator; } } @@ -67779,6 +81649,7 @@ var ts; } function getClassifiableNames() { if (!classifiableNames) { + // Initialize a checker so that all our files are bound. getTypeChecker(); classifiableNames = ts.createUnderscoreEscapedMap(); for (var _i = 0, files_2 = files; _i < files_2.length; _i++) { @@ -67789,11 +81660,21 @@ var ts; return classifiableNames; } function resolveModuleNamesReusingOldState(moduleNames, containingFile, file, oldProgramState) { - if (structuralIsReused === 0 && !file.ambientModuleNames.length) { + if (structuralIsReused === 0 /* Not */ && !file.ambientModuleNames.length) { + // If the old program state does not permit reusing resolutions and `file` does not contain locally defined ambient modules, + // the best we can do is fallback to the default logic. return resolveModuleNamesWorker(moduleNames, containingFile); } var oldSourceFile = oldProgramState.program && oldProgramState.program.getSourceFile(containingFile); if (oldSourceFile !== file && file.resolvedModules) { + // `file` was created for the new program. + // + // We only set `file.resolvedModules` via work from the current function, + // so it is defined iff we already called the current function on `file`. + // That call happened no later than the creation of the `file` object, + // which per above occurred during the current program creation. + // Since we assume the filesystem does not change during program creation, + // it is safe to reuse resolutions from the earlier call. var result_4 = []; for (var _i = 0, moduleNames_1 = moduleNames; _i < moduleNames_1.length; _i++) { var moduleName = moduleNames_1[_i]; @@ -67802,12 +81683,28 @@ var ts; } return result_4; } + // At this point, we know at least one of the following hold: + // - file has local declarations for ambient modules + // - old program state is available + // With this information, we can infer some module resolutions without performing resolution. + /** An ordered list of module names for which we cannot recover the resolution. */ var unknownModuleNames; + /** + * The indexing of elements in this list matches that of `moduleNames`. + * + * Before combining results, result[i] is in one of the following states: + * * undefined: needs to be recomputed, + * * predictedToResolveToAmbientModuleMarker: known to be an ambient module. + * Needs to be reset to undefined before returning, + * * ResolvedModuleFull instance: can be reused. + */ var result; var reusedNames; + /** A transient placeholder used to mark predicted resolution in the result list. */ var predictedToResolveToAmbientModuleMarker = {}; for (var i = 0; i < moduleNames.length; i++) { var moduleName = moduleNames[i]; + // If the source file is unchanged and doesnt have invalidated resolution, reuse the module resolutions if (file === oldSourceFile && !hasInvalidatedResolution(oldSourceFile.path)) { var oldResolvedModule = oldSourceFile && oldSourceFile.resolvedModules.get(moduleName); if (oldResolvedModule) { @@ -67819,6 +81716,10 @@ var ts; continue; } } + // We know moduleName resolves to an ambient module provided that moduleName: + // - is in the list of ambient modules locally declared in the current source file. + // - resolved to an ambient module in the old program whose declaration is in an unmodified file + // (so the same module declaration will land in the new program) var resolvesToAmbientModuleInNonModifiedFile = false; if (ts.contains(file.ambientModuleNames, moduleName)) { resolvesToAmbientModuleInNonModifiedFile = true; @@ -67833,21 +81734,26 @@ var ts; (result || (result = new Array(moduleNames.length)))[i] = predictedToResolveToAmbientModuleMarker; } else { + // Resolution failed in the old program, or resolved to an ambient module for which we can't reuse the result. (unknownModuleNames || (unknownModuleNames = [])).push(moduleName); } } var resolutions = unknownModuleNames && unknownModuleNames.length ? resolveModuleNamesWorker(unknownModuleNames, containingFile, reusedNames) : ts.emptyArray; + // Combine results of resolutions and predicted results if (!result) { + // There were no unresolved/ambient resolutions. ts.Debug.assert(resolutions.length === moduleNames.length); return resolutions; } var j = 0; for (var i = 0; i < result.length; i++) { if (result[i]) { + // `result[i]` is either a `ResolvedModuleFull` or a marker. + // If it is the former, we can leave it as is. if (result[i] === predictedToResolveToAmbientModuleMarker) { - result[i] = undefined; + result[i] = undefined; // TODO: GH#18217 } } else { @@ -67857,16 +81763,23 @@ var ts; } ts.Debug.assert(j === resolutions.length); return result; + // If we change our policy of rechecking failed lookups on each program create, + // we should adjust the value returned here. function moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName, oldProgramState) { - var resolutionToFile = ts.getResolvedModule(oldProgramState.oldSourceFile, moduleName); + var resolutionToFile = ts.getResolvedModule(oldProgramState.oldSourceFile, moduleName); // TODO: GH#18217 var resolvedFile = resolutionToFile && oldProgramState.program && oldProgramState.program.getSourceFile(resolutionToFile.resolvedFileName); if (resolutionToFile && resolvedFile && !resolvedFile.externalModuleIndicator) { + // In the old program, we resolved to an ambient module that was in the same + // place as we expected to find an actual module file. + // We actually need to return 'false' here even though this seems like a 'true' case + // because the normal module resolution algorithm will find this anyway. return false; } var ambientModule = oldProgramState.program && oldProgramState.program.getTypeChecker().tryFindAmbientModuleWithoutAugmentations(moduleName); if (!(ambientModule && ambientModule.declarations)) { return false; } + // at least one of declarations should come from non-modified source file var firstUnmodifiedFile = ts.forEach(ambientModule.declarations, function (d) { var f = ts.getSourceFileOfNode(d); return !ts.contains(oldProgramState.modifiedFilePaths, f.path) && f; @@ -67882,51 +81795,61 @@ var ts; } function tryReuseStructureFromOldProgram() { if (!oldProgram) { - return 0; + return 0 /* Not */; } + // check properties that can affect structure of the program or module resolution strategy + // if any of these properties has changed - structure cannot be reused var oldOptions = oldProgram.getCompilerOptions(); if (ts.changesAffectModuleResolution(oldOptions, options)) { - return oldProgram.structureIsReused = 0; + return oldProgram.structureIsReused = 0 /* Not */; } - ts.Debug.assert(!(oldProgram.structureIsReused & (2 | 1))); + ts.Debug.assert(!(oldProgram.structureIsReused & (2 /* Completely */ | 1 /* SafeModules */))); + // there is an old program, check if we can reuse its structure var oldRootNames = oldProgram.getRootFileNames(); if (!ts.arrayIsEqualTo(oldRootNames, rootNames)) { - return oldProgram.structureIsReused = 0; + return oldProgram.structureIsReused = 0 /* Not */; } if (!ts.arrayIsEqualTo(options.types, oldOptions.types)) { - return oldProgram.structureIsReused = 0; + return oldProgram.structureIsReused = 0 /* Not */; } + // Check if any referenced project tsconfig files are different var oldRefs = oldProgram.getProjectReferences(); if (projectReferences) { if (!oldRefs) { - return oldProgram.structureIsReused = 0; + return oldProgram.structureIsReused = 0 /* Not */; } for (var i = 0; i < projectReferences.length; i++) { var oldRef = oldRefs[i]; if (oldRef) { var newRef = parseProjectReferenceConfigFile(projectReferences[i]); if (!newRef || newRef.sourceFile !== oldRef.sourceFile) { - return oldProgram.structureIsReused = 0; + // Resolved project reference has gone missing or changed + return oldProgram.structureIsReused = 0 /* Not */; } } else { + // A previously-unresolved reference may be resolved now if (parseProjectReferenceConfigFile(projectReferences[i]) !== undefined) { - return oldProgram.structureIsReused = 0; + return oldProgram.structureIsReused = 0 /* Not */; } } } } else { if (oldRefs) { - return oldProgram.structureIsReused = 0; + return oldProgram.structureIsReused = 0 /* Not */; } } + // check if program source files has changed in the way that can affect structure of the program var newSourceFiles = []; var filePaths = []; var modifiedSourceFiles = []; - oldProgram.structureIsReused = 2; + oldProgram.structureIsReused = 2 /* Completely */; + // If the missing file paths are now present, it can change the progam structure, + // and hence cant reuse the structure. + // This is same as how we dont reuse the structure if one of the file from old program is now missing if (oldProgram.getMissingFilePaths().some(function (missingFilePath) { return host.fileExists(missingFilePath); })) { - return oldProgram.structureIsReused = 0; + return oldProgram.structureIsReused = 0 /* Not */; } var oldSourceFiles = oldProgram.getSourceFiles(); var SeenPackageName; @@ -67938,23 +81861,27 @@ var ts; for (var _i = 0, oldSourceFiles_2 = oldSourceFiles; _i < oldSourceFiles_2.length; _i++) { var oldSourceFile = oldSourceFiles_2[_i]; var newSourceFile = host.getSourceFileByPath - ? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.resolvedPath || oldSourceFile.path, options.target, undefined, shouldCreateNewSourceFile) - : host.getSourceFile(oldSourceFile.fileName, options.target, undefined, shouldCreateNewSourceFile); + ? host.getSourceFileByPath(oldSourceFile.fileName, oldSourceFile.resolvedPath || oldSourceFile.path, options.target, /*onError*/ undefined, shouldCreateNewSourceFile) + : host.getSourceFile(oldSourceFile.fileName, options.target, /*onError*/ undefined, shouldCreateNewSourceFile); // TODO: GH#18217 if (!newSourceFile) { - return oldProgram.structureIsReused = 0; + return oldProgram.structureIsReused = 0 /* Not */; } ts.Debug.assert(!newSourceFile.redirectInfo, "Host should not return a redirect source file from `getSourceFile`"); var fileChanged = void 0; if (oldSourceFile.redirectInfo) { + // We got `newSourceFile` by path, so it is actually for the unredirected file. + // This lets us know if the unredirected file has changed. If it has we should break the redirect. if (newSourceFile !== oldSourceFile.redirectInfo.unredirected) { - return oldProgram.structureIsReused = 0; + // Underlying file has changed. Might not redirect anymore. Must rebuild program. + return oldProgram.structureIsReused = 0 /* Not */; } fileChanged = false; - newSourceFile = oldSourceFile; + newSourceFile = oldSourceFile; // Use the redirect. } else if (oldProgram.redirectTargetsSet.has(oldSourceFile.path)) { + // If a redirected-to source file changes, the redirect may be broken. if (newSourceFile !== oldSourceFile) { - return oldProgram.structureIsReused = 0; + return oldProgram.structureIsReused = 0 /* Not */; } fileChanged = false; } @@ -67965,48 +81892,66 @@ var ts; filePaths.push(newSourceFile.path); var packageName = oldProgram.sourceFileToPackageName.get(oldSourceFile.path); if (packageName !== undefined) { + // If there are 2 different source files for the same package name and at least one of them changes, + // they might become redirects. So we must rebuild the program. var prevKind = seenPackageNames.get(packageName); - var newKind = fileChanged ? 1 : 0; - if ((prevKind !== undefined && newKind === 1) || prevKind === 1) { - return oldProgram.structureIsReused = 0; + var newKind = fileChanged ? 1 /* Modified */ : 0 /* Exists */; + if ((prevKind !== undefined && newKind === 1 /* Modified */) || prevKind === 1 /* Modified */) { + return oldProgram.structureIsReused = 0 /* Not */; } seenPackageNames.set(packageName, newKind); } if (fileChanged) { + // The `newSourceFile` object was created for the new program. if (!ts.arrayIsEqualTo(oldSourceFile.libReferenceDirectives, newSourceFile.libReferenceDirectives, fileReferenceIsEqualTo)) { - return oldProgram.structureIsReused = 0; + // 'lib' references has changed. Matches behavior in changesAffectModuleResolution + return oldProgram.structureIsReused = 0 /* Not */; } if (oldSourceFile.hasNoDefaultLib !== newSourceFile.hasNoDefaultLib) { - oldProgram.structureIsReused = 1; + // value of no-default-lib has changed + // this will affect if default library is injected into the list of files + oldProgram.structureIsReused = 1 /* SafeModules */; } + // check tripleslash references if (!ts.arrayIsEqualTo(oldSourceFile.referencedFiles, newSourceFile.referencedFiles, fileReferenceIsEqualTo)) { - oldProgram.structureIsReused = 1; + // tripleslash references has changed + oldProgram.structureIsReused = 1 /* SafeModules */; } + // check imports and module augmentations collectExternalModuleReferences(newSourceFile); if (!ts.arrayIsEqualTo(oldSourceFile.imports, newSourceFile.imports, moduleNameIsEqualTo)) { - oldProgram.structureIsReused = 1; + // imports has changed + oldProgram.structureIsReused = 1 /* SafeModules */; } if (!ts.arrayIsEqualTo(oldSourceFile.moduleAugmentations, newSourceFile.moduleAugmentations, moduleNameIsEqualTo)) { - oldProgram.structureIsReused = 1; + // moduleAugmentations has changed + oldProgram.structureIsReused = 1 /* SafeModules */; } - if ((oldSourceFile.flags & 1572864) !== (newSourceFile.flags & 1572864)) { - oldProgram.structureIsReused = 1; + if ((oldSourceFile.flags & 1572864 /* PermanentlySetIncrementalFlags */) !== (newSourceFile.flags & 1572864 /* PermanentlySetIncrementalFlags */)) { + // dynamicImport has changed + oldProgram.structureIsReused = 1 /* SafeModules */; } if (!ts.arrayIsEqualTo(oldSourceFile.typeReferenceDirectives, newSourceFile.typeReferenceDirectives, fileReferenceIsEqualTo)) { - oldProgram.structureIsReused = 1; + // 'types' references has changed + oldProgram.structureIsReused = 1 /* SafeModules */; } + // tentatively approve the file modifiedSourceFiles.push({ oldFile: oldSourceFile, newFile: newSourceFile }); } else if (hasInvalidatedResolution(oldSourceFile.path)) { - oldProgram.structureIsReused = 1; + // 'module/types' references could have changed + oldProgram.structureIsReused = 1 /* SafeModules */; + // add file to the modified list so that we will resolve it later modifiedSourceFiles.push({ oldFile: oldSourceFile, newFile: newSourceFile }); } + // if file has passed all checks it should be safe to reuse it newSourceFiles.push(newSourceFile); } - if (oldProgram.structureIsReused !== 2) { + if (oldProgram.structureIsReused !== 2 /* Completely */) { return oldProgram.structureIsReused; } modifiedFilePaths = modifiedSourceFiles.map(function (f) { return f.newFile.path; }); + // try to verify results of module resolution for (var _a = 0, modifiedSourceFiles_1 = modifiedSourceFiles; _a < modifiedSourceFiles_1.length; _a++) { var _b = modifiedSourceFiles_1[_a], oldSourceFile = _b.oldFile, newSourceFile = _b.newFile; var newSourceFilePath = ts.getNormalizedAbsolutePath(newSourceFile.fileName, currentDirectory); @@ -68014,9 +81959,10 @@ var ts; var moduleNames = getModuleNames(newSourceFile); var oldProgramState = { program: oldProgram, oldSourceFile: oldSourceFile, modifiedFilePaths: modifiedFilePaths }; var resolutions = resolveModuleNamesReusingOldState(moduleNames, newSourceFilePath, newSourceFile, oldProgramState); + // ensure that module resolution results are still correct var resolutionsChanged = ts.hasChangesInResolutions(moduleNames, resolutions, oldSourceFile.resolvedModules, ts.moduleResolutionIsEqualTo); if (resolutionsChanged) { - oldProgram.structureIsReused = 1; + oldProgram.structureIsReused = 1 /* SafeModules */; newSourceFile.resolvedModules = ts.zipToMap(moduleNames, resolutions); } else { @@ -68026,9 +81972,10 @@ var ts; if (resolveTypeReferenceDirectiveNamesWorker) { var typesReferenceDirectives = ts.map(newSourceFile.typeReferenceDirectives, function (x) { return x.fileName; }); var resolutions = resolveTypeReferenceDirectiveNamesWorker(typesReferenceDirectives, newSourceFilePath); + // ensure that types resolutions are still correct var resolutionsChanged = ts.hasChangesInResolutions(typesReferenceDirectives, resolutions, oldSourceFile.resolvedTypeReferenceDirectiveNames, ts.typeDirectiveIsEqualTo); if (resolutionsChanged) { - oldProgram.structureIsReused = 1; + oldProgram.structureIsReused = 1 /* SafeModules */; newSourceFile.resolvedTypeReferenceDirectiveNames = ts.zipToMap(typesReferenceDirectives, resolutions); } else { @@ -68036,15 +81983,17 @@ var ts; } } } - if (oldProgram.structureIsReused !== 2) { + if (oldProgram.structureIsReused !== 2 /* Completely */) { return oldProgram.structureIsReused; } if (host.hasChangedAutomaticTypeDirectiveNames) { - return oldProgram.structureIsReused = 1; + return oldProgram.structureIsReused = 1 /* SafeModules */; } missingFilePaths = oldProgram.getMissingFilePaths(); + // update fileName -> file mapping for (var i = 0; i < newSourceFiles.length; i++) { filesByName.set(filePaths[i], newSourceFiles[i]); + // Set the file as found during node modules search if it was found that way in old progra, if (oldProgram.isSourceFileFromExternalLibrary(oldProgram.getSourceFileByPath(filePaths[i]))) { sourceFilesFoundSearchingNodeModules.set(filePaths[i], true); } @@ -68059,7 +82008,7 @@ var ts; resolvedProjectReferences = oldProgram.getProjectReferences(); sourceFileToPackageName = oldProgram.sourceFileToPackageName; redirectTargetsSet = oldProgram.redirectTargetsSet; - return oldProgram.structureIsReused = 2; + return oldProgram.structureIsReused = 2 /* Completely */; } function getEmitHost(writeFileCallback) { return __assign({ getPrependNodes: getPrependNodes, @@ -68079,11 +82028,12 @@ var ts; var ref = projectReferences[i]; var resolvedRefOpts = resolvedProjectReferences[i].commandLine; if (ref.prepend && resolvedRefOpts && resolvedRefOpts.options) { + // Upstream project didn't have outFile set -- skip (error will have been issued earlier) if (!resolvedRefOpts.options.outFile) continue; var dtsFilename = ts.changeExtension(resolvedRefOpts.options.outFile, ".d.ts"); var js = host.readFile(resolvedRefOpts.options.outFile) || "/* Input file " + resolvedRefOpts.options.outFile + " was missing */\r\n"; - var jsMapPath = resolvedRefOpts.options.outFile + ".map"; + var jsMapPath = resolvedRefOpts.options.outFile + ".map"; // TODO: try to read sourceMappingUrl comment from the file var jsMap = host.readFile(jsMapPath); var dts = host.readFile(dtsFilename) || "/* Input file " + dtsFilename + " was missing */\r\n"; var dtsMapPath = dtsFilename + ".map"; @@ -68104,6 +82054,8 @@ var ts; if (!options.noLib) { return false; } + // If '--lib' is not specified, include default library file according to '--target' + // otherwise, using options specified in '--lib' instead of '--target' default library file var equalityComparer = host.useCaseSensitiveFileNames() ? ts.equateStringsCaseSensitive : ts.equateStringsCaseInsensitive; if (!options.lib) { return equalityComparer(file.fileName, getDefaultLibraryFileName()); @@ -68113,13 +82065,13 @@ var ts; } } function getDiagnosticsProducingTypeChecker() { - return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = ts.createTypeChecker(program, true)); + return diagnosticsProducingTypeChecker || (diagnosticsProducingTypeChecker = ts.createTypeChecker(program, /*produceDiagnostics:*/ true)); } function dropDiagnosticsProducingTypeChecker() { diagnosticsProducingTypeChecker = undefined; } function getTypeChecker() { - return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = ts.createTypeChecker(program, false)); + return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = ts.createTypeChecker(program, /*produceDiagnostics:*/ false)); } function emit(sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles, transformers) { return runWithCancellationToken(function () { return emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles, transformers); }); @@ -68133,10 +82085,13 @@ var ts; if (options.noEmit) { return { diagnostics: declarationDiagnostics, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true }; } + // If the noEmitOnError flag is set, then check if we have any errors so far. If so, + // immediately bail out. Note that we pass 'undefined' for 'sourceFile' so that we + // get any preEmit diagnostics, not just the ones if (options.noEmitOnError) { var diagnostics = program.getOptionsDiagnostics(cancellationToken).concat(program.getSyntacticDiagnostics(sourceFile, cancellationToken), program.getGlobalDiagnostics(cancellationToken), program.getSemanticDiagnostics(sourceFile, cancellationToken)); if (diagnostics.length === 0 && program.getCompilerOptions().declaration) { - declarationDiagnostics = program.getDeclarationDiagnostics(undefined, cancellationToken); + declarationDiagnostics = program.getDeclarationDiagnostics(/*sourceFile*/ undefined, cancellationToken); } if (diagnostics.length > 0 || declarationDiagnostics.length > 0) { return { @@ -68148,10 +82103,19 @@ var ts; } } } + // Create the emit resolver outside of the "emitTime" tracking code below. That way + // any cost associated with it (like type checking) are appropriate associated with + // the type-checking counter. + // + // If the -out option is specified, we should not pass the source file to getEmitResolver. + // This is because in the -out scenario all files need to be emitted, and therefore all + // files need to be type checked. And the way to specify that all files need to be type + // checked is to not pass the file to getEmitResolver. var emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver((options.outFile || options.out) ? undefined : sourceFile, cancellationToken); ts.performance.mark("beforeEmit"); var transformers = emitOnlyDtsFiles ? [] : ts.getTransformers(options, customTransformers); - var emitResult = ts.emitFiles(emitResolver, getEmitHost(writeFileCallback), sourceFile, emitOnlyDtsFiles, transformers, customTransformers && customTransformers.afterDeclarations); + var emitResult = ts.emitFiles(emitResolver, getEmitHost(writeFileCallback), sourceFile, // TODO: GH#18217 + emitOnlyDtsFiles, transformers, customTransformers && customTransformers.afterDeclarations); ts.performance.mark("afterEmit"); ts.performance.measure("Emit", "beforeEmit", "afterEmit"); return emitResult; @@ -68181,6 +82145,7 @@ var ts; } function getDeclarationDiagnostics(sourceFile, cancellationToken) { var options = program.getCompilerOptions(); + // collect diagnostics from the program only once if either no source file was specified or out/outFile is set (bundled emit) if (!sourceFile || options.out || options.outFile) { return getDeclarationDiagnosticsWorker(sourceFile, cancellationToken); } @@ -68189,6 +82154,8 @@ var ts; } } function getSyntacticDiagnosticsForFile(sourceFile) { + // For JavaScript files, we report semantic errors for using TypeScript-only + // constructs from within a JavaScript file as syntactic errors. if (ts.isSourceFileJavaScript(sourceFile)) { if (!sourceFile.additionalSyntacticDiagnostics) { sourceFile.additionalSyntacticDiagnostics = getJavaScriptSyntacticDiagnosticsForFile(sourceFile); @@ -68203,6 +82170,15 @@ var ts; } catch (e) { if (e instanceof ts.OperationCanceledException) { + // We were canceled while performing the operation. Because our type checker + // might be a bad state, we need to throw it away. + // + // Note: we are overly aggressive here. We do not actually *have* to throw away + // the "noDiagnosticsTypeChecker". However, for simplicity, i'd like to keep + // the lifetimes of these two TypeCheckers the same. Also, we generally only + // cancel when the user has made a change anyways. And, in that case, we (the + // program instance) will get thrown away anyways. So trying to keep one of + // these type checkers alive doesn't serve much purpose. noDiagnosticsTypeChecker = undefined; diagnosticsProducingTypeChecker = undefined; } @@ -68214,14 +82190,18 @@ var ts; } function getSemanticDiagnosticsForFileNoCache(sourceFile, cancellationToken) { return runWithCancellationToken(function () { + // If skipLibCheck is enabled, skip reporting errors if file is a declaration file. + // If skipDefaultLibCheck is enabled, skip reporting errors if file contains a + // '/// ' directive. if (options.skipLibCheck && sourceFile.isDeclarationFile || options.skipDefaultLibCheck && sourceFile.hasNoDefaultLib) { return ts.emptyArray; } var typeChecker = getDiagnosticsProducingTypeChecker(); ts.Debug.assert(!!sourceFile.bindDiagnostics); var isCheckJs = ts.isCheckJsEnabledForFile(sourceFile, options); - var includeBindAndCheckDiagnostics = sourceFile.scriptKind === 3 || sourceFile.scriptKind === 4 || - sourceFile.scriptKind === 5 || isCheckJs || sourceFile.scriptKind === 7; + // By default, only type-check .ts, .tsx, 'Deferred' and 'External' files (external files are added by plugins) + var includeBindAndCheckDiagnostics = sourceFile.scriptKind === 3 /* TS */ || sourceFile.scriptKind === 4 /* TSX */ || + sourceFile.scriptKind === 5 /* External */ || isCheckJs || sourceFile.scriptKind === 7 /* Deferred */; var bindDiagnostics = includeBindAndCheckDiagnostics ? sourceFile.bindDiagnostics : ts.emptyArray; var checkDiagnostics = includeBindAndCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : ts.emptyArray; var fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName); @@ -68246,18 +82226,23 @@ var ts; return getDiagnosticsProducingTypeChecker().getSuggestionDiagnostics(sourceFile, cancellationToken); }); } + /** + * Skip errors if previous line start with '// @ts-ignore' comment, not counting non-empty non-comment lines + */ function shouldReportDiagnostic(diagnostic) { var file = diagnostic.file, start = diagnostic.start; if (file) { var lineStarts = ts.getLineStarts(file); - var line = ts.computeLineAndCharacterOfPosition(lineStarts, start).line; + var line = ts.computeLineAndCharacterOfPosition(lineStarts, start).line; // TODO: GH#18217 while (line > 0) { var previousLineText = file.text.slice(lineStarts[line - 1], lineStarts[line]); var result = ignoreDiagnosticCommentRegEx.exec(previousLineText); if (!result) { + // non-empty line return true; } if (result[3]) { + // @ts-ignore return false; } line--; @@ -68272,64 +82257,68 @@ var ts; walk(sourceFile); return diagnostics; function walk(node) { + // Return directly from the case if the given node doesnt want to visit each child + // Otherwise break to visit each child switch (parent.kind) { - case 149: - case 152: + case 149 /* Parameter */: + case 152 /* PropertyDeclaration */: if (parent.questionToken === node) { diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics._0_can_only_be_used_in_a_ts_file, "?")); return; } - case 154: - case 153: - case 155: - case 156: - case 157: - case 192: - case 234: - case 193: - case 232: + // falls through + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 192 /* FunctionExpression */: + case 234 /* FunctionDeclaration */: + case 193 /* ArrowFunction */: + case 232 /* VariableDeclaration */: + // type annotation if (parent.type === node) { diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.types_can_only_be_used_in_a_ts_file)); return; } } switch (node.kind) { - case 243: + case 243 /* ImportEqualsDeclaration */: diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.import_can_only_be_used_in_a_ts_file)); return; - case 249: + case 249 /* ExportAssignment */: if (node.isExportEquals) { diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.export_can_only_be_used_in_a_ts_file)); return; } break; - case 268: + case 268 /* HeritageClause */: var heritageClause = node; - if (heritageClause.token === 108) { + if (heritageClause.token === 108 /* ImplementsKeyword */) { diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.implements_clauses_can_only_be_used_in_a_ts_file)); return; } break; - case 236: + case 236 /* InterfaceDeclaration */: diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.interface_declarations_can_only_be_used_in_a_ts_file)); return; - case 239: + case 239 /* ModuleDeclaration */: diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.module_declarations_can_only_be_used_in_a_ts_file)); return; - case 237: + case 237 /* TypeAliasDeclaration */: diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.type_aliases_can_only_be_used_in_a_ts_file)); return; - case 238: + case 238 /* EnumDeclaration */: diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.enum_declarations_can_only_be_used_in_a_ts_file)); return; - case 209: + case 209 /* NonNullExpression */: diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.non_null_assertions_can_only_be_used_in_a_ts_file)); return; - case 208: + case 208 /* AsExpression */: diagnostics.push(createDiagnosticForNode(node.type, ts.Diagnostics.type_assertion_expressions_can_only_be_used_in_a_ts_file)); return; - case 190: - ts.Debug.fail(); + case 190 /* TypeAssertionExpression */: + ts.Debug.fail(); // Won't parse these in a JS file anyway, as they are interpreted as JSX. } var prevParent = parent; parent = node; @@ -68341,46 +82330,52 @@ var ts; diagnostics.push(createDiagnosticForNode(parent, ts.Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_to_remove_this_warning)); } switch (parent.kind) { - case 235: - case 154: - case 153: - case 155: - case 156: - case 157: - case 192: - case 234: - case 193: + case 235 /* ClassDeclaration */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 192 /* FunctionExpression */: + case 234 /* FunctionDeclaration */: + case 193 /* ArrowFunction */: + // Check type parameters if (nodes === parent.typeParameters) { diagnostics.push(createDiagnosticForNodeArray(nodes, ts.Diagnostics.type_parameter_declarations_can_only_be_used_in_a_ts_file)); return; } - case 214: + // falls through + case 214 /* VariableStatement */: + // Check modifiers if (nodes === parent.modifiers) { - return checkModifiers(nodes, parent.kind === 214); + return checkModifiers(nodes, parent.kind === 214 /* VariableStatement */); } break; - case 152: + case 152 /* PropertyDeclaration */: + // Check modifiers of property declaration if (nodes === parent.modifiers) { for (var _i = 0, _a = nodes; _i < _a.length; _i++) { var modifier = _a[_i]; - if (modifier.kind !== 115) { + if (modifier.kind !== 115 /* StaticKeyword */) { diagnostics.push(createDiagnosticForNode(modifier, ts.Diagnostics._0_can_only_be_used_in_a_ts_file, ts.tokenToString(modifier.kind))); } } return; } break; - case 149: + case 149 /* Parameter */: + // Check modifiers of parameter declaration if (nodes === parent.modifiers) { diagnostics.push(createDiagnosticForNodeArray(nodes, ts.Diagnostics.parameter_modifiers_can_only_be_used_in_a_ts_file)); return; } break; - case 187: - case 188: - case 207: - case 256: - case 257: + case 187 /* CallExpression */: + case 188 /* NewExpression */: + case 207 /* ExpressionWithTypeArguments */: + case 256 /* JsxSelfClosingElement */: + case 257 /* JsxOpeningElement */: + // Check type arguments if (nodes === parent.typeArguments) { diagnostics.push(createDiagnosticForNodeArray(nodes, ts.Diagnostics.type_arguments_can_only_be_used_in_a_ts_file)); return; @@ -68396,21 +82391,24 @@ var ts; for (var _i = 0, modifiers_1 = modifiers; _i < modifiers_1.length; _i++) { var modifier = modifiers_1[_i]; switch (modifier.kind) { - case 76: + case 76 /* ConstKeyword */: if (isConstValid) { continue; } - case 114: - case 112: - case 113: - case 132: - case 124: - case 117: + // to report error, + // falls through + case 114 /* PublicKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: + case 132 /* ReadonlyKeyword */: + case 124 /* DeclareKeyword */: + case 117 /* AbstractKeyword */: diagnostics.push(createDiagnosticForNode(modifier, ts.Diagnostics._0_can_only_be_used_in_a_ts_file, ts.tokenToString(modifier.kind))); break; - case 115: - case 84: - case 79: + // These are all legal modifiers. + case 115 /* StaticKeyword */: + case 84 /* ExportKeyword */: + case 79 /* DefaultKeyword */: } } } @@ -68418,6 +82416,8 @@ var ts; var start = nodes.pos; return ts.createFileDiagnostic(sourceFile, start, nodes.end - start, message, arg0, arg1, arg2); } + // Since these are syntactic diagnostics, parent might not have been set + // this means the sourceFile cannot be infered from the node function createDiagnosticForNode(node, message, arg0, arg1, arg2) { return ts.createDiagnosticForNodeInSourceFile(sourceFile, node, message, arg0, arg1, arg2); } @@ -68429,6 +82429,7 @@ var ts; function getDeclarationDiagnosticsForFileNoCache(sourceFile, cancellationToken) { return runWithCancellationToken(function () { var resolver = getDiagnosticsProducingTypeChecker().getEmitResolver(sourceFile, cancellationToken); + // Don't actually write any files since we're just getting diagnostics. return ts.getDeclarationDiagnostics(getEmitHost(ts.noop), resolver, sourceFile); }); } @@ -68439,7 +82440,7 @@ var ts; if (cachedResult) { return cachedResult; } - var result = getDiagnostics(sourceFile, cancellationToken) || ts.emptyArray; + var result = getDiagnostics(sourceFile, cancellationToken) || ts.emptyArray; // TODO: GH#18217 if (sourceFile) { if (!cache.perFile) { cache.perFile = ts.createMap(); @@ -68464,15 +82465,15 @@ var ts; return configFileParsingDiagnostics || ts.emptyArray; } function processRootFile(fileName, isDefaultLib, ignoreNoDefaultLib) { - processSourceFile(ts.normalizePath(fileName), isDefaultLib, ignoreNoDefaultLib, undefined); + processSourceFile(ts.normalizePath(fileName), isDefaultLib, ignoreNoDefaultLib, /*packageId*/ undefined); } function fileReferenceIsEqualTo(a, b) { return a.fileName === b.fileName; } function moduleNameIsEqualTo(a, b) { - return a.kind === 71 - ? b.kind === 71 && a.escapedText === b.escapedText - : b.kind === 9 && a.text === b.text; + return a.kind === 71 /* Identifier */ + ? b.kind === 71 /* Identifier */ && a.escapedText === b.escapedText + : b.kind === 9 /* StringLiteral */ && a.text === b.text; } function collectExternalModuleReferences(file) { if (file.imports) { @@ -68480,27 +82481,31 @@ var ts; } var isJavaScriptFile = ts.isSourceFileJavaScript(file); var isExternalModuleFile = ts.isExternalModule(file); + // file.imports may not be undefined if there exists dynamic import var imports; var moduleAugmentations; var ambientModules; + // If we are importing helpers, we need to add a synthetic reference to resolve the + // helpers library. if (options.importHelpers && (options.isolatedModules || isExternalModuleFile) && !file.isDeclarationFile) { + // synthesize 'import "tslib"' declaration var externalHelpersModuleReference = ts.createLiteral(ts.externalHelpersModuleNameText); - var importDecl = ts.createImportDeclaration(undefined, undefined, undefined, externalHelpersModuleReference); - ts.addEmitFlags(importDecl, 67108864); + var importDecl = ts.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*importClause*/ undefined, externalHelpersModuleReference); + ts.addEmitFlags(importDecl, 67108864 /* NeverApplyImportHelper */); externalHelpersModuleReference.parent = importDecl; importDecl.parent = file; imports = [externalHelpersModuleReference]; } for (var _i = 0, _a = file.statements; _i < _a.length; _i++) { var node = _a[_i]; - collectModuleReferences(node, false); - if ((file.flags & 524288) || isJavaScriptFile) { + collectModuleReferences(node, /*inAmbientModule*/ false); + if ((file.flags & 524288 /* PossiblyContainsDynamicImport */) || isJavaScriptFile) { collectDynamicImportOrRequireCalls(node); } } - if ((file.flags & 524288) || isJavaScriptFile) { + if ((file.flags & 524288 /* PossiblyContainsDynamicImport */) || isJavaScriptFile) { collectDynamicImportOrRequireCalls(file.endOfFileToken); } file.imports = imports || ts.emptyArray; @@ -68510,25 +82515,39 @@ var ts; function collectModuleReferences(node, inAmbientModule) { if (ts.isAnyImportOrReExport(node)) { var moduleNameExpr = ts.getExternalModuleName(node); + // TypeScript 1.0 spec (April 2014): 12.1.6 + // An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference other external modules + // only through top - level external module names. Relative external module names are not permitted. if (moduleNameExpr && ts.isStringLiteral(moduleNameExpr) && moduleNameExpr.text && (!inAmbientModule || !ts.isExternalModuleNameRelative(moduleNameExpr.text))) { imports = ts.append(imports, moduleNameExpr); } } else if (ts.isModuleDeclaration(node)) { - if (ts.isAmbientModule(node) && (inAmbientModule || ts.hasModifier(node, 2) || file.isDeclarationFile)) { + if (ts.isAmbientModule(node) && (inAmbientModule || ts.hasModifier(node, 2 /* Ambient */) || file.isDeclarationFile)) { var nameText = ts.getTextOfIdentifierOrLiteral(node.name); + // Ambient module declarations can be interpreted as augmentations for some existing external modules. + // This will happen in two cases: + // - if current file is external module then module augmentation is a ambient module declaration defined in the top level scope + // - if current file is not external module then module augmentation is an ambient module declaration with non-relative module name + // immediately nested in top level ambient module declaration . if (isExternalModuleFile || (inAmbientModule && !ts.isExternalModuleNameRelative(nameText))) { (moduleAugmentations || (moduleAugmentations = [])).push(node.name); } else if (!inAmbientModule) { if (file.isDeclarationFile) { + // for global .d.ts files record name of ambient module (ambientModules || (ambientModules = [])).push(nameText); } + // An AmbientExternalModuleDeclaration declares an external module. + // This type of declaration is permitted only in the global module. + // The StringLiteral must specify a top - level external module name. + // Relative external module names are not permitted + // NOTE: body of ambient module is always a module block, if it exists var body = node.body; if (body) { for (var _i = 0, _a = body.statements; _i < _a.length; _i++) { var statement = _a[_i]; - collectModuleReferences(statement, true); + collectModuleReferences(statement, /*inAmbientModule*/ true); } } } @@ -68536,9 +82555,10 @@ var ts; } } function collectDynamicImportOrRequireCalls(node) { - if (ts.isRequireCall(node, true)) { + if (ts.isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true)) { imports = ts.append(imports, node.arguments[0]); } + // we have to check the argument list has length of 1. We will still have to process these even though we have parsing error. else if (ts.isImportCall(node) && node.arguments.length === 1 && ts.isStringLiteralLike(node.arguments[0])) { imports = ts.append(imports, node.arguments[0]); } @@ -68561,6 +82581,7 @@ var ts; return getSourceFile(ts.combinePaths(defaultLibraryPath, libFileName)); } } + /** This should have similar behavior to 'processSourceFile' without diagnostics or mutation. */ function getSourceFileFromReference(referencingFile, ref) { return getSourceFileFromReferenceWorker(resolveTripleslashReference(ref.fileName, referencingFile.fileName), function (fileName) { return filesByName.get(toPath(fileName)); }); } @@ -68598,12 +82619,14 @@ var ts; } var sourceFileWithAddedExtension = ts.forEach(supportedExtensions, function (extension) { return getSourceFile(fileName + extension); }); if (fail && !sourceFileWithAddedExtension) - fail(ts.Diagnostics.File_0_not_found, fileName + ".ts"); + fail(ts.Diagnostics.File_0_not_found, fileName + ".ts" /* Ts */); return sourceFileWithAddedExtension; } } + /** This has side effects through `findSourceFile`. */ function processSourceFile(fileName, isDefaultLib, ignoreNoDefaultLib, packageId, refFile, refPos, refEnd) { - getSourceFileFromReferenceWorker(fileName, function (fileName) { return findSourceFile(fileName, toPath(fileName), isDefaultLib, ignoreNoDefaultLib, refFile, refPos, refEnd, packageId); }, function (diagnostic) { + getSourceFileFromReferenceWorker(fileName, function (fileName) { return findSourceFile(fileName, toPath(fileName), isDefaultLib, ignoreNoDefaultLib, refFile, refPos, refEnd, packageId); }, // TODO: GH#18217 + function (diagnostic) { var args = []; for (var _i = 1; _i < arguments.length; _i++) { args[_i - 1] = arguments[_i]; @@ -68637,12 +82660,17 @@ var ts; }); return redirect; } + // Get source file from normalized fileName function findSourceFile(fileName, path, isDefaultLib, ignoreNoDefaultLib, refFile, refPos, refEnd, packageId) { if (filesByName.has(path)) { var file_1 = filesByName.get(path); + // try to check if we've already seen this file but with a different casing in path + // NOTE: this only makes sense for case-insensitive file systems if (file_1 && options.forceConsistentCasingInFileNames && ts.getNormalizedAbsolutePath(file_1.fileName, currentDirectory) !== ts.getNormalizedAbsolutePath(fileName, currentDirectory)) { reportFileNamesDifferOnlyInCasingError(fileName, file_1.fileName, refFile, refPos, refEnd); } + // If the file was previously found via a node_modules search, but is now being processed as a root file, + // then everything it sucks in may also be marked incorrectly, and needs to be checked again. if (file_1 && sourceFilesFoundSearchingNodeModules.get(file_1.path) && currentNodeModulesDepth === 0) { sourceFilesFoundSearchingNodeModules.set(file_1.path, false); if (!options.noResolve) { @@ -68653,6 +82681,7 @@ var ts; modulesWithElidedImports.set(file_1.path, false); processImportedModules(file_1); } + // See if we need to reprocess the imports due to prior skipped imports else if (file_1 && modulesWithElidedImports.get(file_1.path)) { if (currentNodeModulesDepth < maxNodeModuleJsDepth) { modulesWithElidedImports.set(file_1.path, false); @@ -68667,9 +82696,15 @@ var ts; if (redirect) { (refFile.redirectedReferences || (refFile.redirectedReferences = [])).push(fileName); fileName = redirect; + // Once we start redirecting to a file, we can potentially come back to it + // via a back-reference from another file in the .d.ts folder. If that happens we'll + // end up trying to add it to the program *again* because we were tracking it via its + // original (un-redirected) name. So we have to map both the original path and the redirected path + // to the source file we're about to find/create redirectedPath = toPath(redirect); } } + // We haven't looked for this file, do so now and cache result var file = host.getSourceFile(fileName, options.target, function (hostErrorMessage) { if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) { fileProcessingDiagnostics.add(ts.createFileDiagnostic(refFile, refPos, refEnd - refPos, ts.Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage)); @@ -68682,7 +82717,9 @@ var ts; var packageIdKey = ts.packageIdToString(packageId); var fileFromPackageId = packageIdToSourceFile.get(packageIdKey); if (fileFromPackageId) { - var dupFile = createRedirectSourceFile(fileFromPackageId, file, fileName, path); + // Some other SourceFile already exists with this package name and version. + // Instead of creating a duplicate, just redirect to the existing one. + var dupFile = createRedirectSourceFile(fileFromPackageId, file, fileName, path); // TODO: GH#18217 redirectTargetsSet.set(fileFromPackageId.path, true); filesByName.set(path, dupFile); sourceFileToPackageName.set(path, packageId.name); @@ -68690,6 +82727,7 @@ var ts; return dupFile; } else if (file) { + // This is the first source file to have this packageId. packageIdToSourceFile.set(packageIdKey, file); sourceFileToPackageName.set(path, packageId.name); } @@ -68704,6 +82742,7 @@ var ts; file.resolvedPath = toPath(fileName); if (host.useCaseSensitiveFileNames()) { var pathLowerCase = path.toLowerCase(); + // for case-sensitive file systems check if we've already seen some file with similar filename ignoring case var existingFile = filesByNameIgnoreCase.get(pathLowerCase); if (existingFile) { reportFileNamesDifferOnlyInCasingError(fileName, existingFile.fileName, refFile, refPos, refEnd); @@ -68718,6 +82757,7 @@ var ts; processTypeReferenceDirectives(file); } processLibReferenceDirectives(file); + // always process imported modules to record module name resolutions processImportedModules(file); if (isDefaultLib) { processingDefaultLibFiles.push(file); @@ -68730,6 +82770,8 @@ var ts; } function getProjectReferenceRedirect(fileName) { var path = toPath(fileName); + // If this file is produced by a referenced project, we need to rewrite it to + // look in the output folder of the referenced project rather than the input var normalized = ts.getNormalizedAbsolutePath(fileName, path); var result; projectReferenceRedirects.forEach(function (v, k) { @@ -68745,10 +82787,11 @@ var ts; function processReferencedFiles(file, isDefaultLib) { ts.forEach(file.referencedFiles, function (ref) { var referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName); - processSourceFile(referencedFileName, isDefaultLib, false, undefined, file, ref.pos, ref.end); + processSourceFile(referencedFileName, isDefaultLib, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined, file, ref.pos, ref.end); }); } function processTypeReferenceDirectives(file) { + // We lower-case all type references because npm automatically lowercases all packages. See GH#9824. var typeDirectives = ts.map(file.typeReferenceDirectives, function (ref) { return ref.fileName.toLocaleLowerCase(); }); if (!typeDirectives) { return; @@ -68757,12 +82800,14 @@ var ts; for (var i = 0; i < typeDirectives.length; i++) { var ref = file.typeReferenceDirectives[i]; var resolvedTypeReferenceDirective = resolutions[i]; + // store resolved type directive on the file var fileName = ref.fileName.toLocaleLowerCase(); ts.setResolvedTypeReferenceDirective(file, fileName, resolvedTypeReferenceDirective); processTypeReferenceDirective(fileName, resolvedTypeReferenceDirective, file, ref.pos, ref.end); } } function processTypeReferenceDirective(typeReferenceDirective, resolvedTypeReferenceDirective, refFile, refPos, refEnd) { + // If we already found this library as a primary reference - nothing to do var previousResolution = resolvedTypeReferenceDirectives.get(typeReferenceDirective); if (previousResolution && previousResolution.primary) { return; @@ -68770,25 +82815,32 @@ var ts; var saveResolution = true; if (resolvedTypeReferenceDirective) { if (resolvedTypeReferenceDirective.primary) { - processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, false, false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd); + // resolved from the primary path + processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd); // TODO: GH#18217 } else { + // If we already resolved to this file, it must have been a secondary reference. Check file contents + // for sameness and possibly issue an error if (previousResolution) { + // Don't bother reading the file again if it's the same file. if (resolvedTypeReferenceDirective.resolvedFileName !== previousResolution.resolvedFileName) { var otherFileText = host.readFile(resolvedTypeReferenceDirective.resolvedFileName); if (otherFileText !== getSourceFile(previousResolution.resolvedFileName).text) { - fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd, ts.Diagnostics.Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict, typeReferenceDirective, resolvedTypeReferenceDirective.resolvedFileName, previousResolution.resolvedFileName)); + fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd, // TODO: GH#18217 + ts.Diagnostics.Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict, typeReferenceDirective, resolvedTypeReferenceDirective.resolvedFileName, previousResolution.resolvedFileName)); } } + // don't overwrite previous resolution result saveResolution = false; } else { - processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, false, false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd); + // First resolution of this library + processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd); } } } else { - fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd, ts.Diagnostics.Cannot_find_type_definition_file_for_0, typeReferenceDirective)); + fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd, ts.Diagnostics.Cannot_find_type_definition_file_for_0, typeReferenceDirective)); // TODO: GH#18217 } if (saveResolution) { resolvedTypeReferenceDirectives.set(typeReferenceDirective, resolvedTypeReferenceDirective); @@ -68799,7 +82851,8 @@ var ts; var libName = libReference.fileName.toLocaleLowerCase(); var libFileName = ts.libMap.get(libName); if (libFileName) { - processRootFile(ts.combinePaths(defaultLibraryPath, libFileName), true, true); + // we ignore any 'no-default-lib' reference set on this file. + processRootFile(ts.combinePaths(defaultLibraryPath, libFileName), /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ true); } else { var unqualifiedLibName = ts.removeSuffix(ts.removePrefix(libName, "lib."), ".d.ts"); @@ -68827,6 +82880,7 @@ var ts; function processImportedModules(file) { collectExternalModuleReferences(file); if (file.imports.length || file.moduleAugmentations.length) { + // Because global augmentation doesn't have string literal name, we can check for global augmentation as such. var moduleNames = getModuleNames(file); var oldProgramState = { program: oldProgram, oldSourceFile: oldProgram && oldProgram.getSourceFile(file.fileName), modifiedFilePaths: modifiedFilePaths }; var resolutions = resolveModuleNamesReusingOldState(moduleNames, ts.getNormalizedAbsolutePath(file.fileName, currentDirectory), file, oldProgramState); @@ -68844,21 +82898,28 @@ var ts; if (isFromNodeModulesSearch) { currentNodeModulesDepth++; } + // add file to program only if: + // - resolution was successful + // - noResolve is falsy + // - module name comes from the list of imports + // - it's not a top level JavaScript module that exceeded the search max var elideImport = isJsFileFromNodeModules && currentNodeModulesDepth > maxNodeModuleJsDepth; + // Don't add the file if it has a bad extension (e.g. 'tsx' if we don't have '--allowJs') + // This may still end up being an untyped module -- the file won't be included but imports will be allowed. var shouldAddFile = resolvedFileName && !getResolutionDiagnostic(options, resolution) && !options.noResolve && i < file.imports.length && !elideImport && !(isJsFile && !options.allowJs) - && (ts.isInJavaScriptFile(file.imports[i]) || !(file.imports[i].flags & 2097152)); + && (ts.isInJavaScriptFile(file.imports[i]) || !(file.imports[i].flags & 2097152 /* JSDoc */)); if (elideImport) { modulesWithElidedImports.set(file.path, true); } else if (shouldAddFile) { var path = toPath(resolvedFileName); var pos = ts.skipTrivia(file.text, file.imports[i].pos); - findSourceFile(resolvedFileName, path, false, false, file, pos, file.imports[i].end, resolution.packageId); + findSourceFile(resolvedFileName, path, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, file, pos, file.imports[i].end, resolution.packageId); } if (isFromNodeModulesSearch) { currentNodeModulesDepth--; @@ -68866,6 +82927,7 @@ var ts; } } else { + // no imports - drop cached module resolutions file.resolvedModules = undefined; } } @@ -68897,23 +82959,25 @@ var ts; return allFilesBelongToPath; } function parseProjectReferenceConfigFile(ref) { + // The actual filename (i.e. add "/tsconfig.json" if necessary) var refPath = resolveProjectReferencePath(host, ref); + // An absolute path pointing to the containing directory of the config file var basePath = ts.getNormalizedAbsolutePath(ts.getDirectoryPath(refPath), host.getCurrentDirectory()); - var sourceFile = host.getSourceFile(refPath, 100); + var sourceFile = host.getSourceFile(refPath, 100 /* JSON */); if (sourceFile === undefined) { return undefined; } - var commandLine = ts.parseJsonSourceFileConfigFileContent(sourceFile, configParsingHost, basePath, undefined, refPath); + var commandLine = ts.parseJsonSourceFileConfigFileContent(sourceFile, configParsingHost, basePath, /*existingOptions*/ undefined, refPath); return { commandLine: commandLine, sourceFile: sourceFile }; } function addProjectReferenceRedirects(referencedProject, target) { - var rootDir = ts.normalizePath(referencedProject.options.rootDir || ts.getDirectoryPath(referencedProject.options.configFilePath)); + var rootDir = ts.normalizePath(referencedProject.options.rootDir || ts.getDirectoryPath(referencedProject.options.configFilePath)); // TODO: GH#18217 target.set(rootDir, getDeclarationOutputDirectory(referencedProject)); } function getDeclarationOutputDirectory(proj) { return proj.options.declarationDir || proj.options.outDir || - ts.getDirectoryPath(proj.options.configFilePath); + ts.getDirectoryPath(proj.options.configFilePath); // TODO: GH#18217 } function verifyCompilerOptions() { if (options.strictPropertyInitialization && !options.strictNullChecks) { @@ -68972,6 +83036,7 @@ var ts; } } } + // List of collected files is complete; validate exhautiveness if this is a project with a file list if (options.composite && rootNames.length < files.length) { var normalizedRootNames = rootNames.map(function (r) { return ts.normalizePath(r).toLowerCase(); }); var sourceFiles = files.filter(function (f) { return !f.isDeclarationFile; }).map(function (f) { return ts.normalizePath(f.path).toLowerCase(); }); @@ -68991,12 +83056,12 @@ var ts; continue; } if (!ts.hasZeroOrOneAsteriskCharacter(key)) { - createDiagnosticForOptionPaths(true, key, ts.Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, key); + createDiagnosticForOptionPaths(/*onKey*/ true, key, ts.Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, key); } if (ts.isArray(options.paths[key])) { var len = options.paths[key].length; if (len === 0) { - createDiagnosticForOptionPaths(false, key, ts.Diagnostics.Substitutions_for_pattern_0_shouldn_t_be_an_empty_array, key); + createDiagnosticForOptionPaths(/*onKey*/ false, key, ts.Diagnostics.Substitutions_for_pattern_0_shouldn_t_be_an_empty_array, key); } for (var i = 0; i < len; i++) { var subst = options.paths[key][i]; @@ -69012,7 +83077,7 @@ var ts; } } else { - createDiagnosticForOptionPaths(false, key, ts.Diagnostics.Substitutions_for_pattern_0_should_be_an_array, key); + createDiagnosticForOptionPaths(/*onKey*/ false, key, ts.Diagnostics.Substitutions_for_pattern_0_should_be_an_array, key); } } } @@ -69028,6 +83093,7 @@ var ts; createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "outFile"); } if (options.mapRoot && !(options.sourceMap || options.declarationMap)) { + // Error to specify --mapRoot without --sourcemap createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "mapRoot", "sourceMap", "declarationMap"); } if (options.declarationDir) { @@ -69047,11 +83113,11 @@ var ts; if (options.noImplicitUseStrict && ts.getStrictOptionValue(options, "alwaysStrict")) { createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "noImplicitUseStrict", "alwaysStrict"); } - var languageVersion = options.target || 0; + var languageVersion = options.target || 0 /* ES3 */; var outFile = options.outFile || options.out; var firstNonAmbientExternalModuleSourceFile = ts.forEach(files, function (f) { return ts.isExternalModule(f) && !f.isDeclarationFile ? f : undefined; }); if (options.isolatedModules) { - if (options.module === ts.ModuleKind.None && languageVersion < 2) { + if (options.module === ts.ModuleKind.None && languageVersion < 2 /* ES2015 */) { createDiagnosticForOptionName(ts.Diagnostics.Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES2015_or_higher, "isolatedModules", "target"); } var firstNonExternalModuleSourceFile = ts.forEach(files, function (f) { return !ts.isExternalModule(f) && !f.isDeclarationFile ? f : undefined; }); @@ -69060,10 +83126,12 @@ var ts; programDiagnostics.add(ts.createFileDiagnostic(firstNonExternalModuleSourceFile, span.start, span.length, ts.Diagnostics.Cannot_compile_namespaces_when_the_isolatedModules_flag_is_provided)); } } - else if (firstNonAmbientExternalModuleSourceFile && languageVersion < 2 && options.module === ts.ModuleKind.None) { + else if (firstNonAmbientExternalModuleSourceFile && languageVersion < 2 /* ES2015 */ && options.module === ts.ModuleKind.None) { + // We cannot use createDiagnosticFromNode because nodes do not have parents yet var span = ts.getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator); programDiagnostics.add(ts.createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span.start, span.length, ts.Diagnostics.Cannot_use_imports_exports_or_module_augmentations_when_module_is_none)); } + // Cannot specify module gen that isn't amd or system with --out if (outFile) { if (options.module && !(options.module === ts.ModuleKind.AMD || options.module === ts.ModuleKind.System)) { createDiagnosticForOptionName(ts.Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, options.out ? "out" : "outFile", "module"); @@ -69078,10 +83146,14 @@ var ts; createDiagnosticForOptionName(ts.Diagnostics.Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy, "resolveJsonModule"); } } - if (options.outDir || - options.sourceRoot || - options.mapRoot) { + // there has to be common source directory if user specified --outdir || --sourceRoot + // if user specified --mapRoot, there needs to be common source directory if there would be multiple files being emitted + if (options.outDir || // there is --outDir specified + options.sourceRoot || // there is --sourceRoot specified + options.mapRoot) { // there is --mapRoot specified + // Precalculate and cache the common source directory var dir = getCommonSourceDirectory(); + // If we failed to find a good common directory, but outDir is specified and at least one of our files is on a windows drive/URL/other resource, add a failure if (options.outDir && dir === "" && ts.forEach(files, function (file) { return ts.getRootLength(file.fileName) > 1; })) { createDiagnosticForOptionName(ts.Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files, "outDir"); } @@ -69115,6 +83187,7 @@ var ts; else if (options.reactNamespace && !ts.isIdentifierText(options.reactNamespace, languageVersion)) { createOptionValueDiagnostic("reactNamespace", ts.Diagnostics.Invalid_value_for_reactNamespace_0_is_not_a_valid_identifier, options.reactNamespace); } + // If the emit is enabled make sure that every output file is unique and not overwriting any of the input files if (!options.noEmit && !options.suppressOutputPathCheck) { var emitHost = getEmitHost(); var emitFilesSeen_1 = ts.createMap(); @@ -69125,19 +83198,24 @@ var ts; verifyEmitFilePath(emitFileNames.declarationFilePath, emitFilesSeen_1); }); } + // Verify that all the emit files are unique and don't overwrite input files function verifyEmitFilePath(emitFileName, emitFilesSeen) { if (emitFileName) { var emitFilePath = toPath(emitFileName); + // Report error if the output overwrites input file if (filesByName.has(emitFilePath)) { var chain_2; if (!options.configFilePath) { - chain_2 = ts.chainDiagnosticMessages(undefined, ts.Diagnostics.Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript_files_Learn_more_at_https_Colon_Slash_Slashaka_ms_Slashtsconfig); + // The program is from either an inferred project or an external project + chain_2 = ts.chainDiagnosticMessages(/*details*/ undefined, ts.Diagnostics.Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript_files_Learn_more_at_https_Colon_Slash_Slashaka_ms_Slashtsconfig); } chain_2 = ts.chainDiagnosticMessages(chain_2, ts.Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file, emitFileName); blockEmittingOfFile(emitFileName, ts.createCompilerDiagnosticFromMessageChain(chain_2)); } var emitFileKey = !host.useCaseSensitiveFileNames() ? emitFilePath.toLocaleLowerCase() : emitFilePath; + // Report error if multiple files write into same file if (emitFilesSeen.has(emitFileKey)) { + // Already seen the same emit file - report error blockEmittingOfFile(emitFileName, ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_write_file_0_because_it_would_be_overwritten_by_multiple_input_files, emitFileName)); } else { @@ -69172,7 +83250,7 @@ var ts; for (var _i = 0, pathsSyntax_2 = pathsSyntax; _i < pathsSyntax_2.length; _i++) { var pathProp = pathsSyntax_2[_i]; if (ts.isObjectLiteralExpression(pathProp.initializer) && - createOptionDiagnosticInObjectLiteralSyntax(pathProp.initializer, onKey, key, undefined, message, arg0)) { + createOptionDiagnosticInObjectLiteralSyntax(pathProp.initializer, onKey, key, /*key2*/ undefined, message, arg0)) { needCompilerDiagnostic = false; } } @@ -69191,10 +83269,10 @@ var ts; return getOptionsSyntaxByName("paths") || ts.emptyArray; } function createDiagnosticForOptionName(message, option1, option2, option3) { - createDiagnosticForOption(true, option1, option2, message, option1, option2, option3); + createDiagnosticForOption(/*onKey*/ true, option1, option2, message, option1, option2, option3); } function createOptionValueDiagnostic(option1, message, arg0) { - createDiagnosticForOption(false, option1, undefined, message, arg0); + createDiagnosticForOption(/*onKey*/ false, option1, /*option2*/ undefined, message, arg0); } function createDiagnosticForReference(index, message, arg0, arg1) { var referencesSyntax = getProjectReferencesSyntax(); @@ -69215,9 +83293,9 @@ var ts; } function getProjectReferencesSyntax() { if (_referencesArrayLiteralSyntax === undefined) { - _referencesArrayLiteralSyntax = null; + _referencesArrayLiteralSyntax = null; // tslint:disable-line:no-null-keyword if (options.configFile) { - var jsonObjectLiteral = ts.getTsConfigObjectLiteralExpression(options.configFile); + var jsonObjectLiteral = ts.getTsConfigObjectLiteralExpression(options.configFile); // TODO: GH#18217 for (var _i = 0, _a = ts.getPropertyAssignment(jsonObjectLiteral, "references"); _i < _a.length; _i++) { var prop = _a[_i]; if (ts.isArrayLiteralExpression(prop.initializer)) { @@ -69231,7 +83309,7 @@ var ts; } function getCompilerOptionsObjectLiteralSyntax() { if (_compilerOptionsObjectLiteralSyntax === undefined) { - _compilerOptionsObjectLiteralSyntax = null; + _compilerOptionsObjectLiteralSyntax = null; // tslint:disable-line:no-null-keyword var jsonObjectLiteral = ts.getTsConfigObjectLiteralExpression(options.configFile); if (jsonObjectLiteral) { for (var _i = 0, _a = ts.getPropertyAssignment(jsonObjectLiteral, "compilerOptions"); _i < _a.length; _i++) { @@ -69255,10 +83333,11 @@ var ts; } function createOptionDiagnosticInArrayLiteralSyntax(arrayLiteral, index, message, arg0, arg1, arg2) { if (arrayLiteral.elements.length <= index) { + // Out-of-bounds return false; } programDiagnostics.add(ts.createDiagnosticForNodeInSourceFile(options.configFile, arrayLiteral.elements[index], message, arg0, arg1, arg2)); - return false; + return false; // TODO: GH#18217 This function always returns `false`!` } function blockEmittingOfFile(emitFileName, diag) { hasEmitBlockingDiagnostics.set(toPath(emitFileName), true); @@ -69268,32 +83347,38 @@ var ts; if (options.noEmit) { return false; } + // If this is source file, its not emitted file var filePath = toPath(file); if (getSourceFileByPath(filePath)) { return false; } + // If options have --outFile or --out just check that var out = options.outFile || options.out; if (out) { - return isSameFile(filePath, out) || isSameFile(filePath, ts.removeFileExtension(out) + ".d.ts"); + return isSameFile(filePath, out) || isSameFile(filePath, ts.removeFileExtension(out) + ".d.ts" /* Dts */); } + // If declarationDir is specified, return if its a file in that directory if (options.declarationDir && ts.containsPath(options.declarationDir, filePath, currentDirectory, !host.useCaseSensitiveFileNames())) { return true; } + // If --outDir, check if file is in that directory if (options.outDir) { return ts.containsPath(options.outDir, filePath, currentDirectory, !host.useCaseSensitiveFileNames()); } - if (ts.fileExtensionIsOneOf(filePath, ts.supportedJavascriptExtensions) || ts.fileExtensionIs(filePath, ".d.ts")) { + if (ts.fileExtensionIsOneOf(filePath, ts.supportedJavascriptExtensions) || ts.fileExtensionIs(filePath, ".d.ts" /* Dts */)) { + // Otherwise just check if sourceFile with the name exists var filePathWithoutExtension = ts.removeFileExtension(filePath); - return !!getSourceFileByPath((filePathWithoutExtension + ".ts")) || - !!getSourceFileByPath((filePathWithoutExtension + ".tsx")); + return !!getSourceFileByPath((filePathWithoutExtension + ".ts" /* Ts */)) || + !!getSourceFileByPath((filePathWithoutExtension + ".tsx" /* Tsx */)); } return false; } function isSameFile(file1, file2) { - return ts.comparePaths(file1, file2, currentDirectory, !host.useCaseSensitiveFileNames()) === 0; + return ts.comparePaths(file1, file2, currentDirectory, !host.useCaseSensitiveFileNames()) === 0 /* EqualTo */; } } ts.createProgram = createProgram; + /* @internal */ function parseConfigHostFromCompilerHost(host) { return { fileExists: function (f) { return host.fileExists(f); }, @@ -69305,6 +83390,9 @@ var ts; }; } ts.parseConfigHostFromCompilerHost = parseConfigHostFromCompilerHost; + /** + * Returns the target config filename of a project reference + */ function resolveProjectReferencePath(host, ref) { if (!host.fileExists(ref.path)) { return ts.combinePaths(ref.path, "tsconfig.json"); @@ -69312,18 +83400,25 @@ var ts; return ref.path; } ts.resolveProjectReferencePath = resolveProjectReferencePath; + /* @internal */ + /** + * Returns a DiagnosticMessage if we won't include a resolved module due to its extension. + * The DiagnosticMessage's parameters are the imported module name, and the filename it resolved to. + * This returns a diagnostic even if the module will be an untyped module. + */ function getResolutionDiagnostic(options, _a) { var extension = _a.extension; switch (extension) { - case ".ts": - case ".d.ts": - case ".json": + case ".ts" /* Ts */: + case ".d.ts" /* Dts */: + case ".json" /* Json */: // Since module is resolved to json file only when --resolveJsonModule, we dont need further check + // These are always allowed. return undefined; - case ".tsx": + case ".tsx" /* Tsx */: return needJsx(); - case ".jsx": + case ".jsx" /* Jsx */: return needJsx() || needAllowJs(); - case ".js": + case ".js" /* Js */: return needAllowJs(); } function needJsx() { @@ -69339,13 +83434,15 @@ var ts; var res = imports.map(function (i) { return i.text; }); for (var _i = 0, moduleAugmentations_1 = moduleAugmentations; _i < moduleAugmentations_1.length; _i++) { var aug = moduleAugmentations_1[_i]; - if (aug.kind === 9) { + if (aug.kind === 9 /* StringLiteral */) { res.push(aug.text); } + // Do nothing if it's an Identifier; we don't need to do module resolution for `declare global`. } return res; } })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { function getFileEmitOutput(program, sourceFile, emitOnlyDtsFiles, cancellationToken, customTransformers) { @@ -69358,11 +83455,18 @@ var ts; } ts.getFileEmitOutput = getFileEmitOutput; })(ts || (ts = {})); +/*@internal*/ (function (ts) { var BuilderState; (function (BuilderState) { + /** + * Gets the referenced files for a file from the program with values for the keys as referenced file's path to be true + */ function getReferencedFiles(program, sourceFile, getCanonicalFileName) { var referencedFiles; + // We need to use a set here since the code can contain the same import twice, + // but that will only be one dependency. + // To avoid invernal conversion, the key of the referencedFiles map must be of type Path if (sourceFile.imports && sourceFile.imports.length > 0) { var checker = program.getTypeChecker(); for (var _i = 0, _a = sourceFile.imports; _i < _a.length; _i++) { @@ -69377,6 +83481,7 @@ var ts; } } var sourceFileDirectory = ts.getDirectoryPath(sourceFile.path); + // Handle triple slash references if (sourceFile.referencedFiles && sourceFile.referencedFiles.length > 0) { for (var _b = 0, _c = sourceFile.referencedFiles; _b < _c.length; _b++) { var referencedFile = _c[_b]; @@ -69384,12 +83489,13 @@ var ts; addReferencedFile(referencedPath); } } + // Handle type reference directives if (sourceFile.resolvedTypeReferenceDirectiveNames) { sourceFile.resolvedTypeReferenceDirectiveNames.forEach(function (resolvedTypeReferenceDirective) { if (!resolvedTypeReferenceDirective) { return; } - var fileName = resolvedTypeReferenceDirective.resolvedFileName; + var fileName = resolvedTypeReferenceDirective.resolvedFileName; // TODO: GH#18217 var typeFilePath = ts.toPath(fileName, sourceFileDirectory, getCanonicalFileName); addReferencedFile(typeFilePath); }); @@ -69402,15 +83508,22 @@ var ts; referencedFiles.set(referencedPath, true); } } + /** + * Returns true if oldState is reusable, that is the emitKind = module/non module has not changed + */ function canReuseOldState(newReferencedMap, oldState) { return oldState && !oldState.referencedMap === !newReferencedMap; } BuilderState.canReuseOldState = canReuseOldState; + /** + * Creates the state of file references and signature for the new program from oldState if it is safe + */ function create(newProgram, getCanonicalFileName, oldState) { var fileInfos = ts.createMap(); var referencedMap = newProgram.getCompilerOptions().module !== ts.ModuleKind.None ? ts.createMap() : undefined; var hasCalledUpdateShapeSignature = ts.createMap(); var useOldState = canReuseOldState(referencedMap, oldState); + // Create the reference map, and set the file infos for (var _i = 0, _a = newProgram.getSourceFiles(); _i < _a.length; _i++) { var sourceFile = _a[_i]; var version_1 = sourceFile.version; @@ -69432,7 +83545,14 @@ var ts; }; } BuilderState.create = create; + /** + * Gets the files affected by the path from the program + */ function getFilesAffectedBy(state, programOfThisState, path, cancellationToken, computeHash, cacheToUpdateSignature) { + // Since the operation could be cancelled, the signatures are always stored in the cache + // They will be commited once it is safe to use them + // eg when calling this api from tsserver, if there is no cancellation of the operation + // In the other cases the affected files signatures are commited only after the iteration through the result is complete var signatureCache = cacheToUpdateSignature || ts.createMap(); var sourceFile = programOfThisState.getSourceFileByPath(path); if (!sourceFile) { @@ -69443,11 +83563,16 @@ var ts; } var result = (state.referencedMap ? getFilesAffectedByUpdatedShapeWhenModuleEmit : getFilesAffectedByUpdatedShapeWhenNonModuleEmit)(state, programOfThisState, sourceFile, signatureCache, cancellationToken, computeHash); if (!cacheToUpdateSignature) { + // Commit all the signatures in the signature cache updateSignaturesFromCache(state, signatureCache); } return result; } BuilderState.getFilesAffectedBy = getFilesAffectedBy; + /** + * Updates the signatures from the cache into state's fileinfo signatures + * This should be called whenever it is safe to commit the state of the builder + */ function updateSignaturesFromCache(state, signatureCache) { signatureCache.forEach(function (signature, path) { state.fileInfos.get(path).signature = signature; @@ -69455,8 +83580,12 @@ var ts; }); } BuilderState.updateSignaturesFromCache = updateSignaturesFromCache; + /** + * Returns if the shape of the signature has changed since last emit + */ function updateShapeSignature(state, programOfThisState, sourceFile, cacheToUpdateSignature, cancellationToken, computeHash) { ts.Debug.assert(!!sourceFile); + // If we have cached the result for this file, that means hence forth we should assume file shape is uptodate if (state.hasCalledUpdateShapeSignature.has(sourceFile.path) || cacheToUpdateSignature.has(sourceFile.path)) { return false; } @@ -69469,26 +83598,32 @@ var ts; latestSignature = sourceFile.version; } else { - var emitOutput = ts.getFileEmitOutput(programOfThisState, sourceFile, true, cancellationToken); + var emitOutput = ts.getFileEmitOutput(programOfThisState, sourceFile, /*emitOnlyDtsFiles*/ true, cancellationToken); if (emitOutput.outputFiles && emitOutput.outputFiles.length > 0) { latestSignature = computeHash(emitOutput.outputFiles[0].text); } else { - latestSignature = prevSignature; + latestSignature = prevSignature; // TODO: GH#18217 } } cacheToUpdateSignature.set(sourceFile.path, latestSignature); return !prevSignature || latestSignature !== prevSignature; } + /** + * Get all the dependencies of the sourceFile + */ function getAllDependencies(state, programOfThisState, sourceFile) { var _a; var compilerOptions = programOfThisState.getCompilerOptions(); + // With --out or --outFile all outputs go into single file, all files depend on each other if (compilerOptions.outFile || compilerOptions.out) { return getAllFileNames(state, programOfThisState); } + // If this is non module emit, or its a global file, it depends on all the source files if (!state.referencedMap || (!ts.isExternalModule(sourceFile) && !containsOnlyAmbientModules(sourceFile))) { return getAllFileNames(state, programOfThisState); } + // Get the references, traversing deep from the referenceMap var seenMap = ts.createMap(); var queue = [sourceFile.path]; while (queue.length) { @@ -69510,6 +83645,9 @@ var ts; })); } BuilderState.getAllDependencies = getAllDependencies; + /** + * Gets the names of all files from the program + */ function getAllFileNames(state, programOfThisState) { if (!state.allFileNames) { var sourceFiles = programOfThisState.getSourceFiles(); @@ -69517,12 +83655,21 @@ var ts; } return state.allFileNames; } + /** + * Gets the files referenced by the the file path + */ function getReferencedByPaths(state, referencedFilePath) { return ts.arrayFrom(ts.mapDefinedIterator(state.referencedMap.entries(), function (_a) { var filePath = _a[0], referencesInFile = _a[1]; return referencesInFile.has(referencedFilePath) ? filePath : undefined; })); } + /** + * For script files that contains only ambient external modules, although they are not actually external module files, + * they can only be consumed via importing elements from them. Regular script files cannot consume them. Therefore, + * there are no point to rebuild all script files if these special files have changed. However, if any statement + * in the file is not ambient external module, we treat it as a regular script file. + */ function containsOnlyAmbientModules(sourceFile) { for (var _i = 0, _a = sourceFile.statements; _i < _a.length; _i++) { var statement = _a[_i]; @@ -69532,7 +83679,11 @@ var ts; } return true; } + /** + * Gets all files of the program excluding the default library file + */ function getAllFilesExcludingDefaultLibraryFile(state, programOfThisState, firstSourceFile) { + // Use cached result if (state.allFilesExcludingDefaultLibraryFile) { return state.allFilesExcludingDefaultLibraryFile; } @@ -69552,13 +83703,21 @@ var ts; } } } + /** + * When program emits non modular code, gets the files affected by the sourceFile whose shape has changed + */ function getFilesAffectedByUpdatedShapeWhenNonModuleEmit(state, programOfThisState, sourceFileWithUpdatedShape) { var compilerOptions = programOfThisState.getCompilerOptions(); + // If `--out` or `--outFile` is specified, any new emit will result in re-emitting the entire project, + // so returning the file itself is good enough. if (compilerOptions && (compilerOptions.out || compilerOptions.outFile)) { return [sourceFileWithUpdatedShape]; } return getAllFilesExcludingDefaultLibraryFile(state, programOfThisState, sourceFileWithUpdatedShape); } + /** + * When program emits modular code, gets the files affected by the sourceFile whose shape has changed + */ function getFilesAffectedByUpdatedShapeWhenModuleEmit(state, programOfThisState, sourceFileWithUpdatedShape, cacheToUpdateSignature, cancellationToken, computeHash) { if (!ts.isExternalModule(sourceFileWithUpdatedShape) && !containsOnlyAmbientModules(sourceFileWithUpdatedShape)) { return getAllFilesExcludingDefaultLibraryFile(state, programOfThisState, sourceFileWithUpdatedShape); @@ -69567,7 +83726,11 @@ var ts; if (compilerOptions && (compilerOptions.isolatedModules || compilerOptions.out || compilerOptions.outFile)) { return [sourceFileWithUpdatedShape]; } + // Now we need to if each file in the referencedBy list has a shape change as well. + // Because if so, its own referencedBy files need to be saved as well to make the + // emitting result consistent with files on disk. var seenFileNamesMap = ts.createMap(); + // Start with the paths this file was referenced by seenFileNamesMap.set(sourceFileWithUpdatedShape.path, sourceFileWithUpdatedShape); var queue = getReferencedByPaths(state, sourceFileWithUpdatedShape.path); while (queue.length > 0) { @@ -69575,20 +83738,28 @@ var ts; if (!seenFileNamesMap.has(currentPath)) { var currentSourceFile = programOfThisState.getSourceFileByPath(currentPath); seenFileNamesMap.set(currentPath, currentSourceFile); - if (currentSourceFile && updateShapeSignature(state, programOfThisState, currentSourceFile, cacheToUpdateSignature, cancellationToken, computeHash)) { - queue.push.apply(queue, getReferencedByPaths(state, currentPath)); + if (currentSourceFile && updateShapeSignature(state, programOfThisState, currentSourceFile, cacheToUpdateSignature, cancellationToken, computeHash)) { // TODO: GH#18217 + queue.push.apply(// TODO: GH#18217 + queue, getReferencedByPaths(state, currentPath)); } } } + // Return array of values that needs emit + // Return array of values that needs emit return ts.arrayFrom(ts.mapDefinedIterator(seenFileNamesMap.values(), function (value) { return value; })); } })(BuilderState = ts.BuilderState || (ts.BuilderState = {})); })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { function hasSameKeys(map1, map2) { + // Has same size and every key is present in both maps return map1 === map2 || map1 !== undefined && map2 !== undefined && map1.size === map2.size && !ts.forEachKey(map1, function (key) { return !map2.has(key); }); } + /** + * Create the state so that we can iterate on changedFiles/affected files + */ function createBuilderProgramState(newProgram, getCanonicalFileName, oldState) { var state = ts.BuilderState.create(newProgram, getCanonicalFileName, oldState); state.program = newProgram; @@ -69600,27 +83771,37 @@ var ts; var useOldState = ts.BuilderState.canReuseOldState(state.referencedMap, oldState); var canCopySemanticDiagnostics = useOldState && oldState.semanticDiagnosticsPerFile && !!state.semanticDiagnosticsPerFile; if (useOldState) { + // Verify the sanity of old state if (!oldState.currentChangedFilePath) { ts.Debug.assert(!oldState.affectedFiles && (!oldState.currentAffectedFilesSignatures || !oldState.currentAffectedFilesSignatures.size), "Cannot reuse if only few affected files of currentChangedFile were iterated"); } if (canCopySemanticDiagnostics) { ts.Debug.assert(!ts.forEachKey(oldState.changedFilesSet, function (path) { return oldState.semanticDiagnosticsPerFile.has(path); }), "Semantic diagnostics shouldnt be available for changed files"); } + // Copy old state's changed files set ts.copyEntries(oldState.changedFilesSet, state.changedFilesSet); } + // Update changed files and copy semantic diagnostics if we can var referencedMap = state.referencedMap; var oldReferencedMap = useOldState ? oldState.referencedMap : undefined; state.fileInfos.forEach(function (info, sourceFilePath) { var oldInfo; var newReferences; + // if not using old state, every file is changed if (!useOldState || + // File wasnt present in old state !(oldInfo = oldState.fileInfos.get(sourceFilePath)) || + // versions dont match oldInfo.version !== info.version || + // Referenced files changed !hasSameKeys(newReferences = referencedMap && referencedMap.get(sourceFilePath), oldReferencedMap && oldReferencedMap.get(sourceFilePath)) || + // Referenced file was deleted in the new program newReferences && ts.forEachKey(newReferences, function (path) { return !state.fileInfos.has(path) && oldState.fileInfos.has(path); })) { + // Register file as changed file and do not copy semantic diagnostics, since all changed files need to be re-evaluated state.changedFilesSet.set(sourceFilePath, true); } else if (canCopySemanticDiagnostics) { + // Unchanged file copy diagnostics var diagnostics = oldState.semanticDiagnosticsPerFile.get(sourceFilePath); if (diagnostics) { state.semanticDiagnosticsPerFile.set(sourceFilePath, diagnostics); @@ -69629,18 +83810,28 @@ var ts; }); return state; } + /** + * Verifies that source file is ok to be used in calls that arent handled by next + */ function assertSourceFileOkWithoutNextAffectedCall(state, sourceFile) { ts.Debug.assert(!sourceFile || !state.affectedFiles || state.affectedFiles[state.affectedFilesIndex - 1] !== sourceFile || !state.semanticDiagnosticsPerFile.has(sourceFile.path)); } + /** + * This function returns the next affected file to be processed. + * Note that until doneAffected is called it would keep reporting same result + * This is to allow the callers to be able to actually remove affected file only when the operation is complete + * eg. if during diagnostics check cancellation token ends up cancelling the request, the affected file should be retained + */ function getNextAffectedFile(state, cancellationToken, computeHash) { while (true) { var affectedFiles = state.affectedFiles; if (affectedFiles) { var seenAffectedFiles = state.seenAffectedFiles, semanticDiagnosticsPerFile = state.semanticDiagnosticsPerFile; - var affectedFilesIndex = state.affectedFilesIndex; + var affectedFilesIndex = state.affectedFilesIndex; // TODO: GH#18217 while (affectedFilesIndex < affectedFiles.length) { var affectedFile = affectedFiles[affectedFilesIndex]; if (!seenAffectedFiles.has(affectedFile.path)) { + // Set the next affected file as seen and remove the cached semantic diagnostics state.affectedFilesIndex = affectedFilesIndex; semanticDiagnosticsPerFile.delete(affectedFile.path); return affectedFile; @@ -69648,21 +83839,28 @@ var ts; seenAffectedFiles.set(affectedFile.path, true); affectedFilesIndex++; } + // Remove the changed file from the change set state.changedFilesSet.delete(state.currentChangedFilePath); state.currentChangedFilePath = undefined; + // Commit the changes in file signature ts.BuilderState.updateSignaturesFromCache(state, state.currentAffectedFilesSignatures); state.currentAffectedFilesSignatures.clear(); state.affectedFiles = undefined; } + // Get next changed file var nextKey = state.changedFilesSet.keys().next(); if (nextKey.done) { + // Done return undefined; } + // With --out or --outFile all outputs go into single file + // so operations are performed directly on program, return program var compilerOptions = state.program.getCompilerOptions(); if (compilerOptions.outFile || compilerOptions.out) { ts.Debug.assert(!state.semanticDiagnosticsPerFile); return state.program; } + // Get next batch of affected files state.currentAffectedFilesSignatures = state.currentAffectedFilesSignatures || ts.createMap(); state.affectedFiles = ts.BuilderState.getFilesAffectedBy(state, state.program, nextKey.value, cancellationToken, computeHash, state.currentAffectedFilesSignatures); state.currentChangedFilePath = nextKey.value; @@ -69671,6 +83869,10 @@ var ts; state.seenAffectedFiles = state.seenAffectedFiles || ts.createMap(); } } + /** + * This is called after completing operation on the next affected file. + * The operations here are postponed to ensure that cancellation during the iteration is handled correctly + */ function doneWithAffectedFile(state, affected) { if (affected === state.program) { state.changedFilesSet.clear(); @@ -69680,16 +83882,25 @@ var ts; state.affectedFilesIndex++; } } + /** + * Returns the result with affected file + */ function toAffectedFileResult(state, result, affected) { doneWithAffectedFile(state, affected); return { result: result, affected: affected }; } + /** + * Gets the semantic diagnostics either from cache if present, or otherwise from program and caches it + * Note that it is assumed that the when asked about semantic diagnostics, the file has been taken out of affected files/changed file set + */ function getSemanticDiagnosticsOfFile(state, sourceFile, cancellationToken) { var path = sourceFile.path; var cachedDiagnostics = state.semanticDiagnosticsPerFile.get(path); + // Report the semantic diagnostics from the cache if we already have those diagnostics present if (cachedDiagnostics) { return cachedDiagnostics; } + // Diagnostics werent cached, get them from program, and cache the result var diagnostics = state.program.getSemanticDiagnostics(sourceFile, cancellationToken); state.semanticDiagnosticsPerFile.set(path, diagnostics); return diagnostics; @@ -69726,16 +83937,24 @@ var ts; ts.getBuilderCreationParameters = getBuilderCreationParameters; function createBuilderProgram(kind, _a) { var newProgram = _a.newProgram, host = _a.host, oldProgram = _a.oldProgram, configFileParsingDiagnostics = _a.configFileParsingDiagnostics; + // Return same program if underlying program doesnt change var oldState = oldProgram && oldProgram.getState(); if (oldState && newProgram === oldState.program && configFileParsingDiagnostics === newProgram.getConfigFileParsingDiagnostics()) { - newProgram = undefined; + newProgram = undefined; // TODO: GH#18217 oldState = undefined; return oldProgram; } + /** + * Create the canonical file name for identity + */ var getCanonicalFileName = ts.createGetCanonicalFileName(host.useCaseSensitiveFileNames()); + /** + * Computing hash to for signature verification + */ var computeHash = host.createHash || ts.identity; var state = createBuilderProgramState(newProgram, getCanonicalFileName, oldState); - newProgram = undefined; + // To ensure that we arent storing any references to old program or new program without state + newProgram = undefined; // TODO: GH#18217 oldProgram = undefined; oldState = undefined; var result = { @@ -69763,17 +83982,38 @@ var ts; ts.notImplemented(); } return result; + /** + * Emits the next affected file's emit result (EmitResult and sourceFiles emitted) or returns undefined if iteration is complete + * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host + * in that order would be used to write the files + */ function emitNextAffectedFile(writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers) { var affected = getNextAffectedFile(state, cancellationToken, computeHash); if (!affected) { + // Done return undefined; } - return toAffectedFileResult(state, state.program.emit(affected === state.program ? undefined : affected, writeFile || host.writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers), affected); + return toAffectedFileResult(state, + // When whole program is affected, do emit only once (eg when --out or --outFile is specified) + // Otherwise just affected file + state.program.emit(affected === state.program ? undefined : affected, writeFile || host.writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers), affected); } + /** + * Emits the JavaScript and declaration files. + * When targetSource file is specified, emits the files corresponding to that source file, + * otherwise for the whole program. + * In case of EmitAndSemanticDiagnosticsBuilderProgram, when targetSourceFile is specified, + * it is assumed that that file is handled from affected file list. If targetSourceFile is not specified, + * it will only emit all the affected files instead of whole program + * + * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host + * in that order would be used to write the files + */ function emit(targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers) { if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { assertSourceFileOkWithoutNextAffectedCall(state, targetSourceFile); if (!targetSourceFile) { + // Emit and report any errors we ran into. var sourceMaps = []; var emitSkipped = false; var diagnostics = void 0; @@ -69795,33 +84035,52 @@ var ts; } return state.program.emit(targetSourceFile, writeFile || host.writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers); } + /** + * Return the semantic diagnostics for the next affected file or undefined if iteration is complete + * If provided ignoreSourceFile would be called before getting the diagnostics and would ignore the sourceFile if the returned value was true + */ function getSemanticDiagnosticsOfNextAffectedFile(cancellationToken, ignoreSourceFile) { while (true) { var affected = getNextAffectedFile(state, cancellationToken, computeHash); if (!affected) { + // Done return undefined; } else if (affected === state.program) { - return toAffectedFileResult(state, state.program.getSemanticDiagnostics(undefined, cancellationToken), affected); + // When whole program is affected, get all semantic diagnostics (eg when --out or --outFile is specified) + return toAffectedFileResult(state, state.program.getSemanticDiagnostics(/*targetSourceFile*/ undefined, cancellationToken), affected); } + // Get diagnostics for the affected file if its not ignored if (ignoreSourceFile && ignoreSourceFile(affected)) { + // Get next affected file doneWithAffectedFile(state, affected); continue; } return toAffectedFileResult(state, getSemanticDiagnosticsOfFile(state, affected, cancellationToken), affected); } } + /** + * Gets the semantic diagnostics from the program corresponding to this state of file (if provided) or whole program + * The semantic diagnostics are cached and managed here + * Note that it is assumed that when asked about semantic diagnostics through this API, + * the file has been taken out of affected files so it is safe to use cache or get from program and cache the diagnostics + * In case of SemanticDiagnosticsBuilderProgram if the source file is not provided, + * it will iterate through all the affected files, to ensure that cache stays valid and yet provide a way to get all semantic diagnostics + */ function getSemanticDiagnostics(sourceFile, cancellationToken) { assertSourceFileOkWithoutNextAffectedCall(state, sourceFile); var compilerOptions = state.program.getCompilerOptions(); if (compilerOptions.outFile || compilerOptions.out) { ts.Debug.assert(!state.semanticDiagnosticsPerFile); + // We dont need to cache the diagnostics just return them from program return state.program.getSemanticDiagnostics(sourceFile, cancellationToken); } if (sourceFile) { return getSemanticDiagnosticsOfFile(state, sourceFile, cancellationToken); } if (kind === BuilderProgramKind.SemanticDiagnosticsBuilderProgram) { + // When semantic builder asks for diagnostics of the whole program, + // ensure that all the affected files are handled var affected = void 0; while (affected = getNextAffectedFile(state, cancellationToken, computeHash)) { doneWithAffectedFile(state, affected); @@ -69849,6 +84108,7 @@ var ts; function createAbstractBuilder(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics) { var program = ts.getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics).newProgram; return { + // Only return program, all other methods are not implemented getProgram: function () { return program; }, getState: ts.notImplemented, getCompilerOptions: ts.notImplemented, @@ -69866,6 +84126,7 @@ var ts; } ts.createAbstractBuilder = createAbstractBuilder; })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { ts.maxNumberOfFilesToIterateForInvalidation = 256; @@ -69874,23 +84135,35 @@ var ts; var filesWithInvalidatedResolutions; var filesWithInvalidatedNonRelativeUnresolvedImports; var allFilesHaveInvalidatedResolution = false; - var getCurrentDirectory = ts.memoize(function () { return resolutionHost.getCurrentDirectory(); }); + var getCurrentDirectory = ts.memoize(function () { return resolutionHost.getCurrentDirectory(); }); // TODO: GH#18217 var cachedDirectoryStructureHost = resolutionHost.getCachedDirectoryStructureHost(); + // The resolvedModuleNames and resolvedTypeReferenceDirectives are the cache of resolutions per file. + // The key in the map is source file's path. + // The values are Map of resolutions with key being name lookedup. var resolvedModuleNames = ts.createMap(); var perDirectoryResolvedModuleNames = ts.createMap(); var nonRelaticeModuleNameCache = ts.createMap(); var moduleResolutionCache = ts.createModuleResolutionCacheWithMaps(perDirectoryResolvedModuleNames, nonRelaticeModuleNameCache, getCurrentDirectory(), resolutionHost.getCanonicalFileName); var resolvedTypeReferenceDirectives = ts.createMap(); var perDirectoryResolvedTypeReferenceDirectives = ts.createMap(); - var failedLookupDefaultExtensions = [".ts", ".tsx", ".js", ".jsx", ".json"]; + /** + * These are the extensions that failed lookup files will have by default, + * any other extension of failed lookup will be store that path in custom failed lookup path + * This helps in not having to comb through all resolutions when files are added/removed + * Note that .d.ts file also has .d.ts extension hence will be part of default extensions + */ + var failedLookupDefaultExtensions = [".ts" /* Ts */, ".tsx" /* Tsx */, ".js" /* Js */, ".jsx" /* Jsx */, ".json" /* Json */]; var customFailedLookupPaths = ts.createMap(); var directoryWatchesOfFailedLookups = ts.createMap(); var rootDir = rootDirForResolution && ts.removeTrailingDirectorySeparator(ts.getNormalizedAbsolutePath(rootDirForResolution, getCurrentDirectory())); - var rootPath = (rootDir && resolutionHost.toPath(rootDir)); + var rootPath = (rootDir && resolutionHost.toPath(rootDir)); // TODO: GH#18217 + // TypeRoot watches for the types that get added as part of getAutomaticTypeDirectiveNames var typeRootsWatches = ts.createMap(); return { startRecordingFilesWithChangedResolutions: startRecordingFilesWithChangedResolutions, finishRecordingFilesWithChangedResolutions: finishRecordingFilesWithChangedResolutions, + // perDirectoryResolvedModuleNames and perDirectoryResolvedTypeReferenceDirectives could be non empty if there was exception during program update + // (between startCachingPerDirectoryResolution and finishCachingPerDirectoryResolution) startCachingPerDirectoryResolution: clearPerDirectoryResolutions, finishCachingPerDirectoryResolution: finishCachingPerDirectoryResolution, resolveModuleNames: resolveModuleNames, @@ -69923,6 +84196,8 @@ var ts; resolvedModuleNames.clear(); resolvedTypeReferenceDirectives.clear(); allFilesHaveInvalidatedResolution = false; + // perDirectoryResolvedModuleNames and perDirectoryResolvedTypeReferenceDirectives could be non empty if there was exception during program update + // (between startCachingPerDirectoryResolution and finishCachingPerDirectoryResolution) clearPerDirectoryResolutions(); } function startRecordingFilesWithChangedResolutions() { @@ -69937,11 +84212,13 @@ var ts; if (!filesWithInvalidatedNonRelativeUnresolvedImports) { return false; } + // Invalidated if file has unresolved imports var value = filesWithInvalidatedNonRelativeUnresolvedImports.get(path); return !!value && !!value.length; } function createHasInvalidatedResolution(forceAllFilesAsInvalidated) { if (allFilesHaveInvalidatedResolution || forceAllFilesAsInvalidated) { + // Any file asked would have invalidated resolution filesWithInvalidatedResolutions = undefined; return ts.returnTrue; } @@ -69968,16 +84245,21 @@ var ts; } function resolveModuleName(moduleName, containingFile, compilerOptions, host) { var primaryResult = ts.resolveModuleName(moduleName, containingFile, compilerOptions, host, moduleResolutionCache); + // return result immediately only if global cache support is not enabled or if it is .ts, .tsx or .d.ts if (!resolutionHost.getGlobalCache) { return primaryResult; } + // otherwise try to load typings from @types var globalCache = resolutionHost.getGlobalCache(); if (globalCache !== undefined && !ts.isExternalModuleNameRelative(moduleName) && !(primaryResult.resolvedModule && ts.extensionIsTypeScript(primaryResult.resolvedModule.extension))) { + // create different collection of failed lookup locations for second pass + // if it will fail and we've already found something during the first pass - we don't want to pollute its results var _a = ts.loadModuleFromGlobalCache(moduleName, resolutionHost.projectName, compilerOptions, host, globalCache), resolvedModule = _a.resolvedModule, failedLookupLocations = _a.failedLookupLocations; if (resolvedModule) { return { resolvedModule: resolvedModule, failedLookupLocations: ts.addRange(primaryResult.failedLookupLocations, failedLookupLocations) }; } } + // Default return the result from the first pass return primaryResult; } function resolveNamesWithLocalCache(names, containingFile, cache, perDirectoryCache, loader, getResolutionWithResolvedFileName, reusedNames, logChanges) { @@ -69996,8 +84278,10 @@ var ts; for (var _i = 0, names_2 = names; _i < names_2.length; _i++) { var name = names_2[_i]; var resolution = resolutionsInFile.get(name); + // Resolution is valid if it is present and not invalidated if (!seenNamesInFile.has(name) && allFilesHaveInvalidatedResolution || !resolution || resolution.isInvalidated || + // If the name is unresolved import that was invalidated, recalculate (hasInvalidatedNonRelativeUnresolvedImport && !ts.isExternalModuleNameRelative(name) && !getResolutionWithResolvedFileName(resolution))) { var existingResolution = resolution; var resolutionInDirectory = perDirectoryResolution.get(name); @@ -70015,13 +84299,15 @@ var ts; } if (logChanges && filesWithChangedSetOfUnresolvedImports && !resolutionIsEqualTo(existingResolution, resolution)) { filesWithChangedSetOfUnresolvedImports.push(path); + // reset log changes to avoid recording the same file multiple times logChanges = false; } } ts.Debug.assert(resolution !== undefined && !resolution.isInvalidated); seenNamesInFile.set(name, true); - resolvedModules.push(getResolutionWithResolvedFileName(resolution)); + resolvedModules.push(getResolutionWithResolvedFileName(resolution)); // TODO: GH#18217 } + // Stop watching and remove the unused name resolutionsInFile.forEach(function (resolution, name) { if (!seenNamesInFile.has(name) && !ts.contains(reusedNames, name)) { stopWatchFailedLookupLocationOfResolution(resolution); @@ -70048,7 +84334,8 @@ var ts; } } function resolveTypeReferenceDirectives(typeDirectiveNames, containingFile) { - return resolveNamesWithLocalCache(typeDirectiveNames, containingFile, resolvedTypeReferenceDirectives, perDirectoryResolvedTypeReferenceDirectives, ts.resolveTypeReferenceDirective, getResolvedTypeReferenceDirective, undefined, false); + return resolveNamesWithLocalCache(typeDirectiveNames, containingFile, resolvedTypeReferenceDirectives, perDirectoryResolvedTypeReferenceDirectives, ts.resolveTypeReferenceDirective, getResolvedTypeReferenceDirective, + /*reusedNames*/ undefined, /*logChanges*/ false); } function resolveModuleNames(moduleNames, containingFile, reusedNames) { return resolveNamesWithLocalCache(moduleNames, containingFile, resolvedModuleNames, perDirectoryResolvedModuleNames, resolveModuleName, getResolvedModule, reusedNames, logChangesWhenResolvingModule); @@ -70063,22 +84350,32 @@ var ts; function isNodeModulesAtTypesDirectory(dirPath) { return ts.endsWith(dirPath, "/node_modules/@types"); } + /** + * Filter out paths like + * "/", "/user", "/user/username", "/user/username/folderAtRoot", + * "c:/", "c:/users", "c:/users/username", "c:/users/username/folderAtRoot", "c:/folderAtRoot" + * @param dirPath + */ function canWatchDirectory(dirPath) { var rootLength = ts.getRootLength(dirPath); if (dirPath.length === rootLength) { + // Ignore "/", "c:/" return false; } var nextDirectorySeparator = dirPath.indexOf(ts.directorySeparator, rootLength); if (nextDirectorySeparator === -1) { + // ignore "/user", "c:/users" or "c:/folderAtRoot" return false; } - if (dirPath.charCodeAt(0) !== 47 && + if (dirPath.charCodeAt(0) !== 47 /* slash */ && dirPath.substr(rootLength, nextDirectorySeparator).search(/users/i) === -1) { + // Paths like c:/folderAtRoot/subFolder are allowed return true; } for (var searchIndex = nextDirectorySeparator + 1, searchLevels = 2; searchLevels > 0; searchLevels--) { searchIndex = dirPath.indexOf(ts.directorySeparator, searchIndex) + 1; if (searchIndex === 0) { + // Folder isnt at expected minimun levels return false; } } @@ -70092,19 +84389,23 @@ var ts; } function getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath) { if (isInDirectoryPath(rootPath, failedLookupLocationPath)) { - return { dir: rootDir, dirPath: rootPath }; + // Always watch root directory recursively + return { dir: rootDir, dirPath: rootPath }; // TODO: GH#18217 } return getDirectoryToWatchFromFailedLookupLocationDirectory(ts.getDirectoryPath(ts.getNormalizedAbsolutePath(failedLookupLocation, getCurrentDirectory())), ts.getDirectoryPath(failedLookupLocationPath)); } function getDirectoryToWatchFromFailedLookupLocationDirectory(dir, dirPath) { + // If directory path contains node module, get the most parent node_modules directory for watching while (ts.stringContains(dirPath, "/node_modules/")) { dir = ts.getDirectoryPath(dir); dirPath = ts.getDirectoryPath(dirPath); } + // If the directory is node_modules use it to watch, always watch it recursively if (isNodeModulesDirectory(dirPath)) { return filterFSRootDirectoriesToWatch({ dir: dir, dirPath: dirPath }, ts.getDirectoryPath(dirPath)); } var nonRecursive = true; + // Use some ancestor of the root directory var subDirectoryPath, subDirectory; if (rootPath !== undefined) { while (!isInDirectoryPath(dirPath, rootPath)) { @@ -70125,6 +84426,7 @@ var ts; return ts.fileExtensionIsOneOf(path, failedLookupDefaultExtensions); } function watchFailedLookupLocationOfResolution(resolution) { + // No need to set the resolution refCount if (!resolution.failedLookupLocations || !resolution.failedLookupLocations.length) { return; } @@ -70140,6 +84442,8 @@ var ts; var failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation); var _a = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath), dir = _a.dir, dirPath = _a.dirPath, nonRecursive = _a.nonRecursive, ignore = _a.ignore; if (!ignore) { + // If the failed lookup location path is not one of the supported extensions, + // store it in the custom path if (!isPathWithDefaultFailedLookupExtension(failedLookupLocationPath)) { var refCount = customFailedLookupPaths.get(failedLookupLocationPath) || 0; customFailedLookupPaths.set(failedLookupLocationPath, refCount + 1); @@ -70153,7 +84457,8 @@ var ts; } } if (setAtRoot) { - setDirectoryWatcher(rootDir, rootPath); + // This is always recursive + setDirectoryWatcher(rootDir, rootPath); // TODO: GH#18217 } } function setDirectoryWatcher(dir, dirPath, nonRecursive) { @@ -70205,20 +84510,23 @@ var ts; } function removeDirectoryWatcher(dirPath) { var dirWatcher = directoryWatchesOfFailedLookups.get(dirPath); + // Do not close the watcher yet since it might be needed by other failed lookup locations. dirWatcher.refCount--; } function createDirectoryWatcher(directory, dirPath, nonRecursive) { return resolutionHost.watchDirectoryOfFailedLookupLocation(directory, function (fileOrDirectory) { var fileOrDirectoryPath = resolutionHost.toPath(fileOrDirectory); if (cachedDirectoryStructureHost) { + // Since the file existence changed, update the sourceFiles cache cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); } if (!allFilesHaveInvalidatedResolution && invalidateResolutionOfFailedLookupLocation(fileOrDirectoryPath, dirPath === fileOrDirectoryPath)) { resolutionHost.onInvalidatedResolution(); } - }, nonRecursive ? 0 : 1); + }, nonRecursive ? 0 /* None */ : 1 /* Recursive */); } function removeResolutionsOfFileFromCache(cache, filePath) { + // Deleted file, stop watching failed lookups for all the resolutions in the file var resolutions = cache.get(filePath); if (resolutions) { resolutions.forEach(stopWatchFailedLookupLocationOfResolution); @@ -70244,6 +84552,7 @@ var ts; } seenInDir.set(name, true); if (!resolution.isInvalidated && isInvalidatedResolution(resolution, getResolutionWithResolvedFileName)) { + // Mark the file as needing re-evaluation of module resolution instead of using it blindly. resolution.isInvalidated = true; (filesWithInvalidatedResolutions || (filesWithInvalidatedResolutions = ts.createMap())).set(containingFilePath, true); } @@ -70255,6 +84564,8 @@ var ts; return resolvedModuleNames.size > maxSize || resolvedTypeReferenceDirectives.size > maxSize; } function invalidateResolutions(isInvalidatedResolution) { + // If more than maxNumberOfFilesToIterateForInvalidation present, + // just invalidated all files and recalculate the resolutions for files instead if (hasReachedResolutionIterationLimit()) { allFilesHaveInvalidatedResolution = true; return; @@ -70264,9 +84575,11 @@ var ts; } function invalidateResolutionOfFile(filePath) { removeResolutionsOfFile(filePath); - invalidateResolutions(function (resolution, getResolutionWithResolvedFileName) { + invalidateResolutions( + // Resolution is invalidated if the resulting file name is same as the deleted file path + function (resolution, getResolutionWithResolvedFileName) { var result = getResolutionWithResolvedFileName(resolution); - return !!result && resolutionHost.toPath(result.resolvedFileName) === filePath; + return !!result && resolutionHost.toPath(result.resolvedFileName) === filePath; // TODO: GH#18217 }); } function setFilesWithInvalidatedNonRelativeUnresolvedImports(filesMap) { @@ -70276,12 +84589,17 @@ var ts; function invalidateResolutionOfFailedLookupLocation(fileOrDirectoryPath, isCreatingWatchedDirectory) { var isChangedFailedLookupLocation; if (isCreatingWatchedDirectory) { + // Watching directory is created + // Invalidate any resolution has failed lookup in this directory isChangedFailedLookupLocation = function (location) { return isInDirectoryPath(fileOrDirectoryPath, resolutionHost.toPath(location)); }; } else { + // Some file or directory in the watching directory is created + // Return early if it does not have any of the watching extension or not the custom failed lookup path var dirOfFileOrDirectory = ts.getDirectoryPath(fileOrDirectoryPath); if (isNodeModulesAtTypesDirectory(fileOrDirectoryPath) || isNodeModulesDirectory(fileOrDirectoryPath) || isNodeModulesAtTypesDirectory(dirOfFileOrDirectory) || isNodeModulesDirectory(dirOfFileOrDirectory)) { + // Invalidate any resolution from this directory isChangedFailedLookupLocation = function (location) { var locationPath = resolutionHost.toPath(location); return locationPath === fileOrDirectoryPath || ts.startsWith(resolutionHost.toPath(location), fileOrDirectoryPath); @@ -70291,15 +84609,19 @@ var ts; if (!isPathWithDefaultFailedLookupExtension(fileOrDirectoryPath) && !customFailedLookupPaths.has(fileOrDirectoryPath)) { return false; } + // Ignore emits from the program if (ts.isEmittedFileOfProgram(resolutionHost.getCurrentProgram(), fileOrDirectoryPath)) { return false; } + // Resolution need to be invalidated if failed lookup location is same as the file or directory getting created isChangedFailedLookupLocation = function (location) { return resolutionHost.toPath(location) === fileOrDirectoryPath; }; } } var hasChangedFailedLookupLocation = function (resolution) { return ts.some(resolution.failedLookupLocations, isChangedFailedLookupLocation); }; var invalidatedFilesCount = filesWithInvalidatedResolutions && filesWithInvalidatedResolutions.size; - invalidateResolutions(hasChangedFailedLookupLocation); + invalidateResolutions( + // Resolution is invalidated if the resulting file name is same as the deleted file path + hasChangedFailedLookupLocation); return allFilesHaveInvalidatedResolution || filesWithInvalidatedResolutions && filesWithInvalidatedResolutions.size !== invalidatedFilesCount; } function closeTypeRootsWatch() { @@ -70316,24 +84638,39 @@ var ts; return !ignore && directoryWatchesOfFailedLookups.has(dirPath) ? dirPath : undefined; } function createTypeRootsWatch(typeRootPath, typeRoot) { + // Create new watch and recursive info return resolutionHost.watchTypeRootsDirectory(typeRoot, function (fileOrDirectory) { var fileOrDirectoryPath = resolutionHost.toPath(fileOrDirectory); if (cachedDirectoryStructureHost) { + // Since the file existence changed, update the sourceFiles cache cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); } + // For now just recompile + // We could potentially store more data here about whether it was/would be really be used or not + // and with that determine to trigger compilation but for now this is enough resolutionHost.onChangedAutomaticTypeDirectiveNames(); + // Since directory watchers invoked are flaky, the failed lookup location events might not be triggered + // So handle to failed lookup locations here as well to ensure we are invalidating resolutions var dirPath = getDirectoryToWatchFailedLookupLocationFromTypeRoot(typeRoot, typeRootPath); if (dirPath && invalidateResolutionOfFailedLookupLocation(fileOrDirectoryPath, dirPath === fileOrDirectoryPath)) { resolutionHost.onInvalidatedResolution(); } - }, 1); + }, 1 /* Recursive */); } + /** + * Watches the types that would get added as part of getAutomaticTypeDirectiveNames + * To be called when compiler options change + */ function updateTypeRootsWatch() { var options = resolutionHost.getCompilationSettings(); if (options.types) { + // No need to do any watch since resolution cache is going to handle the failed lookups + // for the types added by this closeTypeRootsWatch(); return; } + // we need to assume the directories exist to ensure that we can get all the type root directories that get included + // But filter directories that are at root level to say directory doesnt exist, so that we arent watching them var typeRoots = ts.getEffectiveTypeRoots(options, { directoryExists: directoryExistsForTypeRootWatch, getCurrentDirectory: getCurrentDirectory }); if (typeRoots) { ts.mutateMap(typeRootsWatches, ts.arrayToMap(typeRoots, function (tr) { return resolutionHost.toPath(tr); }), { @@ -70345,6 +84682,11 @@ var ts; closeTypeRootsWatch(); } } + /** + * Use this function to return if directory exists to get type roots to watch + * If we return directory exists then only the paths will be added to type roots + * Hence return true for all directories except root directories which are filtered from watching + */ function directoryExistsForTypeRootWatch(nodeTypesDirectory) { var dir = ts.getDirectoryPath(ts.getDirectoryPath(nodeTypesDirectory)); var dirPath = resolutionHost.toPath(dir); @@ -70353,10 +84695,13 @@ var ts; } ts.createResolutionCache = createResolutionCache; })(ts || (ts = {})); +// Used by importFixes to synthesize import module specifiers. +/* @internal */ var ts; (function (ts) { var moduleSpecifiers; (function (moduleSpecifiers) { + // Note: fromSourceFile is just for usesJsExtensionOnImports function getModuleSpecifier(compilerOptions, fromSourceFile, fromSourceFileName, toFileName, host, preferences) { if (preferences === void 0) { preferences = {}; } var info = getInfo(compilerOptions, fromSourceFile, fromSourceFileName, host); @@ -70364,6 +84709,7 @@ var ts; ts.first(getLocalModuleSpecifiers(toFileName, info, compilerOptions, preferences)); } moduleSpecifiers.getModuleSpecifier = getModuleSpecifier; + // For each symlink/original for a module, returns a list of ways to import that file. function getModuleSpecifiers(moduleSymbol, compilerOptions, importingSourceFile, host, files, preferences) { var ambient = tryGetModuleNameFromAmbientModule(moduleSymbol); if (ambient) @@ -70379,6 +84725,7 @@ var ts; }); } moduleSpecifiers.getModuleSpecifiers = getModuleSpecifiers; + // importingSourceFileName is separate because getEditsForFileRename may need to specify an updated path function getInfo(compilerOptions, importingSourceFile, importingSourceFileName, host) { var moduleResolutionKind = ts.getEmitModuleResolutionKind(compilerOptions); var addJsExtension = usesJsExtensionOnImports(importingSourceFile); @@ -70418,6 +84765,33 @@ var ts; if (isPathRelativeToParent(relativeToBaseUrl)) { return [relativePath]; } + /* + Prefer a relative import over a baseUrl import if it doesn't traverse up to baseUrl. + + Suppose we have: + baseUrl = /base + sourceDirectory = /base/a/b + moduleFileName = /base/foo/bar + Then: + relativePath = ../../foo/bar + getRelativePathNParents(relativePath) = 2 + pathFromSourceToBaseUrl = ../../ + getRelativePathNParents(pathFromSourceToBaseUrl) = 2 + 2 < 2 = false + In this case we should prefer using the baseUrl path "/a/b" instead of the relative path "../../foo/bar". + + Suppose we have: + baseUrl = /base + sourceDirectory = /base/foo/a + moduleFileName = /base/foo/bar + Then: + relativePath = ../a + getRelativePathNParents(relativePath) = 1 + pathFromSourceToBaseUrl = ../../ + getRelativePathNParents(pathFromSourceToBaseUrl) = 2 + 1 < 2 = true + In this case we should prefer using the relative path "../a" instead of the baseUrl path "foo/a". + */ var pathFromSourceToBaseUrl = ts.ensurePathIsNonModuleName(ts.getRelativePathFromDirectory(sourceDirectory, baseUrl, getCanonicalFileName)); var relativeFirst = getRelativePathNParents(relativePath) < getRelativePathNParents(pathFromSourceToBaseUrl); return relativeFirst ? [relativePath, importRelativeToBaseUrl] : [importRelativeToBaseUrl, relativePath]; @@ -70426,7 +84800,7 @@ var ts; var imports = _a.imports; return ts.firstDefined(imports, function (_a) { var text = _a.text; - return ts.pathIsRelative(text) ? ts.fileExtensionIs(text, ".js") : undefined; + return ts.pathIsRelative(text) ? ts.fileExtensionIs(text, ".js" /* Js */) : undefined; }) || false; } function discoverProbableSymlinks(files, getCanonicalFileName, host) { @@ -70459,7 +84833,7 @@ var ts; for (var _i = 0, paths_2 = paths; _i < paths_2.length; _i++) { var path = paths_2[_i]; var resolved = links.get(path); - if (compareStrings(target.slice(0, resolved.length + 1), resolved + "/") === 0) { + if (compareStrings(target.slice(0, resolved.length + 1), resolved + "/") === 0 /* EqualTo */) { var relative = ts.getRelativePathFromDirectory(resolved, target, getCanonicalFileName); var option = ts.resolvePath(path, relative); if (!host.fileExists || host.fileExists(option)) { @@ -70470,11 +84844,15 @@ var ts; } } if (options) { - options.push(target); + options.push(target); // Since these are speculative, we also include the original resolved name as a possibility return options; } return [target]; } + /** + * Looks for a existing imports that use symlinks to this module. + * Only if no symlink is available, the real path will be used. + */ function getAllModulePaths(files, _a, getCanonicalFileName, host) { var fileName = _a.fileName; var symlinks = ts.mapDefined(files, function (sf) { @@ -70537,28 +84915,36 @@ var ts; function tryGetModuleNameFromTypeRoots(options, host, getCanonicalFileName, moduleFileName, addJsExtension) { var roots = ts.getEffectiveTypeRoots(options, host); return ts.firstDefined(roots, function (unNormalizedTypeRoot) { - var typeRoot = ts.toPath(unNormalizedTypeRoot, undefined, getCanonicalFileName); + var typeRoot = ts.toPath(unNormalizedTypeRoot, /*basePath*/ undefined, getCanonicalFileName); if (ts.startsWith(moduleFileName, typeRoot)) { + // For a type definition, we can strip `/index` even with classic resolution. return removeExtensionAndIndexPostFix(moduleFileName.substring(typeRoot.length + 1), ts.ModuleResolutionKind.NodeJs, addJsExtension); } }); } function tryGetModuleNameAsNodeModule(options, moduleFileName, host, getCanonicalFileName, sourceDirectory) { if (ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.NodeJs) { + // nothing to do here return undefined; } var parts = getNodeModulePathParts(moduleFileName); if (!parts) { return undefined; } + // Simplify the full file path to something that can be resolved by Node. + // If the module could be imported by a directory name, use that directory's name var moduleSpecifier = getDirectoryOrExtensionlessFileName(moduleFileName); + // Get a path that's relative to node_modules or the importing file's path + // if node_modules folder is in this folder or any of its parent folders, no need to keep it. if (!ts.startsWith(sourceDirectory, moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex))) return undefined; + // If the module was found in @types, get the actual Node package name return ts.getPackageNameFromAtTypesDirectory(moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1)); function getDirectoryOrExtensionlessFileName(path) { + // If the file is the main module, it can be imported by the package name var packageRootPath = path.substring(0, parts.packageRootIndex); var packageJsonPath = ts.combinePaths(packageRootPath, "package.json"); - if (host.fileExists(packageJsonPath)) { + if (host.fileExists(packageJsonPath)) { // TODO: GH#18217 var packageJsonContent = JSON.parse(host.readFile(packageJsonPath)); if (packageJsonContent) { var mainFileRelative = packageJsonContent.typings || packageJsonContent.types || packageJsonContent.main; @@ -70570,7 +84956,10 @@ var ts; } } } + // We still have a file name - remove the extension var fullModulePathWithoutExtension = ts.removeFileExtension(path); + // If the file is /index, it can be imported by its directory name + // IFF there is not _also_ a file by the same name if (getCanonicalFileName(fullModulePathWithoutExtension.substring(parts.fileNameIndex)) === "/index" && !tryGetAnyFileFromPath(host, fullModulePathWithoutExtension.substring(0, parts.fileNameIndex))) { return fullModulePathWithoutExtension.substring(0, parts.fileNameIndex); } @@ -70578,16 +84967,20 @@ var ts; } } function tryGetAnyFileFromPath(host, path) { - var extensions = ts.getSupportedExtensions({ allowJs: true }, [{ extension: "node", isMixedContent: false }, { extension: "json", isMixedContent: false, scriptKind: 6 }]); + // We check all js, `node` and `json` extensions in addition to TS, since node module resolution would also choose those over the directory + var extensions = ts.getSupportedExtensions({ allowJs: true }, [{ extension: "node", isMixedContent: false }, { extension: "json", isMixedContent: false, scriptKind: 6 /* JSON */ }]); for (var _i = 0, extensions_3 = extensions; _i < extensions_3.length; _i++) { var e = extensions_3[_i]; var fullPath = path + e; - if (host.fileExists(fullPath)) { + if (host.fileExists(fullPath)) { // TODO: GH#18217 return fullPath; } } } function getNodeModulePathParts(fullPath) { + // If fullPath can't be valid module file within node_modules, returns undefined. + // Example of expected pattern: /base/path/node_modules/[@scope/otherpackage/@otherscope/node_modules/]package/[subdirectory/]file.js + // Returns indices: ^ ^ ^ ^ var topLevelNodeModulesIndex = 0; var topLevelPackageNameIndex = 0; var packageRootIndex = 0; @@ -70601,44 +84994,44 @@ var ts; })(States || (States = {})); var partStart = 0; var partEnd = 0; - var state = 0; + var state = 0 /* BeforeNodeModules */; while (partEnd >= 0) { partStart = partEnd; partEnd = fullPath.indexOf("/", partStart + 1); switch (state) { - case 0: + case 0 /* BeforeNodeModules */: if (fullPath.indexOf("/node_modules/", partStart) === partStart) { topLevelNodeModulesIndex = partStart; topLevelPackageNameIndex = partEnd; - state = 1; + state = 1 /* NodeModules */; } break; - case 1: - case 2: - if (state === 1 && fullPath.charAt(partStart + 1) === "@") { - state = 2; + case 1 /* NodeModules */: + case 2 /* Scope */: + if (state === 1 /* NodeModules */ && fullPath.charAt(partStart + 1) === "@") { + state = 2 /* Scope */; } else { packageRootIndex = partEnd; - state = 3; + state = 3 /* PackageContent */; } break; - case 3: + case 3 /* PackageContent */: if (fullPath.indexOf("/node_modules/", partStart) === partStart) { - state = 1; + state = 1 /* NodeModules */; } else { - state = 3; + state = 3 /* PackageContent */; } break; } } fileNameIndex = partStart; - return state > 1 ? { topLevelNodeModulesIndex: topLevelNodeModulesIndex, topLevelPackageNameIndex: topLevelPackageNameIndex, packageRootIndex: packageRootIndex, fileNameIndex: fileNameIndex } : undefined; + return state > 1 /* NodeModules */ ? { topLevelNodeModulesIndex: topLevelNodeModulesIndex, topLevelPackageNameIndex: topLevelPackageNameIndex, packageRootIndex: packageRootIndex, fileNameIndex: fileNameIndex } : undefined; } function getPathRelativeToRootDirs(path, rootDirs, getCanonicalFileName) { return ts.firstDefined(rootDirs, function (rootDir) { - var relativePath = getRelativePathIfInDirectory(path, rootDir, getCanonicalFileName); + var relativePath = getRelativePathIfInDirectory(path, rootDir, getCanonicalFileName); // TODO: GH#18217 return isPathRelativeToParent(relativePath) ? undefined : relativePath; }); } @@ -70651,7 +85044,7 @@ var ts; : noExtension; } function getRelativePathIfInDirectory(path, directoryPath, getCanonicalFileName) { - var relativePath = ts.getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, false); + var relativePath = ts.getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); return ts.isRootedDiskPath(relativePath) ? undefined : relativePath; } function isPathRelativeToParent(path) { @@ -70659,13 +85052,17 @@ var ts; } })(moduleSpecifiers = ts.moduleSpecifiers || (ts.moduleSpecifiers = {})); })(ts || (ts = {})); +/*@internal*/ var ts; (function (ts) { var sysFormatDiagnosticsHost = ts.sys ? { getCurrentDirectory: function () { return ts.sys.getCurrentDirectory(); }, getNewLine: function () { return ts.sys.newLine; }, getCanonicalFileName: ts.createGetCanonicalFileName(ts.sys.useCaseSensitiveFileNames) - } : undefined; + } : undefined; // TODO: GH#18217 + /** + * Create a function that reports error by writing to the system and handles the formating of the diagnostic + */ function createDiagnosticReporter(system, pretty) { var host = system === ts.sys ? sysFormatDiagnosticsHost : { getCurrentDirectory: function () { return system.getCurrentDirectory(); }, @@ -70679,14 +85076,18 @@ var ts; return function (diagnostic) { diagnostics[0] = diagnostic; system.write(ts.formatDiagnosticsWithColorAndContext(diagnostics, host) + host.getNewLine()); - diagnostics[0] = undefined; + diagnostics[0] = undefined; // TODO: GH#18217 }; } ts.createDiagnosticReporter = createDiagnosticReporter; + /** @internal */ ts.nonClearingMessageCodes = [ ts.Diagnostics.Found_1_error_Watching_for_file_changes.code, ts.Diagnostics.Found_0_errors_Watching_for_file_changes.code ]; + /** + * @returns Whether the screen was cleared. + */ function clearScreenIfNotWatchingForFileChanges(system, diagnostic, options) { if (system.clearScreen && !options.preserveWatchOutput && @@ -70698,6 +85099,7 @@ var ts; } return false; } + /** @internal */ ts.screenStartingMessageCodes = [ ts.Diagnostics.Starting_compilation_in_watch_mode.code, ts.Diagnostics.File_change_detected_Starting_incremental_compilation.code, @@ -70707,6 +85109,9 @@ var ts; ? newLine + newLine : newLine; } + /** + * Create a function that reports watch status by writing to the system and handles the formating of the diagnostic + */ function createWatchStatusReporter(system, pretty) { return pretty ? function (diagnostic, newLine, options) { @@ -70726,19 +85131,26 @@ var ts; }; } ts.createWatchStatusReporter = createWatchStatusReporter; + /** Parses config file using System interface */ function parseConfigFileWithSystem(configFileName, optionsToExtend, system, reportDiagnostic) { var host = system; host.onUnRecoverableConfigFileDiagnostic = function (diagnostic) { return reportUnrecoverableDiagnostic(ts.sys, reportDiagnostic, diagnostic); }; var result = ts.getParsedCommandLineOfConfigFile(configFileName, optionsToExtend, host); - host.onUnRecoverableConfigFileDiagnostic = undefined; + host.onUnRecoverableConfigFileDiagnostic = undefined; // TODO: GH#18217 return result; } ts.parseConfigFileWithSystem = parseConfigFileWithSystem; + /** + * Helper that emit files, report diagnostics and lists emitted and/or source files depending on compiler options + */ function emitFilesAndReportErrors(program, reportDiagnostic, writeFileName, reportSummary) { + // First get and report any syntactic errors. var diagnostics = program.getConfigFileParsingDiagnostics().slice(); var configFileParsingDiagnosticsLength = diagnostics.length; ts.addRange(diagnostics, program.getSyntacticDiagnostics()); var reportSemanticDiagnostics = false; + // If we didn't have any syntactic errors, then also try getting the global and + // semantic errors. if (diagnostics.length === configFileParsingDiagnosticsLength) { ts.addRange(diagnostics, program.getOptionsDiagnostics()); ts.addRange(diagnostics, program.getGlobalDiagnostics()); @@ -70746,6 +85158,7 @@ var ts; reportSemanticDiagnostics = true; } } + // Emit and report any errors we ran into. var _a = program.emit(), emittedFiles = _a.emittedFiles, emitSkipped = _a.emitSkipped, emitDiagnostics = _a.diagnostics; ts.addRange(diagnostics, emitDiagnostics); if (reportSemanticDiagnostics) { @@ -70768,15 +85181,21 @@ var ts; reportSummary(diagnostics.filter(function (diagnostic) { return diagnostic.category === ts.DiagnosticCategory.Error; }).length); } if (emitSkipped && diagnostics.length > 0) { + // If the emitter didn't emit anything, then pass that value along. return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped; } else if (diagnostics.length > 0) { + // The emitter emitted something, inform the caller if that happened in the presence + // of diagnostics or not. return ts.ExitStatus.DiagnosticsPresent_OutputsGenerated; } return ts.ExitStatus.Success; } ts.emitFilesAndReportErrors = emitFilesAndReportErrors; var noopFileWatcher = { close: ts.noop }; + /** + * Creates the watch compiler host that can be extended with config file or root file names and options host + */ function createWatchCompilerHost(system, createProgram, reportDiagnostic, reportWatchStatus) { if (system === void 0) { system = ts.sys; } if (!createProgram) { @@ -70836,10 +85255,16 @@ var ts; emitFilesAndReportErrors(builderProgram, reportDiagnostic, writeFileName, reportSummary); } } + /** + * Report error and exit + */ function reportUnrecoverableDiagnostic(system, reportDiagnostic, diagnostic) { reportDiagnostic(diagnostic); system.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped); } + /** + * Creates the watch compiler host from system for config file in watch mode + */ function createWatchCompilerHostOfConfigFile(configFileName, optionsToExtend, system, createProgram, reportDiagnostic, reportWatchStatus) { var diagnosticReporter = reportDiagnostic || createDiagnosticReporter(system); var host = createWatchCompilerHost(system, createProgram, diagnosticReporter, reportWatchStatus); @@ -70849,6 +85274,9 @@ var ts; return host; } ts.createWatchCompilerHostOfConfigFile = createWatchCompilerHostOfConfigFile; + /** + * Creates the watch compiler host from system for compiling root files and options in watch mode + */ function createWatchCompilerHostOfFilesAndCompilerOptions(rootFiles, options, system, createProgram, reportDiagnostic, reportWatchStatus) { var host = createWatchCompilerHost(system, createProgram, reportDiagnostic || createDiagnosticReporter(system), reportWatchStatus); host.rootFiles = rootFiles; @@ -70860,7 +85288,7 @@ var ts; (function (ts) { function createWatchCompilerHost(rootFilesOrConfigFileName, options, system, createProgram, reportDiagnostic, reportWatchStatus) { if (ts.isArray(rootFilesOrConfigFileName)) { - return ts.createWatchCompilerHostOfFilesAndCompilerOptions(rootFilesOrConfigFileName, options, system, createProgram, reportDiagnostic, reportWatchStatus); + return ts.createWatchCompilerHostOfFilesAndCompilerOptions(rootFilesOrConfigFileName, options, system, createProgram, reportDiagnostic, reportWatchStatus); // TODO: GH#18217 } else { return ts.createWatchCompilerHostOfConfigFile(rootFilesOrConfigFileName, options, system, createProgram, reportDiagnostic, reportWatchStatus); @@ -70870,14 +85298,14 @@ var ts; var initialVersion = 1; function createWatchProgram(host) { var builderProgram; - var reloadLevel; - var missingFilesMap; - var watchedWildcardDirectories; - var timerToUpdateProgram; - var sourceFilesCache = ts.createMap(); - var missingFilePathsRequestedForRelease; - var hasChangedCompilerOptions = false; - var hasChangedAutomaticTypeDirectiveNames = false; + var reloadLevel; // level to indicate if the program needs to be reloaded from config file/just filenames etc + var missingFilesMap; // Map of file watchers for the missing files + var watchedWildcardDirectories; // map of watchers for the wild card directories in the config file + var timerToUpdateProgram; // timer callback to recompile the program + var sourceFilesCache = ts.createMap(); // Cache that stores the source file and version info + var missingFilePathsRequestedForRelease; // These paths are held temparirly so that we can remove the entry from source file cache if the file is not tracked by missing files + var hasChangedCompilerOptions = false; // True if the compiler options have changed between compilations + var hasChangedAutomaticTypeDirectiveNames = false; // True if the automatic type directives have changed var useCaseSensitiveFileNames = host.useCaseSensitiveFileNames(); var currentDirectory = host.getCurrentDirectory(); var getCurrentDirectory = function () { return currentDirectory; }; @@ -70900,6 +85328,7 @@ var ts; getCurrentDirectory: getCurrentDirectory, onUnRecoverableConfigFileDiagnostic: host.onUnRecoverableConfigFileDiagnostic }; + // From tsc we want to get already parsed result and hence check for rootFileNames var newLine = updateNewLine(); reportWatchDiagnostic(ts.Diagnostics.Starting_compilation_in_watch_mode); if (configFileName) { @@ -70916,7 +85345,7 @@ var ts; var trace = host.trace && (function (s) { host.trace(s + newLine); }); var watchLogLevel = trace ? compilerOptions.extendedDiagnostics ? ts.WatchLogLevel.Verbose : compilerOptions.diagnostis ? ts.WatchLogLevel.TriggerOnly : ts.WatchLogLevel.None : ts.WatchLogLevel.None; - var writeLog = watchLogLevel !== ts.WatchLogLevel.None ? trace : ts.noop; + var writeLog = watchLogLevel !== ts.WatchLogLevel.None ? trace : ts.noop; // TODO: GH#18217 var _b = ts.getWatchFactory(watchLogLevel, writeLog), watchFile = _b.watchFile, watchFilePath = _b.watchFilePath, watchDirectory = _b.watchDirectory; var getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); writeLog("Current directory: " + currentDirectory + " CaseSensitiveFileNames: " + useCaseSensitiveFileNames); @@ -70924,6 +85353,7 @@ var ts; watchFile(host, configFileName, scheduleProgramReload, ts.PollingInterval.High, "Config file"); } var compilerHost = { + // Members for CompilerHost getSourceFile: function (fileName, languageVersion, onError, shouldCreateNewSourceFile) { return getVersionedSourceFileByPath(fileName, toPath(fileName), languageVersion, onError, shouldCreateNewSourceFile); }, getSourceFileByPath: getVersionedSourceFileByPath, getDefaultLibLocation: host.getDefaultLibLocation && (function () { return host.getDefaultLibLocation(); }), @@ -70942,6 +85372,7 @@ var ts; getEnvironmentVariable: host.getEnvironmentVariable ? (function (name) { return host.getEnvironmentVariable(name); }) : (function () { return ""; }), onReleaseOldSourceFile: onReleaseOldSourceFile, createHash: host.createHash && (function (data) { return host.createHash(data); }), + // Members for ResolutionCacheHost toPath: toPath, getCompilationSettings: function () { return compilerOptions; }, watchDirectoryOfFailedLookupLocation: function (dir, cb, flags) { return watchDirectory(host, dir, cb, flags, "Failed Lookup Locations"); }, @@ -70956,9 +85387,12 @@ var ts; getCurrentProgram: getCurrentProgram, writeLog: writeLog }; + // Cache for the module resolution var resolutionCache = ts.createResolutionCache(compilerHost, configFileName ? ts.getDirectoryPath(ts.getNormalizedAbsolutePath(configFileName, currentDirectory)) : - currentDirectory, false); + currentDirectory, + /*logChangesWhenResolvingModule*/ false); + // Resolve module using host module resolution strategy if provided otherwise use resolution cache to resolve module names compilerHost.resolveModuleNames = host.resolveModuleNames ? (function (moduleNames, containingFile, reusedNames) { return host.resolveModuleNames(moduleNames, containingFile, reusedNames); }) : (function (moduleNames, containingFile, reusedNames) { return resolutionCache.resolveModuleNames(moduleNames, containingFile, reusedNames); }); @@ -70967,6 +85401,7 @@ var ts; (function (typeDirectiveNames, containingFile) { return resolutionCache.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile); }); var userProvidedResolution = !!host.resolveModuleNames || !!host.resolveTypeReferenceDirectives; synchronizeProgram(); + // Update the wild card directory watch watchConfigFileWildCardDirectories(); return configFileName ? { getCurrentProgram: getCurrentBuilderProgram, getProgram: synchronizeProgram } : @@ -70986,10 +85421,11 @@ var ts; resolutionCache.clear(); } } + // All resolutions are invalid if user provided resolutions var hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(userProvidedResolution); if (ts.isProgramUptoDate(getCurrentProgram(), rootFileNames, compilerOptions, getSourceVersion, fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames)) { if (hasChangedConfigFileParsingErrors) { - builderProgram = createProgram(undefined, undefined, compilerHost, builderProgram, configFileParsingDiagnostics); + builderProgram = createProgram(/*rootNames*/ undefined, /*options*/ undefined, compilerHost, builderProgram, configFileParsingDiagnostics); hasChangedConfigFileParsingErrors = false; } } @@ -71002,6 +85438,7 @@ var ts; return builderProgram; } function createNewProgram(program, hasInvalidatedResolution) { + // Compile the program if (watchLogLevel !== ts.WatchLogLevel.None) { writeLog("CreatingProgramWith::"); writeLog(" roots: " + JSON.stringify(rootFileNames)); @@ -71015,11 +85452,17 @@ var ts; compilerHost.hasChangedAutomaticTypeDirectiveNames = hasChangedAutomaticTypeDirectiveNames; builderProgram = createProgram(rootFileNames, compilerOptions, compilerHost, builderProgram, configFileParsingDiagnostics); resolutionCache.finishCachingPerDirectoryResolution(); + // Update watches ts.updateMissingFilePathsWatch(builderProgram.getProgram(), missingFilesMap || (missingFilesMap = ts.createMap()), watchMissingFilePath); if (needsUpdateInTypeRootWatch) { resolutionCache.updateTypeRootsWatch(); } if (missingFilePathsRequestedForRelease) { + // These are the paths that program creater told us as not in use any more but were missing on the disk. + // We didnt remove the entry for them from sourceFiles cache so that we dont have to do File IO, + // if there is already watcher for it (for missing files) + // At this point our watches were updated, hence now we know that these paths are not tracked and need to be removed + // so that at later time we have correct result of their presence for (var _i = 0, missingFilePathsRequestedForRelease_1 = missingFilePathsRequestedForRelease; _i < missingFilePathsRequestedForRelease_1.length; _i++) { var missingFilePath = missingFilePathsRequestedForRelease_1[_i]; if (!missingFilesMap.has(missingFilePath)) { @@ -71048,6 +85491,8 @@ var ts; } function fileExists(fileName) { var path = toPath(fileName); + // If file is missing on host from cache, we can definitely say file doesnt exist + // otherwise we need to ensure from the disk if (isFileMissingOnHost(sourceFilesCache.get(path))) { return true; } @@ -71055,9 +85500,11 @@ var ts; } function getVersionedSourceFileByPath(fileName, path, languageVersion, onError, shouldCreateNewSourceFile) { var hostSourceFile = sourceFilesCache.get(path); + // No source file on the host if (isFileMissingOnHost(hostSourceFile)) { return undefined; } + // Create new source file if requested or the versions dont match if (!hostSourceFile || shouldCreateNewSourceFile || !isFilePresentOnHost(hostSourceFile) || hostSourceFile.version.toString() !== hostSourceFile.sourceFile.version) { var sourceFile = getNewSourceFile(); if (hostSourceFile) { @@ -71065,6 +85512,7 @@ var ts; hostSourceFile.version++; } if (sourceFile) { + // Set the source file and create file watcher now that file was present on the disk hostSourceFile.sourceFile = sourceFile; sourceFile.version = hostSourceFile.version.toString(); if (!hostSourceFile.fileWatcher) { @@ -71072,6 +85520,7 @@ var ts; } } else { + // There is no source file on host any more, close the watch, missing file paths will track it if (isFilePresentOnHost(hostSourceFile)) { hostSourceFile.fileWatcher.close(); } @@ -71111,6 +85560,7 @@ var ts; var hostSourceFile = sourceFilesCache.get(path); if (hostSourceFile !== undefined) { if (isFileMissingOnHost(hostSourceFile)) { + // The next version, lets set it as presence unknown file sourceFilesCache.set(path, { version: Number(hostSourceFile) + 1 }); } else { @@ -71124,7 +85574,12 @@ var ts; } function onReleaseOldSourceFile(oldSourceFile, _oldOptions) { var hostSourceFileInfo = sourceFilesCache.get(oldSourceFile.path); + // If this is the source file thats in the cache and new program doesnt need it, + // remove the cached entry. + // Note we arent deleting entry if file became missing in new program or + // there was version update and new source file was created. if (hostSourceFileInfo) { + // record the missing file paths so they can be removed later if watchers arent tracking them if (isFileMissingOnHost(hostSourceFileInfo)) { (missingFilePathsRequestedForRelease || (missingFilePathsRequestedForRelease = [])).push(oldSourceFile.path); } @@ -71142,6 +85597,9 @@ var ts; host.onWatchStatusChange(ts.createCompilerDiagnostic(message), newLine, compilerOptions || optionsToExtendForConfigFile); } } + // Upon detecting a file change, wait for 250ms and then perform a recompilation. This gives batch + // operations (such as saving all modified files in an editor) a chance to complete before we kick + // off a new compilation. function scheduleProgramUpdate() { if (!host.setTimeout || !host.clearTimeout) { return; @@ -71182,6 +85640,7 @@ var ts; hasChangedConfigFileParsingErrors = true; } rootFileNames = result.fileNames; + // Update the program synchronizeProgram(); } function reloadConfigFile() { @@ -71193,24 +85652,27 @@ var ts; parseConfigFile(); hasChangedCompilerOptions = true; synchronizeProgram(); + // Update the wild card directory watch watchConfigFileWildCardDirectories(); } function parseConfigFile() { - setConfigFileParsingResult(ts.getParsedCommandLineOfConfigFile(configFileName, optionsToExtendForConfigFile, parseConfigFileHost)); + setConfigFileParsingResult(ts.getParsedCommandLineOfConfigFile(configFileName, optionsToExtendForConfigFile, parseConfigFileHost)); // TODO: GH#18217 } function setConfigFileParsingResult(configFileParseResult) { rootFileNames = configFileParseResult.fileNames; compilerOptions = configFileParseResult.options; - configFileSpecs = configFileParseResult.configFileSpecs; + configFileSpecs = configFileParseResult.configFileSpecs; // TODO: GH#18217 configFileParsingDiagnostics = ts.getConfigFileParsingDiagnostics(configFileParseResult); hasChangedConfigFileParsingErrors = true; } function onSourceFileChange(fileName, eventKind, path) { updateCachedSystemWithFile(fileName, path, eventKind); + // Update the source file cache if (eventKind === ts.FileWatcherEventKind.Deleted && sourceFilesCache.get(path)) { resolutionCache.invalidateResolutionOfFile(path); } nextSourceFileVersion(path); + // Update the program scheduleProgramUpdate(); } function updateCachedSystemWithFile(fileName, path, eventKind) { @@ -71226,7 +85688,9 @@ var ts; if (eventKind === ts.FileWatcherEventKind.Created && missingFilesMap.has(missingFilePath)) { missingFilesMap.get(missingFilePath).close(); missingFilesMap.delete(missingFilePath); + // Delete the entry in the source files cache so that new source file is created nextSourceFileVersion(missingFilePath); + // When a missing file is created, we should update the graph. scheduleProgramUpdate(); } } @@ -71242,16 +85706,21 @@ var ts; return watchDirectory(host, directory, function (fileOrDirectory) { ts.Debug.assert(!!configFileName); var fileOrDirectoryPath = toPath(fileOrDirectory); + // Since the file existance changed, update the sourceFiles cache if (cachedDirectoryStructureHost) { cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); } nextSourceFileVersion(fileOrDirectoryPath); + // If the the added or created file or directory is not supported file name, ignore the file + // But when watched directory is added/removed, we need to reload the file list if (fileOrDirectoryPath !== directory && ts.hasExtension(fileOrDirectoryPath) && !ts.isSupportedSourceFileName(fileOrDirectory, compilerOptions)) { writeLog("Project: " + configFileName + " Detected file add/remove of non supported extension: " + fileOrDirectory); return; } + // Reload is pending, do the reload if (reloadLevel !== ts.ConfigFileProgramReloadLevel.Full) { reloadLevel = ts.ConfigFileProgramReloadLevel.Partial; + // Schedule Update the program scheduleProgramUpdate(); } }, flags, "Wild card directories"); @@ -71287,7 +85756,14 @@ var ts; var BuildResultFlags; (function (BuildResultFlags) { BuildResultFlags[BuildResultFlags["None"] = 0] = "None"; + /** + * No errors of any kind occurred during build + */ BuildResultFlags[BuildResultFlags["Success"] = 1] = "Success"; + /** + * None of the .d.ts files emitted by this build were + * different from the existing files on disk + */ BuildResultFlags[BuildResultFlags["DeclarationOutputUnchanged"] = 2] = "DeclarationOutputUnchanged"; BuildResultFlags[BuildResultFlags["ConfigFileErrors"] = 4] = "ConfigFileErrors"; BuildResultFlags[BuildResultFlags["SyntaxErrors"] = 8] = "SyntaxErrors"; @@ -71299,15 +85775,27 @@ var ts; (function (UpToDateStatusType) { UpToDateStatusType[UpToDateStatusType["Unbuildable"] = 0] = "Unbuildable"; UpToDateStatusType[UpToDateStatusType["UpToDate"] = 1] = "UpToDate"; + /** + * The project appears out of date because its upstream inputs are newer than its outputs, + * but all of its outputs are actually newer than the previous identical outputs of its (.d.ts) inputs. + * This means we can Pseudo-build (just touch timestamps), as if we had actually built this project. + */ UpToDateStatusType[UpToDateStatusType["UpToDateWithUpstreamTypes"] = 2] = "UpToDateWithUpstreamTypes"; UpToDateStatusType[UpToDateStatusType["OutputMissing"] = 3] = "OutputMissing"; UpToDateStatusType[UpToDateStatusType["OutOfDateWithSelf"] = 4] = "OutOfDateWithSelf"; UpToDateStatusType[UpToDateStatusType["OutOfDateWithUpstream"] = 5] = "OutOfDateWithUpstream"; UpToDateStatusType[UpToDateStatusType["UpstreamOutOfDate"] = 6] = "UpstreamOutOfDate"; UpToDateStatusType[UpToDateStatusType["UpstreamBlocked"] = 7] = "UpstreamBlocked"; + /** + * Projects with no outputs (i.e. "solution" files) + */ UpToDateStatusType[UpToDateStatusType["ContainerOnly"] = 8] = "ContainerOnly"; })(UpToDateStatusType = ts.UpToDateStatusType || (ts.UpToDateStatusType = {})); + /** + * A FileMap maintains a normalized-key to value relationship + */ function createFileMap() { + // tslint:disable-next-line:no-null-keyword var lookup = ts.createMap(); return { setValue: setValue, @@ -71381,14 +85869,14 @@ var ts; }; } function getOutputDeclarationFileName(inputFileName, configFile) { - var relativePath = ts.getRelativePathFromDirectory(rootDirOfOptions(configFile.options, configFile.options.configFilePath), inputFileName, true); + var relativePath = ts.getRelativePathFromDirectory(rootDirOfOptions(configFile.options, configFile.options.configFilePath), inputFileName, /*ignoreCase*/ true); var outputPath = ts.resolvePath(configFile.options.declarationDir || configFile.options.outDir || ts.getDirectoryPath(configFile.options.configFilePath), relativePath); - return ts.changeExtension(outputPath, ".d.ts"); + return ts.changeExtension(outputPath, ".d.ts" /* Dts */); } function getOutputJavaScriptFileName(inputFileName, configFile) { - var relativePath = ts.getRelativePathFromDirectory(rootDirOfOptions(configFile.options, configFile.options.configFilePath), inputFileName, true); + var relativePath = ts.getRelativePathFromDirectory(rootDirOfOptions(configFile.options, configFile.options.configFilePath), inputFileName, /*ignoreCase*/ true); var outputPath = ts.resolvePath(configFile.options.outDir || ts.getDirectoryPath(configFile.options.configFilePath), relativePath); - return ts.changeExtension(outputPath, (ts.fileExtensionIs(inputFileName, ".tsx") && configFile.options.jsx === 1) ? ".jsx" : ".js"); + return ts.changeExtension(outputPath, (ts.fileExtensionIs(inputFileName, ".tsx" /* Tsx */) && configFile.options.jsx === 1 /* Preserve */) ? ".jsx" /* Jsx */ : ".js" /* Js */); } function getOutputFileNames(inputFileName, configFile) { if (configFile.options.outFile) { @@ -71411,7 +85899,7 @@ var ts; var outputs = []; outputs.push(project.options.outFile); if (project.options.declaration) { - var dts = ts.changeExtension(project.options.outFile, ".d.ts"); + var dts = ts.changeExtension(project.options.outFile, ".d.ts" /* Dts */); outputs.push(dts); if (project.options.declarationMap) { outputs.push(dts + ".map"); @@ -71426,7 +85914,7 @@ var ts; var cache = createFileMap(); var configParseHost = ts.parseConfigHostFromCompilerHost(host); function parseConfigFile(configFilePath) { - var sourceFile = host.getSourceFile(configFilePath, 100); + var sourceFile = host.getSourceFile(configFilePath, 100 /* JSON */); if (sourceFile === undefined) { return undefined; } @@ -71447,7 +85935,7 @@ var ts; return date2 > date1 ? date2 : date1; } function isDeclarationFile(fileName) { - return ts.fileExtensionIs(fileName, ".d.ts"); + return ts.fileExtensionIs(fileName, ".d.ts" /* Dts */); } function createBuildContext(options) { var invalidatedProjects = createFileMap(); @@ -71533,8 +86021,10 @@ var ts; ts.printHelp(buildOpts, "--build "); return ts.ExitStatus.Success; } + // Not a flag, parse as filename addProject(arg); } + // Nonsensical combinations if (clean && force) { buildHost.error(ts.Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force"); return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped; @@ -71552,6 +86042,7 @@ var ts; return ts.ExitStatus.DiagnosticsPresent_OutputsSkipped; } if (projects.length === 0) { + // tsc -b invoked with no extra arguments; act as if invoked with "tsc -b ." addProject("."); } var builder = createSolutionBuilder(compilerHost, buildHost, projects, { dry: dry, force: force, verbose: verbose }, system); @@ -71576,6 +86067,10 @@ var ts; } } ts.performBuild = performBuild; + /** + * A SolutionBuilder has an immutable set of rootNames that are the "entry point" projects, but + * can dynamically add/remove other projects based on changes on the rootNames' references + */ function createSolutionBuilder(compilerHost, buildHost, rootNames, defaultOptions, system) { if (!compilerHost.getModifiedTime || !compilerHost.setModifiedTime) { throw new Error("Host must support timestamp APIs"); @@ -71611,22 +86106,26 @@ var ts; throw new Error("System host must support watchFile / watchDirectory / setTimeout if using --watch"); var graph = getGlobalDependencyGraph(); if (!graph.buildQueue) { + // Everything is broken - we don't even know what to watch. Give up. return; } var _loop_12 = function (resolved) { var cfg = configFileCache.parseConfigFile(resolved); if (cfg) { + // Watch this file system.watchFile(resolved, function () { configFileCache.removeKey(resolved); invalidateProjectAndScheduleBuilds(resolved); }); + // Update watchers for wildcard directories if (cfg.configFileSpecs) { ts.updateWatchingWildcardDirectories(existingWatchersForWildcards, ts.createMapFromTemplate(cfg.configFileSpecs.wildcardDirectories), function (dir, flags) { return system.watchDirectory(dir, function () { invalidateProjectAndScheduleBuilds(resolved); - }, !!(flags & 1)); + }, !!(flags & 1 /* Recursive */)); }); } + // Watch input files for (var _i = 0, _a = cfg.fileNames; _i < _a.length; _i++) { var input = _a[_i]; system.watchFile(input, function () { @@ -71667,6 +86166,10 @@ var ts; function invalidateProject(configFileName) { var resolved = resolveProjectName(configFileName); if (resolved === undefined) { + // If this was a rootName, we need to track it as missing. + // Otherwise we can just ignore it and have it possibly surface as an error in any downstream projects, + // if they exist + // TODO: do those things return; } configFileCache.removeKey(resolved); @@ -71676,10 +86179,12 @@ var ts; if (graph) { queueBuildForDownstreamReferences(resolved); } + // Mark all downstream projects of this one needing to be built "later" function queueBuildForDownstreamReferences(root) { var deps = graph.dependencyMap.getReferencesTo(root); for (var _i = 0, deps_1 = deps; _i < deps_1.length; _i++) { var ref = deps_1[_i]; + // Can skip circular references if (!context.queuedProjects.hasKey(ref)) { context.queuedProjects.setValue(ref, true); queueBuildForDownstreamReferences(ref); @@ -71704,10 +86209,10 @@ var ts; continue; var resolved = resolveProjectName(next); if (!resolved) - continue; + continue; // ?? var proj = configFileCache.parseConfigFile(resolved); if (!proj) - continue; + continue; // ? var status = getUpToDateStatus(proj); verboseReportProjectStatus(next, status); if (status.type === UpToDateStatusType.UpstreamBlocked) { @@ -71738,8 +86243,10 @@ var ts; }; function visit(projPath, inCircularContext) { if (inCircularContext === void 0) { inCircularContext = false; } + // Already visited if (permanentMarks[projPath]) return; + // Circular if (temporaryMarks[projPath]) { if (!inCircularContext) { hadError = true; @@ -71782,11 +86289,13 @@ var ts; resultFlags |= BuildResultFlags.DeclarationOutputUnchanged; var configFile = configFileCache.parseConfigFile(proj); if (!configFile) { + // Failed to read the config file resultFlags |= BuildResultFlags.ConfigFileErrors; context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Config file errors" }); return resultFlags; } if (configFile.fileNames.length === 0) { + // Nothing to build - must be a solution file, basically return BuildResultFlags.None; } var programOptions = { @@ -71796,6 +86305,7 @@ var ts; options: configFile.options }; var program = ts.createProgram(programOptions); + // Don't emit anything in the presence of syntactic errors or options diagnostics var syntaxDiagnostics = program.getOptionsDiagnostics().concat(program.getSyntacticDiagnostics()); if (syntaxDiagnostics.length) { resultFlags |= BuildResultFlags.SyntaxErrors; @@ -71806,6 +86316,7 @@ var ts; context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Syntactic errors" }); return resultFlags; } + // Don't emit .d.ts if there are decl file errors if (program.getCompilerOptions().declaration) { var declDiagnostics = program.getDeclarationDiagnostics(); if (declDiagnostics.length) { @@ -71818,6 +86329,7 @@ var ts; return resultFlags; } } + // Same as above but now for semantic diagnostics var semanticDiagnostics = program.getSemanticDiagnostics(); if (semanticDiagnostics.length) { resultFlags |= BuildResultFlags.TypeErrors; @@ -71829,10 +86341,11 @@ var ts; return resultFlags; } var newestDeclarationFileContentChangedTime = minimumDate; - program.emit(undefined, function (fileName, content, writeBom, onError) { + program.emit(/*targetSourceFile*/ undefined, function (fileName, content, writeBom, onError) { var priorChangeTime; if (isDeclarationFile(fileName) && compilerHost.fileExists(fileName)) { if (compilerHost.readFile(fileName) === content) { + // Check for unchanged .d.ts files resultFlags &= ~BuildResultFlags.DeclarationOutputUnchanged; priorChangeTime = compilerHost.getModifiedTime && compilerHost.getModifiedTime(fileName); } @@ -71868,6 +86381,7 @@ var ts; var resolvedNames = resolveProjectNames(configFileNames); if (resolvedNames === undefined) return undefined; + // Get the same graph for cleaning we'd use for building var graph = createDependencyGraph(resolvedNames); if (graph === undefined) return undefined; @@ -71876,6 +86390,7 @@ var ts; var proj = _a[_i]; var parsed = configFileCache.parseConfigFile(proj); if (parsed === undefined) { + // File has gone missing; fine to ignore here continue; } var outputs = getAllProjectOutputs(parsed); @@ -71912,6 +86427,7 @@ var ts; buildHost.message(ts.Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, filesToDelete.map(function (f) { return "\r\n * " + f; }).join("")); return ts.ExitStatus.Success; } + // Do this check later to allow --clean --dry to function even if the host can't delete files if (!compilerHost.deleteFile) { throw new Error("Host does not support deleting files"); } @@ -71963,12 +86479,15 @@ var ts; verboseReportProjectStatus(next, status); var projName = proj.options.configFilePath; if (status.type === UpToDateStatusType.UpToDate && !context.options.force) { + // Up to date, skip if (defaultOptions.dry) { + // In a dry build, inform the user of this fact buildHost.message(ts.Diagnostics.Project_0_is_up_to_date, projName); } continue; } if (status.type === UpToDateStatusType.UpToDateWithUpstreamTypes && !context.options.force) { + // Fake build updateOutputTimestamps(proj); continue; } @@ -71978,6 +86497,7 @@ var ts; continue; } if (status.type === UpToDateStatusType.ContainerOnly) { + // Do nothing continue; } var buildResult = buildSingleProject(next); @@ -71985,6 +86505,9 @@ var ts; } return anyFailed ? ts.ExitStatus.DiagnosticsPresent_OutputsSkipped : ts.ExitStatus.Success; } + /** + * Report the build ordering inferred from the current project graph if we're in verbose mode + */ function reportBuildQueue(graph) { if (!context.options.verbose) return; @@ -72006,6 +86529,9 @@ var ts; } buildHost.verbose.apply(buildHost, [message].concat(args)); } + /** + * Report the up-to-date status of a project if we're in verbose mode + */ function verboseReportProjectStatus(configFileName, status) { if (!context.options.verbose) return; @@ -72013,12 +86539,10 @@ var ts; } } ts.createSolutionBuilder = createSolutionBuilder; + /** + * Gets the UpToDateStatus for a project + */ function getUpToDateStatus(host, project) { - if (project === undefined) { - return { - type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" - }; - } if (project === undefined) { return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" }; } @@ -72036,6 +86560,7 @@ var ts; function getUpToDateStatusWorker(host, project) { var newestInputFileName = undefined; var newestInputFileTime = minimumDate; + // Get timestamps of input files for (var _i = 0, _a = project.fileNames; _i < _a.length; _i++) { var inputFile = _a[_i]; if (!host.fileExists(inputFile)) { @@ -72050,12 +86575,14 @@ var ts; newestInputFileTime = inputTime; } } + // Collect the expected outputs of this project var outputs = getAllProjectOutputs(project); if (outputs.length === 0) { return { type: UpToDateStatusType.ContainerOnly }; } + // Now see if all outputs are newer than the newest input var oldestOutputFileName = "(none)"; var oldestOutputFileTime = maximumDate; var newestOutputFileName = "(none)"; @@ -72065,6 +86592,8 @@ var ts; var isOutOfDateWithInputs = false; for (var _b = 0, outputs_3 = outputs; _b < outputs_3.length; _b++) { var output = outputs_3[_b]; + // Output is missing; can stop checking + // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status if (!host.fileExists(output)) { missingOutputFileName = output; break; @@ -72074,6 +86603,8 @@ var ts; oldestOutputFileTime = outputTime; oldestOutputFileName = output; } + // If an output is older than the newest input, we can stop checking + // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status if (outputTime < newestInputFileTime) { isOutOfDateWithInputs = true; break; @@ -72082,6 +86613,10 @@ var ts; newestOutputFileTime = outputTime; newestOutputFileName = output; } + // Keep track of when the most recent time a .d.ts file was changed. + // In addition to file timestamps, we also keep track of when a .d.ts file + // had its file touched but not had its contents changed - this allows us + // to skip a downstream typecheck if (isDeclarationFile(output)) { var unchangedTime = host.getUnchangedTime ? host.getUnchangedTime(output) : undefined; if (unchangedTime !== undefined) { @@ -72094,31 +86629,40 @@ var ts; } var pseudoUpToDate = false; var usesPrepend = false; + var upstreamChangedProject; if (project.projectReferences && host.parseConfigFile) { for (var _c = 0, _d = project.projectReferences; _c < _d.length; _c++) { var ref = _d[_c]; usesPrepend = usesPrepend || !!(ref.prepend); var resolvedRef = ts.resolveProjectReferencePath(host, ref); var refStatus = getUpToDateStatus(host, host.parseConfigFile(resolvedRef)); + // An upstream project is blocked if (refStatus.type === UpToDateStatusType.Unbuildable) { return { type: UpToDateStatusType.UpstreamBlocked, upstreamProjectName: ref.path }; } + // If the upstream project is out of date, then so are we (someone shouldn't have asked, though?) if (refStatus.type !== UpToDateStatusType.UpToDate) { return { type: UpToDateStatusType.UpstreamOutOfDate, upstreamProjectName: ref.path }; } + // If the upstream project's newest file is older than our oldest output, we + // can't be out of date because of it if (refStatus.newestInputFileTime <= oldestOutputFileTime) { continue; } + // If the upstream project has only change .d.ts files, and we've built + // *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild if (refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) { pseudoUpToDate = true; + upstreamChangedProject = ref.path; continue; } + // We have an output older than an upstream output - we are out of date ts.Debug.assert(oldestOutputFileName !== undefined, "Should have an oldest output filename here"); return { type: UpToDateStatusType.OutOfDateWithUpstream, @@ -72140,9 +86684,14 @@ var ts; newerInputFileName: newestInputFileName }; } - if (usesPrepend) { - pseudoUpToDate = false; + if (usesPrepend && pseudoUpToDate) { + return { + type: UpToDateStatusType.OutOfDateWithUpstream, + outOfDateOutputFileName: oldestOutputFileName, + newerProjectName: upstreamChangedProject + }; } + // Up to date return { type: pseudoUpToDate ? UpToDateStatusType.UpToDateWithUpstreamTypes : UpToDateStatusType.UpToDate, newestDeclarationFileContentChangedTime: newestDeclarationFileContentChangedTime, @@ -72179,6 +86728,7 @@ var ts; if (status.newestInputFileTime !== undefined) { return formatMessage(ts.Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, relName(configFileName), relName(status.newestInputFileName), relName(status.oldestOutputFileName)); } + // Don't report anything for "up to date because it was already built" -- too verbose break; case UpToDateStatusType.UpToDateWithUpstreamTypes: return formatMessage(ts.Diagnostics.Project_0_is_up_to_date_with_d_ts_files_from_its_dependencies, relName(configFileName)); @@ -72189,6 +86739,7 @@ var ts; case UpToDateStatusType.Unbuildable: return formatMessage(ts.Diagnostics.Failed_to_parse_file_0_Colon_1, relName(configFileName), status.reason); case UpToDateStatusType.ContainerOnly: + // Don't report status on "solution" projects break; default: ts.assertTypeIsNever(status); @@ -72196,10 +86747,12 @@ var ts; } ts.formatUpToDateStatus = formatUpToDateStatus; })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var server; (function (server) { + // tslint:disable variable-name server.ActionSet = "action::set"; server.ActionInvalidate = "action::invalidate"; server.ActionPackageInstalled = "action::packageInstalled"; @@ -72214,6 +86767,10 @@ var ts; Arguments.EnableTelemetry = "--enableTelemetry"; Arguments.TypingSafeListLocation = "--typingSafeListLocation"; Arguments.TypesMapLocation = "--typesMapLocation"; + /** + * This argument specifies the location of the NPM executable. + * typingsInstaller will run the command with `${npmLocation} install ...`. + */ Arguments.NpmLocation = "--npmLocation"; })(Arguments = server.Arguments || (server.Arguments = {})); function hasArgument(argumentName) { @@ -72227,22 +86784,27 @@ var ts; : undefined; } server.findArgument = findArgument; + /*@internal*/ function nowString() { + // E.g. "12:34:56.789" var d = new Date(); return d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds() + "." + d.getMilliseconds(); } server.nowString = nowString; })(server = ts.server || (ts.server = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var JsTyping; (function (JsTyping) { + /* @internal */ function isTypingUpToDate(cachedTyping, availableTypingVersions) { var availableVersion = ts.Semver.parse(ts.getProperty(availableTypingVersions, "ts" + ts.versionMajorMinor) || ts.getProperty(availableTypingVersions, "latest")); return !availableVersion.greaterThan(cachedTyping.version); } JsTyping.isTypingUpToDate = isTypingUpToDate; + /* @internal */ JsTyping.nodeCoreModuleList = [ "assert", "async_hooks", @@ -72281,6 +86843,7 @@ var ts; "vm", "zlib" ]; + /* @internal */ JsTyping.nodeCoreModules = ts.arrayToSet(JsTyping.nodeCoreModuleList); function loadSafeList(host, safeListPath) { var result = ts.readConfigFile(safeListPath, function (path) { return host.readFile(path); }); @@ -72295,11 +86858,22 @@ var ts; return undefined; } JsTyping.loadTypesMap = loadTypesMap; + /** + * @param host is the object providing I/O related operations. + * @param fileNames are the file names that belong to the same project + * @param projectRootPath is the path to the project root directory + * @param safeListPath is the path used to retrieve the safe list + * @param packageNameToTypingLocation is the map of package names to their cached typing locations and installed versions + * @param typeAcquisition is used to customize the typing acquisition process + * @param compilerOptions are used as a source for typing inference + */ function discoverTypings(host, log, fileNames, projectRootPath, safeList, packageNameToTypingLocation, typeAcquisition, unresolvedImports, typesRegistry) { if (!typeAcquisition || !typeAcquisition.enable) { return { cachedTypingPaths: [], newTypingNames: [], filesToWatch: [] }; } + // A typing name to typing file path mapping var inferredTypings = ts.createMap(); + // Only infer typings for .js and .jsx files fileNames = ts.mapDefined(fileNames, function (fileName) { var path = ts.normalizePath(fileName); if (ts.hasJavaScriptFileExtension(path)) { @@ -72310,6 +86884,7 @@ var ts; if (typeAcquisition.include) addInferredTypings(typeAcquisition.include, "Explicitly included types"); var exclude = typeAcquisition.exclude || []; + // Directories to search for package.json, bower.json and other typing information var possibleSearchDirs = ts.arrayToSet(fileNames, ts.getDirectoryPath); possibleSearchDirs.set(projectRootPath, true); possibleSearchDirs.forEach(function (_true, searchDir) { @@ -72323,16 +86898,19 @@ var ts; getTypingNamesFromPackagesFolder(nodeModulesPath, filesToWatch); }); getTypingNamesFromSourceFileNames(fileNames); + // add typings for unresolved imports if (unresolvedImports) { var module_1 = ts.deduplicate(unresolvedImports.map(function (moduleId) { return JsTyping.nodeCoreModules.has(moduleId) ? "node" : moduleId; }), ts.equateStringsCaseSensitive, ts.compareStringsCaseSensitive); addInferredTypings(module_1, "Inferred typings from unresolved imports"); } + // Add the cached typing locations for inferred typings that are already installed packageNameToTypingLocation.forEach(function (typing, name) { var registryEntry = typesRegistry.get(name); if (inferredTypings.has(name) && inferredTypings.get(name) === undefined && registryEntry !== undefined && isTypingUpToDate(typing, registryEntry)) { inferredTypings.set(name, typing.typingLocation); } }); + // Remove typings that the user has added to the exclude list for (var _i = 0, exclude_1 = exclude; _i < exclude_1.length; _i++) { var excludeTypingName = exclude_1[_i]; var didDelete = inferredTypings.delete(excludeTypingName); @@ -72355,7 +86933,7 @@ var ts; return result; function addInferredTyping(typingName) { if (!inferredTypings.has(typingName)) { - inferredTypings.set(typingName, undefined); + inferredTypings.set(typingName, undefined); // TODO: GH#18217 } } function addInferredTypings(typingNames, message) { @@ -72363,6 +86941,9 @@ var ts; log(message + ": " + JSON.stringify(typingNames)); ts.forEach(typingNames, addInferredTyping); } + /** + * Get the typing info from common package manager json files like package.json or bower.json + */ function getTypingNamesFromJson(jsonPath, filesToWatch) { if (!host.fileExists(jsonPath)) { return; @@ -72372,6 +86953,12 @@ var ts; var jsonTypingNames = ts.flatMap([jsonConfig.dependencies, jsonConfig.devDependencies, jsonConfig.optionalDependencies, jsonConfig.peerDependencies], ts.getOwnKeys); addInferredTypings(jsonTypingNames, "Typing names in '" + jsonPath + "' dependencies"); } + /** + * Infer typing names from given file names. For example, the file name "jquery-min.2.3.4.js" + * should be inferred to the 'jquery' typing name; and "angular-route.1.2.3.js" should be inferred + * to the 'angular-route' typing name. + * @param fileNames are the names for source files in the project + */ function getTypingNamesFromSourceFileNames(fileNames) { var fromFileNames = ts.mapDefined(fileNames, function (j) { if (!ts.hasJavaScriptFileExtension(j)) @@ -72383,19 +86970,25 @@ var ts; if (fromFileNames.length) { addInferredTypings(fromFileNames, "Inferred typings from file names"); } - var hasJsxFile = ts.some(fileNames, function (f) { return ts.fileExtensionIs(f, ".jsx"); }); + var hasJsxFile = ts.some(fileNames, function (f) { return ts.fileExtensionIs(f, ".jsx" /* Jsx */); }); if (hasJsxFile) { if (log) log("Inferred 'react' typings due to presence of '.jsx' extension"); addInferredTyping("react"); } } + /** + * Infer typing names from packages folder (ex: node_module, bower_components) + * @param packagesFolderPath is the path to the packages folder + */ function getTypingNamesFromPackagesFolder(packagesFolderPath, filesToWatch) { filesToWatch.push(packagesFolderPath); + // Todo: add support for ModuleResolutionHost too if (!host.directoryExists(packagesFolderPath)) { return; } - var fileNames = host.readDirectory(packagesFolderPath, [".json"], undefined, undefined, 2); + // depth of 2, so we access `node_modules/foo` but not `node_modules/foo/bar` + var fileNames = host.readDirectory(packagesFolderPath, [".json" /* Json */], /*excludes*/ undefined, /*includes*/ undefined, /*depth*/ 2); if (log) log("Searching for typing names in " + packagesFolderPath + "; all files: " + JSON.stringify(fileNames)); var packageNames = []; @@ -72408,10 +87001,15 @@ var ts; } var result_5 = ts.readConfigFile(normalizedFileName, function (path) { return host.readFile(path); }); var packageJson = result_5.config; + // npm 3's package.json contains a "_requiredBy" field + // we should include all the top level module names for npm 2, and only module names whose + // "_requiredBy" field starts with "#" or equals "/" for npm 3. if (baseFileName === "package.json" && packageJson._requiredBy && ts.filter(packageJson._requiredBy, function (r) { return r[0] === "#" || r === "/"; }).length === 0) { continue; } + // If the package has its own d.ts typings, those will take precedence. Otherwise the package name will be used + // to download d.ts files from DefinitelyTyped if (!packageJson.name) { continue; } @@ -72441,44 +87039,50 @@ var ts; PackageNameValidationResult[PackageNameValidationResult["NameContainsNonURISafeCharacters"] = 6] = "NameContainsNonURISafeCharacters"; })(PackageNameValidationResult = JsTyping.PackageNameValidationResult || (JsTyping.PackageNameValidationResult = {})); var maxPackageNameLength = 214; + /** + * Validates package name using rules defined at https://docs.npmjs.com/files/package.json + */ function validatePackageName(packageName) { if (!packageName) { - return 2; + return 2 /* EmptyName */; } if (packageName.length > maxPackageNameLength) { - return 3; + return 3 /* NameTooLong */; } - if (packageName.charCodeAt(0) === 46) { - return 4; + if (packageName.charCodeAt(0) === 46 /* dot */) { + return 4 /* NameStartsWithDot */; } - if (packageName.charCodeAt(0) === 95) { - return 5; + if (packageName.charCodeAt(0) === 95 /* _ */) { + return 5 /* NameStartsWithUnderscore */; } + // check if name is scope package like: starts with @ and has one '/' in the middle + // scoped packages are not currently supported + // TODO: when support will be added we'll need to split and check both scope and package name if (/^@[^/]+\/[^/]+$/.test(packageName)) { - return 1; + return 1 /* ScopedPackagesNotSupported */; } if (encodeURIComponent(packageName) !== packageName) { - return 6; + return 6 /* NameContainsNonURISafeCharacters */; } - return 0; + return 0 /* Ok */; } JsTyping.validatePackageName = validatePackageName; function renderPackageNameValidationFailure(result, typing) { switch (result) { - case 2: + case 2 /* EmptyName */: return "Package name '" + typing + "' cannot be empty"; - case 3: + case 3 /* NameTooLong */: return "Package name '" + typing + "' should be less than " + maxPackageNameLength + " characters"; - case 4: + case 4 /* NameStartsWithDot */: return "Package name '" + typing + "' cannot start with '.'"; - case 5: + case 5 /* NameStartsWithUnderscore */: return "Package name '" + typing + "' cannot start with '_'"; - case 1: + case 1 /* ScopedPackagesNotSupported */: return "Package '" + typing + "' is scoped and currently is not supported"; - case 6: + case 6 /* NameContainsNonURISafeCharacters */: return "Package name '" + typing + "' contains non URI safe characters"; - case 0: - return ts.Debug.fail(); + case 0 /* Ok */: + return ts.Debug.fail(); // Shouldn't have called this. default: throw ts.Debug.assertNever(result); } @@ -72486,6 +87090,7 @@ var ts; JsTyping.renderPackageNameValidationFailure = renderPackageNameValidationFailure; })(JsTyping = ts.JsTyping || (ts.JsTyping = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { function stringToInt(str) { @@ -72498,8 +87103,13 @@ var ts; var isPrereleaseRegex = /^(.*)-next.\d+/; var prereleaseSemverRegex = /^(\d+)\.(\d+)\.0-next.(\d+)$/; var semverRegex = /^(\d+)\.(\d+)\.(\d+)$/; - var Semver = (function () { - function Semver(major, minor, patch, isPrerelease) { + var Semver = /** @class */ (function () { + function Semver(major, minor, patch, + /** + * If true, this is `major.minor.0-next.patch`. + * If false, this is `major.minor.patch`. + */ + isPrerelease) { this.major = major; this.minor = minor; this.patch = patch; @@ -72517,7 +87127,10 @@ var ts; var major = _a.major, minor = _a.minor, patch = _a.patch, isPrerelease = _a.isPrerelease; return new Semver(major, minor, patch, isPrerelease); }; + // This must parse the output of `versionString`. Semver.tryParse = function (semver, isPrerelease) { + // Per the semver spec : + // "A normal version number MUST take the form X.Y.Z where X, Y, and Z are non-negative integers, and MUST NOT contain leading zeroes." var rgx = isPrerelease ? prereleaseSemverRegex : semverRegex; var match = rgx.exec(semver); return match ? new Semver(stringToInt(match[1]), stringToInt(match[2]), stringToInt(match[3]), isPrerelease) : undefined; @@ -72546,7 +87159,7 @@ var ts; (function (ts) { var ScriptSnapshot; (function (ScriptSnapshot) { - var StringScriptSnapshot = (function () { + var StringScriptSnapshot = /** @class */ (function () { function StringScriptSnapshot(text) { this.text = text; } @@ -72559,6 +87172,8 @@ var ts; return this.text.length; }; StringScriptSnapshot.prototype.getChangeRange = function () { + // Text-based snapshots do not support incremental parsing. Return undefined + // to signal that to the caller. return undefined; }; return StringScriptSnapshot; @@ -72568,8 +87183,9 @@ var ts; } ScriptSnapshot.fromString = fromString; })(ScriptSnapshot = ts.ScriptSnapshot || (ts.ScriptSnapshot = {})); + /* @internal */ ts.defaultPreferences = {}; - var TextChange = (function () { + var TextChange = /** @class */ (function () { function TextChange() { } return TextChange; @@ -72615,9 +87231,13 @@ var ts; })(SymbolDisplayPartKind = ts.SymbolDisplayPartKind || (ts.SymbolDisplayPartKind = {})); var OutliningSpanKind; (function (OutliningSpanKind) { + /** Single or multi-line comments */ OutliningSpanKind["Comment"] = "comment"; + /** Sections marked by '// #region' and '// #endregion' comments */ OutliningSpanKind["Region"] = "region"; + /** Declarations and expressions */ OutliningSpanKind["Code"] = "code"; + /** Contiguous blocks of import declarations */ OutliningSpanKind["Imports"] = "imports"; })(OutliningSpanKind = ts.OutliningSpanKind || (ts.OutliningSpanKind = {})); var OutputFileType; @@ -72652,27 +87272,56 @@ var ts; (function (ScriptElementKind) { ScriptElementKind["unknown"] = ""; ScriptElementKind["warning"] = "warning"; + /** predefined type (void) or keyword (class) */ ScriptElementKind["keyword"] = "keyword"; + /** top level script node */ ScriptElementKind["scriptElement"] = "script"; + /** module foo {} */ ScriptElementKind["moduleElement"] = "module"; + /** class X {} */ ScriptElementKind["classElement"] = "class"; + /** var x = class X {} */ ScriptElementKind["localClassElement"] = "local class"; + /** interface Y {} */ ScriptElementKind["interfaceElement"] = "interface"; + /** type T = ... */ ScriptElementKind["typeElement"] = "type"; + /** enum E */ ScriptElementKind["enumElement"] = "enum"; ScriptElementKind["enumMemberElement"] = "enum member"; + /** + * Inside module and script only + * const v = .. + */ ScriptElementKind["variableElement"] = "var"; + /** Inside function */ ScriptElementKind["localVariableElement"] = "local var"; + /** + * Inside module and script only + * function f() { } + */ ScriptElementKind["functionElement"] = "function"; + /** Inside function */ ScriptElementKind["localFunctionElement"] = "local function"; + /** class X { [public|private]* foo() {} } */ ScriptElementKind["memberFunctionElement"] = "method"; + /** class X { [public|private]* [get|set] foo:number; } */ ScriptElementKind["memberGetAccessorElement"] = "getter"; ScriptElementKind["memberSetAccessorElement"] = "setter"; + /** + * class X { [public|private]* foo:number; } + * interface Y { foo:number; } + */ ScriptElementKind["memberVariableElement"] = "property"; + /** class X { constructor() { } } */ ScriptElementKind["constructorImplementationElement"] = "constructor"; + /** interface Y { ():number; } */ ScriptElementKind["callSignatureElement"] = "call"; + /** interface Y { []:number; } */ ScriptElementKind["indexSignatureElement"] = "index"; + /** interface Y { new():Y; } */ ScriptElementKind["constructSignatureElement"] = "construct"; + /** function foo(*Y*: string) */ ScriptElementKind["parameterElement"] = "parameter"; ScriptElementKind["typeParameterElement"] = "type parameter"; ScriptElementKind["primitiveType"] = "primitive type"; @@ -72682,7 +87331,11 @@ var ts; ScriptElementKind["letElement"] = "let"; ScriptElementKind["directory"] = "directory"; ScriptElementKind["externalModuleName"] = "external module name"; + /** + * + */ ScriptElementKind["jsxAttribute"] = "JSX attribute"; + /** String literal */ ScriptElementKind["string"] = "string"; })(ScriptElementKind = ts.ScriptElementKind || (ts.ScriptElementKind = {})); var ScriptElementKindModifier; @@ -72751,9 +87404,11 @@ var ts; ClassificationType[ClassificationType["jsxAttributeStringLiteralValue"] = 24] = "jsxAttributeStringLiteralValue"; })(ClassificationType = ts.ClassificationType || (ts.ClassificationType = {})); })(ts || (ts = {})); +// These utilities are common to multiple language service features. +/* @internal */ var ts; (function (ts) { - ts.scanner = ts.createScanner(6, true); + ts.scanner = ts.createScanner(6 /* Latest */, /*skipTrivia*/ true); var SemanticMeaning; (function (SemanticMeaning) { SemanticMeaning[SemanticMeaning["None"] = 0] = "None"; @@ -72764,64 +87419,66 @@ var ts; })(SemanticMeaning = ts.SemanticMeaning || (ts.SemanticMeaning = {})); function getMeaningFromDeclaration(node) { switch (node.kind) { - case 149: - case 232: - case 182: - case 152: - case 151: - case 270: - case 271: - case 154: - case 153: - case 155: - case 156: - case 157: - case 234: - case 192: - case 193: - case 269: - case 262: - return 1; - case 148: - case 236: - case 237: - case 166: - return 2; - case 298: - return node.name === undefined ? 1 | 2 : 2; - case 273: - case 235: - return 1 | 2; - case 239: + case 149 /* Parameter */: + case 232 /* VariableDeclaration */: + case 182 /* BindingElement */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 270 /* PropertyAssignment */: + case 271 /* ShorthandPropertyAssignment */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 269 /* CatchClause */: + case 262 /* JsxAttribute */: + return 1 /* Value */; + case 148 /* TypeParameter */: + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 166 /* TypeLiteral */: + return 2 /* Type */; + case 298 /* JSDocTypedefTag */: + // If it has no name node, it shares the name with the value declaration below it. + return node.name === undefined ? 1 /* Value */ | 2 /* Type */ : 2 /* Type */; + case 273 /* EnumMember */: + case 235 /* ClassDeclaration */: + return 1 /* Value */ | 2 /* Type */; + case 239 /* ModuleDeclaration */: if (ts.isAmbientModule(node)) { - return 4 | 1; + return 4 /* Namespace */ | 1 /* Value */; } - else if (ts.getModuleInstanceState(node) === 1) { - return 4 | 1; + else if (ts.getModuleInstanceState(node) === 1 /* Instantiated */) { + return 4 /* Namespace */ | 1 /* Value */; } else { - return 4; + return 4 /* Namespace */; } - case 238: - case 247: - case 248: - case 243: - case 244: - case 249: - case 250: - return 7; - case 274: - return 4 | 1; + case 238 /* EnumDeclaration */: + case 247 /* NamedImports */: + case 248 /* ImportSpecifier */: + case 243 /* ImportEqualsDeclaration */: + case 244 /* ImportDeclaration */: + case 249 /* ExportAssignment */: + case 250 /* ExportDeclaration */: + return 7 /* All */; + // An external module can be a Value + case 274 /* SourceFile */: + return 4 /* Namespace */ | 1 /* Value */; } - return 7; + return 7 /* All */; } ts.getMeaningFromDeclaration = getMeaningFromDeclaration; function getMeaningFromLocation(node) { - if (node.kind === 274) { - return 1; + if (node.kind === 274 /* SourceFile */) { + return 1 /* Value */; } - else if (node.parent.kind === 249) { - return 7; + else if (node.parent.kind === 249 /* ExportAssignment */) { + return 7 /* All */; } else if (isInRightSideOfInternalImportEqualsDeclaration(node)) { return getMeaningFromRightHandSideOfImportEquals(node); @@ -72830,29 +87487,33 @@ var ts; return getMeaningFromDeclaration(node.parent); } else if (isTypeReference(node)) { - return 2; + return 2 /* Type */; } else if (isNamespaceReference(node)) { - return 4; + return 4 /* Namespace */; } else if (ts.isTypeParameterDeclaration(node.parent)) { - ts.Debug.assert(ts.isJSDocTemplateTag(node.parent.parent)); - return 2; + ts.Debug.assert(ts.isJSDocTemplateTag(node.parent.parent)); // Else would be handled by isDeclarationName + return 2 /* Type */; } else if (ts.isLiteralTypeNode(node.parent)) { - return 2 | 1; + // This might be T["name"], which is actually referencing a property and not a type. So allow both meanings. + return 2 /* Type */ | 1 /* Value */; } else { - return 1; + return 1 /* Value */; } } ts.getMeaningFromLocation = getMeaningFromLocation; function getMeaningFromRightHandSideOfImportEquals(node) { - var name = node.kind === 146 ? node : ts.isQualifiedName(node.parent) && node.parent.right === node ? node.parent : undefined; - return name && name.parent.kind === 243 ? 7 : 4; + // import a = |b|; // Namespace + // import a = |b.c|; // Value, type, namespace + // import a = |b.c|.d; // Namespace + var name = node.kind === 146 /* QualifiedName */ ? node : ts.isQualifiedName(node.parent) && node.parent.right === node ? node.parent : undefined; + return name && name.parent.kind === 243 /* ImportEqualsDeclaration */ ? 7 /* All */ : 4 /* Namespace */; } function isInRightSideOfInternalImportEqualsDeclaration(node) { - while (node.parent.kind === 146) { + while (node.parent.kind === 146 /* QualifiedName */) { node = node.parent; } return ts.isInternalModuleImportEqualsDeclaration(node.parent) && node.parent.moduleReference === node; @@ -72864,27 +87525,27 @@ var ts; function isQualifiedNameNamespaceReference(node) { var root = node; var isLastClause = true; - if (root.parent.kind === 146) { - while (root.parent && root.parent.kind === 146) { + if (root.parent.kind === 146 /* QualifiedName */) { + while (root.parent && root.parent.kind === 146 /* QualifiedName */) { root = root.parent; } isLastClause = root.right === node; } - return root.parent.kind === 162 && !isLastClause; + return root.parent.kind === 162 /* TypeReference */ && !isLastClause; } function isPropertyAccessNamespaceReference(node) { var root = node; var isLastClause = true; - if (root.parent.kind === 185) { - while (root.parent && root.parent.kind === 185) { + if (root.parent.kind === 185 /* PropertyAccessExpression */) { + while (root.parent && root.parent.kind === 185 /* PropertyAccessExpression */) { root = root.parent; } isLastClause = root.name === node; } - if (!isLastClause && root.parent.kind === 207 && root.parent.parent.kind === 268) { + if (!isLastClause && root.parent.kind === 207 /* ExpressionWithTypeArguments */ && root.parent.parent.kind === 268 /* HeritageClause */) { var decl = root.parent.parent.parent; - return (decl.kind === 235 && root.parent.parent.token === 108) || - (decl.kind === 236 && root.parent.parent.token === 85); + return (decl.kind === 235 /* ClassDeclaration */ && root.parent.parent.token === 108 /* ImplementsKeyword */) || + (decl.kind === 236 /* InterfaceDeclaration */ && root.parent.parent.token === 85 /* ExtendsKeyword */); } return false; } @@ -72893,27 +87554,27 @@ var ts; node = node.parent; } switch (node.kind) { - case 99: + case 99 /* ThisKeyword */: return !ts.isExpressionNode(node); - case 174: + case 174 /* ThisType */: return true; } switch (node.parent.kind) { - case 162: + case 162 /* TypeReference */: return true; - case 179: + case 179 /* ImportType */: return !node.parent.isTypeOf; - case 207: + case 207 /* ExpressionWithTypeArguments */: return !ts.isExpressionWithTypeArgumentsInClassExtendsClause(node.parent); } return false; } function isCallExpressionTarget(node) { - return isCallOrNewExpressionTarget(node, 187); + return isCallOrNewExpressionTarget(node, 187 /* CallExpression */); } ts.isCallExpressionTarget = isCallExpressionTarget; function isNewExpressionTarget(node) { - return isCallOrNewExpressionTarget(node, 188); + return isCallOrNewExpressionTarget(node, 188 /* NewExpression */); } ts.isNewExpressionTarget = isNewExpressionTarget; function isCallOrNewExpressionTarget(node, kind) { @@ -72926,7 +87587,7 @@ var ts; ts.climbPastPropertyAccess = climbPastPropertyAccess; function getTargetLabel(referenceNode, labelName) { while (referenceNode) { - if (referenceNode.kind === 228 && referenceNode.label.escapedText === labelName) { + if (referenceNode.kind === 228 /* LabeledStatement */ && referenceNode.label.escapedText === labelName) { return referenceNode.label; } referenceNode = referenceNode.parent; @@ -72935,11 +87596,11 @@ var ts; } ts.getTargetLabel = getTargetLabel; function isJumpStatementTarget(node) { - return node.kind === 71 && ts.isBreakOrContinueStatement(node.parent) && node.parent.label === node; + return node.kind === 71 /* Identifier */ && ts.isBreakOrContinueStatement(node.parent) && node.parent.label === node; } ts.isJumpStatementTarget = isJumpStatementTarget; function isLabelOfLabeledStatement(node) { - return node.kind === 71 && ts.isLabeledStatement(node.parent) && node.parent.label === node; + return node.kind === 71 /* Identifier */ && ts.isLabeledStatement(node.parent) && node.parent.label === node; } ts.isLabelOfLabeledStatement = isLabelOfLabeledStatement; function isLabelName(node) { @@ -72947,40 +87608,40 @@ var ts; } ts.isLabelName = isLabelName; function isRightSideOfQualifiedName(node) { - return node.parent.kind === 146 && node.parent.right === node; + return node.parent.kind === 146 /* QualifiedName */ && node.parent.right === node; } ts.isRightSideOfQualifiedName = isRightSideOfQualifiedName; function isRightSideOfPropertyAccess(node) { - return node && node.parent && node.parent.kind === 185 && node.parent.name === node; + return node && node.parent && node.parent.kind === 185 /* PropertyAccessExpression */ && node.parent.name === node; } ts.isRightSideOfPropertyAccess = isRightSideOfPropertyAccess; function isNameOfModuleDeclaration(node) { - return node.parent.kind === 239 && node.parent.name === node; + return node.parent.kind === 239 /* ModuleDeclaration */ && node.parent.name === node; } ts.isNameOfModuleDeclaration = isNameOfModuleDeclaration; function isNameOfFunctionDeclaration(node) { - return node.kind === 71 && + return node.kind === 71 /* Identifier */ && ts.isFunctionLike(node.parent) && node.parent.name === node; } ts.isNameOfFunctionDeclaration = isNameOfFunctionDeclaration; function isLiteralNameOfPropertyDeclarationOrIndexAccess(node) { switch (node.parent.kind) { - case 152: - case 151: - case 270: - case 273: - case 154: - case 153: - case 156: - case 157: - case 239: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 270 /* PropertyAssignment */: + case 273 /* EnumMember */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 239 /* ModuleDeclaration */: return ts.getNameOfDeclaration(node.parent) === node; - case 186: + case 186 /* ElementAccessExpression */: return node.parent.argumentExpression === node; - case 147: + case 147 /* ComputedPropertyName */: return true; - case 178: - return node.parent.parent.kind === 176; + case 178 /* LiteralType */: + return node.parent.parent.kind === 176 /* IndexedAccessType */; default: return false; } @@ -72993,6 +87654,9 @@ var ts; ts.isExpressionOfExternalModuleImportEqualsDeclaration = isExpressionOfExternalModuleImportEqualsDeclaration; function getContainerNode(node) { if (ts.isJSDocTypeAlias(node)) { + // This doesn't just apply to the node immediately under the comment, but to everything in its parent's scope. + // node.parent = the JSDoc comment, node.parent.parent = the node having the comment. + // Then we get parent again in the loop. node = node.parent.parent; } while (true) { @@ -73001,17 +87665,17 @@ var ts; return undefined; } switch (node.kind) { - case 274: - case 154: - case 153: - case 234: - case 192: - case 156: - case 157: - case 235: - case 236: - case 238: - case 239: + case 274 /* SourceFile */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + case 238 /* EnumDeclaration */: + case 239 /* ModuleDeclaration */: return node; } } @@ -73019,94 +87683,98 @@ var ts; ts.getContainerNode = getContainerNode; function getNodeKind(node) { switch (node.kind) { - case 274: - return ts.isExternalModule(node) ? "module" : "script"; - case 239: - return "module"; - case 235: - case 205: - return "class"; - case 236: return "interface"; - case 237: - case 292: - case 298: - return "type"; - case 238: return "enum"; - case 232: + case 274 /* SourceFile */: + return ts.isExternalModule(node) ? "module" /* moduleElement */ : "script" /* scriptElement */; + case 239 /* ModuleDeclaration */: + return "module" /* moduleElement */; + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + return "class" /* classElement */; + case 236 /* InterfaceDeclaration */: return "interface" /* interfaceElement */; + case 237 /* TypeAliasDeclaration */: + case 292 /* JSDocCallbackTag */: + case 298 /* JSDocTypedefTag */: + return "type" /* typeElement */; + case 238 /* EnumDeclaration */: return "enum" /* enumElement */; + case 232 /* VariableDeclaration */: return getKindOfVariableDeclaration(node); - case 182: + case 182 /* BindingElement */: return getKindOfVariableDeclaration(ts.getRootDeclaration(node)); - case 193: - case 234: - case 192: - return "function"; - case 156: return "getter"; - case 157: return "setter"; - case 154: - case 153: - return "method"; - case 152: - case 151: - return "property"; - case 160: return "index"; - case 159: return "construct"; - case 158: return "call"; - case 155: return "constructor"; - case 148: return "type parameter"; - case 273: return "enum member"; - case 149: return ts.hasModifier(node, 92) ? "property" : "parameter"; - case 243: - case 248: - case 245: - case 252: - case 246: - return "alias"; - case 200: + case 193 /* ArrowFunction */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + return "function" /* functionElement */; + case 156 /* GetAccessor */: return "getter" /* memberGetAccessorElement */; + case 157 /* SetAccessor */: return "setter" /* memberSetAccessorElement */; + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + return "method" /* memberFunctionElement */; + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + return "property" /* memberVariableElement */; + case 160 /* IndexSignature */: return "index" /* indexSignatureElement */; + case 159 /* ConstructSignature */: return "construct" /* constructSignatureElement */; + case 158 /* CallSignature */: return "call" /* callSignatureElement */; + case 155 /* Constructor */: return "constructor" /* constructorImplementationElement */; + case 148 /* TypeParameter */: return "type parameter" /* typeParameterElement */; + case 273 /* EnumMember */: return "enum member" /* enumMemberElement */; + case 149 /* Parameter */: return ts.hasModifier(node, 92 /* ParameterPropertyModifier */) ? "property" /* memberVariableElement */ : "parameter" /* parameterElement */; + case 243 /* ImportEqualsDeclaration */: + case 248 /* ImportSpecifier */: + case 245 /* ImportClause */: + case 252 /* ExportSpecifier */: + case 246 /* NamespaceImport */: + return "alias" /* alias */; + case 200 /* BinaryExpression */: var kind = ts.getSpecialPropertyAssignmentKind(node); var right = node.right; switch (kind) { - case 0: - return ""; - case 1: - case 2: + case 0 /* None */: + return "" /* unknown */; + case 1 /* ExportsProperty */: + case 2 /* ModuleExports */: var rightKind = getNodeKind(right); - return rightKind === "" ? "const" : rightKind; - case 3: - return ts.isFunctionExpression(right) ? "method" : "property"; - case 4: - return "property"; - case 5: - return ts.isFunctionExpression(right) ? "method" : "property"; - case 6: - return "local class"; + return rightKind === "" /* unknown */ ? "const" /* constElement */ : rightKind; + case 3 /* PrototypeProperty */: + return ts.isFunctionExpression(right) ? "method" /* memberFunctionElement */ : "property" /* memberVariableElement */; + case 4 /* ThisProperty */: + return "property" /* memberVariableElement */; // property + case 5 /* Property */: + // static method / property + return ts.isFunctionExpression(right) ? "method" /* memberFunctionElement */ : "property" /* memberVariableElement */; + case 6 /* Prototype */: + return "local class" /* localClassElement */; default: { ts.assertTypeIsNever(kind); - return ""; + return "" /* unknown */; } } default: - return ""; + return "" /* unknown */; } function getKindOfVariableDeclaration(v) { return ts.isConst(v) - ? "const" + ? "const" /* constElement */ : ts.isLet(v) - ? "let" - : "var"; + ? "let" /* letElement */ + : "var" /* variableElement */; } } ts.getNodeKind = getNodeKind; function isThis(node) { switch (node.kind) { - case 99: + case 99 /* ThisKeyword */: + // case SyntaxKind.ThisType: TODO: GH#9267 return true; - case 71: - return ts.identifierIsThisKeyword(node) && node.parent.kind === 149; + case 71 /* Identifier */: + // 'this' as a parameter + return ts.identifierIsThisKeyword(node) && node.parent.kind === 149 /* Parameter */; default: return false; } } ts.isThis = isThis; + // Matches the beginning of a triple slash directive var tripleSlashDirectivePrefixRegex = /^\/\/\/\s*= start and (position < end or (position === end && token is literal or keyword or identifier)) + */ function getTouchingPropertyName(sourceFile, position) { - return getTouchingToken(sourceFile, position, true, function (n) { return ts.isPropertyNameLiteral(n) || ts.isKeyword(n.kind); }); + return getTouchingToken(sourceFile, position, /*includeJsDocComment*/ true, function (n) { return ts.isPropertyNameLiteral(n) || ts.isKeyword(n.kind); }); } ts.getTouchingPropertyName = getTouchingPropertyName; + /** + * Returns the token if position is in [start, end). + * If position === end, returns the preceding token if includeItemAtEndPosition(previousToken) === true + */ function getTouchingToken(sourceFile, position, includeJsDocComment, includePrecedingTokenAtEndPosition) { - return getTokenAtPositionWorker(sourceFile, position, false, includePrecedingTokenAtEndPosition, false, includeJsDocComment); + return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, includePrecedingTokenAtEndPosition, /*includeEndPosition*/ false, includeJsDocComment); } ts.getTouchingToken = getTouchingToken; + /** Returns a token if position is in [start-of-leading-trivia, end) */ function getTokenAtPosition(sourceFile, position, includeJsDocComment, includeEndPosition) { if (includeEndPosition === void 0) { includeEndPosition = false; } - return getTokenAtPositionWorker(sourceFile, position, true, undefined, includeEndPosition, includeJsDocComment); + return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includePrecedingTokenAtEndPosition*/ undefined, includeEndPosition, includeJsDocComment); } ts.getTokenAtPosition = getTokenAtPosition; + /** Get the token whose text contains the position */ function getTokenAtPositionWorker(sourceFile, position, allowPositionInLeadingTrivia, includePrecedingTokenAtEndPosition, includeEndPosition, includeJsDocComment) { var current = sourceFile; outer: while (true) { if (ts.isToken(current)) { + // exit early return current; } + // find the child that contains 'position' for (var _i = 0, _a = current.getChildren(); _i < _a.length; _i++) { var child = _a[_i]; if (!includeJsDocComment && ts.isJSDocNode(child)) { @@ -73324,10 +88025,11 @@ var ts; } var start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile, includeJsDocComment); if (start > position) { + // If this child begins after position, then all subsequent children will as well. break; } var end = child.getEnd(); - if (position < end || (position === end && (child.kind === 1 || includeEndPosition))) { + if (position < end || (position === end && (child.kind === 1 /* EndOfFileToken */ || includeEndPosition))) { current = child; continue outer; } @@ -73341,8 +88043,18 @@ var ts; return current; } } + /** + * The token on the left of the position is the token that strictly includes the position + * or sits to the left of the cursor if it is on a boundary. For example + * + * fo|o -> will return foo + * foo |bar -> will return foo + * + */ function findTokenOnLeftOfPosition(file, position) { - var tokenAtPosition = getTokenAtPosition(file, position, false); + // Ideally, getTokenAtPosition should return a token. However, it is currently + // broken, so we do a check to make sure the result was indeed a token. + var tokenAtPosition = getTokenAtPosition(file, position, /*includeJsDocComment*/ false); if (ts.isToken(tokenAtPosition) && position > tokenAtPosition.getStart(file) && position < tokenAtPosition.getEnd()) { return tokenAtPosition; } @@ -73353,12 +88065,16 @@ var ts; return find(parent); function find(n) { if (ts.isToken(n) && n.pos === previousToken.end) { + // this is token that starts at the end of previous token - return it return n; } var children = n.getChildren(); for (var _i = 0, children_3 = children; _i < children_3.length; _i++) { var child = children_3[_i]; - var shouldDiveInChildNode = (child.pos <= previousToken.pos && child.end > previousToken.end) || + var shouldDiveInChildNode = + // previous token is enclosed somewhere in the child + (child.pos <= previousToken.pos && child.end > previousToken.end) || + // previous token ends exactly at the beginning of child (child.pos === previousToken.end); if (shouldDiveInChildNode && nodeHasTokens(child, sourceFile)) { return find(child); @@ -73368,6 +88084,10 @@ var ts; } } ts.findNextToken = findNextToken; + /** + * Finds the rightmost token satisfying `token.end <= position`, + * excluding `JsxText` tokens containing only whitespace. + */ function findPrecedingToken(position, sourceFile, startNode, includeJsDoc) { var result = find(startNode || sourceFile); ts.Debug.assert(!(result && isWhiteSpaceOnlyJsxText(result))); @@ -73379,23 +88099,34 @@ var ts; var children = n.getChildren(sourceFile); for (var i = 0; i < children.length; i++) { var child = children[i]; + // Note that the span of a node's tokens is [node.getStart(...), node.end). + // Given that `position < child.end` and child has constituent tokens, we distinguish these cases: + // 1) `position` precedes `child`'s tokens or `child` has no tokens (ie: in a comment or whitespace preceding `child`): + // we need to find the last token in a previous child. + // 2) `position` is within the same span: we recurse on `child`. if (position < child.end) { var start = child.getStart(sourceFile, includeJsDoc); - var lookInPreviousChild = (start >= position) || + var lookInPreviousChild = (start >= position) || // cursor in the leading trivia !nodeHasTokens(child, sourceFile) || isWhiteSpaceOnlyJsxText(child); if (lookInPreviousChild) { - var candidate = findRightmostChildNodeWithTokens(children, i, sourceFile); + // actual start of the node is past the position - previous token should be at the end of previous child + var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i, sourceFile); return candidate && findRightmostToken(candidate, sourceFile); } else { + // candidate should be in this node return find(child); } } } - ts.Debug.assert(startNode !== undefined || n.kind === 274 || ts.isJSDocCommentContainingNode(n)); + ts.Debug.assert(startNode !== undefined || n.kind === 274 /* SourceFile */ || ts.isJSDocCommentContainingNode(n)); + // Here we know that none of child token nodes embrace the position, + // the only known case is when position is at the end of the file. + // Try to find the rightmost token in the file without filtering. + // Namely we are skipping the check: 'position < node.end' if (children.length) { - var candidate = findRightmostChildNodeWithTokens(children, children.length, sourceFile); + var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length, sourceFile); return candidate && findRightmostToken(candidate, sourceFile); } } @@ -73409,9 +88140,12 @@ var ts; return n; } var children = n.getChildren(sourceFile); - var candidate = findRightmostChildNodeWithTokens(children, children.length, sourceFile); + var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length, sourceFile); return candidate && findRightmostToken(candidate, sourceFile); } + /** + * Finds the rightmost child to the left of `children[exclusiveStartPosition]` which is a non-all-whitespace token or has constituent tokens. + */ function findRightmostChildNodeWithTokens(children, exclusiveStartPosition, sourceFile) { for (var i = exclusiveStartPosition - 1; i >= 0; i--) { var child = children[i]; @@ -73428,6 +88162,10 @@ var ts; if (previousToken && ts.isStringTextContainingNode(previousToken)) { var start = previousToken.getStart(sourceFile); var end = previousToken.getEnd(); + // To be "in" one of these literals, the position has to be: + // 1. entirely within the token text. + // 2. at the end position of an unterminated token. + // 3. at the end of a regular expression (due to trailing flags like '/foo/g'). if (start < position && position < end) { return true; } @@ -73438,24 +88176,33 @@ var ts; return false; } ts.isInString = isInString; + /** + * returns true if the position is in between the open and close elements of an JSX expression. + */ function isInsideJsxElementOrAttribute(sourceFile, position) { - var token = getTokenAtPosition(sourceFile, position, false); + var token = getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); if (!token) { return false; } - if (token.kind === 10) { + if (token.kind === 10 /* JsxText */) { return true; } - if (token.kind === 27 && token.parent.kind === 10) { + //
Hello |
+ if (token.kind === 27 /* LessThanToken */ && token.parent.kind === 10 /* JsxText */) { return true; } - if (token.kind === 27 && token.parent.kind === 265) { + //
{ |
or
+ if (token.kind === 27 /* LessThanToken */ && token.parent.kind === 265 /* JsxExpression */) { return true; } - if (token && token.kind === 18 && token.parent.kind === 265) { + //
{ + // | + // } < /div> + if (token && token.kind === 18 /* CloseBraceToken */ && token.parent.kind === 265 /* JsxExpression */) { return true; } - if (token.kind === 27 && token.parent.kind === 258) { + //
|
+ if (token.kind === 27 /* LessThanToken */ && token.parent.kind === 258 /* JsxClosingElement */) { return true; } return false; @@ -73465,7 +88212,7 @@ var ts; return ts.isJsxText(node) && node.containsOnlyWhiteSpaces; } function isInTemplateString(sourceFile, position) { - var token = getTokenAtPosition(sourceFile, position, false); + var token = getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); return ts.isTemplateLiteralKind(token.kind) && position > token.getStart(sourceFile); } ts.isInTemplateString = isInTemplateString; @@ -73492,11 +88239,17 @@ var ts; ts.findPrecedingMatchingToken = findPrecedingMatchingToken; function isPossiblyTypeArgumentPosition(tokenIn, sourceFile) { var token = tokenIn; + // This function determines if the node could be type argument position + // Since during editing, when type argument list is not complete, + // the tree could be of any shape depending on the tokens parsed before current node, + // scanning of the previous identifier followed by "<" before current node would give us better result + // Note that we also balance out the already provided type arguments, arrays, object literals while doing so var remainingLessThanTokens = 0; var nTypeArguments = 0; while (token) { switch (token.kind) { - case 27: + case 27 /* LessThanToken */: + // Found the beginning of the generic argument expression token = findPrecedingToken(token.getFullStart(), sourceFile); if (!token || !ts.isIdentifier(token)) return undefined; @@ -73505,51 +88258,59 @@ var ts; } remainingLessThanTokens--; break; - case 47: + case 47 /* GreaterThanGreaterThanGreaterThanToken */: remainingLessThanTokens = +3; break; - case 46: + case 46 /* GreaterThanGreaterThanToken */: remainingLessThanTokens = +2; break; - case 29: + case 29 /* GreaterThanToken */: remainingLessThanTokens++; break; - case 18: - token = findPrecedingMatchingToken(token, 17, sourceFile); + case 18 /* CloseBraceToken */: + // This can be object type, skip until we find the matching open brace token + // Skip until the matching open brace token + token = findPrecedingMatchingToken(token, 17 /* OpenBraceToken */, sourceFile); if (!token) return undefined; break; - case 20: - token = findPrecedingMatchingToken(token, 19, sourceFile); + case 20 /* CloseParenToken */: + // This can be object type, skip until we find the matching open brace token + // Skip until the matching open brace token + token = findPrecedingMatchingToken(token, 19 /* OpenParenToken */, sourceFile); if (!token) return undefined; break; - case 22: - token = findPrecedingMatchingToken(token, 21, sourceFile); + case 22 /* CloseBracketToken */: + // This can be object type, skip until we find the matching open brace token + // Skip until the matching open brace token + token = findPrecedingMatchingToken(token, 21 /* OpenBracketToken */, sourceFile); if (!token) return undefined; break; - case 26: + // Valid tokens in a type name. Skip. + case 26 /* CommaToken */: nTypeArguments++; break; - case 36: - case 71: - case 9: - case 8: - case 101: - case 86: - case 103: - case 85: - case 128: - case 23: - case 49: - case 55: - case 56: + case 36 /* EqualsGreaterThanToken */: + case 71 /* Identifier */: + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: + case 101 /* TrueKeyword */: + case 86 /* FalseKeyword */: + case 103 /* TypeOfKeyword */: + case 85 /* ExtendsKeyword */: + case 128 /* KeyOfKeyword */: + case 23 /* DotToken */: + case 49 /* BarToken */: + case 55 /* QuestionToken */: + case 56 /* ColonToken */: break; default: if (ts.isTypeNode(token)) { break; } + // Invalid token in type return undefined; } token = findPrecedingToken(token.getFullStart(), sourceFile); @@ -73557,12 +88318,19 @@ var ts; return undefined; } ts.isPossiblyTypeArgumentPosition = isPossiblyTypeArgumentPosition; + /** + * Returns true if the cursor at position in sourceFile is within a comment. + * + * @param tokenAtPosition Must equal `getTokenAtPosition(sourceFile, position) + * @param predicate Additional predicate to test on the comment range. + */ function isInComment(sourceFile, position, tokenAtPosition, predicate) { - return !!ts.formatting.getRangeOfEnclosingComment(sourceFile, position, false, undefined, tokenAtPosition, predicate); + return !!ts.formatting.getRangeOfEnclosingComment(sourceFile, position, /*onlyMultiLine*/ false, /*precedingToken*/ undefined, tokenAtPosition, predicate); } ts.isInComment = isInComment; function hasDocComment(sourceFile, position) { - var token = getTokenAtPosition(sourceFile, position, false); + var token = getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); + // First, we have to see if this position actually landed in a comment. var commentRanges = ts.getLeadingCommentRanges(sourceFile.text, token.pos); return ts.forEach(commentRanges, jsDocPrefix); function jsDocPrefix(c) { @@ -73572,45 +88340,47 @@ var ts; } ts.hasDocComment = hasDocComment; function nodeHasTokens(n, sourceFile) { + // If we have a token or node that has a non-zero width, it must have tokens. + // Note: getWidth() does not take trivia into account. return n.getWidth(sourceFile) !== 0; } function getNodeModifiers(node) { var flags = ts.getCombinedModifierFlags(node); var result = []; - if (flags & 8) - result.push("private"); - if (flags & 16) - result.push("protected"); - if (flags & 4) - result.push("public"); - if (flags & 32) - result.push("static"); - if (flags & 128) - result.push("abstract"); - if (flags & 1) - result.push("export"); - if (node.flags & 4194304) - result.push("declare"); - return result.length > 0 ? result.join(",") : ""; + if (flags & 8 /* Private */) + result.push("private" /* privateMemberModifier */); + if (flags & 16 /* Protected */) + result.push("protected" /* protectedMemberModifier */); + if (flags & 4 /* Public */) + result.push("public" /* publicMemberModifier */); + if (flags & 32 /* Static */) + result.push("static" /* staticModifier */); + if (flags & 128 /* Abstract */) + result.push("abstract" /* abstractModifier */); + if (flags & 1 /* Export */) + result.push("export" /* exportedModifier */); + if (node.flags & 4194304 /* Ambient */) + result.push("declare" /* ambientModifier */); + return result.length > 0 ? result.join(",") : "" /* none */; } ts.getNodeModifiers = getNodeModifiers; function getTypeArgumentOrTypeParameterList(node) { - if (node.kind === 162 || node.kind === 187) { + if (node.kind === 162 /* TypeReference */ || node.kind === 187 /* CallExpression */) { return node.typeArguments; } - if (ts.isFunctionLike(node) || node.kind === 235 || node.kind === 236) { + if (ts.isFunctionLike(node) || node.kind === 235 /* ClassDeclaration */ || node.kind === 236 /* InterfaceDeclaration */) { return node.typeParameters; } return undefined; } ts.getTypeArgumentOrTypeParameterList = getTypeArgumentOrTypeParameterList; function isComment(kind) { - return kind === 2 || kind === 3; + return kind === 2 /* SingleLineCommentTrivia */ || kind === 3 /* MultiLineCommentTrivia */; } ts.isComment = isComment; function isStringOrRegularExpressionOrTemplateLiteral(kind) { - if (kind === 9 - || kind === 12 + if (kind === 9 /* StringLiteral */ + || kind === 12 /* RegularExpressionLiteral */ || ts.isTemplateLiteralKind(kind)) { return true; } @@ -73618,7 +88388,7 @@ var ts; } ts.isStringOrRegularExpressionOrTemplateLiteral = isStringOrRegularExpressionOrTemplateLiteral; function isPunctuation(kind) { - return 17 <= kind && kind <= 70; + return 17 /* FirstPunctuation */ <= kind && kind <= 70 /* LastPunctuation */; } ts.isPunctuation = isPunctuation; function isInsideTemplateLiteral(node, position, sourceFile) { @@ -73628,9 +88398,9 @@ var ts; ts.isInsideTemplateLiteral = isInsideTemplateLiteral; function isAccessibilityModifier(kind) { switch (kind) { - case 114: - case 112: - case 113: + case 114 /* PublicKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: return true; } return false; @@ -73643,18 +88413,26 @@ var ts; } ts.cloneCompilerOptions = cloneCompilerOptions; function isArrayLiteralOrObjectLiteralDestructuringPattern(node) { - if (node.kind === 183 || - node.kind === 184) { - if (node.parent.kind === 200 && + if (node.kind === 183 /* ArrayLiteralExpression */ || + node.kind === 184 /* ObjectLiteralExpression */) { + // [a,b,c] from: + // [a, b, c] = someExpression; + if (node.parent.kind === 200 /* BinaryExpression */ && node.parent.left === node && - node.parent.operatorToken.kind === 58) { + node.parent.operatorToken.kind === 58 /* EqualsToken */) { return true; } - if (node.parent.kind === 222 && + // [a, b, c] from: + // for([a, b, c] of expression) + if (node.parent.kind === 222 /* ForOfStatement */ && node.parent.initializer === node) { return true; } - if (isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.kind === 270 ? node.parent.parent : node.parent)) { + // [a, b, c] of + // [x, [a, b, c] ] = someExpression + // or + // {x, a: {a, b, c} } = someExpression + if (isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.kind === 270 /* PropertyAssignment */ ? node.parent.parent : node.parent)) { return true; } } @@ -73662,14 +88440,14 @@ var ts; } ts.isArrayLiteralOrObjectLiteralDestructuringPattern = isArrayLiteralOrObjectLiteralDestructuringPattern; function isInReferenceComment(sourceFile, position) { - return isInComment(sourceFile, position, undefined, function (c) { + return isInComment(sourceFile, position, /*tokenAtPosition*/ undefined, function (c) { var commentText = sourceFile.text.substring(c.pos, c.end); return tripleSlashDirectivePrefixRegex.test(commentText); }); } ts.isInReferenceComment = isInReferenceComment; function isInNonReferenceComment(sourceFile, position) { - return isInComment(sourceFile, position, undefined, function (c) { + return isInComment(sourceFile, position, /*tokenAtPosition*/ undefined, function (c) { var commentText = sourceFile.text.substring(c.pos, c.end); return !tripleSlashDirectivePrefixRegex.test(commentText); }); @@ -73696,27 +88474,28 @@ var ts; } ts.createTextChange = createTextChange; ts.typeKeywords = [ - 119, - 122, - 128, - 131, - 95, - 134, - 135, - 137, - 138, - 105, - 140, - 141, - 142, + 119 /* AnyKeyword */, + 122 /* BooleanKeyword */, + 128 /* KeyOfKeyword */, + 131 /* NeverKeyword */, + 95 /* NullKeyword */, + 134 /* NumberKeyword */, + 135 /* ObjectKeyword */, + 137 /* StringKeyword */, + 138 /* SymbolKeyword */, + 105 /* VoidKeyword */, + 140 /* UndefinedKeyword */, + 141 /* UniqueKeyword */, + 142 /* UnknownKeyword */, ]; function isTypeKeyword(kind) { return ts.contains(ts.typeKeywords, kind); } ts.isTypeKeyword = isTypeKeyword; + /** True if the symbol is for an external module, as opposed to a namespace. */ function isExternalModuleSymbol(moduleSymbol) { - ts.Debug.assert(!!(moduleSymbol.flags & 1536)); - return moduleSymbol.name.charCodeAt(0) === 34; + ts.Debug.assert(!!(moduleSymbol.flags & 1536 /* Module */)); + return moduleSymbol.name.charCodeAt(0) === 34 /* doubleQuote */; } ts.isExternalModuleSymbol = isExternalModuleSymbol; function nodeSeenTracker() { @@ -73740,11 +88519,12 @@ var ts; } ts.repeatString = repeatString; function skipConstraint(type) { - return type.isTypeParameter() ? type.getConstraint() : type; + return type.isTypeParameter() ? type.getConstraint() : type; // TODO: GH#18217 } ts.skipConstraint = skipConstraint; function getNameFromPropertyName(name) { - return name.kind === 147 + return name.kind === 147 /* ComputedPropertyName */ + // treat computed property names where expression is string/numeric literal as just string/numeric literal ? ts.isStringOrNumericLiteral(name.expression) ? name.expression.text : undefined : ts.getTextOfIdentifierOrLiteral(name); } @@ -73754,7 +88534,7 @@ var ts; } ts.programContainsEs6Modules = programContainsEs6Modules; function compilerOptionsIndicateEs6Modules(compilerOptions) { - return !!compilerOptions.module || compilerOptions.target >= 2 || !!compilerOptions.noEmit; + return !!compilerOptions.module || compilerOptions.target >= 2 /* ES2015 */ || !!compilerOptions.noEmit; } ts.compilerOptionsIndicateEs6Modules = compilerOptionsIndicateEs6Modules; function hostUsesCaseSensitiveFileNames(host) { @@ -73770,13 +88550,15 @@ var ts; } ts.makeImportIfNecessary = makeImportIfNecessary; function makeImport(defaultImport, namedImports, moduleSpecifier, quotePreference) { - return ts.createImportDeclaration(undefined, undefined, defaultImport || namedImports + return ts.createImportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, defaultImport || namedImports ? ts.createImportClause(defaultImport, namedImports && namedImports.length ? ts.createNamedImports(namedImports) : undefined) : undefined, typeof moduleSpecifier === "string" ? makeStringLiteral(moduleSpecifier, quotePreference) : moduleSpecifier); } ts.makeImport = makeImport; function makeStringLiteral(text, quotePreference) { - return ts.createLiteral(text, quotePreference === 0); + return ts.createLiteral(text, quotePreference === 0 /* Single */); } ts.makeStringLiteral = makeStringLiteral; var QuotePreference; @@ -73786,11 +88568,11 @@ var ts; })(QuotePreference = ts.QuotePreference || (ts.QuotePreference = {})); function getQuotePreference(sourceFile, preferences) { if (preferences.quotePreference) { - return preferences.quotePreference === "single" ? 0 : 1; + return preferences.quotePreference === "single" ? 0 /* Single */ : 1 /* Double */; } else { var firstModuleSpecifier = ts.firstOrUndefined(sourceFile.imports); - return !!firstModuleSpecifier && !ts.isStringDoubleQuoted(firstModuleSpecifier, sourceFile) ? 0 : 1; + return !!firstModuleSpecifier && !ts.isStringDoubleQuoted(firstModuleSpecifier, sourceFile) ? 0 /* Single */ : 1 /* Double */; } } ts.getQuotePreference = getQuotePreference; @@ -73800,34 +88582,48 @@ var ts; } ts.symbolNameNoDefault = symbolNameNoDefault; function symbolEscapedNameNoDefault(symbol) { - if (symbol.escapedName !== "default") { + if (symbol.escapedName !== "default" /* Default */) { return symbol.escapedName; } return ts.firstDefined(symbol.declarations, function (decl) { var name = ts.getNameOfDeclaration(decl); - return name && name.kind === 71 ? name.escapedText : undefined; + return name && name.kind === 71 /* Identifier */ ? name.escapedText : undefined; }); } ts.symbolEscapedNameNoDefault = symbolEscapedNameNoDefault; function getPropertySymbolFromBindingElement(checker, bindingElement) { var typeOfPattern = checker.getTypeAtLocation(bindingElement.parent); var propSymbol = typeOfPattern && checker.getPropertyOfType(typeOfPattern, bindingElement.name.text); - if (propSymbol && propSymbol.flags & 98304) { - ts.Debug.assert(!!(propSymbol.flags & 33554432)); + if (propSymbol && propSymbol.flags & 98304 /* Accessor */) { + // See GH#16922 + ts.Debug.assert(!!(propSymbol.flags & 33554432 /* Transient */)); return propSymbol.target; } return propSymbol; } ts.getPropertySymbolFromBindingElement = getPropertySymbolFromBindingElement; + /** + * Find symbol of the given property-name and add the symbol to the given result array + * @param symbol a symbol to start searching for the given propertyName + * @param propertyName a name of property to search for + * @param result an array of symbol of found property symbols + * @param previousIterationSymbolsCache a cache of symbol from previous iterations of calling this function to prevent infinite revisiting of the same symbol. + * The value of previousIterationSymbol is undefined when the function is first called. + */ function getPropertySymbolsFromBaseTypes(symbol, propertyName, checker, cb) { var seen = ts.createMap(); return recur(symbol); function recur(symbol) { - if (!(symbol.flags & (32 | 64)) || !ts.addToSeen(seen, ts.getSymbolId(symbol))) + // Use `addToSeen` to ensure we don't infinitely recurse in this situation: + // interface C extends C { + // /*findRef*/propName: string; + // } + if (!(symbol.flags & (32 /* Class */ | 64 /* Interface */)) || !ts.addToSeen(seen, ts.getSymbolId(symbol))) return; return ts.firstDefined(symbol.declarations, function (declaration) { return ts.firstDefined(ts.getAllSuperTypeNodes(declaration), function (typeReference) { var type = checker.getTypeAtLocation(typeReference); var propertySymbol = type && type.symbol && checker.getPropertyOfType(type, propertyName); + // Visit the typeReference as well to see if it directly or indirectly uses that property return type && propertySymbol && (ts.firstDefined(checker.getRootSymbols(propertySymbol), cb) || recur(type.symbol)); }); }); } @@ -73837,7 +88633,7 @@ var ts; return getPropertySymbolsFromBaseTypes(memberSymbol.parent, memberSymbol.name, checker, function (_) { return true; }) || false; } ts.isMemberSymbolInBaseType = isMemberSymbolInBaseType; - var NodeSet = (function () { + var NodeSet = /** @class */ (function () { function NodeSet() { this.map = ts.createMap(); } @@ -73871,20 +88667,23 @@ var ts; return ts.textSpanContainsPosition(span, node.getStart(file)) && node.getEnd() <= ts.textSpanEnd(span); } + /* @internal */ function insertImport(changes, sourceFile, importDecl) { var lastImportDeclaration = ts.findLast(sourceFile.statements, ts.isAnyImportSyntax); if (lastImportDeclaration) { changes.insertNodeAfter(sourceFile, lastImportDeclaration, importDecl); } else { - changes.insertNodeAtTopOfFile(sourceFile, importDecl, true); + changes.insertNodeAtTopOfFile(sourceFile, importDecl, /*blankLineBetween*/ true); } } ts.insertImport = insertImport; })(ts || (ts = {})); +// Display-part writer helpers +/* @internal */ (function (ts) { function isFirstDeclarationOfSymbolParameter(symbol) { - return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === 149; + return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === 149 /* Parameter */; } ts.isFirstDeclarationOfSymbolParameter = isFirstDeclarationOfSymbolParameter; var displayPartWriter = getDisplayPartWriter(); @@ -73954,46 +88753,46 @@ var ts; return displayPart(text, displayPartKind(symbol)); function displayPartKind(symbol) { var flags = symbol.flags; - if (flags & 3) { + if (flags & 3 /* Variable */) { return isFirstDeclarationOfSymbolParameter(symbol) ? ts.SymbolDisplayPartKind.parameterName : ts.SymbolDisplayPartKind.localName; } - else if (flags & 4) { + else if (flags & 4 /* Property */) { return ts.SymbolDisplayPartKind.propertyName; } - else if (flags & 32768) { + else if (flags & 32768 /* GetAccessor */) { return ts.SymbolDisplayPartKind.propertyName; } - else if (flags & 65536) { + else if (flags & 65536 /* SetAccessor */) { return ts.SymbolDisplayPartKind.propertyName; } - else if (flags & 8) { + else if (flags & 8 /* EnumMember */) { return ts.SymbolDisplayPartKind.enumMemberName; } - else if (flags & 16) { + else if (flags & 16 /* Function */) { return ts.SymbolDisplayPartKind.functionName; } - else if (flags & 32) { + else if (flags & 32 /* Class */) { return ts.SymbolDisplayPartKind.className; } - else if (flags & 64) { + else if (flags & 64 /* Interface */) { return ts.SymbolDisplayPartKind.interfaceName; } - else if (flags & 384) { + else if (flags & 384 /* Enum */) { return ts.SymbolDisplayPartKind.enumName; } - else if (flags & 1536) { + else if (flags & 1536 /* Module */) { return ts.SymbolDisplayPartKind.moduleName; } - else if (flags & 8192) { + else if (flags & 8192 /* Method */) { return ts.SymbolDisplayPartKind.methodName; } - else if (flags & 262144) { + else if (flags & 262144 /* TypeParameter */) { return ts.SymbolDisplayPartKind.typeParameterName; } - else if (flags & 524288) { + else if (flags & 524288 /* TypeAlias */) { return ts.SymbolDisplayPartKind.aliasName; } - else if (flags & 2097152) { + else if (flags & 2097152 /* Alias */) { return ts.SymbolDisplayPartKind.aliasName; } return ts.SymbolDisplayPartKind.text; @@ -74032,6 +88831,9 @@ var ts; } ts.textPart = textPart; var carriageReturnLineFeed = "\r\n"; + /** + * The default is CRLF. + */ function getNewLineOrDefaultFromHost(host, formatSettings) { return (formatSettings && formatSettings.newLineCharacter) || (host.getNewLine && host.getNewLine()) || @@ -74042,6 +88844,7 @@ var ts; return displayPart("\n", ts.SymbolDisplayPartKind.lineBreak); } ts.lineBreakPart = lineBreakPart; + /* @internal */ function mapToDisplayParts(writeDisplayParts) { try { writeDisplayParts(displayPartWriter); @@ -74053,33 +88856,38 @@ var ts; } ts.mapToDisplayParts = mapToDisplayParts; function typeToDisplayParts(typechecker, type, enclosingDeclaration, flags) { - if (flags === void 0) { flags = 0; } + if (flags === void 0) { flags = 0 /* None */; } return mapToDisplayParts(function (writer) { - typechecker.writeType(type, enclosingDeclaration, flags | 1024 | 16384, writer); + typechecker.writeType(type, enclosingDeclaration, flags | 1024 /* MultilineObjectLiterals */ | 16384 /* UseAliasDefinedOutsideCurrentScope */, writer); }); } ts.typeToDisplayParts = typeToDisplayParts; function symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration, meaning, flags) { - if (flags === void 0) { flags = 0; } + if (flags === void 0) { flags = 0 /* None */; } return mapToDisplayParts(function (writer) { - typeChecker.writeSymbol(symbol, enclosingDeclaration, meaning, flags | 8, writer); + typeChecker.writeSymbol(symbol, enclosingDeclaration, meaning, flags | 8 /* UseAliasDefinedOutsideCurrentScope */, writer); }); } ts.symbolToDisplayParts = symbolToDisplayParts; function signatureToDisplayParts(typechecker, signature, enclosingDeclaration, flags) { - if (flags === void 0) { flags = 0; } - flags |= 16384 | 1024 | 32 | 8192; + if (flags === void 0) { flags = 0 /* None */; } + flags |= 16384 /* UseAliasDefinedOutsideCurrentScope */ | 1024 /* MultilineObjectLiterals */ | 32 /* WriteTypeArgumentsOfSignature */ | 8192 /* OmitParameterModifiers */; return mapToDisplayParts(function (writer) { - typechecker.writeSignature(signature, enclosingDeclaration, flags, undefined, writer); + typechecker.writeSignature(signature, enclosingDeclaration, flags, /*signatureKind*/ undefined, writer); }); } ts.signatureToDisplayParts = signatureToDisplayParts; function isImportOrExportSpecifierName(location) { return !!location.parent && - (location.parent.kind === 248 || location.parent.kind === 252) && + (location.parent.kind === 248 /* ImportSpecifier */ || location.parent.kind === 252 /* ExportSpecifier */) && location.parent.propertyName === location; } ts.isImportOrExportSpecifierName = isImportOrExportSpecifierName; + /** + * Strip off existed single quotes or double quotes from a given string + * + * @return non-quoted string + */ function stripQuotes(name) { var length = name.length; if (length >= 2 && name.charCodeAt(0) === name.charCodeAt(length - 1) && startsWithQuote(name)) { @@ -74102,6 +88910,8 @@ var ts; } ts.scriptKindIs = scriptKindIs; function getScriptKind(fileName, host) { + // First check to see if the script kind was specified by the host. Chances are the host + // may override the default script kind for the file extension. return ts.ensureScriptKind(fileName, host && host.getScriptKind && host.getScriptKind(fileName)); } ts.getScriptKind = getScriptKind; @@ -74116,6 +88926,12 @@ var ts; return position; } ts.getFirstNonSpaceCharacterPosition = getFirstNonSpaceCharacterPosition; + /** + * Creates a deep, memberwise clone of a node with no source map location. + * + * WARNING: This is an expensive operation and is only intended to be used in refactorings + * and code fixes (because those are triggered by explicit user actions). + */ function getSynthesizedDeepClone(node, includeTrivia) { if (includeTrivia === void 0) { includeTrivia = true; } var clone = node && getSynthesizedDeepCloneWorker(node); @@ -74127,6 +88943,7 @@ var ts; function getSynthesizedDeepCloneWorker(node) { var visited = ts.visitEachChild(node, getSynthesizedDeepClone, ts.nullTransformationContext); if (visited === node) { + // This only happens for leaf nodes - internal nodes always see their children change. var clone_7 = ts.getSynthesizedClone(node); if (ts.isStringLiteral(clone_7)) { clone_7.textSourceNode = node; @@ -74136,6 +88953,9 @@ var ts; } return ts.setTextRange(clone_7, node); } + // PERF: As an optimization, rather than calling getSynthesizedClone, we'll update + // the new node created by visitEachChild with the extra changes getSynthesizedClone + // would have made. visited.parent = undefined; return visited; } @@ -74144,17 +88964,29 @@ var ts; return nodes && ts.createNodeArray(nodes.map(function (n) { return getSynthesizedDeepClone(n, includeTrivia); }), nodes.hasTrailingComma); } ts.getSynthesizedDeepClones = getSynthesizedDeepClones; + /** + * Sets EmitFlags to suppress leading and trailing trivia on the node. + */ + /* @internal */ function suppressLeadingAndTrailingTrivia(node) { suppressLeadingTrivia(node); suppressTrailingTrivia(node); } ts.suppressLeadingAndTrailingTrivia = suppressLeadingAndTrailingTrivia; + /** + * Sets EmitFlags to suppress leading trivia on the node. + */ + /* @internal */ function suppressLeadingTrivia(node) { - addEmitFlagsRecursively(node, 512, getFirstChild); + addEmitFlagsRecursively(node, 512 /* NoLeadingComments */, getFirstChild); } ts.suppressLeadingTrivia = suppressLeadingTrivia; + /** + * Sets EmitFlags to suppress trailing trivia on the node. + */ + /* @internal */ function suppressTrailingTrivia(node) { - addEmitFlagsRecursively(node, 1024, ts.getLastChild); + addEmitFlagsRecursively(node, 1024 /* NoTrailingComments */, ts.getLastChild); } ts.suppressTrailingTrivia = suppressTrailingTrivia; function addEmitFlagsRecursively(node, flag, getChild) { @@ -74166,6 +88998,7 @@ var ts; function getFirstChild(node) { return node.forEachChild(function (child) { return child; }); } + /* @internal */ function getUniqueName(baseName, sourceFile) { var nameText = baseName; for (var i = 1; !ts.isFileLevelUniqueName(sourceFile, nameText); i++) { @@ -74174,6 +89007,12 @@ var ts; return nameText; } ts.getUniqueName = getUniqueName; + /** + * @return The index of the (only) reference to the extracted symbol. We want the cursor + * to be on the reference, rather than the declaration, because it's closer to where the + * user was before extracting it. + */ + /* @internal */ function getRenameLocation(edits, renameFilename, name, preferLastLocation) { var delta = 0; var lastPos = -1; @@ -74186,6 +89025,7 @@ var ts; var index = indexInTextChange(newText, name); if (index !== -1) { lastPos = span.start + delta + index; + // If the reference comes first, return immediately. if (!preferLastLocation) { return lastPos; } @@ -74193,6 +89033,7 @@ var ts; delta += newText.length - span.length; } } + // If the declaration comes first, return the position of the last occurrence. ts.Debug.assert(preferLastLocation); ts.Debug.assert(lastPos >= 0); return lastPos; @@ -74200,11 +89041,14 @@ var ts; ts.getRenameLocation = getRenameLocation; function copyComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) { ts.forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, function (pos, end, kind, htnl) { - if (kind === 3) { + if (kind === 3 /* MultiLineCommentTrivia */) { + // Remove leading /* pos += 2; + // Remove trailing */ end -= 2; } else { + // Remove leading // pos += 2; } ts.addSyntheticLeadingComment(targetNode, commentKind || kind, sourceFile.text.slice(pos, end), hasTrailingNewLine !== undefined ? hasTrailingNewLine : htnl); @@ -74214,6 +89058,7 @@ var ts; function indexInTextChange(change, name) { if (ts.startsWith(change, name)) return 0; + // Add a " " to avoid references inside words var idx = change.indexOf(" " + name); if (idx === -1) idx = change.indexOf("." + name); @@ -74225,23 +89070,64 @@ var ts; var ts; (function (ts) { function createClassifier() { - var scanner = ts.createScanner(6, false); + var scanner = ts.createScanner(6 /* Latest */, /*skipTrivia*/ false); function getClassificationsForLine(text, lexState, syntacticClassifierAbsent) { return convertClassificationsToResult(getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent), text); } + // If there is a syntactic classifier ('syntacticClassifierAbsent' is false), + // we will be more conservative in order to avoid conflicting with the syntactic classifier. function getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent) { - var token = 0; - var lastNonTriviaToken = 0; + var token = 0 /* Unknown */; + var lastNonTriviaToken = 0 /* Unknown */; + // Just a stack of TemplateHeads and OpenCurlyBraces, used to perform rudimentary (inexact) + // classification on template strings. Because of the context free nature of templates, + // the only precise way to classify a template portion would be by propagating the stack across + // lines, just as we do with the end-of-line state. However, this is a burden for implementers, + // and the behavior is entirely subsumed by the syntactic classifier anyway, so we instead + // flatten any nesting when the template stack is non-empty and encode it in the end-of-line state. + // Situations in which this fails are + // 1) When template strings are nested across different lines: + // `hello ${ `world + // ` }` + // + // Where on the second line, you will get the closing of a template, + // a closing curly, and a new template. + // + // 2) When substitution expressions have curly braces and the curly brace falls on the next line: + // `hello ${ () => { + // return "world" } } ` + // + // Where on the second line, you will get the 'return' keyword, + // a string literal, and a template end consisting of '} } `'. var templateStack = []; var _a = getPrefixFromLexState(lexState), prefix = _a.prefix, pushTemplate = _a.pushTemplate; text = prefix + text; var offset = prefix.length; if (pushTemplate) { - templateStack.push(14); + templateStack.push(14 /* TemplateHead */); } scanner.setText(text); - var endOfLineState = 0; + var endOfLineState = 0 /* None */; var spans = []; + // We can run into an unfortunate interaction between the lexical and syntactic classifier + // when the user is typing something generic. Consider the case where the user types: + // + // Foo tokens. It's a weak heuristic, but should + // work well enough in practice. var angleBracketStack = 0; do { token = scanner.scan(); @@ -74257,56 +89143,68 @@ var ts; endOfLineState = end_1; } } - } while (token !== 1); + } while (token !== 1 /* EndOfFileToken */); function handleToken() { switch (token) { - case 41: - case 63: - if (!noRegexTable[lastNonTriviaToken] && scanner.reScanSlashToken() === 12) { - token = 12; + case 41 /* SlashToken */: + case 63 /* SlashEqualsToken */: + if (!noRegexTable[lastNonTriviaToken] && scanner.reScanSlashToken() === 12 /* RegularExpressionLiteral */) { + token = 12 /* RegularExpressionLiteral */; } break; - case 27: - if (lastNonTriviaToken === 71) { + case 27 /* LessThanToken */: + if (lastNonTriviaToken === 71 /* Identifier */) { + // Could be the start of something generic. Keep track of that by bumping + // up the current count of generic contexts we may be in. angleBracketStack++; } break; - case 29: + case 29 /* GreaterThanToken */: if (angleBracketStack > 0) { + // If we think we're currently in something generic, then mark that that + // generic entity is complete. angleBracketStack--; } break; - case 119: - case 137: - case 134: - case 122: - case 138: + case 119 /* AnyKeyword */: + case 137 /* StringKeyword */: + case 134 /* NumberKeyword */: + case 122 /* BooleanKeyword */: + case 138 /* SymbolKeyword */: if (angleBracketStack > 0 && !syntacticClassifierAbsent) { - token = 71; + // If it looks like we're could be in something generic, don't classify this + // as a keyword. We may just get overwritten by the syntactic classifier, + // causing a noisy experience for the user. + token = 71 /* Identifier */; } break; - case 14: + case 14 /* TemplateHead */: templateStack.push(token); break; - case 17: + case 17 /* OpenBraceToken */: + // If we don't have anything on the template stack, + // then we aren't trying to keep track of a previously scanned template head. if (templateStack.length > 0) { templateStack.push(token); } break; - case 18: + case 18 /* CloseBraceToken */: + // If we don't have anything on the template stack, + // then we aren't trying to keep track of a previously scanned template head. if (templateStack.length > 0) { var lastTemplateStackToken = ts.lastOrUndefined(templateStack); - if (lastTemplateStackToken === 14) { + if (lastTemplateStackToken === 14 /* TemplateHead */) { token = scanner.reScanTemplateToken(); - if (token === 16) { + // Only pop on a TemplateTail; a TemplateMiddle indicates there is more for us. + if (token === 16 /* TemplateTail */) { templateStack.pop(); } else { - ts.Debug.assertEqual(token, 15, "Should have been a template middle."); + ts.Debug.assertEqual(token, 15 /* TemplateMiddle */, "Should have been a template middle."); } } else { - ts.Debug.assertEqual(lastTemplateStackToken, 17, "Should have been an open brace"); + ts.Debug.assertEqual(lastTemplateStackToken, 17 /* OpenBraceToken */, "Should have been an open brace"); templateStack.pop(); } } @@ -74315,11 +89213,15 @@ var ts; if (!ts.isKeyword(token)) { break; } - if (lastNonTriviaToken === 23) { - token = 71; + if (lastNonTriviaToken === 23 /* DotToken */) { + token = 71 /* Identifier */; } else if (ts.isKeyword(lastNonTriviaToken) && ts.isKeyword(token) && !canFollow(lastNonTriviaToken, token)) { - token = 71; + // We have two keywords in a row. Only treat the second as a keyword if + // it's a sequence that could legally occur in the language. Otherwise + // treat it as an identifier. This way, if someone writes "private var" + // we recognize that 'var' is actually an identifier here. + token = 71 /* Identifier */; } } } @@ -74328,63 +89230,75 @@ var ts; return { getClassificationsForLine: getClassificationsForLine, getEncodedLexicalClassifications: getEncodedLexicalClassifications }; } ts.createClassifier = createClassifier; + /// We do not have a full parser support to know when we should parse a regex or not + /// If we consider every slash token to be a regex, we could be missing cases like "1/2/3", where + /// we have a series of divide operator. this list allows us to be more accurate by ruling out + /// locations where a regexp cannot exist. var noRegexTable = ts.arrayToNumericMap([ - 71, - 9, - 8, - 12, - 99, - 43, - 44, - 20, - 22, - 18, - 101, - 86, + 71 /* Identifier */, + 9 /* StringLiteral */, + 8 /* NumericLiteral */, + 12 /* RegularExpressionLiteral */, + 99 /* ThisKeyword */, + 43 /* PlusPlusToken */, + 44 /* MinusMinusToken */, + 20 /* CloseParenToken */, + 22 /* CloseBracketToken */, + 18 /* CloseBraceToken */, + 101 /* TrueKeyword */, + 86 /* FalseKeyword */, ], function (token) { return token; }, function () { return true; }); function getNewEndOfLineState(scanner, token, lastOnTemplateStack) { switch (token) { - case 9: { + case 9 /* StringLiteral */: { + // Check to see if we finished up on a multiline string literal. if (!scanner.isUnterminated()) return undefined; var tokenText = scanner.getTokenText(); var lastCharIndex = tokenText.length - 1; var numBackslashes = 0; - while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === 92) { + while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === 92 /* backslash */) { numBackslashes++; } + // If we have an odd number of backslashes, then the multiline string is unclosed if ((numBackslashes & 1) === 0) return undefined; - return tokenText.charCodeAt(0) === 34 ? 3 : 2; + return tokenText.charCodeAt(0) === 34 /* doubleQuote */ ? 3 /* InDoubleQuoteStringLiteral */ : 2 /* InSingleQuoteStringLiteral */; } - case 3: - return scanner.isUnterminated() ? 1 : undefined; + case 3 /* MultiLineCommentTrivia */: + // Check to see if the multiline comment was unclosed. + return scanner.isUnterminated() ? 1 /* InMultiLineCommentTrivia */ : undefined; default: if (ts.isTemplateLiteralKind(token)) { if (!scanner.isUnterminated()) { return undefined; } switch (token) { - case 16: - return 5; - case 13: - return 4; + case 16 /* TemplateTail */: + return 5 /* InTemplateMiddleOrTail */; + case 13 /* NoSubstitutionTemplateLiteral */: + return 4 /* InTemplateHeadOrNoSubstitutionTemplate */; default: return ts.Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token); } } - return lastOnTemplateStack === 14 ? 6 : undefined; + return lastOnTemplateStack === 14 /* TemplateHead */ ? 6 /* InTemplateSubstitutionPosition */ : undefined; } } function pushEncodedClassification(start, end, offset, classification, result) { - if (classification === 8) { + if (classification === 8 /* whiteSpace */) { + // Don't bother with whitespace classifications. They're not needed. return; } if (start === 0 && offset > 0) { + // We're classifying the first token, and this was a case where we prepended text. + // We should consider the start of this token to be at the start of the original text. start += offset; } var length = end - start; if (length > 0) { + // All our tokens are in relation to the augmented text. Move them back to be + // relative to the original text. result.push(start - offset, length, classification); } } @@ -74396,6 +89310,7 @@ var ts; var start = dense[i]; var length_5 = dense[i + 1]; var type = dense[i + 2]; + // Make a whitespace entry between the last item and this one. if (lastEnd >= 0) { var whitespaceLength_1 = start - lastEnd; if (whitespaceLength_1 > 0) { @@ -74413,56 +89328,64 @@ var ts; } function convertClassification(type) { switch (type) { - case 1: return ts.TokenClass.Comment; - case 3: return ts.TokenClass.Keyword; - case 4: return ts.TokenClass.NumberLiteral; - case 5: return ts.TokenClass.Operator; - case 6: return ts.TokenClass.StringLiteral; - case 8: return ts.TokenClass.Whitespace; - case 10: return ts.TokenClass.Punctuation; - case 2: - case 11: - case 12: - case 13: - case 14: - case 15: - case 16: - case 9: - case 17: + case 1 /* comment */: return ts.TokenClass.Comment; + case 3 /* keyword */: return ts.TokenClass.Keyword; + case 4 /* numericLiteral */: return ts.TokenClass.NumberLiteral; + case 5 /* operator */: return ts.TokenClass.Operator; + case 6 /* stringLiteral */: return ts.TokenClass.StringLiteral; + case 8 /* whiteSpace */: return ts.TokenClass.Whitespace; + case 10 /* punctuation */: return ts.TokenClass.Punctuation; + case 2 /* identifier */: + case 11 /* className */: + case 12 /* enumName */: + case 13 /* interfaceName */: + case 14 /* moduleName */: + case 15 /* typeParameterName */: + case 16 /* typeAliasName */: + case 9 /* text */: + case 17 /* parameterName */: return ts.TokenClass.Identifier; default: - return undefined; + return undefined; // TODO: GH#18217 Debug.assertNever(type); } } + /** Returns true if 'keyword2' can legally follow 'keyword1' in any language construct. */ function canFollow(keyword1, keyword2) { if (!ts.isAccessibilityModifier(keyword1)) { + // Assume any other keyword combination is legal. + // This can be refined in the future if there are more cases we want the classifier to be better at. return true; } switch (keyword2) { - case 125: - case 136: - case 123: - case 115: - return true; + case 125 /* GetKeyword */: + case 136 /* SetKeyword */: + case 123 /* ConstructorKeyword */: + case 115 /* StaticKeyword */: + return true; // Allow things like "public get", "public constructor" and "public static". default: - return false; + return false; // Any other keyword following "public" is actually an identifier, not a real keyword. } } function getPrefixFromLexState(lexState) { + // If we're in a string literal, then prepend: "\ + // (and a newline). That way when we lex we'll think we're still in a string literal. + // + // If we're in a multiline comment, then prepend: /* + // (and a newline). That way when we lex we'll think we're still in a multiline comment. switch (lexState) { - case 3: + case 3 /* InDoubleQuoteStringLiteral */: return { prefix: "\"\\\n" }; - case 2: + case 2 /* InSingleQuoteStringLiteral */: return { prefix: "'\\\n" }; - case 1: + case 1 /* InMultiLineCommentTrivia */: return { prefix: "/*\n" }; - case 4: + case 4 /* InTemplateHeadOrNoSubstitutionTemplate */: return { prefix: "`\n" }; - case 5: + case 5 /* InTemplateMiddleOrTail */: return { prefix: "}\n", pushTemplate: true }; - case 6: + case 6 /* InTemplateSubstitutionPosition */: return { prefix: "", pushTemplate: true }; - case 0: + case 0 /* None */: return { prefix: "" }; default: return ts.Debug.assertNever(lexState); @@ -74470,43 +89393,43 @@ var ts; } function isBinaryExpressionOperatorToken(token) { switch (token) { - case 39: - case 41: - case 42: - case 37: - case 38: - case 45: - case 46: - case 47: - case 27: - case 29: - case 30: - case 31: - case 93: - case 92: - case 118: - case 32: - case 33: - case 34: - case 35: - case 48: - case 50: - case 49: - case 53: - case 54: - case 69: - case 68: - case 70: - case 65: - case 66: - case 67: - case 59: - case 60: - case 61: - case 63: - case 64: - case 58: - case 26: + case 39 /* AsteriskToken */: + case 41 /* SlashToken */: + case 42 /* PercentToken */: + case 37 /* PlusToken */: + case 38 /* MinusToken */: + case 45 /* LessThanLessThanToken */: + case 46 /* GreaterThanGreaterThanToken */: + case 47 /* GreaterThanGreaterThanGreaterThanToken */: + case 27 /* LessThanToken */: + case 29 /* GreaterThanToken */: + case 30 /* LessThanEqualsToken */: + case 31 /* GreaterThanEqualsToken */: + case 93 /* InstanceOfKeyword */: + case 92 /* InKeyword */: + case 118 /* AsKeyword */: + case 32 /* EqualsEqualsToken */: + case 33 /* ExclamationEqualsToken */: + case 34 /* EqualsEqualsEqualsToken */: + case 35 /* ExclamationEqualsEqualsToken */: + case 48 /* AmpersandToken */: + case 50 /* CaretToken */: + case 49 /* BarToken */: + case 53 /* AmpersandAmpersandToken */: + case 54 /* BarBarToken */: + case 69 /* BarEqualsToken */: + case 68 /* AmpersandEqualsToken */: + case 70 /* CaretEqualsToken */: + case 65 /* LessThanLessThanEqualsToken */: + case 66 /* GreaterThanGreaterThanEqualsToken */: + case 67 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + case 59 /* PlusEqualsToken */: + case 60 /* MinusEqualsToken */: + case 61 /* AsteriskEqualsToken */: + case 63 /* SlashEqualsToken */: + case 64 /* PercentEqualsToken */: + case 58 /* EqualsToken */: + case 26 /* CommaToken */: return true; default: return false; @@ -74514,12 +89437,12 @@ var ts; } function isPrefixUnaryExpressionOperatorToken(token) { switch (token) { - case 37: - case 38: - case 52: - case 51: - case 43: - case 44: + case 37 /* PlusToken */: + case 38 /* MinusToken */: + case 52 /* TildeToken */: + case 51 /* ExclamationToken */: + case 43 /* PlusPlusToken */: + case 44 /* MinusMinusToken */: return true; default: return false; @@ -74527,56 +89450,72 @@ var ts; } function classFromKind(token) { if (ts.isKeyword(token)) { - return 3; + return 3 /* keyword */; } else if (isBinaryExpressionOperatorToken(token) || isPrefixUnaryExpressionOperatorToken(token)) { - return 5; + return 5 /* operator */; } - else if (token >= 17 && token <= 70) { - return 10; + else if (token >= 17 /* FirstPunctuation */ && token <= 70 /* LastPunctuation */) { + return 10 /* punctuation */; } switch (token) { - case 8: - return 4; - case 9: - return 6; - case 12: - return 7; - case 7: - case 3: - case 2: - return 1; - case 5: - case 4: - return 8; - case 71: + case 8 /* NumericLiteral */: + return 4 /* numericLiteral */; + case 9 /* StringLiteral */: + return 6 /* stringLiteral */; + case 12 /* RegularExpressionLiteral */: + return 7 /* regularExpressionLiteral */; + case 7 /* ConflictMarkerTrivia */: + case 3 /* MultiLineCommentTrivia */: + case 2 /* SingleLineCommentTrivia */: + return 1 /* comment */; + case 5 /* WhitespaceTrivia */: + case 4 /* NewLineTrivia */: + return 8 /* whiteSpace */; + case 71 /* Identifier */: default: if (ts.isTemplateLiteralKind(token)) { - return 6; + return 6 /* stringLiteral */; } - return 2; + return 2 /* identifier */; } } + /* @internal */ function getSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span) { return convertClassificationsToSpans(getEncodedSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span)); } ts.getSemanticClassifications = getSemanticClassifications; function checkForClassificationCancellation(cancellationToken, kind) { + // We don't want to actually call back into our host on every node to find out if we've + // been canceled. That would be an enormous amount of chattyness, along with the all + // the overhead of marshalling the data to/from the host. So instead we pick a few + // reasonable node kinds to bother checking on. These node kinds represent high level + // constructs that we would expect to see commonly, but just at a far less frequent + // interval. + // + // For example, in checker.ts (around 750k) we only have around 600 of these constructs. + // That means we're calling back into the host around every 1.2k of the file we process. + // Lib.d.ts has similar numbers. switch (kind) { - case 239: - case 235: - case 236: - case 234: + case 239 /* ModuleDeclaration */: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + case 234 /* FunctionDeclaration */: cancellationToken.throwIfCancellationRequested(); } } + /* @internal */ function getEncodedSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span) { var spans = []; sourceFile.forEachChild(function cb(node) { + // Only walk into nodes that intersect the requested span. if (!node || !ts.textSpanIntersectsWith(span, node.pos, node.getFullWidth())) { return; } checkForClassificationCancellation(cancellationToken, node.kind); + // Only bother calling into the typechecker if this is an identifier that + // could possibly resolve to a type name. This makes classification run + // in a third of the time it would normally take. if (ts.isIdentifier(node) && !ts.nodeIsMissing(node) && classifiableNames.has(node.escapedText)) { var symbol = typeChecker.getSymbolAtLocation(node); var type = symbol && classifySymbol(symbol, ts.getMeaningFromLocation(node), typeChecker); @@ -74586,7 +89525,7 @@ var ts; } node.forEachChild(cb); }); - return { spans: spans, endOfLineState: 0 }; + return { spans: spans, endOfLineState: 0 /* None */ }; function pushClassification(start, end, type) { spans.push(start); spans.push(end - start); @@ -74596,62 +89535,66 @@ var ts; ts.getEncodedSemanticClassifications = getEncodedSemanticClassifications; function classifySymbol(symbol, meaningAtPosition, checker) { var flags = symbol.getFlags(); - if ((flags & 2885600) === 0) { + if ((flags & 2885600 /* Classifiable */) === 0 /* None */) { return undefined; } - else if (flags & 32) { - return 11; + else if (flags & 32 /* Class */) { + return 11 /* className */; } - else if (flags & 384) { - return 12; + else if (flags & 384 /* Enum */) { + return 12 /* enumName */; } - else if (flags & 524288) { - return 16; + else if (flags & 524288 /* TypeAlias */) { + return 16 /* typeAliasName */; } - else if (flags & 1536) { - return meaningAtPosition & 4 || meaningAtPosition & 1 && hasValueSideModule(symbol) ? 14 : undefined; + else if (flags & 1536 /* Module */) { + // Only classify a module as such if + // - It appears in a namespace context. + // - There exists a module declaration which actually impacts the value side. + return meaningAtPosition & 4 /* Namespace */ || meaningAtPosition & 1 /* Value */ && hasValueSideModule(symbol) ? 14 /* moduleName */ : undefined; } - else if (flags & 2097152) { + else if (flags & 2097152 /* Alias */) { return classifySymbol(checker.getAliasedSymbol(symbol), meaningAtPosition, checker); } - else if (meaningAtPosition & 2) { - return flags & 64 ? 13 : flags & 262144 ? 15 : undefined; + else if (meaningAtPosition & 2 /* Type */) { + return flags & 64 /* Interface */ ? 13 /* interfaceName */ : flags & 262144 /* TypeParameter */ ? 15 /* typeParameterName */ : undefined; } else { return undefined; } } + /** Returns true if there exists a module that introduces entities on the value side. */ function hasValueSideModule(symbol) { return ts.some(symbol.declarations, function (declaration) { - return ts.isModuleDeclaration(declaration) && ts.getModuleInstanceState(declaration) === 1; + return ts.isModuleDeclaration(declaration) && ts.getModuleInstanceState(declaration) === 1 /* Instantiated */; }); } function getClassificationTypeName(type) { switch (type) { - case 1: return "comment"; - case 2: return "identifier"; - case 3: return "keyword"; - case 4: return "number"; - case 5: return "operator"; - case 6: return "string"; - case 8: return "whitespace"; - case 9: return "text"; - case 10: return "punctuation"; - case 11: return "class name"; - case 12: return "enum name"; - case 13: return "interface name"; - case 14: return "module name"; - case 15: return "type parameter name"; - case 16: return "type alias name"; - case 17: return "parameter name"; - case 18: return "doc comment tag name"; - case 19: return "jsx open tag name"; - case 20: return "jsx close tag name"; - case 21: return "jsx self closing tag name"; - case 22: return "jsx attribute"; - case 23: return "jsx text"; - case 24: return "jsx attribute string literal value"; - default: return undefined; + case 1 /* comment */: return "comment" /* comment */; + case 2 /* identifier */: return "identifier" /* identifier */; + case 3 /* keyword */: return "keyword" /* keyword */; + case 4 /* numericLiteral */: return "number" /* numericLiteral */; + case 5 /* operator */: return "operator" /* operator */; + case 6 /* stringLiteral */: return "string" /* stringLiteral */; + case 8 /* whiteSpace */: return "whitespace" /* whiteSpace */; + case 9 /* text */: return "text" /* text */; + case 10 /* punctuation */: return "punctuation" /* punctuation */; + case 11 /* className */: return "class name" /* className */; + case 12 /* enumName */: return "enum name" /* enumName */; + case 13 /* interfaceName */: return "interface name" /* interfaceName */; + case 14 /* moduleName */: return "module name" /* moduleName */; + case 15 /* typeParameterName */: return "type parameter name" /* typeParameterName */; + case 16 /* typeAliasName */: return "type alias name" /* typeAliasName */; + case 17 /* parameterName */: return "parameter name" /* parameterName */; + case 18 /* docCommentTagName */: return "doc comment tag name" /* docCommentTagName */; + case 19 /* jsxOpenTagName */: return "jsx open tag name" /* jsxOpenTagName */; + case 20 /* jsxCloseTagName */: return "jsx close tag name" /* jsxCloseTagName */; + case 21 /* jsxSelfClosingTagName */: return "jsx self closing tag name" /* jsxSelfClosingTagName */; + case 22 /* jsxAttribute */: return "jsx attribute" /* jsxAttribute */; + case 23 /* jsxText */: return "jsx text" /* jsxText */; + case 24 /* jsxAttributeStringLiteralValue */: return "jsx attribute string literal value" /* jsxAttributeStringLiteralValue */; + default: return undefined; // TODO: GH#18217 throw Debug.assertNever(type); } } function convertClassificationsToSpans(classifications) { @@ -74666,18 +89609,21 @@ var ts; } return result; } + /* @internal */ function getSyntacticClassifications(cancellationToken, sourceFile, span) { return convertClassificationsToSpans(getEncodedSyntacticClassifications(cancellationToken, sourceFile, span)); } ts.getSyntacticClassifications = getSyntacticClassifications; + /* @internal */ function getEncodedSyntacticClassifications(cancellationToken, sourceFile, span) { var spanStart = span.start; var spanLength = span.length; - var triviaScanner = ts.createScanner(6, false, sourceFile.languageVariant, sourceFile.text); - var mergeConflictScanner = ts.createScanner(6, false, sourceFile.languageVariant, sourceFile.text); + // Make a scanner we can get trivia from. + var triviaScanner = ts.createScanner(6 /* Latest */, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); + var mergeConflictScanner = ts.createScanner(6 /* Latest */, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); var result = []; processElement(sourceFile); - return { spans: result, endOfLineState: 0 }; + return { spans: result, endOfLineState: 0 /* None */ }; function pushClassification(start, length, type) { result.push(start); result.push(length); @@ -74687,35 +89633,47 @@ var ts; triviaScanner.setTextPos(token.pos); while (true) { var start = triviaScanner.getTextPos(); + // only bother scanning if we have something that could be trivia. if (!ts.couldStartTrivia(sourceFile.text, start)) { return start; } var kind = triviaScanner.scan(); var end = triviaScanner.getTextPos(); var width = end - start; + // The moment we get something that isn't trivia, then stop processing. if (!ts.isTrivia(kind)) { return start; } switch (kind) { - case 4: - case 5: + case 4 /* NewLineTrivia */: + case 5 /* WhitespaceTrivia */: + // Don't bother with newlines/whitespace. continue; - case 2: - case 3: + case 2 /* SingleLineCommentTrivia */: + case 3 /* MultiLineCommentTrivia */: + // Only bother with the trivia if it at least intersects the span of interest. classifyComment(token, kind, start, width); + // Classifying a comment might cause us to reuse the trivia scanner + // (because of jsdoc comments). So after we classify the comment make + // sure we set the scanner position back to where it needs to be. triviaScanner.setTextPos(end); continue; - case 7: + case 7 /* ConflictMarkerTrivia */: var text = sourceFile.text; var ch = text.charCodeAt(start); - if (ch === 60 || ch === 62) { - pushClassification(start, width, 1); + // for the <<<<<<< and >>>>>>> markers, we just add them in as comments + // in the classification stream. + if (ch === 60 /* lessThan */ || ch === 62 /* greaterThan */) { + pushClassification(start, width, 1 /* comment */); continue; } - ts.Debug.assert(ch === 124 || ch === 61); + // for the ||||||| and ======== markers, add a comment for the first line, + // and then lex all subsequent lines up until the end of the conflict marker. + ts.Debug.assert(ch === 124 /* bar */ || ch === 61 /* equals */); classifyDisabledMergeCode(text, start, end); break; - case 6: + case 6 /* ShebangTrivia */: + // TODO: Maybe we should classify these. break; default: ts.Debug.assertNever(kind); @@ -74723,43 +89681,49 @@ var ts; } } function classifyComment(token, kind, start, width) { - if (kind === 3) { + if (kind === 3 /* MultiLineCommentTrivia */) { + // See if this is a doc comment. If so, we'll classify certain portions of it + // specially. var docCommentAndDiagnostics = ts.parseIsolatedJSDocComment(sourceFile.text, start, width); if (docCommentAndDiagnostics && docCommentAndDiagnostics.jsDoc) { + // TODO: This should be predicated on `token["kind"]` being compatible with `HasJSDoc["kind"]` docCommentAndDiagnostics.jsDoc.parent = token; classifyJSDocComment(docCommentAndDiagnostics.jsDoc); return; } } + // Simple comment. Just add as is. pushCommentRange(start, width); } function pushCommentRange(start, width) { - pushClassification(start, width, 1); + pushClassification(start, width, 1 /* comment */); } function classifyJSDocComment(docComment) { var pos = docComment.pos; if (docComment.tags) { for (var _i = 0, _a = docComment.tags; _i < _a.length; _i++) { var tag = _a[_i]; + // As we walk through each tag, classify the portion of text from the end of + // the last tag (or the start of the entire doc comment) as 'comment'. if (tag.pos !== pos) { pushCommentRange(pos, tag.pos - pos); } - pushClassification(tag.atToken.pos, tag.atToken.end - tag.atToken.pos, 10); - pushClassification(tag.tagName.pos, tag.tagName.end - tag.tagName.pos, 18); + pushClassification(tag.atToken.pos, tag.atToken.end - tag.atToken.pos, 10 /* punctuation */); // "@" + pushClassification(tag.tagName.pos, tag.tagName.end - tag.tagName.pos, 18 /* docCommentTagName */); // e.g. "param" pos = tag.tagName.end; switch (tag.kind) { - case 293: + case 293 /* JSDocParameterTag */: processJSDocParameterTag(tag); break; - case 297: + case 297 /* JSDocTemplateTag */: processJSDocTemplateTag(tag); pos = tag.end; break; - case 296: + case 296 /* JSDocTypeTag */: processElement(tag.typeExpression); pos = tag.end; break; - case 294: + case 294 /* JSDocReturnTag */: processElement(tag.typeExpression); pos = tag.end; break; @@ -74773,7 +89737,7 @@ var ts; function processJSDocParameterTag(tag) { if (tag.isNameFirst) { pushCommentRange(pos, tag.name.pos - pos); - pushClassification(tag.name.pos, tag.name.end - tag.name.pos, 17); + pushClassification(tag.name.pos, tag.name.end - tag.name.pos, 17 /* parameterName */); pos = tag.name.end; } if (tag.typeExpression) { @@ -74783,7 +89747,7 @@ var ts; } if (!tag.isNameFirst) { pushCommentRange(pos, tag.name.pos - pos); - pushClassification(tag.name.pos, tag.name.end - tag.name.pos, 17); + pushClassification(tag.name.pos, tag.name.end - tag.name.pos, 17 /* parameterName */); pos = tag.name.end; } } @@ -74795,13 +89759,15 @@ var ts; } } function classifyDisabledMergeCode(text, start, end) { + // Classify the line that the ||||||| or ======= marker is on as a comment. + // Then just lex all further tokens and add them to the result. var i; for (i = start; i < end; i++) { if (ts.isLineBreak(text.charCodeAt(i))) { break; } } - pushClassification(start, i - start, 1); + pushClassification(start, i - start, 1 /* comment */); mergeConflictScanner.setTextPos(i); while (mergeConflictScanner.getTextPos() < end) { classifyDisabledCodeToken(); @@ -74816,6 +89782,10 @@ var ts; pushClassification(start, end - start, type); } } + /** + * Returns true if node should be treated as classified and no further processing is required. + * False will mean that node is not classified and traverse routine should recurse into node contents. + */ function tryClassifyNode(node) { if (ts.isJSDoc(node)) { return true; @@ -74824,10 +89794,10 @@ var ts; return true; } var classifiedElementName = tryClassifyJsxElementName(node); - if (!ts.isToken(node) && node.kind !== 10 && classifiedElementName === undefined) { + if (!ts.isToken(node) && node.kind !== 10 /* JsxText */ && classifiedElementName === undefined) { return false; } - var tokenStart = node.kind === 10 ? node.pos : classifyLeadingTriviaAndGetTokenStart(node); + var tokenStart = node.kind === 10 /* JsxText */ ? node.pos : classifyLeadingTriviaAndGetTokenStart(node); var tokenWidth = node.end - tokenStart; ts.Debug.assert(tokenWidth >= 0); if (tokenWidth > 0) { @@ -74840,120 +89810,133 @@ var ts; } function tryClassifyJsxElementName(token) { switch (token.parent && token.parent.kind) { - case 257: + case 257 /* JsxOpeningElement */: if (token.parent.tagName === token) { - return 19; + return 19 /* jsxOpenTagName */; } break; - case 258: + case 258 /* JsxClosingElement */: if (token.parent.tagName === token) { - return 20; + return 20 /* jsxCloseTagName */; } break; - case 256: + case 256 /* JsxSelfClosingElement */: if (token.parent.tagName === token) { - return 21; + return 21 /* jsxSelfClosingTagName */; } break; - case 262: + case 262 /* JsxAttribute */: if (token.parent.name === token) { - return 22; + return 22 /* jsxAttribute */; } break; } return undefined; } + // for accurate classification, the actual token should be passed in. however, for + // cases like 'disabled merge code' classification, we just get the token kind and + // classify based on that instead. function classifyTokenType(tokenKind, token) { if (ts.isKeyword(tokenKind)) { - return 3; + return 3 /* keyword */; } - if (tokenKind === 27 || tokenKind === 29) { + // Special case `<` and `>`: If they appear in a generic context they are punctuation, + // not operators. + if (tokenKind === 27 /* LessThanToken */ || tokenKind === 29 /* GreaterThanToken */) { + // If the node owning the token has a type argument list or type parameter list, then + // we can effectively assume that a '<' and '>' belong to those lists. if (token && ts.getTypeArgumentOrTypeParameterList(token.parent)) { - return 10; + return 10 /* punctuation */; } } if (ts.isPunctuation(tokenKind)) { if (token) { var parent = token.parent; - if (tokenKind === 58) { - if (parent.kind === 232 || - parent.kind === 152 || - parent.kind === 149 || - parent.kind === 262) { - return 5; + if (tokenKind === 58 /* EqualsToken */) { + // the '=' in a variable declaration is special cased here. + if (parent.kind === 232 /* VariableDeclaration */ || + parent.kind === 152 /* PropertyDeclaration */ || + parent.kind === 149 /* Parameter */ || + parent.kind === 262 /* JsxAttribute */) { + return 5 /* operator */; } } - if (parent.kind === 200 || - parent.kind === 198 || - parent.kind === 199 || - parent.kind === 201) { - return 5; + if (parent.kind === 200 /* BinaryExpression */ || + parent.kind === 198 /* PrefixUnaryExpression */ || + parent.kind === 199 /* PostfixUnaryExpression */ || + parent.kind === 201 /* ConditionalExpression */) { + return 5 /* operator */; } } - return 10; + return 10 /* punctuation */; } - else if (tokenKind === 8) { - return 4; + else if (tokenKind === 8 /* NumericLiteral */) { + return 4 /* numericLiteral */; } - else if (tokenKind === 9) { - return token.parent.kind === 262 ? 24 : 6; + else if (tokenKind === 9 /* StringLiteral */) { + // TODO: GH#18217 + return token.parent.kind === 262 /* JsxAttribute */ ? 24 /* jsxAttributeStringLiteralValue */ : 6 /* stringLiteral */; } - else if (tokenKind === 12) { - return 6; + else if (tokenKind === 12 /* RegularExpressionLiteral */) { + // TODO: we should get another classification type for these literals. + return 6 /* stringLiteral */; } else if (ts.isTemplateLiteralKind(tokenKind)) { - return 6; + // TODO (drosen): we should *also* get another classification type for these literals. + return 6 /* stringLiteral */; } - else if (tokenKind === 10) { - return 23; + else if (tokenKind === 10 /* JsxText */) { + return 23 /* jsxText */; } - else if (tokenKind === 71) { + else if (tokenKind === 71 /* Identifier */) { if (token) { switch (token.parent.kind) { - case 235: + case 235 /* ClassDeclaration */: if (token.parent.name === token) { - return 11; + return 11 /* className */; } return; - case 148: + case 148 /* TypeParameter */: if (token.parent.name === token) { - return 15; + return 15 /* typeParameterName */; } return; - case 236: + case 236 /* InterfaceDeclaration */: if (token.parent.name === token) { - return 13; + return 13 /* interfaceName */; } return; - case 238: + case 238 /* EnumDeclaration */: if (token.parent.name === token) { - return 12; + return 12 /* enumName */; } return; - case 239: + case 239 /* ModuleDeclaration */: if (token.parent.name === token) { - return 14; + return 14 /* moduleName */; } return; - case 149: + case 149 /* Parameter */: if (token.parent.name === token) { - return ts.isThisIdentifier(token) ? 3 : 17; + return ts.isThisIdentifier(token) ? 3 /* keyword */ : 17 /* parameterName */; } return; } } - return 2; + return 2 /* identifier */; } } function processElement(element) { if (!element) { return; } + // Ignore nodes that don't intersect the original span to classify. if (ts.decodedTextSpanIntersectsWith(spanStart, spanLength, element.pos, element.getFullWidth())) { checkForClassificationCancellation(cancellationToken, element.kind); for (var _i = 0, _a = element.getChildren(sourceFile); _i < _a.length; _i++) { var child = _a[_i]; if (!tryClassifyNode(child)) { + // Recurse into our child nodes. processElement(child); } } @@ -74962,6 +89945,7 @@ var ts; } ts.getEncodedSyntacticClassifications = getEncodedSyntacticClassifications; })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var Completions; @@ -74989,27 +89973,35 @@ var ts; if (isPathRelativeToScript(literalValue) || ts.isRootedDiskPath(literalValue)) { var extensions = getSupportedExtensionsForModuleResolution(compilerOptions); if (compilerOptions.rootDirs) { - return getCompletionEntriesForDirectoryFragmentWithRootDirs(compilerOptions.rootDirs, literalValue, scriptDirectory, extensions, false, compilerOptions, host, scriptPath); + return getCompletionEntriesForDirectoryFragmentWithRootDirs(compilerOptions.rootDirs, literalValue, scriptDirectory, extensions, /*includeExtensions*/ false, compilerOptions, host, scriptPath); } else { - return getCompletionEntriesForDirectoryFragment(literalValue, scriptDirectory, extensions, false, host, scriptPath); + return getCompletionEntriesForDirectoryFragment(literalValue, scriptDirectory, extensions, /*includeExtensions*/ false, host, scriptPath); } } else { + // Check for node modules return getCompletionEntriesForNonRelativeModules(literalValue, scriptDirectory, compilerOptions, host, typeChecker); } } function getSupportedExtensionsForModuleResolution(compilerOptions) { var extensions = ts.getSupportedExtensions(compilerOptions); return compilerOptions.resolveJsonModule && ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.NodeJs ? - extensions.concat(".json") : + extensions.concat(".json" /* Json */) : extensions; } + /** + * Takes a script path and returns paths for all potential folders that could be merged with its + * containing folder via the "rootDirs" compiler option + */ function getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptPath, ignoreCase) { + // Make all paths absolute/normalized if they are not already rootDirs = rootDirs.map(function (rootDirectory) { return ts.normalizePath(ts.isRootedDiskPath(rootDirectory) ? rootDirectory : ts.combinePaths(basePath, rootDirectory)); }); + // Determine the path to the directory containing the script relative to the root directory it is contained within var relativeDirectory = ts.firstDefined(rootDirs, function (rootDirectory) { return ts.containsPath(rootDirectory, scriptPath, basePath, ignoreCase) ? scriptPath.substr(rootDirectory.length) : undefined; - }); + }); // TODO: GH#18217 + // Now find a path for each potential directory that is to be merged with the one containing the script return ts.deduplicate(rootDirs.map(function (rootDirectory) { return ts.combinePaths(rootDirectory, relativeDirectory); }), ts.equateStringsCaseSensitive, ts.compareStringsCaseSensitive); } function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs, fragment, scriptPath, extensions, includeExtensions, compilerOptions, host, exclude) { @@ -75023,12 +90015,19 @@ var ts; } return result; } + /** + * Given a path ending at a directory, gets the completions for the path, and filters for those entries containing the basename. + */ function getCompletionEntriesForDirectoryFragment(fragment, scriptPath, extensions, includeExtensions, host, exclude, result) { if (result === void 0) { result = []; } if (fragment === undefined) { fragment = ""; } fragment = ts.normalizeSlashes(fragment); + /** + * Remove the basename from the path. Note that we don't use the basename to filter completions; + * the client is responsible for refining completions. + */ if (!ts.hasTrailingDirectorySeparator(fragment)) { fragment = ts.getDirectoryPath(fragment); } @@ -75036,41 +90035,57 @@ var ts; fragment = "." + ts.directorySeparator; } fragment = ts.ensureTrailingDirectorySeparator(fragment); + // const absolutePath = normalizeAndPreserveTrailingSlash(isRootedDiskPath(fragment) ? fragment : combinePaths(scriptPath, fragment)); // TODO(rbuckton): should use resolvePaths var absolutePath = ts.resolvePath(scriptPath, fragment); var baseDirectory = ts.hasTrailingDirectorySeparator(absolutePath) ? absolutePath : ts.getDirectoryPath(absolutePath); var ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); if (tryDirectoryExists(host, baseDirectory)) { - var files = tryReadDirectory(host, baseDirectory, extensions, undefined, ["./*"]); + // Enumerate the available files if possible + var files = tryReadDirectory(host, baseDirectory, extensions, /*exclude*/ undefined, /*include*/ ["./*"]); if (files) { + /** + * Multiple file entries might map to the same truncated name once we remove extensions + * (happens iff includeExtensions === false)so we use a set-like data structure. Eg: + * + * both foo.ts and foo.tsx become foo + */ var foundFiles = ts.createMap(); for (var _i = 0, files_3 = files; _i < files_3.length; _i++) { var filePath = files_3[_i]; filePath = ts.normalizePath(filePath); - if (exclude && ts.comparePaths(filePath, exclude, scriptPath, ignoreCase) === 0) { + if (exclude && ts.comparePaths(filePath, exclude, scriptPath, ignoreCase) === 0 /* EqualTo */) { continue; } - var foundFileName = includeExtensions || ts.fileExtensionIs(filePath, ".json") ? ts.getBaseFileName(filePath) : ts.removeFileExtension(ts.getBaseFileName(filePath)); + var foundFileName = includeExtensions || ts.fileExtensionIs(filePath, ".json" /* Json */) ? ts.getBaseFileName(filePath) : ts.removeFileExtension(ts.getBaseFileName(filePath)); if (!foundFiles.has(foundFileName)) { foundFiles.set(foundFileName, true); } } ts.forEachKey(foundFiles, function (foundFile) { - result.push(nameAndKind(foundFile, "script")); + result.push(nameAndKind(foundFile, "script" /* scriptElement */)); }); } + // If possible, get folder completion as well var directories = tryGetDirectories(host, baseDirectory); if (directories) { for (var _a = 0, directories_1 = directories; _a < directories_1.length; _a++) { var directory = directories_1[_a]; var directoryName = ts.getBaseFileName(ts.normalizePath(directory)); if (directoryName !== "@types") { - result.push(nameAndKind(directoryName, "directory")); + result.push(nameAndKind(directoryName, "directory" /* directory */)); } } } } return result; } + /** + * Check all of the declared modules and those in node modules. Possible sources of modules: + * Modules that are found by the type checker + * Modules found relative to "baseUrl" compliler options (including patterns from "paths" compiler option) + * Modules from node_modules (i.e. those listed in package.json) + * This includes all files that are found in node_modules/moduleName/ with acceptable file extensions + */ function getCompletionEntriesForNonRelativeModules(fragment, scriptPath, compilerOptions, host, typeChecker) { var baseUrl = compilerOptions.baseUrl, paths = compilerOptions.paths; var result = []; @@ -75078,11 +90093,12 @@ var ts; if (baseUrl) { var projectDir = compilerOptions.project || host.getCurrentDirectory(); var absolute = ts.isRootedDiskPath(baseUrl) ? baseUrl : ts.combinePaths(projectDir, baseUrl); - getCompletionEntriesForDirectoryFragment(fragment, ts.normalizePath(absolute), fileExtensions, false, host, undefined, result); + getCompletionEntriesForDirectoryFragment(fragment, ts.normalizePath(absolute), fileExtensions, /*includeExtensions*/ false, host, /*exclude*/ undefined, result); for (var path in paths) { var patterns = paths[path]; if (paths.hasOwnProperty(path) && patterns) { var _loop_13 = function (name, kind) { + // Path mappings may provide a duplicate way to get to something we've already added, so don't add again. if (!result.some(function (entry) { return entry.name === name; })) { result.push(nameAndKind(name, kind)); } @@ -75097,16 +90113,18 @@ var ts; var fragmentDirectory = containsSlash(fragment) ? ts.hasTrailingDirectorySeparator(fragment) ? fragment : ts.getDirectoryPath(fragment) : undefined; for (var _c = 0, _d = getAmbientModuleCompletions(fragment, fragmentDirectory, typeChecker); _c < _d.length; _c++) { var ambientName = _d[_c]; - result.push(nameAndKind(ambientName, "external module name")); + result.push(nameAndKind(ambientName, "external module name" /* externalModuleName */)); } getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, result); if (ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.NodeJs) { + // If looking for a global package name, don't just include everything in `node_modules` because that includes dependencies' own dependencies. + // (But do if we didn't find anything, e.g. 'package.json' missing.) var foundGlobal = false; if (fragmentDirectory === undefined) { var _loop_14 = function (moduleName) { if (!result.some(function (entry) { return entry.name === moduleName; })) { foundGlobal = true; - result.push(nameAndKind(moduleName, "external module name")); + result.push(nameAndKind(moduleName, "external module name" /* externalModuleName */)); } }; for (var _e = 0, _f = enumerateNodeModulesVisibleToScript(host, scriptPath); _e < _f.length; _e++) { @@ -75118,7 +90136,7 @@ var ts; ts.forEachAncestorDirectory(scriptPath, function (ancestor) { var nodeModules = ts.combinePaths(ancestor, "node_modules"); if (tryDirectoryExists(host, nodeModules)) { - getCompletionEntriesForDirectoryFragment(fragment, nodeModules, fileExtensions, false, host, undefined, result); + getCompletionEntriesForDirectoryFragment(fragment, nodeModules, fileExtensions, /*includeExtensions*/ false, host, /*exclude*/ undefined, result); } }); } @@ -75127,11 +90145,12 @@ var ts; } function getCompletionsForPathMapping(path, patterns, fragment, baseUrl, fileExtensions, host) { if (!ts.endsWith(path, "*")) { - return !ts.stringContains(path, "*") && ts.startsWith(path, fragment) ? [{ name: path, kind: "directory" }] : ts.emptyArray; + // For a path mapping "foo": ["/x/y/z.ts"], add "foo" itself as a completion. + return !ts.stringContains(path, "*") && ts.startsWith(path, fragment) ? [{ name: path, kind: "directory" /* directory */ }] : ts.emptyArray; } var pathPrefix = path.slice(0, path.length - 1); if (!ts.startsWith(fragment, pathPrefix)) { - return [{ name: pathPrefix, kind: "directory" }]; + return [{ name: pathPrefix, kind: "directory" /* directory */ }]; } var remainingFragment = fragment.slice(pathPrefix.length); return ts.flatMap(patterns, function (pattern) { return getModulesForPathsPattern(remainingFragment, baseUrl, pattern, fileExtensions, host); }); @@ -75144,18 +90163,26 @@ var ts; if (!parsed) { return undefined; } + // The prefix has two effective parts: the directory path and the base component after the filepath that is not a + // full directory component. For example: directory/path/of/prefix/base* var normalizedPrefix = ts.resolvePath(parsed.prefix); var normalizedPrefixDirectory = ts.hasTrailingDirectorySeparator(parsed.prefix) ? normalizedPrefix : ts.getDirectoryPath(normalizedPrefix); var normalizedPrefixBase = ts.hasTrailingDirectorySeparator(parsed.prefix) ? "" : ts.getBaseFileName(normalizedPrefix); var fragmentHasPath = containsSlash(fragment); var fragmentDirectory = fragmentHasPath ? ts.hasTrailingDirectorySeparator(fragment) ? fragment : ts.getDirectoryPath(fragment) : undefined; + // Try and expand the prefix to include any path from the fragment so that we can limit the readDirectory call var expandedPrefixDirectory = fragmentHasPath ? ts.combinePaths(normalizedPrefixDirectory, normalizedPrefixBase + fragmentDirectory) : normalizedPrefixDirectory; var normalizedSuffix = ts.normalizePath(parsed.suffix); + // Need to normalize after combining: If we combinePaths("a", "../b"), we want "b" and not "a/../b". var baseDirectory = ts.normalizePath(ts.combinePaths(baseUrl, expandedPrefixDirectory)); var completePrefix = fragmentHasPath ? baseDirectory : ts.ensureTrailingDirectorySeparator(baseDirectory) + normalizedPrefixBase; + // If we have a suffix, then we need to read the directory all the way down. We could create a glob + // that encodes the suffix, but we would have to escape the character "?" which readDirectory + // doesn't support. For now, this is safer but slower var includeGlob = normalizedSuffix ? "**/*" : "./*"; - var matches = tryReadDirectory(host, baseDirectory, fileExtensions, undefined, [includeGlob]).map(function (name) { return ({ name: name, kind: "script" }); }); - var directories = tryGetDirectories(host, baseDirectory).map(function (d) { return ts.combinePaths(baseDirectory, d); }).map(function (name) { return ({ name: name, kind: "directory" }); }); + var matches = tryReadDirectory(host, baseDirectory, fileExtensions, /*exclude*/ undefined, [includeGlob]).map(function (name) { return ({ name: name, kind: "script" /* scriptElement */ }); }); + var directories = tryGetDirectories(host, baseDirectory).map(function (d) { return ts.combinePaths(baseDirectory, d); }).map(function (name) { return ({ name: name, kind: "directory" /* directory */ }); }); + // Trim away prefix and suffix return ts.mapDefined(ts.concatenate(matches, directories), function (_a) { var name = _a.name, kind = _a.kind; var normalizedMatch = ts.normalizePath(name); @@ -75170,8 +90197,12 @@ var ts; return path[0] === ts.directorySeparator ? path.slice(1) : path; } function getAmbientModuleCompletions(fragment, fragmentDirectory, checker) { + // Get modules that the type checker picked up var ambientModules = checker.getAmbientModules().map(function (sym) { return ts.stripQuotes(sym.name); }); var nonRelativeModuleNames = ambientModules.filter(function (moduleName) { return ts.startsWith(moduleName, fragment); }); + // Nested modules of the form "module-name/sub" need to be adjusted to only return the string + // after the last '/' that appears in the fragment because that's where the replacement span + // starts if (fragmentDirectory !== undefined) { var moduleNameWithSeparator_1 = ts.ensureTrailingDirectorySeparator(fragmentDirectory); return nonRelativeModuleNames.map(function (nonRelativeModuleName) { return ts.removePrefix(nonRelativeModuleName, moduleNameWithSeparator_1); }); @@ -75179,7 +90210,7 @@ var ts; return nonRelativeModuleNames; } function getTripleSlashReferenceCompletion(sourceFile, position, compilerOptions, host) { - var token = ts.getTokenAtPosition(sourceFile, position, false); + var token = ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); var commentRanges = ts.getLeadingCommentRanges(sourceFile.text, token.pos); var range = commentRanges && ts.find(commentRanges, function (commentRange) { return position >= commentRange.pos && position <= commentRange.end; }); if (!range) { @@ -75192,7 +90223,7 @@ var ts; } var prefix = match[1], kind = match[2], toComplete = match[3]; var scriptPath = ts.getDirectoryPath(sourceFile.path); - var names = kind === "path" ? getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, ts.getSupportedExtensions(compilerOptions), true, host, sourceFile.path) + var names = kind === "path" ? getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, ts.getSupportedExtensions(compilerOptions), /*includeExtensions*/ true, host, sourceFile.path) : kind === "types" ? getCompletionEntriesFromTypings(host, compilerOptions, scriptPath) : undefined; return names && addReplacementSpans(toComplete, range.pos + prefix.length, names); @@ -75200,6 +90231,7 @@ var ts; PathCompletions.getTripleSlashReferenceCompletion = getTripleSlashReferenceCompletion; function getCompletionEntriesFromTypings(host, options, scriptPath, result) { if (result === void 0) { result = []; } + // Check for typings specified in compiler options var seen = ts.createMap(); if (options.types) { for (var _i = 0, _a = options.types; _i < _a.length; _i++) { @@ -75213,13 +90245,14 @@ var ts; try { typeRoots = ts.getEffectiveTypeRoots(options, host); } - catch (_b) { } + catch ( /* Wrap in try catch because getEffectiveTypeRoots touches the filesystem */_b) { /* Wrap in try catch because getEffectiveTypeRoots touches the filesystem */ } if (typeRoots) { for (var _c = 0, typeRoots_2 = typeRoots; _c < typeRoots_2.length; _c++) { var root = typeRoots_2[_c]; getCompletionEntriesFromDirectories(root); } } + // Also get all @types typings installed in visible node_modules directories for (var _d = 0, _e = findPackageJsons(scriptPath, host); _d < _e.length; _d++) { var packageJson = _e[_d]; var typesDir = ts.combinePaths(ts.getDirectoryPath(packageJson), "node_modules/@types"); @@ -75244,7 +90277,7 @@ var ts; } function pushResult(moduleName) { if (!seen.has(moduleName)) { - result.push(nameAndKind(moduleName, "external module name")); + result.push(nameAndKind(moduleName, "external module name" /* externalModuleName */)); seen.set(moduleName, true); } } @@ -75254,7 +90287,7 @@ var ts; ts.forEachAncestorDirectory(directory, function (ancestor) { var currentConfigPath = ts.findConfigFile(ancestor, function (f) { return tryFileExists(host, f); }, "package.json"); if (!currentConfigPath) { - return true; + return true; // break out } paths.push(currentConfigPath); }); @@ -75266,7 +90299,8 @@ var ts; var result = []; for (var _i = 0, _a = findPackageJsons(scriptPath, host); _i < _a.length; _i++) { var packageJson = _a[_i]; - var contents = ts.readJson(packageJson, host); + var contents = ts.readJson(packageJson, host); // Cast to assert that readFile is defined + // Provide completions for all non @types dependencies for (var _b = 0, nodeModulesDependencyKeys_1 = nodeModulesDependencyKeys; _b < nodeModulesDependencyKeys_1.length; _b++) { var key = nodeModulesDependencyKeys_1[_b]; var dependencies = contents[key]; @@ -75281,20 +90315,35 @@ var ts; } return result; } + // Replace everything after the last directory separator that appears function getDirectoryFragmentTextSpan(text, textStart) { var index = Math.max(text.lastIndexOf(ts.directorySeparator), text.lastIndexOf("\\")); var offset = index !== -1 ? index + 1 : 0; + // If the range is an identifier, span is unnecessary. var length = text.length - offset; - return length === 0 || ts.isIdentifierText(text.substr(offset, length), 6) ? undefined : ts.createTextSpan(textStart + offset, length); + return length === 0 || ts.isIdentifierText(text.substr(offset, length), 6 /* ESNext */) ? undefined : ts.createTextSpan(textStart + offset, length); } + // Returns true if the path is explicitly relative to the script (i.e. relative to . or ..) function isPathRelativeToScript(path) { - if (path && path.length >= 2 && path.charCodeAt(0) === 46) { - var slashIndex = path.length >= 3 && path.charCodeAt(1) === 46 ? 2 : 1; + if (path && path.length >= 2 && path.charCodeAt(0) === 46 /* dot */) { + var slashIndex = path.length >= 3 && path.charCodeAt(1) === 46 /* dot */ ? 2 : 1; var slashCharCode = path.charCodeAt(slashIndex); - return slashCharCode === 47 || slashCharCode === 92; + return slashCharCode === 47 /* slash */ || slashCharCode === 92 /* backslash */; } return false; } + /** + * Matches a triple slash reference directive with an incomplete string literal for its path. Used + * to determine if the caret is currently within the string literal and capture the literal fragment + * for completions. + * For example, this matches + * + * /// + // The completion list at "1" will contain "div" with type any var tagName = location.parent.parent.openingElement.tagName; return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: false, entries: [{ name: tagName.getFullText(), - kind: "class", + kind: "class" /* classElement */, kindModifiers: undefined, sortText: "0", }] }; @@ -75433,16 +90490,20 @@ var ts; var entries = []; if (isUncheckedFile(sourceFile, compilerOptions)) { var uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, preferences, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap); - getJavaScriptCompletionEntries(sourceFile, location.pos, uniqueNames, compilerOptions.target, entries); + getJavaScriptCompletionEntries(sourceFile, location.pos, uniqueNames, compilerOptions.target, entries); // TODO: GH#18217 } else { - if ((!symbols || symbols.length === 0) && keywordFilters === 0) { + if ((!symbols || symbols.length === 0) && keywordFilters === 0 /* None */) { return undefined; } getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, preferences, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap); } + // TODO add filter for keyword based on type/value/namespace and also location + // Add all keywords if + // - this is not a member completion list (all the keywords) + // - other filters are enabled in required scenario so add those keywords var isMemberCompletion = isMemberCompletionKind(completionKind); - if (keywordFilters !== 0 || !isMemberCompletion) { + if (keywordFilters !== 0 /* None */ || !isMemberCompletion) { ts.addRange(entries, getKeywordCompletions(keywordFilters)); } for (var _i = 0, literals_1 = literals; _i < literals_1.length; _i++) { @@ -75456,9 +90517,9 @@ var ts; } function isMemberCompletionKind(kind) { switch (kind) { - case 0: - case 3: - case 2: + case 0 /* ObjectPropertyDeclaration */: + case 3 /* MemberLike */: + case 2 /* PropertyAccess */: return true; default: return false; @@ -75466,6 +90527,7 @@ var ts; } function getJavaScriptCompletionEntries(sourceFile, position, uniqueNames, target, entries) { ts.getNameTable(sourceFile).forEach(function (pos, name) { + // Skip identifiers produced only from the current location if (pos === position) { return; } @@ -75473,7 +90535,7 @@ var ts; if (ts.addToSeen(uniqueNames, realName) && ts.isIdentifierText(realName, target) && !ts.isStringANonContextualKeyword(realName)) { entries.push({ name: realName, - kind: "warning", + kind: "warning" /* warning */, kindModifiers: "", sortText: "1" }); @@ -75482,7 +90544,7 @@ var ts; } var completionNameForLiteral = JSON.stringify; function createCompletionEntryForLiteral(literal) { - return { name: completionNameForLiteral(literal), kind: "string", kindModifiers: "", sortText: "0" }; + return { name: completionNameForLiteral(literal), kind: "string" /* string */, kindModifiers: "" /* none */, sortText: "0" }; } function createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, isJsxInitializer, preferences) { var info = getCompletionEntryDisplayNameForSymbol(symbol, target, origin, kind); @@ -75495,9 +90557,12 @@ var ts; if (origin && origin.type === "this-type") { insertText = needsConvertPropertyAccess ? "this[" + quote(name, preferences) + "]" : "this." + name; } + // We should only have needsConvertPropertyAccess if there's a property access to convert. But see #21790. + // Somehow there was a global with a non-identifier name. Hopefully someone will complain about getting a "foo bar" global completion and provide a repro. else if ((origin && origin.type === "symbol-member" || needsConvertPropertyAccess) && propertyAccessToConvert) { insertText = needsConvertPropertyAccess ? "[" + quote(name, preferences) + "]" : "[" + name + "]"; - var dot = ts.findChildOfKind(propertyAccessToConvert, 23, sourceFile); + var dot = ts.findChildOfKind(propertyAccessToConvert, 23 /* DotToken */, sourceFile); + // If the text after the '.' starts with this name, write over it. Else, add new text. var end = ts.startsWith(name, propertyAccessToConvert.name.text) ? propertyAccessToConvert.name.end : dot.end; replacementSpan = ts.createTextSpanFromBounds(dot.getStart(sourceFile), end); } @@ -75512,6 +90577,13 @@ var ts; if (insertText !== undefined && !preferences.includeCompletionsWithInsertText) { return undefined; } + // TODO(drosen): Right now we just permit *all* semantic meanings when calling + // 'getSymbolKind' which is permissible given that it is backwards compatible; but + // really we should consider passing the meaning for the node so that we don't report + // that a suggestion for a value is an interface. We COULD also just do what + // 'getSymbolModifiers' does, which is to use the first declaration. + // Use a 'sortText' of 0' so that all symbol completion entries come before any other + // entries (like JavaScript identifier entries). return { name: name, kind: ts.SymbolDisplay.getSymbolKind(typeChecker, symbol, location), @@ -75538,7 +90610,7 @@ var ts; } function isRecommendedCompletionMatch(localSymbol, recommendedCompletion, checker) { return localSymbol === recommendedCompletion || - !!(localSymbol.flags & 1048576) && checker.getExportSymbolOfSymbol(localSymbol) === recommendedCompletion; + !!(localSymbol.flags & 1048576 /* ExportValue */) && checker.getExportSymbolOfSymbol(localSymbol) === recommendedCompletion; } function trueOrUndefined(b) { return b ? true : undefined; @@ -75548,6 +90620,10 @@ var ts; } function getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, target, log, kind, preferences, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap) { var start = ts.timestamp(); + // Tracks unique names. + // We don't set this for global variables or completions from external module exports, because we can have multiple of those. + // Based on the order we add things we will always see locals first, then globals, then module exports. + // So adding a completion for a local will prevent us from adding completions for external module exports sharing the same name. var uniques = ts.createMap(); for (var _i = 0, symbols_3 = symbols; _i < symbols_3.length; _i++) { var symbol = symbols_3[_i]; @@ -75560,7 +90636,8 @@ var ts; if (uniques.has(name)) { continue; } - if (!origin && !(symbol.parent === undefined && !ts.some(symbol.declarations, function (d) { return d.getSourceFile() === location.getSourceFile(); }))) { + // Latter case tests whether this is a global variable. + if (!origin && !(symbol.parent === undefined && !ts.some(symbol.declarations, function (d) { return d.getSourceFile() === location.getSourceFile(); }))) { // TODO: GH#18217 uniques.set(name, true); } entries.push(entry); @@ -75588,8 +90665,8 @@ var ts; uniques.set(name, true); entries.push({ name: name, - kindModifiers: "", - kind: "label", + kindModifiers: "" /* none */, + kind: "label" /* label */, sortText: "0" }); } @@ -75606,44 +90683,80 @@ var ts; })(StringLiteralCompletionKind || (StringLiteralCompletionKind = {})); function getStringLiteralCompletionEntries(sourceFile, node, position, typeChecker, compilerOptions, host) { switch (node.parent.kind) { - case 178: + case 178 /* LiteralType */: switch (node.parent.parent.kind) { - case 162: - return { kind: 2, types: getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(node.parent)), isNewIdentifier: false }; - case 176: + case 162 /* TypeReference */: + return { kind: 2 /* Types */, types: getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(node.parent)), isNewIdentifier: false }; + case 176 /* IndexedAccessType */: + // Get all apparent property names + // i.e. interface Foo { + // foo: string; + // bar: string; + // } + // let x: Foo["/*completion position*/"] return stringLiteralCompletionsFromProperties(typeChecker.getTypeFromTypeNode(node.parent.parent.objectType)); - case 179: - return { kind: 0, paths: Completions.PathCompletions.getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker) }; + case 179 /* ImportType */: + return { kind: 0 /* Paths */, paths: Completions.PathCompletions.getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker) }; default: return undefined; } - case 270: + case 270 /* PropertyAssignment */: if (ts.isObjectLiteralExpression(node.parent.parent) && node.parent.name === node) { + // Get quoted name of properties of the object literal expression + // i.e. interface ConfigFiles { + // 'jspm:dev': string + // } + // let files: ConfigFiles = { + // '/*completion position*/' + // } + // + // function foo(c: ConfigFiles) {} + // foo({ + // '/*completion position*/' + // }); return stringLiteralCompletionsFromProperties(typeChecker.getContextualType(node.parent.parent)); } return fromContextualType(); - case 186: { + case 186 /* ElementAccessExpression */: { var _a = node.parent, expression = _a.expression, argumentExpression = _a.argumentExpression; if (node === argumentExpression) { + // Get all names of properties on the expression + // i.e. interface A { + // 'prop1': string + // } + // let a: A; + // a['/*completion position*/'] return stringLiteralCompletionsFromProperties(typeChecker.getTypeAtLocation(expression)); } return undefined; } - case 187: - case 188: - if (!ts.isRequireCall(node.parent, false) && !ts.isImportCall(node.parent)) { + case 187 /* CallExpression */: + case 188 /* NewExpression */: + if (!ts.isRequireCall(node.parent, /*checkArgumentIsStringLiteralLike*/ false) && !ts.isImportCall(node.parent)) { var argumentInfo = ts.SignatureHelp.getArgumentInfoForCompletions(node, position, sourceFile); + // Get string literal completions from specialized signatures of the target + // i.e. declare function f(a: 'A'); + // f("/*completion position*/") return argumentInfo ? getStringLiteralCompletionsFromSignature(argumentInfo, typeChecker) : fromContextualType(); } - case 244: - case 250: - case 254: - return { kind: 0, paths: Completions.PathCompletions.getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker) }; + // falls through (is `require("")` or `import("")`) + case 244 /* ImportDeclaration */: + case 250 /* ExportDeclaration */: + case 254 /* ExternalModuleReference */: + // Get all known external module names or complete a path to a module + // i.e. import * as ns from "/*completion position*/"; + // var y = import("/*completion position*/"); + // import x = require("/*completion position*/"); + // var y = require("/*completion position*/"); + // export * from "/*completion position*/"; + return { kind: 0 /* Paths */, paths: Completions.PathCompletions.getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker) }; default: return fromContextualType(); } function fromContextualType() { - return { kind: 2, types: getStringLiteralTypes(getContextualTypeFromParent(node, typeChecker)), isNewIdentifier: false }; + // Get completion for string literal from string literal type + // i.e. var x: "hi" | "hello" = "/*completion position*/" + return { kind: 2 /* Types */, types: getStringLiteralTypes(getContextualTypeFromParent(node, typeChecker)), isNewIdentifier: false }; } } function getStringLiteralCompletionsFromSignature(argumentInfo, checker) { @@ -75655,13 +90768,13 @@ var ts; if (!candidate.hasRestParameter && argumentInfo.argumentCount > candidate.parameters.length) return; var type = checker.getParameterType(candidate, argumentInfo.argumentIndex); - isNewIdentifier = isNewIdentifier || !!(type.flags & 4); + isNewIdentifier = isNewIdentifier || !!(type.flags & 4 /* String */); return getStringLiteralTypes(type, uniques); }); - return { kind: 2, types: types, isNewIdentifier: isNewIdentifier }; + return { kind: 2 /* Types */, types: types, isNewIdentifier: isNewIdentifier }; } function stringLiteralCompletionsFromProperties(type) { - return type && { kind: 1, symbols: type.getApparentProperties(), hasIndexSignature: hasIndexSignature(type) }; + return type && { kind: 1 /* Properties */, symbols: type.getApparentProperties(), hasIndexSignature: hasIndexSignature(type) }; } function getStringLiteralTypes(type, uniques) { if (uniques === void 0) { uniques = ts.createMap(); } @@ -75670,7 +90783,7 @@ var ts; type = ts.skipConstraint(type); return type.isUnion() ? ts.flatMap(type.types, function (t) { return getStringLiteralTypes(t, uniques); }) - : type.isStringLiteral() && !(type.flags & 512) && ts.addToSeen(uniques, type.value) + : type.isStringLiteral() && !(type.flags & 512 /* EnumLiteral */) && ts.addToSeen(uniques, type.value) ? [type] : ts.emptyArray; } @@ -75680,13 +90793,17 @@ var ts; if (!completionData) { return { type: "none" }; } - if (completionData.kind !== 0) { + if (completionData.kind !== 0 /* Data */) { return { type: "request", request: completionData }; } var symbols = completionData.symbols, literals = completionData.literals, location = completionData.location, completionKind = completionData.completionKind, symbolToOriginInfoMap = completionData.symbolToOriginInfoMap, previousToken = completionData.previousToken, isJsxInitializer = completionData.isJsxInitializer; var literal = ts.find(literals, function (l) { return completionNameForLiteral(l) === entryId.name; }); if (literal !== undefined) return { type: "literal", literal: literal }; + // Find the symbol with the matching entry name. + // We don't need to perform character checks here because we're only comparing the + // name against 'entryName' (which is known to be good), not building a new + // completion entry. return ts.firstDefined(symbols, function (symbol) { var origin = symbolToOriginInfoMap[ts.getSymbolId(symbol)]; var info = getCompletionEntryDisplayNameForSymbol(symbol, compilerOptions.target, origin, completionKind); @@ -75696,7 +90813,8 @@ var ts; }) || { type: "none" }; } function getSymbolName(symbol, origin, target) { - return origin && origin.type === "export" && origin.isDefaultExport && symbol.escapedName === "default" + return origin && origin.type === "export" && origin.isDefaultExport && symbol.escapedName === "default" /* Default */ + // Name of "export default foo;" is "foo". Name of "export default 0" is the filename converted to camelCase. ? ts.firstDefined(symbol.declarations, function (d) { return ts.isExportAssignment(d) && ts.isIdentifier(d.expression) ? d.expression.text : undefined; }) || ts.codefix.moduleSymbolToValidIdentifier(origin.moduleSymbol, target) : symbol.name; @@ -75710,18 +90828,19 @@ var ts; var stringLiteralCompletions = !contextToken || !ts.isStringLiteralLike(contextToken) ? undefined : getStringLiteralCompletionEntries(sourceFile, contextToken, position, typeChecker, compilerOptions, host); - return stringLiteralCompletions && stringLiteralCompletionDetails(name, contextToken, stringLiteralCompletions, sourceFile, typeChecker, cancellationToken); + return stringLiteralCompletions && stringLiteralCompletionDetails(name, contextToken, stringLiteralCompletions, sourceFile, typeChecker, cancellationToken); // TODO: GH#18217 } + // Compute all the completion symbols again. var symbolCompletion = getSymbolCompletionFromEntryId(program, log, sourceFile, position, entryId); switch (symbolCompletion.type) { case "request": { var request = symbolCompletion.request; switch (request.kind) { - case 1: + case 1 /* JsDocTagName */: return ts.JsDoc.getJSDocTagNameCompletionDetails(name); - case 2: + case 2 /* JsDocTag */: return ts.JsDoc.getJSDocTagCompletionDetails(name); - case 3: + case 3 /* JsDocParameterName */: return ts.JsDoc.getJSDocParameterNameCompletionDetails(name); default: return ts.Debug.assertNever(request); @@ -75730,40 +90849,41 @@ var ts; case "symbol": { var symbol = symbolCompletion.symbol, location = symbolCompletion.location, symbolToOriginInfoMap = symbolCompletion.symbolToOriginInfoMap, previousToken = symbolCompletion.previousToken; var _a = getCompletionEntryCodeActionsAndSourceDisplay(symbolToOriginInfoMap, symbol, program, typeChecker, host, compilerOptions, sourceFile, previousToken, formatContext, getCanonicalFileName, program.getSourceFiles(), preferences), codeActions = _a.codeActions, sourceDisplay = _a.sourceDisplay; - return createCompletionDetailsForSymbol(symbol, typeChecker, sourceFile, location, cancellationToken, codeActions, sourceDisplay); + return createCompletionDetailsForSymbol(symbol, typeChecker, sourceFile, location, cancellationToken, codeActions, sourceDisplay); // TODO: GH#18217 } case "literal": { var literal = symbolCompletion.literal; - return createSimpleDetails(completionNameForLiteral(literal), "string", typeof literal === "string" ? ts.SymbolDisplayPartKind.stringLiteral : ts.SymbolDisplayPartKind.numericLiteral); + return createSimpleDetails(completionNameForLiteral(literal), "string" /* string */, typeof literal === "string" ? ts.SymbolDisplayPartKind.stringLiteral : ts.SymbolDisplayPartKind.numericLiteral); } case "none": - return allKeywordsCompletions().some(function (c) { return c.name === name; }) ? createSimpleDetails(name, "keyword", ts.SymbolDisplayPartKind.keyword) : undefined; + // Didn't find a symbol with this name. See if we can find a keyword instead. + return allKeywordsCompletions().some(function (c) { return c.name === name; }) ? createSimpleDetails(name, "keyword" /* keyword */, ts.SymbolDisplayPartKind.keyword) : undefined; default: ts.Debug.assertNever(symbolCompletion); } } Completions.getCompletionEntryDetails = getCompletionEntryDetails; function createSimpleDetails(name, kind, kind2) { - return createCompletionDetails(name, "", kind, [ts.displayPart(name, kind2)]); + return createCompletionDetails(name, "" /* none */, kind, [ts.displayPart(name, kind2)]); } function createCompletionDetailsForSymbol(symbol, checker, sourceFile, location, cancellationToken, codeActions, sourceDisplay) { var _a = checker.runWithCancellationToken(cancellationToken, function (checker) { - return ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, sourceFile, location, location, 7); + return ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, sourceFile, location, location, 7 /* All */); }), displayParts = _a.displayParts, documentation = _a.documentation, symbolKind = _a.symbolKind, tags = _a.tags; return createCompletionDetails(symbol.name, ts.SymbolDisplay.getSymbolModifiers(symbol), symbolKind, displayParts, documentation, tags, codeActions, sourceDisplay); } function stringLiteralCompletionDetails(name, location, completion, sourceFile, checker, cancellationToken) { switch (completion.kind) { - case 0: { + case 0 /* Paths */: { var match = ts.find(completion.paths, function (p) { return p.name === name; }); - return match && createCompletionDetails(name, "", match.kind, [ts.textPart(name)]); + return match && createCompletionDetails(name, "" /* none */, match.kind, [ts.textPart(name)]); } - case 1: { + case 1 /* Properties */: { var match = ts.find(completion.symbols, function (s) { return s.name === name; }); return match && createCompletionDetailsForSymbol(match, checker, sourceFile, location, cancellationToken); } - case 2: - return ts.find(completion.types, function (t) { return t.value === name; }) ? createCompletionDetails(name, "", "type", [ts.textPart(name)]) : undefined; + case 2 /* Types */: + return ts.find(completion.types, function (t) { return t.value === name; }) ? createCompletionDetails(name, "" /* none */, "type" /* typeElement */, [ts.textPart(name)]) : undefined; default: return ts.Debug.assertNever(completion); } @@ -75803,9 +90923,11 @@ var ts; CompletionKind[CompletionKind["None"] = 5] = "None"; })(CompletionKind || (CompletionKind = {})); function getRecommendedCompletion(previousToken, contextualType, checker) { + // For a union, return the first one with a recommended completion. return ts.firstDefined(contextualType && (contextualType.isUnion() ? contextualType.types : [contextualType]), function (type) { var symbol = type && type.symbol; - return symbol && (symbol.flags & (8 | 384 | 32) && !ts.isAbstractConstructorSymbol(symbol)) + // Don't include make a recommended completion for an abstract class + return symbol && (symbol.flags & (8 /* EnumMember */ | 384 /* Enum */ | 32 /* Class */) && !ts.isAbstractConstructorSymbol(symbol)) ? getFirstSymbolInChain(symbol, previousToken, checker) : undefined; }); @@ -75813,30 +90935,32 @@ var ts; function getContextualType(previousToken, position, sourceFile, checker) { var parent = previousToken.parent; switch (previousToken.kind) { - case 71: + case 71 /* Identifier */: return getContextualTypeFromParent(previousToken, checker); - case 58: + case 58 /* EqualsToken */: switch (parent.kind) { - case 232: - return checker.getContextualType(parent.initializer); - case 200: + case 232 /* VariableDeclaration */: + return checker.getContextualType(parent.initializer); // TODO: GH#18217 + case 200 /* BinaryExpression */: return checker.getTypeAtLocation(parent.left); - case 262: + case 262 /* JsxAttribute */: return checker.getContextualTypeForJsxAttribute(parent); default: return undefined; } - case 94: + case 94 /* NewKeyword */: return checker.getContextualType(parent); - case 73: + case 73 /* CaseKeyword */: return getSwitchedType(ts.cast(parent, ts.isCaseClause), checker); - case 17: - return ts.isJsxExpression(parent) && parent.parent.kind !== 255 ? checker.getContextualTypeForJsxAttribute(parent.parent) : undefined; + case 17 /* OpenBraceToken */: + return ts.isJsxExpression(parent) && parent.parent.kind !== 255 /* JsxElement */ ? checker.getContextualTypeForJsxAttribute(parent.parent) : undefined; default: var argInfo = ts.SignatureHelp.getArgumentInfoForCompletions(previousToken, position, sourceFile); return argInfo - ? checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex + (previousToken.kind === 26 ? 1 : 0)) + // At `,`, treat this as the next argument after the comma. + ? checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex + (previousToken.kind === 26 /* CommaToken */ ? 1 : 0)) : isEqualityOperatorKind(previousToken.kind) && ts.isBinaryExpression(parent) && isEqualityOperatorKind(parent.operatorToken.kind) + // completion at `x ===/**/` should be for the right side ? checker.getTypeAtLocation(parent.left) : checker.getContextualType(previousToken); } @@ -75844,15 +90968,15 @@ var ts; function getContextualTypeFromParent(node, checker) { var parent = node.parent; switch (parent.kind) { - case 188: + case 188 /* NewExpression */: return checker.getContextualType(parent); - case 200: { + case 200 /* BinaryExpression */: { var _a = parent, left = _a.left, operatorToken = _a.operatorToken, right = _a.right; return isEqualityOperatorKind(operatorToken.kind) ? checker.getTypeAtLocation(node === right ? left : right) : checker.getContextualType(node); } - case 266: + case 266 /* CaseClause */: return parent.expression === node ? getSwitchedType(parent, checker) : undefined; default: return checker.getContextualType(node); @@ -75862,68 +90986,101 @@ var ts; return checker.getTypeAtLocation(caseClause.parent.parent.expression); } function getFirstSymbolInChain(symbol, enclosingDeclaration, checker) { - var chain = checker.getAccessibleSymbolChain(symbol, enclosingDeclaration, 67108863, false); + var chain = checker.getAccessibleSymbolChain(symbol, enclosingDeclaration, /*meaning*/ 67108863 /* All */, /*useOnlyExternalAliasing*/ false); if (chain) return ts.first(chain); return symbol.parent && (isModuleSymbol(symbol.parent) ? symbol : getFirstSymbolInChain(symbol.parent, enclosingDeclaration, checker)); } function isModuleSymbol(symbol) { - return symbol.declarations.some(function (d) { return d.kind === 274; }); + return symbol.declarations.some(function (d) { return d.kind === 274 /* SourceFile */; }); } function getCompletionData(program, log, sourceFile, isUncheckedFile, position, preferences, detailsEntryId) { var typeChecker = program.getTypeChecker(); var start = ts.timestamp(); - var currentToken = ts.getTokenAtPosition(sourceFile, position, false); + var currentToken = ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); // TODO: GH#15853 + // We will check for jsdoc comments with insideComment and getJsDocTagAtPosition. (TODO: that seems rather inefficient to check the same thing so many times.) log("getCompletionData: Get current token: " + (ts.timestamp() - start)); start = ts.timestamp(); + // Completion not allowed inside comments, bail out if this is the case var insideComment = ts.isInComment(sourceFile, position, currentToken); log("getCompletionData: Is inside comment: " + (ts.timestamp() - start)); var insideJsDocTagTypeExpression = false; var isInSnippetScope = false; if (insideComment) { if (ts.hasDocComment(sourceFile, position)) { - if (sourceFile.text.charCodeAt(position - 1) === 64) { - return { kind: 1 }; + if (sourceFile.text.charCodeAt(position - 1) === 64 /* at */) { + // The current position is next to the '@' sign, when no tag name being provided yet. + // Provide a full list of tag names + return { kind: 1 /* JsDocTagName */ }; } else { + // When completion is requested without "@", we will have check to make sure that + // there are no comments prefix the request position. We will only allow "*" and space. + // e.g + // /** |c| /* + // + // /** + // |c| + // */ + // + // /** + // * |c| + // */ + // + // /** + // * |c| + // */ var lineStart = ts.getLineStartPositionForPosition(position, sourceFile); if (!(sourceFile.text.substring(lineStart, position).match(/[^\*|\s|(/\*\*)]/))) { - return { kind: 2 }; + return { kind: 2 /* JsDocTag */ }; } } } + // Completion should work inside certain JsDoc tags. For example: + // /** @type {number | string} */ + // Completion should work in the brackets var tag = getJsDocTagAtPosition(currentToken, position); if (tag) { if (tag.tagName.pos <= position && position <= tag.tagName.end) { - return { kind: 1 }; + return { kind: 1 /* JsDocTagName */ }; } - if (isTagWithTypeExpression(tag) && tag.typeExpression && tag.typeExpression.kind === 278) { - currentToken = ts.getTokenAtPosition(sourceFile, position, true); + if (isTagWithTypeExpression(tag) && tag.typeExpression && tag.typeExpression.kind === 278 /* JSDocTypeExpression */) { + currentToken = ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ true); if (!currentToken || (!ts.isDeclarationName(currentToken) && - (currentToken.parent.kind !== 299 || + (currentToken.parent.kind !== 299 /* JSDocPropertyTag */ || currentToken.parent.name !== currentToken))) { + // Use as type location if inside tag's type expression insideJsDocTagTypeExpression = isCurrentlyEditingNode(tag.typeExpression); } } if (ts.isJSDocParameterTag(tag) && (ts.nodeIsMissing(tag.name) || tag.name.pos <= position && position <= tag.name.end)) { - return { kind: 3, tag: tag }; + return { kind: 3 /* JsDocParameterName */, tag: tag }; } } if (!insideJsDocTagTypeExpression) { + // Proceed if the current position is in jsDoc tag expression; otherwise it is a normal + // comment or the plain text part of a jsDoc comment, so no completion should be available log("Returning an empty list because completion was inside a regular comment or plain text part of a JsDoc comment."); return undefined; } } start = ts.timestamp(); - var previousToken = ts.findPrecedingToken(position, sourceFile, undefined, insideJsDocTagTypeExpression); + var previousToken = ts.findPrecedingToken(position, sourceFile, /*startNode*/ undefined, insideJsDocTagTypeExpression); // TODO: GH#18217 log("getCompletionData: Get previous token 1: " + (ts.timestamp() - start)); + // The decision to provide completion depends on the contextToken, which is determined through the previousToken. + // Note: 'previousToken' (and thus 'contextToken') can be undefined if we are the beginning of the file var contextToken = previousToken; + // Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS| + // Skip this partial identifier and adjust the contextToken to the token that precedes it. if (contextToken && position <= contextToken.end && (ts.isIdentifier(contextToken) || ts.isKeyword(contextToken.kind))) { var start_4 = ts.timestamp(); - contextToken = ts.findPrecedingToken(contextToken.getFullStart(), sourceFile, undefined, insideJsDocTagTypeExpression); + contextToken = ts.findPrecedingToken(contextToken.getFullStart(), sourceFile, /*startNode*/ undefined, insideJsDocTagTypeExpression); // TODO: GH#18217 log("getCompletionData: Get previous token 2: " + (ts.timestamp() - start_4)); } + // Find the node where completion is requested on. + // Also determine whether we are trying to complete with members of that node + // or attributes of a JSX tag. var node = currentToken; var propertyAccessToConvert; var isRightOfDot = false; @@ -75932,73 +91089,83 @@ var ts; var isJsxInitializer = false; var location = ts.getTouchingPropertyName(sourceFile, position); if (contextToken) { + // Bail out if this is a known invalid completion location if (isCompletionListBlocker(contextToken)) { log("Returning an empty list because completion was requested in an invalid position."); return undefined; } var parent = contextToken.parent; - if (contextToken.kind === 23) { + if (contextToken.kind === 23 /* DotToken */) { isRightOfDot = true; switch (parent.kind) { - case 185: + case 185 /* PropertyAccessExpression */: propertyAccessToConvert = parent; node = propertyAccessToConvert.expression; break; - case 146: + case 146 /* QualifiedName */: node = parent.left; break; - case 179: - case 210: + case 179 /* ImportType */: + case 210 /* MetaProperty */: node = parent; break; default: + // There is nothing that precedes the dot, so this likely just a stray character + // or leading into a '...' token. Just bail out instead. return undefined; } } - else if (sourceFile.languageVariant === 1) { - if (parent && parent.kind === 185) { + else if (sourceFile.languageVariant === 1 /* JSX */) { + // + // If the tagname is a property access expression, we will then walk up to the top most of property access expression. + // Then, try to get a JSX container and its associated attributes type. + if (parent && parent.kind === 185 /* PropertyAccessExpression */) { contextToken = parent; parent = parent.parent; } + // Fix location if (currentToken.parent === location) { switch (currentToken.kind) { - case 29: - if (currentToken.parent.kind === 255 || currentToken.parent.kind === 257) { + case 29 /* GreaterThanToken */: + if (currentToken.parent.kind === 255 /* JsxElement */ || currentToken.parent.kind === 257 /* JsxOpeningElement */) { location = currentToken; } break; - case 41: - if (currentToken.parent.kind === 256) { + case 41 /* SlashToken */: + if (currentToken.parent.kind === 256 /* JsxSelfClosingElement */) { location = currentToken; } break; } } switch (parent.kind) { - case 258: - if (contextToken.kind === 41) { + case 258 /* JsxClosingElement */: + if (contextToken.kind === 41 /* SlashToken */) { isStartingCloseTag = true; location = contextToken; } break; - case 200: - if (!(parent.left.flags & 32768)) { + case 200 /* BinaryExpression */: + if (!(parent.left.flags & 32768 /* ThisNodeHasError */)) { + // It has a left-hand side, so we're not in an opening JSX tag. break; } - case 256: - case 255: - case 257: - if (contextToken.kind === 27) { + // falls through + case 256 /* JsxSelfClosingElement */: + case 255 /* JsxElement */: + case 257 /* JsxOpeningElement */: + if (contextToken.kind === 27 /* LessThanToken */) { isRightOfOpenTag = true; location = contextToken; } break; - case 262: + case 262 /* JsxAttribute */: switch (previousToken.kind) { - case 58: + case 58 /* EqualsToken */: isJsxInitializer = true; break; - case 71: + case 71 /* Identifier */: + // For `
x$ + // + // the cursor is outside of both the 'x' and the arrow function 'xyz => x', + // so 'xyz' is not returned in our results. + // + // We define 'adjustedPosition' so that we may appropriately account for + // being at the end of an identifier. The intention is that if requesting completion + // at the end of an identifier, it should be effectively equivalent to requesting completion + // anywhere inside/at the beginning of the identifier. So in the previous case, the + // 'adjustedPosition' will work as if requesting completion in the following: + // + // xyz => $x + // + // If previousToken !== contextToken, then + // - 'contextToken' was adjusted to the token prior to 'previousToken' + // because we were at the end of an identifier. + // - 'previousToken' is defined. var adjustedPosition = previousToken !== contextToken ? previousToken.getStart() : position; var scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; isInSnippetScope = isSnippetScope(scopeNode); - var symbolMeanings = 67901928 | 67216319 | 1920 | 2097152; + var symbolMeanings = 67901928 /* Type */ | 67216319 /* Value */ | 1920 /* Namespace */ | 2097152 /* Alias */; symbols = ts.Debug.assertEachDefined(typeChecker.getSymbolsInScope(scopeNode, symbolMeanings), "getSymbolsInScope() should all be defined"); - if (preferences.includeCompletionsWithInsertText && scopeNode.kind !== 274) { + // Need to insert 'this.' before properties of `this` type, so only do that if `includeInsertTextCompletions` + if (preferences.includeCompletionsWithInsertText && scopeNode.kind !== 274 /* SourceFile */) { var thisType = typeChecker.tryGetThisTypeAt(scopeNode); if (thisType) { - for (var _i = 0, _a = getPropertiesForCompletion(thisType, typeChecker, true); _i < _a.length; _i++) { + for (var _i = 0, _a = getPropertiesForCompletion(thisType, typeChecker, /*isForAccess*/ true); _i < _a.length; _i++) { var symbol = _a[_i]; symbolToOriginInfoMap[ts.getSymbolId(symbol)] = { type: "this-type" }; symbols.push(symbol); @@ -76181,24 +91394,30 @@ var ts; filterGlobalCompletion(symbols); } function shouldOfferImportCompletions() { + // If not already a module, must have modules enabled and not currently be in a commonjs module. (TODO: import completions for commonjs) if (!preferences.includeCompletionsForModuleExports) return false; + // If already using ES6 modules, OK to continue using them. if (sourceFile.externalModuleIndicator) return true; + // If already using commonjs, don't introduce ES6. if (sourceFile.commonJsModuleIndicator) return false; + // If some file is using ES6 modules, assume that it's OK to add more. if (ts.programContainsEs6Modules(program)) return true; + // For JS, stay on the safe side. if (isUncheckedFile) return false; + // If module transpilation is enabled or we're targeting es6 or above, or not emitting, OK. return ts.compilerOptionsIndicateEs6Modules(program.getCompilerOptions()); } function isSnippetScope(scopeNode) { switch (scopeNode.kind) { - case 274: - case 202: - case 265: - case 213: + case 274 /* SourceFile */: + case 202 /* TemplateExpression */: + case 265 /* JsxExpression */: + case 213 /* Block */: return true; default: return ts.isStatement(scopeNode); @@ -76208,57 +91427,64 @@ var ts; var isTypeOnlyCompletion = insideJsDocTagTypeExpression || !isContextTokenValueLocation(contextToken) && (ts.isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken)); var allowTypes = isTypeOnlyCompletion || !isContextTokenValueLocation(contextToken) && ts.isPossiblyTypeArgumentPosition(contextToken, sourceFile); if (isTypeOnlyCompletion) - keywordFilters = 5; + keywordFilters = 5 /* TypeKeywords */; ts.filterMutate(symbols, function (symbol) { if (!ts.isSourceFile(location)) { + // export = /**/ here we want to get all meanings, so any symbol is ok if (ts.isExportAssignment(location.parent)) { return true; } symbol = ts.skipAlias(symbol, typeChecker); + // import m = /**/ <-- It can only access namespace (if typing import = x. this would get member symbols and not namespace) if (ts.isInRightSideOfInternalImportEqualsDeclaration(location)) { - return !!(symbol.flags & 1920); + return !!(symbol.flags & 1920 /* Namespace */); } if (allowTypes) { + // Its a type, but you can reach it by namespace.type as well var symbolAllowedAsType = symbolCanBeReferencedAtTypeLocation(symbol); if (symbolAllowedAsType || isTypeOnlyCompletion) { return symbolAllowedAsType; } } } - return !!(ts.getCombinedLocalAndExportSymbolFlags(symbol) & 67216319); + // expressions are value space (which includes the value namespaces) + return !!(ts.getCombinedLocalAndExportSymbolFlags(symbol) & 67216319 /* Value */); }); } function isContextTokenValueLocation(contextToken) { return contextToken && - contextToken.kind === 103 && - (contextToken.parent.kind === 165 || ts.isTypeOfExpression(contextToken.parent)); + contextToken.kind === 103 /* TypeOfKeyword */ && + (contextToken.parent.kind === 165 /* TypeQuery */ || ts.isTypeOfExpression(contextToken.parent)); } function isContextTokenTypeLocation(contextToken) { if (contextToken) { var parentKind = contextToken.parent.kind; switch (contextToken.kind) { - case 56: - return parentKind === 152 || - parentKind === 151 || - parentKind === 149 || - parentKind === 232 || + case 56 /* ColonToken */: + return parentKind === 152 /* PropertyDeclaration */ || + parentKind === 151 /* PropertySignature */ || + parentKind === 149 /* Parameter */ || + parentKind === 232 /* VariableDeclaration */ || ts.isFunctionLikeKind(parentKind); - case 58: - return parentKind === 237; - case 118: - return parentKind === 208; + case 58 /* EqualsToken */: + return parentKind === 237 /* TypeAliasDeclaration */; + case 118 /* AsKeyword */: + return parentKind === 208 /* AsExpression */; } } return false; } function symbolCanBeReferencedAtTypeLocation(symbol) { symbol = symbol.exportSymbol || symbol; + // This is an alias, follow what it aliases symbol = ts.skipAlias(symbol, typeChecker); - if (symbol.flags & 67901928) { + if (symbol.flags & 67901928 /* Type */) { return true; } - if (symbol.flags & 1536) { + if (symbol.flags & 1536 /* Module */) { var exportedSymbols = typeChecker.getExportsOfModule(symbol); + // If the exported symbols contains type, + // symbol can be referenced at locations where type is allowed return exportedSymbols.some(symbolCanBeReferencedAtTypeLocation); } return false; @@ -76267,20 +91493,28 @@ var ts; var tokenTextLowerCase = tokenText.toLowerCase(); var seenResolvedModules = ts.createMap(); ts.codefix.forEachExternalModuleToImportFrom(typeChecker, sourceFile, program.getSourceFiles(), function (moduleSymbol) { + // Perf -- ignore other modules if this is a request for details if (detailsEntryId && detailsEntryId.source && ts.stripQuotes(moduleSymbol.name) !== detailsEntryId.source) { return; } var resolvedModuleSymbol = typeChecker.resolveExternalModuleSymbol(moduleSymbol); + // resolvedModuleSymbol may be a namespace. A namespace may be `export =` by multiple module declarations, but only keep the first one. if (!ts.addToSeen(seenResolvedModules, ts.getSymbolId(resolvedModuleSymbol))) { return; } for (var _i = 0, _a = typeChecker.getExportsOfModule(moduleSymbol); _i < _a.length; _i++) { var symbol = _a[_i]; + // Don't add a completion for a re-export, only for the original. + // The actual import fix might end up coming from a re-export -- we don't compute that until getting completion details. + // This is just to avoid adding duplicate completion entries. + // + // If `symbol.parent !== ...`, this comes from an `export * from "foo"` re-export. Those don't create new symbols. + // If `some(...)`, this comes from an `export { foo } from "foo"` re-export, which creates a new symbol (thus isn't caught by the first check). if (typeChecker.getMergedSymbol(symbol.parent) !== resolvedModuleSymbol || ts.some(symbol.declarations, function (d) { return ts.isExportSpecifier(d) && !!d.parent.parent.moduleSpecifier; })) { continue; } - var isDefaultExport = symbol.name === "default"; + var isDefaultExport = symbol.name === "default" /* Default */; if (isDefaultExport) { symbol = ts.getLocalSymbolForExportDefault(symbol) || symbol; } @@ -76292,6 +91526,11 @@ var ts; } }); } + /** + * True if you could remove some characters in `a` to get `b`. + * E.g., true for "abcdef" and "bdf". + * But not true for "abcdef" and "dbf". + */ function stringContainsCharactersInOrder(str, characters) { if (characters.length === 0) { return true; @@ -76305,8 +91544,13 @@ var ts; } } } + // Did not find all characters return false; } + /** + * Finds the first node that "embraces" the position, so that one may + * accurately aggregate locals from the closest containing scope. + */ function getScopeNode(initialToken, position, sourceFile) { var scope = initialToken; while (scope && !ts.positionBelongsToNode(scope, position, sourceFile)) { @@ -76324,15 +91568,15 @@ var ts; return result; } function isInJsxText(contextToken) { - if (contextToken.kind === 10) { + if (contextToken.kind === 10 /* JsxText */) { return true; } - if (contextToken.kind === 29 && contextToken.parent) { - if (contextToken.parent.kind === 257) { + if (contextToken.kind === 29 /* GreaterThanToken */ && contextToken.parent) { + if (contextToken.parent.kind === 257 /* JsxOpeningElement */) { return true; } - if (contextToken.parent.kind === 258 || contextToken.parent.kind === 256) { - return !!contextToken.parent.parent && contextToken.parent.parent.kind === 255; + if (contextToken.parent.kind === 258 /* JsxClosingElement */ || contextToken.parent.kind === 256 /* JsxSelfClosingElement */) { + return !!contextToken.parent.parent && contextToken.parent.parent.kind === 255 /* JsxElement */; } } return false; @@ -76341,149 +91585,201 @@ var ts; if (previousToken) { var containingNodeKind = previousToken.parent.kind; switch (previousToken.kind) { - case 26: - return containingNodeKind === 187 - || containingNodeKind === 155 - || containingNodeKind === 188 - || containingNodeKind === 183 - || containingNodeKind === 200 - || containingNodeKind === 163; - case 19: - return containingNodeKind === 187 - || containingNodeKind === 155 - || containingNodeKind === 188 - || containingNodeKind === 191 - || containingNodeKind === 173; - case 21: - return containingNodeKind === 183 - || containingNodeKind === 160 - || containingNodeKind === 147; - case 129: - case 130: + case 26 /* CommaToken */: + return containingNodeKind === 187 /* CallExpression */ // func( a, | + || containingNodeKind === 155 /* Constructor */ // constructor( a, | /* public, protected, private keywords are allowed here, so show completion */ + || containingNodeKind === 188 /* NewExpression */ // new C(a, | + || containingNodeKind === 183 /* ArrayLiteralExpression */ // [a, | + || containingNodeKind === 200 /* BinaryExpression */ // const x = (a, | + || containingNodeKind === 163 /* FunctionType */; // var x: (s: string, list| + case 19 /* OpenParenToken */: + return containingNodeKind === 187 /* CallExpression */ // func( | + || containingNodeKind === 155 /* Constructor */ // constructor( | + || containingNodeKind === 188 /* NewExpression */ // new C(a| + || containingNodeKind === 191 /* ParenthesizedExpression */ // const x = (a| + || containingNodeKind === 173 /* ParenthesizedType */; // function F(pred: (a| /* this can become an arrow function, where 'a' is the argument */ + case 21 /* OpenBracketToken */: + return containingNodeKind === 183 /* ArrayLiteralExpression */ // [ | + || containingNodeKind === 160 /* IndexSignature */ // [ | : string ] + || containingNodeKind === 147 /* ComputedPropertyName */; // [ | /* this can become an index signature */ + case 129 /* ModuleKeyword */: // module | + case 130 /* NamespaceKeyword */: // namespace | return true; - case 23: - return containingNodeKind === 239; - case 17: - return containingNodeKind === 235; - case 58: - return containingNodeKind === 232 - || containingNodeKind === 200; - case 14: - return containingNodeKind === 202; - case 15: - return containingNodeKind === 211; - case 114: - case 112: - case 113: - return containingNodeKind === 152; + case 23 /* DotToken */: + return containingNodeKind === 239 /* ModuleDeclaration */; // module A.| + case 17 /* OpenBraceToken */: + return containingNodeKind === 235 /* ClassDeclaration */; // class A{ | + case 58 /* EqualsToken */: + return containingNodeKind === 232 /* VariableDeclaration */ // const x = a| + || containingNodeKind === 200 /* BinaryExpression */; // x = a| + case 14 /* TemplateHead */: + return containingNodeKind === 202 /* TemplateExpression */; // `aa ${| + case 15 /* TemplateMiddle */: + return containingNodeKind === 211 /* TemplateSpan */; // `aa ${10} dd ${| + case 114 /* PublicKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: + return containingNodeKind === 152 /* PropertyDeclaration */; // class A{ public | } + // Previous token may have been a keyword that was converted to an identifier. switch (keywordForNode(previousToken)) { - case 114: - case 113: - case 112: + case 114 /* PublicKeyword */: + case 113 /* ProtectedKeyword */: + case 112 /* PrivateKeyword */: return true; } } return false; } function isInStringOrRegularExpressionOrTemplateLiteral(contextToken) { + // To be "in" one of these literals, the position has to be: + // 1. entirely within the token text. + // 2. at the end position of an unterminated token. + // 3. at the end of a regular expression (due to trailing flags like '/foo/g'). return (ts.isRegularExpressionLiteral(contextToken) || ts.isStringTextContainingNode(contextToken)) && (ts.rangeContainsPositionExclusive(ts.createTextRangeFromSpan(ts.createTextSpanFromNode(contextToken)), position) || position === contextToken.end && (!!contextToken.isUnterminated || ts.isRegularExpressionLiteral(contextToken))); } + /** + * Aggregates relevant symbols for completion in object literals and object binding patterns. + * Relevant symbols are stored in the captured 'symbols' variable. + * + * @returns true if 'symbols' was successfully populated; false otherwise. + */ function tryGetObjectLikeCompletionSymbols() { var objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken); if (!objectLikeContainer) - return 0; - completionKind = 0; + return 0 /* Continue */; + // We're looking up possible property names from contextual/inferred/declared type. + completionKind = 0 /* ObjectPropertyDeclaration */; var typeMembers; var existingMembers; - if (objectLikeContainer.kind === 184) { + if (objectLikeContainer.kind === 184 /* ObjectLiteralExpression */) { var typeForObject = typeChecker.getContextualType(objectLikeContainer); if (!typeForObject) - return 2; + return 2 /* Fail */; isNewIdentifierLocation = hasIndexSignature(typeForObject); - typeMembers = getPropertiesForCompletion(typeForObject, typeChecker, false); + typeMembers = getPropertiesForCompletion(typeForObject, typeChecker, /*isForAccess*/ false); existingMembers = objectLikeContainer.properties; } else { - ts.Debug.assert(objectLikeContainer.kind === 180); + ts.Debug.assert(objectLikeContainer.kind === 180 /* ObjectBindingPattern */); + // We are *only* completing on properties from the type being destructured. isNewIdentifierLocation = false; var rootDeclaration = ts.getRootDeclaration(objectLikeContainer.parent); if (!ts.isVariableLike(rootDeclaration)) return ts.Debug.fail("Root declaration is not variable-like."); - var canGetType = ts.hasInitializer(rootDeclaration) || ts.hasType(rootDeclaration) || rootDeclaration.parent.parent.kind === 222; - if (!canGetType && rootDeclaration.kind === 149) { + // We don't want to complete using the type acquired by the shape + // of the binding pattern; we are only interested in types acquired + // through type declaration or inference. + // Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed - + // type of parameter will flow in from the contextual type of the function + var canGetType = ts.hasInitializer(rootDeclaration) || ts.hasType(rootDeclaration) || rootDeclaration.parent.parent.kind === 222 /* ForOfStatement */; + if (!canGetType && rootDeclaration.kind === 149 /* Parameter */) { if (ts.isExpression(rootDeclaration.parent)) { canGetType = !!typeChecker.getContextualType(rootDeclaration.parent); } - else if (rootDeclaration.parent.kind === 154 || rootDeclaration.parent.kind === 157) { + else if (rootDeclaration.parent.kind === 154 /* MethodDeclaration */ || rootDeclaration.parent.kind === 157 /* SetAccessor */) { canGetType = ts.isExpression(rootDeclaration.parent.parent) && !!typeChecker.getContextualType(rootDeclaration.parent.parent); } } if (canGetType) { var typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer); if (!typeForObject) - return 2; - typeMembers = typeChecker.getPropertiesOfType(typeForObject).filter(function (symbol) { return !(ts.getDeclarationModifierFlagsFromSymbol(symbol) & 24); }); + return 2 /* Fail */; + // In a binding pattern, get only known properties. Everywhere else we will get all possible properties. + typeMembers = typeChecker.getPropertiesOfType(typeForObject).filter(function (symbol) { return !(ts.getDeclarationModifierFlagsFromSymbol(symbol) & 24 /* NonPublicAccessibilityModifier */); }); existingMembers = objectLikeContainer.elements; } } if (typeMembers && typeMembers.length > 0) { + // Add filtered items to the completion list symbols = filterObjectMembersList(typeMembers, ts.Debug.assertDefined(existingMembers)); } - return 1; + return 1 /* Success */; } + /** + * Aggregates relevant symbols for completion in import clauses and export clauses + * whose declarations have a module specifier; for instance, symbols will be aggregated for + * + * import { | } from "moduleName"; + * export { a as foo, | } from "moduleName"; + * + * but not for + * + * export { | }; + * + * Relevant symbols are stored in the captured 'symbols' variable. + * + * @returns true if 'symbols' was successfully populated; false otherwise. + */ function tryGetImportOrExportClauseCompletionSymbols() { - var namedImportsOrExports = contextToken && (contextToken.kind === 17 || contextToken.kind === 26) + // `import { |` or `import { a as 0, | }` + var namedImportsOrExports = contextToken && (contextToken.kind === 17 /* OpenBraceToken */ || contextToken.kind === 26 /* CommaToken */) ? ts.tryCast(contextToken.parent, ts.isNamedImportsOrExports) : undefined; if (!namedImportsOrExports) - return 0; - var moduleSpecifier = (namedImportsOrExports.kind === 247 ? namedImportsOrExports.parent.parent : namedImportsOrExports.parent).moduleSpecifier; - var moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier); + return 0 /* Continue */; + // cursor is in an import clause + // try to show exported member for imported module + var moduleSpecifier = (namedImportsOrExports.kind === 247 /* NamedImports */ ? namedImportsOrExports.parent.parent : namedImportsOrExports.parent).moduleSpecifier; + var moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier); // TODO: GH#18217 if (!moduleSpecifierSymbol) - return 2; - completionKind = 3; + return 2 /* Fail */; + completionKind = 3 /* MemberLike */; isNewIdentifierLocation = false; var exports = typeChecker.getExportsAndPropertiesOfModule(moduleSpecifierSymbol); var existing = ts.arrayToSet(namedImportsOrExports.elements, function (n) { return isCurrentlyEditingNode(n) ? undefined : (n.propertyName || n.name).escapedText; }); - symbols = exports.filter(function (e) { return e.escapedName !== "default" && !existing.get(e.escapedName); }); - return 1; + symbols = exports.filter(function (e) { return e.escapedName !== "default" /* Default */ && !existing.get(e.escapedName); }); + return 1 /* Success */; } + /** + * Aggregates relevant symbols for completion in class declaration + * Relevant symbols are stored in the captured 'symbols' variable. + */ function tryGetClassLikeCompletionSymbols() { var decl = tryGetObjectTypeDeclarationCompletionContainer(sourceFile, contextToken, location); if (!decl) - return 0; - completionKind = 3; + return 0 /* Continue */; + // We're looking up possible property names from parent type. + completionKind = 3 /* MemberLike */; + // Declaring new property/method/accessor isNewIdentifierLocation = true; - keywordFilters = ts.isClassLike(decl) ? 1 : 2; + keywordFilters = ts.isClassLike(decl) ? 1 /* ClassElementKeywords */ : 2 /* InterfaceElementKeywords */; + // If you're in an interface you don't want to repeat things from super-interface. So just stop here. if (!ts.isClassLike(decl)) - return 1; + return 1 /* Success */; var classElement = contextToken.parent; - var classElementModifierFlags = ts.isClassElement(classElement) ? ts.getModifierFlags(classElement) : 0; - if (contextToken.kind === 71 && !isCurrentlyEditingNode(contextToken)) { + var classElementModifierFlags = ts.isClassElement(classElement) ? ts.getModifierFlags(classElement) : 0 /* None */; + // If this is context token is not something we are editing now, consider if this would lead to be modifier + if (contextToken.kind === 71 /* Identifier */ && !isCurrentlyEditingNode(contextToken)) { switch (contextToken.getText()) { case "private": - classElementModifierFlags = classElementModifierFlags | 8; + classElementModifierFlags = classElementModifierFlags | 8 /* Private */; break; case "static": - classElementModifierFlags = classElementModifierFlags | 32; + classElementModifierFlags = classElementModifierFlags | 32 /* Static */; break; } } - if (!(classElementModifierFlags & 8)) { + // No member list for private methods + if (!(classElementModifierFlags & 8 /* Private */)) { + // List of property symbols of base type that are not private and already implemented var baseSymbols = ts.flatMap(ts.getAllSuperTypeNodes(decl), function (baseTypeNode) { - var type = typeChecker.getTypeAtLocation(baseTypeNode); - return typeChecker.getPropertiesOfType(classElementModifierFlags & 32 ? typeChecker.getTypeOfSymbolAtLocation(type.symbol, decl) : type); + var type = typeChecker.getTypeAtLocation(baseTypeNode); // TODO: GH#18217 + return typeChecker.getPropertiesOfType(classElementModifierFlags & 32 /* Static */ ? typeChecker.getTypeOfSymbolAtLocation(type.symbol, decl) : type); }); symbols = filterClassMembersList(baseSymbols, decl.members, classElementModifierFlags); } - return 1; + return 1 /* Success */; } + /** + * Returns the immediate owning object literal or binding pattern of a context token, + * on the condition that one exists and that the context implies completion should be given. + */ function tryGetObjectLikeCompletionContainer(contextToken) { if (contextToken) { switch (contextToken.kind) { - case 17: - case 26: + case 17 /* OpenBraceToken */: // const x = { | + case 26 /* CommaToken */: // const x = { a: 0, | var parent = contextToken.parent; if (ts.isObjectLiteralExpression(parent) || ts.isObjectBindingPattern(parent)) { return parent; @@ -76497,12 +91793,16 @@ var ts; return !!node.parent && ts.isParameter(node.parent) && ts.isConstructorDeclaration(node.parent.parent) && (ts.isParameterPropertyModifier(node.kind) || ts.isDeclarationName(node)); } + /** + * Returns the immediate owning class declaration of a context token, + * on the condition that one exists and that the context implies completion should be given. + */ function tryGetConstructorLikeCompletionContainer(contextToken) { if (contextToken) { var parent = contextToken.parent; switch (contextToken.kind) { - case 19: - case 26: + case 19 /* OpenParenToken */: + case 26 /* CommaToken */: return ts.isConstructorDeclaration(contextToken.parent) ? contextToken.parent : undefined; default: if (isConstructorParameterCompletion(contextToken)) { @@ -76532,32 +91832,52 @@ var ts; if (contextToken) { var parent = contextToken.parent; switch (contextToken.kind) { - case 28: - case 41: - case 71: - case 185: - case 263: - case 262: - case 264: - if (parent && (parent.kind === 256 || parent.kind === 257)) { + case 28 /* LessThanSlashToken */: + case 41 /* SlashToken */: + case 71 /* Identifier */: + case 185 /* PropertyAccessExpression */: + case 263 /* JsxAttributes */: + case 262 /* JsxAttribute */: + case 264 /* JsxSpreadAttribute */: + if (parent && (parent.kind === 256 /* JsxSelfClosingElement */ || parent.kind === 257 /* JsxOpeningElement */)) { return parent; } - else if (parent.kind === 262) { + else if (parent.kind === 262 /* JsxAttribute */) { + // Currently we parse JsxOpeningLikeElement as: + // JsxOpeningLikeElement + // attributes: JsxAttributes + // properties: NodeArray return parent.parent.parent; } break; - case 9: - if (parent && ((parent.kind === 262) || (parent.kind === 264))) { + // The context token is the closing } or " of an attribute, which means + // its parent is a JsxExpression, whose parent is a JsxAttribute, + // whose parent is a JsxOpeningLikeElement + case 9 /* StringLiteral */: + if (parent && ((parent.kind === 262 /* JsxAttribute */) || (parent.kind === 264 /* JsxSpreadAttribute */))) { + // Currently we parse JsxOpeningLikeElement as: + // JsxOpeningLikeElement + // attributes: JsxAttributes + // properties: NodeArray return parent.parent.parent; } break; - case 18: + case 18 /* CloseBraceToken */: if (parent && - parent.kind === 265 && - parent.parent && parent.parent.kind === 262) { + parent.kind === 265 /* JsxExpression */ && + parent.parent && parent.parent.kind === 262 /* JsxAttribute */) { + // Currently we parse JsxOpeningLikeElement as: + // JsxOpeningLikeElement + // attributes: JsxAttributes + // properties: NodeArray + // each JsxAttribute can have initializer as JsxExpression return parent.parent.parent.parent; } - if (parent && parent.kind === 264) { + if (parent && parent.kind === 264 /* JsxSpreadAttribute */) { + // Currently we parse JsxOpeningLikeElement as: + // JsxOpeningLikeElement + // attributes: JsxAttributes + // properties: NodeArray return parent.parent.parent; } break; @@ -76565,111 +91885,132 @@ var ts; } return undefined; } + /** + * @returns true if we are certain that the currently edited location must define a new location; false otherwise. + */ function isSolelyIdentifierDefinitionLocation(contextToken) { var parent = contextToken.parent; var containingNodeKind = parent.kind; switch (contextToken.kind) { - case 26: - return containingNodeKind === 232 || - containingNodeKind === 233 || - containingNodeKind === 214 || - containingNodeKind === 238 || + case 26 /* CommaToken */: + return containingNodeKind === 232 /* VariableDeclaration */ || + containingNodeKind === 233 /* VariableDeclarationList */ || + containingNodeKind === 214 /* VariableStatement */ || + containingNodeKind === 238 /* EnumDeclaration */ || // enum a { foo, | isFunctionLikeButNotConstructor(containingNodeKind) || - containingNodeKind === 236 || - containingNodeKind === 181 || - containingNodeKind === 237 || + containingNodeKind === 236 /* InterfaceDeclaration */ || // interface A= contextToken.pos); - case 23: - return containingNodeKind === 181; - case 56: - return containingNodeKind === 182; - case 21: - return containingNodeKind === 181; - case 19: - return containingNodeKind === 269 || + case 23 /* DotToken */: + return containingNodeKind === 181 /* ArrayBindingPattern */; // var [.| + case 56 /* ColonToken */: + return containingNodeKind === 182 /* BindingElement */; // var {x :html| + case 21 /* OpenBracketToken */: + return containingNodeKind === 181 /* ArrayBindingPattern */; // var [x| + case 19 /* OpenParenToken */: + return containingNodeKind === 269 /* CatchClause */ || isFunctionLikeButNotConstructor(containingNodeKind); - case 17: - return containingNodeKind === 238; - case 27: - return containingNodeKind === 235 || - containingNodeKind === 205 || - containingNodeKind === 236 || - containingNodeKind === 237 || + case 17 /* OpenBraceToken */: + return containingNodeKind === 238 /* EnumDeclaration */; // enum a { | + case 27 /* LessThanToken */: + return containingNodeKind === 235 /* ClassDeclaration */ || // class A< | + containingNodeKind === 205 /* ClassExpression */ || // var C = class D< | + containingNodeKind === 236 /* InterfaceDeclaration */ || // interface A< | + containingNodeKind === 237 /* TypeAliasDeclaration */ || // type List< | ts.isFunctionLikeKind(containingNodeKind); - case 115: - return containingNodeKind === 152 && !ts.isClassLike(parent.parent); - case 24: - return containingNodeKind === 149 || - (!!parent.parent && parent.parent.kind === 181); - case 114: - case 112: - case 113: - return containingNodeKind === 149 && !ts.isConstructorDeclaration(parent.parent); - case 118: - return containingNodeKind === 248 || - containingNodeKind === 252 || - containingNodeKind === 246; - case 125: - case 136: + case 115 /* StaticKeyword */: + return containingNodeKind === 152 /* PropertyDeclaration */ && !ts.isClassLike(parent.parent); + case 24 /* DotDotDotToken */: + return containingNodeKind === 149 /* Parameter */ || + (!!parent.parent && parent.parent.kind === 181 /* ArrayBindingPattern */); // var [...z| + case 114 /* PublicKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: + return containingNodeKind === 149 /* Parameter */ && !ts.isConstructorDeclaration(parent.parent); + case 118 /* AsKeyword */: + return containingNodeKind === 248 /* ImportSpecifier */ || + containingNodeKind === 252 /* ExportSpecifier */ || + containingNodeKind === 246 /* NamespaceImport */; + case 125 /* GetKeyword */: + case 136 /* SetKeyword */: if (isFromObjectTypeDeclaration(contextToken)) { return false; } - case 75: - case 83: - case 109: - case 89: - case 104: - case 91: - case 110: - case 76: - case 116: - case 139: + // falls through + case 75 /* ClassKeyword */: + case 83 /* EnumKeyword */: + case 109 /* InterfaceKeyword */: + case 89 /* FunctionKeyword */: + case 104 /* VarKeyword */: + case 91 /* ImportKeyword */: + case 110 /* LetKeyword */: + case 76 /* ConstKeyword */: + case 116 /* YieldKeyword */: + case 139 /* TypeKeyword */: // type htm| return true; } + // If the previous token is keyword correspoding to class member completion keyword + // there will be completion available here if (isClassMemberCompletionKeyword(keywordForNode(contextToken)) && isFromObjectTypeDeclaration(contextToken)) { return false; } if (isConstructorParameterCompletion(contextToken)) { + // constructor parameter completion is available only if + // - its modifier of the constructor parameter or + // - its name of the parameter and not being edited + // eg. constructor(a |<- this shouldnt show completion if (!ts.isIdentifier(contextToken) || ts.isParameterPropertyModifier(keywordForNode(contextToken)) || isCurrentlyEditingNode(contextToken)) { return false; } } + // Previous token may have been a keyword that was converted to an identifier. switch (keywordForNode(contextToken)) { - case 117: - case 120: - case 75: - case 76: - case 124: - case 83: - case 89: - case 109: - case 110: - case 112: - case 113: - case 114: - case 115: - case 104: - case 116: + case 117 /* AbstractKeyword */: + case 120 /* AsyncKeyword */: + case 75 /* ClassKeyword */: + case 76 /* ConstKeyword */: + case 124 /* DeclareKeyword */: + case 83 /* EnumKeyword */: + case 89 /* FunctionKeyword */: + case 109 /* InterfaceKeyword */: + case 110 /* LetKeyword */: + case 112 /* PrivateKeyword */: + case 113 /* ProtectedKeyword */: + case 114 /* PublicKeyword */: + case 115 /* StaticKeyword */: + case 104 /* VarKeyword */: + case 116 /* YieldKeyword */: return true; } return ts.isDeclarationName(contextToken) && !ts.isJsxAttribute(contextToken.parent) + // Don't block completions if we're in `class C /**/`, because we're *past* the end of the identifier and might want to complete `extends`. + // If `contextToken !== previousToken`, this is `class C ex/**/`. && !(ts.isClassLike(contextToken.parent) && (contextToken !== previousToken || position > previousToken.end)); } function isFunctionLikeButNotConstructor(kind) { - return ts.isFunctionLikeKind(kind) && kind !== 155; + return ts.isFunctionLikeKind(kind) && kind !== 155 /* Constructor */; } function isDotOfNumericLiteral(contextToken) { - if (contextToken.kind === 8) { + if (contextToken.kind === 8 /* NumericLiteral */) { var text = contextToken.getFullText(); return text.charAt(text.length - 1) === "."; } return false; } + /** + * Filters out completion suggestions for named imports or exports. + * + * @returns Symbols to be suggested in an object binding pattern or object literal expression, barring those whose declarations + * do not occur at the current position and have not otherwise been typed. + */ function filterObjectMembersList(contextualMemberSymbols, existingMembers) { if (existingMembers.length === 0) { return contextualMemberSymbols; @@ -76677,48 +92018,63 @@ var ts; var existingMemberNames = ts.createUnderscoreEscapedMap(); for (var _i = 0, existingMembers_1 = existingMembers; _i < existingMembers_1.length; _i++) { var m = existingMembers_1[_i]; - if (m.kind !== 270 && - m.kind !== 271 && - m.kind !== 182 && - m.kind !== 154 && - m.kind !== 156 && - m.kind !== 157) { + // Ignore omitted expressions for missing members + if (m.kind !== 270 /* PropertyAssignment */ && + m.kind !== 271 /* ShorthandPropertyAssignment */ && + m.kind !== 182 /* BindingElement */ && + m.kind !== 154 /* MethodDeclaration */ && + m.kind !== 156 /* GetAccessor */ && + m.kind !== 157 /* SetAccessor */) { continue; } + // If this is the current item we are editing right now, do not filter it out if (isCurrentlyEditingNode(m)) { continue; } var existingName = void 0; if (ts.isBindingElement(m) && m.propertyName) { - if (m.propertyName.kind === 71) { + // include only identifiers in completion list + if (m.propertyName.kind === 71 /* Identifier */) { existingName = m.propertyName.escapedText; } } else { + // TODO: Account for computed property name + // NOTE: if one only performs this step when m.name is an identifier, + // things like '__proto__' are not filtered out. var name = ts.getNameOfDeclaration(m); existingName = ts.isPropertyNameLiteral(name) ? ts.getEscapedTextOfIdentifierOrLiteral(name) : undefined; } - existingMemberNames.set(existingName, true); + existingMemberNames.set(existingName, true); // TODO: GH#18217 } return contextualMemberSymbols.filter(function (m) { return !existingMemberNames.get(m.escapedName); }); } + /** + * Filters out completion suggestions for class elements. + * + * @returns Symbols to be suggested in an class element depending on existing memebers and symbol flags + */ function filterClassMembersList(baseSymbols, existingMembers, currentClassElementModifierFlags) { var existingMemberNames = ts.createUnderscoreEscapedMap(); for (var _i = 0, existingMembers_2 = existingMembers; _i < existingMembers_2.length; _i++) { var m = existingMembers_2[_i]; - if (m.kind !== 152 && - m.kind !== 154 && - m.kind !== 156 && - m.kind !== 157) { + // Ignore omitted expressions for missing members + if (m.kind !== 152 /* PropertyDeclaration */ && + m.kind !== 154 /* MethodDeclaration */ && + m.kind !== 156 /* GetAccessor */ && + m.kind !== 157 /* SetAccessor */) { continue; } + // If this is the current item we are editing right now, do not filter it out if (isCurrentlyEditingNode(m)) { continue; } - if (ts.hasModifier(m, 8)) { + // Dont filter member even if the name matches if it is declared private in the list + if (ts.hasModifier(m, 8 /* Private */)) { continue; } - if (ts.hasModifier(m, 32) !== !!(currentClassElementModifierFlags & 32)) { + // do not filter it out if the static presence doesnt match + if (ts.hasModifier(m, 32 /* Static */) !== !!(currentClassElementModifierFlags & 32 /* Static */)) { continue; } var existingName = ts.getPropertyNameForPropertyNameNode(m.name); @@ -76729,17 +92085,24 @@ var ts; return baseSymbols.filter(function (propertySymbol) { return !existingMemberNames.has(propertySymbol.escapedName) && !!propertySymbol.declarations && - !(ts.getDeclarationModifierFlagsFromSymbol(propertySymbol) & 8); + !(ts.getDeclarationModifierFlagsFromSymbol(propertySymbol) & 8 /* Private */); }); } + /** + * Filters out completion suggestions from 'symbols' according to existing JSX attributes. + * + * @returns Symbols to be suggested in a JSX element, barring those whose attributes + * do not occur at the current position and have not otherwise been typed. + */ function filterJsxAttributes(symbols, attributes) { var seenNames = ts.createUnderscoreEscapedMap(); for (var _i = 0, attributes_1 = attributes; _i < attributes_1.length; _i++) { var attr = attributes_1[_i]; + // If this is the current item we are editing right now, do not filter it out if (isCurrentlyEditingNode(attr)) { continue; } - if (attr.kind === 262) { + if (attr.kind === 262 /* JsxAttribute */) { seenNames.set(attr.name.escapedText, true); } } @@ -76752,7 +92115,10 @@ var ts; function getCompletionEntryDisplayNameForSymbol(symbol, target, origin, kind) { var name = getSymbolName(symbol, origin, target); if (name === undefined - || symbol.flags & 1536 && ts.startsWithQuote(name) + // If the symbol is external module, don't show it in the completion list + // (i.e declare module "http" { const x; } | // <= request completion here, "http" should not be there) + || symbol.flags & 1536 /* Module */ && ts.startsWithQuote(name) + // If the symbol is the internal name of an ES symbol, it is not a valid entry. Internal names for ES symbols start with "__@" || ts.isKnownSymbol(symbol)) { return undefined; } @@ -76760,28 +92126,31 @@ var ts; if (ts.isIdentifierText(name, target)) return validIdentiferResult; switch (kind) { - case 3: + case 3 /* MemberLike */: return undefined; - case 0: + case 0 /* ObjectPropertyDeclaration */: + // TODO: GH#18169 return { name: JSON.stringify(name), needsConvertPropertyAccess: false }; - case 2: - case 1: - return name.charCodeAt(0) === 32 ? undefined : { name: name, needsConvertPropertyAccess: true }; - case 5: - case 4: + case 2 /* PropertyAccess */: + case 1 /* Global */: // For a 'this.' completion it will be in a global context, but may have a non-identifier name. + // Don't add a completion for a name starting with a space. See https://github.com/Microsoft/TypeScript/pull/20547 + return name.charCodeAt(0) === 32 /* space */ ? undefined : { name: name, needsConvertPropertyAccess: true }; + case 5 /* None */: + case 4 /* String */: return validIdentiferResult; default: ts.Debug.assertNever(kind); } } + // A cache of completion entries for keywords, these do not change between sessions var _keywordCompletions = []; var allKeywordsCompletions = ts.memoize(function () { var res = []; - for (var i = 72; i <= 145; i++) { + for (var i = 72 /* FirstKeyword */; i <= 145 /* LastKeyword */; i++) { res.push({ name: ts.tokenToString(i), - kind: "keyword", - kindModifiers: "", + kind: "keyword" /* keyword */, + kindModifiers: "" /* none */, sortText: "0" }); } @@ -76791,17 +92160,18 @@ var ts; return _keywordCompletions[keywordFilter] || (_keywordCompletions[keywordFilter] = allKeywordsCompletions().filter(function (entry) { var kind = ts.stringToToken(entry.name); switch (keywordFilter) { - case 0: - return kind !== 140; - case 1: + case 0 /* None */: + // "undefined" is a global variable, so don't need a keyword completion for it. + return kind !== 140 /* UndefinedKeyword */; + case 1 /* ClassElementKeywords */: return isClassMemberCompletionKeyword(kind); - case 2: + case 2 /* InterfaceElementKeywords */: return isInterfaceOrTypeLiteralCompletionKeyword(kind); - case 3: + case 3 /* ConstructorParameterKeywords */: return ts.isParameterPropertyModifier(kind); - case 4: + case 4 /* FunctionLikeBodyKeywords */: return !isClassMemberCompletionKeyword(kind); - case 5: + case 5 /* TypeKeywords */: return ts.isTypeKeyword(kind); default: return ts.Debug.assertNever(keywordFilter); @@ -76809,34 +92179,35 @@ var ts; })); } function isInterfaceOrTypeLiteralCompletionKeyword(kind) { - return kind === 132; + return kind === 132 /* ReadonlyKeyword */; } function isClassMemberCompletionKeyword(kind) { switch (kind) { - case 117: - case 123: - case 125: - case 136: - case 120: + case 117 /* AbstractKeyword */: + case 123 /* ConstructorKeyword */: + case 125 /* GetKeyword */: + case 136 /* SetKeyword */: + case 120 /* AsyncKeyword */: return true; default: return ts.isClassMemberModifier(kind); } } function keywordForNode(node) { - return ts.isIdentifier(node) ? node.originalKeywordKind || 0 : node.kind; + return ts.isIdentifier(node) ? node.originalKeywordKind || 0 /* Unknown */ : node.kind; } function isEqualityOperatorKind(kind) { switch (kind) { - case 34: - case 32: - case 35: - case 33: + case 34 /* EqualsEqualsEqualsToken */: + case 32 /* EqualsEqualsToken */: + case 35 /* ExclamationEqualsEqualsToken */: + case 33 /* ExclamationEqualsToken */: return true; default: return false; } } + /** Get the corresponding JSDocTag node if the position is in a jsDoc comment */ function getJsDocTagAtPosition(node, position) { var jsDoc = getJsDocHavingNode(node).jsDoc; if (!jsDoc) @@ -76857,52 +92228,65 @@ var ts; if (!ts.isToken(node)) return node; switch (node.kind) { - case 104: - case 110: - case 76: + case 104 /* VarKeyword */: + case 110 /* LetKeyword */: + case 76 /* ConstKeyword */: + // if the current token is var, let or const, skip the VariableDeclarationList return node.parent.parent; default: return node.parent; } } + /** + * Gets all properties on a type, but if that type is a union of several types, + * excludes array-like types or callable/constructable types. + */ function getPropertiesForCompletion(type, checker, isForAccess) { if (!(type.isUnion())) { return ts.Debug.assertEachDefined(type.getApparentProperties(), "getApparentProperties() should all be defined"); } + // If we're providing completions for an object literal, skip primitive, array-like, or callable types since those shouldn't be implemented by object literals. var filteredTypes = isForAccess ? type.types : type.types.filter(function (memberType) { - return !(memberType.flags & 32764 || checker.isArrayLikeType(memberType) || ts.typeHasCallOrConstructSignatures(memberType, checker)); + return !(memberType.flags & 32764 /* Primitive */ || checker.isArrayLikeType(memberType) || ts.typeHasCallOrConstructSignatures(memberType, checker)); }); return ts.Debug.assertEachDefined(checker.getAllPossiblePropertiesOfTypes(filteredTypes), "getAllPossiblePropertiesOfTypes() should all be defined"); } + /** + * Returns the immediate owning class declaration of a context token, + * on the condition that one exists and that the context implies completion should be given. + */ function tryGetObjectTypeDeclarationCompletionContainer(sourceFile, contextToken, location) { + // class c { method() { } | method2() { } } switch (location.kind) { - case 300: + case 300 /* SyntaxList */: return ts.tryCast(location.parent, ts.isObjectTypeDeclaration); - case 1: + case 1 /* EndOfFileToken */: var cls = ts.tryCast(ts.lastOrUndefined(ts.cast(location.parent, ts.isSourceFile).statements), ts.isObjectTypeDeclaration); - if (cls && !ts.findChildOfKind(cls, 18, sourceFile)) { + if (cls && !ts.findChildOfKind(cls, 18 /* CloseBraceToken */, sourceFile)) { return cls; } } if (!contextToken) return undefined; switch (contextToken.kind) { - case 25: - case 18: + case 25 /* SemicolonToken */: // class c {getValue(): number; | } + case 18 /* CloseBraceToken */: // class c { method() { } | } + // class c { method() { } b| } return isFromObjectTypeDeclaration(location) && location.parent.name === location ? location.parent.parent : ts.tryCast(location, ts.isObjectTypeDeclaration); - case 17: - case 26: + case 17 /* OpenBraceToken */: // class c { | + case 26 /* CommaToken */: // class c {getValue(): number, | } return ts.tryCast(contextToken.parent, ts.isObjectTypeDeclaration); default: if (!isFromObjectTypeDeclaration(contextToken)) return undefined; var isValidKeyword = ts.isClassLike(contextToken.parent.parent) ? isClassMemberCompletionKeyword : isInterfaceOrTypeLiteralCompletionKeyword; - return (isValidKeyword(contextToken.kind) || ts.isIdentifier(contextToken) && isValidKeyword(ts.stringToToken(contextToken.text))) + return (isValidKeyword(contextToken.kind) || ts.isIdentifier(contextToken) && isValidKeyword(ts.stringToToken(contextToken.text))) // TODO: GH#18217 ? contextToken.parent.parent : undefined; } } + // TODO: GH#19856 Would like to return `node is Node & { parent: (ClassElement | TypeElement) & { parent: ObjectTypeDeclaration } }` but then compilation takes > 10 minutes function isFromObjectTypeDeclaration(node) { return node.parent && ts.isClassOrTypeElement(node.parent) && ts.isObjectTypeDeclaration(node.parent.parent); } @@ -76917,23 +92301,25 @@ var ts; case '"': case "'": case "`": + // Only automatically bring up completions if this is an opening quote. return isStringLiteralOrTemplate(contextToken) && position === contextToken.getStart(sourceFile) + 1; case "<": - return contextToken.kind === 27 && contextToken.parent.kind !== 200; + // Opening JSX tag + return contextToken.kind === 27 /* LessThanToken */ && contextToken.parent.kind !== 200 /* BinaryExpression */; case "/": return ts.isStringLiteralLike(contextToken) ? !!ts.tryGetImportFromModuleSpecifier(contextToken) - : contextToken.kind === 41 && ts.isJsxClosingElement(contextToken.parent); + : contextToken.kind === 41 /* SlashToken */ && ts.isJsxClosingElement(contextToken.parent); default: return ts.Debug.assertNever(triggerCharacter); } } function isStringLiteralOrTemplate(node) { switch (node.kind) { - case 9: - case 13: - case 202: - case 189: + case 9 /* StringLiteral */: + case 13 /* NoSubstitutionTemplateLiteral */: + case 202 /* TemplateExpression */: + case 189 /* TaggedTemplateExpression */: return true; default: return false; @@ -76941,6 +92327,7 @@ var ts; } })(Completions = ts.Completions || (ts.Completions = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var DocumentHighlights; @@ -76948,6 +92335,7 @@ var ts; function getDocumentHighlights(program, cancellationToken, sourceFile, position, sourceFilesToSearch) { var node = ts.getTouchingPropertyName(sourceFile, position); if (node.parent && (ts.isJsxOpeningElement(node.parent) && node.parent.tagName === node || ts.isJsxClosingElement(node.parent))) { + // For a JSX element, just highlight the matching tag, not all references. var _a = node.parent.parent, openingElement = _a.openingElement, closingElement = _a.closingElement; var highlightSpans = [openingElement, closingElement].map(function (_a) { var tagName = _a.tagName; @@ -76962,12 +92350,12 @@ var ts; return { fileName: sourceFile.fileName, textSpan: ts.createTextSpanFromNode(node, sourceFile), - kind: "none" + kind: "none" /* none */ }; } function getSemanticDocumentHighlights(position, node, program, cancellationToken, sourceFilesToSearch) { var sourceFilesSet = ts.arrayToSet(sourceFilesToSearch, function (f) { return f.fileName; }); - var referenceEntries = ts.FindAllReferences.getReferenceEntriesForNode(position, node, program, sourceFilesToSearch, cancellationToken, undefined, sourceFilesSet); + var referenceEntries = ts.FindAllReferences.getReferenceEntriesForNode(position, node, program, sourceFilesToSearch, cancellationToken, /*options*/ undefined, sourceFilesSet); if (!referenceEntries) return undefined; var map = ts.arrayToMultiMap(referenceEntries.map(ts.FindAllReferences.toHighlightSpan), function (e) { return e.fileName; }, function (e) { return e.span; }); @@ -76989,40 +92377,40 @@ var ts; } function getHighlightSpans(node, sourceFile) { switch (node.kind) { - case 90: - case 82: + case 90 /* IfKeyword */: + case 82 /* ElseKeyword */: return ts.isIfStatement(node.parent) ? getIfElseOccurrences(node.parent, sourceFile) : undefined; - case 96: + case 96 /* ReturnKeyword */: return useParent(node.parent, ts.isReturnStatement, getReturnOccurrences); - case 100: + case 100 /* ThrowKeyword */: return useParent(node.parent, ts.isThrowStatement, getThrowOccurrences); - case 102: - case 74: - case 87: - var tryStatement = node.kind === 74 ? node.parent.parent : node.parent; + case 102 /* TryKeyword */: + case 74 /* CatchKeyword */: + case 87 /* FinallyKeyword */: + var tryStatement = node.kind === 74 /* CatchKeyword */ ? node.parent.parent : node.parent; return useParent(tryStatement, ts.isTryStatement, getTryCatchFinallyOccurrences); - case 98: + case 98 /* SwitchKeyword */: return useParent(node.parent, ts.isSwitchStatement, getSwitchCaseDefaultOccurrences); - case 73: - case 79: + case 73 /* CaseKeyword */: + case 79 /* DefaultKeyword */: return useParent(node.parent.parent.parent, ts.isSwitchStatement, getSwitchCaseDefaultOccurrences); - case 72: - case 77: + case 72 /* BreakKeyword */: + case 77 /* ContinueKeyword */: return useParent(node.parent, ts.isBreakOrContinueStatement, getBreakOrContinueStatementOccurrences); - case 88: - case 106: - case 81: - return useParent(node.parent, function (n) { return ts.isIterationStatement(n, true); }, getLoopBreakContinueOccurrences); - case 123: - return getFromAllDeclarations(ts.isConstructorDeclaration, [123]); - case 125: - case 136: - return getFromAllDeclarations(ts.isAccessor, [125, 136]); - case 121: + case 88 /* ForKeyword */: + case 106 /* WhileKeyword */: + case 81 /* DoKeyword */: + return useParent(node.parent, function (n) { return ts.isIterationStatement(n, /*lookInLabeledStatements*/ true); }, getLoopBreakContinueOccurrences); + case 123 /* ConstructorKeyword */: + return getFromAllDeclarations(ts.isConstructorDeclaration, [123 /* ConstructorKeyword */]); + case 125 /* GetKeyword */: + case 136 /* SetKeyword */: + return getFromAllDeclarations(ts.isAccessor, [125 /* GetKeyword */, 136 /* SetKeyword */]); + case 121 /* AwaitKeyword */: return useParent(node.parent, ts.isAwaitExpression, getAsyncAndAwaitOccurrences); - case 120: + case 120 /* AsyncKeyword */: return highlightSpans(getAsyncAndAwaitOccurrences(node)); - case 116: + case 116 /* YieldKeyword */: return highlightSpans(getYieldOccurrences(node)); default: return ts.isModifierKind(node.kind) && (ts.isDeclaration(node.parent) || ts.isVariableStatement(node.parent)) @@ -77041,22 +92429,35 @@ var ts; return nodes && nodes.map(function (node) { return getHighlightSpanForNode(node, sourceFile); }); } } + /** + * Aggregates all throw-statements within this node *without* crossing + * into function boundaries and try-blocks with catch-clauses. + */ function aggregateOwnedThrowStatements(node) { if (ts.isThrowStatement(node)) { return [node]; } else if (ts.isTryStatement(node)) { + // Exceptions thrown within a try block lacking a catch clause are "owned" in the current context. return ts.concatenate(node.catchClause ? aggregateOwnedThrowStatements(node.catchClause) : node.tryBlock && aggregateOwnedThrowStatements(node.tryBlock), node.finallyBlock && aggregateOwnedThrowStatements(node.finallyBlock)); } + // Do not cross function boundaries. return ts.isFunctionLike(node) ? undefined : flatMapChildren(node, aggregateOwnedThrowStatements); } + /** + * For lack of a better name, this function takes a throw statement and returns the + * nearest ancestor that is a try-block (whose try statement has a catch clause), + * function-block, or source file. + */ function getThrowStatementOwner(throwStatement) { var child = throwStatement; while (child.parent) { var parent = child.parent; - if (ts.isFunctionBlock(parent) || parent.kind === 274) { + if (ts.isFunctionBlock(parent) || parent.kind === 274 /* SourceFile */) { return parent; } + // A throw-statement is only owned by a try-statement if the try-statement has + // a catch clause, and if the throw-statement occurs within the try block. if (ts.isTryStatement(parent) && parent.tryBlock === child && parent.catchClause) { return child; } @@ -77084,17 +92485,20 @@ var ts; function getBreakOrContinueOwner(statement) { return ts.findAncestor(statement, function (node) { switch (node.kind) { - case 227: - if (statement.kind === 223) { + case 227 /* SwitchStatement */: + if (statement.kind === 223 /* ContinueStatement */) { return false; } - case 220: - case 221: - case 222: - case 219: - case 218: + // falls through + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 219 /* WhileStatement */: + case 218 /* DoStatement */: return !statement.label || isLabeledBy(node, statement.label.escapedText); default: + // Don't cross function boundaries. + // TODO: GH#20090 return ts.isFunctionLike(node) && "quit"; } }); @@ -77110,33 +92514,37 @@ var ts; }); } function getNodesToSearchForModifier(declaration, modifierFlag) { + // Types of node whose children might have modifiers. var container = declaration.parent; switch (container.kind) { - case 240: - case 274: - case 213: - case 266: - case 267: - if (modifierFlag & 128 && ts.isClassDeclaration(declaration)) { + case 240 /* ModuleBlock */: + case 274 /* SourceFile */: + case 213 /* Block */: + case 266 /* CaseClause */: + case 267 /* DefaultClause */: + // Container is either a class declaration or the declaration is a classDeclaration + if (modifierFlag & 128 /* Abstract */ && ts.isClassDeclaration(declaration)) { return declaration.members.concat([declaration]); } else { return container.statements; } - case 155: - case 154: - case 234: + case 155 /* Constructor */: + case 154 /* MethodDeclaration */: + case 234 /* FunctionDeclaration */: return container.parameters.concat((ts.isClassLike(container.parent) ? container.parent.members : [])); - case 235: - case 205: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: var nodes = container.members; - if (modifierFlag & 28) { + // If we're an accessibility modifier, we're in an instance member and should search + // the constructor's parameter list for instance members as well. + if (modifierFlag & 28 /* AccessibilityModifier */) { var constructor = ts.find(container.members, ts.isConstructorDeclaration); if (constructor) { return nodes.concat(constructor.parameters); } } - else if (modifierFlag & 128) { + else if (modifierFlag & 128 /* Abstract */) { return nodes.concat([container]); } return nodes; @@ -77157,11 +92565,12 @@ var ts; } function getLoopBreakContinueOccurrences(loopNode) { var keywords = []; - if (pushKeywordIf(keywords, loopNode.getFirstToken(), 88, 106, 81)) { - if (loopNode.kind === 218) { + if (pushKeywordIf(keywords, loopNode.getFirstToken(), 88 /* ForKeyword */, 106 /* WhileKeyword */, 81 /* DoKeyword */)) { + // If we succeeded and got a do-while loop, then start looking for a 'while' keyword. + if (loopNode.kind === 218 /* DoStatement */) { var loopTokens = loopNode.getChildren(); for (var i = loopTokens.length - 1; i >= 0; i--) { - if (pushKeywordIf(keywords, loopTokens[i], 106)) { + if (pushKeywordIf(keywords, loopTokens[i], 106 /* WhileKeyword */)) { break; } } @@ -77169,7 +92578,7 @@ var ts; } ts.forEach(aggregateAllBreakAndContinueStatements(loopNode.statement), function (statement) { if (ownsBreakOrContinueStatement(loopNode, statement)) { - pushKeywordIf(keywords, statement.getFirstToken(), 72, 77); + pushKeywordIf(keywords, statement.getFirstToken(), 72 /* BreakKeyword */, 77 /* ContinueKeyword */); } }); return keywords; @@ -77178,13 +92587,13 @@ var ts; var owner = getBreakOrContinueOwner(breakOrContinueStatement); if (owner) { switch (owner.kind) { - case 220: - case 221: - case 222: - case 218: - case 219: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 218 /* DoStatement */: + case 219 /* WhileStatement */: return getLoopBreakContinueOccurrences(owner); - case 227: + case 227 /* SwitchStatement */: return getSwitchCaseDefaultOccurrences(owner); } } @@ -77192,12 +92601,13 @@ var ts; } function getSwitchCaseDefaultOccurrences(switchStatement) { var keywords = []; - pushKeywordIf(keywords, switchStatement.getFirstToken(), 98); + pushKeywordIf(keywords, switchStatement.getFirstToken(), 98 /* SwitchKeyword */); + // Go through each clause in the switch statement, collecting the 'case'/'default' keywords. ts.forEach(switchStatement.caseBlock.clauses, function (clause) { - pushKeywordIf(keywords, clause.getFirstToken(), 73, 79); + pushKeywordIf(keywords, clause.getFirstToken(), 73 /* CaseKeyword */, 79 /* DefaultKeyword */); ts.forEach(aggregateAllBreakAndContinueStatements(clause), function (statement) { if (ownsBreakOrContinueStatement(switchStatement, statement)) { - pushKeywordIf(keywords, statement.getFirstToken(), 72); + pushKeywordIf(keywords, statement.getFirstToken(), 72 /* BreakKeyword */); } }); }); @@ -77205,13 +92615,13 @@ var ts; } function getTryCatchFinallyOccurrences(tryStatement, sourceFile) { var keywords = []; - pushKeywordIf(keywords, tryStatement.getFirstToken(), 102); + pushKeywordIf(keywords, tryStatement.getFirstToken(), 102 /* TryKeyword */); if (tryStatement.catchClause) { - pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), 74); + pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), 74 /* CatchKeyword */); } if (tryStatement.finallyBlock) { - var finallyKeyword = ts.findChildOfKind(tryStatement, 87, sourceFile); - pushKeywordIf(keywords, finallyKeyword, 87); + var finallyKeyword = ts.findChildOfKind(tryStatement, 87 /* FinallyKeyword */, sourceFile); + pushKeywordIf(keywords, finallyKeyword, 87 /* FinallyKeyword */); } return keywords; } @@ -77222,11 +92632,13 @@ var ts; } var keywords = []; ts.forEach(aggregateOwnedThrowStatements(owner), function (throwStatement) { - keywords.push(ts.findChildOfKind(throwStatement, 100, sourceFile)); + keywords.push(ts.findChildOfKind(throwStatement, 100 /* ThrowKeyword */, sourceFile)); }); + // If the "owner" is a function, then we equate 'return' and 'throw' statements in their + // ability to "jump out" of the function, and include occurrences for both. if (ts.isFunctionBlock(owner)) { ts.forEachReturnStatement(owner, function (returnStatement) { - keywords.push(ts.findChildOfKind(returnStatement, 96, sourceFile)); + keywords.push(ts.findChildOfKind(returnStatement, 96 /* ReturnKeyword */, sourceFile)); }); } return keywords; @@ -77238,10 +92650,11 @@ var ts; } var keywords = []; ts.forEachReturnStatement(ts.cast(func.body, ts.isBlock), function (returnStatement) { - keywords.push(ts.findChildOfKind(returnStatement, 96, sourceFile)); + keywords.push(ts.findChildOfKind(returnStatement, 96 /* ReturnKeyword */, sourceFile)); }); + // Include 'throw' statements that do not occur within a try block. ts.forEach(aggregateOwnedThrowStatements(func.body), function (throwStatement) { - keywords.push(ts.findChildOfKind(throwStatement, 100, sourceFile)); + keywords.push(ts.findChildOfKind(throwStatement, 100 /* ThrowKeyword */, sourceFile)); }); return keywords; } @@ -77253,13 +92666,13 @@ var ts; var keywords = []; if (func.modifiers) { func.modifiers.forEach(function (modifier) { - pushKeywordIf(keywords, modifier, 120); + pushKeywordIf(keywords, modifier, 120 /* AsyncKeyword */); }); } ts.forEachChild(func, function (child) { traverseWithoutCrossingFunction(child, function (node) { if (ts.isAwaitExpression(node)) { - pushKeywordIf(keywords, node.getFirstToken(), 121); + pushKeywordIf(keywords, node.getFirstToken(), 121 /* AwaitKeyword */); } }); }); @@ -77274,12 +92687,13 @@ var ts; ts.forEachChild(func, function (child) { traverseWithoutCrossingFunction(child, function (node) { if (ts.isYieldExpression(node)) { - pushKeywordIf(keywords, node.getFirstToken(), 116); + pushKeywordIf(keywords, node.getFirstToken(), 116 /* YieldKeyword */); } }); }); return keywords; } + // Do not cross function/class/interface/module/type boundaries. function traverseWithoutCrossingFunction(node, cb) { cb(node); if (!ts.isFunctionLike(node) && !ts.isClassLike(node) && !ts.isInterfaceDeclaration(node) && !ts.isModuleDeclaration(node) && !ts.isTypeAliasDeclaration(node) && !ts.isTypeNode(node)) { @@ -77289,11 +92703,14 @@ var ts; function getIfElseOccurrences(ifStatement, sourceFile) { var keywords = getIfElseKeywords(ifStatement, sourceFile); var result = []; + // We'd like to highlight else/ifs together if they are only separated by whitespace + // (i.e. the keywords are separated by no comments, no newlines). for (var i = 0; i < keywords.length; i++) { - if (keywords[i].kind === 82 && i < keywords.length - 1) { + if (keywords[i].kind === 82 /* ElseKeyword */ && i < keywords.length - 1) { var elseKeyword = keywords[i]; - var ifKeyword = keywords[i + 1]; + var ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword. var shouldCombineElseAndIf = true; + // Avoid recalculating getStart() by iterating backwards. for (var j = ifKeyword.getStart(sourceFile) - 1; j >= elseKeyword.end; j--) { if (!ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(j))) { shouldCombineElseAndIf = false; @@ -77304,26 +92721,30 @@ var ts; result.push({ fileName: sourceFile.fileName, textSpan: ts.createTextSpanFromBounds(elseKeyword.getStart(), ifKeyword.end), - kind: "reference" + kind: "reference" /* reference */ }); - i++; + i++; // skip the next keyword continue; } } + // Ordinary case: just highlight the keyword. result.push(getHighlightSpanForNode(keywords[i], sourceFile)); } return result; } function getIfElseKeywords(ifStatement, sourceFile) { var keywords = []; + // Traverse upwards through all parent if-statements linked by their else-branches. while (ts.isIfStatement(ifStatement.parent) && ifStatement.parent.elseStatement === ifStatement) { ifStatement = ifStatement.parent; } + // Now traverse back down through the else branches, aggregating if/else keywords of if-statements. while (true) { var children = ifStatement.getChildren(sourceFile); - pushKeywordIf(keywords, children[0], 90); + pushKeywordIf(keywords, children[0], 90 /* IfKeyword */); + // Generally the 'else' keyword is second-to-last, so we traverse backwards. for (var i = children.length - 1; i >= 0; i--) { - if (pushKeywordIf(keywords, children[i], 82)) { + if (pushKeywordIf(keywords, children[i], 82 /* ElseKeyword */)) { break; } } @@ -77334,6 +92755,10 @@ var ts; } return keywords; } + /** + * Whether or not a 'node' is preceded by a label of the given string. + * Note: 'node' cannot be a SourceFile. + */ function isLabeledBy(node, labelName) { return !!ts.findAncestor(node.parent, function (owner) { return !ts.isLabeledStatement(owner) ? "quit" : owner.label.escapedText === labelName; }); } @@ -77345,8 +92770,11 @@ var ts; return createDocumentRegistryInternal(useCaseSensitiveFileNames, currentDirectory); } ts.createDocumentRegistry = createDocumentRegistry; + /*@internal*/ function createDocumentRegistryInternal(useCaseSensitiveFileNames, currentDirectory, externalCache) { if (currentDirectory === void 0) { currentDirectory = ""; } + // Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have + // for those settings. var buckets = ts.createMap(); var getCanonicalFileName = ts.createGetCanonicalFileName(!!useCaseSensitiveFileNames); function getKeyForCompilationSettings(settings) { @@ -77357,7 +92785,7 @@ var ts; if (!bucket && createIfMissing) { buckets.set(key, bucket = ts.createMap()); } - return bucket; + return bucket; // TODO: GH#18217 } function reportStats() { var bucketInfoArray = ts.arrayFrom(buckets.keys()).filter(function (name) { return name && name.charAt(0) === "_"; }).map(function (name) { @@ -77383,7 +92811,7 @@ var ts; return acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind); } function acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind) { - return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, true, scriptKind); + return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ true, scriptKind); } function updateDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) { var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); @@ -77391,12 +92819,12 @@ var ts; return updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind); } function updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind) { - return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, false, scriptKind); + return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ false, scriptKind); } function acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, acquiring, scriptKind) { - var bucket = getBucketForCompilationSettings(key, true); + var bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ true); var entry = bucket.get(path); - var scriptTarget = scriptKind === 6 ? 100 : compilationSettings.target; + var scriptTarget = scriptKind === 6 /* JSON */ ? 100 /* JSON */ : compilationSettings.target; if (!entry && externalCache) { var sourceFile = externalCache.getDocument(key, path); if (sourceFile) { @@ -77409,7 +92837,8 @@ var ts; } } if (!entry) { - var sourceFile = ts.createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, false, scriptKind); + // Have never seen this file with these settings. Create a new source file for it. + var sourceFile = ts.createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, /*setNodeParents*/ false, scriptKind); // TODO: GH#18217 if (externalCache) { externalCache.setDocument(key, path, sourceFile); } @@ -77420,12 +92849,20 @@ var ts; bucket.set(path, entry); } else { + // We have an entry for this file. However, it may be for a different version of + // the script snapshot. If so, update it appropriately. Otherwise, we can just + // return it as is. if (entry.sourceFile.version !== version) { - entry.sourceFile = ts.updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version, scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot)); + entry.sourceFile = ts.updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version, scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot)); // TODO: GH#18217 if (externalCache) { externalCache.setDocument(key, path, entry.sourceFile); } } + // If we're acquiring, then this is the first time this LS is asking for this document. + // Increase our ref count so we know there's another LS using the document. If we're + // not acquiring, then that means the LS is 'updating' the file instead, and that means + // it has already acquired the document previously. As such, we do not need to increase + // the ref count. if (acquiring) { entry.languageServiceRefCount++; } @@ -77439,7 +92876,7 @@ var ts; return releaseDocumentWithKey(path, key); } function releaseDocumentWithKey(path, key) { - var bucket = getBucketForCompilationSettings(key, false); + var bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ false); ts.Debug.assert(bucket !== undefined); var entry = bucket.get(path); entry.languageServiceRefCount--; @@ -77469,10 +92906,13 @@ var ts; } ts.createDocumentRegistryInternal = createDocumentRegistryInternal; })(ts || (ts = {})); +/* Code for finding imports of an exported symbol. Used only by FindAllReferences. */ +/* @internal */ var ts; (function (ts) { var FindAllReferences; (function (FindAllReferences) { + /** Creates the imports map and returns an ImportTracker that uses it. Call this lazily to avoid calling `getDirectImportsMap` unnecessarily. */ function createImportTracker(sourceFiles, sourceFilesSet, checker, cancellationToken) { var allDirectImports = getDirectImportsMap(sourceFiles, checker, cancellationToken); return function (exportSymbol, exportInfo, isForRename) { @@ -77492,6 +92932,7 @@ var ts; ImportExport[ImportExport["Import"] = 0] = "Import"; ImportExport[ImportExport["Export"] = 1] = "Export"; })(ImportExport = FindAllReferences.ImportExport || (FindAllReferences.ImportExport = {})); + /** Returns import statements that directly reference the exporting module, and a list of files that may access the module through a namespace. */ function getImportersForExport(sourceFiles, sourceFilesSet, allDirectImports, _a, checker, cancellationToken) { var exportingModuleSymbol = _a.exportingModuleSymbol, exportKind = _a.exportKind; var markSeenDirectImport = ts.nodeSeenTracker(); @@ -77503,14 +92944,17 @@ var ts; return { directImports: directImports, indirectUsers: getIndirectUsers() }; function getIndirectUsers() { if (isAvailableThroughGlobal) { + // It has `export as namespace`, so anything could potentially use it. return sourceFiles; } + // Module augmentations may use this module's exports without importing it. for (var _i = 0, _a = exportingModuleSymbol.declarations; _i < _a.length; _i++) { var decl = _a[_i]; if (ts.isExternalModuleAugmentation(decl) && sourceFilesSet.has(decl.getSourceFile().fileName)) { addIndirectUser(decl); } } + // This may return duplicates (if there are multiple module declarations in a single source file, all importing the same thing as a namespace), but `State.markSearchedSymbol` will handle that. return indirectUserDeclarations.map(ts.getSourceFileOfNode); } function handleDirectImports(exportingModuleSymbol) { @@ -77523,43 +92967,46 @@ var ts; } cancellationToken.throwIfCancellationRequested(); switch (direct.kind) { - case 187: + case 187 /* CallExpression */: if (!isAvailableThroughGlobal) { var parent = direct.parent; - if (exportKind === 2 && parent.kind === 232) { + if (exportKind === 2 /* ExportEquals */ && parent.kind === 232 /* VariableDeclaration */) { var name = parent.name; - if (name.kind === 71) { + if (name.kind === 71 /* Identifier */) { directImports.push(name); break; } } + // Don't support re-exporting 'require()' calls, so just add a single indirect user. addIndirectUser(direct.getSourceFile()); } break; - case 71: + case 71 /* Identifier */: // for 'const x = require("y"); + break; // TODO: GH#23879 + case 243 /* ImportEqualsDeclaration */: + handleNamespaceImport(direct, direct.name, ts.hasModifier(direct, 1 /* Export */), /*alreadyAddedDirect*/ false); break; - case 243: - handleNamespaceImport(direct, direct.name, ts.hasModifier(direct, 1), false); - break; - case 244: + case 244 /* ImportDeclaration */: directImports.push(direct); var namedBindings = direct.importClause && direct.importClause.namedBindings; - if (namedBindings && namedBindings.kind === 246) { - handleNamespaceImport(direct, namedBindings.name, false, true); + if (namedBindings && namedBindings.kind === 246 /* NamespaceImport */) { + handleNamespaceImport(direct, namedBindings.name, /*isReExport*/ false, /*alreadyAddedDirect*/ true); } else if (!isAvailableThroughGlobal && ts.isDefaultImport(direct)) { - addIndirectUser(getSourceFileLikeForImportDeclaration(direct)); + addIndirectUser(getSourceFileLikeForImportDeclaration(direct)); // Add a check for indirect uses to handle synthetic default imports } break; - case 250: + case 250 /* ExportDeclaration */: if (!direct.exportClause) { + // This is `export * from "foo"`, so imports of this module may import the export too. handleDirectImports(getContainingModuleSymbol(direct, checker)); } else { + // This is `export { foo } from "foo"` and creates an alias symbol, so recursive search will get handle re-exports. directImports.push(direct); } break; - case 179: + case 179 /* ImportType */: directImports.push(direct); break; default: @@ -77569,13 +93016,14 @@ var ts; } } function handleNamespaceImport(importDeclaration, name, isReExport, alreadyAddedDirect) { - if (exportKind === 2) { + if (exportKind === 2 /* ExportEquals */) { + // This is a direct import, not import-as-namespace. if (!alreadyAddedDirect) directImports.push(importDeclaration); } else if (!isAvailableThroughGlobal) { var sourceFileLike = getSourceFileLikeForImportDeclaration(importDeclaration); - ts.Debug.assert(sourceFileLike.kind === 274 || sourceFileLike.kind === 239); + ts.Debug.assert(sourceFileLike.kind === 274 /* SourceFile */ || sourceFileLike.kind === 239 /* ModuleDeclaration */); if (isReExport || findNamespaceReExports(sourceFileLike, name, checker)) { addIndirectUsers(sourceFileLike); } @@ -77588,16 +93036,17 @@ var ts; ts.Debug.assert(!isAvailableThroughGlobal); var isNew = markSeenIndirectUser(sourceFileLike); if (isNew) { - indirectUserDeclarations.push(sourceFileLike); + indirectUserDeclarations.push(sourceFileLike); // TODO: GH#18217 } return isNew; } + /** Adds a module and all of its transitive dependencies as possible indirect users. */ function addIndirectUsers(sourceFileLike) { if (!addIndirectUser(sourceFileLike)) { return; } var moduleSymbol = checker.getMergedSymbol(sourceFileLike.symbol); - ts.Debug.assert(!!(moduleSymbol.flags & 1536)); + ts.Debug.assert(!!(moduleSymbol.flags & 1536 /* Module */)); var directImports = getDirectImports(moduleSymbol); if (directImports) { for (var _i = 0, directImports_1 = directImports; _i < directImports_1.length; _i++) { @@ -77610,6 +93059,11 @@ var ts; return allDirectImports.get(ts.getSymbolId(moduleSymbol).toString()); } } + /** + * Given the set of direct imports of a module, we need to find which ones import the particular exported symbol. + * The returned `importSearches` will result in the entire source file being searched. + * But re-exports will be placed in 'singleReferences' since they cannot be locally referenced. + */ function getSearchesFromDirectImports(directImports, exportSymbol, exportKind, checker, isForRename) { var importSearches = []; var singleReferences = []; @@ -77624,42 +93078,44 @@ var ts; } return { importSearches: importSearches, singleReferences: singleReferences }; function handleImport(decl) { - if (decl.kind === 243) { + if (decl.kind === 243 /* ImportEqualsDeclaration */) { if (isExternalModuleImportEquals(decl)) { handleNamespaceImportLike(decl.name); } return; } - if (decl.kind === 71) { + if (decl.kind === 71 /* Identifier */) { handleNamespaceImportLike(decl); return; } - if (decl.kind === 179) { + if (decl.kind === 179 /* ImportType */) { if (decl.qualifier) { if (ts.isIdentifier(decl.qualifier) && decl.qualifier.escapedText === ts.symbolName(exportSymbol)) { singleReferences.push(decl.qualifier); } } - else if (exportKind === 2) { + else if (exportKind === 2 /* ExportEquals */) { singleReferences.push(decl.argument.literal); } return; } - if (decl.moduleSpecifier.kind !== 9) { + // Ignore if there's a grammar error + if (decl.moduleSpecifier.kind !== 9 /* StringLiteral */) { return; } - if (decl.kind === 250) { + if (decl.kind === 250 /* ExportDeclaration */) { searchForNamedImport(decl.exportClause); return; } var _a = decl.importClause || { name: undefined, namedBindings: undefined }, name = _a.name, namedBindings = _a.namedBindings; if (namedBindings) { switch (namedBindings.kind) { - case 246: + case 246 /* NamespaceImport */: handleNamespaceImportLike(namedBindings.name); break; - case 247: - if (exportKind === 0 || exportKind === 1) { + case 247 /* NamedImports */: + // 'default' might be accessed as a named import `{ default as foo }`. + if (exportKind === 0 /* Named */ || exportKind === 1 /* Default */) { searchForNamedImport(namedBindings); } break; @@ -77667,13 +93123,22 @@ var ts; ts.Debug.assertNever(namedBindings); } } - if (name && (exportKind === 1 || exportKind === 2) && (!isForRename || name.escapedText === ts.symbolEscapedNameNoDefault(exportSymbol))) { + // `export =` might be imported by a default import if `--allowSyntheticDefaultImports` is on, so this handles both ExportKind.Default and ExportKind.ExportEquals. + // If a default import has the same name as the default export, allow to rename it. + // Given `import f` and `export default function f`, we will rename both, but for `import g` we will rename just that. + if (name && (exportKind === 1 /* Default */ || exportKind === 2 /* ExportEquals */) && (!isForRename || name.escapedText === ts.symbolEscapedNameNoDefault(exportSymbol))) { var defaultImportAlias = checker.getSymbolAtLocation(name); addSearch(name, defaultImportAlias); } } + /** + * `import x = require("./x") or `import * as x from "./x"`. + * An `export =` may be imported by this syntax, so it may be a direct import. + * If it's not a direct import, it will be in `indirectUsers`, so we don't have to do anything here. + */ function handleNamespaceImportLike(importName) { - if (exportKind === 2 && (!isForRename || isNameMatch(importName.escapedText))) { + // Don't rename an import that already has a different name than the export. + if (exportKind === 2 /* ExportEquals */ && (!isForRename || isNameMatch(importName.escapedText))) { addSearch(importName, checker.getSymbolAtLocation(importName)); } } @@ -77688,23 +93153,29 @@ var ts; continue; } if (propertyName) { + // This is `import { foo as bar } from "./a"` or `export { foo as bar } from "./a"`. `foo` isn't a local in the file, so just add it as a single reference. singleReferences.push(propertyName); + // If renaming `{ foo as bar }`, don't touch `bar`, just `foo`. + // But do rename `foo` in ` { default as foo }` if that's the original export name. if (!isForRename || name.escapedText === exportSymbol.escapedName) { + // Search locally for `bar`. addSearch(name, checker.getSymbolAtLocation(name)); } } else { - var localSymbol = element.kind === 252 && element.propertyName - ? checker.getExportSpecifierLocalTargetSymbol(element) + var localSymbol = element.kind === 252 /* ExportSpecifier */ && element.propertyName + ? checker.getExportSpecifierLocalTargetSymbol(element) // For re-exporting under a different name, we want to get the re-exported symbol. : checker.getSymbolAtLocation(name); addSearch(name, localSymbol); } } } function isNameMatch(name) { - return name === exportSymbol.escapedName || exportKind !== 0 && name === "default"; + // Use name of "default" even in `export =` case because we may have allowSyntheticDefaultImports + return name === exportSymbol.escapedName || exportKind !== 0 /* Named */ && name === "default" /* Default */; } } + /** Returns 'true' is the namespace 'name' is re-exported from this module, and 'false' if it is only used locally. */ function findNamespaceReExports(sourceFileLike, name, checker) { var namespaceImportSymbol = checker.getSymbolAtLocation(name); return !!forEachPossibleImportOrExportStatement(sourceFileLike, function (statement) { @@ -77721,7 +93192,7 @@ var ts; for (var _i = 0, sourceFiles_5 = sourceFiles; _i < sourceFiles_5.length; _i++) { var referencingFile = sourceFiles_5[_i]; var searchSourceFile = searchModuleSymbol.valueDeclaration; - if (searchSourceFile.kind === 274) { + if (searchSourceFile.kind === 274 /* SourceFile */) { for (var _a = 0, _b = referencingFile.referencedFiles; _a < _b.length; _a++) { var ref = _b[_a]; if (program.getSourceFileFromReference(referencingFile, ref) === searchSourceFile) { @@ -77746,6 +93217,7 @@ var ts; return refs; } FindAllReferences.findModuleReferences = findModuleReferences; + /** Returns a map from a module symbol Id to all import statements that directly reference the module. */ function getDirectImportsMap(sourceFiles, checker, cancellationToken) { var map = ts.createMap(); for (var _i = 0, sourceFiles_6 = sourceFiles; _i < sourceFiles_6.length; _i++) { @@ -77765,11 +93237,13 @@ var ts; } return map; } + /** Iterates over all statements at the top level or in module declarations. Returns the first truthy result. */ function forEachPossibleImportOrExportStatement(sourceFileLike, action) { - return ts.forEach(sourceFileLike.kind === 274 ? sourceFileLike.statements : sourceFileLike.body.statements, function (statement) { + return ts.forEach(sourceFileLike.kind === 274 /* SourceFile */ ? sourceFileLike.statements : sourceFileLike.body.statements, function (statement) { return action(statement) || (isAmbientModuleDeclaration(statement) && ts.forEach(statement.body && statement.body.statements, action)); }); } + /** Calls `action` for each import, re-export, or require() in a file. */ function forEachImport(sourceFile, action) { if (sourceFile.externalModuleIndicator || sourceFile.imports !== undefined) { for (var _i = 0, _a = sourceFile.imports; _i < _a.length; _i++) { @@ -77780,15 +93254,15 @@ var ts; else { forEachPossibleImportOrExportStatement(sourceFile, function (statement) { switch (statement.kind) { - case 250: - case 244: { + case 250 /* ExportDeclaration */: + case 244 /* ImportDeclaration */: { var decl = statement; if (decl.moduleSpecifier && ts.isStringLiteral(decl.moduleSpecifier)) { action(decl, decl.moduleSpecifier); } break; } - case 243: { + case 243 /* ImportEqualsDeclaration */: { var decl = statement; if (isExternalModuleImportEquals(decl)) { action(decl, decl.moduleReference.expression); @@ -77799,15 +93273,24 @@ var ts; }); } } + /** + * Given a local reference, we might notice that it's an import/export and recursively search for references of that. + * If at an import, look locally for the symbol it imports. + * If an an export, look for all imports of it. + * This doesn't handle export specifiers; that is done in `getReferencesAtExportSpecifier`. + * @param comingFromExport If we are doing a search for all exports, don't bother looking backwards for the imported symbol, since that's the reason we're here. + */ function getImportOrExportSymbol(node, symbol, checker, comingFromExport) { return comingFromExport ? getExport() : getExport() || getImport(); function getExport() { var parent = node.parent; var grandParent = parent.parent; if (symbol.exportSymbol) { - if (parent.kind === 185) { + if (parent.kind === 185 /* PropertyAccessExpression */) { + // When accessing an export of a JS module, there's no alias. The symbol will still be flagged as an export even though we're at the use. + // So check that we are at the declaration. return symbol.declarations.some(function (d) { return d === parent; }) && ts.isBinaryExpression(grandParent) - ? getSpecialPropertyExport(grandParent, false) + ? getSpecialPropertyExport(grandParent, /*useLhsSymbol*/ false) : undefined; } else { @@ -77816,53 +93299,59 @@ var ts; } else { var exportNode = getExportNode(parent, node); - if (exportNode && ts.hasModifier(exportNode, 1)) { + if (exportNode && ts.hasModifier(exportNode, 1 /* Export */)) { if (ts.isImportEqualsDeclaration(exportNode) && exportNode.moduleReference === node) { + // We're at `Y` in `export import X = Y`. This is not the exported symbol, the left-hand-side is. So treat this as an import statement. if (comingFromExport) { return undefined; } var lhsSymbol = checker.getSymbolAtLocation(exportNode.name); - return { kind: 0, symbol: lhsSymbol, isNamedImport: false }; + return { kind: 0 /* Import */, symbol: lhsSymbol, isNamedImport: false }; } else { return exportInfo(symbol, getExportKindForDeclaration(exportNode)); } } + // If we are in `export = a;` or `export default a;`, `parent` is the export assignment. else if (ts.isExportAssignment(parent)) { return getExportAssignmentExport(parent); } + // If we are in `export = class A {};` (or `export = class A {};`) at `A`, `parent.parent` is the export assignment. else if (ts.isExportAssignment(grandParent)) { return getExportAssignmentExport(grandParent); } + // Similar for `module.exports =` and `exports.A =`. else if (ts.isBinaryExpression(parent)) { - return getSpecialPropertyExport(parent, true); + return getSpecialPropertyExport(parent, /*useLhsSymbol*/ true); } else if (ts.isBinaryExpression(grandParent)) { - return getSpecialPropertyExport(grandParent, true); + return getSpecialPropertyExport(grandParent, /*useLhsSymbol*/ true); } else if (ts.isJSDocTypedefTag(parent)) { - return exportInfo(symbol, 0); + return exportInfo(symbol, 0 /* Named */); } } function getExportAssignmentExport(ex) { + // Get the symbol for the `export =` node; its parent is the module it's the export of. var exportingModuleSymbol = ts.Debug.assertDefined(ex.symbol.parent, "Expected export symbol to have a parent"); - var exportKind = ex.isExportEquals ? 2 : 1; - return { kind: 1, symbol: symbol, exportInfo: { exportingModuleSymbol: exportingModuleSymbol, exportKind: exportKind } }; + var exportKind = ex.isExportEquals ? 2 /* ExportEquals */ : 1 /* Default */; + return { kind: 1 /* Export */, symbol: symbol, exportInfo: { exportingModuleSymbol: exportingModuleSymbol, exportKind: exportKind } }; } function getSpecialPropertyExport(node, useLhsSymbol) { var kind; switch (ts.getSpecialPropertyAssignmentKind(node)) { - case 1: - kind = 0; + case 1 /* ExportsProperty */: + kind = 0 /* Named */; break; - case 2: - kind = 2; + case 2 /* ModuleExports */: + kind = 2 /* ExportEquals */; break; default: return undefined; } var sym = useLhsSymbol ? checker.getSymbolAtLocation(ts.cast(node.left, ts.isPropertyAccessExpression).name) : symbol; - if (sym && !(checker.getMergedSymbol(sym.parent).flags & 1536)) { + // Better detection for GH#20803 + if (sym && !(checker.getMergedSymbol(sym.parent).flags & 1536 /* Module */)) { ts.Debug.fail("Special property assignment kind does not have a module as its parent. Assignment is " + ts.Debug.showSymbol(sym) + ", parent is " + ts.Debug.showSymbol(sym.parent)); } return sym && exportInfo(sym, kind); @@ -77872,48 +93361,57 @@ var ts; var isImport = isNodeImport(node); if (!isImport) return undefined; + // A symbol being imported is always an alias. So get what that aliases to find the local symbol. var importedSymbol = checker.getImmediateAliasedSymbol(symbol); if (!importedSymbol) return undefined; + // Search on the local symbol in the exporting module, not the exported symbol. importedSymbol = skipExportSpecifierSymbol(importedSymbol, checker); + // Similarly, skip past the symbol for 'export =' if (importedSymbol.escapedName === "export=") { importedSymbol = getExportEqualsLocalSymbol(importedSymbol, checker); } + // If the import has a different name than the export, do not continue searching. + // If `importedName` is undefined, do continue searching as the export is anonymous. + // (All imports returned from this function will be ignored anyway if we are in rename and this is a not a named export.) var importedName = ts.symbolEscapedNameNoDefault(importedSymbol); - if (importedName === undefined || importedName === "default" || importedName === symbol.escapedName) { - return __assign({ kind: 0, symbol: importedSymbol }, isImport); + if (importedName === undefined || importedName === "default" /* Default */ || importedName === symbol.escapedName) { + return __assign({ kind: 0 /* Import */, symbol: importedSymbol }, isImport); } } function exportInfo(symbol, kind) { var exportInfo = getExportInfo(symbol, kind, checker); - return exportInfo && { kind: 1, symbol: symbol, exportInfo: exportInfo }; + return exportInfo && { kind: 1 /* Export */, symbol: symbol, exportInfo: exportInfo }; } + // Not meant for use with export specifiers or export assignment. function getExportKindForDeclaration(node) { - return ts.hasModifier(node, 512) ? 1 : 0; + return ts.hasModifier(node, 512 /* Default */) ? 1 /* Default */ : 0 /* Named */; } } FindAllReferences.getImportOrExportSymbol = getImportOrExportSymbol; function getExportEqualsLocalSymbol(importedSymbol, checker) { - if (importedSymbol.flags & 2097152) { + if (importedSymbol.flags & 2097152 /* Alias */) { return ts.Debug.assertDefined(checker.getImmediateAliasedSymbol(importedSymbol)); } var decl = importedSymbol.valueDeclaration; - if (ts.isExportAssignment(decl)) { + if (ts.isExportAssignment(decl)) { // `export = class {}` return ts.Debug.assertDefined(decl.expression.symbol); } - else if (ts.isBinaryExpression(decl)) { + else if (ts.isBinaryExpression(decl)) { // `module.exports = class {}` return ts.Debug.assertDefined(decl.right.symbol); } - else if (ts.isSourceFile(decl)) { + else if (ts.isSourceFile(decl)) { // json module return ts.Debug.assertDefined(decl.symbol); } return ts.Debug.fail(); } + // If a reference is a class expression, the exported node would be its parent. + // If a reference is a variable declaration, the exported node would be the variable statement. function getExportNode(parent, node) { - if (parent.kind === 232) { + if (parent.kind === 232 /* VariableDeclaration */) { var p = parent; return p.name !== node ? undefined : - p.parent.kind === 269 ? undefined : p.parent.parent.kind === 214 ? p.parent.parent : undefined; + p.parent.kind === 269 /* CatchClause */ ? undefined : p.parent.parent.kind === 214 /* VariableStatement */ ? p.parent.parent : undefined; } else { return parent; @@ -77922,14 +93420,15 @@ var ts; function isNodeImport(node) { var parent = node.parent; switch (parent.kind) { - case 243: + case 243 /* ImportEqualsDeclaration */: return parent.name === node && isExternalModuleImportEquals(parent) ? { isNamedImport: false } : undefined; - case 248: + case 248 /* ImportSpecifier */: + // For a rename import `{ foo as bar }`, don't search for the imported symbol. Just find local uses of `bar`. return parent.propertyName ? undefined : { isNamedImport: true }; - case 245: - case 246: + case 245 /* ImportClause */: + case 246 /* NamespaceImport */: ts.Debug.assert(parent.name === node); return { isNamedImport: false }; default: @@ -77939,12 +93438,15 @@ var ts; function getExportInfo(exportSymbol, exportKind, checker) { var moduleSymbol = exportSymbol.parent; if (!moduleSymbol) - return undefined; - var exportingModuleSymbol = checker.getMergedSymbol(moduleSymbol); + return undefined; // This can happen if an `export` is not at the top-level (which is a compile error). + var exportingModuleSymbol = checker.getMergedSymbol(moduleSymbol); // Need to get merged symbol in case there's an augmentation. + // `export` may appear in a namespace. In that case, just rely on global search. return ts.isExternalModuleSymbol(exportingModuleSymbol) ? { exportingModuleSymbol: exportingModuleSymbol, exportKind: exportKind } : undefined; } FindAllReferences.getExportInfo = getExportInfo; + /** If at an export specifier, go to the symbol it refers to. */ function skipExportSpecifierSymbol(symbol, checker) { + // For `export { foo } from './bar", there's nothing to skip, because it does not create a new alias. But `export { foo } does. if (symbol.declarations) { for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var declaration = _a[_i]; @@ -77959,24 +93461,25 @@ var ts; return checker.getMergedSymbol(getSourceFileLikeForImportDeclaration(importer).symbol); } function getSourceFileLikeForImportDeclaration(node) { - if (node.kind === 187) { + if (node.kind === 187 /* CallExpression */) { return node.getSourceFile(); } var parent = node.parent; - if (parent.kind === 274) { + if (parent.kind === 274 /* SourceFile */) { return parent; } - ts.Debug.assert(parent.kind === 240); + ts.Debug.assert(parent.kind === 240 /* ModuleBlock */); return ts.cast(parent.parent, isAmbientModuleDeclaration); } function isAmbientModuleDeclaration(node) { - return node.kind === 239 && node.name.kind === 9; + return node.kind === 239 /* ModuleDeclaration */ && node.name.kind === 9 /* StringLiteral */; } function isExternalModuleImportEquals(eq) { - return eq.moduleReference.kind === 254 && eq.moduleReference.expression.kind === 9; + return eq.moduleReference.kind === 254 /* ExternalModuleReference */ && eq.moduleReference.expression.kind === 9 /* StringLiteral */; } })(FindAllReferences = ts.FindAllReferences || (ts.FindAllReferences = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var FindAllReferences; @@ -77991,6 +93494,7 @@ var ts; var checker = program.getTypeChecker(); return !referencedSymbols || !referencedSymbols.length ? undefined : ts.mapDefined(referencedSymbols, function (_a) { var definition = _a.definition, references = _a.references; + // Only include referenced symbols that have a valid definition. return definition && { definition: checker.runWithCancellationToken(cancellationToken, function (checker) { return definitionToReferencedSymbolDefinitionInfo(definition, checker, node); }), references: references.map(toReferenceEntry) @@ -78006,20 +93510,25 @@ var ts; } FindAllReferences.getImplementationsAtPosition = getImplementationsAtPosition; function getImplementationReferenceEntries(program, cancellationToken, sourceFiles, node, position) { - if (node.kind === 274) { + if (node.kind === 274 /* SourceFile */) { return undefined; } var checker = program.getTypeChecker(); - if (node.parent.kind === 271) { + // If invoked directly on a shorthand property assignment, then return + // the declaration of the symbol being assigned (not the symbol being assigned to). + if (node.parent.kind === 271 /* ShorthandPropertyAssignment */) { var result_6 = []; FindAllReferences.Core.getReferenceEntriesForShorthandPropertyAssignment(node, checker, function (node) { return result_6.push(nodeEntry(node)); }); return result_6; } - else if (node.kind === 97 || ts.isSuperProperty(node.parent)) { + else if (node.kind === 97 /* SuperKeyword */ || ts.isSuperProperty(node.parent)) { + // References to and accesses on the super keyword only have one possible implementation, so no + // need to "Find all References" var symbol = checker.getSymbolAtLocation(node); return symbol.valueDeclaration && [nodeEntry(symbol.valueDeclaration)]; } else { + // Perform "Find all References" and retrieve only those that are implementations return getReferenceEntriesForNode(position, node, program, sourceFiles, cancellationToken, { implementations: true }); } } @@ -78048,22 +93557,22 @@ var ts; } case "label": { var node_3 = def.node; - return { node: node_3, name: node_3.text, kind: "label", displayParts: [ts.displayPart(node_3.text, ts.SymbolDisplayPartKind.text)] }; + return { node: node_3, name: node_3.text, kind: "label" /* label */, displayParts: [ts.displayPart(node_3.text, ts.SymbolDisplayPartKind.text)] }; } case "keyword": { var node_4 = def.node; var name_4 = ts.tokenToString(node_4.kind); - return { node: node_4, name: name_4, kind: "keyword", displayParts: [{ text: name_4, kind: "keyword" }] }; + return { node: node_4, name: name_4, kind: "keyword" /* keyword */, displayParts: [{ text: name_4, kind: "keyword" /* keyword */ }] }; } case "this": { var node_5 = def.node; var symbol = checker.getSymbolAtLocation(node_5); var displayParts_2 = symbol && ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, node_5.getSourceFile(), ts.getContainerNode(node_5), node_5).displayParts || [ts.textPart("this")]; - return { node: node_5, name: "this", kind: "var", displayParts: displayParts_2 }; + return { node: node_5, name: "this", kind: "var" /* variableElement */, displayParts: displayParts_2 }; } case "string": { var node_6 = def.node; - return { node: node_6, name: node_6.text, kind: "var", displayParts: [ts.displayPart(ts.getTextOfNode(node_6), ts.SymbolDisplayPartKind.stringLiteral)] }; + return { node: node_6, name: node_6.text, kind: "var" /* variableElement */, displayParts: [ts.displayPart(ts.getTextOfNode(node_6), ts.SymbolDisplayPartKind.stringLiteral)] }; } default: return ts.Debug.assertNever(def); @@ -78071,7 +93580,7 @@ var ts; })(); var node = info.node, name = info.name, kind = info.kind, displayParts = info.displayParts; var sourceFile = node.getSourceFile(); - return { containerKind: "", containerName: "", fileName: sourceFile.fileName, kind: kind, name: name, textSpan: getTextSpan(ts.isComputedPropertyName(node) ? node.expression : node, sourceFile), displayParts: displayParts }; + return { containerKind: "" /* unknown */, containerName: "", fileName: sourceFile.fileName, kind: kind, name: name, textSpan: getTextSpan(ts.isComputedPropertyName(node) ? node.expression : node, sourceFile), displayParts: displayParts }; } function getDefinitionKindAndDisplayParts(symbol, checker, node) { var meaning = FindAllReferences.Core.getIntersectingMeaningFromDeclarations(node, symbol); @@ -78089,7 +93598,7 @@ var ts; fileName: sourceFile.fileName, textSpan: getTextSpan(node, sourceFile), isWriteAccess: isWriteAccessForReference(node), - isDefinition: node.kind === 79 + isDefinition: node.kind === 79 /* DefaultKeyword */ || ts.isAnyDeclarationName(node) || ts.isLiteralComputedPropertyDeclarationName(node), isInString: isInString, @@ -78103,7 +93612,7 @@ var ts; } else { var textSpan = entry.textSpan, fileName = entry.fileName; - return { textSpan: textSpan, fileName: fileName, kind: "", displayParts: [] }; + return { textSpan: textSpan, fileName: fileName, kind: "" /* unknown */, displayParts: [] }; } } function implementationKindDisplayParts(node, checker) { @@ -78111,16 +93620,16 @@ var ts; if (symbol) { return getDefinitionKindAndDisplayParts(symbol, checker, node); } - else if (node.kind === 184) { + else if (node.kind === 184 /* ObjectLiteralExpression */) { return { - kind: "interface", - displayParts: [ts.punctuationPart(19), ts.textPart("object literal"), ts.punctuationPart(20)] + kind: "interface" /* interfaceElement */, + displayParts: [ts.punctuationPart(19 /* OpenParenToken */), ts.textPart("object literal"), ts.punctuationPart(20 /* CloseParenToken */)] }; } - else if (node.kind === 205) { + else if (node.kind === 205 /* ClassExpression */) { return { - kind: "local class", - displayParts: [ts.punctuationPart(19), ts.textPart("anonymous local class"), ts.punctuationPart(20)] + kind: "local class" /* localClassElement */, + displayParts: [ts.punctuationPart(19 /* OpenParenToken */), ts.textPart("anonymous local class"), ts.punctuationPart(20 /* CloseParenToken */)] }; } else { @@ -78130,14 +93639,14 @@ var ts; function toHighlightSpan(entry) { if (entry.type === "span") { var fileName = entry.fileName, textSpan = entry.textSpan; - return { fileName: fileName, span: { textSpan: textSpan, kind: "reference" } }; + return { fileName: fileName, span: { textSpan: textSpan, kind: "reference" /* reference */ } }; } var node = entry.node, isInString = entry.isInString; var sourceFile = node.getSourceFile(); var writeAccess = isWriteAccessForReference(node); var span = { textSpan: getTextSpan(node, sourceFile), - kind: writeAccess ? "writtenReference" : "reference", + kind: writeAccess ? "writtenReference" /* writtenReference */ : "reference" /* reference */, isInString: isInString }; return { fileName: sourceFile.fileName, span: span }; @@ -78146,28 +93655,32 @@ var ts; function getTextSpan(node, sourceFile) { var start = node.getStart(sourceFile); var end = node.getEnd(); - if (node.kind === 9) { + if (node.kind === 9 /* StringLiteral */) { start += 1; end -= 1; } return ts.createTextSpanFromBounds(start, end); } + /** A node is considered a writeAccess iff it is a name of a declaration or a target of an assignment */ function isWriteAccessForReference(node) { - return node.kind === 79 || ts.isAnyDeclarationName(node) || ts.isWriteAccess(node); + return node.kind === 79 /* DefaultKeyword */ || ts.isAnyDeclarationName(node) || ts.isWriteAccess(node); } })(FindAllReferences = ts.FindAllReferences || (ts.FindAllReferences = {})); })(ts || (ts = {})); +/** Encapsulates the core find-all-references algorithm. */ +/* @internal */ (function (ts) { var FindAllReferences; (function (FindAllReferences) { var Core; (function (Core) { + /** Core find-all-references algorithm. Handles special cases before delegating to `getReferencedSymbolsForSymbol`. */ function getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options, sourceFilesSet) { if (options === void 0) { options = {}; } if (sourceFilesSet === void 0) { sourceFilesSet = ts.arrayToSet(sourceFiles, function (f) { return f.fileName; }); } if (ts.isSourceFile(node)) { var reference = ts.GoToDefinition.getReferenceAtPosition(node, position, program); - return reference && getReferencedSymbolsForModule(program, program.getTypeChecker().getMergedSymbol(reference.file.symbol), false, sourceFiles, sourceFilesSet); + return reference && getReferencedSymbolsForModule(program, program.getTypeChecker().getMergedSymbol(reference.file.symbol), /*excludeImportTypeOfExportEquals*/ false, sourceFiles, sourceFilesSet); } if (!options.implementations) { var special = getReferencedSymbolsSpecial(node, sourceFiles, cancellationToken); @@ -78177,17 +93690,21 @@ var ts; } var checker = program.getTypeChecker(); var symbol = checker.getSymbolAtLocation(node); + // Could not find a symbol e.g. unknown identifier if (!symbol) { + // String literal might be a property (and thus have a symbol), so do this here rather than in getReferencedSymbolsSpecial. return !options.implementations && ts.isStringLiteral(node) ? getReferencesForStringLiteral(node, sourceFiles, cancellationToken) : undefined; } var moduleReferences = ts.emptyArray; var moduleSourceFile = isModuleSymbol(symbol); var referencedNode = node; if (moduleSourceFile) { - var exportEquals = symbol.exports.get("export="); + var exportEquals = symbol.exports.get("export=" /* ExportEquals */); + // If !!exportEquals, we're about to add references to `import("mod")` anyway, so don't double-count them. moduleReferences = getReferencedSymbolsForModule(program, symbol, !!exportEquals, sourceFiles, sourceFilesSet); if (!exportEquals || !sourceFilesSet.has(moduleSourceFile.fileName)) return moduleReferences; + // Continue to get references to 'export ='. symbol = ts.skipAlias(exportEquals, checker); referencedNode = undefined; } @@ -78195,7 +93712,7 @@ var ts; } Core.getReferencedSymbolsForNode = getReferencedSymbolsForNode; function isModuleSymbol(symbol) { - return symbol.flags & 1536 ? ts.find(symbol.declarations, ts.isSourceFile) : undefined; + return symbol.flags & 1536 /* Module */ ? ts.find(symbol.declarations, ts.isSourceFile) : undefined; } function getReferencedSymbolsForModule(program, symbol, excludeImportTypeOfExportEquals, sourceFiles, sourceFilesSet) { ts.Debug.assert(!!symbol.valueDeclaration); @@ -78208,6 +93725,7 @@ var ts; return undefined; } } + // import("foo") with no qualifier will reference the `export =` of the module, which may be referenced anyway. return { type: "node", node: reference.literal }; } else { @@ -78221,54 +93739,66 @@ var ts; for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var decl = _a[_i]; switch (decl.kind) { - case 274: + case 274 /* SourceFile */: + // Don't include the source file itself. (This may not be ideal behavior, but awkward to include an entire file as a reference.) break; - case 239: + case 239 /* ModuleDeclaration */: if (sourceFilesSet.has(decl.getSourceFile().fileName)) { references.push({ type: "node", node: decl.name }); } break; default: + // This may be merged with something. ts.Debug.fail("Expected a module symbol to be declared by a SourceFile or ModuleDeclaration."); } } return references.length ? [{ definition: { type: "symbol", symbol: symbol }, references: references }] : ts.emptyArray; } + /** getReferencedSymbols for special node kinds. */ function getReferencedSymbolsSpecial(node, sourceFiles, cancellationToken) { if (ts.isTypeKeyword(node.kind)) { return getAllReferencesForKeyword(sourceFiles, node.kind, cancellationToken); } + // Labels if (ts.isJumpStatementTarget(node)) { var labelDefinition = ts.getTargetLabel(node.parent, node.text); + // if we have a label definition, look within its statement for references, if not, then + // the label is undefined and we have no results.. return labelDefinition && getLabelReferencesInNode(labelDefinition.parent, labelDefinition); } else if (ts.isLabelOfLabeledStatement(node)) { + // it is a label definition and not a target, search within the parent labeledStatement return getLabelReferencesInNode(node.parent, node); } if (ts.isThis(node)) { return getReferencesForThisKeyword(node, sourceFiles, cancellationToken); } - if (node.kind === 97) { + if (node.kind === 97 /* SuperKeyword */) { return getReferencesForSuperKeyword(node); } return undefined; } + /** Core find-all-references algorithm for a normal symbol. */ function getReferencedSymbolsForSymbol(symbol, node, sourceFiles, sourceFilesSet, checker, cancellationToken, options) { symbol = node && skipPastExportOrImportSpecifierOrUnion(symbol, node, checker) || symbol; - var searchMeaning = node ? getIntersectingMeaningFromDeclarations(node, symbol) : 7; + // Compute the meaning from the location and the symbol it references + var searchMeaning = node ? getIntersectingMeaningFromDeclarations(node, symbol) : 7 /* All */; var result = []; - var state = new State(sourceFiles, sourceFilesSet, node ? getSpecialSearchKind(node) : 0, checker, cancellationToken, searchMeaning, options, result); - if (node && node.kind === 79) { + var state = new State(sourceFiles, sourceFilesSet, node ? getSpecialSearchKind(node) : 0 /* None */, checker, cancellationToken, searchMeaning, options, result); + if (node && node.kind === 79 /* DefaultKeyword */) { addReference(node, symbol, state); - searchForImportsOfExport(node, symbol, { exportingModuleSymbol: ts.Debug.assertDefined(symbol.parent, "Expected export symbol to have a parent"), exportKind: 1 }, state); + searchForImportsOfExport(node, symbol, { exportingModuleSymbol: ts.Debug.assertDefined(symbol.parent, "Expected export symbol to have a parent"), exportKind: 1 /* Default */ }, state); } else { - var search = state.createSearch(node, symbol, undefined, { allSearchSymbols: node ? populateSearchSymbolSet(symbol, node, checker, !!options.implementations) : [symbol] }); + var search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: node ? populateSearchSymbolSet(symbol, node, checker, !!options.implementations) : [symbol] }); + // Try to get the smallest valid scope that we can limit our search to; + // otherwise we'll need to search globally (i.e. include each file). var scope = getSymbolScope(symbol); if (scope) { - getReferencesInContainer(scope, scope.getSourceFile(), search, state, !(ts.isSourceFile(scope) && !ts.contains(sourceFiles, scope))); + getReferencesInContainer(scope, scope.getSourceFile(), search, state, /*addReferencesHere*/ !(ts.isSourceFile(scope) && !ts.contains(sourceFiles, scope))); } else { + // Global search for (var _i = 0, _a = state.sourceFiles; _i < _a.length; _i++) { var sourceFile = _a[_i]; state.cancellationToken.throwIfCancellationRequested(); @@ -78280,27 +93810,32 @@ var ts; } function getSpecialSearchKind(node) { switch (node.kind) { - case 123: - return 1; - case 71: + case 123 /* ConstructorKeyword */: + return 1 /* Constructor */; + case 71 /* Identifier */: if (ts.isClassLike(node.parent)) { ts.Debug.assert(node.parent.name === node); - return 2; + return 2 /* Class */; } + // falls through default: - return 0; + return 0 /* None */; } } + /** Handle a few special cases relating to export/import specifiers. */ function skipPastExportOrImportSpecifierOrUnion(symbol, node, checker) { var parent = node.parent; if (ts.isExportSpecifier(parent)) { return getLocalSymbolForExportSpecifier(node, symbol, parent, checker); } if (ts.isImportSpecifier(parent) && parent.propertyName === node) { + // We're at `foo` in `import { foo as bar }`. Probably intended to find all refs on the original, not just on the import. return checker.getImmediateAliasedSymbol(symbol); } + // If the symbol is declared as part of a declaration like `{ type: "a" } | { type: "b" }`, use the property on the union type to get more references. return ts.firstDefined(symbol.declarations, function (decl) { if (!decl.parent) { + // Assertions for GH#21814. We should be handling SourceFile symbols in `getReferencedSymbolsForModule` instead of getting here. ts.Debug.fail("Unexpected symbol at " + ts.Debug.showSyntaxKind(node) + ": " + ts.Debug.showSymbol(symbol)); } return ts.isTypeLiteralNode(decl.parent) && ts.isUnionTypeNode(decl.parent.parent) @@ -78314,8 +93849,14 @@ var ts; SpecialSearchKind[SpecialSearchKind["Constructor"] = 1] = "Constructor"; SpecialSearchKind[SpecialSearchKind["Class"] = 2] = "Class"; })(SpecialSearchKind || (SpecialSearchKind = {})); - var State = (function () { - function State(sourceFiles, sourceFilesSet, specialSearchKind, checker, cancellationToken, searchMeaning, options, result) { + /** + * Holds all state needed for the finding references. + * Unlike `Search`, there is only one `State`. + */ + var State = /** @class */ (function () { + function State(sourceFiles, sourceFilesSet, + /** True if we're searching for constructor references. */ + specialSearchKind, checker, cancellationToken, searchMeaning, options, result) { this.sourceFiles = sourceFiles; this.sourceFilesSet = sourceFilesSet; this.specialSearchKind = specialSearchKind; @@ -78324,27 +93865,57 @@ var ts; this.searchMeaning = searchMeaning; this.options = options; this.result = result; + /** Cache for `explicitlyinheritsFrom`. */ this.inheritsFromCache = ts.createMap(); + /** + * Type nodes can contain multiple references to the same type. For example: + * let x: Foo & (Foo & Bar) = ... + * Because we are returning the implementation locations and not the identifier locations, + * duplicate entries would be returned here as each of the type references is part of + * the same implementation. For that reason, check before we add a new entry. + */ this.markSeenContainingTypeReference = ts.nodeSeenTracker(); + /** + * It's possible that we will encounter the right side of `export { foo as bar } from "x";` more than once. + * For example: + * // b.ts + * export { foo as bar } from "./a"; + * import { bar } from "./b"; + * + * Normally at `foo as bar` we directly add `foo` and do not locally search for it (since it doesn't declare a local). + * But another reference to it may appear in the same source file. + * See `tests/cases/fourslash/transitiveExportImports3.ts`. + */ this.markSeenReExportRHS = ts.nodeSeenTracker(); this.symbolIdToReferences = []; + // Source file ID → symbol ID → Whether the symbol has been searched for in the source file. this.sourceFileToSeenSymbols = []; } State.prototype.includesSourceFile = function (sourceFile) { return this.sourceFilesSet.has(sourceFile.fileName); }; + /** Gets every place to look for references of an exported symbols. See `ImportsResult` in `importTracker.ts` for more documentation. */ State.prototype.getImportSearches = function (exportSymbol, exportInfo) { if (!this.importTracker) this.importTracker = FindAllReferences.createImportTracker(this.sourceFiles, this.sourceFilesSet, this.checker, this.cancellationToken); return this.importTracker(exportSymbol, exportInfo, !!this.options.isForRename); }; + /** @param allSearchSymbols set of additinal symbols for use by `includes`. */ State.prototype.createSearch = function (location, symbol, comingFrom, searchOptions) { if (searchOptions === void 0) { searchOptions = {}; } + // Note: if this is an external module symbol, the name doesn't include quotes. + // Note: getLocalSymbolForExportDefault handles `export default class C {}`, but not `export default C` or `export { C as default }`. + // The other two forms seem to be handled downstream (e.g. in `skipPastExportOrImportSpecifier`), so special-casing the first form + // here appears to be intentional). var _a = searchOptions.text, text = _a === void 0 ? ts.stripQuotes(ts.unescapeLeadingUnderscores((ts.getLocalSymbolForExportDefault(symbol) || symbol).escapedName)) : _a, _b = searchOptions.allSearchSymbols, allSearchSymbols = _b === void 0 ? [symbol] : _b; var escapedText = ts.escapeLeadingUnderscores(text); var parents = this.options.implementations && location ? getParentSymbolsOfPropertyAccess(location, symbol, this.checker) : undefined; return { symbol: symbol, comingFrom: comingFrom, text: text, escapedText: escapedText, parents: parents, allSearchSymbols: allSearchSymbols, includes: function (sym) { return ts.contains(allSearchSymbols, sym); } }; }; + /** + * Callback to add references for a particular searched symbol. + * This initializes a reference group, so only call this if you will add at least one reference. + */ State.prototype.referenceAdder = function (searchSymbol) { var symbolId = ts.getSymbolId(searchSymbol); var references = this.symbolIdToReferences[symbolId]; @@ -78354,12 +93925,14 @@ var ts; } return function (node) { return references.push(FindAllReferences.nodeEntry(node)); }; }; + /** Add a reference with no associated definition. */ State.prototype.addStringOrCommentReference = function (fileName, textSpan) { this.result.push({ definition: undefined, references: [{ type: "span", fileName: fileName, textSpan: textSpan }] }); }; + /** Returns `true` the first time we search for a symbol in a file and `false` afterwards. */ State.prototype.markSearchedSymbols = function (sourceFile, symbols) { var sourceId = ts.getNodeId(sourceFile); var seenSymbols = this.sourceFileToSeenSymbols[sourceId] || (this.sourceFileToSeenSymbols[sourceId] = ts.createMap()); @@ -78372,8 +93945,10 @@ var ts; }; return State; }()); + /** Search for all imports of a given exported symbol using `State.getImportSearches`. */ function searchForImportsOfExport(exportLocation, exportSymbol, exportInfo, state) { var _a = state.getImportSearches(exportSymbol, exportInfo), importSearches = _a.importSearches, singleReferences = _a.singleReferences, indirectUsers = _a.indirectUsers; + // For `import { foo as bar }` just add the reference to `foo`, and don't otherwise search in the file. if (singleReferences.length) { var addRef = state.referenceAdder(exportSymbol); for (var _i = 0, singleReferences_1 = singleReferences; _i < singleReferences_1.length; _i++) { @@ -78382,20 +93957,22 @@ var ts; addRef(singleRef); } } + // For each import, find all references to that import in its source file. for (var _b = 0, importSearches_1 = importSearches; _b < importSearches_1.length; _b++) { var _c = importSearches_1[_b], importLocation = _c[0], importSymbol = _c[1]; - getReferencesInSourceFile(importLocation.getSourceFile(), state.createSearch(importLocation, importSymbol, 1), state); + getReferencesInSourceFile(importLocation.getSourceFile(), state.createSearch(importLocation, importSymbol, 1 /* Export */), state); } if (indirectUsers.length) { var indirectSearch = void 0; switch (exportInfo.exportKind) { - case 0: - indirectSearch = state.createSearch(exportLocation, exportSymbol, 1); + case 0 /* Named */: + indirectSearch = state.createSearch(exportLocation, exportSymbol, 1 /* Export */); break; - case 1: - indirectSearch = state.options.isForRename ? undefined : state.createSearch(exportLocation, exportSymbol, 1, { text: "default" }); + case 1 /* Default */: + // Search for a property access to '.default'. This can't be renamed. + indirectSearch = state.options.isForRename ? undefined : state.createSearch(exportLocation, exportSymbol, 1 /* Export */, { text: "default" }); break; - case 2: + case 2 /* ExportEquals */: break; } if (indirectSearch) { @@ -78411,17 +93988,22 @@ var ts; return false; if (!state.options.isForRename) return true; + // Don't rename an import type `import("./module-name")` when renaming `name` in `export = name;` if (!ts.isIdentifier(singleRef)) return false; - return !((ts.isExportSpecifier(singleRef.parent) || ts.isImportSpecifier(singleRef.parent)) && singleRef.escapedText === "default"); + // At `default` in `import { default as x }` or `export { default as x }`, do add a reference, but do not rename. + return !((ts.isExportSpecifier(singleRef.parent) || ts.isImportSpecifier(singleRef.parent)) && singleRef.escapedText === "default" /* Default */); } + // Go to the symbol we imported from and find references for it. function searchForImportedSymbol(symbol, state) { for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var declaration = _a[_i]; var exportingFile = declaration.getSourceFile(); - getReferencesInSourceFile(exportingFile, state.createSearch(declaration, symbol, 0), state, state.includesSourceFile(exportingFile)); + // Need to search in the file even if it's not in the search-file set, because it might export the symbol. + getReferencesInSourceFile(exportingFile, state.createSearch(declaration, symbol, 0 /* Import */), state, state.includesSourceFile(exportingFile)); } } + /** Search for all occurences of an identifier in a source file (and filter out the ones that match). */ function searchForName(sourceFile, search, state) { if (ts.getNameTable(sourceFile).get(search.escapedText) !== undefined) { getReferencesInSourceFile(sourceFile, search, state); @@ -78433,9 +94015,9 @@ var ts; : undefined; } function getObjectBindingElementWithoutPropertyName(symbol) { - var bindingElement = ts.getDeclarationOfKind(symbol, 182); + var bindingElement = ts.getDeclarationOfKind(symbol, 182 /* BindingElement */); if (bindingElement && - bindingElement.parent.kind === 180 && + bindingElement.parent.kind === 180 /* ObjectBindingPattern */ && ts.isIdentifier(bindingElement.name) && !bindingElement.propertyName) { return bindingElement; @@ -78445,26 +94027,47 @@ var ts; var bindingElement = getObjectBindingElementWithoutPropertyName(symbol); return bindingElement && ts.getPropertySymbolFromBindingElement(checker, bindingElement); } + /** + * Determines the smallest scope in which a symbol may have named references. + * Note that not every construct has been accounted for. This function can + * probably be improved. + * + * @returns undefined if the scope cannot be determined, implying that + * a reference to a symbol can occur anywhere. + */ function getSymbolScope(symbol) { + // If this is the symbol of a named function expression or named class expression, + // then named references are limited to its own scope. var declarations = symbol.declarations, flags = symbol.flags, parent = symbol.parent, valueDeclaration = symbol.valueDeclaration; - if (valueDeclaration && (valueDeclaration.kind === 192 || valueDeclaration.kind === 205)) { + if (valueDeclaration && (valueDeclaration.kind === 192 /* FunctionExpression */ || valueDeclaration.kind === 205 /* ClassExpression */)) { return valueDeclaration; } if (!declarations) { return undefined; } - if (flags & (4 | 8192)) { - var privateDeclaration = ts.find(declarations, function (d) { return ts.hasModifier(d, 8); }); + // If this is private property or method, the scope is the containing class + if (flags & (4 /* Property */ | 8192 /* Method */)) { + var privateDeclaration = ts.find(declarations, function (d) { return ts.hasModifier(d, 8 /* Private */); }); if (privateDeclaration) { - return ts.getAncestor(privateDeclaration, 235); + return ts.getAncestor(privateDeclaration, 235 /* ClassDeclaration */); } + // Else this is a public property and could be accessed from anywhere. return undefined; } + // If symbol is of object binding pattern element without property name we would want to + // look for property too and that could be anywhere if (getObjectBindingElementWithoutPropertyName(symbol)) { return undefined; } - var exposedByParent = parent && !(symbol.flags & 262144); - if (exposedByParent && !((parent.flags & 1536) && ts.isExternalModuleSymbol(parent) && !parent.globalExports)) { + /* + If the symbol has a parent, it's globally visible unless: + - It's a private property (handled above). + - It's a type parameter. + - The parent is an external module: then we should only search in the module (and recurse on the export later). + - But if the parent has `export as namespace`, the symbol is globally visible through that namespace. + */ + var exposedByParent = parent && !(symbol.flags & 262144 /* TypeParameter */); + if (exposedByParent && !((parent.flags & 1536 /* Module */) && ts.isExternalModuleSymbol(parent) && !parent.globalExports)) { return undefined; } var scope; @@ -78472,15 +94075,25 @@ var ts; var declaration = declarations_10[_i]; var container = ts.getContainerNode(declaration); if (scope && scope !== container) { + // Different declarations have different containers, bail out return undefined; } - if (!container || container.kind === 274 && !ts.isExternalOrCommonJsModule(container)) { + if (!container || container.kind === 274 /* SourceFile */ && !ts.isExternalOrCommonJsModule(container)) { + // This is a global variable and not an external module, any declaration defined + // within this scope is visible outside the file return undefined; } + // The search scope is the container node scope = container; } - return exposedByParent ? scope.getSourceFile() : scope; + // If symbol.parent, this means we are in an export of an external module. (Otherwise we would have returned `undefined` above.) + // For an export of a module, we may be in a declaration file, and it may be accessed elsewhere. E.g.: + // declare module "a" { export type T = number; } + // declare module "b" { import { T } from "a"; export const x: T; } + // So we must search the whole source file. (Because we will mark the source file as seen, we we won't return to it when searching for imports.) + return exposedByParent ? scope.getSourceFile() : scope; // TODO: GH#18217 } + /** Used as a quick check for whether a symbol is used at all in a file (besides its definition). */ function isSymbolReferencedInFile(definition, checker, sourceFile) { return eachSymbolReferenceInFile(definition, checker, sourceFile, function () { return true; }) || false; } @@ -78493,7 +94106,7 @@ var ts; var token = _a[_i]; if (!ts.isIdentifier(token) || token === definition || token.escapedText !== definition.escapedText) continue; - var referenceSymbol = checker.getSymbolAtLocation(token); + var referenceSymbol = checker.getSymbolAtLocation(token); // See GH#19955 for why the type annotation is necessary if (referenceSymbol === symbol || checker.getShorthandAssignmentValueSymbol(token.parent) === symbol || ts.isExportSpecifier(token.parent) && getLocalSymbolForExportSpecifier(token, referenceSymbol, token.parent, checker) === symbol) { @@ -78511,6 +94124,9 @@ var ts; function getPossibleSymbolReferencePositions(sourceFile, symbolName, container) { if (container === void 0) { container = sourceFile; } var positions = []; + /// TODO: Cache symbol existence for files to save text search + // Also, need to make this work for unicode escapes. + // Be resilient in the face of a symbol with no name or zero length name if (!symbolName || !symbolName.length) { return positions; } @@ -78519,11 +94135,15 @@ var ts; var symbolNameLength = symbolName.length; var position = text.indexOf(symbolName, container.pos); while (position >= 0) { + // If we are past the end, stop looking if (position > container.end) break; + // We found a match. Make sure it's not part of a larger word (i.e. the char + // before and after it have to be a non-identifier char). var endPosition = position + symbolNameLength; - if ((position === 0 || !ts.isIdentifierPart(text.charCodeAt(position - 1), 6)) && - (endPosition === sourceLength || !ts.isIdentifierPart(text.charCodeAt(endPosition), 6))) { + if ((position === 0 || !ts.isIdentifierPart(text.charCodeAt(position - 1), 6 /* Latest */)) && + (endPosition === sourceLength || !ts.isIdentifierPart(text.charCodeAt(endPosition), 6 /* Latest */))) { + // Found a real match. Keep searching. positions.push(position); } position = text.indexOf(symbolName, position + symbolNameLength + 1); @@ -78534,22 +94154,24 @@ var ts; var sourceFile = container.getSourceFile(); var labelName = targetLabel.text; var references = ts.mapDefined(getPossibleSymbolReferenceNodes(sourceFile, labelName, container), function (node) { + // Only pick labels that are either the target label, or have a target that is the target label return node === targetLabel || (ts.isJumpStatementTarget(node) && ts.getTargetLabel(node, labelName) === targetLabel) ? FindAllReferences.nodeEntry(node) : undefined; }); return [{ definition: { type: "label", node: targetLabel }, references: references }]; } function isValidReferencePosition(node, searchSymbolName) { + // Compare the length so we filter out strict superstrings of the symbol we are looking for switch (node.kind) { - case 71: + case 71 /* Identifier */: return node.text.length === searchSymbolName.length; - case 9: { + case 9 /* StringLiteral */: { var str = node; return (ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(str) || ts.isNameOfModuleDeclaration(node) || ts.isExpressionOfExternalModuleImportEqualsDeclaration(node)) && str.text.length === searchSymbolName.length; } - case 8: + case 8 /* NumericLiteral */: return ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node) && node.text.length === searchSymbolName.length; - case 79: + case 79 /* DefaultKeyword */: return "default".length === searchSymbolName.length; default: return false; @@ -78569,6 +94191,11 @@ var ts; state.cancellationToken.throwIfCancellationRequested(); return getReferencesInContainer(sourceFile, sourceFile, search, state, addReferencesHere); } + /** + * Search within node "container" for references for a search value, where the search value is defined as a + * tuple of(searchSymbol, searchText, searchLocation, and searchMeaning). + * searchLocation: a node where the search value + */ function getReferencesInContainer(container, sourceFile, search, state, addReferencesHere) { if (!state.markSearchedSymbols(sourceFile, search.allSearchSymbols)) { return; @@ -78584,7 +94211,14 @@ var ts; function getReferencesAtLocation(sourceFile, position, search, state, addReferencesHere) { var referenceLocation = ts.getTouchingPropertyName(sourceFile, position); if (!isValidReferencePosition(referenceLocation, search.text)) { + // This wasn't the start of a token. Check to see if it might be a + // match in a comment or string if that's what the caller is asking + // for. if (!state.options.implementations && (state.options.findInStrings && ts.isInString(sourceFile, position) || state.options.findInComments && ts.isInNonReferenceComment(sourceFile, position))) { + // In the case where we're looking inside comments/strings, we don't have + // an actual definition. So just use 'undefined' here. Features like + // 'Rename' won't care (as they ignore the definitions), and features like + // 'FindReferences' will just filter out these results. state.addStringOrCommentReference(sourceFile.fileName, ts.createTextSpan(position, search.text.length)); } return; @@ -78597,10 +94231,11 @@ var ts; } var parent = referenceLocation.parent; if (ts.isImportSpecifier(parent) && parent.propertyName === referenceLocation) { + // This is added through `singleReferences` in ImportsResult. If we happen to see it again, don't add it again. return; } if (ts.isExportSpecifier(parent)) { - ts.Debug.assert(referenceLocation.kind === 71); + ts.Debug.assert(referenceLocation.kind === 71 /* Identifier */); getReferencesAtExportSpecifier(referenceLocation, referenceSymbol, parent, search, state, addReferencesHere); return; } @@ -78610,14 +94245,14 @@ var ts; return; } switch (state.specialSearchKind) { - case 0: + case 0 /* None */: if (addReferencesHere) addReference(referenceLocation, relatedSymbol, state); break; - case 1: + case 1 /* Constructor */: addConstructorReferences(referenceLocation, sourceFile, search, state); break; - case 2: + case 2 /* Class */: addClassStaticThisReferences(referenceLocation, search, state); break; default: @@ -78633,11 +94268,14 @@ var ts; return; } if (!propertyName) { - if (!(state.options.isForRename && name.escapedText === "default")) { + // Don't rename at `export { default } from "m";`. (but do continue to search for imports of the re-export) + if (!(state.options.isForRename && name.escapedText === "default" /* Default */)) { addRef(); } } else if (referenceLocation === propertyName) { + // For `export { foo as bar } from "baz"`, "`foo`" will be added from the singleReferences for import searches of the original export. + // For `export { foo as bar };`, where `foo` is a local, so add it now. if (!exportDeclaration.moduleSpecifier) { addRef(); } @@ -78650,14 +94288,16 @@ var ts; addRef(); } } + // For `export { foo as bar }`, rename `foo`, but not `bar`. if (!(referenceLocation === propertyName && state.options.isForRename)) { - var exportKind = referenceLocation.originalKeywordKind === 79 ? 1 : 0; + var exportKind = referenceLocation.originalKeywordKind === 79 /* DefaultKeyword */ ? 1 /* Default */ : 0 /* Named */; var exportInfo = FindAllReferences.getExportInfo(referenceSymbol, exportKind, state.checker); if (!exportInfo) return ts.Debug.fail(); searchForImportsOfExport(referenceLocation, referenceSymbol, exportInfo, state); } - if (search.comingFrom !== 1 && exportDeclaration.moduleSpecifier && !propertyName) { + // At `export { x } from "foo"`, also search for the imported symbol `"foo".x`. + if (search.comingFrom !== 1 /* Export */ && exportDeclaration.moduleSpecifier && !propertyName) { var imported = state.checker.getExportSpecifierLocalTargetSymbol(exportSpecifier); if (imported) searchForImportedSymbol(imported, state); @@ -78674,30 +94314,41 @@ var ts; var parent = exportSpecifier.parent, propertyName = exportSpecifier.propertyName, name = exportSpecifier.name; ts.Debug.assert(propertyName === referenceLocation || name === referenceLocation); if (propertyName) { + // Given `export { foo as bar } [from "someModule"]`: It's an alias at `foo`, but at `bar` it's a new symbol. return propertyName === referenceLocation; } else { + // `export { foo } from "foo"` is a re-export. + // `export { foo };` is not a re-export, it creates an alias for the local variable `foo`. return !parent.parent.moduleSpecifier; } } function getImportOrExportReferences(referenceLocation, referenceSymbol, search, state) { - var importOrExport = FindAllReferences.getImportOrExportSymbol(referenceLocation, referenceSymbol, state.checker, search.comingFrom === 1); + var importOrExport = FindAllReferences.getImportOrExportSymbol(referenceLocation, referenceSymbol, state.checker, search.comingFrom === 1 /* Export */); if (!importOrExport) return; var symbol = importOrExport.symbol; - if (importOrExport.kind === 0) { + if (importOrExport.kind === 0 /* Import */) { if (!state.options.isForRename || importOrExport.isNamedImport) { searchForImportedSymbol(symbol, state); } } else { + // We don't check for `state.isForRename`, even for default exports, because importers that previously matched the export name should be updated to continue matching. searchForImportsOfExport(referenceLocation, symbol, importOrExport.exportInfo, state); } } function getReferenceForShorthandProperty(_a, search, state) { var flags = _a.flags, valueDeclaration = _a.valueDeclaration; var shorthandValueSymbol = state.checker.getShorthandAssignmentValueSymbol(valueDeclaration); - if (!(flags & 33554432) && search.includes(shorthandValueSymbol)) { + /* + * Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment + * has two meanings: property name and property value. Therefore when we do findAllReference at the position where + * an identifier is declared, the language service should return the position of the variable declaration as well as + * the position in short-hand property assignment excluding property accessing. However, if we do findAllReference at the + * position of property accessing, the referenceEntry of such position will be handled in the first case. + */ + if (!(flags & 33554432 /* Transient */) && search.includes(shorthandValueSymbol)) { addReference(ts.getNameOfDeclaration(valueDeclaration), shorthandValueSymbol, state); } } @@ -78710,16 +94361,19 @@ var ts; addRef(referenceLocation); } } + /** Adds references when a constructor is used with `new this()` in its own class and `super()` calls in subclasses. */ function addConstructorReferences(referenceLocation, sourceFile, search, state) { if (ts.isNewExpressionTarget(referenceLocation)) { addReference(referenceLocation, search.symbol, state); } var pusher = function () { return state.referenceAdder(search.symbol); }; if (ts.isClassLike(referenceLocation.parent)) { - ts.Debug.assert(referenceLocation.kind === 79 || referenceLocation.parent.name === referenceLocation); + ts.Debug.assert(referenceLocation.kind === 79 /* DefaultKeyword */ || referenceLocation.parent.name === referenceLocation); + // This is the class declaration containing the constructor. findOwnConstructorReferences(search.symbol, sourceFile, pusher()); } else { + // If this class appears in `extends C`, then the extending class' "super" calls are references. var classExtending = tryGetClassByExtendingIdentifier(referenceLocation); if (classExtending) { findSuperConstructorAccesses(classExtending, pusher()); @@ -78735,12 +94389,12 @@ var ts; var addRef = state.referenceAdder(search.symbol); for (var _i = 0, _a = classLike.members; _i < _a.length; _i++) { var member = _a[_i]; - if (!(ts.isMethodOrAccessor(member) && ts.hasModifier(member, 32))) { + if (!(ts.isMethodOrAccessor(member) && ts.hasModifier(member, 32 /* Static */))) { continue; } if (member.body) { member.body.forEachChild(function cb(node) { - if (node.kind === 99) { + if (node.kind === 99 /* ThisKeyword */) { addRef(node); } else if (!ts.isFunctionLike(node) && !ts.isClassLike(node)) { @@ -78750,19 +94404,23 @@ var ts; } } } + /** + * `classSymbol` is the class where the constructor was defined. + * Reference the constructor and all calls to `new this()`. + */ function findOwnConstructorReferences(classSymbol, sourceFile, addNode) { - for (var _i = 0, _a = classSymbol.members.get("__constructor").declarations; _i < _a.length; _i++) { + for (var _i = 0, _a = classSymbol.members.get("__constructor" /* Constructor */).declarations; _i < _a.length; _i++) { var decl = _a[_i]; - var ctrKeyword = ts.findChildOfKind(decl, 123, sourceFile); - ts.Debug.assert(decl.kind === 155 && !!ctrKeyword); + var ctrKeyword = ts.findChildOfKind(decl, 123 /* ConstructorKeyword */, sourceFile); + ts.Debug.assert(decl.kind === 155 /* Constructor */ && !!ctrKeyword); addNode(ctrKeyword); } classSymbol.exports.forEach(function (member) { var decl = member.valueDeclaration; - if (decl && decl.kind === 154) { + if (decl && decl.kind === 154 /* MethodDeclaration */) { var body = decl.body; if (body) { - forEachDescendantOfKind(body, 99, function (thisKeyword) { + forEachDescendantOfKind(body, 99 /* ThisKeyword */, function (thisKeyword) { if (ts.isNewExpressionTarget(thisKeyword)) { addNode(thisKeyword); } @@ -78771,17 +94429,18 @@ var ts; } }); } + /** Find references to `super` in the constructor of an extending class. */ function findSuperConstructorAccesses(cls, addNode) { - var ctr = cls.symbol.members.get("__constructor"); + var ctr = cls.symbol.members.get("__constructor" /* Constructor */); if (!ctr) { return; } for (var _i = 0, _a = ctr.declarations; _i < _a.length; _i++) { var decl = _a[_i]; - ts.Debug.assert(decl.kind === 155); + ts.Debug.assert(decl.kind === 155 /* Constructor */); var body = decl.body; if (body) { - forEachDescendantOfKind(body, 97, function (node) { + forEachDescendantOfKind(body, 97 /* SuperKeyword */, function (node) { if (ts.isCallExpressionTarget(node)) { addNode(node); } @@ -78790,21 +94449,26 @@ var ts; } } function addImplementationReferences(refNode, addReference, state) { + // Check if we found a function/propertyAssignment/method with an implementation or initializer if (ts.isDeclarationName(refNode) && isImplementation(refNode.parent)) { addReference(refNode); return; } - if (refNode.kind !== 71) { + if (refNode.kind !== 71 /* Identifier */) { return; } - if (refNode.parent.kind === 271) { + if (refNode.parent.kind === 271 /* ShorthandPropertyAssignment */) { + // Go ahead and dereference the shorthand assignment by going to its definition getReferenceEntriesForShorthandPropertyAssignment(refNode, state.checker, addReference); } + // Check if the node is within an extends or implements clause var containingClass = getContainingClassIfInHeritageClause(refNode); if (containingClass) { addReference(containingClass); return; } + // If we got a type reference, try and see if the reference applies to any expressions that can implement an interface + // Find the first node whose parent isn't a type node -- i.e., the highest type node. var typeNode = ts.findAncestor(refNode, function (a) { return !ts.isQualifiedName(a.parent) && !ts.isTypeNode(a.parent) && !ts.isTypeElement(a.parent); }); var typeHavingNode = typeNode.parent; if (ts.hasType(typeHavingNode) && typeHavingNode.type === typeNode && state.markSeenContainingTypeReference(typeHavingNode)) { @@ -78813,7 +94477,7 @@ var ts; } else if (ts.isFunctionLike(typeHavingNode) && typeHavingNode.body) { var body = typeHavingNode.body; - if (body.kind === 213) { + if (body.kind === 213 /* Block */) { ts.forEachReturnStatement(body, function (returnStatement) { if (returnStatement.expression) addIfImplementation(returnStatement.expression); @@ -78836,20 +94500,42 @@ var ts; return ts.isIdentifier(node) || ts.isPropertyAccessExpression(node) ? getContainingClassIfInHeritageClause(node.parent) : ts.isExpressionWithTypeArguments(node) ? ts.tryCast(node.parent.parent, ts.isClassLike) : undefined; } + /** + * Returns true if this is an expression that can be considered an implementation + */ function isImplementationExpression(node) { switch (node.kind) { - case 191: + case 191 /* ParenthesizedExpression */: return isImplementationExpression(node.expression); - case 193: - case 192: - case 184: - case 205: - case 183: + case 193 /* ArrowFunction */: + case 192 /* FunctionExpression */: + case 184 /* ObjectLiteralExpression */: + case 205 /* ClassExpression */: + case 183 /* ArrayLiteralExpression */: return true; default: return false; } } + /** + * Determines if the parent symbol occurs somewhere in the child's ancestry. If the parent symbol + * is an interface, determines if some ancestor of the child symbol extends or inherits from it. + * Also takes in a cache of previous results which makes this slightly more efficient and is + * necessary to avoid potential loops like so: + * class A extends B { } + * class B extends A { } + * + * We traverse the AST rather than using the type checker because users are typically only interested + * in explicit implementations of an interface/class when calling "Go to Implementation". Sibling + * implementations of types that share a common ancestor with the type whose implementation we are + * searching for need to be filtered out of the results. The type checker doesn't let us make the + * distinction between structurally compatible implementations and explicit implementations, so we + * must use the AST. + * + * @param symbol A class or interface Symbol + * @param parent Another class or interface Symbol + * @param cachedResults A map of symbol id pairs (i.e. "child,parent") to booleans indicating previous results + */ function explicitlyInheritsFrom(symbol, parent, cachedResults, checker) { if (symbol === parent) { return true; @@ -78859,6 +94545,7 @@ var ts; if (cached !== undefined) { return cached; } + // Set the key so that we don't infinitely recurse cachedResults.set(key, false); var inherits = symbol.declarations.some(function (declaration) { return ts.getAllSuperTypeNodes(declaration).some(function (typeReference) { @@ -78870,81 +94557,92 @@ var ts; return inherits; } function getReferencesForSuperKeyword(superKeyword) { - var searchSpaceNode = ts.getSuperContainer(superKeyword, false); + var searchSpaceNode = ts.getSuperContainer(superKeyword, /*stopOnFunctions*/ false); if (!searchSpaceNode) { return undefined; } - var staticFlag = 32; + // Whether 'super' occurs in a static context within a class. + var staticFlag = 32 /* Static */; switch (searchSpaceNode.kind) { - case 152: - case 151: - case 154: - case 153: - case 155: - case 156: - case 157: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: staticFlag &= ts.getModifierFlags(searchSpaceNode); - searchSpaceNode = searchSpaceNode.parent; + searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class break; default: return undefined; } var sourceFile = searchSpaceNode.getSourceFile(); var references = ts.mapDefined(getPossibleSymbolReferenceNodes(sourceFile, "super", searchSpaceNode), function (node) { - if (node.kind !== 97) { + if (node.kind !== 97 /* SuperKeyword */) { return; } - var container = ts.getSuperContainer(node, false); - return container && (32 & ts.getModifierFlags(container)) === staticFlag && container.parent.symbol === searchSpaceNode.symbol ? FindAllReferences.nodeEntry(node) : undefined; + var container = ts.getSuperContainer(node, /*stopOnFunctions*/ false); + // If we have a 'super' container, we must have an enclosing class. + // Now make sure the owning class is the same as the search-space + // and has the same static qualifier as the original 'super's owner. + return container && (32 /* Static */ & ts.getModifierFlags(container)) === staticFlag && container.parent.symbol === searchSpaceNode.symbol ? FindAllReferences.nodeEntry(node) : undefined; }); return [{ definition: { type: "symbol", symbol: searchSpaceNode.symbol }, references: references }]; } function getReferencesForThisKeyword(thisOrSuperKeyword, sourceFiles, cancellationToken) { - var searchSpaceNode = ts.getThisContainer(thisOrSuperKeyword, false); - var staticFlag = 32; + var searchSpaceNode = ts.getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false); + // Whether 'this' occurs in a static context within a class. + var staticFlag = 32 /* Static */; switch (searchSpaceNode.kind) { - case 154: - case 153: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: if (ts.isObjectLiteralMethod(searchSpaceNode)) { break; } - case 152: - case 151: - case 155: - case 156: - case 157: + // falls through + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: staticFlag &= ts.getModifierFlags(searchSpaceNode); - searchSpaceNode = searchSpaceNode.parent; + searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class break; - case 274: + case 274 /* SourceFile */: if (ts.isExternalModule(searchSpaceNode)) { return undefined; } - case 234: - case 192: + // falls through + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: break; + // Computed properties in classes are not handled here because references to this are illegal, + // so there is no point finding references to them. default: return undefined; } - var references = ts.flatMap(searchSpaceNode.kind === 274 ? sourceFiles : [searchSpaceNode.getSourceFile()], function (sourceFile) { + var references = ts.flatMap(searchSpaceNode.kind === 274 /* SourceFile */ ? sourceFiles : [searchSpaceNode.getSourceFile()], function (sourceFile) { cancellationToken.throwIfCancellationRequested(); return getPossibleSymbolReferenceNodes(sourceFile, "this", ts.isSourceFile(searchSpaceNode) ? sourceFile : searchSpaceNode).filter(function (node) { if (!ts.isThis(node)) { return false; } - var container = ts.getThisContainer(node, false); + var container = ts.getThisContainer(node, /* includeArrowFunctions */ false); switch (searchSpaceNode.kind) { - case 192: - case 234: + case 192 /* FunctionExpression */: + case 234 /* FunctionDeclaration */: return searchSpaceNode.symbol === container.symbol; - case 154: - case 153: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: return ts.isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol; - case 205: - case 235: - return container.parent && searchSpaceNode.symbol === container.parent.symbol && (ts.getModifierFlags(container) & 32) === staticFlag; - case 274: - return container.kind === 274 && !ts.isExternalModule(container); + case 205 /* ClassExpression */: + case 235 /* ClassDeclaration */: + // Make sure the container belongs to the same class + // and has the appropriate static modifier from the original container. + return container.parent && searchSpaceNode.symbol === container.parent.symbol && (ts.getModifierFlags(container) & 32 /* Static */) === staticFlag; + case 274 /* SourceFile */: + return container.kind === 274 /* SourceFile */ && !ts.isExternalModule(container); } }); }).map(function (n) { return FindAllReferences.nodeEntry(n); }); @@ -78957,7 +94655,7 @@ var ts; var references = ts.flatMap(sourceFiles, function (sourceFile) { cancellationToken.throwIfCancellationRequested(); return ts.mapDefined(getPossibleSymbolReferenceNodes(sourceFile, node.text), function (ref) { - return ts.isStringLiteral(ref) && ref.text === node.text ? FindAllReferences.nodeEntry(ref, true) : undefined; + return ts.isStringLiteral(ref) && ref.text === node.text ? FindAllReferences.nodeEntry(ref, /*isInString*/ true) : undefined; }); }); return [{ @@ -78965,21 +94663,41 @@ var ts; references: references }]; } + // For certain symbol kinds, we need to include other symbols in the search set. + // This is not needed when searching for re-exports. function populateSearchSymbolSet(symbol, location, checker, implementations) { var result = []; - forEachRelatedSymbol(symbol, location, checker, function (sym, root, base) { result.push(base || root || sym); }, function () { return !implementations; }); + forEachRelatedSymbol(symbol, location, checker, function (sym, root, base) { result.push(base || root || sym); }, + /*allowBaseTypes*/ function () { return !implementations; }); return result; } function forEachRelatedSymbol(symbol, location, checker, cbSymbol, allowBaseTypes) { var containingObjectLiteralElement = ts.getContainingObjectLiteralElement(location); if (containingObjectLiteralElement) { + // If the location is in a context sensitive location (i.e. in an object literal) try + // to get a contextual type for it, and add the property symbol from the contextual + // type to the search set var res_1 = ts.firstDefined(getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker), fromRoot); if (res_1) return res_1; + // If the location is name of property symbol from object literal destructuring pattern + // Search the property symbol + // for ( { property: p2 } of elems) { } var propertySymbol = getPropertySymbolOfDestructuringAssignment(location, checker); var res1 = propertySymbol && cbSymbol(propertySymbol); if (res1) return res1; + /* Because in short-hand property assignment, location has two meaning : property name and as value of the property + * When we do findAllReference at the position of the short-hand property assignment, we would want to have references to position of + * property name and variable declaration of the identifier. + * Like in below example, when querying for all references for an identifier 'name', of the property assignment, the language service + * should show both 'name' in 'obj' and 'name' in variable declaration + * const name = "Foo"; + * const obj = { name }; + * In order to do that, we will populate the search set with the value symbol of the identifier as a value of the property assignment + * so that when matching with potential reference symbol, both symbols from property declaration and variable declaration + * will be included correctly. + */ var shorthandValueSymbol = checker.getShorthandAssignmentValueSymbol(location.parent); var res2 = shorthandValueSymbol && cbSymbol(shorthandValueSymbol); if (res2) @@ -78989,16 +94707,26 @@ var ts; if (res) return res; if (symbol.valueDeclaration && ts.isParameterPropertyDeclaration(symbol.valueDeclaration)) { + // For a parameter property, now try on the other symbol (property if this was a parameter, parameter if this was a property). var paramProps = checker.getSymbolsOfParameterPropertyDeclaration(ts.cast(symbol.valueDeclaration, ts.isParameter), symbol.name); - ts.Debug.assert(paramProps.length === 2 && !!(paramProps[0].flags & 1) && !!(paramProps[1].flags & 4)); - return fromRoot(symbol.flags & 1 ? paramProps[1] : paramProps[0]); + ts.Debug.assert(paramProps.length === 2 && !!(paramProps[0].flags & 1 /* FunctionScopedVariable */) && !!(paramProps[1].flags & 4 /* Property */)); // is [parameter, property] + return fromRoot(symbol.flags & 1 /* FunctionScopedVariable */ ? paramProps[1] : paramProps[0]); } + // If this is symbol of binding element without propertyName declaration in Object binding pattern + // Include the property in the search var bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol, checker); return bindingElementPropertySymbol && fromRoot(bindingElementPropertySymbol); function fromRoot(sym) { + // If this is a union property: + // - In populateSearchSymbolsSet we will add all the symbols from all its source symbols in all unioned types. + // - In findRelatedSymbol, we will just use the union symbol if any source symbol is included in the search. + // If the symbol is an instantiation from a another symbol (e.g. widened symbol): + // - In populateSearchSymbolsSet, add the root the list + // - In findRelatedSymbol, return the source symbol if that is in the search. (Do not return the instantiation symbol.) return ts.firstDefined(checker.getRootSymbols(sym), function (rootSymbol) { return cbSymbol(sym, rootSymbol) - || (rootSymbol.parent && rootSymbol.parent.flags & (32 | 64) && allowBaseTypes(rootSymbol) + // Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions + || (rootSymbol.parent && rootSymbol.parent.flags & (32 /* Class */ | 64 /* Interface */) && allowBaseTypes(rootSymbol) ? ts.getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, checker, function (base) { return cbSymbol(sym, rootSymbol, base); }) : undefined); }); @@ -79007,24 +94735,40 @@ var ts; function getRelatedSymbol(search, referenceSymbol, referenceLocation, state) { var checker = state.checker; return forEachRelatedSymbol(referenceSymbol, referenceLocation, checker, function (sym, rootSymbol, baseSymbol) { return search.includes(baseSymbol || rootSymbol || sym) - ? rootSymbol && !(ts.getCheckFlags(sym) & 6) ? rootSymbol : sym - : undefined; }, function (rootSymbol) { + // For a base type, use the symbol for the derived type. For a synthetic (e.g. union) property, use the union symbol. + ? rootSymbol && !(ts.getCheckFlags(sym) & 6 /* Synthetic */) ? rootSymbol : sym + : undefined; }, + /*allowBaseTypes*/ function (rootSymbol) { return !(search.parents && !search.parents.some(function (parent) { return explicitlyInheritsFrom(rootSymbol.parent, parent, state.inheritsFromCache, checker); })); }); } + /** Gets all symbols for one property. Does not get symbols for every property. */ function getPropertySymbolsFromContextualType(node, checker) { var contextualType = checker.getContextualType(node.parent); var name = ts.getNameFromPropertyName(node.name); var symbol = contextualType && name && contextualType.getProperty(name); return symbol ? [symbol] : - contextualType && contextualType.isUnion() ? ts.mapDefined(contextualType.types, function (t) { return t.getProperty(name); }) : ts.emptyArray; + contextualType && contextualType.isUnion() ? ts.mapDefined(contextualType.types, function (t) { return t.getProperty(name); }) : ts.emptyArray; // TODO: GH#18217 } + /** + * Given an initial searchMeaning, extracted from a location, widen the search scope based on the declarations + * of the corresponding symbol. e.g. if we are searching for "Foo" in value position, but "Foo" references a class + * then we need to widen the search to include type positions as well. + * On the contrary, if we are searching for "Bar" in type position and we trace bar to an interface, and an uninstantiated + * module, we want to keep the search limited to only types, as the two declarations (interface and uninstantiated module) + * do not intersect in any of the three spaces. + */ function getIntersectingMeaningFromDeclarations(node, symbol) { var meaning = ts.getMeaningFromLocation(node); var declarations = symbol.declarations; if (declarations) { var lastIterationMeaning = void 0; do { + // The result is order-sensitive, for instance if initialMeaning === Namespace, and declarations = [class, instantiated module] + // we need to consider both as they initialMeaning intersects with the module in the namespace space, and the module + // intersects with the class in the value space. + // To achieve that we will keep iterating until the result stabilizes. + // Remember the last meaning lastIterationMeaning = meaning; for (var _i = 0, declarations_11 = declarations; _i < declarations_11.length; _i++) { var declaration = declarations_11[_i]; @@ -79039,7 +94783,7 @@ var ts; } Core.getIntersectingMeaningFromDeclarations = getIntersectingMeaningFromDeclarations; function isImplementation(node) { - return !!(node.flags & 4194304) + return !!(node.flags & 4194304 /* Ambient */) || (ts.isVariableLike(node) ? ts.hasInitializer(node) : ts.isFunctionLikeDeclaration(node) ? !!node.body : ts.isClassLike(node) || ts.isModuleOrEnumDeclaration(node)); @@ -79050,7 +94794,7 @@ var ts; if (shorthandSymbol) { for (var _i = 0, _a = shorthandSymbol.getDeclarations(); _i < _a.length; _i++) { var declaration = _a[_i]; - if (ts.getMeaningFromDeclaration(declaration) & 1) { + if (ts.getMeaningFromDeclaration(declaration) & 1 /* Value */) { addReference(declaration); } } @@ -79065,20 +94809,28 @@ var ts; forEachDescendantOfKind(child, kind, action); }); } + /** Get `C` given `N` if `N` is in the position `class C extends N` or `class C extends foo.N` where `N` is an identifier. */ function tryGetClassByExtendingIdentifier(node) { return ts.tryGetClassExtendingExpressionWithTypeArguments(ts.climbPastPropertyAccess(node).parent); } + /** + * If we are just looking for implementations and this is a property access expression, we need to get the + * symbol of the local type of the symbol the property is being accessed on. This is because our search + * symbol may have a different parent symbol if the local type's symbol does not declare the property + * being accessed (i.e. it is declared in some parent class or interface) + */ function getParentSymbolsOfPropertyAccess(location, symbol, checker) { var propertyAccessExpression = ts.isRightSideOfPropertyAccess(location) ? location.parent : undefined; var lhsType = propertyAccessExpression && checker.getTypeAtLocation(propertyAccessExpression.expression); var res = ts.mapDefined(lhsType && (lhsType.isUnionOrIntersection() ? lhsType.types : lhsType.symbol === symbol.parent ? undefined : [lhsType]), function (t) { - return t.symbol && t.symbol.flags & (32 | 64) ? t.symbol : undefined; + return t.symbol && t.symbol.flags & (32 /* Class */ | 64 /* Interface */) ? t.symbol : undefined; }); return res.length === 0 ? undefined : res; } })(Core = FindAllReferences.Core || (FindAllReferences.Core = {})); })(FindAllReferences = ts.FindAllReferences || (ts.FindAllReferences = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { function getEditsForFileRename(program, oldFileOrDirPath, newFileOrDirPath, host, formatContext, preferences) { @@ -79118,7 +94870,8 @@ var ts; var foundExactMatch = updatePaths(property); if (!foundExactMatch && propertyName === "include" && ts.isArrayLiteralExpression(property.initializer)) { var includes = ts.mapDefined(property.initializer.elements, function (e) { return ts.isStringLiteral(e) ? e.text : undefined; }); - var matchers = ts.getFileMatcherPatterns(configDir, [], includes, useCaseSensitiveFileNames, currentDirectory); + var matchers = ts.getFileMatcherPatterns(configDir, /*excludes*/ [], includes, useCaseSensitiveFileNames, currentDirectory); + // If there isn't some include for this, add a new one. if (!ts.getRegexFromPattern(ts.Debug.assertDefined(matchers.includeFilePattern), useCaseSensitiveFileNames).test(newFileOrDirPath)) { changeTracker.insertNodeAfter(configFile, ts.last(property.initializer.elements), ts.createStringLiteral(relativePath(newFileOrDirPath))); } @@ -79146,6 +94899,7 @@ var ts; } }); function updatePaths(property) { + // Type annotation needed due to #7294 var elements = ts.isArrayLiteralExpression(property.initializer) ? property.initializer.elements : [property.initializer]; var foundExactMatch = false; for (var _i = 0, elements_5 = elements; _i < elements_5.length; _i++) { @@ -79166,7 +94920,7 @@ var ts; return false; } function relativePath(path) { - return ts.getRelativePathFromDirectory(configDir, path, !useCaseSensitiveFileNames); + return ts.getRelativePathFromDirectory(configDir, path, /*ignoreCase*/ !useCaseSensitiveFileNames); } } function updateImports(program, changeTracker, oldToNew, newToOld, host, getCanonicalFileName, preferences) { @@ -79186,8 +94940,11 @@ var ts; return newAbsolute === undefined ? undefined : ts.ensurePathIsNonModuleName(ts.getRelativePathFromDirectory(newImportFromDirectory, newAbsolute, getCanonicalFileName)); }, function (importLiteral) { var toImport = oldFromNew !== undefined + // If we're at the new location (file was already renamed), need to redo module resolution starting from the old location. + // TODO:GH#18217 ? getSourceFileToImportFromResolved(ts.resolveModuleName(importLiteral.text, oldImportFromPath, program.getCompilerOptions(), host), oldToNew, program) : getSourceFileToImport(importLiteral, sourceFile, program, host, oldToNew); + // If neither the importing source file nor the imported file moved, do nothing. return toImport === undefined || !toImport.updated && !importingSourceFileMoved ? undefined : ts.moduleSpecifiers.getModuleSpecifier(program.getCompilerOptions(), sourceFile, newImportFromPath, toImport.newFileName, host, preferences); @@ -79208,7 +94965,7 @@ var ts; var symbol = program.getTypeChecker().getSymbolAtLocation(importLiteral); if (symbol) { if (symbol.declarations.some(function (d) { return ts.isAmbientModule(d); })) - return undefined; + return undefined; // No need to update if it's an ambient module var oldFileName = ts.find(symbol.declarations, ts.isSourceFile).fileName; var newFileName = oldToNew(oldFileName); return newFileName === undefined ? { newFileName: oldFileName, updated: false } : { newFileName: newFileName, updated: true }; @@ -79257,6 +95014,7 @@ var ts; } } })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var GoToDefinition; @@ -79271,31 +95029,54 @@ var ts; return undefined; } var parent = node.parent; + // Labels if (ts.isJumpStatementTarget(node)) { var label = ts.getTargetLabel(node.parent, node.text); - return label ? [createDefinitionInfoFromName(label, "label", node.text, undefined)] : undefined; + return label ? [createDefinitionInfoFromName(label, "label" /* label */, node.text, /*containerName*/ undefined)] : undefined; // TODO: GH#18217 } var typeChecker = program.getTypeChecker(); var symbol = getSymbol(node, typeChecker); + // Could not find a symbol e.g. node is string or number keyword, + // or the symbol was an internal symbol and does not have a declaration e.g. undefined symbol if (!symbol) { return getDefinitionInfoForIndexSignatures(node, typeChecker); } var calledDeclaration = tryGetSignatureDeclaration(typeChecker, node); if (calledDeclaration) { var sigInfo = createDefinitionFromSignatureDeclaration(typeChecker, calledDeclaration); + // For a function, if this is the original function definition, return just sigInfo. + // If this is the original constructor definition, parent is the class. if (typeChecker.getRootSymbols(symbol).some(function (s) { return symbolMatchesSignature(s, calledDeclaration); }) || - symbol.declarations.some(function (d) { return ts.isVariableDeclaration(d) && !!d.initializer && ts.isRequireCall(d.initializer, false); })) { + // TODO: GH#23742 Following check shouldn't be necessary if 'require' is an alias + symbol.declarations.some(function (d) { return ts.isVariableDeclaration(d) && !!d.initializer && ts.isRequireCall(d.initializer, /*checkArgumentIsStringLiteralLike*/ false); })) { return [sigInfo]; } else { var defs = getDefinitionFromSymbol(typeChecker, symbol, node); - return node.kind === 97 ? [sigInfo].concat(defs) : defs.concat([sigInfo]); + // For a 'super()' call, put the signature first, else put the variable first. + return node.kind === 97 /* SuperKeyword */ ? [sigInfo].concat(defs) : defs.concat([sigInfo]); } } - if (node.parent.kind === 271) { + // Because name in short-hand property assignment has two different meanings: property name and property value, + // using go-to-definition at such position should go to the variable declaration of the property value rather than + // go to the declaration of the property name (in this case stay at the same position). However, if go-to-definition + // is performed at the location of property access, we would like to go to definition of the property in the short-hand + // assignment. This case and others are handled by the following code. + if (node.parent.kind === 271 /* ShorthandPropertyAssignment */) { var shorthandSymbol_1 = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); return shorthandSymbol_1 ? shorthandSymbol_1.declarations.map(function (decl) { return createDefinitionInfo(decl, typeChecker, shorthandSymbol_1, node); }) : []; } + // If the node is the name of a BindingElement within an ObjectBindingPattern instead of just returning the + // declaration the symbol (which is itself), we should try to get to the original type of the ObjectBindingPattern + // and return the property declaration for the referenced property. + // For example: + // import('./foo').then(({ b/*goto*/ar }) => undefined); => should get use to the declaration in file "./foo" + // + // function bar(onfulfilled: (value: T) => void) { //....} + // interface Test { + // pr/*destination*/op1: number + // } + // bar(({pr/*goto*/op1})=>{}); if (ts.isPropertyName(node) && ts.isBindingElement(parent) && ts.isObjectBindingPattern(parent.parent) && (node === (parent.propertyName || parent.name))) { var type = typeChecker.getTypeAtLocation(parent.parent); @@ -79306,6 +95087,15 @@ var ts; } } } + // If the current location we want to find its definition is in an object literal, try to get the contextual type for the + // object literal, lookup the property symbol in the contextual type, and use this for goto-definition. + // For example + // interface Props{ + // /*first*/prop1: number + // prop2: boolean + // } + // function Foo(arg: Props) {} + // Foo( { pr/*1*/op1: 10, prop2: true }) var element = ts.getContainingObjectLiteralElement(node); if (element && typeChecker.getContextualType(element.parent)) { return ts.flatMap(ts.getPropertySymbolsFromContextualType(typeChecker, element), function (propertySymbol) { @@ -79315,6 +95105,10 @@ var ts; return getDefinitionFromSymbol(typeChecker, symbol, node); } GoToDefinition.getDefinitionAtPosition = getDefinitionAtPosition; + /** + * True if we should not add definitions for both the signature symbol and the definition symbol. + * True for `const |f = |() => 0`, false for `function |f() {} const |g = f;`. + */ function symbolMatchesSignature(s, calledDeclaration) { return s === calledDeclaration.symbol || s === calledDeclaration.symbol.parent || ts.isVariableDeclaration(calledDeclaration.parent) && s === calledDeclaration.parent.symbol; @@ -79328,7 +95122,7 @@ var ts; var typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position); if (typeReferenceDirective) { var reference = program.getResolvedTypeReferenceDirectives().get(typeReferenceDirective.fileName); - var file = reference && program.getSourceFile(reference.resolvedFileName); + var file = reference && program.getSourceFile(reference.resolvedFileName); // TODO:GH#18217 return file && { fileName: typeReferenceDirective.fileName, file: file }; } var libReferenceDirective = findReferenceInPosition(sourceFile.libReferenceDirectives, position); @@ -79339,6 +95133,7 @@ var ts; return undefined; } GoToDefinition.getReferenceAtPosition = getReferenceAtPosition; + /// Goto type function getTypeDefinitionAtPosition(typeChecker, sourceFile, position) { var node = ts.getTouchingPropertyName(sourceFile, position); if (node === sourceFile) { @@ -79349,7 +95144,7 @@ var ts; if (!type) { return undefined; } - if (type.isUnion() && !(type.flags & 32)) { + if (type.isUnion() && !(type.flags & 32 /* Enum */)) { return ts.flatMap(type.types, function (t) { return t.symbol && getDefinitionFromSymbol(typeChecker, t.symbol, node); }); } return type.symbol && getDefinitionFromSymbol(typeChecker, type.symbol, node); @@ -79360,6 +95155,7 @@ var ts; if (!definitions || definitions.length === 0) { return undefined; } + // Check if position is on triple slash reference. var comment = findReferenceInPosition(sourceFile.referencedFiles, position) || findReferenceInPosition(sourceFile.typeReferenceDirectives, position) || findReferenceInPosition(sourceFile.libReferenceDirectives, position); @@ -79371,18 +95167,23 @@ var ts; return { definitions: definitions, textSpan: textSpan }; } GoToDefinition.getDefinitionAndBoundSpan = getDefinitionAndBoundSpan; + // At 'x.foo', see if the type of 'x' has an index signature, and if so find its declarations. function getDefinitionInfoForIndexSignatures(node, checker) { if (!ts.isPropertyAccessExpression(node.parent) || node.parent.name !== node) return; var type = checker.getTypeAtLocation(node.parent.expression); return ts.mapDefined(type.isUnionOrIntersection() ? type.types : [type], function (nonUnionType) { - var info = checker.getIndexInfoOfType(nonUnionType, 0); + var info = checker.getIndexInfoOfType(nonUnionType, 0 /* String */); return info && info.declaration && createDefinitionFromSignatureDeclaration(checker, info.declaration); }); } function getSymbol(node, checker) { var symbol = checker.getSymbolAtLocation(node); - if (symbol && symbol.flags & 2097152 && shouldSkipAlias(node, symbol.declarations[0])) { + // If this is an alias, and the request came at the declaration location + // get the aliased symbol instead. This allows for goto def on an import e.g. + // import {A, B} from "mod"; + // to jump to the implementation directly. + if (symbol && symbol.flags & 2097152 /* Alias */ && shouldSkipAlias(node, symbol.declarations[0])) { var aliased = checker.getAliasedSymbol(symbol); if (aliased.declarations) { return aliased; @@ -79390,19 +95191,24 @@ var ts; } return symbol; } + // Go to the original declaration for cases: + // + // (1) when the aliased symbol was declared in the location(parent). + // (2) when the aliased symbol is originating from an import. + // function shouldSkipAlias(node, declaration) { - if (node.kind !== 71) { + if (node.kind !== 71 /* Identifier */) { return false; } if (node.parent === declaration) { return true; } switch (declaration.kind) { - case 245: - case 243: + case 245 /* ImportClause */: + case 243 /* ImportEqualsDeclaration */: return true; - case 248: - return declaration.parent.kind === 247; + case 248 /* ImportSpecifier */: + return declaration.parent.kind === 247 /* NamedImports */; default: return false; } @@ -79410,14 +95216,16 @@ var ts; function getDefinitionFromSymbol(typeChecker, symbol, node) { return getConstructSignatureDefinition() || getCallSignatureDefinition() || ts.map(symbol.declarations, function (declaration) { return createDefinitionInfo(declaration, typeChecker, symbol, node); }); function getConstructSignatureDefinition() { - if (symbol.flags & 32 && (ts.isNewExpressionTarget(node) || node.kind === 123)) { + // Applicable only if we are in a new expression, or we are on a constructor declaration + // and in either case the symbol has a construct signature definition, i.e. class + if (symbol.flags & 32 /* Class */ && (ts.isNewExpressionTarget(node) || node.kind === 123 /* ConstructorKeyword */)) { var cls = ts.find(symbol.declarations, ts.isClassLike) || ts.Debug.fail("Expected declaration to have at least one class-like declaration"); - return getSignatureDefinition(cls.members, true); + return getSignatureDefinition(cls.members, /*selectConstructors*/ true); } } function getCallSignatureDefinition() { return ts.isCallExpressionTarget(node) || ts.isNewExpressionTarget(node) || ts.isNameOfFunctionDeclaration(node) - ? getSignatureDefinition(symbol.declarations, false) + ? getSignatureDefinition(symbol.declarations, /*selectConstructors*/ false) : undefined; } function getSignatureDefinition(signatureDeclarations, selectConstructors) { @@ -79430,12 +95238,14 @@ var ts; : undefined; } } + /** Creates a DefinitionInfo from a Declaration, using the declaration's name if possible. */ function createDefinitionInfo(declaration, checker, symbol, node) { - var symbolName = checker.symbolToString(symbol); + var symbolName = checker.symbolToString(symbol); // Do not get scoped name, just the name of the symbol var symbolKind = ts.SymbolDisplay.getSymbolKind(checker, symbol, node); var containerName = symbol.parent ? checker.symbolToString(symbol.parent, node) : ""; return createDefinitionInfoFromName(declaration, symbolKind, symbolName, containerName); } + /** Creates a DefinitionInfo directly from the name of a declaration. */ function createDefinitionInfoFromName(declaration, symbolKind, symbolName, containerName) { var name = ts.getNameOfDeclaration(declaration) || declaration; var sourceFile = name.getSourceFile(); @@ -79459,12 +95269,13 @@ var ts; return { fileName: targetFileName, textSpan: ts.createTextSpanFromBounds(0, 0), - kind: "script", + kind: "script" /* scriptElement */, name: name, containerName: undefined, containerKind: undefined, }; } + /** Returns a CallLikeExpression where `node` is the target being invoked. */ function getAncestorCallLikeExpression(node) { var target = climbPastManyPropertyAccesses(node); var callLike = target.parent; @@ -79476,10 +95287,12 @@ var ts; function tryGetSignatureDeclaration(typeChecker, node) { var callLike = getAncestorCallLikeExpression(node); var signature = callLike && typeChecker.getResolvedSignature(callLike); + // Don't go to a function type, go to the value having that type. return ts.tryCast(signature && signature.declaration, function (d) { return ts.isFunctionLike(d) && !ts.isFunctionTypeNode(d); }); } })(GoToDefinition = ts.GoToDefinition || (ts.GoToDefinition = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var JsDoc; @@ -79531,6 +95344,12 @@ var ts; var jsDocTagNameCompletionEntries; var jsDocTagCompletionEntries; function getJsDocCommentsFromDeclarations(declarations) { + // Only collect doc comments from duplicate declarations once: + // In case of a union property there might be same declaration multiple times + // which only varies in type parameter + // Eg. const a: Array | Array; a.length + // The property length will have two declarations of property length coming + // from Array - Array and Array var documentationComment = []; forEachUnique(declarations, function (declaration) { for (var _i = 0, _a = getCommentHavingNodes(declaration); _i < _a.length; _i++) { @@ -79548,17 +95367,18 @@ var ts; JsDoc.getJsDocCommentsFromDeclarations = getJsDocCommentsFromDeclarations; function getCommentHavingNodes(declaration) { switch (declaration.kind) { - case 293: - case 299: + case 293 /* JSDocParameterTag */: + case 299 /* JSDocPropertyTag */: return [declaration]; - case 292: - case 298: + case 292 /* JSDocCallbackTag */: + case 298 /* JSDocTypedefTag */: return [declaration, declaration.parent]; default: return ts.getJSDocCommentsAndTags(declaration); } } function getJsDocTagsFromDeclarations(declarations) { + // Only collect doc comments from duplicate declarations once. var tags = []; forEachUnique(declarations, function (declaration) { for (var _i = 0, _a = ts.getJSDocTags(declaration); _i < _a.length; _i++) { @@ -79572,16 +95392,16 @@ var ts; function getCommentText(tag) { var comment = tag.comment; switch (tag.kind) { - case 290: + case 290 /* JSDocAugmentsTag */: return withNode(tag.class); - case 297: + case 297 /* JSDocTemplateTag */: return withList(tag.typeParameters); - case 296: + case 296 /* JSDocTypeTag */: return withNode(tag.typeExpression); - case 298: - case 292: - case 299: - case 293: + case 298 /* JSDocTypedefTag */: + case 292 /* JSDocCallbackTag */: + case 299 /* JSDocPropertyTag */: + case 293 /* JSDocParameterTag */: var name = tag.name; return name ? withNode(name) : comment; default: @@ -79597,6 +95417,11 @@ var ts; return comment === undefined ? s : s + " " + comment; } } + /** + * Iterates through 'array' by index and performs the callback on each element of array until the callback + * returns a truthy value, then returns that value. + * If no such value is found, the callback is applied to each element of array and undefined is returned. + */ function forEachUnique(array, callback) { if (array) { for (var i = 0; i < array.length; i++) { @@ -79614,7 +95439,7 @@ var ts; return jsDocTagNameCompletionEntries || (jsDocTagNameCompletionEntries = ts.map(jsDocTagNames, function (tagName) { return { name: tagName, - kind: "keyword", + kind: "keyword" /* keyword */, kindModifiers: "", sortText: "0", }; @@ -79626,7 +95451,7 @@ var ts; return jsDocTagCompletionEntries || (jsDocTagCompletionEntries = ts.map(jsDocTagNames, function (tagName) { return { name: "@" + tagName, - kind: "keyword", + kind: "keyword" /* keyword */, kindModifiers: "", sortText: "0" }; @@ -79636,7 +95461,7 @@ var ts; function getJSDocTagCompletionDetails(name) { return { name: name, - kind: "", + kind: "" /* unknown */, kindModifiers: "", displayParts: [ts.textPart(name)], documentation: ts.emptyArray, @@ -79658,18 +95483,18 @@ var ts; if (!ts.isIdentifier(param.name)) return undefined; var name = param.name.text; - if (jsdoc.tags.some(function (t) { return t !== tag && ts.isJSDocParameterTag(t) && ts.isIdentifier(t.name) && t.name.escapedText === name; }) + if (jsdoc.tags.some(function (t) { return t !== tag && ts.isJSDocParameterTag(t) && ts.isIdentifier(t.name) && t.name.escapedText === name; }) // TODO: GH#18217 || nameThusFar !== undefined && !ts.startsWith(name, nameThusFar)) { return undefined; } - return { name: name, kind: "parameter", kindModifiers: "", sortText: "0" }; + return { name: name, kind: "parameter" /* parameterElement */, kindModifiers: "", sortText: "0" }; }); } JsDoc.getJSDocParameterNameCompletions = getJSDocParameterNameCompletions; function getJSDocParameterNameCompletionDetails(name) { return { name: name, - kind: "parameter", + kind: "parameter" /* parameterElement */, kindModifiers: "", displayParts: [ts.textPart(name)], documentation: ts.emptyArray, @@ -79678,11 +95503,35 @@ var ts; }; } JsDoc.getJSDocParameterNameCompletionDetails = getJSDocParameterNameCompletionDetails; + /** + * Checks if position points to a valid position to add JSDoc comments, and if so, + * returns the appropriate template. Otherwise returns an empty string. + * Valid positions are + * - outside of comments, statements, and expressions, and + * - preceding a: + * - function/constructor/method declaration + * - class declarations + * - variable statements + * - namespace declarations + * - interface declarations + * - method signatures + * - type alias declarations + * + * Hosts should ideally check that: + * - The line is all whitespace up to 'position' before performing the insertion. + * - If the keystroke sequence "/\*\*" induced the call, we also check that the next + * non-whitespace character is '*', which (approximately) indicates whether we added + * the second '*' to complete an existing (JSDoc) comment. + * @param fileName The file in which to perform the check. + * @param position The (character-indexed) position in the file where the check should + * be performed. + */ function getDocCommentTemplateAtPosition(newLine, sourceFile, position) { + // Check if in a context where we don't want to perform any insertion if (ts.isInString(sourceFile, position) || ts.isInComment(sourceFile, position) || ts.hasDocComment(sourceFile, position)) { return undefined; } - var tokenAtPos = ts.getTokenAtPosition(sourceFile, position, false); + var tokenAtPos = ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); var tokenStart = tokenAtPos.getStart(sourceFile); if (!tokenAtPos || tokenStart < position) { return undefined; @@ -79696,12 +95545,21 @@ var ts; return undefined; } if (!parameters || parameters.length === 0) { + // if there are no parameters, just complete to a single line JSDoc comment var singleLineResult = "/** */"; return { newText: singleLineResult, caretOffset: 3 }; } var posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position); var lineStart = sourceFile.getLineStarts()[posLineAndChar.line]; + // replace non-whitespace characters in prefix with spaces. var indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character).replace(/\S/i, function () { return " "; }); + // A doc comment consists of the following + // * The opening comment line + // * the first line (without a param) for the object's untagged info (this is also where the caret ends up) + // * the '@param'-tagged lines + // * TODO: other tags. + // * the closing comment line + // * if the caret was directly in front of the object, then we add an extra line and indentation. var preamble = "/**" + newLine + indentationStr + " * "; var result = preamble + newLine + @@ -79714,7 +95572,7 @@ var ts; function parameterDocComments(parameters, isJavaScriptFile, indentationStr, newLine) { return parameters.map(function (_a, i) { var name = _a.name, dotDotDotToken = _a.dotDotDotToken; - var paramName = name.kind === 71 ? name.text : "param" + i; + var paramName = name.kind === 71 /* Identifier */ ? name.text : "param" + i; var type = isJavaScriptFile ? (dotDotDotToken ? "{...any} " : "{any} ") : ""; return indentationStr + " * @param " + type + paramName + newLine; }).join(""); @@ -79722,20 +95580,20 @@ var ts; function getCommentOwnerInfo(tokenAtPos) { for (var commentOwner = tokenAtPos; commentOwner; commentOwner = commentOwner.parent) { switch (commentOwner.kind) { - case 234: - case 154: - case 155: - case 153: + case 234 /* FunctionDeclaration */: + case 154 /* MethodDeclaration */: + case 155 /* Constructor */: + case 153 /* MethodSignature */: var parameters = commentOwner.parameters; return { commentOwner: commentOwner, parameters: parameters }; - case 235: - case 236: - case 151: - case 238: - case 273: - case 237: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + case 151 /* PropertySignature */: + case 238 /* EnumDeclaration */: + case 273 /* EnumMember */: + case 237 /* TypeAliasDeclaration */: return { commentOwner: commentOwner }; - case 214: { + case 214 /* VariableStatement */: { var varStatement = commentOwner; var varDeclarations = varStatement.declarationList.declarations; var parameters_1 = varDeclarations.length === 1 && varDeclarations[0].initializer @@ -79743,13 +95601,16 @@ var ts; : undefined; return { commentOwner: commentOwner, parameters: parameters_1 }; } - case 274: + case 274 /* SourceFile */: return undefined; - case 239: - return commentOwner.parent.kind === 239 ? undefined : { commentOwner: commentOwner }; - case 200: { + case 239 /* ModuleDeclaration */: + // If in walking up the tree, we hit a a nested namespace declaration, + // then we must be somewhere within a dotted namespace name; however we don't + // want to give back a JSDoc template for the 'b' or 'c' in 'namespace a.b.c { }'. + return commentOwner.parent.kind === 239 /* ModuleDeclaration */ ? undefined : { commentOwner: commentOwner }; + case 200 /* BinaryExpression */: { var be = commentOwner; - if (ts.getSpecialPropertyAssignmentKind(be) === 0) { + if (ts.getSpecialPropertyAssignmentKind(be) === 0 /* None */) { return undefined; } var parameters_2 = ts.isFunctionLike(be.right) ? be.right.parameters : ts.emptyArray; @@ -79758,15 +95619,23 @@ var ts; } } } + /** + * Digs into an an initializer or RHS operand of an assignment operation + * to get the parameters of an apt signature corresponding to a + * function expression or a class expression. + * + * @param rightHandSide the expression which may contain an appropriate set of parameters + * @returns the parameters of a signature found on the RHS if one exists; otherwise 'emptyArray'. + */ function getParametersFromRightHandSideOfAssignment(rightHandSide) { - while (rightHandSide.kind === 191) { + while (rightHandSide.kind === 191 /* ParenthesizedExpression */) { rightHandSide = rightHandSide.expression; } switch (rightHandSide.kind) { - case 192: - case 193: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: return rightHandSide.parameters; - case 205: { + case 205 /* ClassExpression */: { var ctr = ts.find(rightHandSide.members, ts.isConstructorDeclaration); return ctr ? ctr.parameters : ts.emptyArray; } @@ -79775,6 +95644,7 @@ var ts; } })(JsDoc = ts.JsDoc || (ts.JsDoc = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var NavigateTo; @@ -79786,13 +95656,14 @@ var ts; var rawItems = []; var _loop_16 = function (sourceFile) { cancellationToken.throwIfCancellationRequested(); - if (excludeDtsFiles && ts.fileExtensionIs(sourceFile.fileName, ".d.ts")) { + if (excludeDtsFiles && ts.fileExtensionIs(sourceFile.fileName, ".d.ts" /* Dts */)) { return "continue"; } sourceFile.getNamedDeclarations().forEach(function (declarations, name) { getItemsFromNamedDeclaration(patternMatcher, name, declarations, checker, sourceFile.fileName, rawItems); }); }; + // Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[] for (var _i = 0, sourceFiles_7 = sourceFiles; _i < sourceFiles_7.length; _i++) { var sourceFile = sourceFiles_7[_i]; _loop_16(sourceFile); @@ -79805,30 +95676,33 @@ var ts; } NavigateTo.getNavigateToItems = getNavigateToItems; function getItemsFromNamedDeclaration(patternMatcher, name, declarations, checker, fileName, rawItems) { + // First do a quick check to see if the name of the declaration matches the + // last portion of the (possibly) dotted name they're searching for. var match = patternMatcher.getMatchForLastSegmentOfPattern(name); if (!match) { - return; + return; // continue to next named declarations } for (var _i = 0, declarations_12 = declarations; _i < declarations_12.length; _i++) { var declaration = declarations_12[_i]; if (!shouldKeepItem(declaration, checker)) continue; if (patternMatcher.patternContainsDots) { - var fullMatch = patternMatcher.getFullMatch(getContainers(declaration), name); + var fullMatch = patternMatcher.getFullMatch(getContainers(declaration), name); // TODO: GH#18217 if (fullMatch) { rawItems.push({ name: name, fileName: fileName, matchKind: fullMatch.kind, isCaseSensitive: fullMatch.isCaseSensitive, declaration: declaration }); } } else { + // If the pattern has dots in it, then also see if the declaration container matches as well. rawItems.push({ name: name, fileName: fileName, matchKind: match.kind, isCaseSensitive: match.isCaseSensitive, declaration: declaration }); } } } function shouldKeepItem(declaration, checker) { switch (declaration.kind) { - case 245: - case 248: - case 243: + case 245 /* ImportClause */: + case 248 /* ImportSpecifier */: + case 243 /* ImportEqualsDeclaration */: var importer = checker.getSymbolAtLocation(declaration.name); var imported = checker.getAliasedSymbol(importer); return importer.escapedName !== imported.escapedName; @@ -79842,13 +95716,17 @@ var ts; containers.unshift(ts.getTextOfIdentifierOrLiteral(name)); return true; } - else if (name && name.kind === 147) { - return tryAddComputedPropertyName(name.expression, containers, true); + else if (name && name.kind === 147 /* ComputedPropertyName */) { + return tryAddComputedPropertyName(name.expression, containers, /*includeLastPortion*/ true); } else { + // Don't know how to add this. return false; } } + // Only added the names of computed properties if they're simple dotted expressions, like: + // + // [X.Y.Z]() { } function tryAddComputedPropertyName(expression, containers, includeLastPortion) { if (ts.isPropertyNameLiteral(expression)) { var text = ts.getTextOfIdentifierOrLiteral(expression); @@ -79861,16 +95739,19 @@ var ts; if (includeLastPortion) { containers.unshift(expression.name.text); } - return tryAddComputedPropertyName(expression.expression, containers, true); + return tryAddComputedPropertyName(expression.expression, containers, /*includeLastPortion*/ true); } return false; } function getContainers(declaration) { var containers = []; + // First, if we started with a computed property name, then add all but the last + // portion into the container array. var name = ts.getNameOfDeclaration(declaration); - if (name.kind === 147 && !tryAddComputedPropertyName(name.expression, containers, false)) { + if (name.kind === 147 /* ComputedPropertyName */ && !tryAddComputedPropertyName(name.expression, containers, /*includeLastPortion*/ false)) { return undefined; } + // Now, walk up our containers, adding all their names to the container array. var container = ts.getContainerNode(declaration); while (container) { if (!tryAddSingleDeclarationName(container, containers)) { @@ -79881,6 +95762,7 @@ var ts; return containers; } function compareNavigateToItems(i1, i2) { + // TODO(cyrusn): get the gamut of comparisons that VS already uses here. return ts.compareValues(i1.matchKind, i2.matchKind) || ts.compareStringsCaseSensitiveUI(i1.name, i2.name); } @@ -79896,21 +95778,43 @@ var ts; isCaseSensitive: rawItem.isCaseSensitive, fileName: rawItem.fileName, textSpan: ts.createTextSpanFromNode(declaration), + // TODO(jfreeman): What should be the containerName when the container has a computed name? containerName: containerName ? containerName.text : "", - containerKind: containerName ? ts.getNodeKind(container) : "" + containerKind: containerName ? ts.getNodeKind(container) : "" /* unknown */ // TODO: GH#18217 Just use `container ? ...` }; } })(NavigateTo = ts.NavigateTo || (ts.NavigateTo = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var NavigationBar; (function (NavigationBar) { + /** + * Matches all whitespace characters in a string. Eg: + * + * "app. + * + * onactivated" + * + * matches because of the newline, whereas + * + * "app.onactivated" + * + * does not match. + */ var whiteSpaceRegex = /\s+/g; + // Keep sourceFile handy so we don't have to search for it every time we need to call `getText`. var curCancellationToken; var curSourceFile; + /** + * For performance, we keep navigation bar parents on a stack rather than passing them through each recursion. + * `parent` is the current parent and is *not* stored in parentsStack. + * `startNode` sets a new parent and `endNode` returns to the previous parent. + */ var parentsStack = []; var parent; + // NavigationBarItem requires an array, but will not mutate it, so just give it this for performance. var emptyChildItemArray = []; function getNavigationBarItems(sourceFile, cancellationToken) { curCancellationToken = cancellationToken; @@ -79980,12 +95884,18 @@ var ts; indent: parent.indent + 1 }; } + /** + * Add a new level of NavigationBarNodes. + * This pushes to the stack, so you must call `endNode` when you are done adding to this node. + */ function startNode(node) { var navNode = emptyNavigationBarNode(node); pushChild(parent, navNode); + // Save the old parent parentsStack.push(parent); parent = navNode; } + /** Call after calling `startNode` and adding children to it. */ function endNode() { if (parent.children) { mergeChildren(parent.children); @@ -79998,15 +95908,18 @@ var ts; addChildrenRecursively(child); endNode(); } + /** Look for navigation bar items in node's subtree, adding them to the current `parent`. */ function addChildrenRecursively(node) { curCancellationToken.throwIfCancellationRequested(); if (!node || ts.isToken(node)) { return; } switch (node.kind) { - case 155: + case 155 /* Constructor */: + // Get parameter properties, and treat them as being on the *same* level as the constructor, not under it. var ctr = node; addNodeWithRecursiveChild(ctr, ctr.body); + // Parameter properties are children of the class, not the constructor. for (var _i = 0, _a = ctr.parameters; _i < _a.length; _i++) { var param = _a[_i]; if (ts.isParameterPropertyDeclaration(param)) { @@ -80014,28 +95927,33 @@ var ts; } } break; - case 154: - case 156: - case 157: - case 153: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 153 /* MethodSignature */: if (!ts.hasDynamicName(node)) { addNodeWithRecursiveChild(node, node.body); } break; - case 152: - case 151: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: if (!ts.hasDynamicName(node)) { addLeafNode(node); } break; - case 245: + case 245 /* ImportClause */: var importClause = node; + // Handle default import case e.g.: + // import d from "mod"; if (importClause.name) { addLeafNode(importClause); } + // Handle named bindings in imports e.g.: + // import * as NS from "mod"; + // import {a, b as B} from "mod"; var namedBindings = importClause.namedBindings; if (namedBindings) { - if (namedBindings.kind === 246) { + if (namedBindings.kind === 246 /* NamespaceImport */) { addLeafNode(namedBindings); } else { @@ -80046,17 +95964,19 @@ var ts; } } break; - case 182: - case 232: + case 182 /* BindingElement */: + case 232 /* VariableDeclaration */: var _d = node, name = _d.name, initializer = _d.initializer; if (ts.isBindingPattern(name)) { addChildrenRecursively(name); } else if (initializer && isFunctionOrClassExpression(initializer)) { if (initializer.name) { + // Don't add a node for the VariableDeclaration, just for the initializer. addChildrenRecursively(initializer); } else { + // Add a node for the VariableDeclaration, but not for the initializer. startNode(node); ts.forEachChild(initializer, addChildrenRecursively); endNode(); @@ -80066,12 +95986,12 @@ var ts; addNodeWithRecursiveChild(node, initializer); } break; - case 193: - case 234: - case 192: + case 193 /* ArrowFunction */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: addNodeWithRecursiveChild(node, node.body); break; - case 238: + case 238 /* EnumDeclaration */: startNode(node); for (var _e = 0, _f = node.members; _e < _f.length; _e++) { var member = _f[_e]; @@ -80081,9 +96001,9 @@ var ts; } endNode(); break; - case 235: - case 205: - case 236: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 236 /* InterfaceDeclaration */: startNode(node); for (var _g = 0, _h = node.members; _g < _h.length; _g++) { var member = _h[_g]; @@ -80091,34 +96011,35 @@ var ts; } endNode(); break; - case 239: + case 239 /* ModuleDeclaration */: addNodeWithRecursiveChild(node, getInteriorModule(node).body); break; - case 252: - case 243: - case 160: - case 158: - case 159: - case 237: + case 252 /* ExportSpecifier */: + case 243 /* ImportEqualsDeclaration */: + case 160 /* IndexSignature */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 237 /* TypeAliasDeclaration */: addLeafNode(node); break; - case 200: { + case 200 /* BinaryExpression */: { var special = ts.getSpecialPropertyAssignmentKind(node); switch (special) { - case 1: - case 2: - case 3: - case 6: + case 1 /* ExportsProperty */: + case 2 /* ModuleExports */: + case 3 /* PrototypeProperty */: + case 6 /* Prototype */: addNodeWithRecursiveChild(node, node.right); break; - case 4: - case 5: - case 0: + case 4 /* ThisProperty */: + case 5 /* Property */: + case 0 /* None */: break; default: ts.Debug.assertNever(special); } } + // falls through default: if (ts.hasJSDocNodes(node)) { ts.forEach(node.jsDoc, function (jsDoc) { @@ -80132,12 +96053,14 @@ var ts; ts.forEachChild(node, addChildrenRecursively); } } + /** Merge declarations of the same kind. */ function mergeChildren(children) { var nameToItems = ts.createMap(); ts.filterMutate(children, function (child) { var declName = ts.getNameOfDeclaration(child.node); var name = declName && nodeText(declName); if (!name) { + // Anonymous items are never merged. return true; } var itemsWithSameName = nameToItems.get(name); @@ -80172,25 +96095,30 @@ var ts; } return false; } + /** a and b have the same name, but they may not be mergeable. */ function shouldReallyMerge(a, b) { if (a.kind !== b.kind) { return false; } switch (a.kind) { - case 152: - case 154: - case 156: - case 157: - return ts.hasModifier(a, 32) === ts.hasModifier(b, 32); - case 239: + case 152 /* PropertyDeclaration */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + return ts.hasModifier(a, 32 /* Static */) === ts.hasModifier(b, 32 /* Static */); + case 239 /* ModuleDeclaration */: return areSameModule(a, b); default: return true; } } + // We use 1 NavNode to represent 'A.B.C', but there are multiple source nodes. + // Only merge module nodes that have the same chain. Don't merge 'A.B.C' with 'A'! function areSameModule(a, b) { - return a.body.kind === b.body.kind && (a.body.kind !== 239 || areSameModule(a.body, b.body)); + // TODO: GH#18217 + return a.body.kind === b.body.kind && (a.body.kind !== 239 /* ModuleDeclaration */ || areSameModule(a.body, b.body)); } + /** Merge source into target. Source should be thrown away after this is called. */ function merge(target, source) { var _a; target.additionalNodes = target.additionalNodes || []; @@ -80204,32 +96132,38 @@ var ts; sortChildren(target.children); } } + /** Recursively ensure that each NavNode's children are in sorted order. */ function sortChildren(children) { children.sort(compareChildren); } function compareChildren(child1, child2) { - return ts.compareStringsCaseSensitiveUI(tryGetName(child1.node), tryGetName(child2.node)) + return ts.compareStringsCaseSensitiveUI(tryGetName(child1.node), tryGetName(child2.node)) // TODO: GH#18217 || ts.compareValues(navigationBarNodeKind(child1), navigationBarNodeKind(child2)); } + /** + * This differs from getItemName because this is just used for sorting. + * We only sort nodes by name that have a more-or-less "direct" name, as opposed to `new()` and the like. + * So `new()` can still come before an `aardvark` method. + */ function tryGetName(node) { - if (node.kind === 239) { + if (node.kind === 239 /* ModuleDeclaration */) { return getModuleName(node); } var declName = ts.getNameOfDeclaration(node); if (declName) { - return ts.unescapeLeadingUnderscores(ts.getPropertyNameForPropertyNameNode(declName)); + return ts.unescapeLeadingUnderscores(ts.getPropertyNameForPropertyNameNode(declName)); // TODO: GH#18217 } switch (node.kind) { - case 192: - case 193: - case 205: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 205 /* ClassExpression */: return getFunctionOrClassName(node); default: return undefined; } } function getItemName(node, name) { - if (node.kind === 239) { + if (node.kind === 239 /* ModuleDeclaration */) { return getModuleName(node); } if (name) { @@ -80239,32 +96173,36 @@ var ts; } } switch (node.kind) { - case 274: + case 274 /* SourceFile */: var sourceFile = node; return ts.isExternalModule(sourceFile) ? "\"" + ts.escapeString(ts.getBaseFileName(ts.removeFileExtension(ts.normalizePath(sourceFile.fileName)))) + "\"" : ""; - case 193: - case 234: - case 192: - case 235: - case 205: - if (ts.getModifierFlags(node) & 512) { + case 193 /* ArrowFunction */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + if (ts.getModifierFlags(node) & 512 /* Default */) { return "default"; } + // We may get a string with newlines or other whitespace in the case of an object dereference + // (eg: "app\n.onactivated"), so we should remove the whitespace for readabiltiy in the + // navigation bar. return getFunctionOrClassName(node); - case 155: + case 155 /* Constructor */: return "constructor"; - case 159: + case 159 /* ConstructSignature */: return "new()"; - case 158: + case 158 /* CallSignature */: return "()"; - case 160: + case 160 /* IndexSignature */: return "[]"; default: return ""; } } + /** Flattens the NavNode tree to a list, keeping only the top-level items. */ function topLevelItems(root) { var topLevel = []; function recur(item) { @@ -80282,25 +96220,25 @@ var ts; return topLevel; function isTopLevel(item) { switch (navigationBarNodeKind(item)) { - case 235: - case 205: - case 238: - case 236: - case 239: - case 274: - case 237: - case 298: - case 292: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 238 /* EnumDeclaration */: + case 236 /* InterfaceDeclaration */: + case 239 /* ModuleDeclaration */: + case 274 /* SourceFile */: + case 237 /* TypeAliasDeclaration */: + case 298 /* JSDocTypedefTag */: + case 292 /* JSDocCallbackTag */: return true; - case 155: - case 154: - case 156: - case 157: - case 232: + case 155 /* Constructor */: + case 154 /* MethodDeclaration */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 232 /* VariableDeclaration */: return hasSomeImportantChild(item); - case 193: - case 234: - case 192: + case 193 /* ArrowFunction */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: return isTopLevelFunctionDeclaration(item); default: return false; @@ -80310,10 +96248,10 @@ var ts; return false; } switch (navigationBarNodeKind(item.parent)) { - case 240: - case 274: - case 154: - case 155: + case 240 /* ModuleBlock */: + case 274 /* SourceFile */: + case 154 /* MethodDeclaration */: + case 155 /* Constructor */: return true; default: return hasSomeImportantChild(item); @@ -80322,7 +96260,7 @@ var ts; function hasSomeImportantChild(item) { return ts.some(item.children, function (child) { var childKind = navigationBarNodeKind(child); - return childKind !== 232 && childKind !== 182; + return childKind !== 232 /* VariableDeclaration */ && childKind !== 182 /* BindingElement */; }); } } @@ -80372,28 +96310,34 @@ var ts; return spans; } function getModuleName(moduleDeclaration) { + // We want to maintain quotation marks. if (ts.isAmbientModule(moduleDeclaration)) { return ts.getTextOfNode(moduleDeclaration.name); } + // Otherwise, we need to aggregate each identifier to build up the qualified name. var result = []; result.push(ts.getTextOfIdentifierOrLiteral(moduleDeclaration.name)); - while (moduleDeclaration.body && moduleDeclaration.body.kind === 239) { + while (moduleDeclaration.body && moduleDeclaration.body.kind === 239 /* ModuleDeclaration */) { moduleDeclaration = moduleDeclaration.body; result.push(ts.getTextOfIdentifierOrLiteral(moduleDeclaration.name)); } return result.join("."); } + /** + * For 'module A.B.C', we want to get the node for 'C'. + * We store 'A' as associated with a NavNode, and use getModuleName to traverse down again. + */ function getInteriorModule(decl) { - return decl.body.kind === 239 ? getInteriorModule(decl.body) : decl; + return decl.body.kind === 239 /* ModuleDeclaration */ ? getInteriorModule(decl.body) : decl; // TODO: GH#18217 } function isComputedProperty(member) { - return !member.name || member.name.kind === 147; + return !member.name || member.name.kind === 147 /* ComputedPropertyName */; } function getNodeSpan(node) { - return node.kind === 274 ? ts.createTextSpanFromRange(node) : ts.createTextSpanFromNode(node, curSourceFile); + return node.kind === 274 /* SourceFile */ ? ts.createTextSpanFromRange(node) : ts.createTextSpanFromNode(node, curSourceFile); } function getModifiers(node) { - if (node.parent && node.parent.kind === 232) { + if (node.parent && node.parent.kind === 232 /* VariableDeclaration */) { node = node.parent; } return ts.getNodeModifiers(node); @@ -80402,17 +96346,21 @@ var ts; if (node.name && ts.getFullWidth(node.name) > 0) { return ts.declarationNameToString(node.name); } - else if (node.parent.kind === 232) { + // See if it is a var initializer. If so, use the var name. + else if (node.parent.kind === 232 /* VariableDeclaration */) { return ts.declarationNameToString(node.parent.name); } - else if (node.parent.kind === 200 && - node.parent.operatorToken.kind === 58) { + // See if it is of the form " = function(){...}". If so, use the text from the left-hand side. + else if (node.parent.kind === 200 /* BinaryExpression */ && + node.parent.operatorToken.kind === 58 /* EqualsToken */) { return nodeText(node.parent.left).replace(whiteSpaceRegex, ""); } - else if (node.parent.kind === 270 && node.parent.name) { + // See if it is a property assignment, and if so use the property name + else if (node.parent.kind === 270 /* PropertyAssignment */ && node.parent.name) { return nodeText(node.parent.name); } - else if (ts.getModifierFlags(node) & 512) { + // Default exports are named "default" + else if (ts.getModifierFlags(node) & 512 /* Default */) { return "default"; } else { @@ -80421,9 +96369,9 @@ var ts; } function isFunctionOrClassExpression(node) { switch (node.kind) { - case 193: - case 192: - case 205: + case 193 /* ArrowFunction */: + case 192 /* FunctionExpression */: + case 205 /* ClassExpression */: return true; default: return false; @@ -80431,20 +96379,29 @@ var ts; } })(NavigationBar = ts.NavigationBar || (ts.NavigationBar = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var OrganizeImports; (function (OrganizeImports) { + /** + * Organize imports by: + * 1) Removing unused imports + * 2) Coalescing imports from the same module + * 3) Sorting imports + */ function organizeImports(sourceFile, formatContext, host, program, _preferences) { var changeTracker = ts.textChanges.ChangeTracker.fromContext({ host: host, formatContext: formatContext }); var coalesceAndOrganizeImports = function (importGroup) { return coalesceImports(removeUnusedImports(importGroup, sourceFile, program)); }; + // All of the old ImportDeclarations in the file, in syntactic order. var topLevelImportDecls = sourceFile.statements.filter(ts.isImportDeclaration); organizeImportsWorker(topLevelImportDecls, coalesceAndOrganizeImports); + // All of the old ExportDeclarations in the file, in syntactic order. var topLevelExportDecls = sourceFile.statements.filter(ts.isExportDeclaration); organizeImportsWorker(topLevelExportDecls, coalesceExports); for (var _i = 0, _a = sourceFile.statements.filter(ts.isAmbientModule); _i < _a.length; _i++) { var ambientModule = _a[_i]; - var ambientModuleBody = getModuleBlock(ambientModule); + var ambientModuleBody = getModuleBlock(ambientModule); // TODO: GH#18217 var ambientModuleImportDecls = ambientModuleBody.statements.filter(ts.isImportDeclaration); organizeImportsWorker(ambientModuleImportDecls, coalesceAndOrganizeImports); var ambientModuleExportDecls = ambientModuleBody.statements.filter(ts.isExportDeclaration); @@ -80455,6 +96412,11 @@ var ts; if (ts.length(oldImportDecls) === 0) { return; } + // Special case: normally, we'd expect leading and trailing trivia to follow each import + // around as it's sorted. However, we do not want this to happen for leading trivia + // on the first import because it is probably the header comment for the file. + // Consider: we could do a more careful check that this trivia is actually a header, + // but the consequences of being wrong are very minor. ts.suppressLeadingTrivia(oldImportDecls[0]); var oldImportGroups = ts.group(oldImportDecls, function (importDecl) { return getExternalModuleName(importDecl.moduleSpecifier); }); var sortedImportGroups = ts.stableSort(oldImportGroups, function (group1, group2) { return compareModuleSpecifiers(group1[0].moduleSpecifier, group2[0].moduleSpecifier); }); @@ -80463,6 +96425,7 @@ var ts; ? coalesce(importGroup) : importGroup; }); + // Delete or replace the first import. if (newImportDecls.length === 0) { changeTracker.deleteNode(sourceFile, oldImportDecls[0], { useNonAdjustedStartPosition: true, @@ -80470,12 +96433,14 @@ var ts; }); } else { + // Note: Delete the surrounding trivia because it will have been retained in newImportDecls. changeTracker.replaceNodeWithNodes(sourceFile, oldImportDecls[0], newImportDecls, { useNonAdjustedStartPosition: true, useNonAdjustedEndPosition: false, suffix: ts.getNewLineOrDefaultFromHost(host, formatContext.options), }); } + // Delete any subsequent imports. for (var i = 1; i < oldImportDecls.length; i++) { changeTracker.deleteNode(sourceFile, oldImportDecls[i]); } @@ -80489,26 +96454,30 @@ var ts; function removeUnusedImports(oldImports, sourceFile, program) { var typeChecker = program.getTypeChecker(); var jsxNamespace = typeChecker.getJsxNamespace(); - var jsxElementsPresent = !!(sourceFile.transformFlags & 4); + var jsxElementsPresent = !!(sourceFile.transformFlags & 4 /* ContainsJsx */); var usedImports = []; for (var _i = 0, oldImports_1 = oldImports; _i < oldImports_1.length; _i++) { var importDecl = oldImports_1[_i]; var importClause = importDecl.importClause; if (!importClause) { + // Imports without import clauses are assumed to be included for their side effects and are not removed. usedImports.push(importDecl); continue; } var name = importClause.name, namedBindings = importClause.namedBindings; + // Default import if (name && !isDeclarationUsed(name)) { name = undefined; } if (namedBindings) { if (ts.isNamespaceImport(namedBindings)) { + // Namespace import if (!isDeclarationUsed(namedBindings.name)) { namedBindings = undefined; } } else { + // List of named imports var newElements = namedBindings.elements.filter(function (e) { return isDeclarationUsed(e.name); }); if (newElements.length < namedBindings.elements.length) { namedBindings = newElements.length @@ -80523,6 +96492,7 @@ var ts; } return usedImports; function isDeclarationUsed(identifier) { + // The JSX factory symbol is always used if JSX elements are present - even if they are not allowed. return jsxElementsPresent && (identifier.text === jsxNamespace) || ts.FindAllReferences.Core.isSymbolReferencedInFile(identifier, typeChecker, sourceFile); } } @@ -80531,6 +96501,10 @@ var ts; ? specifier.text : undefined; } + /* @internal */ // Internal for testing + /** + * @param importGroup a list of ImportDeclarations, all with the same module name. + */ function coalesceImports(importGroup) { if (importGroup.length === 0) { return importGroup; @@ -80540,17 +96514,21 @@ var ts; if (importWithoutClause) { coalescedImports.push(importWithoutClause); } + // Normally, we don't combine default and namespace imports, but it would be silly to + // produce two import declarations in this special case. if (defaultImports.length === 1 && namespaceImports.length === 1 && namedImports.length === 0) { + // Add the namespace import to the existing default ImportDeclaration. var defaultImport = defaultImports[0]; - coalescedImports.push(updateImportDeclarationAndClause(defaultImport, defaultImport.importClause.name, namespaceImports[0].importClause.namedBindings)); + coalescedImports.push(updateImportDeclarationAndClause(defaultImport, defaultImport.importClause.name, namespaceImports[0].importClause.namedBindings)); // TODO: GH#18217 return coalescedImports; } var sortedNamespaceImports = ts.stableSort(namespaceImports, function (i1, i2) { return compareIdentifiers(i1.importClause.namedBindings.name, i2.importClause.namedBindings.name); - }); + }); // TODO: GH#18217 for (var _i = 0, sortedNamespaceImports_1 = sortedNamespaceImports; _i < sortedNamespaceImports_1.length; _i++) { var namespaceImport = sortedNamespaceImports_1[_i]; - coalescedImports.push(updateImportDeclarationAndClause(namespaceImport, undefined, namespaceImport.importClause.namedBindings)); + // Drop the name, if any + coalescedImports.push(updateImportDeclarationAndClause(namespaceImport, /*name*/ undefined, namespaceImport.importClause.namedBindings)); // TODO: GH#18217 } if (defaultImports.length === 0 && namedImports.length === 0) { return coalescedImports; @@ -80563,10 +96541,10 @@ var ts; else { for (var _b = 0, defaultImports_1 = defaultImports; _b < defaultImports_1.length; _b++) { var defaultImport = defaultImports_1[_b]; - newImportSpecifiers.push(ts.createImportSpecifier(ts.createIdentifier("default"), defaultImport.importClause.name)); + newImportSpecifiers.push(ts.createImportSpecifier(ts.createIdentifier("default"), defaultImport.importClause.name)); // TODO: GH#18217 } } - newImportSpecifiers.push.apply(newImportSpecifiers, ts.flatMap(namedImports, function (i) { return i.importClause.namedBindings.elements; })); + newImportSpecifiers.push.apply(newImportSpecifiers, ts.flatMap(namedImports, function (i) { return i.importClause.namedBindings.elements; })); // TODO: GH#18217 var sortedImportSpecifiers = sortSpecifiers(newImportSpecifiers); var importDecl = defaultImports.length > 0 ? defaultImports[0] @@ -80577,9 +96555,16 @@ var ts; : ts.createNamedImports(ts.emptyArray) : namedImports.length === 0 ? ts.createNamedImports(sortedImportSpecifiers) - : ts.updateNamedImports(namedImports[0].importClause.namedBindings, sortedImportSpecifiers); + : ts.updateNamedImports(namedImports[0].importClause.namedBindings, sortedImportSpecifiers); // TODO: GH#18217 coalescedImports.push(updateImportDeclarationAndClause(importDecl, newDefaultImport, newNamedImports)); return coalescedImports; + /* + * Returns entire import declarations because they may already have been rewritten and + * may lack parent pointers. The desired parts can easily be recovered based on the + * categorization. + * + * NB: There may be overlap between `defaultImports` and `namespaceImports`/`namedImports`. + */ function getCategorizedImports(importGroup) { var importWithoutClause; var defaultImports = []; @@ -80588,6 +96573,8 @@ var ts; for (var _i = 0, importGroup_1 = importGroup; _i < importGroup_1.length; _i++) { var importDeclaration = importGroup_1[_i]; if (importDeclaration.importClause === undefined) { + // Only the first such import is interesting - the others are redundant. + // Note: Unfortunately, we will lose trivia that was on this node. importWithoutClause = importWithoutClause || importDeclaration; continue; } @@ -80613,6 +96600,10 @@ var ts; } } OrganizeImports.coalesceImports = coalesceImports; + /* @internal */ // Internal for testing + /** + * @param exportGroup a list of ExportDeclarations, all with the same module name. + */ function coalesceExports(exportGroup) { if (exportGroup.length === 0) { return exportGroup; @@ -80631,12 +96622,19 @@ var ts; var exportDecl = namedExports[0]; coalescedExports.push(ts.updateExportDeclaration(exportDecl, exportDecl.decorators, exportDecl.modifiers, ts.updateNamedExports(exportDecl.exportClause, sortedExportSpecifiers), exportDecl.moduleSpecifier)); return coalescedExports; + /* + * Returns entire export declarations because they may already have been rewritten and + * may lack parent pointers. The desired parts can easily be recovered based on the + * categorization. + */ function getCategorizedExports(exportGroup) { var exportWithoutClause; var namedExports = []; for (var _i = 0, exportGroup_1 = exportGroup; _i < exportGroup_1.length; _i++) { var exportDeclaration = exportGroup_1[_i]; if (exportDeclaration.exportClause === undefined) { + // Only the first such export is interesting - the others are redundant. + // Note: Unfortunately, we will lose trivia that was on this node. exportWithoutClause = exportWithoutClause || exportDeclaration; } else { @@ -80651,7 +96649,8 @@ var ts; } OrganizeImports.coalesceExports = coalesceExports; function updateImportDeclarationAndClause(importDeclaration, name, namedBindings) { - return ts.updateImportDeclaration(importDeclaration, importDeclaration.decorators, importDeclaration.modifiers, ts.updateImportClause(importDeclaration.importClause, name, namedBindings), importDeclaration.moduleSpecifier); + return ts.updateImportDeclaration(importDeclaration, importDeclaration.decorators, importDeclaration.modifiers, ts.updateImportClause(importDeclaration.importClause, name, namedBindings), // TODO: GH#18217 + importDeclaration.moduleSpecifier); } function sortSpecifiers(specifiers) { return ts.stableSort(specifiers, function (s1, s2) { @@ -80659,6 +96658,7 @@ var ts; compareIdentifiers(s1.name, s2.name); }); } + /* internal */ // Exported for testing function compareModuleSpecifiers(m1, m2) { var name1 = getExternalModuleName(m1); var name2 = getExternalModuleName(m2); @@ -80672,6 +96672,7 @@ var ts; } })(OrganizeImports = ts.OrganizeImports || (ts.OrganizeImports = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var OutliningElementsCollector; @@ -80702,7 +96703,7 @@ var ts; } var lastImport = current - 1; if (lastImport !== firstImport) { - out.push(createOutliningSpanFromBounds(ts.findChildOfKind(statements[firstImport], 91, sourceFile).getStart(sourceFile), statements[lastImport].getEnd(), "imports")); + out.push(createOutliningSpanFromBounds(ts.findChildOfKind(statements[firstImport], 91 /* ImportKeyword */, sourceFile).getStart(sourceFile), statements[lastImport].getEnd(), "imports" /* Imports */)); } } function visitNonImportNode(n) { @@ -80717,6 +96718,7 @@ var ts; out.push(span); depthRemaining--; if (ts.isIfStatement(n) && n.elseStatement && ts.isIfStatement(n.elseStatement)) { + // Consider an 'else if' to be on the same depth as the 'if'. visitNonImportNode(n.expression); visitNonImportNode(n.thenStatement); depthRemaining++; @@ -80742,7 +96744,7 @@ var ts; } if (!result[1]) { var span = ts.createTextSpanFromBounds(sourceFile.text.indexOf("//", currentLineStart), lineEnd); - regions.push(createOutliningSpan(span, "region", span, false, result[2] || "#region")); + regions.push(createOutliningSpan(span, "region" /* Region */, span, /*autoCollapse*/ false, result[2] || "#region")); } else { var region = regions.pop(); @@ -80765,16 +96767,18 @@ var ts; var _a = comments_3[_i], kind = _a.kind, pos = _a.pos, end = _a.end; cancellationToken.throwIfCancellationRequested(); switch (kind) { - case 2: + case 2 /* SingleLineCommentTrivia */: + // For single line comments, combine consecutive ones (2 or more) into + // a single span from the start of the first till the end of the last if (singleLineCommentCount === 0) { firstSingleLineCommentStart = pos; } lastSingleLineCommentEnd = end; singleLineCommentCount++; break; - case 3: + case 3 /* MultiLineCommentTrivia */: combineAndAddMultipleSingleLineComments(); - out.push(createOutliningSpanFromBounds(pos, end, "comment")); + out.push(createOutliningSpanFromBounds(pos, end, "comment" /* Comment */)); singleLineCommentCount = 0; break; default: @@ -80783,8 +96787,9 @@ var ts; } combineAndAddMultipleSingleLineComments(); function combineAndAddMultipleSingleLineComments() { + // Only outline spans of two or more consecutive single line comments if (singleLineCommentCount > 1) { - out.push(createOutliningSpanFromBounds(firstSingleLineCommentStart, lastSingleLineCommentEnd, "comment")); + out.push(createOutliningSpanFromBounds(firstSingleLineCommentStart, lastSingleLineCommentEnd, "comment" /* Comment */)); } } } @@ -80793,59 +96798,69 @@ var ts; } function getOutliningSpanForNode(n, sourceFile) { switch (n.kind) { - case 213: + case 213 /* Block */: if (ts.isFunctionBlock(n)) { - return spanForNode(n.parent, n.parent.kind !== 193); + return spanForNode(n.parent, /*autoCollapse*/ n.parent.kind !== 193 /* ArrowFunction */); } + // Check if the block is standalone, or 'attached' to some parent statement. + // If the latter, we want to collapse the block, but consider its hint span + // to be the entire span of the parent. switch (n.parent.kind) { - case 218: - case 221: - case 222: - case 220: - case 217: - case 219: - case 226: - case 269: + case 218 /* DoStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 220 /* ForStatement */: + case 217 /* IfStatement */: + case 219 /* WhileStatement */: + case 226 /* WithStatement */: + case 269 /* CatchClause */: return spanForNode(n.parent); - case 230: + case 230 /* TryStatement */: + // Could be the try-block, or the finally-block. var tryStatement = n.parent; if (tryStatement.tryBlock === n) { return spanForNode(n.parent); } else if (tryStatement.finallyBlock === n) { - return spanForNode(ts.findChildOfKind(tryStatement, 87, sourceFile)); + return spanForNode(ts.findChildOfKind(tryStatement, 87 /* FinallyKeyword */, sourceFile)); } + // falls through default: - return createOutliningSpan(ts.createTextSpanFromNode(n, sourceFile), "code"); + // Block was a standalone block. In this case we want to only collapse + // the span of the block, independent of any parent span. + return createOutliningSpan(ts.createTextSpanFromNode(n, sourceFile), "code" /* Code */); } - case 240: + case 240 /* ModuleBlock */: return spanForNode(n.parent); - case 235: - case 236: - case 238: - case 241: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: + case 238 /* EnumDeclaration */: + case 241 /* CaseBlock */: return spanForNode(n); - case 184: + case 184 /* ObjectLiteralExpression */: return spanForObjectOrArrayLiteral(n); - case 183: - return spanForObjectOrArrayLiteral(n, 21); + case 183 /* ArrayLiteralExpression */: + return spanForObjectOrArrayLiteral(n, 21 /* OpenBracketToken */); } function spanForObjectOrArrayLiteral(node, open) { - if (open === void 0) { open = 17; } - return spanForNode(node, false, !ts.isArrayLiteralExpression(node.parent), open); + if (open === void 0) { open = 17 /* OpenBraceToken */; } + // If the block has no leading keywords and is inside an array literal, + // we only want to collapse the span of the block. + // Otherwise, the collapsed section will include the end of the previous line. + return spanForNode(node, /*autoCollapse*/ false, /*useFullStart*/ !ts.isArrayLiteralExpression(node.parent), open); } function spanForNode(hintSpanNode, autoCollapse, useFullStart, open) { if (autoCollapse === void 0) { autoCollapse = false; } if (useFullStart === void 0) { useFullStart = true; } - if (open === void 0) { open = 17; } + if (open === void 0) { open = 17 /* OpenBraceToken */; } var openToken = ts.findChildOfKind(n, open, sourceFile); - var close = open === 17 ? 18 : 22; + var close = open === 17 /* OpenBraceToken */ ? 18 /* CloseBraceToken */ : 22 /* CloseBracketToken */; var closeToken = ts.findChildOfKind(n, close, sourceFile); if (!openToken || !closeToken) { return undefined; } var textSpan = ts.createTextSpanFromBounds(useFullStart ? openToken.getFullStart() : openToken.getStart(sourceFile), closeToken.getEnd()); - return createOutliningSpan(textSpan, "code", ts.createTextSpanFromNode(hintSpanNode, sourceFile), autoCollapse); + return createOutliningSpan(textSpan, "code" /* Code */, ts.createTextSpanFromNode(hintSpanNode, sourceFile), autoCollapse); } } function createOutliningSpan(textSpan, kind, hintSpan, autoCollapse, bannerText) { @@ -80856,8 +96871,10 @@ var ts; } })(OutliningElementsCollector = ts.OutliningElementsCollector || (ts.OutliningElementsCollector = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { + // Note(cyrusn): this enum is ordered from strongest match type to weakest match type. var PatternMatchKind; (function (PatternMatchKind) { PatternMatchKind[PatternMatchKind["exact"] = 0] = "exact"; @@ -80872,8 +96889,13 @@ var ts; }; } function createPatternMatcher(pattern) { + // We'll often see the same candidate string many times when searching (For example, when + // we see the name of a module that is used everywhere, or the name of an overload). As + // such, we cache the information we compute about the candidate for the life of this + // pattern matcher so we don't have to compute it multiple times. var stringToWordSpans = ts.createMap(); var dotSeparatedSegments = pattern.trim().split(".").map(function (p) { return createSegment(p.trim()); }); + // A segment is considered invalid if we couldn't find any words in it. if (dotSeparatedSegments.some(function (segment) { return !segment.subWordTextChunks.length; })) return undefined; return { @@ -80884,12 +96906,19 @@ var ts; } ts.createPatternMatcher = createPatternMatcher; function getFullMatch(candidateContainers, candidate, dotSeparatedSegments, stringToWordSpans) { + // First, check that the last part of the dot separated pattern matches the name of the + // candidate. If not, then there's no point in proceeding and doing the more + // expensive work. var candidateMatch = matchSegment(candidate, ts.last(dotSeparatedSegments), stringToWordSpans); if (!candidateMatch) { return undefined; } candidateContainers = candidateContainers || []; + // -1 because the last part was checked against the name, and only the rest + // of the parts are checked against the container. if (dotSeparatedSegments.length - 1 > candidateContainers.length) { + // There weren't enough container parts to match against the pattern parts. + // So this definitely doesn't match. return undefined; } var bestMatch; @@ -80908,30 +96937,49 @@ var ts; function matchTextChunk(candidate, chunk, stringToWordSpans) { var index = indexOfIgnoringCase(candidate, chunk.textLowerCase); if (index === 0) { - return createPatternMatch(chunk.text.length === candidate.length ? PatternMatchKind.exact : PatternMatchKind.prefix, ts.startsWith(candidate, chunk.text)); + // a) Check if the word is a prefix of the candidate, in a case insensitive or + // sensitive manner. If it does, return that there was an exact match if the word and candidate are the same length, else a prefix match. + return createPatternMatch(chunk.text.length === candidate.length ? PatternMatchKind.exact : PatternMatchKind.prefix, /*isCaseSensitive:*/ ts.startsWith(candidate, chunk.text)); } if (chunk.isLowerCase) { if (index === -1) return undefined; + // b) If the part is entirely lowercase, then check if it is contained anywhere in the + // candidate in a case insensitive manner. If so, return that there was a substring + // match. + // + // Note: We only have a substring match if the lowercase part is prefix match of some + // word part. That way we don't match something like 'Class' when the user types 'a'. + // But we would match 'FooAttribute' (since 'Attribute' starts with 'a'). var wordSpans = getWordSpans(candidate, stringToWordSpans); for (var _i = 0, wordSpans_1 = wordSpans; _i < wordSpans_1.length; _i++) { var span = wordSpans_1[_i]; - if (partStartsWith(candidate, span, chunk.text, true)) { - return createPatternMatch(PatternMatchKind.substring, partStartsWith(candidate, span, chunk.text, false)); + if (partStartsWith(candidate, span, chunk.text, /*ignoreCase:*/ true)) { + return createPatternMatch(PatternMatchKind.substring, /*isCaseSensitive:*/ partStartsWith(candidate, span, chunk.text, /*ignoreCase:*/ false)); } } + // c) Is the pattern a substring of the candidate starting on one of the candidate's word boundaries? + // We could check every character boundary start of the candidate for the pattern. However, that's + // an m * n operation in the wost case. Instead, find the first instance of the pattern + // substring, and see if it starts on a capital letter. It seems unlikely that the user will try to + // filter the list based on a substring that starts on a capital letter and also with a lowercase one. + // (Pattern: fogbar, Candidate: quuxfogbarFogBar). if (chunk.text.length < candidate.length && isUpperCaseLetter(candidate.charCodeAt(index))) { - return createPatternMatch(PatternMatchKind.substring, false); + return createPatternMatch(PatternMatchKind.substring, /*isCaseSensitive:*/ false); } } else { + // d) If the part was not entirely lowercase, then check if it is contained in the + // candidate in a case *sensitive* manner. If so, return that there was a substring + // match. if (candidate.indexOf(chunk.text) > 0) { - return createPatternMatch(PatternMatchKind.substring, true); + return createPatternMatch(PatternMatchKind.substring, /*isCaseSensitive:*/ true); } + // e) If the part was not entirely lowercase, then attempt a camel cased match as well. if (chunk.characterSpans.length > 0) { var candidateParts = getWordSpans(candidate, stringToWordSpans); - var isCaseSensitive = tryCamelCaseMatch(candidate, candidateParts, chunk, false) ? true - : tryCamelCaseMatch(candidate, candidateParts, chunk, true) ? false : undefined; + var isCaseSensitive = tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ false) ? true + : tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ true) ? false : undefined; if (isCaseSensitive !== undefined) { return createPatternMatch(PatternMatchKind.camelCase, isCaseSensitive); } @@ -80939,11 +96987,53 @@ var ts; } } function matchSegment(candidate, segment, stringToWordSpans) { - if (every(segment.totalTextChunk.text, function (ch) { return ch !== 32 && ch !== 42; })) { + // First check if the segment matches as is. This is also useful if the segment contains + // characters we would normally strip when splitting into parts that we also may want to + // match in the candidate. For example if the segment is "@int" and the candidate is + // "@int", then that will show up as an exact match here. + // + // Note: if the segment contains a space or an asterisk then we must assume that it's a + // multi-word segment. + if (every(segment.totalTextChunk.text, function (ch) { return ch !== 32 /* space */ && ch !== 42 /* asterisk */; })) { var match = matchTextChunk(candidate, segment.totalTextChunk, stringToWordSpans); if (match) return match; } + // The logic for pattern matching is now as follows: + // + // 1) Break the segment passed in into words. Breaking is rather simple and a + // good way to think about it that if gives you all the individual alphanumeric words + // of the pattern. + // + // 2) For each word try to match the word against the candidate value. + // + // 3) Matching is as follows: + // + // a) Check if the word is a prefix of the candidate, in a case insensitive or + // sensitive manner. If it does, return that there was an exact match if the word and candidate are the same length, else a prefix match. + // + // If the word is entirely lowercase: + // b) Then check if it is contained anywhere in the + // candidate in a case insensitive manner. If so, return that there was a substring + // match. + // + // Note: We only have a substring match if the lowercase part is prefix match of + // some word part. That way we don't match something like 'Class' when the user + // types 'a'. But we would match 'FooAttribute' (since 'Attribute' starts with + // 'a'). + // + // c) The word is all lower case. Is it a case insensitive substring of the candidate starting + // on a part boundary of the candidate? + // + // Else: + // d) If the word was not entirely lowercase, then check if it is contained in the + // candidate in a case *sensitive* manner. If so, return that there was a substring + // match. + // + // e) If the word was not entirely lowercase, then attempt a camel cased match as + // well. + // + // Only if all words have some sort of match is the pattern considered matched. var subWordTextChunks = segment.subWordTextChunks; var bestMatch; for (var _i = 0, subWordTextChunks_1 = subWordTextChunks; _i < subWordTextChunks_1.length; _i++) { @@ -80956,12 +97046,12 @@ var ts; return ts.min(a, b, compareMatches); } function compareMatches(a, b) { - return a === undefined ? 1 : b === undefined ? -1 + return a === undefined ? 1 /* GreaterThan */ : b === undefined ? -1 /* LessThan */ : ts.compareValues(a.kind, b.kind) || ts.compareBooleans(!a.isCaseSensitive, !b.isCaseSensitive); } function partStartsWith(candidate, candidateSpan, pattern, ignoreCase, patternSpan) { if (patternSpan === void 0) { patternSpan = { start: 0, length: pattern.length }; } - return patternSpan.length <= candidateSpan.length + return patternSpan.length <= candidateSpan.length // If pattern part is longer than the candidate part there can never be a match. && everyInRange(0, patternSpan.length, function (i) { return equalChars(pattern.charCodeAt(patternSpan.start + i), candidate.charCodeAt(candidateSpan.start + i), ignoreCase); }); } function equalChars(ch1, ch2, ignoreCase) { @@ -80969,22 +97059,35 @@ var ts; } function tryCamelCaseMatch(candidate, candidateParts, chunk, ignoreCase) { var chunkCharacterSpans = chunk.characterSpans; + // Note: we may have more pattern parts than candidate parts. This is because multiple + // pattern parts may match a candidate part. For example "SiUI" against "SimpleUI". + // We'll have 3 pattern parts Si/U/I against two candidate parts Simple/UI. However, U + // and I will both match in UI. var currentCandidate = 0; var currentChunkSpan = 0; var firstMatch; var contiguous; while (true) { + // Let's consider our termination cases if (currentChunkSpan === chunkCharacterSpans.length) { return true; } else if (currentCandidate === candidateParts.length) { + // No match, since we still have more of the pattern to hit return false; } var candidatePart = candidateParts[currentCandidate]; var gotOneMatchThisCandidate = false; + // Consider the case of matching SiUI against SimpleUIElement. The candidate parts + // will be Simple/UI/Element, and the pattern parts will be Si/U/I. We'll match 'Si' + // against 'Simple' first. Then we'll match 'U' against 'UI'. However, we want to + // still keep matching pattern parts against that candidate part. for (; currentChunkSpan < chunkCharacterSpans.length; currentChunkSpan++) { var chunkCharacterSpan = chunkCharacterSpans[currentChunkSpan]; if (gotOneMatchThisCandidate) { + // We've already gotten one pattern part match in this candidate. We will + // only continue trying to consumer pattern parts if the last part and this + // part are both upper case. if (!isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan - 1].start)) || !isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan].start))) { break; @@ -80995,12 +97098,20 @@ var ts; } gotOneMatchThisCandidate = true; firstMatch = firstMatch === undefined ? currentCandidate : firstMatch; + // If we were contiguous, then keep that value. If we weren't, then keep that + // value. If we don't know, then set the value to 'true' as an initial match is + // obviously contiguous. contiguous = contiguous === undefined ? true : contiguous; candidatePart = ts.createTextSpan(candidatePart.start + chunkCharacterSpan.length, candidatePart.length - chunkCharacterSpan.length); } + // Check if we matched anything at all. If we didn't, then we need to unset the + // contiguous bit if we currently had it set. + // If we haven't set the bit yet, then that means we haven't matched anything so + // far, and we don't want to change that. if (!gotOneMatchThisCandidate && contiguous !== undefined) { contiguous = false; } + // Move onto the next candidate. currentCandidate++; } } @@ -81011,25 +97122,32 @@ var ts; }; } function isUpperCaseLetter(ch) { - if (ch >= 65 && ch <= 90) { + // Fast check for the ascii range. + if (ch >= 65 /* A */ && ch <= 90 /* Z */) { return true; } - if (ch < 127 || !ts.isUnicodeIdentifierStart(ch, 6)) { + if (ch < 127 /* maxAsciiCharacter */ || !ts.isUnicodeIdentifierStart(ch, 6 /* Latest */)) { return false; } + // TODO: find a way to determine this for any unicode characters in a + // non-allocating manner. var str = String.fromCharCode(ch); return str === str.toUpperCase(); } function isLowerCaseLetter(ch) { - if (ch >= 97 && ch <= 122) { + // Fast check for the ascii range. + if (ch >= 97 /* a */ && ch <= 122 /* z */) { return true; } - if (ch < 127 || !ts.isUnicodeIdentifierStart(ch, 6)) { + if (ch < 127 /* maxAsciiCharacter */ || !ts.isUnicodeIdentifierStart(ch, 6 /* Latest */)) { return false; } + // TODO: find a way to determine this for any unicode characters in a + // non-allocating manner. var str = String.fromCharCode(ch); return str === str.toLowerCase(); } + // Assumes 'value' is already lowercase. function indexOfIgnoringCase(str, value) { var n = str.length - value.length; var _loop_17 = function (start) { @@ -81045,19 +97163,23 @@ var ts; return -1; } function toLowerCase(ch) { - if (ch >= 65 && ch <= 90) { - return 97 + (ch - 65); + // Fast convert for the ascii range. + if (ch >= 65 /* A */ && ch <= 90 /* Z */) { + return 97 /* a */ + (ch - 65 /* A */); } - if (ch < 127) { + if (ch < 127 /* maxAsciiCharacter */) { return ch; } + // TODO: find a way to compute this for any unicode characters in a + // non-allocating manner. return String.fromCharCode(ch).toLowerCase().charCodeAt(0); } function isDigit(ch) { - return ch >= 48 && ch <= 57; + // TODO(cyrusn): Find a way to support this for unicode digits. + return ch >= 48 /* _0 */ && ch <= 57 /* _9 */; } function isWordChar(ch) { - return isUpperCaseLetter(ch) || isLowerCaseLetter(ch) || isDigit(ch) || ch === 95 || ch === 36; + return isUpperCaseLetter(ch) || isLowerCaseLetter(ch) || isDigit(ch) || ch === 95 /* _ */ || ch === 36 /* $ */; } function breakPatternIntoTextChunks(pattern) { var result = []; @@ -81092,12 +97214,12 @@ var ts; characterSpans: breakIntoCharacterSpans(text) }; } - function breakIntoCharacterSpans(identifier) { - return breakIntoSpans(identifier, false); + /* @internal */ function breakIntoCharacterSpans(identifier) { + return breakIntoSpans(identifier, /*word:*/ false); } ts.breakIntoCharacterSpans = breakIntoCharacterSpans; - function breakIntoWordSpans(identifier) { - return breakIntoSpans(identifier, true); + /* @internal */ function breakIntoWordSpans(identifier) { + return breakIntoSpans(identifier, /*word:*/ true); } ts.breakIntoWordSpans = breakIntoWordSpans; function breakIntoSpans(identifier, word) { @@ -81126,37 +97248,51 @@ var ts; } function charIsPunctuation(ch) { switch (ch) { - case 33: - case 34: - case 35: - case 37: - case 38: - case 39: - case 40: - case 41: - case 42: - case 44: - case 45: - case 46: - case 47: - case 58: - case 59: - case 63: - case 64: - case 91: - case 92: - case 93: - case 95: - case 123: - case 125: + case 33 /* exclamation */: + case 34 /* doubleQuote */: + case 35 /* hash */: + case 37 /* percent */: + case 38 /* ampersand */: + case 39 /* singleQuote */: + case 40 /* openParen */: + case 41 /* closeParen */: + case 42 /* asterisk */: + case 44 /* comma */: + case 45 /* minus */: + case 46 /* dot */: + case 47 /* slash */: + case 58 /* colon */: + case 59 /* semicolon */: + case 63 /* question */: + case 64 /* at */: + case 91 /* openBracket */: + case 92 /* backslash */: + case 93 /* closeBracket */: + case 95 /* _ */: + case 123 /* openBrace */: + case 125 /* closeBrace */: return true; } return false; } function isAllPunctuation(identifier, start, end) { - return every(identifier, function (ch) { return charIsPunctuation(ch) && ch !== 95; }, start, end); + return every(identifier, function (ch) { return charIsPunctuation(ch) && ch !== 95 /* _ */; }, start, end); } function transitionFromUpperToLower(identifier, index, wordStart) { + // Cases this supports: + // 1) IDisposable -> I, Disposable + // 2) UIElement -> UI, Element + // 3) HTMLDocument -> HTML, Document + // + // etc. + // We have a transition from an upper to a lower letter here. But we only + // want to break if all the letters that preceded are uppercase. i.e. if we + // have "Foo" we don't want to break that into "F, oo". But if we have + // "IFoo" or "UIFoo", then we want to break that into "I, Foo" and "UI, + // Foo". i.e. the last uppercase letter belongs to the lowercase letters + // that follows. Note: this will make the following not split properly: + // "HELLOthere". However, these sorts of names do not show up in .Net + // programs. return index !== wordStart && index + 1 < identifier.length && isUpperCaseLetter(identifier.charCodeAt(index)) @@ -81166,6 +97302,19 @@ var ts; function transitionFromLowerToUpper(identifier, word, index) { var lastIsUpper = isUpperCaseLetter(identifier.charCodeAt(index - 1)); var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index)); + // See if the casing indicates we're starting a new word. Note: if we're breaking on + // words, then just seeing an upper case character isn't enough. Instead, it has to + // be uppercase and the previous character can't be uppercase. + // + // For example, breaking "AddMetadata" on words would make: Add Metadata + // + // on characters would be: A dd M etadata + // + // Break "AM" on words would be: AM + // + // on characters would be: A M + // + // We break the search string on characters. But we break the symbol name on words. return currentIsUpper && (!word || !lastIsUpper); } function everyInRange(start, end, pred) { @@ -81188,7 +97337,7 @@ var ts; if (readImportFiles === void 0) { readImportFiles = true; } if (detectJavaScriptImports === void 0) { detectJavaScriptImports = false; } var pragmaContext = { - languageVersion: 1, + languageVersion: 1 /* ES5 */, pragmas: undefined, checkJsDirective: undefined, referencedFiles: [], @@ -81203,14 +97352,16 @@ var ts; var lastToken; var currentToken; var braceNesting = 0; + // assume that text represent an external module if it contains at least one top level import/export + // ambient modules that are found inside external modules are interpreted as module augmentations var externalModule = false; function nextToken() { lastToken = currentToken; currentToken = ts.scanner.scan(); - if (currentToken === 17) { + if (currentToken === 17 /* OpenBraceToken */) { braceNesting++; } - else if (currentToken === 18) { + else if (currentToken === 18 /* CloseBraceToken */) { braceNesting--; } return currentToken; @@ -81235,13 +97386,17 @@ var ts; externalModule = true; } } + /** + * Returns true if at least one token was consumed from the stream + */ function tryConsumeDeclare() { var token = ts.scanner.getToken(); - if (token === 124) { + if (token === 124 /* DeclareKeyword */) { + // declare module "mod" token = nextToken(); - if (token === 129) { + if (token === 129 /* ModuleKeyword */) { token = nextToken(); - if (token === 9) { + if (token === 9 /* StringLiteral */) { recordAmbientExternalModule(); } } @@ -81249,70 +97404,84 @@ var ts; } return false; } + /** + * Returns true if at least one token was consumed from the stream + */ function tryConsumeImport() { - if (lastToken === 23) { + if (lastToken === 23 /* DotToken */) { return false; } var token = ts.scanner.getToken(); - if (token === 91) { + if (token === 91 /* ImportKeyword */) { token = nextToken(); - if (token === 19) { + if (token === 19 /* OpenParenToken */) { token = nextToken(); - if (token === 9) { + if (token === 9 /* StringLiteral */) { + // import("mod"); recordModuleName(); return true; } } - else if (token === 9) { + else if (token === 9 /* StringLiteral */) { + // import "mod"; recordModuleName(); return true; } else { - if (token === 71 || ts.isKeyword(token)) { + if (token === 71 /* Identifier */ || ts.isKeyword(token)) { token = nextToken(); - if (token === 143) { + if (token === 143 /* FromKeyword */) { token = nextToken(); - if (token === 9) { + if (token === 9 /* StringLiteral */) { + // import d from "mod"; recordModuleName(); return true; } } - else if (token === 58) { - if (tryConsumeRequireCall(true)) { + else if (token === 58 /* EqualsToken */) { + if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) { return true; } } - else if (token === 26) { + else if (token === 26 /* CommaToken */) { + // consume comma and keep going token = nextToken(); } else { + // unknown syntax return true; } } - if (token === 17) { + if (token === 17 /* OpenBraceToken */) { token = nextToken(); - while (token !== 18 && token !== 1) { + // consume "{ a as B, c, d as D}" clauses + // make sure that it stops on EOF + while (token !== 18 /* CloseBraceToken */ && token !== 1 /* EndOfFileToken */) { token = nextToken(); } - if (token === 18) { + if (token === 18 /* CloseBraceToken */) { token = nextToken(); - if (token === 143) { + if (token === 143 /* FromKeyword */) { token = nextToken(); - if (token === 9) { + if (token === 9 /* StringLiteral */) { + // import {a as A} from "mod"; + // import d, {a, b as B} from "mod" recordModuleName(); } } } } - else if (token === 39) { + else if (token === 39 /* AsteriskToken */) { token = nextToken(); - if (token === 118) { + if (token === 118 /* AsKeyword */) { token = nextToken(); - if (token === 71 || ts.isKeyword(token)) { + if (token === 71 /* Identifier */ || ts.isKeyword(token)) { token = nextToken(); - if (token === 143) { + if (token === 143 /* FromKeyword */) { token = nextToken(); - if (token === 9) { + if (token === 9 /* StringLiteral */) { + // import * as NS from "mod" + // import d, * as NS from "mod" recordModuleName(); } } @@ -81326,39 +97495,44 @@ var ts; } function tryConsumeExport() { var token = ts.scanner.getToken(); - if (token === 84) { + if (token === 84 /* ExportKeyword */) { markAsExternalModuleIfTopLevel(); token = nextToken(); - if (token === 17) { + if (token === 17 /* OpenBraceToken */) { token = nextToken(); - while (token !== 18 && token !== 1) { + // consume "{ a as B, c, d as D}" clauses + // make sure it stops on EOF + while (token !== 18 /* CloseBraceToken */ && token !== 1 /* EndOfFileToken */) { token = nextToken(); } - if (token === 18) { + if (token === 18 /* CloseBraceToken */) { token = nextToken(); - if (token === 143) { + if (token === 143 /* FromKeyword */) { token = nextToken(); - if (token === 9) { + if (token === 9 /* StringLiteral */) { + // export {a as A} from "mod"; + // export {a, b as B} from "mod" recordModuleName(); } } } } - else if (token === 39) { + else if (token === 39 /* AsteriskToken */) { token = nextToken(); - if (token === 143) { + if (token === 143 /* FromKeyword */) { token = nextToken(); - if (token === 9) { + if (token === 9 /* StringLiteral */) { + // export * from "mod" recordModuleName(); } } } - else if (token === 91) { + else if (token === 91 /* ImportKeyword */) { token = nextToken(); - if (token === 71 || ts.isKeyword(token)) { + if (token === 71 /* Identifier */ || ts.isKeyword(token)) { token = nextToken(); - if (token === 58) { - if (tryConsumeRequireCall(true)) { + if (token === 58 /* EqualsToken */) { + if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) { return true; } } @@ -81370,11 +97544,12 @@ var ts; } function tryConsumeRequireCall(skipCurrentToken) { var token = skipCurrentToken ? nextToken() : ts.scanner.getToken(); - if (token === 133) { + if (token === 133 /* RequireKeyword */) { token = nextToken(); - if (token === 19) { + if (token === 19 /* OpenParenToken */) { token = nextToken(); - if (token === 9) { + if (token === 9 /* StringLiteral */) { + // require("mod"); recordModuleName(); } } @@ -81384,27 +97559,33 @@ var ts; } function tryConsumeDefine() { var token = ts.scanner.getToken(); - if (token === 71 && ts.scanner.getTokenValue() === "define") { + if (token === 71 /* Identifier */ && ts.scanner.getTokenValue() === "define") { token = nextToken(); - if (token !== 19) { + if (token !== 19 /* OpenParenToken */) { return true; } token = nextToken(); - if (token === 9) { + if (token === 9 /* StringLiteral */) { + // looks like define ("modname", ... - skip string literal and comma token = nextToken(); - if (token === 26) { + if (token === 26 /* CommaToken */) { token = nextToken(); } else { + // unexpected token return true; } } - if (token !== 21) { + // should be start of dependency list + if (token !== 21 /* OpenBracketToken */) { return true; } + // skip open bracket token = nextToken(); - while (token !== 22 && token !== 1) { - if (token === 9) { + // scan until ']' or EOF + while (token !== 22 /* CloseBracketToken */ && token !== 1 /* EndOfFileToken */) { + // record string literals as module names + if (token === 9 /* StringLiteral */) { recordModuleName(); } token = nextToken(); @@ -81416,14 +97597,30 @@ var ts; function processImports() { ts.scanner.setText(sourceText); nextToken(); + // Look for: + // import "mod"; + // import d from "mod" + // import {a as A } from "mod"; + // import * as NS from "mod" + // import d, {a, b as B} from "mod" + // import i = require("mod"); + // import("mod"); + // export * from "mod" + // export {a as b} from "mod" + // export import i = require("mod") + // (for JavaScript files) require("mod") + // Do not look for: + // AnySymbol.import("mod") + // AnySymbol.nested.import("mod") while (true) { - if (ts.scanner.getToken() === 1) { + if (ts.scanner.getToken() === 1 /* EndOfFileToken */) { break; } + // check if at least one of alternative have moved scanner forward if (tryConsumeDeclare() || tryConsumeImport() || tryConsumeExport() || - (detectJavaScriptImports && (tryConsumeRequireCall(false) || tryConsumeDefine()))) { + (detectJavaScriptImports && (tryConsumeRequireCall(/*skipCurrentToken*/ false) || tryConsumeDefine()))) { continue; } else { @@ -81438,7 +97635,9 @@ var ts; ts.processCommentPragmas(pragmaContext, sourceText); ts.processPragmasIntoFields(pragmaContext, ts.noop); if (externalModule) { + // for external modules module all nested ambient modules are augmentations if (ambientExternalModules) { + // move all detected ambient modules to imported files since they need to be resolved for (var _i = 0, ambientExternalModules_1 = ambientExternalModules; _i < ambientExternalModules_1.length; _i++) { var decl = ambientExternalModules_1[_i]; importedFiles.push(decl.ref); @@ -81447,6 +97646,7 @@ var ts; return { referencedFiles: pragmaContext.referencedFiles, typeReferenceDirectives: pragmaContext.typeReferenceDirectives, libReferenceDirectives: pragmaContext.libReferenceDirectives, importedFiles: importedFiles, isLibFile: !!pragmaContext.hasNoDefaultLib, ambientExternalModules: undefined }; } else { + // for global scripts ambient modules still can have augmentations - look for ambient modules with depth > 0 var ambientModuleNames = void 0; if (ambientExternalModules) { for (var _a = 0, ambientExternalModules_2 = ambientExternalModules; _a < ambientExternalModules_2.length; _a++) { @@ -81467,6 +97667,7 @@ var ts; } ts.preProcessFile = preProcessFile; })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var Rename; @@ -81492,19 +97693,23 @@ var ts; var symbol = typeChecker.getSymbolAtLocation(node); if (!symbol) return; + // Only allow a symbol to be renamed if it actually has at least one declaration. var declarations = symbol.declarations; if (!declarations || declarations.length === 0) return; + // Disallow rename for elements that are defined in the standard TypeScript library. if (declarations.some(isDefinedInLibraryFile)) { return getRenameInfoError(ts.Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library); } - if (ts.isIdentifier(node) && node.originalKeywordKind === 79 && symbol.parent.flags & 1536) { + // Cannot rename `default` as in `import { default as foo } from "./someModule"; + if (ts.isIdentifier(node) && node.originalKeywordKind === 79 /* DefaultKeyword */ && symbol.parent.flags & 1536 /* Module */) { return undefined; } + // Can't rename a module name. if (ts.isStringLiteralLike(node) && ts.tryGetImportFromModuleSpecifier(node)) return undefined; var kind = ts.SymbolDisplay.getSymbolKind(typeChecker, symbol, node); - var specifierName = (ts.isImportOrExportSpecifierName(node) || ts.isStringOrNumericLiteral(node) && node.parent.kind === 147) + var specifierName = (ts.isImportOrExportSpecifierName(node) || ts.isStringOrNumericLiteral(node) && node.parent.kind === 147 /* ComputedPropertyName */) ? ts.stripQuotes(ts.getTextOfIdentifierOrLiteral(node)) : undefined; var displayName = specifierName || typeChecker.symbolToString(symbol); @@ -81523,6 +97728,7 @@ var ts; }; } function getRenameInfoError(diagnostic) { + // TODO: GH#18217 return { canRename: false, localizedErrorMessage: ts.getLocaleSpecificMessage(diagnostic), @@ -81536,7 +97742,8 @@ var ts; function createTriggerSpanForNode(node, sourceFile) { var start = node.getStart(sourceFile); var width = node.getWidth(sourceFile); - if (node.kind === 9) { + if (node.kind === 9 /* StringLiteral */) { + // Exclude the quotes start += 1; width -= 2; } @@ -81544,11 +97751,11 @@ var ts; } function nodeIsEligibleForRename(node) { switch (node.kind) { - case 71: - case 9: - case 99: + case 71 /* Identifier */: + case 9 /* StringLiteral */: + case 99 /* ThisKeyword */: return true; - case 8: + case 8 /* NumericLiteral */: return ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node); default: return false; @@ -81556,6 +97763,7 @@ var ts; } })(Rename = ts.Rename || (ts.Rename = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var SignatureHelp; @@ -81574,17 +97782,22 @@ var ts; })(InvocationKind || (InvocationKind = {})); function getSignatureHelpItems(program, sourceFile, position, cancellationToken) { var typeChecker = program.getTypeChecker(); + // Decide whether to show signature help var startingToken = ts.findTokenOnLeftOfPosition(sourceFile, position); if (!startingToken) { + // We are at the beginning of the file return undefined; } var argumentInfo = getContainingArgumentInfo(startingToken, position, sourceFile); if (!argumentInfo) return undefined; cancellationToken.throwIfCancellationRequested(); + // Semantic filtering of signature help var candidateInfo = getCandidateInfo(argumentInfo, typeChecker); cancellationToken.throwIfCancellationRequested(); if (!candidateInfo) { + // We didn't have any sig help items produced by the TS compiler. If this is a JS + // file, then see if we can figure out anything better. if (ts.isSourceFileJavaScript(sourceFile)) { return createJavaScriptSignatureHelpItems(argumentInfo, program, cancellationToken); } @@ -81595,19 +97808,20 @@ var ts; SignatureHelp.getSignatureHelpItems = getSignatureHelpItems; function getCandidateInfo(argumentInfo, checker) { var invocation = argumentInfo.invocation; - if (invocation.kind === 0) { + if (invocation.kind === 0 /* Call */) { var candidates = []; - var resolvedSignature = checker.getResolvedSignature(invocation.node, candidates, argumentInfo.argumentCount); + var resolvedSignature = checker.getResolvedSignature(invocation.node, candidates, argumentInfo.argumentCount); // TODO: GH#18217 return candidates.length === 0 ? undefined : { candidates: candidates, resolvedSignature: resolvedSignature }; } else { - var type = checker.getTypeAtLocation(invocation.called); + var type = checker.getTypeAtLocation(invocation.called); // TODO: GH#18217 var signatures = ts.isNewExpression(invocation.called.parent) ? type.getConstructSignatures() : type.getCallSignatures(); var candidates = signatures.filter(function (candidate) { return !!candidate.typeParameters && candidate.typeParameters.length >= argumentInfo.argumentCount; }); return candidates.length === 0 ? undefined : { candidates: candidates, resolvedSignature: ts.first(candidates) }; } } function createJavaScriptSignatureHelpItems(argumentInfo, program, cancellationToken) { + // See if we can find some symbol with the call expression name that has call signatures. var expression = getExpressionFromInvocation(argumentInfo.invocation); var name = ts.isIdentifier(expression) ? expression : ts.isPropertyAccessExpression(expression) ? expression.name : undefined; if (!name || !name.escapedText) { @@ -81647,50 +97861,79 @@ var ts; } function getArgumentInfoForCompletions(node, position, sourceFile) { var info = getImmediatelyContainingArgumentInfo(node, position, sourceFile); - return !info || info.kind === 0 || info.invocation.kind === 1 ? undefined + return !info || info.kind === 0 /* TypeArguments */ || info.invocation.kind === 1 /* TypeArgs */ ? undefined : { invocation: info.invocation.node, argumentCount: info.argumentCount, argumentIndex: info.argumentIndex }; } SignatureHelp.getArgumentInfoForCompletions = getArgumentInfoForCompletions; + /** + * Returns relevant information for the argument list and the current argument if we are + * in the argument of an invocation; returns undefined otherwise. + */ function getImmediatelyContainingArgumentInfo(node, position, sourceFile) { var parent = node.parent; if (ts.isCallOrNewExpression(parent)) { var invocation = parent; var list = void 0; var argumentIndex = void 0; - if (node.kind === 27 || node.kind === 19) { + // There are 3 cases to handle: + // 1. The token introduces a list, and should begin a signature help session + // 2. The token is either not associated with a list, or ends a list, so the session should end + // 3. The token is buried inside a list, and should give signature help + // + // The following are examples of each: + // + // Case 1: + // foo<#T, U>(#a, b) -> The token introduces a list, and should begin a signature help session + // Case 2: + // fo#o#(a, b)# -> The token is either not associated with a list, or ends a list, so the session should end + // Case 3: + // foo(a#, #b#) -> The token is buried inside a list, and should give signature help + // Find out if 'node' is an argument, a type argument, or neither + if (node.kind === 27 /* LessThanToken */ || node.kind === 19 /* OpenParenToken */) { + // Find the list that starts right *after* the < or ( token. + // If the user has just opened a list, consider this item 0. list = getChildListThatStartsWithOpenerToken(parent, node, sourceFile); ts.Debug.assert(list !== undefined); argumentIndex = 0; } else { + // findListItemInfo can return undefined if we are not in parent's argument list + // or type argument list. This includes cases where the cursor is: + // - To the right of the closing parenthesis, non-substitution template, or template tail. + // - Between the type arguments and the arguments (greater than token) + // - On the target of the call (parent.func) + // - On the 'new' keyword in a 'new' expression list = ts.findContainingList(node); if (!list) return undefined; argumentIndex = getArgumentIndex(list, node); } - var kind = parent.typeArguments && parent.typeArguments.pos === list.pos ? 0 : 1; + var kind = parent.typeArguments && parent.typeArguments.pos === list.pos ? 0 /* TypeArguments */ : 1 /* CallArguments */; var argumentCount = getArgumentCount(list); if (argumentIndex !== 0) { ts.Debug.assertLessThan(argumentIndex, argumentCount); } var argumentsSpan = getApplicableSpanForArguments(list, sourceFile); - return { kind: kind, invocation: { kind: 0, node: invocation }, argumentsSpan: argumentsSpan, argumentIndex: argumentIndex, argumentCount: argumentCount }; + return { kind: kind, invocation: { kind: 0 /* Call */, node: invocation }, argumentsSpan: argumentsSpan, argumentIndex: argumentIndex, argumentCount: argumentCount }; } else if (ts.isNoSubstitutionTemplateLiteral(node) && ts.isTaggedTemplateExpression(parent)) { + // Check if we're actually inside the template; + // otherwise we'll fall out and return undefined. if (ts.isInsideTemplateLiteral(node, position, sourceFile)) { - return getArgumentListInfoForTemplate(parent, 0, sourceFile); + return getArgumentListInfoForTemplate(parent, /*argumentIndex*/ 0, sourceFile); } } - else if (ts.isTemplateHead(node) && parent.parent.kind === 189) { + else if (ts.isTemplateHead(node) && parent.parent.kind === 189 /* TaggedTemplateExpression */) { var templateExpression = parent; var tagExpression = templateExpression.parent; - ts.Debug.assert(templateExpression.kind === 202); + ts.Debug.assert(templateExpression.kind === 202 /* TemplateExpression */); var argumentIndex = ts.isInsideTemplateLiteral(node, position, sourceFile) ? 0 : 1; return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile); } else if (ts.isTemplateSpan(parent) && ts.isTaggedTemplateExpression(parent.parent.parent)) { var templateSpan = parent; var tagExpression = parent.parent.parent; + // If we're just after a template tail, don't show signature help. if (ts.isTemplateTail(node) && !ts.isInsideTemplateLiteral(node, position, sourceFile)) { return undefined; } @@ -81699,11 +97942,16 @@ var ts; return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile); } else if (ts.isJsxOpeningLikeElement(parent)) { + // Provide a signature help for JSX opening element or JSX self-closing element. + // This is not guarantee that JSX tag-name is resolved into stateless function component. (that is done in "getSignatureHelpItems") + // i.e + // export function MainButton(props: ButtonProps, context: any): JSX.Element { ... } + // ' 'b'. So, in this case the arg count will be 2. However, there + // is a small subtlety. If you have "Foo(a,)", then the child list will just have + // 'a' ''. So, in the case where the last child is a comma, we increase the + // arg count by one to compensate. + // + // Note: this subtlety only applies to the last comma. If you had "Foo(a,," then + // we'll have: 'a' '' '' + // That will give us 2 non-commas. We then add one for the last comma, giving us an + // arg count of 3. var listChildren = argumentsList.getChildren(); - var argumentCount = ts.countWhere(listChildren, function (arg) { return arg.kind !== 26; }); - if (listChildren.length > 0 && ts.last(listChildren).kind === 26) { + var argumentCount = ts.countWhere(listChildren, function (arg) { return arg.kind !== 26 /* CommaToken */; }); + if (listChildren.length > 0 && ts.last(listChildren).kind === 26 /* CommaToken */) { argumentCount++; } return argumentCount; } + // spanIndex is either the index for a given template span. + // This does not give appropriate results for a NoSubstitutionTemplateLiteral function getArgumentIndexForTemplatePiece(spanIndex, node, position, sourceFile) { + // Because the TemplateStringsArray is the first argument, we have to offset each substitution expression by 1. + // There are three cases we can encounter: + // 1. We are precisely in the template literal (argIndex = 0). + // 2. We are in or to the right of the substitution expression (argIndex = spanIndex + 1). + // 3. We are directly to the right of the template literal, but because we look for the token on the left, + // not enough to put us in the substitution expression; we should consider ourselves part of + // the *next* span's expression by offsetting the index (argIndex = (spanIndex + 1) + 1). + // + // tslint:disable no-double-space + // Example: f `# abcd $#{# 1 + 1# }# efghi ${ #"#hello"# } # ` + // ^ ^ ^ ^ ^ ^ ^ ^ ^ + // Case: 1 1 3 2 1 3 2 2 1 + // tslint:enable no-double-space ts.Debug.assert(position >= node.getStart(), "Assumed 'position' could not occur before node."); if (ts.isTemplateLiteralToken(node)) { if (ts.isInsideTemplateLiteral(node, position, sourceFile)) { @@ -81752,37 +98037,56 @@ var ts; return spanIndex + 1; } function getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile) { + // argumentCount is either 1 or (numSpans + 1) to account for the template strings array argument. var argumentCount = ts.isNoSubstitutionTemplateLiteral(tagExpression.template) ? 1 : tagExpression.template.templateSpans.length + 1; if (argumentIndex !== 0) { ts.Debug.assertLessThan(argumentIndex, argumentCount); } return { - kind: 2, - invocation: { kind: 0, node: tagExpression }, + kind: 2 /* TaggedTemplateArguments */, + invocation: { kind: 0 /* Call */, node: tagExpression }, argumentsSpan: getApplicableSpanForTaggedTemplate(tagExpression, sourceFile), argumentIndex: argumentIndex, argumentCount: argumentCount }; } function getApplicableSpanForArguments(argumentsList, sourceFile) { + // We use full start and skip trivia on the end because we want to include trivia on + // both sides. For example, + // + // foo( /*comment */ a, b, c /*comment*/ ) + // | | + // + // The applicable span is from the first bar to the second bar (inclusive, + // but not including parentheses) var applicableSpanStart = argumentsList.getFullStart(); - var applicableSpanEnd = ts.skipTrivia(sourceFile.text, argumentsList.getEnd(), false); + var applicableSpanEnd = ts.skipTrivia(sourceFile.text, argumentsList.getEnd(), /*stopAfterLineBreak*/ false); return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); } function getApplicableSpanForTaggedTemplate(taggedTemplate, sourceFile) { var template = taggedTemplate.template; var applicableSpanStart = template.getStart(); var applicableSpanEnd = template.getEnd(); - if (template.kind === 202) { + // We need to adjust the end position for the case where the template does not have a tail. + // Otherwise, we will not show signature help past the expression. + // For example, + // + // ` ${ 1 + 1 foo(10) + // | | + // This is because a Missing node has no width. However, what we actually want is to include trivia + // leading up to the next token in case the user is about to type in a TemplateMiddle or TemplateTail. + if (template.kind === 202 /* TemplateExpression */) { var lastSpan = ts.last(template.templateSpans); if (lastSpan.literal.getFullWidth() === 0) { - applicableSpanEnd = ts.skipTrivia(sourceFile.text, applicableSpanEnd, false); + applicableSpanEnd = ts.skipTrivia(sourceFile.text, applicableSpanEnd, /*stopAfterLineBreak*/ false); } } return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); } function getContainingArgumentInfo(node, position, sourceFile) { var _loop_20 = function (n) { + // If the node is not a subspan of its parent, this is a big problem. + // There have been crashes that might be caused by this violation. ts.Debug.assert(ts.rangeContainsRange(n.parent, n), "Not a subspan", function () { return "Child: " + ts.Debug.showSyntaxKind(n) + ", parent: " + ts.Debug.showSyntaxKind(n.parent); }); var argumentInfo = getImmediatelyContainingArgumentInfo(n, position, sourceFile); if (argumentInfo) { @@ -81803,15 +98107,15 @@ var ts; return children[indexOfOpenerToken + 1]; } function getExpressionFromInvocation(invocation) { - return invocation.kind === 0 ? ts.getInvokedExpression(invocation.node) : invocation.called; + return invocation.kind === 0 /* Call */ ? ts.getInvokedExpression(invocation.node) : invocation.called; } - var signatureHelpNodeBuilderFlags = 8192 | 3112960 | 16384; + var signatureHelpNodeBuilderFlags = 8192 /* OmitParameterModifiers */ | 3112960 /* IgnoreErrors */ | 16384 /* UseAliasDefinedOutsideCurrentScope */; function createSignatureHelpItems(candidates, resolvedSignature, argumentListInfo, sourceFile, typeChecker) { var argumentCount = argumentListInfo.argumentCount, applicableSpan = argumentListInfo.argumentsSpan, invocation = argumentListInfo.invocation, argumentIndex = argumentListInfo.argumentIndex; - var isTypeParameterList = argumentListInfo.kind === 0; - var enclosingDeclaration = invocation.kind === 0 ? invocation.node : invocation.called; + var isTypeParameterList = argumentListInfo.kind === 0 /* TypeArguments */; + var enclosingDeclaration = invocation.kind === 0 /* Call */ ? invocation.node : invocation.called; var callTargetSymbol = typeChecker.getSymbolAtLocation(getExpressionFromInvocation(invocation)); - var callTargetDisplayParts = callTargetSymbol && ts.symbolToDisplayParts(typeChecker, callTargetSymbol, undefined, undefined); + var callTargetDisplayParts = callTargetSymbol && ts.symbolToDisplayParts(typeChecker, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined); var printer = ts.createPrinter({ removeComments: true }); var items = candidates.map(function (candidateSignature) { var signatureHelpParameters; @@ -81822,15 +98126,15 @@ var ts; } var isVariadic; if (isTypeParameterList) { - isVariadic = false; - prefixDisplayParts.push(ts.punctuationPart(27)); + isVariadic = false; // type parameter lists are not variadic + prefixDisplayParts.push(ts.punctuationPart(27 /* LessThanToken */)); var typeParameters = (candidateSignature.target || candidateSignature).typeParameters; signatureHelpParameters = typeParameters && typeParameters.length > 0 ? ts.map(typeParameters, createSignatureHelpParameterForTypeParameter) : ts.emptyArray; - suffixDisplayParts.push(ts.punctuationPart(29)); + suffixDisplayParts.push(ts.punctuationPart(29 /* GreaterThanToken */)); var parameterParts = ts.mapToDisplayParts(function (writer) { var thisParameter = candidateSignature.thisParameter ? [typeChecker.symbolToParameterDeclaration(candidateSignature.thisParameter, enclosingDeclaration, signatureHelpNodeBuilderFlags)] : []; var params = ts.createNodeArray(thisParameter.concat(candidateSignature.parameters.map(function (param) { return typeChecker.symbolToParameterDeclaration(param, enclosingDeclaration, signatureHelpNodeBuilderFlags); }))); - printer.writeList(1296, params, sourceFile, writer); + printer.writeList(1296 /* CallExpressionArguments */, params, sourceFile, writer); }); ts.addRange(suffixDisplayParts, parameterParts); } @@ -81839,23 +98143,23 @@ var ts; var typeParameterParts = ts.mapToDisplayParts(function (writer) { if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) { var args = ts.createNodeArray(candidateSignature.typeParameters.map(function (p) { return typeChecker.typeParameterToDeclaration(p, enclosingDeclaration); })); - printer.writeList(26896, args, sourceFile, writer); + printer.writeList(26896 /* TypeParameters */, args, sourceFile, writer); } }); ts.addRange(prefixDisplayParts, typeParameterParts); - prefixDisplayParts.push(ts.punctuationPart(19)); + prefixDisplayParts.push(ts.punctuationPart(19 /* OpenParenToken */)); signatureHelpParameters = ts.map(candidateSignature.parameters, createSignatureHelpParameterForParameter); - suffixDisplayParts.push(ts.punctuationPart(20)); + suffixDisplayParts.push(ts.punctuationPart(20 /* CloseParenToken */)); } var returnTypeParts = ts.mapToDisplayParts(function (writer) { writer.writePunctuation(":"); writer.writeSpace(" "); var predicate = typeChecker.getTypePredicateOfSignature(candidateSignature); if (predicate) { - typeChecker.writeTypePredicate(predicate, enclosingDeclaration, undefined, writer); + typeChecker.writeTypePredicate(predicate, enclosingDeclaration, /*flags*/ undefined, writer); } else { - typeChecker.writeType(typeChecker.getReturnTypeOfSignature(candidateSignature), enclosingDeclaration, undefined, writer); + typeChecker.writeType(typeChecker.getReturnTypeOfSignature(candidateSignature), enclosingDeclaration, /*flags*/ undefined, writer); } }); ts.addRange(suffixDisplayParts, returnTypeParts); @@ -81863,7 +98167,7 @@ var ts; isVariadic: isVariadic, prefixDisplayParts: prefixDisplayParts, suffixDisplayParts: suffixDisplayParts, - separatorDisplayParts: [ts.punctuationPart(26), ts.spacePart()], + separatorDisplayParts: [ts.punctuationPart(26 /* CommaToken */), ts.spacePart()], parameters: signatureHelpParameters, documentation: candidateSignature.getDocumentationComment(typeChecker), tags: candidateSignature.getJsDocTags() @@ -81873,12 +98177,12 @@ var ts; ts.Debug.assertLessThan(argumentIndex, argumentCount); } var selectedItemIndex = candidates.indexOf(resolvedSignature); - ts.Debug.assert(selectedItemIndex !== -1); + ts.Debug.assert(selectedItemIndex !== -1); // If candidates is non-empty it should always include bestSignature. We check for an empty candidates before calling this function. return { items: items, applicableSpan: applicableSpan, selectedItemIndex: selectedItemIndex, argumentIndex: argumentIndex, argumentCount: argumentCount }; function createSignatureHelpParameterForParameter(parameter) { var displayParts = ts.mapToDisplayParts(function (writer) { var param = typeChecker.symbolToParameterDeclaration(parameter, enclosingDeclaration, signatureHelpNodeBuilderFlags); - printer.writeNode(4, param, sourceFile, writer); + printer.writeNode(4 /* Unspecified */, param, sourceFile, writer); }); return { name: parameter.name, @@ -81890,7 +98194,7 @@ var ts; function createSignatureHelpParameterForTypeParameter(typeParameter) { var displayParts = ts.mapToDisplayParts(function (writer) { var param = typeChecker.typeParameterToDeclaration(typeParameter, enclosingDeclaration); - printer.writeNode(4, param, sourceFile, writer); + printer.writeNode(4 /* Unspecified */, param, sourceFile, writer); }); return { name: typeParameter.symbol.name, @@ -81902,6 +98206,7 @@ var ts; } })(SignatureHelp = ts.SignatureHelp || (ts.SignatureHelp = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { function computeSuggestionDiagnostics(sourceFile, program, cancellationToken) { @@ -81934,7 +98239,7 @@ var ts; function check(node) { if (isJsFile) { switch (node.kind) { - case 192: + case 192 /* FunctionExpression */: var decl = ts.getDeclarationOfJSInitializer(node); if (decl) { var symbol_3 = decl.symbol; @@ -81943,7 +98248,8 @@ var ts; break; } } - case 234: + // falls through if no diagnostic was created + case 234 /* FunctionDeclaration */: var symbol = node.symbol; if (symbol.members && (symbol.members.size > 0)) { diags.push(ts.createDiagnosticForNode(ts.isVariableDeclaration(node.parent) ? node.parent.name : node, ts.Diagnostics.This_constructor_function_may_be_converted_to_a_class_declaration)); @@ -81954,10 +98260,10 @@ var ts; else { if (ts.isVariableStatement(node) && node.parent === sourceFile && - node.declarationList.flags & 2 && + node.declarationList.flags & 2 /* Const */ && node.declarationList.declarations.length === 1) { var init = node.declarationList.declarations[0].initializer; - if (init && ts.isRequireCall(init, true)) { + if (init && ts.isRequireCall(init, /*checkArgumentIsStringLiteralLike*/ true)) { diags.push(ts.createDiagnosticForNode(init, ts.Diagnostics.require_call_may_be_converted_to_an_import)); } } @@ -81969,19 +98275,20 @@ var ts; } } ts.computeSuggestionDiagnostics = computeSuggestionDiagnostics; + // convertToEs6Module only works on top-level, so don't trigger it if commonjs code only appears in nested scopes. function containsTopLevelCommonjs(sourceFile) { return sourceFile.statements.some(function (statement) { switch (statement.kind) { - case 214: + case 214 /* VariableStatement */: return statement.declarationList.declarations.some(function (decl) { - return ts.isRequireCall(propertyAccessLeftHandSide(decl.initializer), true); - }); - case 216: { + return ts.isRequireCall(propertyAccessLeftHandSide(decl.initializer), /*checkArgumentIsStringLiteralLike*/ true); + }); // TODO: GH#18217 + case 216 /* ExpressionStatement */: { var expression = statement.expression; if (!ts.isBinaryExpression(expression)) - return ts.isRequireCall(expression, true); + return ts.isRequireCall(expression, /*checkArgumentIsStringLiteralLike*/ true); var kind = ts.getSpecialPropertyAssignmentKind(expression); - return kind === 1 || kind === 2; + return kind === 1 /* ExportsProperty */ || kind === 2 /* ModuleExports */; } default: return false; @@ -81993,12 +98300,12 @@ var ts; } function importNameForConvertToDefaultImport(node) { switch (node.kind) { - case 244: + case 244 /* ImportDeclaration */: var importClause = node.importClause, moduleSpecifier = node.moduleSpecifier; - return importClause && !importClause.name && importClause.namedBindings && importClause.namedBindings.kind === 246 && ts.isStringLiteral(moduleSpecifier) + return importClause && !importClause.name && importClause.namedBindings && importClause.namedBindings.kind === 246 /* NamespaceImport */ && ts.isStringLiteral(moduleSpecifier) ? importClause.namedBindings.name : undefined; - case 243: + case 243 /* ImportEqualsDeclaration */: return node.name; default: return undefined; @@ -82008,119 +98315,130 @@ var ts; return ts.isBinaryExpression(commonJsModuleIndicator) ? commonJsModuleIndicator.left : commonJsModuleIndicator; } })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var SymbolDisplay; (function (SymbolDisplay) { + // TODO(drosen): use contextual SemanticMeaning. function getSymbolKind(typeChecker, symbol, location) { var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location); - if (result !== "") { + if (result !== "" /* unknown */) { return result; } var flags = ts.getCombinedLocalAndExportSymbolFlags(symbol); - if (flags & 32) { - return ts.getDeclarationOfKind(symbol, 205) ? - "local class" : "class"; + if (flags & 32 /* Class */) { + return ts.getDeclarationOfKind(symbol, 205 /* ClassExpression */) ? + "local class" /* localClassElement */ : "class" /* classElement */; } - if (flags & 384) - return "enum"; - if (flags & 524288) - return "type"; - if (flags & 64) - return "interface"; - if (flags & 262144) - return "type parameter"; - if (flags & 262144) - return "type parameter"; - if (flags & 8) - return "enum member"; - if (flags & 2097152) - return "alias"; - if (flags & 1536) - return "module"; + if (flags & 384 /* Enum */) + return "enum" /* enumElement */; + if (flags & 524288 /* TypeAlias */) + return "type" /* typeElement */; + if (flags & 64 /* Interface */) + return "interface" /* interfaceElement */; + if (flags & 262144 /* TypeParameter */) + return "type parameter" /* typeParameterElement */; + if (flags & 262144 /* TypeParameter */) + return "type parameter" /* typeParameterElement */; + if (flags & 8 /* EnumMember */) + return "enum member" /* enumMemberElement */; + if (flags & 2097152 /* Alias */) + return "alias" /* alias */; + if (flags & 1536 /* Module */) + return "module" /* moduleElement */; return result; } SymbolDisplay.getSymbolKind = getSymbolKind; function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location) { var roots = typeChecker.getRootSymbols(symbol); + // If this is a method from a mapped type, leave as a method so long as it still has a call signature. if (roots.length === 1 - && ts.first(roots).flags & 8192 + && ts.first(roots).flags & 8192 /* Method */ + // Ensure the mapped version is still a method, as opposed to `{ [K in keyof I]: number }`. && typeChecker.getTypeOfSymbolAtLocation(symbol, location).getNonNullableType().getCallSignatures().length !== 0) { - return "method"; + return "method" /* memberFunctionElement */; } if (typeChecker.isUndefinedSymbol(symbol)) { - return "var"; + return "var" /* variableElement */; } if (typeChecker.isArgumentsSymbol(symbol)) { - return "local var"; + return "local var" /* localVariableElement */; } - if (location.kind === 99 && ts.isExpression(location)) { - return "parameter"; + if (location.kind === 99 /* ThisKeyword */ && ts.isExpression(location)) { + return "parameter" /* parameterElement */; } var flags = ts.getCombinedLocalAndExportSymbolFlags(symbol); - if (flags & 3) { + if (flags & 3 /* Variable */) { if (ts.isFirstDeclarationOfSymbolParameter(symbol)) { - return "parameter"; + return "parameter" /* parameterElement */; } else if (symbol.valueDeclaration && ts.isConst(symbol.valueDeclaration)) { - return "const"; + return "const" /* constElement */; } else if (ts.forEach(symbol.declarations, ts.isLet)) { - return "let"; + return "let" /* letElement */; } - return isLocalVariableOrFunction(symbol) ? "local var" : "var"; + return isLocalVariableOrFunction(symbol) ? "local var" /* localVariableElement */ : "var" /* variableElement */; } - if (flags & 16) - return isLocalVariableOrFunction(symbol) ? "local function" : "function"; - if (flags & 32768) - return "getter"; - if (flags & 65536) - return "setter"; - if (flags & 8192) - return "method"; - if (flags & 16384) - return "constructor"; - if (flags & 4) { - if (flags & 33554432 && symbol.checkFlags & 6) { + if (flags & 16 /* Function */) + return isLocalVariableOrFunction(symbol) ? "local function" /* localFunctionElement */ : "function" /* functionElement */; + if (flags & 32768 /* GetAccessor */) + return "getter" /* memberGetAccessorElement */; + if (flags & 65536 /* SetAccessor */) + return "setter" /* memberSetAccessorElement */; + if (flags & 8192 /* Method */) + return "method" /* memberFunctionElement */; + if (flags & 16384 /* Constructor */) + return "constructor" /* constructorImplementationElement */; + if (flags & 4 /* Property */) { + if (flags & 33554432 /* Transient */ && symbol.checkFlags & 6 /* Synthetic */) { + // If union property is result of union of non method (property/accessors/variables), it is labeled as property var unionPropertyKind = ts.forEach(typeChecker.getRootSymbols(symbol), function (rootSymbol) { var rootSymbolFlags = rootSymbol.getFlags(); - if (rootSymbolFlags & (98308 | 3)) { - return "property"; + if (rootSymbolFlags & (98308 /* PropertyOrAccessor */ | 3 /* Variable */)) { + return "property" /* memberVariableElement */; } - ts.Debug.assert(!!(rootSymbolFlags & (8192 | 16))); + // May be a Function if this was from `typeof N` with `namespace N { function f();. }`. + ts.Debug.assert(!!(rootSymbolFlags & (8192 /* Method */ | 16 /* Function */))); }); if (!unionPropertyKind) { + // If this was union of all methods, + // make sure it has call signatures before we can label it as method var typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location); if (typeOfUnionProperty.getCallSignatures().length) { - return "method"; + return "method" /* memberFunctionElement */; } - return "property"; + return "property" /* memberVariableElement */; } return unionPropertyKind; } + // If we requested completions after `x.` at the top-level, we may be at a source file location. switch (location.parent && location.parent.kind) { - case 257: - case 255: - case 256: - return location.kind === 71 ? "property" : "JSX attribute"; - case 262: - return "JSX attribute"; + // If we've typed a character of the attribute name, will be 'JsxAttribute', else will be 'JsxOpeningElement'. + case 257 /* JsxOpeningElement */: + case 255 /* JsxElement */: + case 256 /* JsxSelfClosingElement */: + return location.kind === 71 /* Identifier */ ? "property" /* memberVariableElement */ : "JSX attribute" /* jsxAttribute */; + case 262 /* JsxAttribute */: + return "JSX attribute" /* jsxAttribute */; default: - return "property"; + return "property" /* memberVariableElement */; } } - return ""; + return "" /* unknown */; } function getSymbolModifiers(symbol) { var nodeModifiers = symbol && symbol.declarations && symbol.declarations.length > 0 ? ts.getNodeModifiers(symbol.declarations[0]) - : ""; - var symbolModifiers = symbol && symbol.flags & 16777216 ? - "optional" - : ""; + : "" /* none */; + var symbolModifiers = symbol && symbol.flags & 16777216 /* Optional */ ? + "optional" /* optionalModifier */ + : "" /* none */; return nodeModifiers && symbolModifiers ? nodeModifiers + "," + symbolModifiers : nodeModifiers || symbolModifiers; } SymbolDisplay.getSymbolModifiers = getSymbolModifiers; + // TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, enclosingDeclaration, location, semanticMeaning, alias) { if (semanticMeaning === void 0) { semanticMeaning = ts.getMeaningFromLocation(location); } var displayParts = []; @@ -82129,23 +98447,27 @@ var ts; var symbolFlags = ts.getCombinedLocalAndExportSymbolFlags(symbol); var symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location); var hasAddedSymbolInfo = false; - var isThisExpression = location.kind === 99 && ts.isExpression(location); + var isThisExpression = location.kind === 99 /* ThisKeyword */ && ts.isExpression(location); var type; var printer; var documentationFromAlias; var tagsFromAlias; - if (symbolKind !== "" || symbolFlags & 32 || symbolFlags & 2097152) { - if (symbolKind === "getter" || symbolKind === "setter") { - symbolKind = "property"; + // Class at constructor site need to be shown as constructor apart from property,method, vars + if (symbolKind !== "" /* unknown */ || symbolFlags & 32 /* Class */ || symbolFlags & 2097152 /* Alias */) { + // If it is accessor they are allowed only if location is at name of the accessor + if (symbolKind === "getter" /* memberGetAccessorElement */ || symbolKind === "setter" /* memberSetAccessorElement */) { + symbolKind = "property" /* memberVariableElement */; } var signature = void 0; type = isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol.exportSymbol || symbol, location); - if (location.parent && location.parent.kind === 185) { + if (location.parent && location.parent.kind === 185 /* PropertyAccessExpression */) { var right = location.parent.name; + // Either the location is on the right of a property access, or on the left and the right is missing if (right === location || (right && right.getFullWidth() === 0)) { location = location.parent; } } + // try get the call/construct signature from the type if it matches var callExpressionLike = void 0; if (ts.isCallOrNewExpression(location)) { callExpressionLike = location; @@ -82158,23 +98480,26 @@ var ts; } if (callExpressionLike) { var candidateSignatures = []; - signature = typeChecker.getResolvedSignature(callExpressionLike, candidateSignatures); - var useConstructSignatures = callExpressionLike.kind === 188 || (ts.isCallExpression(callExpressionLike) && callExpressionLike.expression.kind === 97); + signature = typeChecker.getResolvedSignature(callExpressionLike, candidateSignatures); // TODO: GH#18217 + var useConstructSignatures = callExpressionLike.kind === 188 /* NewExpression */ || (ts.isCallExpression(callExpressionLike) && callExpressionLike.expression.kind === 97 /* SuperKeyword */); var allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); if (!ts.contains(allSignatures, signature.target) && !ts.contains(allSignatures, signature)) { + // Get the first signature if there is one -- allSignatures may contain + // either the original signature or its target, so check for either signature = allSignatures.length ? allSignatures[0] : undefined; } if (signature) { - if (useConstructSignatures && (symbolFlags & 32)) { - symbolKind = "constructor"; + if (useConstructSignatures && (symbolFlags & 32 /* Class */)) { + // Constructor + symbolKind = "constructor" /* constructorImplementationElement */; addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); } - else if (symbolFlags & 2097152) { - symbolKind = "alias"; + else if (symbolFlags & 2097152 /* Alias */) { + symbolKind = "alias" /* alias */; pushSymbolKind(symbolKind); displayParts.push(ts.spacePart()); if (useConstructSignatures) { - displayParts.push(ts.keywordPart(94)); + displayParts.push(ts.keywordPart(94 /* NewKeyword */)); displayParts.push(ts.spacePart()); } addFullSymbolName(symbol); @@ -82183,139 +98508,154 @@ var ts; addPrefixForAnyFunctionOrVar(symbol, symbolKind); } switch (symbolKind) { - case "JSX attribute": - case "property": - case "var": - case "const": - case "let": - case "parameter": - case "local var": - displayParts.push(ts.punctuationPart(56)); + case "JSX attribute" /* jsxAttribute */: + case "property" /* memberVariableElement */: + case "var" /* variableElement */: + case "const" /* constElement */: + case "let" /* letElement */: + case "parameter" /* parameterElement */: + case "local var" /* localVariableElement */: + // If it is call or construct signature of lambda's write type name + displayParts.push(ts.punctuationPart(56 /* ColonToken */)); displayParts.push(ts.spacePart()); - if (!(ts.getObjectFlags(type) & 16) && type.symbol) { - ts.addRange(displayParts, ts.symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, undefined, 4 | 1)); + if (!(ts.getObjectFlags(type) & 16 /* Anonymous */) && type.symbol) { + ts.addRange(displayParts, ts.symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, 4 /* AllowAnyNodeKind */ | 1 /* WriteTypeParametersOrArguments */)); displayParts.push(ts.lineBreakPart()); } if (useConstructSignatures) { - displayParts.push(ts.keywordPart(94)); + displayParts.push(ts.keywordPart(94 /* NewKeyword */)); displayParts.push(ts.spacePart()); } - addSignatureDisplayParts(signature, allSignatures, 262144); + addSignatureDisplayParts(signature, allSignatures, 262144 /* WriteArrowStyleSignature */); break; default: + // Just signature addSignatureDisplayParts(signature, allSignatures); } hasAddedSymbolInfo = true; } } - else if ((ts.isNameOfFunctionDeclaration(location) && !(symbolFlags & 98304)) || - (location.kind === 123 && location.parent.kind === 155)) { + else if ((ts.isNameOfFunctionDeclaration(location) && !(symbolFlags & 98304 /* Accessor */)) || // name of function declaration + (location.kind === 123 /* ConstructorKeyword */ && location.parent.kind === 155 /* Constructor */)) { // At constructor keyword of constructor declaration + // get the signature from the declaration and write it var functionDeclaration_1 = location.parent; + // Use function declaration to write the signatures only if the symbol corresponding to this declaration var locationIsSymbolDeclaration = ts.find(symbol.declarations, function (declaration) { - return declaration === (location.kind === 123 ? functionDeclaration_1.parent : functionDeclaration_1); + return declaration === (location.kind === 123 /* ConstructorKeyword */ ? functionDeclaration_1.parent : functionDeclaration_1); }); if (locationIsSymbolDeclaration) { - var allSignatures = functionDeclaration_1.kind === 155 ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures(); + var allSignatures = functionDeclaration_1.kind === 155 /* Constructor */ ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures(); if (!typeChecker.isImplementationOfOverload(functionDeclaration_1)) { - signature = typeChecker.getSignatureFromDeclaration(functionDeclaration_1); + signature = typeChecker.getSignatureFromDeclaration(functionDeclaration_1); // TODO: GH#18217 } else { signature = allSignatures[0]; } - if (functionDeclaration_1.kind === 155) { - symbolKind = "constructor"; + if (functionDeclaration_1.kind === 155 /* Constructor */) { + // show (constructor) Type(...) signature + symbolKind = "constructor" /* constructorImplementationElement */; addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); } else { - addPrefixForAnyFunctionOrVar(functionDeclaration_1.kind === 158 && - !(type.symbol.flags & 2048 || type.symbol.flags & 4096) ? type.symbol : symbol, symbolKind); + // (function/method) symbol(..signature) + addPrefixForAnyFunctionOrVar(functionDeclaration_1.kind === 158 /* CallSignature */ && + !(type.symbol.flags & 2048 /* TypeLiteral */ || type.symbol.flags & 4096 /* ObjectLiteral */) ? type.symbol : symbol, symbolKind); } addSignatureDisplayParts(signature, allSignatures); hasAddedSymbolInfo = true; } } } - if (symbolFlags & 32 && !hasAddedSymbolInfo && !isThisExpression) { + if (symbolFlags & 32 /* Class */ && !hasAddedSymbolInfo && !isThisExpression) { addAliasPrefixIfNecessary(); - if (ts.getDeclarationOfKind(symbol, 205)) { - pushSymbolKind("local class"); + if (ts.getDeclarationOfKind(symbol, 205 /* ClassExpression */)) { + // Special case for class expressions because we would like to indicate that + // the class name is local to the class body (similar to function expression) + // (local class) class + pushSymbolKind("local class" /* localClassElement */); } else { - displayParts.push(ts.keywordPart(75)); + // Class declaration has name which is not local. + displayParts.push(ts.keywordPart(75 /* ClassKeyword */)); } displayParts.push(ts.spacePart()); addFullSymbolName(symbol); writeTypeParametersOfSymbol(symbol, sourceFile); } - if ((symbolFlags & 64) && (semanticMeaning & 2)) { + if ((symbolFlags & 64 /* Interface */) && (semanticMeaning & 2 /* Type */)) { prefixNextMeaning(); - displayParts.push(ts.keywordPart(109)); + displayParts.push(ts.keywordPart(109 /* InterfaceKeyword */)); displayParts.push(ts.spacePart()); addFullSymbolName(symbol); writeTypeParametersOfSymbol(symbol, sourceFile); } - if (symbolFlags & 524288) { + if (symbolFlags & 524288 /* TypeAlias */) { prefixNextMeaning(); - displayParts.push(ts.keywordPart(139)); + displayParts.push(ts.keywordPart(139 /* TypeKeyword */)); displayParts.push(ts.spacePart()); addFullSymbolName(symbol); writeTypeParametersOfSymbol(symbol, sourceFile); displayParts.push(ts.spacePart()); - displayParts.push(ts.operatorPart(58)); + displayParts.push(ts.operatorPart(58 /* EqualsToken */)); displayParts.push(ts.spacePart()); - ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, typeChecker.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration, 8388608)); + ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, typeChecker.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration, 8388608 /* InTypeAlias */)); } - if (symbolFlags & 384) { + if (symbolFlags & 384 /* Enum */) { prefixNextMeaning(); if (ts.forEach(symbol.declarations, ts.isConstEnumDeclaration)) { - displayParts.push(ts.keywordPart(76)); + displayParts.push(ts.keywordPart(76 /* ConstKeyword */)); displayParts.push(ts.spacePart()); } - displayParts.push(ts.keywordPart(83)); + displayParts.push(ts.keywordPart(83 /* EnumKeyword */)); displayParts.push(ts.spacePart()); addFullSymbolName(symbol); } - if (symbolFlags & 1536) { + if (symbolFlags & 1536 /* Module */) { prefixNextMeaning(); - var declaration = ts.getDeclarationOfKind(symbol, 239); - var isNamespace = declaration && declaration.name && declaration.name.kind === 71; - displayParts.push(ts.keywordPart(isNamespace ? 130 : 129)); + var declaration = ts.getDeclarationOfKind(symbol, 239 /* ModuleDeclaration */); + var isNamespace = declaration && declaration.name && declaration.name.kind === 71 /* Identifier */; + displayParts.push(ts.keywordPart(isNamespace ? 130 /* NamespaceKeyword */ : 129 /* ModuleKeyword */)); displayParts.push(ts.spacePart()); addFullSymbolName(symbol); } - if ((symbolFlags & 262144) && (semanticMeaning & 2)) { + if ((symbolFlags & 262144 /* TypeParameter */) && (semanticMeaning & 2 /* Type */)) { prefixNextMeaning(); - displayParts.push(ts.punctuationPart(19)); + displayParts.push(ts.punctuationPart(19 /* OpenParenToken */)); displayParts.push(ts.textPart("type parameter")); - displayParts.push(ts.punctuationPart(20)); + displayParts.push(ts.punctuationPart(20 /* CloseParenToken */)); displayParts.push(ts.spacePart()); addFullSymbolName(symbol); if (symbol.parent) { + // Class/Interface type parameter addInPrefix(); addFullSymbolName(symbol.parent, enclosingDeclaration); writeTypeParametersOfSymbol(symbol.parent, enclosingDeclaration); } else { - var decl = ts.getDeclarationOfKind(symbol, 148); + // Method/function type parameter + var decl = ts.getDeclarationOfKind(symbol, 148 /* TypeParameter */); if (decl === undefined) return ts.Debug.fail(); var declaration = decl.parent; if (declaration) { if (ts.isFunctionLikeKind(declaration.kind)) { addInPrefix(); - var signature = typeChecker.getSignatureFromDeclaration(declaration); - if (declaration.kind === 159) { - displayParts.push(ts.keywordPart(94)); + var signature = typeChecker.getSignatureFromDeclaration(declaration); // TODO: GH#18217 + if (declaration.kind === 159 /* ConstructSignature */) { + displayParts.push(ts.keywordPart(94 /* NewKeyword */)); displayParts.push(ts.spacePart()); } - else if (declaration.kind !== 158 && declaration.name) { + else if (declaration.kind !== 158 /* CallSignature */ && declaration.name) { addFullSymbolName(declaration.symbol); } - ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, sourceFile, 32)); + ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, sourceFile, 32 /* WriteTypeArgumentsOfSignature */)); } - else if (declaration.kind === 237) { + else if (declaration.kind === 237 /* TypeAliasDeclaration */) { + // Type alias type parameter + // For example + // type list = T[]; // Both T will go through same code path addInPrefix(); - displayParts.push(ts.keywordPart(139)); + displayParts.push(ts.keywordPart(139 /* TypeKeyword */)); displayParts.push(ts.spacePart()); addFullSymbolName(declaration.symbol); writeTypeParametersOfSymbol(declaration.symbol, sourceFile); @@ -82323,21 +98663,21 @@ var ts; } } } - if (symbolFlags & 8) { - symbolKind = "enum member"; + if (symbolFlags & 8 /* EnumMember */) { + symbolKind = "enum member" /* enumMemberElement */; addPrefixForAnyFunctionOrVar(symbol, "enum member"); var declaration = symbol.declarations[0]; - if (declaration.kind === 273) { + if (declaration.kind === 273 /* EnumMember */) { var constantValue = typeChecker.getConstantValue(declaration); if (constantValue !== undefined) { displayParts.push(ts.spacePart()); - displayParts.push(ts.operatorPart(58)); + displayParts.push(ts.operatorPart(58 /* EqualsToken */)); displayParts.push(ts.spacePart()); displayParts.push(ts.displayPart(ts.getTextOfConstantValue(constantValue), typeof constantValue === "number" ? ts.SymbolDisplayPartKind.numericLiteral : ts.SymbolDisplayPartKind.stringLiteral)); } } } - if (symbolFlags & 2097152) { + if (symbolFlags & 2097152 /* Alias */) { prefixNextMeaning(); if (!hasAddedSymbolInfo) { var resolvedSymbol = typeChecker.getAliasedSymbol(symbol); @@ -82346,7 +98686,7 @@ var ts; var declarationName = ts.getNameOfDeclaration(resolvedNode); if (declarationName) { var isExternalModuleDeclaration = ts.isModuleWithStringLiteralName(resolvedNode) && - ts.hasModifier(resolvedNode, 2); + ts.hasModifier(resolvedNode, 2 /* Ambient */); var shouldUseAliasName = symbol.name !== "default" && !isExternalModuleDeclaration; var resolvedInfo = getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, resolvedSymbol, ts.getSourceFileOfNode(resolvedNode), resolvedNode, declarationName, semanticMeaning, shouldUseAliasName ? symbol : resolvedSymbol); displayParts.push.apply(displayParts, resolvedInfo.displayParts); @@ -82357,41 +98697,41 @@ var ts; } } switch (symbol.declarations[0].kind) { - case 242: - displayParts.push(ts.keywordPart(84)); + case 242 /* NamespaceExportDeclaration */: + displayParts.push(ts.keywordPart(84 /* ExportKeyword */)); displayParts.push(ts.spacePart()); - displayParts.push(ts.keywordPart(130)); + displayParts.push(ts.keywordPart(130 /* NamespaceKeyword */)); break; - case 249: - displayParts.push(ts.keywordPart(84)); + case 249 /* ExportAssignment */: + displayParts.push(ts.keywordPart(84 /* ExportKeyword */)); displayParts.push(ts.spacePart()); - displayParts.push(ts.keywordPart(symbol.declarations[0].isExportEquals ? 58 : 79)); + displayParts.push(ts.keywordPart(symbol.declarations[0].isExportEquals ? 58 /* EqualsToken */ : 79 /* DefaultKeyword */)); break; - case 252: - displayParts.push(ts.keywordPart(84)); + case 252 /* ExportSpecifier */: + displayParts.push(ts.keywordPart(84 /* ExportKeyword */)); break; default: - displayParts.push(ts.keywordPart(91)); + displayParts.push(ts.keywordPart(91 /* ImportKeyword */)); } displayParts.push(ts.spacePart()); addFullSymbolName(symbol); ts.forEach(symbol.declarations, function (declaration) { - if (declaration.kind === 243) { + if (declaration.kind === 243 /* ImportEqualsDeclaration */) { var importEqualsDeclaration = declaration; if (ts.isExternalModuleImportEqualsDeclaration(importEqualsDeclaration)) { displayParts.push(ts.spacePart()); - displayParts.push(ts.operatorPart(58)); + displayParts.push(ts.operatorPart(58 /* EqualsToken */)); displayParts.push(ts.spacePart()); - displayParts.push(ts.keywordPart(133)); - displayParts.push(ts.punctuationPart(19)); + displayParts.push(ts.keywordPart(133 /* RequireKeyword */)); + displayParts.push(ts.punctuationPart(19 /* OpenParenToken */)); displayParts.push(ts.displayPart(ts.getTextOfNode(ts.getExternalModuleImportEqualsDeclarationExpression(importEqualsDeclaration)), ts.SymbolDisplayPartKind.stringLiteral)); - displayParts.push(ts.punctuationPart(20)); + displayParts.push(ts.punctuationPart(20 /* CloseParenToken */)); } else { var internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference); if (internalAliasSymbol) { displayParts.push(ts.spacePart()); - displayParts.push(ts.operatorPart(58)); + displayParts.push(ts.operatorPart(58 /* EqualsToken */)); displayParts.push(ts.spacePart()); addFullSymbolName(internalAliasSymbol, enclosingDeclaration); } @@ -82401,26 +98741,28 @@ var ts; }); } if (!hasAddedSymbolInfo) { - if (symbolKind !== "") { + if (symbolKind !== "" /* unknown */) { if (type) { if (isThisExpression) { prefixNextMeaning(); - displayParts.push(ts.keywordPart(99)); + displayParts.push(ts.keywordPart(99 /* ThisKeyword */)); } else { addPrefixForAnyFunctionOrVar(symbol, symbolKind); } - if (symbolKind === "property" || - symbolKind === "JSX attribute" || - symbolFlags & 3 || - symbolKind === "local var" || + // For properties, variables and local vars: show the type + if (symbolKind === "property" /* memberVariableElement */ || + symbolKind === "JSX attribute" /* jsxAttribute */ || + symbolFlags & 3 /* Variable */ || + symbolKind === "local var" /* localVariableElement */ || isThisExpression) { - displayParts.push(ts.punctuationPart(56)); + displayParts.push(ts.punctuationPart(56 /* ColonToken */)); displayParts.push(ts.spacePart()); - if (type.symbol && type.symbol.flags & 262144) { + // If the type is type parameter, format it specially + if (type.symbol && type.symbol.flags & 262144 /* TypeParameter */) { var typeParameterParts = ts.mapToDisplayParts(function (writer) { var param = typeChecker.typeParameterToDeclaration(type, enclosingDeclaration); - getPrinter().writeNode(4, param, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosingDeclaration)), writer); + getPrinter().writeNode(4 /* Unspecified */, param, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosingDeclaration)), writer); }); ts.addRange(displayParts, typeParameterParts); } @@ -82428,12 +98770,12 @@ var ts; ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, type, enclosingDeclaration)); } } - else if (symbolFlags & 16 || - symbolFlags & 8192 || - symbolFlags & 16384 || - symbolFlags & 131072 || - symbolFlags & 98304 || - symbolKind === "method") { + else if (symbolFlags & 16 /* Function */ || + symbolFlags & 8192 /* Method */ || + symbolFlags & 16384 /* Constructor */ || + symbolFlags & 131072 /* Signature */ || + symbolFlags & 98304 /* Accessor */ || + symbolKind === "method" /* memberFunctionElement */) { var allSignatures = type.getNonNullableType().getCallSignatures(); if (allSignatures.length) { addSignatureDisplayParts(allSignatures[0], allSignatures); @@ -82448,11 +98790,14 @@ var ts; if (!documentation) { documentation = symbol.getDocumentationComment(typeChecker); tags = symbol.getJsDocTags(); - if (documentation.length === 0 && symbolFlags & 4) { - if (symbol.parent && ts.forEach(symbol.parent.declarations, function (declaration) { return declaration.kind === 274; })) { + if (documentation.length === 0 && symbolFlags & 4 /* Property */) { + // For some special property access expressions like `exports.foo = foo` or `module.exports.foo = foo` + // there documentation comments might be attached to the right hand side symbol of their declarations. + // The pattern of such special property access is that the parent symbol is the symbol of the file. + if (symbol.parent && ts.forEach(symbol.parent.declarations, function (declaration) { return declaration.kind === 274 /* SourceFile */; })) { for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var declaration = _a[_i]; - if (!declaration.parent || declaration.parent.kind !== 200) { + if (!declaration.parent || declaration.parent.kind !== 200 /* BinaryExpression */) { continue; } var rhsSymbol = typeChecker.getSymbolAtLocation(declaration.parent.right); @@ -82489,23 +98834,23 @@ var ts; } function addAliasPrefixIfNecessary() { if (alias) { - pushSymbolKind("alias"); + pushSymbolKind("alias" /* alias */); displayParts.push(ts.spacePart()); } } function addInPrefix() { displayParts.push(ts.spacePart()); - displayParts.push(ts.keywordPart(92)); + displayParts.push(ts.keywordPart(92 /* InKeyword */)); displayParts.push(ts.spacePart()); } function addFullSymbolName(symbolToDisplay, enclosingDeclaration) { if (alias && symbolToDisplay === symbol) { symbolToDisplay = alias; } - var fullSymbolDisplayParts = ts.symbolToDisplayParts(typeChecker, symbolToDisplay, enclosingDeclaration || sourceFile, undefined, 1 | 2 | 4); + var fullSymbolDisplayParts = ts.symbolToDisplayParts(typeChecker, symbolToDisplay, enclosingDeclaration || sourceFile, /*meaning*/ undefined, 1 /* WriteTypeParametersOrArguments */ | 2 /* UseOnlyExternalAliasing */ | 4 /* AllowAnyNodeKind */); ts.addRange(displayParts, fullSymbolDisplayParts); - if (symbol.flags & 16777216) { - displayParts.push(ts.punctuationPart(55)); + if (symbol.flags & 16777216 /* Optional */) { + displayParts.push(ts.punctuationPart(55 /* QuestionToken */)); } } function addPrefixForAnyFunctionOrVar(symbol, symbolKind) { @@ -82520,31 +98865,31 @@ var ts; } function pushSymbolKind(symbolKind) { switch (symbolKind) { - case "var": - case "function": - case "let": - case "const": - case "constructor": + case "var" /* variableElement */: + case "function" /* functionElement */: + case "let" /* letElement */: + case "const" /* constElement */: + case "constructor" /* constructorImplementationElement */: displayParts.push(ts.textOrKeywordPart(symbolKind)); return; default: - displayParts.push(ts.punctuationPart(19)); + displayParts.push(ts.punctuationPart(19 /* OpenParenToken */)); displayParts.push(ts.textOrKeywordPart(symbolKind)); - displayParts.push(ts.punctuationPart(20)); + displayParts.push(ts.punctuationPart(20 /* CloseParenToken */)); return; } } function addSignatureDisplayParts(signature, allSignatures, flags) { - if (flags === void 0) { flags = 0; } - ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags | 32)); + if (flags === void 0) { flags = 0 /* None */; } + ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags | 32 /* WriteTypeArgumentsOfSignature */)); if (allSignatures.length > 1) { displayParts.push(ts.spacePart()); - displayParts.push(ts.punctuationPart(19)); - displayParts.push(ts.operatorPart(37)); + displayParts.push(ts.punctuationPart(19 /* OpenParenToken */)); + displayParts.push(ts.operatorPart(37 /* PlusToken */)); displayParts.push(ts.displayPart((allSignatures.length - 1).toString(), ts.SymbolDisplayPartKind.numericLiteral)); displayParts.push(ts.spacePart()); displayParts.push(ts.textPart(allSignatures.length === 2 ? "overload" : "overloads")); - displayParts.push(ts.punctuationPart(20)); + displayParts.push(ts.punctuationPart(20 /* CloseParenToken */)); } documentation = signature.getDocumentationComment(typeChecker); tags = signature.getJsDocTags(); @@ -82552,7 +98897,7 @@ var ts; function writeTypeParametersOfSymbol(symbol, enclosingDeclaration) { var typeParameterParts = ts.mapToDisplayParts(function (writer) { var params = typeChecker.symbolToTypeParameterDeclarations(symbol, enclosingDeclaration); - getPrinter().writeList(26896, params, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosingDeclaration)), writer); + getPrinter().writeList(26896 /* TypeParameters */, params, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosingDeclaration)), writer); }); ts.addRange(displayParts, typeParameterParts); } @@ -82560,20 +98905,24 @@ var ts; SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind; function isLocalVariableOrFunction(symbol) { if (symbol.parent) { - return false; + return false; // This is exported symbol } return ts.forEach(symbol.declarations, function (declaration) { - if (declaration.kind === 192) { + // Function expressions are local + if (declaration.kind === 192 /* FunctionExpression */) { return true; } - if (declaration.kind !== 232 && declaration.kind !== 234) { + if (declaration.kind !== 232 /* VariableDeclaration */ && declaration.kind !== 234 /* FunctionDeclaration */) { return false; } + // If the parent is not sourceFile or module block it is local variable for (var parent = declaration.parent; !ts.isFunctionBlock(parent); parent = parent.parent) { - if (parent.kind === 274 || parent.kind === 240) { + // Reached source file or module block + if (parent.kind === 274 /* SourceFile */ || parent.kind === 240 /* ModuleBlock */) { return false; } } + // parent is in function block return true; }); } @@ -82581,13 +98930,27 @@ var ts; })(ts || (ts = {})); var ts; (function (ts) { + /* + * This function will compile source text from 'input' argument using specified compiler options. + * If not options are provided - it will use a set of default compiler options. + * Extra compiler options that will unconditionally be used by this function are: + * - isolatedModules = true + * - allowNonTsExtensions = true + * - noLib = true + * - noResolve = true + */ function transpileModule(input, transpileOptions) { var diagnostics = []; var options = transpileOptions.compilerOptions ? fixupCompilerOptions(transpileOptions.compilerOptions, diagnostics) : ts.getDefaultCompilerOptions(); options.isolatedModules = true; + // transpileModule does not write anything to disk so there is no need to verify that there are no conflicts between input and output paths. options.suppressOutputPathCheck = true; + // Filename can be non-ts file. options.allowNonTsExtensions = true; + // We are not returning a sourceFile for lib file when asked by the program, + // so pass --noLib to avoid reporting a file not found error. options.noLib = true; + // Clear out other settings that would not be used in transpiling this module options.lib = undefined; options.types = undefined; options.noEmit = undefined; @@ -82598,9 +98961,12 @@ var ts; options.declarationDir = undefined; options.out = undefined; options.outFile = undefined; + // We are not doing a full typecheck, we are not resolving the whole context, + // so pass --noResolve to avoid reporting missing file errors. options.noResolve = true; + // if jsx is specified then treat file as .tsx var inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts"); - var sourceFile = ts.createSourceFile(inputFileName, input, options.target); + var sourceFile = ts.createSourceFile(inputFileName, input, options.target); // TODO: GH#18217 if (transpileOptions.moduleName) { sourceFile.moduleName = transpileOptions.moduleName; } @@ -82608,8 +98974,10 @@ var ts; sourceFile.renamedDependencies = ts.createMapFromTemplate(transpileOptions.renamedDependencies); } var newLine = ts.getNewLineCharacter(options); + // Output var outputText; var sourceMapText; + // Create a compilerHost object to allow the compiler to read and write files var compilerHost = { getSourceFile: function (fileName) { return fileName === ts.normalizePath(inputFileName) ? sourceFile : undefined; }, writeFile: function (name, text) { @@ -82634,23 +99002,31 @@ var ts; }; var program = ts.createProgram([inputFileName], options, compilerHost); if (transpileOptions.reportDiagnostics) { - ts.addRange(diagnostics, program.getSyntacticDiagnostics(sourceFile)); - ts.addRange(diagnostics, program.getOptionsDiagnostics()); + ts.addRange(/*to*/ diagnostics, /*from*/ program.getSyntacticDiagnostics(sourceFile)); + ts.addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics()); } - program.emit(undefined, undefined, undefined, undefined, transpileOptions.transformers); + // Emit + program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ undefined, transpileOptions.transformers); if (outputText === undefined) return ts.Debug.fail("Output generation failed"); return { outputText: outputText, diagnostics: diagnostics, sourceMapText: sourceMapText }; } ts.transpileModule = transpileModule; + /* + * This is a shortcut function for transpileModule - it accepts transpileOptions as parameters and returns only outputText part of the result. + */ function transpile(input, compilerOptions, fileName, diagnostics, moduleName) { var output = transpileModule(input, { compilerOptions: compilerOptions, fileName: fileName, reportDiagnostics: !!diagnostics, moduleName: moduleName }); + // addRange correctly handles cases when wither 'from' or 'to' argument is missing ts.addRange(diagnostics, output.diagnostics); return output.outputText; } ts.transpile = transpile; var commandLineOptionsStringToEnum; + /** JS users may pass in string values for enum compiler options (such as ModuleKind), so convert. */ + /*@internal*/ function fixupCompilerOptions(options, diagnostics) { + // Lazily create this value to fix module loading errors. commandLineOptionsStringToEnum = commandLineOptionsStringToEnum || ts.filter(ts.optionDeclarations, function (o) { return typeof o.type === "object" && !ts.forEachEntry(o.type, function (v) { return typeof v !== "number"; }); }); @@ -82660,11 +99036,14 @@ var ts; return "continue"; } var value = options[opt.name]; + // Value should be a key of opt.type if (ts.isString(value)) { + // If value is not a string, this will fail options[opt.name] = ts.parseCustomTypeOption(opt, value, diagnostics); } else { if (!ts.forEachEntry(opt.type, function (v) { return v === value; })) { + // Supplied value isn't a valid enum value. diagnostics.push(ts.createCompilerDiagnosticForInvalidCustomType(opt)); } } @@ -82677,6 +99056,7 @@ var ts; } ts.fixupCompilerOptions = fixupCompilerOptions; })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var formatting; @@ -82690,7 +99070,7 @@ var ts; FormattingRequestKind[FormattingRequestKind["FormatOnOpeningCurlyBrace"] = 4] = "FormatOnOpeningCurlyBrace"; FormattingRequestKind[FormattingRequestKind["FormatOnClosingCurlyBrace"] = 5] = "FormatOnClosingCurlyBrace"; })(FormattingRequestKind = formatting.FormattingRequestKind || (formatting.FormattingRequestKind = {})); - var FormattingContext = (function () { + var FormattingContext = /** @class */ (function () { function FormattingContext(sourceFile, formattingRequestKind, options) { this.sourceFile = sourceFile; this.formattingRequestKind = formattingRequestKind; @@ -82707,6 +99087,7 @@ var ts; this.nextTokenSpan = nextRange; this.nextTokenParent = nextTokenParent; this.contextNode = commonParent; + // drop cached results this.contextNodeAllOnSameLine = undefined; this.nextNodeAllOnSameLine = undefined; this.tokensAreOnSameLine = undefined; @@ -82751,8 +99132,8 @@ var ts; return startLine === endLine; }; FormattingContext.prototype.BlockIsOnOneLine = function (node) { - var openBrace = ts.findChildOfKind(node, 17, this.sourceFile); - var closeBrace = ts.findChildOfKind(node, 18, this.sourceFile); + var openBrace = ts.findChildOfKind(node, 17 /* OpenBraceToken */, this.sourceFile); + var closeBrace = ts.findChildOfKind(node, 18 /* CloseBraceToken */, this.sourceFile); if (openBrace && closeBrace) { var startLine = this.sourceFile.getLineAndCharacterOfPosition(openBrace.getEnd()).line; var endLine = this.sourceFile.getLineAndCharacterOfPosition(closeBrace.getStart(this.sourceFile)).line; @@ -82765,12 +99146,13 @@ var ts; formatting.FormattingContext = FormattingContext; })(formatting = ts.formatting || (ts.formatting = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var formatting; (function (formatting) { - var standardScanner = ts.createScanner(6, false, 0); - var jsxScanner = ts.createScanner(6, false, 1); + var standardScanner = ts.createScanner(6 /* Latest */, /*skipTrivia*/ false, 0 /* Standard */); + var jsxScanner = ts.createScanner(6 /* Latest */, /*skipTrivia*/ false, 1 /* JSX */); var ScanAction; (function (ScanAction) { ScanAction[ScanAction["Scan"] = 0] = "Scan"; @@ -82781,7 +99163,7 @@ var ts; ScanAction[ScanAction["RescanJsxText"] = 5] = "RescanJsxText"; })(ScanAction || (ScanAction = {})); function getFormattingScanner(text, languageVariant, startPos, endPos, cb) { - var scanner = languageVariant === 1 ? jsxScanner : standardScanner; + var scanner = languageVariant === 1 /* JSX */ ? jsxScanner : standardScanner; scanner.setText(text); scanner.setTextPos(startPos); var wasNewLine = true; @@ -82805,7 +99187,7 @@ var ts; lastTokenInfo = undefined; var isStarted = scanner.getStartPos() !== startPos; if (isStarted) { - wasNewLine = !!trailingTrivia && ts.last(trailingTrivia).kind === 4; + wasNewLine = !!trailingTrivia && ts.last(trailingTrivia).kind === 4 /* NewLineTrivia */; } else { scanner.scan(); @@ -82813,11 +99195,13 @@ var ts; leadingTrivia = undefined; trailingTrivia = undefined; var pos = scanner.getStartPos(); + // Read leading trivia and token while (pos < endPos) { var t = scanner.getToken(); if (!ts.isTrivia(t)) { break; } + // consume leading trivia scanner.scan(); var item = { pos: pos, @@ -82831,11 +99215,11 @@ var ts; } function shouldRescanGreaterThanToken(node) { switch (node.kind) { - case 31: - case 66: - case 67: - case 47: - case 46: + case 31 /* GreaterThanEqualsToken */: + case 66 /* GreaterThanGreaterThanEqualsToken */: + case 67 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + case 47 /* GreaterThanGreaterThanGreaterThanToken */: + case 46 /* GreaterThanGreaterThanToken */: return true; } return false; @@ -82843,46 +99227,56 @@ var ts; function shouldRescanJsxIdentifier(node) { if (node.parent) { switch (node.parent.kind) { - case 262: - case 257: - case 258: - case 256: - return ts.isKeyword(node.kind) || node.kind === 71; + case 262 /* JsxAttribute */: + case 257 /* JsxOpeningElement */: + case 258 /* JsxClosingElement */: + case 256 /* JsxSelfClosingElement */: + // May parse an identifier like `module-layout`; that will be scanned as a keyword at first, but we should parse the whole thing to get an identifier. + return ts.isKeyword(node.kind) || node.kind === 71 /* Identifier */; } } return false; } function shouldRescanJsxText(node) { - return node.kind === 10; + return node.kind === 10 /* JsxText */; } function shouldRescanSlashToken(container) { - return container.kind === 12; + return container.kind === 12 /* RegularExpressionLiteral */; } function shouldRescanTemplateToken(container) { - return container.kind === 15 || - container.kind === 16; + return container.kind === 15 /* TemplateMiddle */ || + container.kind === 16 /* TemplateTail */; } function startsWithSlashToken(t) { - return t === 41 || t === 63; + return t === 41 /* SlashToken */ || t === 63 /* SlashEqualsToken */; } function readTokenInfo(n) { ts.Debug.assert(isOnToken()); + // normally scanner returns the smallest available token + // check the kind of context node to determine if scanner should have more greedy behavior and consume more text. var expectedScanAction = shouldRescanGreaterThanToken(n) - ? 1 + ? 1 /* RescanGreaterThanToken */ : shouldRescanSlashToken(n) - ? 2 + ? 2 /* RescanSlashToken */ : shouldRescanTemplateToken(n) - ? 3 + ? 3 /* RescanTemplateToken */ : shouldRescanJsxIdentifier(n) - ? 4 + ? 4 /* RescanJsxIdentifier */ : shouldRescanJsxText(n) - ? 5 - : 0; + ? 5 /* RescanJsxText */ + : 0 /* Scan */; if (lastTokenInfo && expectedScanAction === lastScanAction) { + // readTokenInfo was called before with the same expected scan action. + // No need to re-scan text, return existing 'lastTokenInfo' + // it is ok to call fixTokenKind here since it does not affect + // what portion of text is consumed. In contrast rescanning can change it, + // i.e. for '>=' when originally scanner eats just one character + // and rescanning forces it to consume more. return fixTokenKind(lastTokenInfo, n); } if (scanner.getStartPos() !== savedPos) { ts.Debug.assert(lastTokenInfo !== undefined); + // readTokenInfo was called before but scan action differs - rescan text scanner.setTextPos(savedPos); scanner.scan(); } @@ -82892,6 +99286,7 @@ var ts; end: scanner.getTextPos(), kind: currentToken }; + // consume trailing trivia if (trailingTrivia) { trailingTrivia = undefined; } @@ -82909,7 +99304,8 @@ var ts; trailingTrivia = []; } trailingTrivia.push(trivia); - if (currentToken === 4) { + if (currentToken === 4 /* NewLineTrivia */) { + // move past new line scanner.scan(); break; } @@ -82919,37 +99315,37 @@ var ts; } function getNextToken(n, expectedScanAction) { var token = scanner.getToken(); - lastScanAction = 0; + lastScanAction = 0 /* Scan */; switch (expectedScanAction) { - case 1: - if (token === 29) { - lastScanAction = 1; + case 1 /* RescanGreaterThanToken */: + if (token === 29 /* GreaterThanToken */) { + lastScanAction = 1 /* RescanGreaterThanToken */; var newToken = scanner.reScanGreaterToken(); ts.Debug.assert(n.kind === newToken); return newToken; } break; - case 2: + case 2 /* RescanSlashToken */: if (startsWithSlashToken(token)) { - lastScanAction = 2; + lastScanAction = 2 /* RescanSlashToken */; var newToken = scanner.reScanSlashToken(); ts.Debug.assert(n.kind === newToken); return newToken; } break; - case 3: - if (token === 18) { - lastScanAction = 3; + case 3 /* RescanTemplateToken */: + if (token === 18 /* CloseBraceToken */) { + lastScanAction = 3 /* RescanTemplateToken */; return scanner.reScanTemplateToken(); } break; - case 4: - lastScanAction = 4; + case 4 /* RescanJsxIdentifier */: + lastScanAction = 4 /* RescanJsxIdentifier */; return scanner.scanJsxIdentifier(); - case 5: - lastScanAction = 5; + case 5 /* RescanJsxText */: + lastScanAction = 5 /* RescanJsxText */; return scanner.reScanJsxToken(); - case 0: + case 0 /* Scan */: break; default: ts.Debug.assertNever(expectedScanAction); @@ -82959,8 +99355,12 @@ var ts; function isOnToken() { var current = lastTokenInfo ? lastTokenInfo.token.kind : scanner.getToken(); var startPos = lastTokenInfo ? lastTokenInfo.token.pos : scanner.getStartPos(); - return startPos < endPos && current !== 1 && !ts.isTrivia(current); + return startPos < endPos && current !== 1 /* EndOfFileToken */ && !ts.isTrivia(current); } + // when containing node in the tree is token + // but its kind differs from the kind that was returned by the scanner, + // then kind needs to be fixed. This might happen in cases + // when parser interprets token differently, i.e keyword treated as identifier function fixTokenKind(tokenInfo, container) { if (ts.isToken(container) && tokenInfo.token.kind !== container.kind) { tokenInfo.token.kind = container.kind; @@ -82980,6 +99380,7 @@ var ts; formatting.getFormattingScanner = getFormattingScanner; })(formatting = ts.formatting || (ts.formatting = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var formatting; @@ -82999,13 +99400,14 @@ var ts; })(RuleFlags = formatting.RuleFlags || (formatting.RuleFlags = {})); })(formatting = ts.formatting || (ts.formatting = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var formatting; (function (formatting) { function getAllRules() { var allTokens = []; - for (var token = 0; token <= 145; token++) { + for (var token = 0 /* FirstToken */; token <= 145 /* LastToken */; token++) { allTokens.push(token); } function anyTokenExcept() { @@ -83016,200 +99418,262 @@ var ts; return { tokens: allTokens.filter(function (t) { return !tokens.some(function (t2) { return t2 === t; }); }), isSpecific: false }; } var anyToken = { tokens: allTokens, isSpecific: false }; - var anyTokenIncludingMultilineComments = tokenRangeFrom(allTokens.concat([3])); - var keywords = tokenRangeFromRange(72, 145); - var binaryOperators = tokenRangeFromRange(27, 70); - var binaryKeywordOperators = [92, 93, 145, 118, 127]; - var unaryPrefixOperators = [43, 44, 52, 51]; + var anyTokenIncludingMultilineComments = tokenRangeFrom(allTokens.concat([3 /* MultiLineCommentTrivia */])); + var keywords = tokenRangeFromRange(72 /* FirstKeyword */, 145 /* LastKeyword */); + var binaryOperators = tokenRangeFromRange(27 /* FirstBinaryOperator */, 70 /* LastBinaryOperator */); + var binaryKeywordOperators = [92 /* InKeyword */, 93 /* InstanceOfKeyword */, 145 /* OfKeyword */, 118 /* AsKeyword */, 127 /* IsKeyword */]; + var unaryPrefixOperators = [43 /* PlusPlusToken */, 44 /* MinusMinusToken */, 52 /* TildeToken */, 51 /* ExclamationToken */]; var unaryPrefixExpressions = [ - 8, 71, 19, 21, - 17, 99, 94 + 8 /* NumericLiteral */, 71 /* Identifier */, 19 /* OpenParenToken */, 21 /* OpenBracketToken */, + 17 /* OpenBraceToken */, 99 /* ThisKeyword */, 94 /* NewKeyword */ ]; - var unaryPreincrementExpressions = [71, 19, 99, 94]; - var unaryPostincrementExpressions = [71, 20, 22, 94]; - var unaryPredecrementExpressions = [71, 19, 99, 94]; - var unaryPostdecrementExpressions = [71, 20, 22, 94]; - var comments = [2, 3]; - var typeNames = [71].concat(ts.typeKeywords); + var unaryPreincrementExpressions = [71 /* Identifier */, 19 /* OpenParenToken */, 99 /* ThisKeyword */, 94 /* NewKeyword */]; + var unaryPostincrementExpressions = [71 /* Identifier */, 20 /* CloseParenToken */, 22 /* CloseBracketToken */, 94 /* NewKeyword */]; + var unaryPredecrementExpressions = [71 /* Identifier */, 19 /* OpenParenToken */, 99 /* ThisKeyword */, 94 /* NewKeyword */]; + var unaryPostdecrementExpressions = [71 /* Identifier */, 20 /* CloseParenToken */, 22 /* CloseBracketToken */, 94 /* NewKeyword */]; + var comments = [2 /* SingleLineCommentTrivia */, 3 /* MultiLineCommentTrivia */]; + var typeNames = [71 /* Identifier */].concat(ts.typeKeywords); + // Place a space before open brace in a function declaration + // TypeScript: Function can have return types, which can be made of tons of different token kinds var functionOpenBraceLeftTokenRange = anyTokenIncludingMultilineComments; - var typeScriptOpenBraceLeftTokenRange = tokenRangeFrom([71, 3, 75, 84, 91]); - var controlOpenBraceLeftTokenRange = tokenRangeFrom([20, 3, 81, 102, 87, 82]); + // Place a space before open brace in a TypeScript declaration that has braces as children (class, module, enum, etc) + var typeScriptOpenBraceLeftTokenRange = tokenRangeFrom([71 /* Identifier */, 3 /* MultiLineCommentTrivia */, 75 /* ClassKeyword */, 84 /* ExportKeyword */, 91 /* ImportKeyword */]); + // Place a space before open brace in a control flow construct + var controlOpenBraceLeftTokenRange = tokenRangeFrom([20 /* CloseParenToken */, 3 /* MultiLineCommentTrivia */, 81 /* DoKeyword */, 102 /* TryKeyword */, 87 /* FinallyKeyword */, 82 /* ElseKeyword */]); + // These rules are higher in priority than user-configurable var highPriorityCommonRules = [ - rule("IgnoreBeforeComment", anyToken, comments, formatting.anyContext, 1), - rule("IgnoreAfterLineComment", 2, anyToken, formatting.anyContext, 1), - rule("NotSpaceBeforeColon", anyToken, 56, [isNonJsxSameLineTokenContext, isNotBinaryOpContext, isNotTypeAnnotationContext], 8), - rule("SpaceAfterColon", 56, anyToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 2), - rule("NoSpaceBeforeQuestionMark", anyToken, 55, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 8), - rule("SpaceAfterQuestionMarkInConditionalOperator", 55, anyToken, [isNonJsxSameLineTokenContext, isConditionalOperatorContext], 2), - rule("NoSpaceAfterQuestionMark", 55, anyToken, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceBeforeDot", anyToken, 23, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceAfterDot", 23, anyToken, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceBetweenImportParenInImportType", 91, 19, [isNonJsxSameLineTokenContext, isImportTypeContext], 8), - rule("NoSpaceAfterUnaryPrefixOperator", unaryPrefixOperators, unaryPrefixExpressions, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 8), - rule("NoSpaceAfterUnaryPreincrementOperator", 43, unaryPreincrementExpressions, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceAfterUnaryPredecrementOperator", 44, unaryPredecrementExpressions, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceBeforeUnaryPostincrementOperator", unaryPostincrementExpressions, 43, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceBeforeUnaryPostdecrementOperator", unaryPostdecrementExpressions, 44, [isNonJsxSameLineTokenContext], 8), - rule("SpaceAfterPostincrementWhenFollowedByAdd", 43, 37, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2), - rule("SpaceAfterAddWhenFollowedByUnaryPlus", 37, 37, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2), - rule("SpaceAfterAddWhenFollowedByPreincrement", 37, 43, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2), - rule("SpaceAfterPostdecrementWhenFollowedBySubtract", 44, 38, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2), - rule("SpaceAfterSubtractWhenFollowedByUnaryMinus", 38, 38, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2), - rule("SpaceAfterSubtractWhenFollowedByPredecrement", 38, 44, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2), - rule("NoSpaceAfterCloseBrace", 18, [26, 25], [isNonJsxSameLineTokenContext], 8), - rule("NewLineBeforeCloseBraceInBlockContext", anyTokenIncludingMultilineComments, 18, [isMultilineBlockContext], 4), - rule("SpaceAfterCloseBrace", 18, anyTokenExcept(20), [isNonJsxSameLineTokenContext, isAfterCodeBlockContext], 2), - rule("SpaceBetweenCloseBraceAndElse", 18, 82, [isNonJsxSameLineTokenContext], 2), - rule("SpaceBetweenCloseBraceAndWhile", 18, 106, [isNonJsxSameLineTokenContext], 2), - rule("NoSpaceBetweenEmptyBraceBrackets", 17, 18, [isNonJsxSameLineTokenContext, isObjectContext], 8), - rule("SpaceAfterConditionalClosingParen", 20, 21, [isControlDeclContext], 2), - rule("NoSpaceBetweenFunctionKeywordAndStar", 89, 39, [isFunctionDeclarationOrFunctionExpressionContext], 8), - rule("SpaceAfterStarInGeneratorDeclaration", 39, [71, 19], [isFunctionDeclarationOrFunctionExpressionContext], 2), - rule("SpaceAfterFunctionInFuncDecl", 89, anyToken, [isFunctionDeclContext], 2), - rule("NewLineAfterOpenBraceInBlockContext", 17, anyToken, [isMultilineBlockContext], 4), - rule("SpaceAfterGetSetInMember", [125, 136], 71, [isFunctionDeclContext], 2), - rule("NoSpaceBetweenYieldKeywordAndStar", 116, 39, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], 8), - rule("SpaceBetweenYieldOrYieldStarAndOperand", [116, 39], anyToken, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], 2), - rule("NoSpaceBetweenReturnAndSemicolon", 96, 25, [isNonJsxSameLineTokenContext], 8), - rule("SpaceAfterCertainKeywords", [104, 100, 94, 80, 96, 103, 121], anyToken, [isNonJsxSameLineTokenContext], 2), - rule("SpaceAfterLetConstInVariableDeclaration", [110, 76], anyToken, [isNonJsxSameLineTokenContext, isStartOfVariableDeclarationList], 2), - rule("NoSpaceBeforeOpenParenInFuncCall", anyToken, 19, [isNonJsxSameLineTokenContext, isFunctionCallOrNewContext, isPreviousTokenNotComma], 8), - rule("SpaceBeforeBinaryKeywordOperator", anyToken, binaryKeywordOperators, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2), - rule("SpaceAfterBinaryKeywordOperator", binaryKeywordOperators, anyToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2), - rule("SpaceAfterVoidOperator", 105, anyToken, [isNonJsxSameLineTokenContext, isVoidOpContext], 2), - rule("SpaceBetweenAsyncAndOpenParen", 120, 19, [isArrowFunctionContext, isNonJsxSameLineTokenContext], 2), - rule("SpaceBetweenAsyncAndFunctionKeyword", 120, 89, [isNonJsxSameLineTokenContext], 2), - rule("NoSpaceBetweenTagAndTemplateString", [71, 20], [13, 14], [isNonJsxSameLineTokenContext], 8), - rule("SpaceBeforeJsxAttribute", anyToken, 71, [isNextTokenParentJsxAttribute, isNonJsxSameLineTokenContext], 2), - rule("SpaceBeforeSlashInJsxOpeningElement", anyToken, 41, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], 2), - rule("NoSpaceBeforeGreaterThanTokenInJsxOpeningElement", 41, 29, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], 8), - rule("NoSpaceBeforeEqualInJsxAttribute", anyToken, 58, [isJsxAttributeContext, isNonJsxSameLineTokenContext], 8), - rule("NoSpaceAfterEqualInJsxAttribute", 58, anyToken, [isJsxAttributeContext, isNonJsxSameLineTokenContext], 8), - rule("NoSpaceAfterModuleImport", [129, 133], 19, [isNonJsxSameLineTokenContext], 8), + // Leave comments alone + rule("IgnoreBeforeComment", anyToken, comments, formatting.anyContext, 1 /* Ignore */), + rule("IgnoreAfterLineComment", 2 /* SingleLineCommentTrivia */, anyToken, formatting.anyContext, 1 /* Ignore */), + rule("NotSpaceBeforeColon", anyToken, 56 /* ColonToken */, [isNonJsxSameLineTokenContext, isNotBinaryOpContext, isNotTypeAnnotationContext], 8 /* Delete */), + rule("SpaceAfterColon", 56 /* ColonToken */, anyToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 2 /* Space */), + rule("NoSpaceBeforeQuestionMark", anyToken, 55 /* QuestionToken */, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 8 /* Delete */), + // insert space after '?' only when it is used in conditional operator + rule("SpaceAfterQuestionMarkInConditionalOperator", 55 /* QuestionToken */, anyToken, [isNonJsxSameLineTokenContext, isConditionalOperatorContext], 2 /* Space */), + // in other cases there should be no space between '?' and next token + rule("NoSpaceAfterQuestionMark", 55 /* QuestionToken */, anyToken, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceBeforeDot", anyToken, 23 /* DotToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceAfterDot", 23 /* DotToken */, anyToken, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceBetweenImportParenInImportType", 91 /* ImportKeyword */, 19 /* OpenParenToken */, [isNonJsxSameLineTokenContext, isImportTypeContext], 8 /* Delete */), + // Special handling of unary operators. + // Prefix operators generally shouldn't have a space between + // them and their target unary expression. + rule("NoSpaceAfterUnaryPrefixOperator", unaryPrefixOperators, unaryPrefixExpressions, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 8 /* Delete */), + rule("NoSpaceAfterUnaryPreincrementOperator", 43 /* PlusPlusToken */, unaryPreincrementExpressions, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceAfterUnaryPredecrementOperator", 44 /* MinusMinusToken */, unaryPredecrementExpressions, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceBeforeUnaryPostincrementOperator", unaryPostincrementExpressions, 43 /* PlusPlusToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceBeforeUnaryPostdecrementOperator", unaryPostdecrementExpressions, 44 /* MinusMinusToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + // More unary operator special-casing. + // DevDiv 181814: Be careful when removing leading whitespace + // around unary operators. Examples: + // 1 - -2 --X--> 1--2 + // a + ++b --X--> a+++b + rule("SpaceAfterPostincrementWhenFollowedByAdd", 43 /* PlusPlusToken */, 37 /* PlusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */), + rule("SpaceAfterAddWhenFollowedByUnaryPlus", 37 /* PlusToken */, 37 /* PlusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */), + rule("SpaceAfterAddWhenFollowedByPreincrement", 37 /* PlusToken */, 43 /* PlusPlusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */), + rule("SpaceAfterPostdecrementWhenFollowedBySubtract", 44 /* MinusMinusToken */, 38 /* MinusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */), + rule("SpaceAfterSubtractWhenFollowedByUnaryMinus", 38 /* MinusToken */, 38 /* MinusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */), + rule("SpaceAfterSubtractWhenFollowedByPredecrement", 38 /* MinusToken */, 44 /* MinusMinusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */), + rule("NoSpaceAfterCloseBrace", 18 /* CloseBraceToken */, [26 /* CommaToken */, 25 /* SemicolonToken */], [isNonJsxSameLineTokenContext], 8 /* Delete */), + // For functions and control block place } on a new line [multi-line rule] + rule("NewLineBeforeCloseBraceInBlockContext", anyTokenIncludingMultilineComments, 18 /* CloseBraceToken */, [isMultilineBlockContext], 4 /* NewLine */), + // Space/new line after }. + rule("SpaceAfterCloseBrace", 18 /* CloseBraceToken */, anyTokenExcept(20 /* CloseParenToken */), [isNonJsxSameLineTokenContext, isAfterCodeBlockContext], 2 /* Space */), + // Special case for (}, else) and (}, while) since else & while tokens are not part of the tree which makes SpaceAfterCloseBrace rule not applied + // Also should not apply to }) + rule("SpaceBetweenCloseBraceAndElse", 18 /* CloseBraceToken */, 82 /* ElseKeyword */, [isNonJsxSameLineTokenContext], 2 /* Space */), + rule("SpaceBetweenCloseBraceAndWhile", 18 /* CloseBraceToken */, 106 /* WhileKeyword */, [isNonJsxSameLineTokenContext], 2 /* Space */), + rule("NoSpaceBetweenEmptyBraceBrackets", 17 /* OpenBraceToken */, 18 /* CloseBraceToken */, [isNonJsxSameLineTokenContext, isObjectContext], 8 /* Delete */), + // Add a space after control dec context if the next character is an open bracket ex: 'if (false)[a, b] = [1, 2];' -> 'if (false) [a, b] = [1, 2];' + rule("SpaceAfterConditionalClosingParen", 20 /* CloseParenToken */, 21 /* OpenBracketToken */, [isControlDeclContext], 2 /* Space */), + rule("NoSpaceBetweenFunctionKeywordAndStar", 89 /* FunctionKeyword */, 39 /* AsteriskToken */, [isFunctionDeclarationOrFunctionExpressionContext], 8 /* Delete */), + rule("SpaceAfterStarInGeneratorDeclaration", 39 /* AsteriskToken */, [71 /* Identifier */, 19 /* OpenParenToken */], [isFunctionDeclarationOrFunctionExpressionContext], 2 /* Space */), + rule("SpaceAfterFunctionInFuncDecl", 89 /* FunctionKeyword */, anyToken, [isFunctionDeclContext], 2 /* Space */), + // Insert new line after { and before } in multi-line contexts. + rule("NewLineAfterOpenBraceInBlockContext", 17 /* OpenBraceToken */, anyToken, [isMultilineBlockContext], 4 /* NewLine */), + // For get/set members, we check for (identifier,identifier) since get/set don't have tokens and they are represented as just an identifier token. + // Though, we do extra check on the context to make sure we are dealing with get/set node. Example: + // get x() {} + // set x(val) {} + rule("SpaceAfterGetSetInMember", [125 /* GetKeyword */, 136 /* SetKeyword */], 71 /* Identifier */, [isFunctionDeclContext], 2 /* Space */), + rule("NoSpaceBetweenYieldKeywordAndStar", 116 /* YieldKeyword */, 39 /* AsteriskToken */, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], 8 /* Delete */), + rule("SpaceBetweenYieldOrYieldStarAndOperand", [116 /* YieldKeyword */, 39 /* AsteriskToken */], anyToken, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], 2 /* Space */), + rule("NoSpaceBetweenReturnAndSemicolon", 96 /* ReturnKeyword */, 25 /* SemicolonToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("SpaceAfterCertainKeywords", [104 /* VarKeyword */, 100 /* ThrowKeyword */, 94 /* NewKeyword */, 80 /* DeleteKeyword */, 96 /* ReturnKeyword */, 103 /* TypeOfKeyword */, 121 /* AwaitKeyword */], anyToken, [isNonJsxSameLineTokenContext], 2 /* Space */), + rule("SpaceAfterLetConstInVariableDeclaration", [110 /* LetKeyword */, 76 /* ConstKeyword */], anyToken, [isNonJsxSameLineTokenContext, isStartOfVariableDeclarationList], 2 /* Space */), + rule("NoSpaceBeforeOpenParenInFuncCall", anyToken, 19 /* OpenParenToken */, [isNonJsxSameLineTokenContext, isFunctionCallOrNewContext, isPreviousTokenNotComma], 8 /* Delete */), + // Special case for binary operators (that are keywords). For these we have to add a space and shouldn't follow any user options. + rule("SpaceBeforeBinaryKeywordOperator", anyToken, binaryKeywordOperators, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */), + rule("SpaceAfterBinaryKeywordOperator", binaryKeywordOperators, anyToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */), + rule("SpaceAfterVoidOperator", 105 /* VoidKeyword */, anyToken, [isNonJsxSameLineTokenContext, isVoidOpContext], 2 /* Space */), + // Async-await + rule("SpaceBetweenAsyncAndOpenParen", 120 /* AsyncKeyword */, 19 /* OpenParenToken */, [isArrowFunctionContext, isNonJsxSameLineTokenContext], 2 /* Space */), + rule("SpaceBetweenAsyncAndFunctionKeyword", 120 /* AsyncKeyword */, 89 /* FunctionKeyword */, [isNonJsxSameLineTokenContext], 2 /* Space */), + // Template string + rule("NoSpaceBetweenTagAndTemplateString", [71 /* Identifier */, 20 /* CloseParenToken */], [13 /* NoSubstitutionTemplateLiteral */, 14 /* TemplateHead */], [isNonJsxSameLineTokenContext], 8 /* Delete */), + // JSX opening elements + rule("SpaceBeforeJsxAttribute", anyToken, 71 /* Identifier */, [isNextTokenParentJsxAttribute, isNonJsxSameLineTokenContext], 2 /* Space */), + rule("SpaceBeforeSlashInJsxOpeningElement", anyToken, 41 /* SlashToken */, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], 2 /* Space */), + rule("NoSpaceBeforeGreaterThanTokenInJsxOpeningElement", 41 /* SlashToken */, 29 /* GreaterThanToken */, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceBeforeEqualInJsxAttribute", anyToken, 58 /* EqualsToken */, [isJsxAttributeContext, isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceAfterEqualInJsxAttribute", 58 /* EqualsToken */, anyToken, [isJsxAttributeContext, isNonJsxSameLineTokenContext], 8 /* Delete */), + // TypeScript-specific rules + // Use of module as a function call. e.g.: import m2 = module("m2"); + rule("NoSpaceAfterModuleImport", [129 /* ModuleKeyword */, 133 /* RequireKeyword */], 19 /* OpenParenToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + // Add a space around certain TypeScript keywords rule("SpaceAfterCertainTypeScriptKeywords", [ - 117, - 75, - 124, - 79, - 83, - 84, - 85, - 125, - 108, - 91, - 109, - 129, - 130, - 112, - 114, - 113, - 132, - 136, - 115, - 139, - 143, - 128, - 126, - ], anyToken, [isNonJsxSameLineTokenContext], 2), - rule("SpaceBeforeCertainTypeScriptKeywords", anyToken, [85, 108, 143], [isNonJsxSameLineTokenContext], 2), - rule("SpaceAfterModuleName", 9, 17, [isModuleDeclContext], 2), - rule("SpaceBeforeArrow", anyToken, 36, [isNonJsxSameLineTokenContext], 2), - rule("SpaceAfterArrow", 36, anyToken, [isNonJsxSameLineTokenContext], 2), - rule("NoSpaceAfterEllipsis", 24, 71, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceAfterOptionalParameters", 55, [20, 26], [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 8), - rule("NoSpaceBetweenEmptyInterfaceBraceBrackets", 17, 18, [isNonJsxSameLineTokenContext, isObjectTypeContext], 8), - rule("NoSpaceBeforeOpenAngularBracket", typeNames, 27, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8), - rule("NoSpaceBetweenCloseParenAndAngularBracket", 20, 27, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8), - rule("NoSpaceAfterOpenAngularBracket", 27, anyToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8), - rule("NoSpaceBeforeCloseAngularBracket", anyToken, 29, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8), - rule("NoSpaceAfterCloseAngularBracket", 29, [19, 21, 29, 26], [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext, isNotFunctionDeclContext], 8), - rule("SpaceBeforeAt", [20, 71], 57, [isNonJsxSameLineTokenContext], 2), - rule("NoSpaceAfterAt", 57, anyToken, [isNonJsxSameLineTokenContext], 8), + 117 /* AbstractKeyword */, + 75 /* ClassKeyword */, + 124 /* DeclareKeyword */, + 79 /* DefaultKeyword */, + 83 /* EnumKeyword */, + 84 /* ExportKeyword */, + 85 /* ExtendsKeyword */, + 125 /* GetKeyword */, + 108 /* ImplementsKeyword */, + 91 /* ImportKeyword */, + 109 /* InterfaceKeyword */, + 129 /* ModuleKeyword */, + 130 /* NamespaceKeyword */, + 112 /* PrivateKeyword */, + 114 /* PublicKeyword */, + 113 /* ProtectedKeyword */, + 132 /* ReadonlyKeyword */, + 136 /* SetKeyword */, + 115 /* StaticKeyword */, + 139 /* TypeKeyword */, + 143 /* FromKeyword */, + 128 /* KeyOfKeyword */, + 126 /* InferKeyword */, + ], anyToken, [isNonJsxSameLineTokenContext], 2 /* Space */), + rule("SpaceBeforeCertainTypeScriptKeywords", anyToken, [85 /* ExtendsKeyword */, 108 /* ImplementsKeyword */, 143 /* FromKeyword */], [isNonJsxSameLineTokenContext], 2 /* Space */), + // Treat string literals in module names as identifiers, and add a space between the literal and the opening Brace braces, e.g.: module "m2" { + rule("SpaceAfterModuleName", 9 /* StringLiteral */, 17 /* OpenBraceToken */, [isModuleDeclContext], 2 /* Space */), + // Lambda expressions + rule("SpaceBeforeArrow", anyToken, 36 /* EqualsGreaterThanToken */, [isNonJsxSameLineTokenContext], 2 /* Space */), + rule("SpaceAfterArrow", 36 /* EqualsGreaterThanToken */, anyToken, [isNonJsxSameLineTokenContext], 2 /* Space */), + // Optional parameters and let args + rule("NoSpaceAfterEllipsis", 24 /* DotDotDotToken */, 71 /* Identifier */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceAfterOptionalParameters", 55 /* QuestionToken */, [20 /* CloseParenToken */, 26 /* CommaToken */], [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 8 /* Delete */), + // Remove spaces in empty interface literals. e.g.: x: {} + rule("NoSpaceBetweenEmptyInterfaceBraceBrackets", 17 /* OpenBraceToken */, 18 /* CloseBraceToken */, [isNonJsxSameLineTokenContext, isObjectTypeContext], 8 /* Delete */), + // generics and type assertions + rule("NoSpaceBeforeOpenAngularBracket", typeNames, 27 /* LessThanToken */, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8 /* Delete */), + rule("NoSpaceBetweenCloseParenAndAngularBracket", 20 /* CloseParenToken */, 27 /* LessThanToken */, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8 /* Delete */), + rule("NoSpaceAfterOpenAngularBracket", 27 /* LessThanToken */, anyToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8 /* Delete */), + rule("NoSpaceBeforeCloseAngularBracket", anyToken, 29 /* GreaterThanToken */, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8 /* Delete */), + rule("NoSpaceAfterCloseAngularBracket", 29 /* GreaterThanToken */, [19 /* OpenParenToken */, 21 /* OpenBracketToken */, 29 /* GreaterThanToken */, 26 /* CommaToken */], [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext, isNotFunctionDeclContext /*To prevent an interference with the SpaceBeforeOpenParenInFuncDecl rule*/], 8 /* Delete */), + // decorators + rule("SpaceBeforeAt", [20 /* CloseParenToken */, 71 /* Identifier */], 57 /* AtToken */, [isNonJsxSameLineTokenContext], 2 /* Space */), + rule("NoSpaceAfterAt", 57 /* AtToken */, anyToken, [isNonJsxSameLineTokenContext], 8 /* Delete */), + // Insert space after @ in decorator rule("SpaceAfterDecorator", anyToken, [ - 117, - 71, - 84, - 79, - 75, - 115, - 114, - 112, - 113, - 125, - 136, - 21, - 39, - ], [isEndOfDecoratorContextOnSameLine], 2), - rule("NoSpaceBeforeNonNullAssertionOperator", anyToken, 51, [isNonJsxSameLineTokenContext, isNonNullAssertionContext], 8), - rule("NoSpaceAfterNewKeywordOnConstructorSignature", 94, 19, [isNonJsxSameLineTokenContext, isConstructorSignatureContext], 8), + 117 /* AbstractKeyword */, + 71 /* Identifier */, + 84 /* ExportKeyword */, + 79 /* DefaultKeyword */, + 75 /* ClassKeyword */, + 115 /* StaticKeyword */, + 114 /* PublicKeyword */, + 112 /* PrivateKeyword */, + 113 /* ProtectedKeyword */, + 125 /* GetKeyword */, + 136 /* SetKeyword */, + 21 /* OpenBracketToken */, + 39 /* AsteriskToken */, + ], [isEndOfDecoratorContextOnSameLine], 2 /* Space */), + rule("NoSpaceBeforeNonNullAssertionOperator", anyToken, 51 /* ExclamationToken */, [isNonJsxSameLineTokenContext, isNonNullAssertionContext], 8 /* Delete */), + rule("NoSpaceAfterNewKeywordOnConstructorSignature", 94 /* NewKeyword */, 19 /* OpenParenToken */, [isNonJsxSameLineTokenContext, isConstructorSignatureContext], 8 /* Delete */), ]; + // These rules are applied after high priority var userConfigurableRules = [ - rule("SpaceAfterConstructor", 123, 19, [isOptionEnabled("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], 2), - rule("NoSpaceAfterConstructor", 123, 19, [isOptionDisabledOrUndefined("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], 8), - rule("SpaceAfterComma", 26, anyToken, [isOptionEnabled("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNextTokenNotCloseBracket], 2), - rule("NoSpaceAfterComma", 26, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext], 8), - rule("SpaceAfterAnonymousFunctionKeyword", 89, 19, [isOptionEnabled("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], 2), - rule("NoSpaceAfterAnonymousFunctionKeyword", 89, 19, [isOptionDisabledOrUndefined("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], 8), - rule("SpaceAfterKeywordInControl", keywords, 19, [isOptionEnabled("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], 2), - rule("NoSpaceAfterKeywordInControl", keywords, 19, [isOptionDisabledOrUndefined("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], 8), - rule("SpaceAfterOpenParen", 19, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 2), - rule("SpaceBeforeCloseParen", anyToken, 20, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 2), - rule("SpaceBetweenOpenParens", 19, 19, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 2), - rule("NoSpaceBetweenParens", 19, 20, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceAfterOpenParen", 19, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 8), - rule("NoSpaceBeforeCloseParen", anyToken, 20, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 8), - rule("SpaceAfterOpenBracket", 21, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 2), - rule("SpaceBeforeCloseBracket", anyToken, 22, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 2), - rule("NoSpaceBetweenBrackets", 21, 22, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceAfterOpenBracket", 21, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 8), - rule("NoSpaceBeforeCloseBracket", anyToken, 22, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 8), - rule("SpaceAfterOpenBrace", 17, anyToken, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], 2), - rule("SpaceBeforeCloseBrace", anyToken, 18, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], 2), - rule("NoSpaceBetweenEmptyBraceBrackets", 17, 18, [isNonJsxSameLineTokenContext, isObjectContext], 8), - rule("NoSpaceAfterOpenBrace", 17, anyToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], 8), - rule("NoSpaceBeforeCloseBrace", anyToken, 18, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], 8), - rule("SpaceAfterTemplateHeadAndMiddle", [14, 15], anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 2), - rule("SpaceBeforeTemplateMiddleAndTail", anyToken, [15, 16], [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 2), - rule("NoSpaceAfterTemplateHeadAndMiddle", [14, 15], anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 8), - rule("NoSpaceBeforeTemplateMiddleAndTail", anyToken, [15, 16], [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 8), - rule("SpaceAfterOpenBraceInJsxExpression", 17, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 2), - rule("SpaceBeforeCloseBraceInJsxExpression", anyToken, 18, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 2), - rule("NoSpaceAfterOpenBraceInJsxExpression", 17, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 8), - rule("NoSpaceBeforeCloseBraceInJsxExpression", anyToken, 18, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 8), - rule("SpaceAfterSemicolonInFor", 25, anyToken, [isOptionEnabled("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], 2), - rule("NoSpaceAfterSemicolonInFor", 25, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], 8), - rule("SpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 2), - rule("SpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 2), - rule("NoSpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 8), - rule("NoSpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 8), - rule("SpaceBeforeOpenParenInFuncDecl", anyToken, 19, [isOptionEnabled("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], 2), - rule("NoSpaceBeforeOpenParenInFuncDecl", anyToken, 19, [isOptionDisabledOrUndefined("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], 8), - rule("NewLineBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, 17, [isOptionEnabled("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isBeforeMultilineBlockContext], 4, 1), - rule("NewLineBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, 17, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeMultilineBlockContext], 4, 1), - rule("NewLineBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, 17, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isBeforeMultilineBlockContext], 4, 1), - rule("SpaceAfterTypeAssertion", 29, anyToken, [isOptionEnabled("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], 2), - rule("NoSpaceAfterTypeAssertion", 29, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], 8), - rule("SpaceBeforeTypeAnnotation", anyToken, 56, [isOptionEnabled("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], 2), - rule("NoSpaceBeforeTypeAnnotation", anyToken, 56, [isOptionDisabledOrUndefined("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], 8), + // Treat constructor as an identifier in a function declaration, and remove spaces between constructor and following left parentheses + rule("SpaceAfterConstructor", 123 /* ConstructorKeyword */, 19 /* OpenParenToken */, [isOptionEnabled("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], 2 /* Space */), + rule("NoSpaceAfterConstructor", 123 /* ConstructorKeyword */, 19 /* OpenParenToken */, [isOptionDisabledOrUndefined("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("SpaceAfterComma", 26 /* CommaToken */, anyToken, [isOptionEnabled("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNextTokenNotCloseBracket], 2 /* Space */), + rule("NoSpaceAfterComma", 26 /* CommaToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext], 8 /* Delete */), + // Insert space after function keyword for anonymous functions + rule("SpaceAfterAnonymousFunctionKeyword", 89 /* FunctionKeyword */, 19 /* OpenParenToken */, [isOptionEnabled("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], 2 /* Space */), + rule("NoSpaceAfterAnonymousFunctionKeyword", 89 /* FunctionKeyword */, 19 /* OpenParenToken */, [isOptionDisabledOrUndefined("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], 8 /* Delete */), + // Insert space after keywords in control flow statements + rule("SpaceAfterKeywordInControl", keywords, 19 /* OpenParenToken */, [isOptionEnabled("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], 2 /* Space */), + rule("NoSpaceAfterKeywordInControl", keywords, 19 /* OpenParenToken */, [isOptionDisabledOrUndefined("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], 8 /* Delete */), + // Insert space after opening and before closing nonempty parenthesis + rule("SpaceAfterOpenParen", 19 /* OpenParenToken */, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 2 /* Space */), + rule("SpaceBeforeCloseParen", anyToken, 20 /* CloseParenToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 2 /* Space */), + rule("SpaceBetweenOpenParens", 19 /* OpenParenToken */, 19 /* OpenParenToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 2 /* Space */), + rule("NoSpaceBetweenParens", 19 /* OpenParenToken */, 20 /* CloseParenToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceAfterOpenParen", 19 /* OpenParenToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceBeforeCloseParen", anyToken, 20 /* CloseParenToken */, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 8 /* Delete */), + // Insert space after opening and before closing nonempty brackets + rule("SpaceAfterOpenBracket", 21 /* OpenBracketToken */, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 2 /* Space */), + rule("SpaceBeforeCloseBracket", anyToken, 22 /* CloseBracketToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 2 /* Space */), + rule("NoSpaceBetweenBrackets", 21 /* OpenBracketToken */, 22 /* CloseBracketToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceAfterOpenBracket", 21 /* OpenBracketToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceBeforeCloseBracket", anyToken, 22 /* CloseBracketToken */, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 8 /* Delete */), + // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}. + rule("SpaceAfterOpenBrace", 17 /* OpenBraceToken */, anyToken, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], 2 /* Space */), + rule("SpaceBeforeCloseBrace", anyToken, 18 /* CloseBraceToken */, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], 2 /* Space */), + rule("NoSpaceBetweenEmptyBraceBrackets", 17 /* OpenBraceToken */, 18 /* CloseBraceToken */, [isNonJsxSameLineTokenContext, isObjectContext], 8 /* Delete */), + rule("NoSpaceAfterOpenBrace", 17 /* OpenBraceToken */, anyToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceBeforeCloseBrace", anyToken, 18 /* CloseBraceToken */, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], 8 /* Delete */), + // Insert space after opening and before closing template string braces + rule("SpaceAfterTemplateHeadAndMiddle", [14 /* TemplateHead */, 15 /* TemplateMiddle */], anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 2 /* Space */), + rule("SpaceBeforeTemplateMiddleAndTail", anyToken, [15 /* TemplateMiddle */, 16 /* TemplateTail */], [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 2 /* Space */), + rule("NoSpaceAfterTemplateHeadAndMiddle", [14 /* TemplateHead */, 15 /* TemplateMiddle */], anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceBeforeTemplateMiddleAndTail", anyToken, [15 /* TemplateMiddle */, 16 /* TemplateTail */], [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 8 /* Delete */), + // No space after { and before } in JSX expression + rule("SpaceAfterOpenBraceInJsxExpression", 17 /* OpenBraceToken */, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 2 /* Space */), + rule("SpaceBeforeCloseBraceInJsxExpression", anyToken, 18 /* CloseBraceToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 2 /* Space */), + rule("NoSpaceAfterOpenBraceInJsxExpression", 17 /* OpenBraceToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 8 /* Delete */), + rule("NoSpaceBeforeCloseBraceInJsxExpression", anyToken, 18 /* CloseBraceToken */, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 8 /* Delete */), + // Insert space after semicolon in for statement + rule("SpaceAfterSemicolonInFor", 25 /* SemicolonToken */, anyToken, [isOptionEnabled("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], 2 /* Space */), + rule("NoSpaceAfterSemicolonInFor", 25 /* SemicolonToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], 8 /* Delete */), + // Insert space before and after binary operators + rule("SpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */), + rule("SpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */), + rule("NoSpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 8 /* Delete */), + rule("NoSpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 8 /* Delete */), + rule("SpaceBeforeOpenParenInFuncDecl", anyToken, 19 /* OpenParenToken */, [isOptionEnabled("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], 2 /* Space */), + rule("NoSpaceBeforeOpenParenInFuncDecl", anyToken, 19 /* OpenParenToken */, [isOptionDisabledOrUndefined("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], 8 /* Delete */), + // Open Brace braces after control block + rule("NewLineBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, 17 /* OpenBraceToken */, [isOptionEnabled("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isBeforeMultilineBlockContext], 4 /* NewLine */, 1 /* CanDeleteNewLines */), + // Open Brace braces after function + // TypeScript: Function can have return types, which can be made of tons of different token kinds + rule("NewLineBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, 17 /* OpenBraceToken */, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeMultilineBlockContext], 4 /* NewLine */, 1 /* CanDeleteNewLines */), + // Open Brace braces after TypeScript module/class/interface + rule("NewLineBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, 17 /* OpenBraceToken */, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isBeforeMultilineBlockContext], 4 /* NewLine */, 1 /* CanDeleteNewLines */), + rule("SpaceAfterTypeAssertion", 29 /* GreaterThanToken */, anyToken, [isOptionEnabled("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], 2 /* Space */), + rule("NoSpaceAfterTypeAssertion", 29 /* GreaterThanToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], 8 /* Delete */), + rule("SpaceBeforeTypeAnnotation", anyToken, 56 /* ColonToken */, [isOptionEnabled("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], 2 /* Space */), + rule("NoSpaceBeforeTypeAnnotation", anyToken, 56 /* ColonToken */, [isOptionDisabledOrUndefined("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], 8 /* Delete */), ]; + // These rules are lower in priority than user-configurable. Rules earlier in this list have priority over rules later in the list. var lowPriorityCommonRules = [ - rule("NoSpaceBeforeSemicolon", anyToken, 25, [isNonJsxSameLineTokenContext], 8), - rule("SpaceBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, 17, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 2, 1), - rule("SpaceBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, 17, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 2, 1), - rule("SpaceBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, 17, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 2, 1), - rule("NoSpaceBeforeComma", anyToken, 26, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceBeforeOpenBracket", anyTokenExcept(120, 73), 21, [isNonJsxSameLineTokenContext], 8), - rule("NoSpaceAfterCloseBracket", 22, anyToken, [isNonJsxSameLineTokenContext, isNotBeforeBlockInFunctionDeclarationContext], 8), - rule("SpaceAfterSemicolon", 25, anyToken, [isNonJsxSameLineTokenContext], 2), - rule("SpaceBetweenForAndAwaitKeyword", 88, 121, [isNonJsxSameLineTokenContext], 2), - rule("SpaceBetweenStatements", [20, 81, 82, 73], anyToken, [isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNotForContext], 2), - rule("SpaceAfterTryFinally", [102, 87], 17, [isNonJsxSameLineTokenContext], 2), + // Space after keyword but not before ; or : or ? + rule("NoSpaceBeforeSemicolon", anyToken, 25 /* SemicolonToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("SpaceBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, 17 /* OpenBraceToken */, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 2 /* Space */, 1 /* CanDeleteNewLines */), + rule("SpaceBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, 17 /* OpenBraceToken */, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 2 /* Space */, 1 /* CanDeleteNewLines */), + rule("SpaceBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, 17 /* OpenBraceToken */, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 2 /* Space */, 1 /* CanDeleteNewLines */), + rule("NoSpaceBeforeComma", anyToken, 26 /* CommaToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + // No space before and after indexer `x[]` + rule("NoSpaceBeforeOpenBracket", anyTokenExcept(120 /* AsyncKeyword */, 73 /* CaseKeyword */), 21 /* OpenBracketToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */), + rule("NoSpaceAfterCloseBracket", 22 /* CloseBracketToken */, anyToken, [isNonJsxSameLineTokenContext, isNotBeforeBlockInFunctionDeclarationContext], 8 /* Delete */), + rule("SpaceAfterSemicolon", 25 /* SemicolonToken */, anyToken, [isNonJsxSameLineTokenContext], 2 /* Space */), + // Remove extra space between for and await + rule("SpaceBetweenForAndAwaitKeyword", 88 /* ForKeyword */, 121 /* AwaitKeyword */, [isNonJsxSameLineTokenContext], 2 /* Space */), + // Add a space between statements. All keywords except (do,else,case) has open/close parens after them. + // So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any] + rule("SpaceBetweenStatements", [20 /* CloseParenToken */, 81 /* DoKeyword */, 82 /* ElseKeyword */, 73 /* CaseKeyword */], anyToken, [isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNotForContext], 2 /* Space */), + // This low-pri rule takes care of "try {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter. + rule("SpaceAfterTryFinally", [102 /* TryKeyword */, 87 /* FinallyKeyword */], 17 /* OpenBraceToken */, [isNonJsxSameLineTokenContext], 2 /* Space */), ]; return highPriorityCommonRules.concat(userConfigurableRules, lowPriorityCommonRules); } formatting.getAllRules = getAllRules; function rule(debugName, left, right, context, action, flags) { - if (flags === void 0) { flags = 0; } + if (flags === void 0) { flags = 0 /* None */; } return { leftTokenRange: toTokenRange(left), rightTokenRange: toTokenRange(right), rule: { debugName: debugName, context: context, action: action, flags: flags } }; } function tokenRangeFrom(tokens) { @@ -83228,6 +99692,9 @@ var ts; } return tokenRangeFrom(tokens); } + /// + /// Contexts + /// function isOptionEnabled(optionName) { return function (context) { return context.options && context.options.hasOwnProperty(optionName) && !!context.options[optionName]; }; } @@ -83244,37 +99711,45 @@ var ts; return function (context) { return !context.options || !context.options.hasOwnProperty(optionName) || !!context.options[optionName]; }; } function isForContext(context) { - return context.contextNode.kind === 220; + return context.contextNode.kind === 220 /* ForStatement */; } function isNotForContext(context) { return !isForContext(context); } function isBinaryOpContext(context) { switch (context.contextNode.kind) { - case 200: - case 201: - case 171: - case 208: - case 252: - case 248: - case 161: - case 169: - case 170: + case 200 /* BinaryExpression */: + case 201 /* ConditionalExpression */: + case 171 /* ConditionalType */: + case 208 /* AsExpression */: + case 252 /* ExportSpecifier */: + case 248 /* ImportSpecifier */: + case 161 /* TypePredicate */: + case 169 /* UnionType */: + case 170 /* IntersectionType */: return true; - case 182: - case 237: - case 243: - case 232: - case 149: - case 273: - case 152: - case 151: - return context.currentTokenSpan.kind === 58 || context.nextTokenSpan.kind === 58; - case 221: - case 148: - return context.currentTokenSpan.kind === 92 || context.nextTokenSpan.kind === 92; - case 222: - return context.currentTokenSpan.kind === 145 || context.nextTokenSpan.kind === 145; + // equals in binding elements: function foo([[x, y] = [1, 2]]) + case 182 /* BindingElement */: + // equals in type X = ... + case 237 /* TypeAliasDeclaration */: + // equal in import a = module('a'); + case 243 /* ImportEqualsDeclaration */: + // equal in let a = 0; + case 232 /* VariableDeclaration */: + // equal in p = 0; + case 149 /* Parameter */: + case 273 /* EnumMember */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + return context.currentTokenSpan.kind === 58 /* EqualsToken */ || context.nextTokenSpan.kind === 58 /* EqualsToken */; + // "in" keyword in for (let x in []) { } + case 221 /* ForInStatement */: + // "in" keyword in [P in keyof T]: T[P] + case 148 /* TypeParameter */: + return context.currentTokenSpan.kind === 92 /* InKeyword */ || context.nextTokenSpan.kind === 92 /* InKeyword */; + // Technically, "of" is not a binary operator, but format it the same way as "in" + case 222 /* ForOfStatement */: + return context.currentTokenSpan.kind === 145 /* OfKeyword */ || context.nextTokenSpan.kind === 145 /* OfKeyword */; } return false; } @@ -83286,24 +99761,25 @@ var ts; } function isTypeAnnotationContext(context) { var contextKind = context.contextNode.kind; - return contextKind === 152 || - contextKind === 151 || - contextKind === 149 || - contextKind === 232 || + return contextKind === 152 /* PropertyDeclaration */ || + contextKind === 151 /* PropertySignature */ || + contextKind === 149 /* Parameter */ || + contextKind === 232 /* VariableDeclaration */ || ts.isFunctionLikeKind(contextKind); } function isConditionalOperatorContext(context) { - return context.contextNode.kind === 201 || - context.contextNode.kind === 171; + return context.contextNode.kind === 201 /* ConditionalExpression */ || + context.contextNode.kind === 171 /* ConditionalType */; } function isSameLineTokenOrBeforeBlockContext(context) { return context.TokensAreOnSameLine() || isBeforeBlockContext(context); } function isBraceWrappedContext(context) { - return context.contextNode.kind === 180 || - context.contextNode.kind === 177 || + return context.contextNode.kind === 180 /* ObjectBindingPattern */ || + context.contextNode.kind === 177 /* MappedType */ || isSingleLineBlockContext(context); } + // This check is done before an open brace in a control construct, a function, or a typescript block declaration function isBeforeMultilineBlockContext(context) { return isBeforeBlockContext(context) && !(context.NextNodeAllOnSameLine() || context.NextNodeBlockIsOnOneLine()); } @@ -83319,31 +99795,38 @@ var ts; function isBeforeBlockContext(context) { return nodeIsBlockContext(context.nextTokenParent); } + // IMPORTANT!!! This method must return true ONLY for nodes with open and close braces as immediate children function nodeIsBlockContext(node) { if (nodeIsTypeScriptDeclWithBlockContext(node)) { + // This means we are in a context that looks like a block to the user, but in the grammar is actually not a node (it's a class, module, enum, object type literal, etc). return true; } switch (node.kind) { - case 213: - case 241: - case 184: - case 240: + case 213 /* Block */: + case 241 /* CaseBlock */: + case 184 /* ObjectLiteralExpression */: + case 240 /* ModuleBlock */: return true; } return false; } function isFunctionDeclContext(context) { switch (context.contextNode.kind) { - case 234: - case 154: - case 153: - case 156: - case 157: - case 158: - case 192: - case 155: - case 193: - case 236: + case 234 /* FunctionDeclaration */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + // case SyntaxKind.MemberFunctionDeclaration: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + // case SyntaxKind.MethodSignature: + case 158 /* CallSignature */: + case 192 /* FunctionExpression */: + case 155 /* Constructor */: + case 193 /* ArrowFunction */: + // case SyntaxKind.ConstructorDeclaration: + // case SyntaxKind.SimpleArrowFunctionExpression: + // case SyntaxKind.ParenthesizedArrowFunctionExpression: + case 236 /* InterfaceDeclaration */: // This one is not truly a function, but for formatting purposes, it acts just like one return true; } return false; @@ -83352,39 +99835,40 @@ var ts; return !isFunctionDeclContext(context); } function isFunctionDeclarationOrFunctionExpressionContext(context) { - return context.contextNode.kind === 234 || context.contextNode.kind === 192; + return context.contextNode.kind === 234 /* FunctionDeclaration */ || context.contextNode.kind === 192 /* FunctionExpression */; } function isTypeScriptDeclWithBlockContext(context) { return nodeIsTypeScriptDeclWithBlockContext(context.contextNode); } function nodeIsTypeScriptDeclWithBlockContext(node) { switch (node.kind) { - case 235: - case 205: - case 236: - case 238: - case 166: - case 239: - case 250: - case 251: - case 244: - case 247: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 236 /* InterfaceDeclaration */: + case 238 /* EnumDeclaration */: + case 166 /* TypeLiteral */: + case 239 /* ModuleDeclaration */: + case 250 /* ExportDeclaration */: + case 251 /* NamedExports */: + case 244 /* ImportDeclaration */: + case 247 /* NamedImports */: return true; } return false; } function isAfterCodeBlockContext(context) { switch (context.currentTokenParent.kind) { - case 235: - case 239: - case 238: - case 269: - case 240: - case 227: + case 235 /* ClassDeclaration */: + case 239 /* ModuleDeclaration */: + case 238 /* EnumDeclaration */: + case 269 /* CatchClause */: + case 240 /* ModuleBlock */: + case 227 /* SwitchStatement */: return true; - case 213: { + case 213 /* Block */: { var blockParent = context.currentTokenParent.parent; - if (!blockParent || blockParent.kind !== 193 && blockParent.kind !== 192) { + // In a codefix scenario, we can't rely on parents being set. So just always return true. + if (!blockParent || blockParent.kind !== 193 /* ArrowFunction */ && blockParent.kind !== 192 /* FunctionExpression */) { return true; } } @@ -83393,62 +99877,64 @@ var ts; } function isControlDeclContext(context) { switch (context.contextNode.kind) { - case 217: - case 227: - case 220: - case 221: - case 222: - case 219: - case 230: - case 218: - case 226: - case 269: + case 217 /* IfStatement */: + case 227 /* SwitchStatement */: + case 220 /* ForStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 219 /* WhileStatement */: + case 230 /* TryStatement */: + case 218 /* DoStatement */: + case 226 /* WithStatement */: + // TODO + // case SyntaxKind.ElseClause: + case 269 /* CatchClause */: return true; default: return false; } } function isObjectContext(context) { - return context.contextNode.kind === 184; + return context.contextNode.kind === 184 /* ObjectLiteralExpression */; } function isFunctionCallContext(context) { - return context.contextNode.kind === 187; + return context.contextNode.kind === 187 /* CallExpression */; } function isNewContext(context) { - return context.contextNode.kind === 188; + return context.contextNode.kind === 188 /* NewExpression */; } function isFunctionCallOrNewContext(context) { return isFunctionCallContext(context) || isNewContext(context); } function isPreviousTokenNotComma(context) { - return context.currentTokenSpan.kind !== 26; + return context.currentTokenSpan.kind !== 26 /* CommaToken */; } function isNextTokenNotCloseBracket(context) { - return context.nextTokenSpan.kind !== 22; + return context.nextTokenSpan.kind !== 22 /* CloseBracketToken */; } function isArrowFunctionContext(context) { - return context.contextNode.kind === 193; + return context.contextNode.kind === 193 /* ArrowFunction */; } function isImportTypeContext(context) { - return context.contextNode.kind === 179; + return context.contextNode.kind === 179 /* ImportType */; } function isNonJsxSameLineTokenContext(context) { - return context.TokensAreOnSameLine() && context.contextNode.kind !== 10; + return context.TokensAreOnSameLine() && context.contextNode.kind !== 10 /* JsxText */; } function isNonJsxElementOrFragmentContext(context) { - return context.contextNode.kind !== 255 && context.contextNode.kind !== 259; + return context.contextNode.kind !== 255 /* JsxElement */ && context.contextNode.kind !== 259 /* JsxFragment */; } function isJsxExpressionContext(context) { - return context.contextNode.kind === 265 || context.contextNode.kind === 264; + return context.contextNode.kind === 265 /* JsxExpression */ || context.contextNode.kind === 264 /* JsxSpreadAttribute */; } function isNextTokenParentJsxAttribute(context) { - return context.nextTokenParent.kind === 262; + return context.nextTokenParent.kind === 262 /* JsxAttribute */; } function isJsxAttributeContext(context) { - return context.contextNode.kind === 262; + return context.contextNode.kind === 262 /* JsxAttribute */; } function isJsxSelfClosingElementContext(context) { - return context.contextNode.kind === 256; + return context.contextNode.kind === 256 /* JsxSelfClosingElement */; } function isNotBeforeBlockInFunctionDeclarationContext(context) { return !isFunctionDeclContext(context) && !isBeforeBlockContext(context); @@ -83463,45 +99949,45 @@ var ts; while (ts.isExpressionNode(node)) { node = node.parent; } - return node.kind === 150; + return node.kind === 150 /* Decorator */; } function isStartOfVariableDeclarationList(context) { - return context.currentTokenParent.kind === 233 && + return context.currentTokenParent.kind === 233 /* VariableDeclarationList */ && context.currentTokenParent.getStart(context.sourceFile) === context.currentTokenSpan.pos; } function isNotFormatOnEnter(context) { - return context.formattingRequestKind !== 2; + return context.formattingRequestKind !== 2 /* FormatOnEnter */; } function isModuleDeclContext(context) { - return context.contextNode.kind === 239; + return context.contextNode.kind === 239 /* ModuleDeclaration */; } function isObjectTypeContext(context) { - return context.contextNode.kind === 166; + return context.contextNode.kind === 166 /* TypeLiteral */; // && context.contextNode.parent.kind !== SyntaxKind.InterfaceDeclaration; } function isConstructorSignatureContext(context) { - return context.contextNode.kind === 159; + return context.contextNode.kind === 159 /* ConstructSignature */; } function isTypeArgumentOrParameterOrAssertion(token, parent) { - if (token.kind !== 27 && token.kind !== 29) { + if (token.kind !== 27 /* LessThanToken */ && token.kind !== 29 /* GreaterThanToken */) { return false; } switch (parent.kind) { - case 162: - case 190: - case 237: - case 235: - case 205: - case 236: - case 234: - case 192: - case 193: - case 154: - case 153: - case 158: - case 159: - case 187: - case 188: - case 207: + case 162 /* TypeReference */: + case 190 /* TypeAssertionExpression */: + case 237 /* TypeAliasDeclaration */: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 236 /* InterfaceDeclaration */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 187 /* CallExpression */: + case 188 /* NewExpression */: + case 207 /* ExpressionWithTypeArguments */: return true; default: return false; @@ -83512,19 +99998,20 @@ var ts; isTypeArgumentOrParameterOrAssertion(context.nextTokenSpan, context.nextTokenParent); } function isTypeAssertionContext(context) { - return context.contextNode.kind === 190; + return context.contextNode.kind === 190 /* TypeAssertionExpression */; } function isVoidOpContext(context) { - return context.currentTokenSpan.kind === 105 && context.currentTokenParent.kind === 196; + return context.currentTokenSpan.kind === 105 /* VoidKeyword */ && context.currentTokenParent.kind === 196 /* VoidExpression */; } function isYieldOrYieldStarWithOperand(context) { - return context.contextNode.kind === 203 && context.contextNode.expression !== undefined; + return context.contextNode.kind === 203 /* YieldExpression */ && context.contextNode.expression !== undefined; } function isNonNullAssertionContext(context) { - return context.contextNode.kind === 209; + return context.contextNode.kind === 209 /* NonNullExpression */; } })(formatting = ts.formatting || (ts.formatting = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var formatting; @@ -83548,7 +100035,9 @@ var ts; }; } function buildMap(rules) { + // Map from bucket index to array of rules var map = new Array(mapRowLength * mapRowLength); + // This array is used only during construction of the rulesbucket in the map var rulesBucketConstructionStateList = new Array(map.length); for (var _i = 0, rules_1 = rules; _i < rules_1.length; _i++) { var rule = rules_1[_i]; @@ -83569,12 +100058,12 @@ var ts; return map; } function getRuleBucketIndex(row, column) { - ts.Debug.assert(row <= 145 && column <= 145, "Must compute formatting context from tokens"); + ts.Debug.assert(row <= 145 /* LastKeyword */ && column <= 145 /* LastKeyword */, "Must compute formatting context from tokens"); return (row * mapRowLength) + column; } var maskBitSize = 5; - var mask = 31; - var mapRowLength = 145 + 1; + var mask = 31; // MaskBitSize bits + var mapRowLength = 145 /* LastToken */ + 1; var RulesPosition; (function (RulesPosition) { RulesPosition[RulesPosition["IgnoreRulesSpecific"] = 0] = "IgnoreRulesSpecific"; @@ -83584,8 +100073,23 @@ var ts; RulesPosition[RulesPosition["NoContextRulesSpecific"] = maskBitSize * 4] = "NoContextRulesSpecific"; RulesPosition[RulesPosition["NoContextRulesAny"] = maskBitSize * 5] = "NoContextRulesAny"; })(RulesPosition || (RulesPosition = {})); + // The Rules list contains all the inserted rules into a rulebucket in the following order: + // 1- Ignore rules with specific token combination + // 2- Ignore rules with any token combination + // 3- Context rules with specific token combination + // 4- Context rules with any token combination + // 5- Non-context rules with specific token combination + // 6- Non-context rules with any token combination + // + // The member rulesInsertionIndexBitmap is used to describe the number of rules + // in each sub-bucket (above) hence can be used to know the index of where to insert + // the next rule. It's a bitmap which contains 6 different sections each is given 5 bits. + // + // Example: + // In order to insert a rule to the end of sub-bucket (3), we get the index by adding + // the values in the bitmap segments 3rd, 2nd, and 1st. function addRule(rules, rule, specificTokens, constructionState, rulesBucketIndex) { - var position = rule.action === 1 + var position = rule.action === 1 /* Ignore */ ? specificTokens ? RulesPosition.IgnoreRulesSpecific : RulesPosition.IgnoreRulesAny : rule.context !== formatting.anyContext ? specificTokens ? RulesPosition.ContextRulesSpecific : RulesPosition.ContextRulesAny @@ -83609,6 +100113,7 @@ var ts; } })(formatting = ts.formatting || (ts.formatting = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var formatting; @@ -83622,42 +100127,64 @@ var ts; if (line === 0) { return []; } + // After the enter key, the cursor is now at a new line. The new line may or may not contain non-whitespace characters. + // If the new line has only whitespaces, we won't want to format this line, because that would remove the indentation as + // trailing whitespaces. So the end of the formatting span should be the later one between: + // 1. the end of the previous line + // 2. the last non-whitespace character in the current line var endOfFormatSpan = ts.getEndLinePosition(line, sourceFile); while (ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(endOfFormatSpan))) { endOfFormatSpan--; } + // if the character at the end of the span is a line break, we shouldn't include it, because it indicates we don't want to + // touch the current line at all. Also, on some OSes the line break consists of two characters (\r\n), we should test if the + // previous character before the end of format span is line break character as well. if (ts.isLineBreak(sourceFile.text.charCodeAt(endOfFormatSpan))) { endOfFormatSpan--; } var span = { + // get start position for the previous line pos: ts.getStartPositionOfLine(line - 1, sourceFile), + // end value is exclusive so add 1 to the result end: endOfFormatSpan + 1 }; - return formatSpan(span, sourceFile, formatContext, 2); + return formatSpan(span, sourceFile, formatContext, 2 /* FormatOnEnter */); } formatting.formatOnEnter = formatOnEnter; function formatOnSemicolon(position, sourceFile, formatContext) { - var semicolon = findImmediatelyPrecedingTokenOfKind(position, 25, sourceFile); - return formatNodeLines(findOutermostNodeWithinListLevel(semicolon), sourceFile, formatContext, 3); + var semicolon = findImmediatelyPrecedingTokenOfKind(position, 25 /* SemicolonToken */, sourceFile); + return formatNodeLines(findOutermostNodeWithinListLevel(semicolon), sourceFile, formatContext, 3 /* FormatOnSemicolon */); } formatting.formatOnSemicolon = formatOnSemicolon; function formatOnOpeningCurly(position, sourceFile, formatContext) { - var openingCurly = findImmediatelyPrecedingTokenOfKind(position, 17, sourceFile); + var openingCurly = findImmediatelyPrecedingTokenOfKind(position, 17 /* OpenBraceToken */, sourceFile); if (!openingCurly) { return []; } var curlyBraceRange = openingCurly.parent; var outermostNode = findOutermostNodeWithinListLevel(curlyBraceRange); + /** + * We limit the span to end at the opening curly to handle the case where + * the brace matched to that just typed will be incorrect after further edits. + * For example, we could type the opening curly for the following method + * body without brace-matching activated: + * ``` + * class C { + * foo() + * } + * ``` + * and we wouldn't want to move the closing brace. + */ var textRange = { pos: ts.getLineStartPositionForPosition(outermostNode.getStart(sourceFile), sourceFile), end: position }; - return formatSpan(textRange, sourceFile, formatContext, 4); + return formatSpan(textRange, sourceFile, formatContext, 4 /* FormatOnOpeningCurlyBrace */); } formatting.formatOnOpeningCurly = formatOnOpeningCurly; function formatOnClosingCurly(position, sourceFile, formatContext) { - var precedingToken = findImmediatelyPrecedingTokenOfKind(position, 18, sourceFile); - return formatNodeLines(findOutermostNodeWithinListLevel(precedingToken), sourceFile, formatContext, 5); + var precedingToken = findImmediatelyPrecedingTokenOfKind(position, 18 /* CloseBraceToken */, sourceFile); + return formatNodeLines(findOutermostNodeWithinListLevel(precedingToken), sourceFile, formatContext, 5 /* FormatOnClosingCurlyBrace */); } formatting.formatOnClosingCurly = formatOnClosingCurly; function formatDocument(sourceFile, formatContext) { @@ -83665,23 +100192,41 @@ var ts; pos: 0, end: sourceFile.text.length }; - return formatSpan(span, sourceFile, formatContext, 0); + return formatSpan(span, sourceFile, formatContext, 0 /* FormatDocument */); } formatting.formatDocument = formatDocument; function formatSelection(start, end, sourceFile, formatContext) { + // format from the beginning of the line var span = { pos: ts.getLineStartPositionForPosition(start, sourceFile), end: end, }; - return formatSpan(span, sourceFile, formatContext, 1); + return formatSpan(span, sourceFile, formatContext, 1 /* FormatSelection */); } formatting.formatSelection = formatSelection; + /** + * Validating `expectedTokenKind` ensures the token was typed in the context we expect (eg: not a comment). + * @param expectedTokenKind The kind of the last token constituting the desired parent node. + */ function findImmediatelyPrecedingTokenOfKind(end, expectedTokenKind, sourceFile) { var precedingToken = ts.findPrecedingToken(end, sourceFile); return precedingToken && precedingToken.kind === expectedTokenKind && end === precedingToken.getEnd() ? precedingToken : undefined; } + /** + * Finds the highest node enclosing `node` at the same list level as `node` + * and whose end does not exceed `node.end`. + * + * Consider typing the following + * ``` + * let x = 1; + * while (true) { + * } + * ``` + * Upon typing the closing curly, we want to format the entire `while`-statement, but not the preceding + * variable declaration. + */ function findOutermostNodeWithinListLevel(node) { var current = node; while (current && @@ -83692,23 +100237,26 @@ var ts; } return current; } + // Returns true if node is a element in some list in parent + // i.e. parent is class declaration with the list of members and node is one of members. function isListElement(parent, node) { switch (parent.kind) { - case 235: - case 236: + case 235 /* ClassDeclaration */: + case 236 /* InterfaceDeclaration */: return ts.rangeContainsRange(parent.members, node); - case 239: + case 239 /* ModuleDeclaration */: var body = parent.body; - return !!body && body.kind === 240 && ts.rangeContainsRange(body.statements, node); - case 274: - case 213: - case 240: + return !!body && body.kind === 240 /* ModuleBlock */ && ts.rangeContainsRange(body.statements, node); + case 274 /* SourceFile */: + case 213 /* Block */: + case 240 /* ModuleBlock */: return ts.rangeContainsRange(parent.statements, node); - case 269: + case 269 /* CatchClause */: return ts.rangeContainsRange(parent.block.statements, node); } return false; } + /** find node that fully contains given text range */ function findEnclosingNode(range, sourceFile) { return find(sourceFile); function find(n) { @@ -83722,27 +100270,37 @@ var ts; return n; } } + /** formatting is not applied to ranges that contain parse errors. + * This function will return a predicate that for a given text range will tell + * if there are any parse errors that overlap with the range. + */ function prepareRangeContainsErrorFunction(errors, originalRange) { if (!errors.length) { return rangeHasNoErrors; } + // pick only errors that fall in range var sorted = errors - .filter(function (d) { return ts.rangeOverlapsWithStartEnd(originalRange, d.start, d.start + d.length); }) + .filter(function (d) { return ts.rangeOverlapsWithStartEnd(originalRange, d.start, d.start + d.length); }) // TODO: GH#18217 .sort(function (e1, e2) { return e1.start - e2.start; }); if (!sorted.length) { return rangeHasNoErrors; } var index = 0; return function (r) { + // in current implementation sequence of arguments [r1, r2...] is monotonically increasing. + // 'index' tracks the index of the most recent error that was checked. while (true) { if (index >= sorted.length) { + // all errors in the range were already checked -> no error in specified range return false; } var error = sorted[index]; if (r.end <= error.start) { + // specified range ends before the error refered by 'index' - no error in range return false; } if (ts.startEndOverlapsWithStartEnd(r.pos, r.end, error.start, error.start + error.length)) { + // specified range overlaps with error range return true; } index++; @@ -83752,6 +100310,11 @@ var ts; return false; } } + /** + * Start of the original range might fall inside the comment - scanner will not yield appropriate results + * This function will look for token that is located before the start of target range + * and return its end as start position for the scanner. + */ function getScanStartPosition(enclosingNode, originalRange, sourceFile) { var start = enclosingNode.getStart(sourceFile); if (start === originalRange.pos && enclosingNode.end === originalRange.end) { @@ -83759,19 +100322,37 @@ var ts; } var precedingToken = ts.findPrecedingToken(originalRange.pos, sourceFile); if (!precedingToken) { + // no preceding token found - start from the beginning of enclosing node return enclosingNode.pos; } + // preceding token ends after the start of original range (i.e when originalRange.pos falls in the middle of literal) + // start from the beginning of enclosingNode to handle the entire 'originalRange' if (precedingToken.end >= originalRange.pos) { return enclosingNode.pos; } return precedingToken.end; } + /* + * For cases like + * if (a || + * b ||$ + * c) {...} + * If we hit Enter at $ we want line ' b ||' to be indented. + * Formatting will be applied to the last two lines. + * Node that fully encloses these lines is binary expression 'a ||...'. + * Initial indentation for this node will be 0. + * Binary expressions don't introduce new indentation scopes, however it is possible + * that some parent node on the same line does - like if statement in this case. + * Note that we are considering parents only from the same line with initial node - + * if parent is on the different line - its delta was already contributed + * to the initial indentation. + */ function getOwnOrInheritedDelta(n, options, sourceFile) { - var previousLine = -1; + var previousLine = -1 /* Unknown */; var child; while (n) { var line = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)).line; - if (previousLine !== -1 && line !== previousLine) { + if (previousLine !== -1 /* Unknown */ && line !== previousLine) { break; } if (formatting.SmartIndenter.shouldIndentChildNode(options, n, child, sourceFile)) { @@ -83783,9 +100364,11 @@ var ts; } return 0; } + /* @internal */ function formatNodeGivenIndentation(node, sourceFileLike, languageVariant, initialIndentation, delta, formatContext) { var range = { pos: 0, end: sourceFileLike.text.length }; - return formatting.getFormattingScanner(sourceFileLike.text, languageVariant, range.pos, range.end, function (scanner) { return formatSpanWorker(range, node, initialIndentation, delta, scanner, formatContext, 1, function (_) { return false; }, sourceFileLike); }); + return formatting.getFormattingScanner(sourceFileLike.text, languageVariant, range.pos, range.end, function (scanner) { return formatSpanWorker(range, node, initialIndentation, delta, scanner, formatContext, 1 /* FormatSelection */, function (_) { return false; }, // assume that node does not have any errors + sourceFileLike); }); } formatting.formatNodeGivenIndentation = formatNodeGivenIndentation; function formatNodeLines(node, sourceFile, formatContext, requestKind) { @@ -83799,11 +100382,13 @@ var ts; return formatSpan(span, sourceFile, formatContext, requestKind); } function formatSpan(originalRange, sourceFile, formatContext, requestKind) { + // find the smallest node that fully wraps the range and compute the initial indentation for the node var enclosingNode = findEnclosingNode(originalRange, sourceFile); return formatting.getFormattingScanner(sourceFile.text, sourceFile.languageVariant, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end, function (scanner) { return formatSpanWorker(originalRange, enclosingNode, formatting.SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, formatContext.options), getOwnOrInheritedDelta(enclosingNode, formatContext.options, sourceFile), scanner, formatContext, requestKind, prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange), sourceFile); }); } function formatSpanWorker(originalRange, enclosingNode, initialIndentation, delta, formattingScanner, _a, requestKind, rangeContainsError, sourceFile) { var options = _a.options, getRule = _a.getRule; + // formatting context is used by rules provider var formattingContext = new formatting.FormattingContext(sourceFile, requestKind, options); var previousRange; var previousParent; @@ -83823,15 +100408,23 @@ var ts; if (!formattingScanner.isOnToken()) { var leadingTrivia = formattingScanner.getCurrentLeadingTrivia(); if (leadingTrivia) { - processTrivia(leadingTrivia, enclosingNode, enclosingNode, undefined); + processTrivia(leadingTrivia, enclosingNode, enclosingNode, /*dynamicIndentation*/ undefined); // TODO: GH#18217 trimTrailingWhitespacesForRemainingRange(); } } return edits; + // local functions + /** Tries to compute the indentation for a list element. + * If list element is not in range then + * function will pick its actual indentation + * so it can be pushed downstream as inherited indentation. + * If list element is in the range - its indentation will be equal + * to inherited indentation from its predecessors. + */ function tryComputeIndentationForListItem(startPos, endPos, parentStartLine, range, inheritedIndentation) { if (ts.rangeOverlapsWithStartEnd(range, startPos, endPos) || - ts.rangeContainsStartEnd(range, startPos, endPos)) { - if (inheritedIndentation !== -1) { + ts.rangeContainsStartEnd(range, startPos, endPos) /* Not to miss zero-range nodes e.g. JsxText */) { + if (inheritedIndentation !== -1 /* Unknown */) { return inheritedIndentation; } } @@ -83840,22 +100433,29 @@ var ts; var startLinePosition = ts.getLineStartPositionForPosition(startPos, sourceFile); var column = formatting.SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, startPos, sourceFile, options); if (startLine !== parentStartLine || startPos === column) { + // Use the base indent size if it is greater than + // the indentation of the inherited predecessor. var baseIndentSize = formatting.SmartIndenter.getBaseIndentation(options); return baseIndentSize > column ? baseIndentSize : column; } } - return -1; + return -1 /* Unknown */; } function computeIndentation(node, startLine, inheritedIndentation, parent, parentDynamicIndentation, effectiveParentStartLine) { var delta = formatting.SmartIndenter.shouldIndentChildNode(options, node) ? options.indentSize : 0; if (effectiveParentStartLine === startLine) { + // if node is located on the same line with the parent + // - inherit indentation from the parent + // - push children if either parent of node itself has non-zero delta return { indentation: startLine === lastIndentedLine ? indentationOnLastIndentedLine : parentDynamicIndentation.getIndentation(), delta: Math.min(options.indentSize, parentDynamicIndentation.getDelta(node) + delta) }; } - else if (inheritedIndentation === -1) { - if (node.kind === 19 && startLine === lastIndentedLine) { + else if (inheritedIndentation === -1 /* Unknown */) { + if (node.kind === 19 /* OpenParenToken */ && startLine === lastIndentedLine) { + // the is used for chaining methods formatting + // - we need to get the indentation on last line and the delta of parent return { indentation: indentationOnLastIndentedLine, delta: parentDynamicIndentation.getDelta(node) }; } else if (formatting.SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile)) { @@ -83874,18 +100474,19 @@ var ts; return node.modifiers[0].kind; } switch (node.kind) { - case 235: return 75; - case 236: return 109; - case 234: return 89; - case 238: return 238; - case 156: return 125; - case 157: return 136; - case 154: + case 235 /* ClassDeclaration */: return 75 /* ClassKeyword */; + case 236 /* InterfaceDeclaration */: return 109 /* InterfaceKeyword */; + case 234 /* FunctionDeclaration */: return 89 /* FunctionKeyword */; + case 238 /* EnumDeclaration */: return 238 /* EnumDeclaration */; + case 156 /* GetAccessor */: return 125 /* GetKeyword */; + case 157 /* SetAccessor */: return 136 /* SetKeyword */; + case 154 /* MethodDeclaration */: if (node.asteriskToken) { - return 39; + return 39 /* AsteriskToken */; } - case 152: - case 149: + // falls through + case 152 /* PropertyDeclaration */: + case 149 /* Parameter */: return ts.getNameOfDeclaration(node).kind; } } @@ -83893,12 +100494,16 @@ var ts; return { getIndentationForComment: function (kind, tokenIndentation, container) { switch (kind) { - case 18: - case 22: - case 20: + // preceding comment to the token that closes the indentation scope inherits the indentation from the scope + // .. { + // // comment + // } + case 18 /* CloseBraceToken */: + case 22 /* CloseBracketToken */: + case 20 /* CloseParenToken */: return indentation + getDelta(container); } - return tokenIndentation !== -1 ? tokenIndentation : indentation; + return tokenIndentation !== -1 /* Unknown */ ? tokenIndentation : indentation; }, getIndentationForToken: function (line, kind, container) { return shouldAddDelta(line, kind, container) ? indentation + getDelta(container) : indentation; @@ -83914,35 +100519,39 @@ var ts; }; function shouldAddDelta(line, kind, container) { switch (kind) { - case 17: - case 18: - case 19: - case 20: - case 82: - case 106: - case 57: + // open and close brace, 'else' and 'while' (in do statement) tokens has indentation of the parent + case 17 /* OpenBraceToken */: + case 18 /* CloseBraceToken */: + case 19 /* OpenParenToken */: + case 20 /* CloseParenToken */: + case 82 /* ElseKeyword */: + case 106 /* WhileKeyword */: + case 57 /* AtToken */: return false; - case 41: - case 29: + case 41 /* SlashToken */: + case 29 /* GreaterThanToken */: switch (container.kind) { - case 257: - case 258: - case 256: + case 257 /* JsxOpeningElement */: + case 258 /* JsxClosingElement */: + case 256 /* JsxSelfClosingElement */: return false; } break; - case 21: - case 22: - if (container.kind !== 177) { + case 21 /* OpenBracketToken */: + case 22 /* CloseBracketToken */: + if (container.kind !== 177 /* MappedType */) { return false; } break; } + // if token line equals to the line of containing node (this is a first token in the node) - use node indentation return nodeStartLine !== line + // if this token is the first token following the list of decorators, we do not need to indent && !(node.decorators && kind === getFirstNonDecoratorTokenOfNode(node)); } function getDelta(child) { - return formatting.SmartIndenter.nodeWillIndentChild(options, node, child, sourceFile, true) ? delta : 0; + // Delta value should be zero when the node explicitly prevents indentation of the child node + return formatting.SmartIndenter.nodeWillIndentChild(options, node, child, sourceFile, /*indentByDefault*/ true) ? delta : 0; } } function processNode(node, contextNode, nodeStartLine, undecoratedNodeStartLine, indentation, delta) { @@ -83950,12 +100559,26 @@ var ts; return; } var nodeDynamicIndentation = getDynamicIndentation(node, nodeStartLine, indentation, delta); + // a useful observations when tracking context node + // / + // [a] + // / | \ + // [b] [c] [d] + // node 'a' is a context node for nodes 'b', 'c', 'd' + // except for the leftmost leaf token in [b] - in this case context node ('e') is located somewhere above 'a' + // this rule can be applied recursively to child nodes of 'a'. + // + // context node is set to parent node value after processing every child node + // context node is set to parent of the token after processing every token var childContextNode = contextNode; + // if there are any tokens that logically belong to node and interleave child nodes + // such tokens will be consumed in processChildNode for the child that follows them ts.forEachChild(node, function (child) { - processChildNode(child, -1, node, nodeDynamicIndentation, nodeStartLine, undecoratedNodeStartLine, false); + processChildNode(child, /*inheritedIndentation*/ -1 /* Unknown */, node, nodeDynamicIndentation, nodeStartLine, undecoratedNodeStartLine, /*isListItem*/ false); }, function (nodes) { processChildNodes(nodes, node, nodeStartLine, nodeDynamicIndentation); }); + // proceed any tokens in the node that are located after child nodes while (formattingScanner.isOnToken()) { var tokenInfo = formattingScanner.readTokenInfo(node); if (tokenInfo.token.end > node.end) { @@ -83970,13 +100593,15 @@ var ts; if (child.decorators) { undecoratedChildStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(child, sourceFile)).line; } - var childIndentationAmount = -1; + // if child is a list item - try to get its indentation, only if parent is within the original range. + var childIndentationAmount = -1 /* Unknown */; if (isListItem && ts.rangeContainsRange(originalRange, parent)) { childIndentationAmount = tryComputeIndentationForListItem(childStartPos, child.end, parentStartLine, originalRange, inheritedIndentation); - if (childIndentationAmount !== -1) { + if (childIndentationAmount !== -1 /* Unknown */) { inheritedIndentation = childIndentationAmount; } } + // child node is outside the target range - do not dive inside if (!ts.rangeOverlapsWithStartEnd(originalRange, child.pos, child.end)) { if (child.end < originalRange.pos) { formattingScanner.skipToEndOf(child); @@ -83987,8 +100612,10 @@ var ts; return inheritedIndentation; } while (formattingScanner.isOnToken()) { + // proceed any parent tokens that are located prior to child.getStart() var tokenInfo = formattingScanner.readTokenInfo(node); if (tokenInfo.token.end > childStartPos) { + // stop when formatting scanner advances past the beginning of the child break; } consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, node); @@ -83996,21 +100623,23 @@ var ts; if (!formattingScanner.isOnToken()) { return inheritedIndentation; } - if (ts.isToken(child) && child.kind !== 10) { + // JSX text shouldn't affect indenting + if (ts.isToken(child) && child.kind !== 10 /* JsxText */) { + // if child node is a token, it does not impact indentation, proceed it using parent indentation scope rules var tokenInfo = formattingScanner.readTokenInfo(child); ts.Debug.assert(tokenInfo.token.end === child.end, "Token end is child end"); consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, child); return inheritedIndentation; } - var effectiveParentStartLine = child.kind === 150 ? childStartLine : undecoratedParentStartLine; + var effectiveParentStartLine = child.kind === 150 /* Decorator */ ? childStartLine : undecoratedParentStartLine; var childIndentation = computeIndentation(child, childStartLine, childIndentationAmount, node, parentDynamicIndentation, effectiveParentStartLine); processNode(child, childContextNode, childStartLine, undecoratedChildStartLine, childIndentation.indentation, childIndentation.delta); - if (child.kind === 10) { + if (child.kind === 10 /* JsxText */) { var range = { pos: child.getStart(), end: child.getEnd() }; - indentMultilineCommentOrJsxText(range, childIndentation.indentation, true, false); + indentMultilineCommentOrJsxText(range, childIndentation.indentation, /*firstLineIsIndented*/ true, /*indentFinalLine*/ false); } childContextNode = node; - if (isFirstListItem && parent.kind === 183 && inheritedIndentation === -1) { + if (isFirstListItem && parent.kind === 183 /* ArrayLiteralExpression */ && inheritedIndentation === -1 /* Unknown */) { inheritedIndentation = childIndentation.indentation; } return inheritedIndentation; @@ -84021,32 +100650,41 @@ var ts; var listEndToken = getCloseTokenForOpenToken(listStartToken); var listDynamicIndentation = parentDynamicIndentation; var startLine = parentStartLine; - if (listStartToken !== 0) { + if (listStartToken !== 0 /* Unknown */) { + // introduce a new indentation scope for lists (including list start and end tokens) while (formattingScanner.isOnToken()) { var tokenInfo = formattingScanner.readTokenInfo(parent); if (tokenInfo.token.end > nodes.pos) { + // stop when formatting scanner moves past the beginning of node list break; } else if (tokenInfo.token.kind === listStartToken) { + // consume list start token startLine = sourceFile.getLineAndCharacterOfPosition(tokenInfo.token.pos).line; - var indentation_2 = computeIndentation(tokenInfo.token, startLine, -1, parent, parentDynamicIndentation, parentStartLine); + var indentation_2 = computeIndentation(tokenInfo.token, startLine, -1 /* Unknown */, parent, parentDynamicIndentation, parentStartLine); listDynamicIndentation = getDynamicIndentation(parent, parentStartLine, indentation_2.indentation, indentation_2.delta); consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation, parent); } else { + // consume any tokens that precede the list as child elements of 'node' using its indentation scope consumeTokenAndAdvanceScanner(tokenInfo, parent, parentDynamicIndentation, parent); } } } - var inheritedIndentation = -1; + var inheritedIndentation = -1 /* Unknown */; for (var i = 0; i < nodes.length; i++) { var child = nodes[i]; - inheritedIndentation = processChildNode(child, inheritedIndentation, node, listDynamicIndentation, startLine, startLine, true, i === 0); + inheritedIndentation = processChildNode(child, inheritedIndentation, node, listDynamicIndentation, startLine, startLine, /*isListItem*/ true, /*isFirstListItem*/ i === 0); } - if (listEndToken !== 0) { + if (listEndToken !== 0 /* Unknown */) { if (formattingScanner.isOnToken()) { var tokenInfo = formattingScanner.readTokenInfo(parent); + // consume the list end token only if it is still belong to the parent + // there might be the case when current token matches end token but does not considered as one + // function (x: function) <-- + // without this check close paren will be interpreted as list end token for function expression which is wrong if (tokenInfo.token.kind === listEndToken && ts.rangeContainsRange(parent, tokenInfo.token)) { + // consume list end token consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation, parent); } } @@ -84059,20 +100697,23 @@ var ts; if (currentTokenInfo.leadingTrivia) { processTrivia(currentTokenInfo.leadingTrivia, parent, childContextNode, dynamicIndentation); } - var lineAction = 0; + var lineAction = 0 /* None */; var isTokenInRange = ts.rangeContainsRange(originalRange, currentTokenInfo.token); var tokenStart = sourceFile.getLineAndCharacterOfPosition(currentTokenInfo.token.pos); if (isTokenInRange) { var rangeHasError = rangeContainsError(currentTokenInfo.token); + // save previousRange since processRange will overwrite this value with current one var savePreviousRange = previousRange; lineAction = processRange(currentTokenInfo.token, tokenStart, parent, childContextNode, dynamicIndentation); + // do not indent comments\token if token range overlaps with some error if (!rangeHasError) { - if (lineAction === 0) { + if (lineAction === 0 /* None */) { + // indent token only if end line of previous range does not match start line of the token var prevEndLine = savePreviousRange && sourceFile.getLineAndCharacterOfPosition(savePreviousRange.end).line; indentToken = lastTriviaWasNewLine && tokenStart.line !== prevEndLine; } else { - indentToken = lineAction === 1; + indentToken = lineAction === 1 /* LineAdded */; } } } @@ -84082,7 +100723,7 @@ var ts; if (indentToken) { var tokenIndentation = (isTokenInRange && !rangeContainsError(currentTokenInfo.token)) ? dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind, container) : - -1; + -1 /* Unknown */; var indentNextTokenOrTrivia = true; if (currentTokenInfo.leadingTrivia) { var commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind, tokenIndentation, container); @@ -84090,26 +100731,27 @@ var ts; var triviaItem = _a[_i]; var triviaInRange = ts.rangeContainsRange(originalRange, triviaItem); switch (triviaItem.kind) { - case 3: + case 3 /* MultiLineCommentTrivia */: if (triviaInRange) { - indentMultilineCommentOrJsxText(triviaItem, commentIndentation, !indentNextTokenOrTrivia); + indentMultilineCommentOrJsxText(triviaItem, commentIndentation, /*firstLineIsIndented*/ !indentNextTokenOrTrivia); } indentNextTokenOrTrivia = false; break; - case 2: + case 2 /* SingleLineCommentTrivia */: if (indentNextTokenOrTrivia && triviaInRange) { - insertIndentation(triviaItem.pos, commentIndentation, false); + insertIndentation(triviaItem.pos, commentIndentation, /*lineAdded*/ false); } indentNextTokenOrTrivia = false; break; - case 4: + case 4 /* NewLineTrivia */: indentNextTokenOrTrivia = true; break; } } } - if (tokenIndentation !== -1 && indentNextTokenOrTrivia) { - insertIndentation(currentTokenInfo.token.pos, tokenIndentation, lineAction === 1); + // indent token only if is it is in target range and does not overlap with any error ranges + if (tokenIndentation !== -1 /* Unknown */ && indentNextTokenOrTrivia) { + insertIndentation(currentTokenInfo.token.pos, tokenIndentation, lineAction === 1 /* LineAdded */); lastIndentedLine = tokenStart.line; indentationOnLastIndentedLine = tokenIndentation; } @@ -84127,11 +100769,13 @@ var ts; } } } + // TODO: GH#18217 use an enum instead of `boolean | undefined` function processRange(range, rangeStart, parent, contextNode, dynamicIndentation) { var rangeHasError = rangeContainsError(range); - var lineAction = 0; + var lineAction = 0 /* None */; if (!rangeHasError) { if (!previousRange) { + // trim whitespaces starting from the beginning of the span up to the current line var originalStart = sourceFile.getLineAndCharacterOfPosition(originalRange.pos); trimTrailingWhitespacesForLines(originalStart.line, rangeStart.line); } @@ -84149,29 +100793,36 @@ var ts; formattingContext.updateContext(previousItem, previousParent, currentItem, currentParent, contextNode); var rule = getRule(formattingContext); var trimTrailingWhitespaces; - var lineAction = 0; + var lineAction = 0 /* None */; if (rule) { lineAction = applyRuleEdits(rule, previousItem, previousStartLine, currentItem, currentStartLine); switch (lineAction) { - case 2: + case 2 /* LineRemoved */: + // Handle the case where the next line is moved to be the end of this line. + // In this case we don't indent the next line in the next pass. if (currentParent.getStart(sourceFile) === currentItem.pos) { - dynamicIndentation.recomputeIndentation(false); + dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ false); } break; - case 1: + case 1 /* LineAdded */: + // Handle the case where token2 is moved to the new line. + // In this case we indent token2 in the next pass but we set + // sameLineIndent flag to notify the indenter that the indentation is within the line. if (currentParent.getStart(sourceFile) === currentItem.pos) { - dynamicIndentation.recomputeIndentation(true); + dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ true); } break; default: - ts.Debug.assert(lineAction === 0); + ts.Debug.assert(lineAction === 0 /* None */); } - trimTrailingWhitespaces = !(rule.action & 8) && rule.flags !== 1; + // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line + trimTrailingWhitespaces = !(rule.action & 8 /* Delete */) && rule.flags !== 1 /* CanDeleteNewLines */; } else { trimTrailingWhitespaces = true; } if (currentStartLine !== previousStartLine && trimTrailingWhitespaces) { + // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line trimTrailingWhitespacesForLines(previousStartLine, currentStartLine, previousItem); } return lineAction; @@ -84179,6 +100830,8 @@ var ts; function insertIndentation(pos, indentation, lineAdded) { var indentationString = getIndentationString(indentation, options); if (lineAdded) { + // new line is added before the token by the formatting rules + // insert indentation string at the very beginning of the token recordReplace(pos, 0, indentationString); } else { @@ -84192,7 +100845,7 @@ var ts; function characterToColumn(startLinePosition, characterInLine) { var column = 0; for (var i = 0; i < characterInLine; i++) { - if (sourceFile.text.charCodeAt(startLinePosition + i) === 9) { + if (sourceFile.text.charCodeAt(startLinePosition + i) === 9 /* tab */) { column += options.tabSize - column % options.tabSize; } else { @@ -84206,12 +100859,14 @@ var ts; } function indentMultilineCommentOrJsxText(commentRange, indentation, firstLineIsIndented, indentFinalLine) { if (indentFinalLine === void 0) { indentFinalLine = true; } + // split comment in lines var startLine = sourceFile.getLineAndCharacterOfPosition(commentRange.pos).line; var endLine = sourceFile.getLineAndCharacterOfPosition(commentRange.end).line; var parts; if (startLine === endLine) { if (!firstLineIsIndented) { - insertIndentation(commentRange.pos, indentation, false); + // treat as single line comment + insertIndentation(commentRange.pos, indentation, /*lineAdded*/ false); } return; } @@ -84237,6 +100892,7 @@ var ts; startIndex = 1; startLine++; } + // shift all parts on the delta size var delta = indentation - nonWhitespaceColumnInFirstPart.column; for (var i = startIndex; i < parts.length; i++, startLine++) { var startLinePos_1 = ts.getStartPositionOfLine(startLine, sourceFile); @@ -84257,6 +100913,7 @@ var ts; for (var line = line1; line < line2; line++) { var lineStartPosition = ts.getStartPositionOfLine(line, sourceFile); var lineEndPosition = ts.getEndLinePosition(line, sourceFile); + // do not trim whitespaces in comments or template expression if (range && (ts.isComment(range.kind) || ts.isStringOrRegularExpressionOrTemplateLiteral(range.kind)) && range.pos <= lineEndPosition && range.end > lineEndPosition) { continue; } @@ -84267,6 +100924,10 @@ var ts; } } } + /** + * @param start The position of the first character in range + * @param end The position of the last character in range + */ function getTrailingWhitespaceStartPosition(start, end) { var pos = end; while (pos >= start && ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(pos))) { @@ -84277,6 +100938,9 @@ var ts; } return -1; } + /** + * Trimming will be done for lines after the previous range + */ function trimTrailingWhitespacesForRemainingRange() { var startPosition = previousRange ? previousRange.end : originalRange.pos; var startLine = sourceFile.getLineAndCharacterOfPosition(startPosition).line; @@ -84296,35 +100960,42 @@ var ts; function applyRuleEdits(rule, previousRange, previousStartLine, currentRange, currentStartLine) { var onLaterLine = currentStartLine !== previousStartLine; switch (rule.action) { - case 1: - return 0; - case 8: + case 1 /* Ignore */: + // no action required + return 0 /* None */; + case 8 /* Delete */: if (previousRange.end !== currentRange.pos) { + // delete characters starting from t1.end up to t2.pos exclusive recordDelete(previousRange.end, currentRange.pos - previousRange.end); - return onLaterLine ? 2 : 0; + return onLaterLine ? 2 /* LineRemoved */ : 0 /* None */; } break; - case 4: - if (rule.flags !== 1 && previousStartLine !== currentStartLine) { - return 0; + case 4 /* NewLine */: + // exit early if we on different lines and rule cannot change number of newlines + // if line1 and line2 are on subsequent lines then no edits are required - ok to exit + // if line1 and line2 are separated with more than one newline - ok to exit since we cannot delete extra new lines + if (rule.flags !== 1 /* CanDeleteNewLines */ && previousStartLine !== currentStartLine) { + return 0 /* None */; } + // edit should not be applied if we have one line feed between elements var lineDelta = currentStartLine - previousStartLine; if (lineDelta !== 1) { recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.newLineCharacter); - return onLaterLine ? 0 : 1; + return onLaterLine ? 0 /* None */ : 1 /* LineAdded */; } break; - case 2: - if (rule.flags !== 1 && previousStartLine !== currentStartLine) { - return 0; + case 2 /* Space */: + // exit early if we on different lines and rule cannot change number of newlines + if (rule.flags !== 1 /* CanDeleteNewLines */ && previousStartLine !== currentStartLine) { + return 0 /* None */; } var posDelta = currentRange.pos - previousRange.end; - if (posDelta !== 1 || sourceFile.text.charCodeAt(previousRange.end) !== 32) { + if (posDelta !== 1 || sourceFile.text.charCodeAt(previousRange.end) !== 32 /* space */) { recordReplace(previousRange.end, currentRange.pos - previousRange.end, " "); - return onLaterLine ? 2 : 0; + return onLaterLine ? 2 /* LineRemoved */ : 0 /* None */; } } - return 0; + return 0 /* None */; } } var LineAction; @@ -84333,8 +101004,12 @@ var ts; LineAction[LineAction["LineAdded"] = 1] = "LineAdded"; LineAction[LineAction["LineRemoved"] = 2] = "LineRemoved"; })(LineAction || (LineAction = {})); - function getRangeOfEnclosingComment(sourceFile, position, onlyMultiLine, precedingToken, tokenAtPosition, predicate) { - if (tokenAtPosition === void 0) { tokenAtPosition = ts.getTokenAtPosition(sourceFile, position, false); } + /** + * @param precedingToken pass `null` if preceding token was already computed and result was `undefined`. + */ + function getRangeOfEnclosingComment(sourceFile, position, onlyMultiLine, precedingToken, // tslint:disable-line:no-null-keyword + tokenAtPosition, predicate) { + if (tokenAtPosition === void 0) { tokenAtPosition = ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); } var tokenStart = tokenAtPosition.getStart(sourceFile); if (tokenStart <= position && position < tokenAtPosition.getEnd()) { return undefined; @@ -84342,6 +101017,8 @@ var ts; if (precedingToken === undefined) { precedingToken = ts.findPrecedingToken(position, sourceFile); } + // Between two consecutive tokens, all comments are either trailing on the former + // or leading on the latter (and none are in both lists). var trailingRangesOfPreviousToken = precedingToken && ts.getTrailingCommentRanges(sourceFile.text, precedingToken.end); var leadingCommentRangesOfNextToken = ts.getLeadingCommentRangesOfNode(tokenAtPosition, sourceFile); var commentRanges = trailingRangesOfPreviousToken && leadingCommentRangesOfNextToken ? @@ -84350,9 +101027,22 @@ var ts; if (commentRanges) { for (var _i = 0, commentRanges_1 = commentRanges; _i < commentRanges_1.length; _i++) { var range = commentRanges_1[_i]; + // The end marker of a single-line comment does not include the newline character. + // With caret at `^`, in the following case, we are inside a comment (^ denotes the cursor position): + // + // // asdf ^\n + // + // But for closed multi-line comments, we don't want to be inside the comment in the following case: + // + // /* asdf */^ + // + // However, unterminated multi-line comments *do* contain their end. + // + // Internally, we represent the end of the comment at the newline and closing '/', respectively. + // if ((range.pos < position && position < range.end || - position === range.end && (range.kind === 2 || position === sourceFile.getFullWidth()))) { - return (range.kind === 3 || !onlyMultiLine) && (!predicate || predicate(range)) ? range : undefined; + position === range.end && (range.kind === 2 /* SingleLineCommentTrivia */ || position === sourceFile.getFullWidth()))) { + return (range.kind === 3 /* MultiLineCommentTrivia */ || !onlyMultiLine) && (!predicate || predicate(range)) ? range : undefined; } } } @@ -84361,48 +101051,49 @@ var ts; formatting.getRangeOfEnclosingComment = getRangeOfEnclosingComment; function getOpenTokenForList(node, list) { switch (node.kind) { - case 155: - case 234: - case 192: - case 154: - case 153: - case 193: + case 155 /* Constructor */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 193 /* ArrowFunction */: if (node.typeParameters === list) { - return 27; + return 27 /* LessThanToken */; } else if (node.parameters === list) { - return 19; + return 19 /* OpenParenToken */; } break; - case 187: - case 188: + case 187 /* CallExpression */: + case 188 /* NewExpression */: if (node.typeArguments === list) { - return 27; + return 27 /* LessThanToken */; } else if (node.arguments === list) { - return 19; + return 19 /* OpenParenToken */; } break; - case 162: + case 162 /* TypeReference */: if (node.typeArguments === list) { - return 27; + return 27 /* LessThanToken */; } } - return 0; + return 0 /* Unknown */; } function getCloseTokenForOpenToken(kind) { switch (kind) { - case 19: - return 20; - case 27: - return 29; + case 19 /* OpenParenToken */: + return 20 /* CloseParenToken */; + case 27 /* LessThanToken */: + return 29 /* GreaterThanToken */; } - return 0; + return 0 /* Unknown */; } var internedSizes; var internedTabsIndentation; var internedSpacesIndentation; function getIndentationString(indentation, options) { + // reset interned strings if FormatCodeOptions were changed var resetInternedStrings = !internedSizes || (internedSizes.tabSize !== options.tabSize || internedSizes.indentSize !== options.indentSize); if (resetInternedStrings) { internedSizes = { tabSize: options.tabSize, indentSize: options.indentSize }; @@ -84443,6 +101134,7 @@ var ts; formatting.getIndentationString = getIndentationString; })(formatting = ts.formatting || (ts.formatting = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var formatting; @@ -84453,33 +101145,55 @@ var ts; (function (Value) { Value[Value["Unknown"] = -1] = "Unknown"; })(Value || (Value = {})); + /** + * @param assumeNewLineBeforeCloseBrace + * `false` when called on text from a real source file. + * `true` when we need to assume `position` is on a newline. + * + * This is useful for codefixes. Consider + * ``` + * function f() { + * |} + * ``` + * with `position` at `|`. + * + * When inserting some text after an open brace, we would like to get indentation as if a newline was already there. + * By default indentation at `position` will be 0 so 'assumeNewLineBeforeCloseBrace' overrides this behavior. + */ function getIndentation(position, sourceFile, options, assumeNewLineBeforeCloseBrace) { if (assumeNewLineBeforeCloseBrace === void 0) { assumeNewLineBeforeCloseBrace = false; } if (position > sourceFile.text.length) { - return getBaseIndentation(options); + return getBaseIndentation(options); // past EOF } + // no indentation when the indent style is set to none, + // so we can return fast if (options.indentStyle === ts.IndentStyle.None) { return 0; } var precedingToken = ts.findPrecedingToken(position, sourceFile); - var enclosingCommentRange = formatting.getRangeOfEnclosingComment(sourceFile, position, true, precedingToken || null); + var enclosingCommentRange = formatting.getRangeOfEnclosingComment(sourceFile, position, /*onlyMultiLine*/ true, precedingToken || null); // tslint:disable-line:no-null-keyword if (enclosingCommentRange) { return getCommentIndent(sourceFile, position, options, enclosingCommentRange); } if (!precedingToken) { return getBaseIndentation(options); } + // no indentation in string \regex\template literals var precedingTokenIsLiteral = ts.isStringOrRegularExpressionOrTemplateLiteral(precedingToken.kind); if (precedingTokenIsLiteral && precedingToken.getStart(sourceFile) <= position && position < precedingToken.end) { return 0; } var lineAtPosition = sourceFile.getLineAndCharacterOfPosition(position).line; + // indentation is first non-whitespace character in a previous line + // for block indentation, we should look for a line which contains something that's not + // whitespace. if (options.indentStyle === ts.IndentStyle.Block) { return getBlockIndent(sourceFile, position, options); } - if (precedingToken.kind === 26 && precedingToken.parent.kind !== 200) { + if (precedingToken.kind === 26 /* CommaToken */ && precedingToken.parent.kind !== 200 /* BinaryExpression */) { + // previous token is comma that separates items in list - find the previous item and try to derive indentation from it var actualIndentation = getActualIndentationForListItemBeforeComma(precedingToken, sourceFile, options); - if (actualIndentation !== -1) { + if (actualIndentation !== -1 /* Unknown */) { return actualIndentation; } } @@ -84499,9 +101213,11 @@ var ts; return column; } var firstNonWhitespaceCharacterCode = sourceFile.text.charCodeAt(startPostionOfLine + character); - return firstNonWhitespaceCharacterCode === 42 ? column - 1 : column; + return firstNonWhitespaceCharacterCode === 42 /* asterisk */ ? column - 1 : column; } function getBlockIndent(sourceFile, position, options) { + // move backwards until we find a line with a non-whitespace character, + // then find the first non-whitespace character for that line. var current = position; while (current > 0) { var char = sourceFile.text.charCodeAt(current); @@ -84514,33 +101230,38 @@ var ts; return findFirstNonWhitespaceColumn(lineStart, current, sourceFile, options); } function getSmartIndent(sourceFile, position, precedingToken, lineAtPosition, assumeNewLineBeforeCloseBrace, options) { + // try to find node that can contribute to indentation and includes 'position' starting from 'precedingToken' + // if such node is found - compute initial indentation for 'position' inside this node var previous; var current = precedingToken; while (current) { - if (ts.positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(options, current, previous, sourceFile, true)) { + if (ts.positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(options, current, previous, sourceFile, /*isNextChild*/ true)) { var currentStart = getStartLineAndCharacterForNode(current, sourceFile); var nextTokenKind = nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile); - var indentationDelta = nextTokenKind !== 0 - ? assumeNewLineBeforeCloseBrace && nextTokenKind === 2 ? options.indentSize : 0 + var indentationDelta = nextTokenKind !== 0 /* Unknown */ + // handle cases when codefix is about to be inserted before the close brace + ? assumeNewLineBeforeCloseBrace && nextTokenKind === 2 /* CloseBrace */ ? options.indentSize : 0 : lineAtPosition !== currentStart.line ? options.indentSize : 0; - return getIndentationForNodeWorker(current, currentStart, undefined, indentationDelta, sourceFile, true, options); + return getIndentationForNodeWorker(current, currentStart, /*ignoreActualIndentationRange*/ undefined, indentationDelta, sourceFile, /*isNextChild*/ true, options); // TODO: GH#18217 } + // check if current node is a list item - if yes, take indentation from it var actualIndentation = getActualIndentationForListItem(current, sourceFile, options); - if (actualIndentation !== -1) { + if (actualIndentation !== -1 /* Unknown */) { return actualIndentation; } actualIndentation = getLineIndentationWhenExpressionIsInMultiLine(current, sourceFile, options); - if (actualIndentation !== -1) { - return actualIndentation + options.indentSize; + if (actualIndentation !== -1 /* Unknown */) { + return actualIndentation + options.indentSize; // TODO: GH#18217 } previous = current; current = current.parent; } + // no parent was found - return the base indentation of the SourceFile return getBaseIndentation(options); } function getIndentationForNode(n, ignoreActualIndentationRange, sourceFile, options) { var start = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); - return getIndentationForNodeWorker(n, start, ignoreActualIndentationRange, 0, sourceFile, false, options); + return getIndentationForNodeWorker(n, start, ignoreActualIndentationRange, /*indentationDelta*/ 0, sourceFile, /*isNextChild*/ false, options); } SmartIndenter.getIndentationForNode = getIndentationForNode; function getBaseIndentation(options) { @@ -84549,6 +101270,9 @@ var ts; SmartIndenter.getBaseIndentation = getBaseIndentation; function getIndentationForNodeWorker(current, currentStart, ignoreActualIndentationRange, indentationDelta, sourceFile, isNextChild, options) { var parent = current.parent; + // Walk up the tree and collect indentation for parent-child node pairs. Indentation is not added if + // * parent and child nodes start on the same line, or + // * parent is an IfStatement and child starts on the same line as an 'else clause'. while (parent) { var useActualIndentation = true; if (ignoreActualIndentationRange) { @@ -84556,8 +101280,9 @@ var ts; useActualIndentation = start < ignoreActualIndentationRange.pos || start > ignoreActualIndentationRange.end; } if (useActualIndentation) { + // check if current node is a list item - if yes, take indentation from it var actualIndentation = getActualIndentationForListItem(current, sourceFile, options); - if (actualIndentation !== -1) { + if (actualIndentation !== -1 /* Unknown */) { return actualIndentation + indentationDelta; } } @@ -84565,18 +101290,28 @@ var ts; var parentAndChildShareLine = containingListOrParentStart.line === currentStart.line || childStartsOnTheSameLineWithElseInIfStatement(parent, current, currentStart.line, sourceFile); if (useActualIndentation) { + // try to fetch actual indentation for current node from source text var actualIndentation = getActualIndentationForNode(current, parent, currentStart, parentAndChildShareLine, sourceFile, options); - if (actualIndentation !== -1) { + if (actualIndentation !== -1 /* Unknown */) { return actualIndentation + indentationDelta; } actualIndentation = getLineIndentationWhenExpressionIsInMultiLine(current, sourceFile, options); - if (actualIndentation !== -1) { + if (actualIndentation !== -1 /* Unknown */) { return actualIndentation + indentationDelta; } } + // increase indentation if parent node wants its content to be indented and parent and child nodes don't start on the same line if (shouldIndentChildNode(options, parent, current, sourceFile, isNextChild) && !parentAndChildShareLine) { indentationDelta += options.indentSize; } + // In our AST, a call argument's `parent` is the call-expression, not the argument list. + // We would like to increase indentation based on the relationship between an argument and its argument-list, + // so we spoof the starting position of the (parent) call-expression to match the (non-parent) argument-list. + // But, the spoofed start-value could then cause a problem when comparing the start position of the call-expression + // to *its* parent (in the case of an iife, an expression statement), adding an extra level of indentation. + // + // Instead, when at an argument, we unspoof the starting position of the enclosing call expression + // *after* applying indentation for the argument. var useTrueStart = isArgumentAndStartLineOverlapsExpressionBeingCalled(parent, current, currentStart.line, sourceFile); current = parent; parent = current.parent; @@ -84589,20 +101324,31 @@ var ts; var startPos = containingList ? containingList.pos : parent.getStart(sourceFile); return sourceFile.getLineAndCharacterOfPosition(startPos); } + /* + * Function returns Value.Unknown if indentation cannot be determined + */ function getActualIndentationForListItemBeforeComma(commaToken, sourceFile, options) { + // previous token is comma that separates items in list - find the previous item and try to derive indentation from it var commaItemInfo = ts.findListItemInfo(commaToken); if (commaItemInfo && commaItemInfo.listItemIndex > 0) { return deriveActualIndentationFromList(commaItemInfo.list.getChildren(), commaItemInfo.listItemIndex - 1, sourceFile, options); } else { - return -1; + // handle broken code gracefully + return -1 /* Unknown */; } } + /* + * Function returns Value.Unknown if actual indentation for node should not be used (i.e because node is nested expression) + */ function getActualIndentationForNode(current, parent, currentLineAndChar, parentAndChildShareLine, sourceFile, options) { + // actual indentation is used for statements\declarations if one of cases below is true: + // - parent is SourceFile - by default immediate children of SourceFile are not indented except when user indents them manually + // - parent and child are not on the same line var useActualIndentation = (ts.isDeclaration(current) || ts.isStatementButNotDeclaration(current)) && - (parent.kind === 274 || !parentAndChildShareLine); + (parent.kind === 274 /* SourceFile */ || !parentAndChildShareLine); if (!useActualIndentation) { - return -1; + return -1 /* Unknown */; } return findColumnForFirstNonWhitespaceCharacterInLine(currentLineAndChar, sourceFile, options); } @@ -84615,16 +101361,25 @@ var ts; function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile) { var nextToken = ts.findNextToken(precedingToken, current, sourceFile); if (!nextToken) { - return 0; + return 0 /* Unknown */; } - if (nextToken.kind === 17) { - return 1; + if (nextToken.kind === 17 /* OpenBraceToken */) { + // open braces are always indented at the parent level + return 1 /* OpenBrace */; } - else if (nextToken.kind === 18) { + else if (nextToken.kind === 18 /* CloseBraceToken */) { + // close braces are indented at the parent level if they are located on the same line with cursor + // this means that if new line will be added at $ position, this case will be indented + // class A { + // $ + // } + /// and this one - not + // class A { + // $} var nextTokenStartLine = getStartLineAndCharacterForNode(nextToken, sourceFile).line; - return lineAtPosition === nextTokenStartLine ? 2 : 0; + return lineAtPosition === nextTokenStartLine ? 2 /* CloseBrace */ : 0 /* Unknown */; } - return 0; + return 0 /* Unknown */; } function getStartLineAndCharacterForNode(n, sourceFile) { return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); @@ -84639,8 +101394,8 @@ var ts; } SmartIndenter.isArgumentAndStartLineOverlapsExpressionBeingCalled = isArgumentAndStartLineOverlapsExpressionBeingCalled; function childStartsOnTheSameLineWithElseInIfStatement(parent, child, childStartLine, sourceFile) { - if (parent.kind === 217 && parent.elseStatement === child) { - var elseKeyword = ts.findChildOfKind(parent, 82, sourceFile); + if (parent.kind === 217 /* IfStatement */ && parent.elseStatement === child) { + var elseKeyword = ts.findChildOfKind(parent, 82 /* ElseKeyword */, sourceFile); ts.Debug.assert(elseKeyword !== undefined); var elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line; return elseKeywordStartLine === childStartLine; @@ -84655,40 +101410,40 @@ var ts; if (node.parent) { var end = node.end; switch (node.parent.kind) { - case 162: + case 162 /* TypeReference */: return getListIfStartEndIsInListRange(node.parent.typeArguments, node.getStart(sourceFile), end); - case 184: + case 184 /* ObjectLiteralExpression */: return node.parent.properties; - case 183: + case 183 /* ArrayLiteralExpression */: return node.parent.elements; - case 234: - case 192: - case 193: - case 154: - case 153: - case 158: - case 155: - case 164: - case 159: { + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 158 /* CallSignature */: + case 155 /* Constructor */: + case 164 /* ConstructorType */: + case 159 /* ConstructSignature */: { var start = node.getStart(sourceFile); return getListIfStartEndIsInListRange(node.parent.typeParameters, start, end) || getListIfStartEndIsInListRange(node.parent.parameters, start, end); } - case 235: + case 235 /* ClassDeclaration */: return getListIfStartEndIsInListRange(node.parent.typeParameters, node.getStart(sourceFile), end); - case 188: - case 187: { + case 188 /* NewExpression */: + case 187 /* CallExpression */: { var start = node.getStart(sourceFile); return getListIfStartEndIsInListRange(node.parent.typeArguments, start, end) || getListIfStartEndIsInListRange(node.parent.arguments, start, end); } - case 233: + case 233 /* VariableDeclarationList */: return getListIfStartEndIsInListRange(node.parent.declarations, node.getStart(sourceFile), end); - case 247: - case 251: + case 247 /* NamedImports */: + case 251 /* NamedExports */: return getListIfStartEndIsInListRange(node.parent.elements, node.getStart(sourceFile), end); - case 180: - case 181: + case 180 /* ObjectBindingPattern */: + case 181 /* ArrayBindingPattern */: return getListIfStartEndIsInListRange(node.parent.elements, node.getStart(sourceFile), end); } } @@ -84703,33 +101458,35 @@ var ts; return deriveActualIndentationFromList(containingList, index, sourceFile, options); } } - return -1; + return -1 /* Unknown */; } function getLineIndentationWhenExpressionIsInMultiLine(node, sourceFile, options) { - if (node.kind === 20) { - return -1; + // actual indentation should not be used when: + // - node is close parenthesis - this is the end of the expression + if (node.kind === 20 /* CloseParenToken */) { + return -1 /* Unknown */; } if (node.parent && ts.isCallOrNewExpression(node.parent) && node.parent.expression !== node) { var fullCallOrNewExpression = node.parent.expression; var startingExpression = getStartingExpression(fullCallOrNewExpression); if (fullCallOrNewExpression === startingExpression) { - return -1; + return -1 /* Unknown */; } var fullCallOrNewExpressionEnd = sourceFile.getLineAndCharacterOfPosition(fullCallOrNewExpression.end); var startingExpressionEnd = sourceFile.getLineAndCharacterOfPosition(startingExpression.end); if (fullCallOrNewExpressionEnd.line === startingExpressionEnd.line) { - return -1; + return -1 /* Unknown */; } return findColumnForFirstNonWhitespaceCharacterInLine(fullCallOrNewExpressionEnd, sourceFile, options); } - return -1; + return -1 /* Unknown */; function getStartingExpression(node) { while (true) { switch (node.kind) { - case 187: - case 188: - case 185: - case 186: + case 187 /* CallExpression */: + case 188 /* NewExpression */: + case 185 /* PropertyAccessExpression */: + case 186 /* ElementAccessExpression */: node = node.expression; break; default: @@ -84741,23 +101498,33 @@ var ts; function deriveActualIndentationFromList(list, index, sourceFile, options) { ts.Debug.assert(index >= 0 && index < list.length); var node = list[index]; + // walk toward the start of the list starting from current node and check if the line is the same for all items. + // if end line for item [i - 1] differs from the start line for item [i] - find column of the first non-whitespace character on the line of item [i] var lineAndCharacter = getStartLineAndCharacterForNode(node, sourceFile); for (var i = index - 1; i >= 0; i--) { - if (list[i].kind === 26) { + if (list[i].kind === 26 /* CommaToken */) { continue; } + // skip list items that ends on the same line with the current list element var prevEndLine = sourceFile.getLineAndCharacterOfPosition(list[i].end).line; if (prevEndLine !== lineAndCharacter.line) { return findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options); } lineAndCharacter = getStartLineAndCharacterForNode(list[i], sourceFile); } - return -1; + return -1 /* Unknown */; } function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options) { var lineStart = sourceFile.getPositionOfLineAndCharacter(lineAndCharacter.line, 0); return findFirstNonWhitespaceColumn(lineStart, lineStart + lineAndCharacter.character, sourceFile, options); } + /** + * Character is the actual index of the character since the beginning of the line. + * Column - position of the character after expanding tabs to spaces. + * "0\t2$" + * value of 'character' for '$' is 3 + * value of 'column' for '$' is 6 (assuming that tab size is 4) + */ function findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options) { var character = 0; var column = 0; @@ -84766,7 +101533,7 @@ var ts; if (!ts.isWhiteSpaceSingleLine(ch)) { break; } - if (ch === 9) { + if (ch === 9 /* tab */) { column += options.tabSize + (column % options.tabSize); } else { @@ -84782,111 +101549,118 @@ var ts; } SmartIndenter.findFirstNonWhitespaceColumn = findFirstNonWhitespaceColumn; function nodeWillIndentChild(settings, parent, child, sourceFile, indentByDefault) { - var childKind = child ? child.kind : 0; + var childKind = child ? child.kind : 0 /* Unknown */; switch (parent.kind) { - case 216: - case 235: - case 205: - case 236: - case 238: - case 237: - case 183: - case 213: - case 240: - case 184: - case 166: - case 177: - case 168: - case 241: - case 267: - case 266: - case 191: - case 185: - case 187: - case 188: - case 214: - case 249: - case 225: - case 201: - case 181: - case 180: - case 257: - case 260: - case 256: - case 265: - case 153: - case 158: - case 159: - case 149: - case 163: - case 164: - case 173: - case 189: - case 197: - case 251: - case 247: - case 252: - case 248: - case 152: + case 216 /* ExpressionStatement */: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 236 /* InterfaceDeclaration */: + case 238 /* EnumDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 183 /* ArrayLiteralExpression */: + case 213 /* Block */: + case 240 /* ModuleBlock */: + case 184 /* ObjectLiteralExpression */: + case 166 /* TypeLiteral */: + case 177 /* MappedType */: + case 168 /* TupleType */: + case 241 /* CaseBlock */: + case 267 /* DefaultClause */: + case 266 /* CaseClause */: + case 191 /* ParenthesizedExpression */: + case 185 /* PropertyAccessExpression */: + case 187 /* CallExpression */: + case 188 /* NewExpression */: + case 214 /* VariableStatement */: + case 249 /* ExportAssignment */: + case 225 /* ReturnStatement */: + case 201 /* ConditionalExpression */: + case 181 /* ArrayBindingPattern */: + case 180 /* ObjectBindingPattern */: + case 257 /* JsxOpeningElement */: + case 260 /* JsxOpeningFragment */: + case 256 /* JsxSelfClosingElement */: + case 265 /* JsxExpression */: + case 153 /* MethodSignature */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 149 /* Parameter */: + case 163 /* FunctionType */: + case 164 /* ConstructorType */: + case 173 /* ParenthesizedType */: + case 189 /* TaggedTemplateExpression */: + case 197 /* AwaitExpression */: + case 251 /* NamedExports */: + case 247 /* NamedImports */: + case 252 /* ExportSpecifier */: + case 248 /* ImportSpecifier */: + case 152 /* PropertyDeclaration */: return true; - case 232: - case 270: - if (!settings.indentMultiLineObjectLiteralBeginningOnBlankLine && sourceFile && childKind === 184) { + case 232 /* VariableDeclaration */: + case 270 /* PropertyAssignment */: + if (!settings.indentMultiLineObjectLiteralBeginningOnBlankLine && sourceFile && childKind === 184 /* ObjectLiteralExpression */) { // TODO: GH#18217 return rangeIsOnOneLine(sourceFile, child); } return true; - case 218: - case 219: - case 221: - case 222: - case 220: - case 217: - case 234: - case 192: - case 154: - case 193: - case 155: - case 156: - case 157: - return childKind !== 213; - case 250: - return childKind !== 251; - case 244: - return childKind !== 245 || - (!!child.namedBindings && child.namedBindings.kind !== 247); - case 255: - return childKind !== 258; - case 259: - return childKind !== 261; - case 170: - case 169: - if (childKind === 166) { + case 218 /* DoStatement */: + case 219 /* WhileStatement */: + case 221 /* ForInStatement */: + case 222 /* ForOfStatement */: + case 220 /* ForStatement */: + case 217 /* IfStatement */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 154 /* MethodDeclaration */: + case 193 /* ArrowFunction */: + case 155 /* Constructor */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + return childKind !== 213 /* Block */; + case 250 /* ExportDeclaration */: + return childKind !== 251 /* NamedExports */; + case 244 /* ImportDeclaration */: + return childKind !== 245 /* ImportClause */ || + (!!child.namedBindings && child.namedBindings.kind !== 247 /* NamedImports */); + case 255 /* JsxElement */: + return childKind !== 258 /* JsxClosingElement */; + case 259 /* JsxFragment */: + return childKind !== 261 /* JsxClosingFragment */; + case 170 /* IntersectionType */: + case 169 /* UnionType */: + if (childKind === 166 /* TypeLiteral */) { return false; } + // falls through } + // No explicit rule for given nodes so the result will follow the default value argument return indentByDefault; } SmartIndenter.nodeWillIndentChild = nodeWillIndentChild; function isControlFlowEndingStatement(kind, parent) { switch (kind) { - case 225: - case 229: { - if (parent.kind !== 213) { + case 225 /* ReturnStatement */: + case 229 /* ThrowStatement */: { + if (parent.kind !== 213 /* Block */) { return true; } var grandParent = parent.parent; - return !(grandParent && grandParent.kind === 192 || grandParent.kind === 234); + // In a function, we may want to write inner functions after this. + return !(grandParent && grandParent.kind === 192 /* FunctionExpression */ || grandParent.kind === 234 /* FunctionDeclaration */); } - case 223: - case 224: + case 223 /* ContinueStatement */: + case 224 /* BreakStatement */: return true; default: return false; } } + /** + * True when the parent node should indent the given child by an explicit rule. + * @param isNextChild If true, we are judging indent of a hypothetical child *after* this one, not the current child. + */ function shouldIndentChildNode(settings, parent, child, sourceFile, isNextChild) { if (isNextChild === void 0) { isNextChild = false; } - return nodeWillIndentChild(settings, parent, child, sourceFile, false) + return nodeWillIndentChild(settings, parent, child, sourceFile, /*indentByDefault*/ false) && !(isNextChild && child && isControlFlowEndingStatement(child.kind, parent)); } SmartIndenter.shouldIndentChildNode = shouldIndentChildNode; @@ -84899,10 +101673,15 @@ var ts; })(SmartIndenter = formatting.SmartIndenter || (formatting.SmartIndenter = {})); })(formatting = ts.formatting || (ts.formatting = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var textChanges; (function (textChanges_3) { + /** + * Currently for simplicity we store recovered positions on the node itself. + * It can be changed to side-table later if we decide that current design is too invasive. + */ function getPos(n) { var result = n.__pos; ts.Debug.assert(typeof result === "number"); @@ -84927,7 +101706,7 @@ var ts; Position[Position["Start"] = 1] = "Start"; })(Position = textChanges_3.Position || (textChanges_3.Position = {})); function skipWhitespacesAndLineBreaks(text, start) { - return ts.skipTrivia(text, start, false, true); + return ts.skipTrivia(text, start, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); } function hasCommentsBeforeLineBreak(text, start) { var i = start; @@ -84937,7 +101716,7 @@ var ts; i++; continue; } - return ch === 47; + return ch === 47 /* slash */; } return false; } @@ -84967,10 +101746,20 @@ var ts; var fullStartLine = ts.getLineStartPositionForPosition(fullStart, sourceFile); var startLine = ts.getLineStartPositionForPosition(start, sourceFile); if (startLine === fullStartLine) { + // full start and start of the node are on the same line + // a, b; + // ^ ^ + // | start + // fullstart + // when b is replaced - we usually want to keep the leading trvia + // when b is deleted - we delete it return position === Position.Start ? start : fullStart; } + // get start position of the line following the line that contains fullstart position + // (but only if the fullstart isn't the very beginning of the file) var nextLineStart = fullStart > 0 ? 1 : 0; var adjustedStartPosition = ts.getStartPositionOfLine(ts.getLineOfLocalPosition(sourceFile, fullStartLine) + nextLineStart, sourceFile); + // skip whitespaces/newlines adjustedStartPosition = skipWhitespacesAndLineBreaks(sourceFile.text, adjustedStartPosition); return ts.getStartPositionOfLine(ts.getLineOfLocalPosition(sourceFile, adjustedStartPosition), sourceFile); } @@ -84979,13 +101768,16 @@ var ts; if (options.useNonAdjustedEndPosition || ts.isExpression(node)) { return end; } - var newEnd = ts.skipTrivia(sourceFile.text, end, true); + var newEnd = ts.skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true); return newEnd !== end && ts.isLineBreak(sourceFile.text.charCodeAt(newEnd - 1)) ? newEnd : end; } + /** + * Checks if 'candidate' argument is a legal separator in the list that contains 'node' as an element + */ function isSeparator(node, candidate) { - return !!candidate && !!node.parent && (candidate.kind === 26 || (candidate.kind === 25 && node.parent.kind === 184)); + return !!candidate && !!node.parent && (candidate.kind === 26 /* CommaToken */ || (candidate.kind === 25 /* SemicolonToken */ && node.parent.kind === 184 /* ObjectLiteralExpression */)); } function spaces(count) { var s = ""; @@ -84994,14 +101786,15 @@ var ts; } return s; } - var ChangeTracker = (function () { + var ChangeTracker = /** @class */ (function () { + /** Public for tests only. Other callers should use `ChangeTracker.with`. */ function ChangeTracker(newLineCharacter, formatContext) { this.newLineCharacter = newLineCharacter; this.formatContext = formatContext; this.changes = []; this.newFiles = []; - this.deletedNodesInLists = new ts.NodeSet(); - this.classesWithNodesInsertedAtStart = ts.createMap(); + this.deletedNodesInLists = new ts.NodeSet(); // Stores ids of nodes in lists that we already deleted. Used to avoid deleting `, ` twice in `a, b`. + this.classesWithNodesInsertedAtStart = ts.createMap(); // Set implemented as Map } ChangeTracker.fromContext = function (context) { return new ChangeTracker(ts.getNewLineOrDefaultFromHost(context.host, context.formatContext.options), context.formatContext); @@ -85015,6 +101808,7 @@ var ts; this.changes.push({ kind: ChangeKind.Remove, sourceFile: sourceFile, range: range }); return this; }; + /** Warning: This deletes comments too. See `copyComments` in `convertFunctionToEs6Class`. */ ChangeTracker.prototype.deleteNode = function (sourceFile, node, options) { if (options === void 0) { options = {}; } var startPosition = getAdjustedStartPosition(sourceFile, node, options, Position.FullStart); @@ -85049,6 +101843,8 @@ var ts; this.deleteNode(sourceFile, node); return this; } + // Note: We will only delete a comma *after* a node. This will leave a trailing comma if we delete the last node. + // That's handled in the end by `finishTrailingCommaAfterDeletingNodesInList`. ts.Debug.assert(!this.deletedNodesInLists.has(node), "Deleting a node twice"); this.deletedNodesInLists.add(node); this.deleteRange(sourceFile, { @@ -85085,7 +101881,7 @@ var ts; }; ChangeTracker.prototype.nextCommaToken = function (sourceFile, node) { var next = ts.findNextToken(node, node.parent, sourceFile); - return next && next.kind === 26 ? next : undefined; + return next && next.kind === 26 /* CommaToken */ ? next : undefined; }; ChangeTracker.prototype.replacePropertyAssignment = function (sourceFile, oldNode, newNode) { var suffix = this.nextCommaToken(sourceFile, oldNode) ? "" : ("," + this.newLineCharacter); @@ -85117,8 +101913,12 @@ var ts; ChangeTracker.prototype.insertCommentBeforeLine = function (sourceFile, lineNumber, position, commentText) { var lineStartPosition = ts.getStartPositionOfLine(lineNumber, sourceFile); var startPosition = ts.getFirstNonSpaceCharacterPosition(sourceFile.text, lineStartPosition); + // First try to see if we can put the comment on the previous line. + // We need to make sure that we are not in the middle of a string literal or a comment. + // If so, we do not want to separate the node from its comment if we can. + // Otherwise, add an extra new line immediately before the error span. var insertAtLineStart = isValidLocationToAddComment(sourceFile, startPosition); - var token = ts.getTouchingToken(sourceFile, insertAtLineStart ? startPosition : position, false); + var token = ts.getTouchingToken(sourceFile, insertAtLineStart ? startPosition : position, /*includeJsDocComment*/ false); var indent = sourceFile.text.slice(lineStartPosition, startPosition); var text = (insertAtLineStart ? "" : this.newLineCharacter) + "//" + commentText + this.newLineCharacter + indent; this.insertText(sourceFile, token.getStart(sourceFile), text); @@ -85129,36 +101929,39 @@ var ts; ChangeTracker.prototype.insertText = function (sourceFile, pos, text) { this.replaceRangeWithText(sourceFile, ts.createTextRange(pos), text); }; + /** Prefer this over replacing a node with another that has a type annotation, as it avoids reformatting the other parts of the node. */ ChangeTracker.prototype.tryInsertTypeAnnotation = function (sourceFile, node, type) { var endNode; if (ts.isFunctionLike(node)) { - endNode = ts.findChildOfKind(node, 20, sourceFile); + endNode = ts.findChildOfKind(node, 20 /* CloseParenToken */, sourceFile); if (!endNode) { if (!ts.isArrowFunction(node)) - return; + return; // Function missing parentheses, give up + // If no `)`, is an arrow function `x => x`, so use the end of the first parameter endNode = ts.first(node.parameters); } } else { - endNode = node.kind !== 232 && node.questionToken ? node.questionToken : node.name; + endNode = node.kind !== 232 /* VariableDeclaration */ && node.questionToken ? node.questionToken : node.name; } this.insertNodeAt(sourceFile, endNode.end, type, { prefix: ": " }); }; ChangeTracker.prototype.insertTypeParameters = function (sourceFile, node, typeParameters) { - var start = (ts.findChildOfKind(node, 19, sourceFile) || ts.first(node.parameters)).getStart(sourceFile); + // If no `(`, is an arrow function `x => x`, so use the pos of the first parameter + var start = (ts.findChildOfKind(node, 19 /* OpenParenToken */, sourceFile) || ts.first(node.parameters)).getStart(sourceFile); this.insertNodesAt(sourceFile, start, typeParameters, { prefix: "<", suffix: ">" }); }; ChangeTracker.prototype.getOptionsForInsertNodeBefore = function (before, doubleNewlines) { if (ts.isStatement(before) || ts.isClassElement(before)) { return { suffix: doubleNewlines ? this.newLineCharacter + this.newLineCharacter : this.newLineCharacter }; } - else if (ts.isVariableDeclaration(before)) { + else if (ts.isVariableDeclaration(before)) { // insert `x = 1, ` into `const x = 1, y = 2; return { suffix: ", " }; } else if (ts.isParameter(before)) { return {}; } - return ts.Debug.failBadSyntaxKind(before); + return ts.Debug.failBadSyntaxKind(before); // We haven't handled this kind of node yet -- add it }; ChangeTracker.prototype.insertNodeAtConstructorStart = function (sourceFile, ctr, newStatement) { var firstStatement = ts.firstOrUndefined(ctr.body.statements); @@ -85179,7 +101982,7 @@ var ts; } }; ChangeTracker.prototype.replaceConstructorBody = function (sourceFile, ctr, statements) { - this.replaceNode(sourceFile, ctr.body, ts.createBlock(statements, true)); + this.replaceNode(sourceFile, ctr.body, ts.createBlock(statements, /*multiLine*/ true)); }; ChangeTracker.prototype.insertNodeAtEndOfScope = function (sourceFile, scope, newNode) { var pos = getAdjustedStartPosition(sourceFile, scope.getLastToken(), {}, Position.Start); @@ -85197,7 +102000,8 @@ var ts; ChangeTracker.prototype.getInsertNodeAtClassStartPrefixSuffix = function (sourceFile, cls) { if (cls.members.length === 0) { if (ts.addToSeen(this.classesWithNodesInsertedAtStart, ts.getNodeId(cls), cls)) { - var shouldSuffix = ts.positionsAreOnSameLine.apply(void 0, getClassBraceEnds(cls, sourceFile).concat([sourceFile])); + // For `class C {\n}`, don't add the trailing "\n" + var shouldSuffix = ts.positionsAreOnSameLine.apply(void 0, getClassBraceEnds(cls, sourceFile).concat([sourceFile])); // TODO: GH#4130 remove 'as any' return { prefix: this.newLineCharacter, suffix: shouldSuffix ? this.newLineCharacter : "" }; } else { @@ -85222,8 +102026,10 @@ var ts; }; ChangeTracker.prototype.insertNodeAfterWorker = function (sourceFile, after, newNode) { if (needSemicolonBetween(after, newNode)) { - if (sourceFile.text.charCodeAt(after.end - 1) !== 59) { - this.replaceRange(sourceFile, ts.createTextRange(after.end), ts.createToken(25)); + // check if previous statement ends with semicolon + // if not - insert semicolon to preserve the code from changing the meaning due to ASI + if (sourceFile.text.charCodeAt(after.end - 1) !== 59 /* semicolon */) { + this.replaceRange(sourceFile, ts.createTextRange(after.end), ts.createToken(25 /* SemicolonToken */)); } } var endPosition = getAdjustedEndPosition(sourceFile, after, {}); @@ -85249,34 +102055,43 @@ var ts; else if (ts.isParameter(node)) { return {}; } - return ts.Debug.failBadSyntaxKind(node); + return ts.Debug.failBadSyntaxKind(node); // We haven't handled this kind of node yet -- add it }; ChangeTracker.prototype.insertName = function (sourceFile, node, name) { ts.Debug.assert(!node.name); - if (node.kind === 193) { - var arrow = ts.findChildOfKind(node, 36, sourceFile); - var lparen = ts.findChildOfKind(node, 19, sourceFile); + if (node.kind === 193 /* ArrowFunction */) { + var arrow = ts.findChildOfKind(node, 36 /* EqualsGreaterThanToken */, sourceFile); + var lparen = ts.findChildOfKind(node, 19 /* OpenParenToken */, sourceFile); if (lparen) { - this.insertNodesAt(sourceFile, lparen.getStart(sourceFile), [ts.createToken(89), ts.createIdentifier(name)], { joiner: " " }); + // `() => {}` --> `function f() {}` + this.insertNodesAt(sourceFile, lparen.getStart(sourceFile), [ts.createToken(89 /* FunctionKeyword */), ts.createIdentifier(name)], { joiner: " " }); this.deleteNode(sourceFile, arrow); } else { + // `x => {}` -> `function f(x) {}` this.insertText(sourceFile, ts.first(node.parameters).getStart(sourceFile), "function " + name + "("); - this.replaceRange(sourceFile, arrow, ts.createToken(20)); + // Replacing full range of arrow to get rid of the leading space -- replace ` =>` with `)` + this.replaceRange(sourceFile, arrow, ts.createToken(20 /* CloseParenToken */)); } - if (node.body.kind !== 213) { - this.insertNodesAt(sourceFile, node.body.getStart(sourceFile), [ts.createToken(17), ts.createToken(96)], { joiner: " ", suffix: " " }); - this.insertNodesAt(sourceFile, node.body.end, [ts.createToken(25), ts.createToken(18)], { joiner: " " }); + if (node.body.kind !== 213 /* Block */) { + // `() => 0` => `function f() { return 0; }` + this.insertNodesAt(sourceFile, node.body.getStart(sourceFile), [ts.createToken(17 /* OpenBraceToken */), ts.createToken(96 /* ReturnKeyword */)], { joiner: " ", suffix: " " }); + this.insertNodesAt(sourceFile, node.body.end, [ts.createToken(25 /* SemicolonToken */), ts.createToken(18 /* CloseBraceToken */)], { joiner: " " }); } } else { - var pos = ts.findChildOfKind(node, node.kind === 192 ? 89 : 75, sourceFile).end; + var pos = ts.findChildOfKind(node, node.kind === 192 /* FunctionExpression */ ? 89 /* FunctionKeyword */ : 75 /* ClassKeyword */, sourceFile).end; this.insertNodeAt(sourceFile, pos, ts.createIdentifier(name), { prefix: " " }); } }; ChangeTracker.prototype.insertExportModifier = function (sourceFile, node) { this.insertText(sourceFile, node.getStart(sourceFile), "export "); }; + /** + * This function should be used to insert nodes in lists when nodes don't carry separators as the part of the node range, + * i.e. arguments in arguments lists, parameters in parameter lists etc. + * Note that separators are part of the node in statements and class elements. + */ ChangeTracker.prototype.insertNodeInListAfter = function (sourceFile, after, newNode, containingList) { if (containingList === void 0) { containingList = ts.formatting.SmartIndenter.getContainingList(after, sourceFile); } if (!containingList) { @@ -85289,19 +102104,53 @@ var ts; } var end = after.getEnd(); if (index !== containingList.length - 1) { - var nextToken = ts.getTokenAtPosition(sourceFile, after.end, false); + // any element except the last one + // use next sibling as an anchor + var nextToken = ts.getTokenAtPosition(sourceFile, after.end, /*includeJsDocComment*/ false); if (nextToken && isSeparator(after, nextToken)) { + // for list + // a, b, c + // create change for adding 'e' after 'a' as + // - find start of next element after a (it is b) + // - use this start as start and end position in final change + // - build text of change by formatting the text of node + separator + whitespace trivia of b + // in multiline case it will work as + // a, + // b, + // c, + // result - '*' denotes leading trivia that will be inserted after new text (displayed as '#') + // a,* + // ***insertedtext# + // ###b, + // c, + // find line and character of the next element var lineAndCharOfNextElement = ts.getLineAndCharacterOfPosition(sourceFile, skipWhitespacesAndLineBreaks(sourceFile.text, containingList[index + 1].getFullStart())); + // find line and character of the token that precedes next element (usually it is separator) var lineAndCharOfNextToken = ts.getLineAndCharacterOfPosition(sourceFile, nextToken.end); var prefix = void 0; var startPos = void 0; if (lineAndCharOfNextToken.line === lineAndCharOfNextElement.line) { + // next element is located on the same line with separator: + // a,$$$$b + // ^ ^ + // | |-next element + // |-separator + // where $$$ is some leading trivia + // for a newly inserted node we'll maintain the same relative position comparing to separator and replace leading trivia with spaces + // a, x,$$$$b + // ^ ^ ^ + // | | |-next element + // | |-new inserted node padded with spaces + // |-separator startPos = nextToken.end; prefix = spaces(lineAndCharOfNextElement.character - lineAndCharOfNextToken.character); } else { + // next element is located on different line that separator + // let insert position be the beginning of the line that contains next element startPos = ts.getStartPositionOfLine(lineAndCharOfNextElement.line, sourceFile); } + // write separator and leading trivia of the next element as suffix var suffix = "" + ts.tokenToString(nextToken.kind) + sourceFile.text.substring(nextToken.end, containingList[index + 1].getStart(sourceFile)); this.replaceRange(sourceFile, ts.createTextRange(startPos, containingList[index + 1].getStart(sourceFile)), newNode, { prefix: prefix, suffix: suffix }); } @@ -85311,22 +102160,35 @@ var ts; var afterStartLinePosition = ts.getLineStartPositionForPosition(afterStart, sourceFile); var separator = void 0; var multilineList = false; + // insert element after the last element in the list that has more than one item + // pick the element preceding the after element to: + // - pick the separator + // - determine if list is a multiline if (containingList.length === 1) { - separator = 26; + // if list has only one element then we'll format is as multiline if node has comment in trailing trivia, or as singleline otherwise + // i.e. var x = 1 // this is x + // | new element will be inserted at this position + separator = 26 /* CommaToken */; } else { + // element has more than one element, pick separator from the list var tokenBeforeInsertPosition = ts.findPrecedingToken(after.pos, sourceFile); - separator = isSeparator(after, tokenBeforeInsertPosition) ? tokenBeforeInsertPosition.kind : 26; + separator = isSeparator(after, tokenBeforeInsertPosition) ? tokenBeforeInsertPosition.kind : 26 /* CommaToken */; + // determine if list is multiline by checking lines of after element and element that precedes it. var afterMinusOneStartLinePosition = ts.getLineStartPositionForPosition(containingList[index - 1].getStart(sourceFile), sourceFile); multilineList = afterMinusOneStartLinePosition !== afterStartLinePosition; } if (hasCommentsBeforeLineBreak(sourceFile.text, after.end)) { + // in this case we'll always treat containing list as multiline multilineList = true; } if (multilineList) { + // insert separator immediately following the 'after' node to preserve comments in trailing trivia this.replaceRange(sourceFile, ts.createTextRange(end), ts.createToken(separator)); + // use the same indentation as 'after' item var indentation = ts.formatting.SmartIndenter.findFirstNonWhitespaceColumn(afterStartLinePosition, afterStart, sourceFile, this.formatContext.options); - var insertPos = ts.skipTrivia(sourceFile.text, end, true, false); + // insert element before the line break on the line that contains 'after' element + var insertPos = ts.skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true, /*stopAtComments*/ false); if (insertPos !== end && ts.isLineBreak(sourceFile.text.charCodeAt(insertPos - 1))) { insertPos--; } @@ -85343,6 +102205,7 @@ var ts; this.classesWithNodesInsertedAtStart.forEach(function (cls) { var sourceFile = cls.getSourceFile(); var _a = getClassBraceEnds(cls, sourceFile), openBraceEnd = _a[0], closeBraceEnd = _a[1]; + // For `class C { }` remove the whitespace inside the braces. if (ts.positionsAreOnSameLine(openBraceEnd, closeBraceEnd, sourceFile) && openBraceEnd !== closeBraceEnd - 1) { _this.deleteRange(sourceFile, ts.createTextRange(openBraceEnd, closeBraceEnd - 1)); } @@ -85361,6 +102224,12 @@ var ts; } }); }; + /** + * Note: after calling this, the TextChanges object must be discarded! + * @param validate only for tests + * The reason we must validate as part of this method is that `getNonFormattedText` changes the node's positions, + * so we can only call this once and can't get the non-formatted text separately. + */ ChangeTracker.prototype.getChanges = function (validate) { this.finishClassesWithNodesInsertedAtStart(); this.finishTrailingCommaAfterDeletingNodesInList(); @@ -85377,23 +102246,27 @@ var ts; return ChangeTracker; }()); textChanges_3.ChangeTracker = ChangeTracker; + // find first non-whitespace position in the leading trivia of the node function startPositionToDeleteNodeInList(sourceFile, node) { - return ts.skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, {}, Position.FullStart), false, true); + return ts.skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, {}, Position.FullStart), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); } function getClassBraceEnds(cls, sourceFile) { - return [ts.findChildOfKind(cls, 17, sourceFile).end, ts.findChildOfKind(cls, 18, sourceFile).end]; + return [ts.findChildOfKind(cls, 17 /* OpenBraceToken */, sourceFile).end, ts.findChildOfKind(cls, 18 /* CloseBraceToken */, sourceFile).end]; } var changesToText; (function (changesToText) { function getTextChangesFromChanges(changes, newLineCharacter, formatContext, validate) { return ts.group(changes, function (c) { return c.sourceFile.path; }).map(function (changesInFile) { var sourceFile = changesInFile[0].sourceFile; + // order changes by start position + // If the start position is the same, put the shorter range first, since an empty range (x, x) may precede (x, y) but not vice-versa. var normalized = ts.stableSort(changesInFile, function (a, b) { return (a.range.pos - b.range.pos) || (a.range.end - b.range.end); }); var _loop_22 = function (i) { ts.Debug.assert(normalized[i].range.end <= normalized[i + 1].range.pos, "Changes overlap", function () { return JSON.stringify(normalized[i].range) + " and " + JSON.stringify(normalized[i + 1].range); }); }; + // verify that change intervals do not overlap, except possibly at end points. for (var i = 0; i < normalized.length - 1; i++) { _loop_22(i); } @@ -85405,8 +102278,9 @@ var ts; } changesToText.getTextChangesFromChanges = getTextChangesFromChanges; function newFileChanges(oldFile, fileName, statements, newLineCharacter, formatContext) { + // TODO: this emits the file, parses it back, then formats it that -- may be a less roundabout way to do this var nonFormattedText = statements.map(function (s) { return getNonformattedText(s, oldFile, newLineCharacter).text; }).join(newLineCharacter); - var sourceFile = ts.createSourceFile(fileName, nonFormattedText, 6, true); + var sourceFile = ts.createSourceFile(fileName, nonFormattedText, 6 /* ESNext */, /*setParentNodes*/ true); var changes = ts.formatting.formatDocument(sourceFile, formatContext); var text = applyChanges(nonFormattedText, changes); return { fileName: fileName, textChanges: [ts.createTextChange(ts.createTextSpan(0, 0), text)], isNewFile: true }; @@ -85422,11 +102296,13 @@ var ts; var _a = change.options, options = _a === void 0 ? {} : _a, pos = change.range.pos; var format = function (n) { return getFormattedTextOfNode(n, sourceFile, pos, options, newLineCharacter, formatContext, validate); }; var text = change.kind === ChangeKind.ReplaceWithMultipleNodes - ? change.nodes.map(function (n) { return ts.removeSuffix(format(n), newLineCharacter); }).join(change.options.joiner || newLineCharacter) + ? change.nodes.map(function (n) { return ts.removeSuffix(format(n), newLineCharacter); }).join(change.options.joiner || newLineCharacter) // TODO: GH#18217 : format(change.node); + // strip initial indentation (spaces or tabs) if text will be inserted in the middle of the line var noIndent = (options.preserveLeadingWhitespace || options.indentation !== undefined || ts.getLineStartPositionForPosition(pos, sourceFile) === pos) ? text : text.replace(/^\s+/, ""); return (options.prefix || "") + noIndent + (options.suffix || ""); } + /** Note: this may mutate `nodeIn`. */ function getFormattedTextOfNode(nodeIn, sourceFile, pos, _a, newLineCharacter, formatContext, validate) { var indentation = _a.indentation, prefix = _a.prefix, delta = _a.delta; var _b = getNonformattedText(nodeIn, sourceFile, newLineCharacter), node = _b.node, text = _b.text; @@ -85443,10 +102319,11 @@ var ts; var changes = ts.formatting.formatNodeGivenIndentation(node, file, sourceFile.languageVariant, initialIndentation, delta, formatContext); return applyChanges(text, changes); } + /** Note: output node may be mutated input node. */ function getNonformattedText(node, sourceFile, newLineCharacter) { var writer = new Writer(newLineCharacter); - var newLine = newLineCharacter === "\n" ? 1 : 0; - ts.createPrinter({ newLine: newLine }, writer).writeNode(4, node, sourceFile, writer); + var newLine = newLineCharacter === "\n" ? 1 /* LineFeed */ : 0 /* CarriageReturnLineFeed */; + ts.createPrinter({ newLine: newLine }, writer).writeNode(4 /* Unspecified */, node, sourceFile, writer); return { text: writer.getText(), node: assignPositionsToNode(node) }; } })(changesToText || (changesToText = {})); @@ -85462,7 +102339,8 @@ var ts; return ts.skipTrivia(s, 0) === s.length; } function assignPositionsToNode(node) { - var visited = ts.visitEachChild(node, assignPositionsToNode, ts.nullTransformationContext, assignPositionsToNodeArray, assignPositionsToNode); + var visited = ts.visitEachChild(node, assignPositionsToNode, ts.nullTransformationContext, assignPositionsToNodeArray, assignPositionsToNode); // TODO: GH#18217 + // create proxy node for non synthesized nodes var newNode = ts.nodeIsSynthesized(visited) ? visited : Object.create(visited); newNode.pos = getPos(node); newNode.end = getEnd(node); @@ -85473,12 +102351,13 @@ var ts; if (!visited) { return visited; } + // clone nodearray if necessary var nodeArray = visited === nodes ? ts.createNodeArray(visited.slice(0)) : visited; nodeArray.pos = getPos(nodes); nodeArray.end = getEnd(nodes); return nodeArray; } - var Writer = (function () { + var Writer = /** @class */ (function () { function Writer(newLine) { var _this = this; this.lastNonTriviaPosition = 0; @@ -85520,44 +102399,45 @@ var ts; while (ts.isWhiteSpaceLike(s.charCodeAt(s.length - i - 1))) { i++; } + // trim trailing whitespaces this.lastNonTriviaPosition -= i; } }; Writer.prototype.write = function (s) { this.writer.write(s); - this.setLastNonTriviaPosition(s, false); + this.setLastNonTriviaPosition(s, /*force*/ false); }; Writer.prototype.writeKeyword = function (s) { this.writer.writeKeyword(s); - this.setLastNonTriviaPosition(s, false); + this.setLastNonTriviaPosition(s, /*force*/ false); }; Writer.prototype.writeOperator = function (s) { this.writer.writeOperator(s); - this.setLastNonTriviaPosition(s, false); + this.setLastNonTriviaPosition(s, /*force*/ false); }; Writer.prototype.writePunctuation = function (s) { this.writer.writePunctuation(s); - this.setLastNonTriviaPosition(s, false); + this.setLastNonTriviaPosition(s, /*force*/ false); }; Writer.prototype.writeParameter = function (s) { this.writer.writeParameter(s); - this.setLastNonTriviaPosition(s, false); + this.setLastNonTriviaPosition(s, /*force*/ false); }; Writer.prototype.writeProperty = function (s) { this.writer.writeProperty(s); - this.setLastNonTriviaPosition(s, false); + this.setLastNonTriviaPosition(s, /*force*/ false); }; Writer.prototype.writeSpace = function (s) { this.writer.writeSpace(s); - this.setLastNonTriviaPosition(s, false); + this.setLastNonTriviaPosition(s, /*force*/ false); }; Writer.prototype.writeStringLiteral = function (s) { this.writer.writeStringLiteral(s); - this.setLastNonTriviaPosition(s, false); + this.setLastNonTriviaPosition(s, /*force*/ false); }; Writer.prototype.writeSymbol = function (s, sym) { this.writer.writeSymbol(s, sym); - this.setLastNonTriviaPosition(s, false); + this.setLastNonTriviaPosition(s, /*force*/ false); }; Writer.prototype.writeTextOfNode = function (text, node) { this.writer.writeTextOfNode(text, node); @@ -85576,11 +102456,11 @@ var ts; }; Writer.prototype.rawWrite = function (s) { this.writer.rawWrite(s); - this.setLastNonTriviaPosition(s, false); + this.setLastNonTriviaPosition(s, /*force*/ false); }; Writer.prototype.writeLiteral = function (s) { this.writer.writeLiteral(s); - this.setLastNonTriviaPosition(s, true); + this.setLastNonTriviaPosition(s, /*force*/ true); }; Writer.prototype.getTextPos = function () { return this.writer.getTextPos(); @@ -85611,17 +102491,20 @@ var ts; position = shebang.length; advancePastLineBreak(); } + // For a source file, it is possible there are detached comments we should not skip var ranges = ts.getLeadingCommentRanges(text, position); if (!ranges) return position; - if (ranges.length && ranges[0].kind === 3 && ts.isPinnedComment(text, ranges[0].pos)) { + // However we should still skip a pinned comment at the top + if (ranges.length && ranges[0].kind === 3 /* MultiLineCommentTrivia */ && ts.isPinnedComment(text, ranges[0].pos)) { position = ranges[0].end; advancePastLineBreak(); ranges = ranges.slice(1); } + // As well as any triple slash references for (var _i = 0, ranges_1 = ranges; _i < ranges_1.length; _i++) { var range = ranges_1[_i]; - if (range.kind === 2 && ts.isRecognizedTripleSlashComment(text, range.pos, range.end)) { + if (range.kind === 2 /* SingleLineCommentTrivia */ && ts.isRecognizedTripleSlashComment(text, range.pos, range.end)) { position = range.end; advancePastLineBreak(); continue; @@ -85634,7 +102517,7 @@ var ts; var charCode = text.charCodeAt(position); if (ts.isLineBreak(charCode)) { position++; - if (position < text.length && charCode === 13 && text.charCodeAt(position) === 10) { + if (position < text.length && charCode === 13 /* carriageReturn */ && text.charCodeAt(position) === 10 /* lineFeed */) { position++; } } @@ -85646,11 +102529,12 @@ var ts; } textChanges_3.isValidLocationToAddComment = isValidLocationToAddComment; function needSemicolonBetween(a, b) { - return (ts.isPropertySignature(a) || ts.isPropertyDeclaration(a)) && ts.isClassOrTypeElement(b) && b.name.kind === 147 - || ts.isStatementButNotDeclaration(a) && ts.isStatementButNotDeclaration(b); + return (ts.isPropertySignature(a) || ts.isPropertyDeclaration(a)) && ts.isClassOrTypeElement(b) && b.name.kind === 147 /* ComputedPropertyName */ + || ts.isStatementButNotDeclaration(a) && ts.isStatementButNotDeclaration(b); // TODO: only if b would start with a `(` or `[` } })(textChanges = ts.textChanges || (ts.textChanges = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -85663,7 +102547,7 @@ var ts; : ts.getLocaleSpecificMessage(diag); } function createCodeFixActionNoFixId(fixName, changes, description) { - return createCodeFixActionWorker(fixName, diagnosticToString(description), changes, undefined, undefined); + return createCodeFixActionWorker(fixName, diagnosticToString(description), changes, /*fixId*/ undefined, /*fixAllDescription*/ undefined); } codefix.createCodeFixActionNoFixId = createCodeFixActionNoFixId; function createCodeFixAction(fixName, changes, description, fixId, fixAllDescription, command) { @@ -85696,6 +102580,7 @@ var ts; } codefix.getFixes = getFixes; function getAllFixes(context) { + // Currently fixId is always a string. return fixIdToRegistration.get(ts.cast(context.fixId, ts.isString)).getAllCodeActions(context); } codefix.getAllFixes = getAllFixes; @@ -85725,11 +102610,15 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var refactor; (function (refactor_1) { + // A map with the refactor code as key, the refactor itself as value + // e.g. nonSuggestableRefactors[refactorCode] -> the refactor you want var refactors = ts.createMap(); + /** @param name An unique code associated with each refactor. Does not have to be human-readable. */ function registerRefactor(name, refactor) { refactors.set(name, refactor); } @@ -85752,6 +102641,7 @@ var ts; } ts.getRefactorContextSpan = getRefactorContextSpan; })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -85768,14 +102658,15 @@ var ts; getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { return makeChange(changes, diag.file, diag.start); }); }, }); function makeChange(changeTracker, sourceFile, pos) { - var token = ts.getTokenAtPosition(sourceFile, pos, false); + var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); var decorator = ts.findAncestor(token, ts.isDecorator); ts.Debug.assert(!!decorator, "Expected position to be owned by a decorator."); - var replacement = ts.createCall(decorator.expression, undefined, undefined); + var replacement = ts.createCall(decorator.expression, /*typeArguments*/ undefined, /*argumentsArray*/ undefined); changeTracker.replaceNode(sourceFile, decorator.expression, replacement); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -85799,7 +102690,8 @@ var ts; }); }, }); function getDeclaration(file, pos) { - var name = ts.getTokenAtPosition(file, pos, false); + var name = ts.getTokenAtPosition(file, pos, /*includeJsDocComment*/ false); + // For an arrow function with no name, 'name' lands on the first parameter. return ts.tryCast(ts.isParameter(name.parent) ? name.parent.parent : name.parent, parameterShouldGetTypeFromJSDoc); } function parameterShouldGetTypeFromJSDoc(node) { @@ -85818,9 +102710,9 @@ var ts; if (typeParameters.length) changes.insertTypeParameters(sourceFile, decl, typeParameters); } - var needParens = ts.isArrowFunction(decl) && !ts.findChildOfKind(decl, 19, sourceFile); + var needParens = ts.isArrowFunction(decl) && !ts.findChildOfKind(decl, 19 /* OpenParenToken */, sourceFile); if (needParens) - changes.insertNodeBefore(sourceFile, ts.first(decl.parameters), ts.createToken(19)); + changes.insertNodeBefore(sourceFile, ts.first(decl.parameters), ts.createToken(19 /* OpenParenToken */)); for (var _i = 0, _a = decl.parameters; _i < _a.length; _i++) { var param = _a[_i]; if (!param.type) { @@ -85830,7 +102722,7 @@ var ts; } } if (needParens) - changes.insertNodeAfter(sourceFile, ts.last(decl.parameters), ts.createToken(20)); + changes.insertNodeAfter(sourceFile, ts.last(decl.parameters), ts.createToken(20 /* CloseParenToken */)); if (!decl.type) { var returnType = ts.getJSDocReturnType(decl); if (returnType) @@ -85838,37 +102730,37 @@ var ts; } } else { - var jsdocType = ts.Debug.assertDefined(ts.getJSDocType(decl)); - ts.Debug.assert(!decl.type); + var jsdocType = ts.Debug.assertDefined(ts.getJSDocType(decl)); // If not defined, shouldn't have been an error to fix + ts.Debug.assert(!decl.type); // If defined, shouldn't have been an error to fix. changes.tryInsertTypeAnnotation(sourceFile, decl, transformJSDocType(jsdocType)); } } function isDeclarationWithType(node) { return ts.isFunctionLikeDeclaration(node) || - node.kind === 232 || - node.kind === 151 || - node.kind === 152; + node.kind === 232 /* VariableDeclaration */ || + node.kind === 151 /* PropertySignature */ || + node.kind === 152 /* PropertyDeclaration */; } function transformJSDocType(node) { switch (node.kind) { - case 279: - case 280: + case 279 /* JSDocAllType */: + case 280 /* JSDocUnknownType */: return ts.createTypeReferenceNode("any", ts.emptyArray); - case 283: + case 283 /* JSDocOptionalType */: return transformJSDocOptionalType(node); - case 282: + case 282 /* JSDocNonNullableType */: return transformJSDocType(node.type); - case 281: + case 281 /* JSDocNullableType */: return transformJSDocNullableType(node); - case 285: + case 285 /* JSDocVariadicType */: return transformJSDocVariadicType(node); - case 284: + case 284 /* JSDocFunctionType */: return transformJSDocFunctionType(node); - case 162: + case 162 /* TypeReference */: return transformJSDocTypeReference(node); default: - var visited = ts.visitEachChild(node, transformJSDocType, undefined); - ts.setEmitFlags(visited, 1); + var visited = ts.visitEachChild(node, transformJSDocType, /*context*/ undefined); // TODO: GH#18217 + ts.setEmitFlags(visited, 1 /* SingleLine */); return visited; } } @@ -85886,9 +102778,9 @@ var ts; } function transformJSDocParameter(node) { var index = node.parent.parameters.indexOf(node); - var isRest = node.type.kind === 285 && index === node.parent.parameters.length - 1; + var isRest = node.type.kind === 285 /* JSDocVariadicType */ && index === node.parent.parameters.length - 1; // TODO: GH#18217 var name = node.name || (isRest ? "rest" : "arg" + index); - var dotdotdot = isRest ? ts.createToken(24) : node.dotDotDotToken; + var dotdotdot = isRest ? ts.createToken(24 /* DotDotDotToken */) : node.dotDotDotToken; return ts.createParameter(node.decorators, node.modifiers, dotdotdot, name, node.questionToken, ts.visitNode(node.type, transformJSDocType), node.initializer); } function transformJSDocTypeReference(node) { @@ -85923,13 +102815,19 @@ var ts; return ts.createTypeReferenceNode(name, args); } function transformJSDocIndexSignature(node) { - var index = ts.createParameter(undefined, undefined, undefined, node.typeArguments[0].kind === 134 ? "n" : "s", undefined, ts.createTypeReferenceNode(node.typeArguments[0].kind === 134 ? "number" : "string", []), undefined); - var indexSignature = ts.createTypeLiteralNode([ts.createIndexSignature(undefined, undefined, [index], node.typeArguments[1])]); - ts.setEmitFlags(indexSignature, 1); + var index = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, node.typeArguments[0].kind === 134 /* NumberKeyword */ ? "n" : "s", + /*questionToken*/ undefined, ts.createTypeReferenceNode(node.typeArguments[0].kind === 134 /* NumberKeyword */ ? "number" : "string", []), + /*initializer*/ undefined); + var indexSignature = ts.createTypeLiteralNode([ts.createIndexSignature(/*decorators*/ undefined, /*modifiers*/ undefined, [index], node.typeArguments[1])]); + ts.setEmitFlags(indexSignature, 1 /* SingleLine */); return indexSignature; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -85947,28 +102845,29 @@ var ts; }); function doChange(changes, sourceFile, position, checker) { var deletedNodes = []; - var ctorSymbol = checker.getSymbolAtLocation(ts.getTokenAtPosition(sourceFile, position, false)); - if (!ctorSymbol || !(ctorSymbol.flags & (16 | 3))) { + var ctorSymbol = checker.getSymbolAtLocation(ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false)); + if (!ctorSymbol || !(ctorSymbol.flags & (16 /* Function */ | 3 /* Variable */))) { + // Bad input return undefined; } var ctorDeclaration = ctorSymbol.valueDeclaration; var precedingNode; var newClassDeclaration; switch (ctorDeclaration.kind) { - case 234: + case 234 /* FunctionDeclaration */: precedingNode = ctorDeclaration; deleteNode(ctorDeclaration); newClassDeclaration = createClassFromFunctionDeclaration(ctorDeclaration); break; - case 232: + case 232 /* VariableDeclaration */: precedingNode = ctorDeclaration.parent.parent; newClassDeclaration = createClassFromVariableDeclaration(ctorDeclaration); if (ctorDeclaration.parent.declarations.length === 1) { - ts.copyComments(precedingNode, newClassDeclaration, sourceFile); + ts.copyComments(precedingNode, newClassDeclaration, sourceFile); // TODO: GH#18217 deleteNode(precedingNode); } else { - deleteNode(ctorDeclaration, true); + deleteNode(ctorDeclaration, /*inList*/ true); } break; } @@ -85976,6 +102875,7 @@ var ts; return undefined; } ts.copyComments(ctorDeclaration, newClassDeclaration, sourceFile); + // Because the preceding node could be touched, we need to insert nodes before delete nodes. changes.insertNodeAfter(sourceFile, precedingNode, newClassDeclaration); for (var _i = 0, deletedNodes_1 = deletedNodes; _i < deletedNodes_1.length; _i++) { var _a = deletedNodes_1[_i], node = _a.node, inList = _a.inList; @@ -85988,23 +102888,26 @@ var ts; } function deleteNode(node, inList) { if (inList === void 0) { inList = false; } + // If parent node has already been deleted, do nothing if (!deletedNodes.some(function (n) { return ts.isNodeDescendantOf(node, n.node); })) { deletedNodes.push({ node: node, inList: inList }); } } function createClassElementsFromSymbol(symbol) { var memberElements = []; + // all instance members are stored in the "member" array of symbol if (symbol.members) { symbol.members.forEach(function (member) { - var memberElement = createClassElement(member, undefined); + var memberElement = createClassElement(member, /*modifiers*/ undefined); if (memberElement) { memberElements.push(memberElement); } }); } + // all static members are stored in the "exports" array of symbol if (symbol.exports) { symbol.exports.forEach(function (member) { - var memberElement = createClassElement(member, [ts.createToken(115)]); + var memberElement = createClassElement(member, [ts.createToken(115 /* StaticKeyword */)]); if (memberElement) { memberElements.push(memberElement); } @@ -86012,10 +102915,13 @@ var ts; } return memberElements; function shouldConvertDeclaration(_target, source) { + // Right now the only thing we can convert are function expressions - other values shouldn't get + // transformed. We can update this once ES public class properties are available. return ts.isFunctionLike(source); } function createClassElement(symbol, modifiers) { - if (!(symbol.flags & 8192)) { + // Right now the only thing we can convert are function expressions, which are marked as methods + if (!(symbol.flags & 8192 /* Method */)) { return; } var memberDeclaration = symbol.valueDeclaration; @@ -86023,40 +102929,48 @@ var ts; if (!shouldConvertDeclaration(memberDeclaration, assignmentBinaryExpression.right)) { return; } - var nodeToDelete = assignmentBinaryExpression.parent && assignmentBinaryExpression.parent.kind === 216 + // delete the entire statement if this expression is the sole expression to take care of the semicolon at the end + var nodeToDelete = assignmentBinaryExpression.parent && assignmentBinaryExpression.parent.kind === 216 /* ExpressionStatement */ ? assignmentBinaryExpression.parent : assignmentBinaryExpression; deleteNode(nodeToDelete); if (!assignmentBinaryExpression.right) { - return ts.createProperty([], modifiers, symbol.name, undefined, undefined, undefined); + return ts.createProperty([], modifiers, symbol.name, /*questionToken*/ undefined, + /*type*/ undefined, /*initializer*/ undefined); } switch (assignmentBinaryExpression.right.kind) { - case 192: { + case 192 /* FunctionExpression */: { var functionExpression = assignmentBinaryExpression.right; - var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(functionExpression, 120)); - var method = ts.createMethod(undefined, fullModifiers, undefined, memberDeclaration.name, undefined, undefined, functionExpression.parameters, undefined, functionExpression.body); + var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(functionExpression, 120 /* AsyncKeyword */)); + var method = ts.createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined, + /*typeParameters*/ undefined, functionExpression.parameters, /*type*/ undefined, functionExpression.body); ts.copyComments(assignmentBinaryExpression, method, sourceFile); return method; } - case 193: { + case 193 /* ArrowFunction */: { var arrowFunction = assignmentBinaryExpression.right; var arrowFunctionBody = arrowFunction.body; var bodyBlock = void 0; - if (arrowFunctionBody.kind === 213) { + // case 1: () => { return [1,2,3] } + if (arrowFunctionBody.kind === 213 /* Block */) { bodyBlock = arrowFunctionBody; } + // case 2: () => [1,2,3] else { bodyBlock = ts.createBlock([ts.createReturn(arrowFunctionBody)]); } - var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(arrowFunction, 120)); - var method = ts.createMethod(undefined, fullModifiers, undefined, memberDeclaration.name, undefined, undefined, arrowFunction.parameters, undefined, bodyBlock); + var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(arrowFunction, 120 /* AsyncKeyword */)); + var method = ts.createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined, + /*typeParameters*/ undefined, arrowFunction.parameters, /*type*/ undefined, bodyBlock); ts.copyComments(assignmentBinaryExpression, method, sourceFile); return method; } default: { + // Don't try to declare members in JavaScript files if (ts.isSourceFileJavaScript(sourceFile)) { return; } - var prop = ts.createProperty(undefined, modifiers, memberDeclaration.name, undefined, undefined, assignmentBinaryExpression.right); + var prop = ts.createProperty(/*decorators*/ undefined, modifiers, memberDeclaration.name, /*questionToken*/ undefined, + /*type*/ undefined, assignmentBinaryExpression.right); ts.copyComments(assignmentBinaryExpression.parent, prop, sourceFile); return prop; } @@ -86065,27 +102979,31 @@ var ts; } function createClassFromVariableDeclaration(node) { var initializer = node.initializer; - if (!initializer || initializer.kind !== 192) { + if (!initializer || initializer.kind !== 192 /* FunctionExpression */) { return undefined; } - if (node.name.kind !== 71) { + if (node.name.kind !== 71 /* Identifier */) { return undefined; } var memberElements = createClassElementsFromSymbol(node.symbol); if (initializer.body) { - memberElements.unshift(ts.createConstructor(undefined, undefined, initializer.parameters, initializer.body)); + memberElements.unshift(ts.createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, initializer.parameters, initializer.body)); } - var modifiers = getModifierKindFromSource(precedingNode, 84); - var cls = ts.createClassDeclaration(undefined, modifiers, node.name, undefined, undefined, memberElements); + var modifiers = getModifierKindFromSource(precedingNode, 84 /* ExportKeyword */); + var cls = ts.createClassDeclaration(/*decorators*/ undefined, modifiers, node.name, + /*typeParameters*/ undefined, /*heritageClauses*/ undefined, memberElements); + // Don't call copyComments here because we'll already leave them in place return cls; } function createClassFromFunctionDeclaration(node) { var memberElements = createClassElementsFromSymbol(ctorSymbol); if (node.body) { - memberElements.unshift(ts.createConstructor(undefined, undefined, node.parameters, node.body)); + memberElements.unshift(ts.createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, node.parameters, node.body)); } - var modifiers = getModifierKindFromSource(node, 84); - var cls = ts.createClassDeclaration(undefined, modifiers, node.name, undefined, undefined, memberElements); + var modifiers = getModifierKindFromSource(node, 84 /* ExportKeyword */); + var cls = ts.createClassDeclaration(/*decorators*/ undefined, modifiers, node.name, + /*typeParameters*/ undefined, /*heritageClauses*/ undefined, memberElements); + // Don't call copyComments here because we'll already leave them in place return cls; } } @@ -86094,6 +103012,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -86111,6 +103030,7 @@ var ts; } } }); + // No support for fix-all since this applies to the whole file at once anyway. return [codefix.createCodeFixActionNoFixId("convertToEs6Module", changes, ts.Diagnostics.Convert_to_ES6_module)]; }, }); @@ -86123,17 +103043,18 @@ var ts; } var importNode = ts.importFromModuleSpecifier(moduleSpecifier); switch (importNode.kind) { - case 243: - changes.replaceNode(importingFile, importNode, ts.makeImport(importNode.name, undefined, moduleSpecifier, quotePreference)); + case 243 /* ImportEqualsDeclaration */: + changes.replaceNode(importingFile, importNode, ts.makeImport(importNode.name, /*namedImports*/ undefined, moduleSpecifier, quotePreference)); break; - case 187: - if (ts.isRequireCall(importNode, false)) { + case 187 /* CallExpression */: + if (ts.isRequireCall(importNode, /*checkArgumentIsStringLiteralLike*/ false)) { changes.replaceNode(importingFile, importNode, ts.createPropertyAccess(ts.getSynthesizedDeepClone(importNode), "default")); } break; } } } + /** @returns Whether we converted a `module.exports =` to a default export. */ function convertFileToEs6Module(sourceFile, checker, changes, target, quotePreference) { var identifiers = { original: collectFreeIdentifiers(sourceFile), additional: ts.createMap() }; var exports = collectExportRenames(sourceFile, checker, identifiers); @@ -86151,7 +103072,8 @@ var ts; forEachExportReference(sourceFile, function (node) { var _a = node.name, text = _a.text, originalKeywordKind = _a.originalKeywordKind; if (!res.has(text) && (originalKeywordKind !== undefined && ts.isNonContextualKeyword(originalKeywordKind) - || checker.resolveName(node.name.text, node, 67216319, true))) { + || checker.resolveName(node.name.text, node, 67216319 /* Value */, /*excludeGlobals*/ true))) { + // Unconditionally add an underscore in case `text` is a keyword. res.set(text, makeUniqueName("_" + text, identifiers)); } }); @@ -86170,31 +103092,33 @@ var ts; sourceFile.forEachChild(function recur(node) { if (ts.isPropertyAccessExpression(node) && ts.isExportsOrModuleExportsOrAlias(sourceFile, node.expression)) { var parent = node.parent; - cb(node, ts.isBinaryExpression(parent) && parent.left === node && parent.operatorToken.kind === 58); + cb(node, ts.isBinaryExpression(parent) && parent.left === node && parent.operatorToken.kind === 58 /* EqualsToken */); } node.forEachChild(recur); }); } function convertStatement(sourceFile, statement, checker, changes, identifiers, target, exports, quotePreference) { switch (statement.kind) { - case 214: + case 214 /* VariableStatement */: convertVariableStatement(sourceFile, statement, changes, checker, identifiers, target, quotePreference); return false; - case 216: { + case 216 /* ExpressionStatement */: { var expression = statement.expression; switch (expression.kind) { - case 187: { - if (ts.isRequireCall(expression, true)) { - changes.replaceNode(sourceFile, statement, ts.makeImport(undefined, undefined, expression.arguments[0], quotePreference)); + case 187 /* CallExpression */: { + if (ts.isRequireCall(expression, /*checkArgumentIsStringLiteralLike*/ true)) { + // For side-effecting require() call, just make a side-effecting import. + changes.replaceNode(sourceFile, statement, ts.makeImport(/*name*/ undefined, /*namedImports*/ undefined, expression.arguments[0], quotePreference)); } return false; } - case 200: { + case 200 /* BinaryExpression */: { var operatorToken = expression.operatorToken; - return operatorToken.kind === 58 && convertAssignment(sourceFile, checker, expression, changes, exports); + return operatorToken.kind === 58 /* EqualsToken */ && convertAssignment(sourceFile, checker, expression, changes, exports); } } } + // falls through default: return false; } @@ -86206,35 +103130,41 @@ var ts; var name = decl.name, initializer = decl.initializer; if (initializer) { if (ts.isExportsOrModuleExportsOrAlias(sourceFile, initializer)) { + // `const alias = module.exports;` can be removed. foundImport = true; return []; } - else if (ts.isRequireCall(initializer, true)) { + else if (ts.isRequireCall(initializer, /*checkArgumentIsStringLiteralLike*/ true)) { foundImport = true; return convertSingleImport(sourceFile, name, initializer.arguments[0], changes, checker, identifiers, target, quotePreference); } - else if (ts.isPropertyAccessExpression(initializer) && ts.isRequireCall(initializer.expression, true)) { + else if (ts.isPropertyAccessExpression(initializer) && ts.isRequireCall(initializer.expression, /*checkArgumentIsStringLiteralLike*/ true)) { foundImport = true; return convertPropertyAccessImport(name, initializer.name.text, initializer.expression.arguments[0], identifiers, quotePreference); } } - return ts.createVariableStatement(undefined, ts.createVariableDeclarationList([decl], declarationList.flags)); + // Move it out to its own variable statement. (This will not be used if `!foundImport`) + return ts.createVariableStatement(/*modifiers*/ undefined, ts.createVariableDeclarationList([decl], declarationList.flags)); }); if (foundImport) { + // useNonAdjustedEndPosition to ensure we don't eat the newline after the statement. changes.replaceNodeWithNodes(sourceFile, statement, newNodes); } } + /** Converts `const name = require("moduleSpecifier").propertyName` */ function convertPropertyAccessImport(name, propertyName, moduleSpecifier, identifiers, quotePreference) { switch (name.kind) { - case 180: - case 181: { + case 180 /* ObjectBindingPattern */: + case 181 /* ArrayBindingPattern */: { + // `const [a, b] = require("c").d` --> `import { d } from "c"; const [a, b] = d;` var tmp = makeUniqueName(propertyName, identifiers); return [ makeSingleImport(tmp, propertyName, moduleSpecifier, quotePreference), - makeConst(undefined, name, ts.createIdentifier(tmp)), + makeConst(/*modifiers*/ undefined, name, ts.createIdentifier(tmp)), ]; } - case 71: + case 71 /* Identifier */: + // `const a = require("b").c` --> `import { c as a } from "./b"; return [makeSingleImport(name.text, propertyName, moduleSpecifier, quotePreference)]; default: return ts.Debug.assertNever(name); @@ -86247,11 +103177,12 @@ var ts; } if (ts.isExportsOrModuleExportsOrAlias(sourceFile, left)) { if (ts.isExportsOrModuleExportsOrAlias(sourceFile, right)) { + // `const alias = module.exports;` or `module.exports = alias;` can be removed. changes.deleteNode(sourceFile, assignment.parent); } else { var replacement = ts.isObjectLiteralExpression(right) ? tryChangeModuleExportsObject(right) - : ts.isRequireCall(right, true) ? convertReExportAll(right.arguments[0], checker) + : ts.isRequireCall(right, /*checkArgumentIsStringLiteralLike*/ true) ? convertReExportAll(right.arguments[0], checker) : undefined; if (replacement) { changes.replaceNodeWithNodes(sourceFile, assignment.parent, replacement[0]); @@ -86268,18 +103199,23 @@ var ts; } return false; } + /** + * Convert `module.exports = { ... }` to individual exports.. + * We can't always do this if the module has interesting members -- then it will be a default export instead. + */ function tryChangeModuleExportsObject(object) { var statements = ts.mapAllOrFail(object.properties, function (prop) { switch (prop.kind) { - case 156: - case 157: - case 271: - case 272: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + // TODO: Maybe we should handle this? See fourslash test `refactorConvertToEs6Module_export_object_shorthand.ts`. + case 271 /* ShorthandPropertyAssignment */: + case 272 /* SpreadAssignment */: return undefined; - case 270: + case 270 /* PropertyAssignment */: return !ts.isIdentifier(prop.name) ? undefined : convertExportsDotXEquals_replaceNode(prop.name.text, prop.initializer); - case 154: - return !ts.isIdentifier(prop.name) ? undefined : functionExpressionToDeclaration(prop.name.text, [ts.createToken(84)], prop); + case 154 /* MethodDeclaration */: + return !ts.isIdentifier(prop.name) ? undefined : functionExpressionToDeclaration(prop.name.text, [ts.createToken(84 /* ExportKeyword */)], prop); default: ts.Debug.assertNever(prop); } @@ -86287,11 +103223,16 @@ var ts; return statements && [statements, false]; } function convertNamedExport(sourceFile, assignment, changes, exports) { + // If "originalKeywordKind" was set, this is e.g. `exports. var text = assignment.left.name.text; var rename = exports.get(text); if (rename !== undefined) { + /* + const _class = 0; + export { _class as class }; + */ var newNodes = [ - makeConst(undefined, rename, assignment.right), + makeConst(/*modifiers*/ undefined, rename, assignment.right), makeExportDeclaration([ts.createExportSpecifier(rename, text)]), ]; changes.replaceNodeWithNodes(sourceFile, assignment.parent, newNodes); @@ -86301,6 +103242,7 @@ var ts; } } function convertReExportAll(reExported, checker) { + // `module.exports = require("x");` ==> `export * from "x"; export { default } from "x";` var moduleSpecifier = reExported.text; var moduleSymbol = checker.getSymbolAtLocation(reExported); var exports = moduleSymbol ? moduleSymbol.exports : ts.emptyUnderscoreEscapedMap; @@ -86308,87 +103250,113 @@ var ts; ? [[reExportDefault(moduleSpecifier)], true] : !exports.has("default") ? [[reExportStar(moduleSpecifier)], false] + // If there's some non-default export, must include both `export *` and `export default`. : exports.size > 1 ? [[reExportStar(moduleSpecifier), reExportDefault(moduleSpecifier)], true] : [[reExportDefault(moduleSpecifier)], true]; } function reExportStar(moduleSpecifier) { - return makeExportDeclaration(undefined, moduleSpecifier); + return makeExportDeclaration(/*exportClause*/ undefined, moduleSpecifier); } function reExportDefault(moduleSpecifier) { - return makeExportDeclaration([ts.createExportSpecifier(undefined, "default")], moduleSpecifier); + return makeExportDeclaration([ts.createExportSpecifier(/*propertyName*/ undefined, "default")], moduleSpecifier); } function convertExportsPropertyAssignment(_a, sourceFile, changes) { var left = _a.left, right = _a.right, parent = _a.parent; var name = left.name.text; if ((ts.isFunctionExpression(right) || ts.isArrowFunction(right) || ts.isClassExpression(right)) && (!right.name || right.name.text === name)) { - changes.replaceRange(sourceFile, { pos: left.getStart(sourceFile), end: right.getStart(sourceFile) }, ts.createToken(84), { suffix: " " }); + // `exports.f = function() {}` -> `export function f() {}` -- Replace `exports.f = ` with `export `, and insert the name after `function`. + changes.replaceRange(sourceFile, { pos: left.getStart(sourceFile), end: right.getStart(sourceFile) }, ts.createToken(84 /* ExportKeyword */), { suffix: " " }); if (!right.name) changes.insertName(sourceFile, right, name); - var semi = ts.findChildOfKind(parent, 25, sourceFile); + var semi = ts.findChildOfKind(parent, 25 /* SemicolonToken */, sourceFile); if (semi) changes.deleteNode(sourceFile, semi, { useNonAdjustedEndPosition: true }); } else { - changes.replaceNodeRangeWithNodes(sourceFile, left.expression, ts.findChildOfKind(left, 23, sourceFile), [ts.createToken(84), ts.createToken(76)], { joiner: " ", suffix: " " }); + // `exports.f = function g() {}` -> `export const f = function g() {}` -- just replace `exports.` with `export const ` + changes.replaceNodeRangeWithNodes(sourceFile, left.expression, ts.findChildOfKind(left, 23 /* DotToken */, sourceFile), [ts.createToken(84 /* ExportKeyword */), ts.createToken(76 /* ConstKeyword */)], { joiner: " ", suffix: " " }); } } + // TODO: GH#22492 this will cause an error if a change has been made inside the body of the node. function convertExportsDotXEquals_replaceNode(name, exported) { - var modifiers = [ts.createToken(84)]; + var modifiers = [ts.createToken(84 /* ExportKeyword */)]; switch (exported.kind) { - case 192: { + case 192 /* FunctionExpression */: { var expressionName = exported.name; if (expressionName && expressionName.text !== name) { + // `exports.f = function g() {}` -> `export const f = function g() {}` return exportConst(); } } - case 193: + // falls through + case 193 /* ArrowFunction */: + // `exports.f = function() {}` --> `export function f() {}` return functionExpressionToDeclaration(name, modifiers, exported); - case 205: + case 205 /* ClassExpression */: + // `exports.C = class {}` --> `export class C {}` return classExpressionToDeclaration(name, modifiers, exported); default: return exportConst(); } function exportConst() { - return makeConst(modifiers, ts.createIdentifier(name), exported); + // `exports.x = 0;` --> `export const x = 0;` + return makeConst(modifiers, ts.createIdentifier(name), exported); // TODO: GH#18217 } } + /** + * Converts `const <> = require("x");`. + * Returns nodes that will replace the variable declaration for the commonjs import. + * May also make use `changes` to remove qualifiers at the use sites of imports, to change `mod.x` to `x`. + */ function convertSingleImport(file, name, moduleSpecifier, changes, checker, identifiers, target, quotePreference) { switch (name.kind) { - case 180: { + case 180 /* ObjectBindingPattern */: { var importSpecifiers = ts.mapAllOrFail(name.elements, function (e) { return e.dotDotDotToken || e.initializer || e.propertyName && !ts.isIdentifier(e.propertyName) || !ts.isIdentifier(e.name) ? undefined : makeImportSpecifier(e.propertyName && e.propertyName.text, e.name.text); - }); + }); // tslint:disable-line no-unnecessary-type-assertion (TODO: GH#18217) if (importSpecifiers) { - return [ts.makeImport(undefined, importSpecifiers, moduleSpecifier, quotePreference)]; + return [ts.makeImport(/*name*/ undefined, importSpecifiers, moduleSpecifier, quotePreference)]; } } - case 181: { + // falls through -- object destructuring has an interesting pattern and must be a variable declaration + case 181 /* ArrayBindingPattern */: { + /* + import x from "x"; + const [a, b, c] = x; + */ var tmp = makeUniqueName(codefix.moduleSpecifierToValidIdentifier(moduleSpecifier.text, target), identifiers); return [ - ts.makeImport(ts.createIdentifier(tmp), undefined, moduleSpecifier, quotePreference), - makeConst(undefined, ts.getSynthesizedDeepClone(name), ts.createIdentifier(tmp)), + ts.makeImport(ts.createIdentifier(tmp), /*namedImports*/ undefined, moduleSpecifier, quotePreference), + makeConst(/*modifiers*/ undefined, ts.getSynthesizedDeepClone(name), ts.createIdentifier(tmp)), ]; } - case 71: + case 71 /* Identifier */: return convertSingleIdentifierImport(file, name, moduleSpecifier, changes, checker, identifiers, quotePreference); default: return ts.Debug.assertNever(name); } } + /** + * Convert `import x = require("x").` + * Also converts uses like `x.y()` to `y()` and uses a named import. + */ function convertSingleIdentifierImport(file, name, moduleSpecifier, changes, checker, identifiers, quotePreference) { var nameSymbol = checker.getSymbolAtLocation(name); + // Maps from module property name to name actually used. (The same if there isn't shadowing.) var namedBindingsNames = ts.createMap(); + // True if there is some non-property use like `x()` or `f(x)`. var needDefaultImport = false; for (var _i = 0, _a = identifiers.original.get(name.text); _i < _a.length; _i++) { var use = _a[_i]; if (checker.getSymbolAtLocation(use) !== nameSymbol || use === name) { + // This was a use of a different symbol with the same name, due to shadowing. Ignore. continue; } var parent = use.parent; if (ts.isPropertyAccessExpression(parent)) { var expression = parent.expression, propertyName = parent.name.text; - ts.Debug.assert(expression === use); + ts.Debug.assert(expression === use); // Else shouldn't have been in `collectIdentifiers` var idName = namedBindingsNames.get(propertyName); if (idName === undefined) { idName = makeUniqueName(propertyName, identifiers); @@ -86405,10 +103373,12 @@ var ts; return ts.createImportSpecifier(propertyName === idName ? undefined : ts.createIdentifier(propertyName), ts.createIdentifier(idName)); })); if (!namedBindings) { + // If it was unused, ensure that we at least import *something*. needDefaultImport = true; } return [ts.makeImport(needDefaultImport ? ts.getSynthesizedDeepClone(name) : undefined, namedBindings, moduleSpecifier, quotePreference)]; } + // Identifiers helpers function makeUniqueName(name, identifiers) { while (identifiers.original.has(name) || identifiers.additional.has(name)) { name = "_" + name; @@ -86421,6 +103391,10 @@ var ts; forEachFreeIdentifier(file, function (id) { return map.add(id.text, id); }); return map; } + /** + * A free identifier is an identifier that can be accessed through name lookup as a local variable. + * In the expression `x.y`, `x` is a free identifier, but `y` is not. + */ function forEachFreeIdentifier(node, cb) { if (ts.isIdentifier(node) && isFreeIdentifier(node)) cb(node); @@ -86429,38 +103403,44 @@ var ts; function isFreeIdentifier(node) { var parent = node.parent; switch (parent.kind) { - case 185: + case 185 /* PropertyAccessExpression */: return parent.name !== node; - case 182: + case 182 /* BindingElement */: return parent.propertyName !== node; - case 248: + case 248 /* ImportSpecifier */: return parent.propertyName !== node; default: return true; } } + // Node helpers function functionExpressionToDeclaration(name, additionalModifiers, fn) { - return ts.createFunctionDeclaration(ts.getSynthesizedDeepClones(fn.decorators), ts.concatenate(additionalModifiers, ts.getSynthesizedDeepClones(fn.modifiers)), ts.getSynthesizedDeepClone(fn.asteriskToken), name, ts.getSynthesizedDeepClones(fn.typeParameters), ts.getSynthesizedDeepClones(fn.parameters), ts.getSynthesizedDeepClone(fn.type), ts.convertToFunctionBody(ts.getSynthesizedDeepClone(fn.body))); + return ts.createFunctionDeclaration(ts.getSynthesizedDeepClones(fn.decorators), // TODO: GH#19915 Don't think this is even legal. + ts.concatenate(additionalModifiers, ts.getSynthesizedDeepClones(fn.modifiers)), ts.getSynthesizedDeepClone(fn.asteriskToken), name, ts.getSynthesizedDeepClones(fn.typeParameters), ts.getSynthesizedDeepClones(fn.parameters), ts.getSynthesizedDeepClone(fn.type), ts.convertToFunctionBody(ts.getSynthesizedDeepClone(fn.body))); } function classExpressionToDeclaration(name, additionalModifiers, cls) { - return ts.createClassDeclaration(ts.getSynthesizedDeepClones(cls.decorators), ts.concatenate(additionalModifiers, ts.getSynthesizedDeepClones(cls.modifiers)), name, ts.getSynthesizedDeepClones(cls.typeParameters), ts.getSynthesizedDeepClones(cls.heritageClauses), ts.getSynthesizedDeepClones(cls.members)); + return ts.createClassDeclaration(ts.getSynthesizedDeepClones(cls.decorators), // TODO: GH#19915 Don't think this is even legal. + ts.concatenate(additionalModifiers, ts.getSynthesizedDeepClones(cls.modifiers)), name, ts.getSynthesizedDeepClones(cls.typeParameters), ts.getSynthesizedDeepClones(cls.heritageClauses), ts.getSynthesizedDeepClones(cls.members)); } function makeSingleImport(localName, propertyName, moduleSpecifier, quotePreference) { return propertyName === "default" - ? ts.makeImport(ts.createIdentifier(localName), undefined, moduleSpecifier, quotePreference) - : ts.makeImport(undefined, [makeImportSpecifier(propertyName, localName)], moduleSpecifier, quotePreference); + ? ts.makeImport(ts.createIdentifier(localName), /*namedImports*/ undefined, moduleSpecifier, quotePreference) + : ts.makeImport(/*name*/ undefined, [makeImportSpecifier(propertyName, localName)], moduleSpecifier, quotePreference); } function makeImportSpecifier(propertyName, name) { return ts.createImportSpecifier(propertyName !== undefined && propertyName !== name ? ts.createIdentifier(propertyName) : undefined, ts.createIdentifier(name)); } function makeConst(modifiers, name, init) { - return ts.createVariableStatement(modifiers, ts.createVariableDeclarationList([ts.createVariableDeclaration(name, undefined, init)], 2)); + return ts.createVariableStatement(modifiers, ts.createVariableDeclarationList([ts.createVariableDeclaration(name, /*type*/ undefined, init)], 2 /* Const */)); } function makeExportDeclaration(exportSpecifiers, moduleSpecifier) { - return ts.createExportDeclaration(undefined, undefined, exportSpecifiers && ts.createNamedExports(exportSpecifiers), moduleSpecifier === undefined ? undefined : ts.createLiteral(moduleSpecifier)); + return ts.createExportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, exportSpecifiers && ts.createNamedExports(exportSpecifiers), moduleSpecifier === undefined ? undefined : ts.createLiteral(moduleSpecifier)); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -86486,24 +103466,25 @@ var ts; }); }, }); function getQualifiedName(sourceFile, pos) { - var qualifiedName = ts.findAncestor(ts.getTokenAtPosition(sourceFile, pos, true), ts.isQualifiedName); + var qualifiedName = ts.findAncestor(ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ true), ts.isQualifiedName); ts.Debug.assert(!!qualifiedName, "Expected position to be owned by a qualified name."); return ts.isIdentifier(qualifiedName.left) ? qualifiedName : undefined; } function doChange(changeTracker, sourceFile, qualifiedName) { var rightText = qualifiedName.right.text; - var replacement = ts.createIndexedAccessTypeNode(ts.createTypeReferenceNode(qualifiedName.left, undefined), ts.createLiteralTypeNode(ts.createLiteral(rightText))); + var replacement = ts.createIndexedAccessTypeNode(ts.createTypeReferenceNode(qualifiedName.left, /*typeArguments*/ undefined), ts.createLiteralTypeNode(ts.createLiteral(rightText))); changeTracker.replaceNode(sourceFile, qualifiedName, replacement); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; (function (codefix) { var errorCodes = [ts.Diagnostics.Class_0_incorrectly_implements_interface_1.code, ts.Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass.code]; - var fixId = "fixClassIncorrectlyImplementsInterface"; + var fixId = "fixClassIncorrectlyImplementsInterface"; // TODO: share a group with fixClassDoesntImplementInheritedAbstractMember? codefix.registerCodeFix({ errorCodes: errorCodes, getCodeActions: function (context) { @@ -86530,22 +103511,24 @@ var ts; }, }); function getClass(sourceFile, pos) { - return ts.Debug.assertDefined(ts.getContainingClass(ts.getTokenAtPosition(sourceFile, pos, false))); + return ts.Debug.assertDefined(ts.getContainingClass(ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false))); } function symbolPointsToNonPrivateMember(symbol) { - return !(ts.getModifierFlags(symbol.valueDeclaration) & 8); + return !(ts.getModifierFlags(symbol.valueDeclaration) & 8 /* Private */); } function addMissingDeclarations(checker, implementedTypeNode, sourceFile, classDeclaration, changeTracker, preferences) { var maybeHeritageClauseSymbol = getHeritageClauseSymbolTable(classDeclaration, checker); + // Note that this is ultimately derived from a map indexed by symbol names, + // so duplicates cannot occur. var implementedType = checker.getTypeAtLocation(implementedTypeNode); var implementedTypeSymbols = checker.getPropertiesOfType(implementedType); var nonPrivateAndNotExistedInHeritageClauseMembers = implementedTypeSymbols.filter(ts.and(symbolPointsToNonPrivateMember, function (symbol) { return !maybeHeritageClauseSymbol.has(symbol.escapedName); })); var classType = checker.getTypeAtLocation(classDeclaration); if (!classType.getNumberIndexType()) { - createMissingIndexSignatureDeclaration(implementedType, 1); + createMissingIndexSignatureDeclaration(implementedType, 1 /* Number */); } if (!classType.getStringIndexType()) { - createMissingIndexSignatureDeclaration(implementedType, 0); + createMissingIndexSignatureDeclaration(implementedType, 0 /* String */); } codefix.createMissingMemberNodes(classDeclaration, nonPrivateAndNotExistedInHeritageClauseMembers, checker, preferences, function (member) { return changeTracker.insertNodeAtClassStart(sourceFile, classDeclaration, member); }); function createMissingIndexSignatureDeclaration(type, kind) { @@ -86565,6 +103548,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -86581,10 +103565,12 @@ var ts; getCodeActions: function (context) { return context.errorCode === ts.Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code ? getActionsForUMDImport(context) : getActionsForNonUMDImport(context); }, + // TODO: GH#20315 fixIds: [], getAllCodeActions: ts.notImplemented, }); function createCodeAction(descriptionDiagnostic, diagnosticArgs, changes) { + // TODO: GH#20315 return codefix.createCodeFixActionNoFixId("import", changes, [descriptionDiagnostic].concat(diagnosticArgs)); } function convertToImportCodeFixContext(context, symbolToken, symbolName) { @@ -86613,6 +103599,7 @@ var ts; function getImportCompletionAction(exportedSymbol, moduleSymbol, sourceFile, symbolName, host, program, checker, compilerOptions, allSourceFiles, formatContext, getCanonicalFileName, symbolToken, preferences) { var exportInfos = getAllReExportingModules(exportedSymbol, moduleSymbol, symbolName, sourceFile, checker, allSourceFiles); ts.Debug.assert(exportInfos.some(function (info) { return info.moduleSymbol === moduleSymbol; })); + // We sort the best codefixes first, so taking `first` is best for completions. var moduleSpecifier = ts.first(getNewImportInfos(program, sourceFile, exportInfos, host, preferences)).moduleSpecifier; var ctx = { host: host, program: program, checker: checker, compilerOptions: compilerOptions, sourceFile: sourceFile, formatContext: formatContext, symbolName: symbolName, getCanonicalFileName: getCanonicalFileName, symbolToken: symbolToken, preferences: preferences }; return { moduleSpecifier: moduleSpecifier, codeAction: ts.first(getCodeActionsForImport(exportInfos, ctx)) }; @@ -86621,14 +103608,15 @@ var ts; function getAllReExportingModules(exportedSymbol, exportingModuleSymbol, symbolName, sourceFile, checker, allSourceFiles) { var result = []; forEachExternalModule(checker, allSourceFiles, function (moduleSymbol, moduleFile) { + // Don't import from a re-export when looking "up" like to `./index` or `../index`. if (moduleFile && moduleSymbol !== exportingModuleSymbol && ts.startsWith(sourceFile.fileName, ts.getDirectoryPath(moduleFile.fileName))) { return; } for (var _i = 0, _a = checker.getExportsOfModule(moduleSymbol); _i < _a.length; _i++) { var exported = _a[_i]; - if ((exported.escapedName === "default" || exported.name === symbolName) && ts.skipAlias(exported, checker) === exportedSymbol) { - var isDefaultExport = checker.tryGetMemberInModuleExports("default", moduleSymbol) === exported; - result.push({ moduleSymbol: moduleSymbol, importKind: isDefaultExport ? 1 : 0 }); + if ((exported.escapedName === "default" /* Default */ || exported.name === symbolName) && ts.skipAlias(exported, checker) === exportedSymbol) { + var isDefaultExport = checker.tryGetMemberInModuleExports("default" /* Default */, moduleSymbol) === exported; + result.push({ moduleSymbol: moduleSymbol, importKind: isDefaultExport ? 1 /* Default */ : 0 /* Named */ }); } } }); @@ -86646,11 +103634,23 @@ var ts; if (addToExisting) { useExisting.push(addToExisting); } - else { + else { // Don't bother providing an action to add a new import if we can add to an existing one. getCodeActionsForAddImport(exportInfos, context, existingImports, addNew); } } function tryUseExistingNamespaceImport(existingImports, context, symbolToken, checker) { + // It is possible that multiple import statements with the same specifier exist in the file. + // e.g. + // + // import * as ns from "foo"; + // import { member1, member2 } from "foo"; + // + // member3/**/ <-- cusor here + // + // in this case we should provie 2 actions: + // 1. change "member3" to "ns.member3" + // 2. add "member3" to the second import statement's import list + // and it is up to the user to decide which one fits best. return !symbolToken || !ts.isIdentifier(symbolToken) ? undefined : ts.firstDefined(existingImports, function (_a) { var declaration = _a.declaration; var namespace = getNamespaceImportName(declaration); @@ -86665,7 +103665,7 @@ var ts; function tryAddToExistingImport(existingImports, context) { return ts.firstDefined(existingImports, function (_a) { var declaration = _a.declaration, importKind = _a.importKind; - if (declaration.kind === 244 && declaration.importClause) { + if (declaration.kind === 244 /* ImportDeclaration */ && declaration.importClause) { var changes = tryUpdateExistingImport(context, declaration.importClause, importKind); if (changes) { var moduleSpecifierWithoutQuotes = ts.stripQuotes(declaration.moduleSpecifier.getText()); @@ -86675,9 +103675,9 @@ var ts; }); } function getNamespaceImportName(declaration) { - if (declaration.kind === 244) { + if (declaration.kind === 244 /* ImportDeclaration */) { var namedBindings = declaration.importClause && ts.isImportClause(declaration.importClause) && declaration.importClause.namedBindings; - return namedBindings && namedBindings.kind === 246 ? namedBindings.name : undefined; + return namedBindings && namedBindings.kind === 246 /* NamespaceImport */ ? namedBindings.name : undefined; } else { return declaration.name; @@ -86688,7 +103688,7 @@ var ts; var imports = _b.imports; return ts.mapDefined(imports, function (moduleSpecifier) { var i = ts.importFromModuleSpecifier(moduleSpecifier); - return (i.kind === 244 || i.kind === 243) + return (i.kind === 244 /* ImportDeclaration */ || i.kind === 243 /* ImportEqualsDeclaration */) && checker.getSymbolAtLocation(moduleSpecifier) === moduleSymbol ? { declaration: i, importKind: importKind } : undefined; }); } @@ -86697,21 +103697,28 @@ var ts; var sourceFile = context.sourceFile, symbolName = context.symbolName, preferences = context.preferences; var moduleSpecifierWithoutQuotes = ts.stripQuotes(moduleSpecifier); var quotedModuleSpecifier = ts.makeStringLiteral(moduleSpecifierWithoutQuotes, ts.getQuotePreference(sourceFile, preferences)); - var importDecl = importKind !== 3 - ? ts.createImportDeclaration(undefined, undefined, createImportClauseOfKind(importKind, symbolName), quotedModuleSpecifier) - : ts.createImportEqualsDeclaration(undefined, undefined, ts.createIdentifier(symbolName), ts.createExternalModuleReference(quotedModuleSpecifier)); + var importDecl = importKind !== 3 /* Equals */ + ? ts.createImportDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, createImportClauseOfKind(importKind, symbolName), quotedModuleSpecifier) + : ts.createImportEqualsDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, ts.createIdentifier(symbolName), ts.createExternalModuleReference(quotedModuleSpecifier)); var changes = ChangeTracker.with(context, function (t) { return ts.insertImport(t, sourceFile, importDecl); }); + // if this file doesn't have any import statements, insert an import statement and then insert a new line + // between the only import statement and user code. Otherwise just insert the statement because chances + // are there are already a new line separating code and import statements. return createCodeAction(ts.Diagnostics.Import_0_from_module_1, [symbolName, moduleSpecifierWithoutQuotes], changes); } function createImportClauseOfKind(kind, symbolName) { var id = ts.createIdentifier(symbolName); switch (kind) { - case 1: - return ts.createImportClause(id, undefined); - case 2: - return ts.createImportClause(undefined, ts.createNamespaceImport(id)); - case 0: - return ts.createImportClause(undefined, ts.createNamedImports([ts.createImportSpecifier(undefined, id)])); + case 1 /* Default */: + return ts.createImportClause(id, /*namedBindings*/ undefined); + case 2 /* Namespace */: + return ts.createImportClause(/*name*/ undefined, ts.createNamespaceImport(id)); + case 0 /* Named */: + return ts.createImportClause(/*name*/ undefined, ts.createNamedImports([ts.createImportSpecifier(/*propertyName*/ undefined, id)])); default: ts.Debug.assertNever(kind); } @@ -86722,6 +103729,7 @@ var ts; var modulePathsGroups = ts.moduleSpecifiers.getModuleSpecifiers(moduleSymbol, program.getCompilerOptions(), sourceFile, host, program.getSourceFiles(), preferences); return modulePathsGroups.map(function (group) { return group.map(function (moduleSpecifier) { return ({ moduleSpecifier: moduleSpecifier, importKind: importKind }); }); }); }); + // Sort to keep the shortest paths first, but keep [relativePath, importRelativeToBaseUrl] groups together return ts.flatten(choicesForEachExportingModule.sort(function (a, b) { return ts.first(a).moduleSpecifier.length - ts.first(b).moduleSpecifier.length; })); } function getCodeActionsForAddImport(exportInfos, ctx, existingImports, addNew) { @@ -86736,9 +103744,9 @@ var ts; } function newImportInfoFromExistingSpecifier(_a) { var declaration = _a.declaration, importKind = _a.importKind; - var expression = declaration.kind === 244 + var expression = declaration.kind === 244 /* ImportDeclaration */ ? declaration.moduleSpecifier - : declaration.moduleReference.kind === 254 + : declaration.moduleReference.kind === 254 /* ExternalModuleReference */ ? declaration.moduleReference.expression : undefined; return expression && ts.isStringLiteral(expression) ? { moduleSpecifier: expression.text, importKind: importKind } : undefined; @@ -86746,29 +103754,30 @@ var ts; function tryUpdateExistingImport(context, importClause, importKind) { var symbolName = context.symbolName, sourceFile = context.sourceFile; var name = importClause.name; - var namedBindings = (importClause.kind !== 243 && importClause).namedBindings; + var namedBindings = (importClause.kind !== 243 /* ImportEqualsDeclaration */ && importClause).namedBindings; // TODO: GH#18217 switch (importKind) { - case 1: + case 1 /* Default */: return name ? undefined : ChangeTracker.with(context, function (t) { return t.replaceNode(sourceFile, importClause, ts.createImportClause(ts.createIdentifier(symbolName), namedBindings)); }); - case 0: { - var newImportSpecifier_1 = ts.createImportSpecifier(undefined, ts.createIdentifier(symbolName)); - if (namedBindings && namedBindings.kind === 247 && namedBindings.elements.length !== 0) { + case 0 /* Named */: { + var newImportSpecifier_1 = ts.createImportSpecifier(/*propertyName*/ undefined, ts.createIdentifier(symbolName)); + if (namedBindings && namedBindings.kind === 247 /* NamedImports */ && namedBindings.elements.length !== 0) { + // There are already named imports; add another. return ChangeTracker.with(context, function (t) { return t.insertNodeInListAfter(sourceFile, namedBindings.elements[namedBindings.elements.length - 1], newImportSpecifier_1); }); } - if (!namedBindings || namedBindings.kind === 247 && namedBindings.elements.length === 0) { + if (!namedBindings || namedBindings.kind === 247 /* NamedImports */ && namedBindings.elements.length === 0) { return ChangeTracker.with(context, function (t) { return t.replaceNode(sourceFile, importClause, ts.createImportClause(name, ts.createNamedImports([newImportSpecifier_1]))); }); } return undefined; } - case 2: + case 2 /* Namespace */: return namedBindings ? undefined : ChangeTracker.with(context, function (t) { return t.replaceNode(sourceFile, importClause, ts.createImportClause(name, ts.createNamespaceImport(ts.createIdentifier(symbolName)))); }); - case 3: + case 3 /* Equals */: return undefined; default: ts.Debug.assertNever(importKind); @@ -86776,23 +103785,35 @@ var ts; } function getCodeActionForUseExistingNamespaceImport(namespacePrefix, context, symbolToken) { var symbolName = context.symbolName, sourceFile = context.sourceFile; + /** + * Cases: + * import * as ns from "mod" + * import default, * as ns from "mod" + * import ns = require("mod") + * + * Because there is no import list, we alter the reference to include the + * namespace instead of altering the import declaration. For example, "foo" would + * become "ns.foo" + */ var changes = ChangeTracker.with(context, function (tracker) { return tracker.replaceNode(sourceFile, symbolToken, ts.createPropertyAccess(ts.createIdentifier(namespacePrefix), symbolToken)); }); return createCodeAction(ts.Diagnostics.Change_0_to_1, [symbolName, namespacePrefix + "." + symbolName], changes); } function getActionsForUMDImport(context) { - var token = ts.getTokenAtPosition(context.sourceFile, context.span.start, false); + var token = ts.getTokenAtPosition(context.sourceFile, context.span.start, /*includeJsDocComment*/ false); var checker = context.program.getTypeChecker(); var umdSymbol; if (ts.isIdentifier(token)) { + // try the identifier to see if it is the umd symbol umdSymbol = checker.getSymbolAtLocation(token); } if (!ts.isUMDExportSymbol(umdSymbol)) { + // The error wasn't for the symbolAtLocation, it was for the JSX tag itself, which needs access to e.g. `React`. var parent = token.parent; var isNodeOpeningLikeElement = ts.isJsxOpeningLikeElement(parent); - if ((ts.isJsxOpeningLikeElement && parent.tagName === token) || parent.kind === 260) { - umdSymbol = checker.resolveName(checker.getJsxNamespace(parent), isNodeOpeningLikeElement ? parent.tagName : parent, 67216319, false); + if ((ts.isJsxOpeningLikeElement && parent.tagName === token) || parent.kind === 260 /* JsxOpeningFragment */) { + umdSymbol = checker.resolveName(checker.getJsxNamespace(parent), isNodeOpeningLikeElement ? parent.tagName : parent, 67216319 /* Value */, /*excludeGlobals*/ false); } } if (ts.isUMDExportSymbol(umdSymbol)) { @@ -86804,35 +103825,41 @@ var ts; return undefined; } function getUmdImportKind(compilerOptions) { + // Import a synthetic `default` if enabled. if (ts.getAllowSyntheticDefaultImports(compilerOptions)) { - return 1; + return 1 /* Default */; } + // When a synthetic `default` is unavailable, use `import..require` if the module kind supports it. var moduleKind = ts.getEmitModuleKind(compilerOptions); switch (moduleKind) { case ts.ModuleKind.AMD: case ts.ModuleKind.CommonJS: case ts.ModuleKind.UMD: - return 3; + return 3 /* Equals */; case ts.ModuleKind.System: case ts.ModuleKind.ES2015: case ts.ModuleKind.ESNext: case ts.ModuleKind.None: - return 2; + // Fall back to the `import * as ns` style import. + return 2 /* Namespace */; default: return ts.Debug.assertNever(moduleKind); } } function getActionsForNonUMDImport(context) { + // This will always be an Identifier, since the diagnostics we fix only fail on identifiers. var sourceFile = context.sourceFile, span = context.span, program = context.program, cancellationToken = context.cancellationToken; var checker = program.getTypeChecker(); - var symbolToken = ts.getTokenAtPosition(sourceFile, span.start, false); + var symbolToken = ts.getTokenAtPosition(sourceFile, span.start, /*includeJsDocComment*/ false); + // If we're at ``, we must check if `Foo` is already in scope, and if so, get an import for `React` instead. var symbolName = ts.isJsxOpeningLikeElement(symbolToken.parent) && symbolToken.parent.tagName === symbolToken - && (!ts.isIdentifier(symbolToken) || ts.isIntrinsicJsxName(symbolToken.text) || checker.resolveName(symbolToken.text, symbolToken, 67108863, false)) + && (!ts.isIdentifier(symbolToken) || ts.isIntrinsicJsxName(symbolToken.text) || checker.resolveName(symbolToken.text, symbolToken, 67108863 /* All */, /*excludeGlobals*/ false)) ? checker.getJsxNamespace() : ts.isIdentifier(symbolToken) ? symbolToken.text : undefined; if (!symbolName) return undefined; + // "default" is a keyword and not a legal identifier for the import, so we don't expect it here ts.Debug.assert(symbolName !== "default"); var addToExistingDeclaration = []; var addNewDeclaration = []; @@ -86842,24 +103869,28 @@ var ts; return addToExistingDeclaration.concat(addNewDeclaration); } function getExportInfos(symbolName, currentTokenMeaning, cancellationToken, sourceFile, checker, program) { + // For each original symbol, keep all re-exports of that symbol together so we can call `getCodeActionsForImport` on the whole group at once. + // Maps symbol id to info for modules providing that symbol (original export + re-exports). var originalSymbolToExportInfos = ts.createMultiMap(); function addSymbol(moduleSymbol, exportedSymbol, importKind) { originalSymbolToExportInfos.add(ts.getUniqueSymbolId(exportedSymbol, checker).toString(), { moduleSymbol: moduleSymbol, importKind: importKind }); } forEachExternalModuleToImportFrom(checker, sourceFile, program.getSourceFiles(), function (moduleSymbol) { cancellationToken.throwIfCancellationRequested(); - var defaultExport = checker.tryGetMemberInModuleExports("default", moduleSymbol); + // check the default export + var defaultExport = checker.tryGetMemberInModuleExports("default" /* Default */, moduleSymbol); if (defaultExport) { var localSymbol = ts.getLocalSymbolForExportDefault(defaultExport); if ((localSymbol && localSymbol.escapedName === symbolName || getEscapedNameForExportDefault(defaultExport) === symbolName || moduleSymbolToValidIdentifier(moduleSymbol, program.getCompilerOptions().target) === symbolName) && checkSymbolHasMeaning(localSymbol || defaultExport, currentTokenMeaning)) { - addSymbol(moduleSymbol, localSymbol || defaultExport, 1); + addSymbol(moduleSymbol, localSymbol || defaultExport, 1 /* Default */); } } + // check exports with the same name var exportSymbolWithIdenticalName = checker.tryGetMemberInModuleExportsAndProperties(symbolName, moduleSymbol); if (exportSymbolWithIdenticalName && checkSymbolHasMeaning(exportSymbolWithIdenticalName, currentTokenMeaning)) { - addSymbol(moduleSymbol, exportSymbolWithIdenticalName, 0); + addSymbol(moduleSymbol, exportSymbolWithIdenticalName, 0 /* Named */); } function getEscapedNameForExportDefault(symbol) { return symbol.declarations && ts.firstDefined(symbol.declarations, function (declaration) { @@ -86869,7 +103900,7 @@ var ts; } } else if (ts.isExportSpecifier(declaration)) { - ts.Debug.assert(declaration.name.escapedText === "default"); + ts.Debug.assert(declaration.name.escapedText === "default" /* Default */); return declaration.propertyName && declaration.propertyName.escapedText; } }); @@ -86892,7 +103923,7 @@ var ts; function forEachExternalModule(checker, allSourceFiles, cb) { for (var _i = 0, _a = checker.getAmbientModules(); _i < _a.length; _i++) { var ambient = _a[_i]; - cb(ambient, undefined); + cb(ambient, /*sourceFile*/ undefined); } for (var _b = 0, allSourceFiles_1 = allSourceFiles; _b < allSourceFiles_1.length; _b++) { var sourceFile = allSourceFiles_1[_b]; @@ -86901,7 +103932,12 @@ var ts; } } } + /** + * Don't include something from a `node_modules` that isn't actually reachable by a global import. + * A relative import to node_modules is usually a bad idea. + */ function isImportablePath(fromPath, toPath) { + // If it's in a `node_modules` but is not reachable from here via a global import, don't bother. var toNodeModules = ts.forEachAncestorDirectory(toPath, function (ancestor) { return ts.getBaseFileName(ancestor) === "node_modules" ? ancestor : undefined; }); return toNodeModules === undefined || ts.startsWith(fromPath, ts.getDirectoryPath(toNodeModules)); } @@ -86932,11 +103968,13 @@ var ts; } lastCharWasValid = isValid; } + // Need `|| "_"` to ensure result isn't empty. return !ts.isStringANonContextualKeyword(res) ? res || "_" : "_" + res; } codefix.moduleSpecifierToValidIdentifier = moduleSpecifierToValidIdentifier; })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -86968,16 +104006,19 @@ var ts; }); }, }); function getInfo(sourceFile, pos, context) { - var node = ts.getTokenAtPosition(sourceFile, pos, false); + // This is the identifier of the misspelled word. eg: + // this.speling = 1; + // ^^^^^^^ + var node = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); // TODO: GH#15852 var checker = context.program.getTypeChecker(); var suggestion; if (ts.isPropertyAccessExpression(node.parent) && node.parent.name === node) { - ts.Debug.assert(node.kind === 71); + ts.Debug.assert(node.kind === 71 /* Identifier */); var containingType = checker.getTypeAtLocation(node.parent.expression); suggestion = checker.getSuggestionForNonexistentProperty(node, containingType); } else if (ts.isImportSpecifier(node.parent) && node.parent.name === node) { - ts.Debug.assert(node.kind === 71); + ts.Debug.assert(node.kind === 71 /* Identifier */); var importDeclaration = ts.findAncestor(node, ts.isImportDeclaration); var resolvedSourceFile = getResolvedSourceFileFromImportDeclaration(sourceFile, context, importDeclaration); if (resolvedSourceFile && resolvedSourceFile.symbol) { @@ -87002,14 +104043,14 @@ var ts; } function convertSemanticMeaningToSymbolFlags(meaning) { var flags = 0; - if (meaning & 4) { - flags |= 1920; + if (meaning & 4 /* Namespace */) { + flags |= 1920 /* Namespace */; } - if (meaning & 2) { - flags |= 67901928; + if (meaning & 2 /* Type */) { + flags |= 67901928 /* Type */; } - if (meaning & 1) { - flags |= 67216319; + if (meaning & 1 /* Value */) { + flags |= 67216319 /* Value */; } return flags; } @@ -87023,6 +104064,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87058,6 +104100,7 @@ var ts; if (!ts.addToSeen(seenNames, token.text)) { return; } + // Always prefer to add a method declaration if possible. if (call) { addMethodDeclaration(changes, classDeclarationSourceFile, classDeclaration, token, call, makeStatic, inJs, preferences); } @@ -87074,7 +104117,10 @@ var ts; }, }); function getInfo(tokenSourceFile, tokenPos, checker) { - var token = ts.getTokenAtPosition(tokenSourceFile, tokenPos, false); + // The identifier of the missing property. eg: + // this.missing = 1; + // ^^^^^^^ + var token = ts.getTokenAtPosition(tokenSourceFile, tokenPos, /*includeJsDocComment*/ false); if (!ts.isIdentifier(token)) { return undefined; } @@ -87099,7 +104145,7 @@ var ts; } function addMissingMemberInJs(changeTracker, classDeclarationSourceFile, classDeclaration, tokenName, makeStatic) { if (makeStatic) { - if (classDeclaration.kind === 205) { + if (classDeclaration.kind === 205 /* ClassExpression */) { return; } var className = classDeclaration.name.getText(); @@ -87125,20 +104171,24 @@ var ts; } function getTypeNode(checker, classDeclaration, token) { var typeNode; - if (token.parent.parent.kind === 200) { + if (token.parent.parent.kind === 200 /* BinaryExpression */) { var binaryExpression = token.parent.parent; var otherExpression = token.parent === binaryExpression.left ? binaryExpression.right : binaryExpression.left; - var widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(otherExpression))); + var widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(otherExpression))); // TODO: GH#18217 typeNode = checker.typeToTypeNode(widenedType, classDeclaration); } - return typeNode || ts.createKeywordTypeNode(119); + return typeNode || ts.createKeywordTypeNode(119 /* AnyKeyword */); } function createAddPropertyDeclarationAction(context, classDeclarationSourceFile, classDeclaration, makeStatic, tokenName, typeNode) { var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addPropertyDeclaration(t, classDeclarationSourceFile, classDeclaration, tokenName, typeNode, makeStatic); }); return codefix.createCodeFixAction(fixName, changes, [makeStatic ? ts.Diagnostics.Declare_static_property_0 : ts.Diagnostics.Declare_property_0, tokenName], fixId, ts.Diagnostics.Add_all_missing_members); } function addPropertyDeclaration(changeTracker, classDeclarationSourceFile, classDeclaration, tokenName, typeNode, makeStatic) { - var property = ts.createProperty(undefined, makeStatic ? [ts.createToken(115)] : undefined, tokenName, undefined, typeNode, undefined); + var property = ts.createProperty( + /*decorators*/ undefined, + /*modifiers*/ makeStatic ? [ts.createToken(115 /* StaticKeyword */)] : undefined, tokenName, + /*questionToken*/ undefined, typeNode, + /*initializer*/ undefined); var lastProp = getNodeToInsertPropertyAfter(classDeclaration); if (lastProp) { changeTracker.insertNodeAfter(classDeclarationSourceFile, lastProp, property); @@ -87147,6 +104197,7 @@ var ts; changeTracker.insertNodeAtClassStart(classDeclarationSourceFile, classDeclaration, property); } } + // Gets the last of the first run of PropertyDeclarations, or undefined if the class does not start with a PropertyDeclaration. function getNodeToInsertPropertyAfter(cls) { var res; for (var _i = 0, _a = cls.members; _i < _a.length; _i++) { @@ -87158,10 +104209,19 @@ var ts; return res; } function createAddIndexSignatureAction(context, classDeclarationSourceFile, classDeclaration, tokenName, typeNode) { - var stringTypeNode = ts.createKeywordTypeNode(137); - var indexingParameter = ts.createParameter(undefined, undefined, undefined, "x", undefined, stringTypeNode, undefined); - var indexSignature = ts.createIndexSignature(undefined, undefined, [indexingParameter], typeNode); + // Index signatures cannot have the static modifier. + var stringTypeNode = ts.createKeywordTypeNode(137 /* StringKeyword */); + var indexingParameter = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, "x", + /*questionToken*/ undefined, stringTypeNode, + /*initializer*/ undefined); + var indexSignature = ts.createIndexSignature( + /*decorators*/ undefined, + /*modifiers*/ undefined, [indexingParameter], typeNode); var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return t.insertNodeAtClassStart(classDeclarationSourceFile, classDeclaration, indexSignature); }); + // No fixId here because code-fix-all currently only works on adding individual named properties. return codefix.createCodeFixActionNoFixId(fixName, changes, [ts.Diagnostics.Add_index_signature_for_property_0, tokenName]); } function getActionForMethodDeclaration(context, classDeclarationSourceFile, classDeclaration, token, callExpression, makeStatic, inJs, preferences) { @@ -87170,7 +104230,7 @@ var ts; } function addMethodDeclaration(changeTracker, classDeclarationSourceFile, classDeclaration, token, callExpression, makeStatic, inJs, preferences) { var methodDeclaration = codefix.createMethodFromCallExpression(callExpression, token.text, inJs, makeStatic, preferences); - var containingMethodDeclaration = ts.getAncestor(callExpression, 154); + var containingMethodDeclaration = ts.getAncestor(callExpression, 154 /* MethodDeclaration */); if (containingMethodDeclaration && containingMethodDeclaration.parent === classDeclaration) { changeTracker.insertNodeAfter(classDeclarationSourceFile, containingMethodDeclaration, methodDeclaration); } @@ -87180,6 +104240,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87196,7 +104257,7 @@ var ts; var host = context.host, sourceFile = context.sourceFile, start = context.span.start; var packageName = getTypesPackageNameToInstall(host, sourceFile, start, context.errorCode); return packageName === undefined ? [] - : [codefix.createCodeFixAction(fixId, [], [ts.Diagnostics.Install_0, packageName], fixId, ts.Diagnostics.Install_all_missing_types_packages, getCommand(sourceFile.fileName, packageName))]; + : [codefix.createCodeFixAction(fixId, /*changes*/ [], [ts.Diagnostics.Install_0, packageName], fixId, ts.Diagnostics.Install_all_missing_types_packages, getCommand(sourceFile.fileName, packageName))]; }, fixIds: [fixId], getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (_, diag, commands) { @@ -87210,14 +104271,15 @@ var ts; return { type: "install package", file: fileName, packageName: packageName }; } function getTypesPackageNameToInstall(host, sourceFile, pos, diagCode) { - var moduleName = ts.cast(ts.getTokenAtPosition(sourceFile, pos, false), ts.isStringLiteral).text; + var moduleName = ts.cast(ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false), ts.isStringLiteral).text; var packageName = ts.getPackageName(moduleName).packageName; return diagCode === errorCodeCannotFindModule ? (ts.JsTyping.nodeCoreModules.has(packageName) ? "@types/node" : undefined) - : (host.isKnownTypesPackageName(packageName) ? ts.getTypesPackageName(packageName) : undefined); + : (host.isKnownTypesPackageName(packageName) ? ts.getTypesPackageName(packageName) : undefined); // TODO: GH#18217 } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87248,21 +104310,28 @@ var ts; }, }); function getClass(sourceFile, pos) { - var token = ts.getTokenAtPosition(sourceFile, pos, false); + // Token is the identifier in the case of a class declaration + // or the class keyword token in the case of a class expression. + var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); return ts.cast(token.parent, ts.isClassLike); } function addMissingMembers(classDeclaration, sourceFile, checker, changeTracker, preferences) { var extendsNode = ts.getClassExtendsHeritageClauseElement(classDeclaration); var instantiatedExtendsType = checker.getTypeAtLocation(extendsNode); + // Note that this is ultimately derived from a map indexed by symbol names, + // so duplicates cannot occur. var abstractAndNonPrivateExtendsSymbols = checker.getPropertiesOfType(instantiatedExtendsType).filter(symbolPointsToNonPrivateAndAbstractMember); codefix.createMissingMemberNodes(classDeclaration, abstractAndNonPrivateExtendsSymbols, checker, preferences, function (member) { return changeTracker.insertNodeAtClassStart(sourceFile, classDeclaration, member); }); } function symbolPointsToNonPrivateAndAbstractMember(symbol) { + // See `codeFixClassExtendAbstractProtectedProperty.ts` in https://github.com/Microsoft/TypeScript/pull/11547/files + // (now named `codeFixClassExtendAbstractPrivateProperty.ts`) var flags = ts.getModifierFlags(ts.first(symbol.getDeclarations())); - return !(flags & 8) && !!(flags & 128); + return !(flags & 8 /* Private */) && !!(flags & 128 /* Abstract */); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87283,7 +104352,7 @@ var ts; fixIds: [fixId], getAllCodeActions: function (context) { var sourceFile = context.sourceFile; - var seenClasses = ts.createMap(); + var seenClasses = ts.createMap(); // Ensure we only do this once per class. return codefix.codeFixAll(context, errorCodes, function (changes, diag) { var nodes = getNodes(diag.file, diag.start); if (!nodes) @@ -87300,11 +104369,13 @@ var ts; changes.deleteNode(sourceFile, superCall); } function getNodes(sourceFile, pos) { - var token = ts.getTokenAtPosition(sourceFile, pos, false); - if (token.kind !== 99) + var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); + if (token.kind !== 99 /* ThisKeyword */) return undefined; var constructor = ts.getContainingFunction(token); var superCall = findSuperCall(constructor.body); + // figure out if the `this` access is actually inside the supercall + // i.e. super(this.a), since in that case we won't suggest a fix return superCall && !superCall.expression.arguments.some(function (arg) { return ts.isPropertyAccessExpression(arg) && arg.expression === token; }) ? { constructor: constructor, superCall: superCall } : undefined; } function findSuperCall(n) { @@ -87316,6 +104387,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87336,16 +104408,17 @@ var ts; }); }, }); function getNode(sourceFile, pos) { - var token = ts.getTokenAtPosition(sourceFile, pos, false); - ts.Debug.assert(token.kind === 123); + var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); + ts.Debug.assert(token.kind === 123 /* ConstructorKeyword */); return token.parent; } function doChange(changes, sourceFile, ctr) { - var superCall = ts.createStatement(ts.createCall(ts.createSuper(), undefined, ts.emptyArray)); + var superCall = ts.createStatement(ts.createCall(ts.createSuper(), /*typeArguments*/ undefined, /*argumentsArray*/ ts.emptyArray)); changes.insertNodeAtConstructorStart(sourceFile, ctr, superCall); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87371,19 +104444,22 @@ var ts; }); }, }); function getNodes(sourceFile, pos) { - var token = ts.getTokenAtPosition(sourceFile, pos, false); + var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); var heritageClauses = ts.getContainingClass(token).heritageClauses; var extendsToken = heritageClauses[0].getFirstToken(); - return extendsToken.kind === 85 ? { extendsToken: extendsToken, heritageClauses: heritageClauses } : undefined; + return extendsToken.kind === 85 /* ExtendsKeyword */ ? { extendsToken: extendsToken, heritageClauses: heritageClauses } : undefined; } function doChanges(changes, sourceFile, extendsToken, heritageClauses) { - changes.replaceNode(sourceFile, extendsToken, ts.createToken(108)); + changes.replaceNode(sourceFile, extendsToken, ts.createToken(108 /* ImplementsKeyword */)); + // If there is already an implements clause, replace the implements keyword with a comma. if (heritageClauses.length === 2 && - heritageClauses[0].token === 85 && - heritageClauses[1].token === 108) { + heritageClauses[0].token === 85 /* ExtendsKeyword */ && + heritageClauses[1].token === 108 /* ImplementsKeyword */) { var implementsToken = heritageClauses[1].getFirstToken(); var implementsFullStart = implementsToken.getFullStart(); - changes.replaceRange(sourceFile, { pos: implementsFullStart, end: implementsFullStart }, ts.createToken(26)); + changes.replaceRange(sourceFile, { pos: implementsFullStart, end: implementsFullStart }, ts.createToken(26 /* CommaToken */)); + // Rough heuristic: delete trailing whitespace after keyword so that it's not excessive. + // (Trailing because leading might be indentation, which is more sensitive.) var text = sourceFile.text; var end = implementsToken.end; while (end < text.length && ts.isWhiteSpaceSingleLine(text.charCodeAt(end))) { @@ -87394,6 +104470,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87423,18 +104500,20 @@ var ts; }); }, }); function getInfo(sourceFile, pos, diagCode) { - var node = ts.getTokenAtPosition(sourceFile, pos, false); + var node = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); if (!ts.isIdentifier(node)) return undefined; return { node: node, className: diagCode === didYouMeanStaticMemberCode ? ts.getContainingClass(node).name.text : undefined }; } function doChange(changes, sourceFile, _a) { var node = _a.node, className = _a.className; + // TODO (https://github.com/Microsoft/TypeScript/issues/21246): use shared helper ts.suppressLeadingAndTrailingTrivia(node); changes.replaceNode(sourceFile, node, ts.createPropertyAccess(className ? ts.createIdentifier(className) : ts.createThis(), node)); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87455,23 +104534,23 @@ var ts; getCodeActions: function (context) { var errorCode = context.errorCode, sourceFile = context.sourceFile, program = context.program; var checker = program.getTypeChecker(); - var startToken = ts.getTokenAtPosition(sourceFile, context.span.start, false); + var startToken = ts.getTokenAtPosition(sourceFile, context.span.start, /*includeJsDocComment*/ false); var importDecl = tryGetFullImport(startToken); if (importDecl) { var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return t.deleteNode(sourceFile, importDecl); }); return [codefix.createCodeFixAction(fixName, changes, [ts.Diagnostics.Remove_import_from_0, ts.showModuleSpecifier(importDecl)], fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations)]; } - var delDestructure = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullDestructure(t, sourceFile, startToken, undefined, checker, false); }); + var delDestructure = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullDestructure(t, sourceFile, startToken, /*deleted*/ undefined, checker, /*isFixAll*/ false); }); if (delDestructure.length) { return [codefix.createCodeFixAction(fixName, delDestructure, ts.Diagnostics.Remove_destructuring, fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations)]; } - var delVar = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullVariableStatement(t, sourceFile, startToken, undefined); }); + var delVar = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullVariableStatement(t, sourceFile, startToken, /*deleted*/ undefined); }); if (delVar.length) { return [codefix.createCodeFixAction(fixName, delVar, ts.Diagnostics.Remove_variable_statement, fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations)]; } var token = getToken(sourceFile, ts.textSpanEnd(context.span)); var result = []; - var deletion = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteDeclaration(t, sourceFile, token, undefined, checker, false); }); + var deletion = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteDeclaration(t, sourceFile, token, /*deleted*/ undefined, checker, /*isFixAll*/ false); }); if (deletion.length) { result.push(codefix.createCodeFixAction(fixName, deletion, [ts.Diagnostics.Remove_declaration_for_Colon_0, token.getText(sourceFile)], fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations)); } @@ -87483,11 +104562,12 @@ var ts; }, fixIds: [fixIdPrefix, fixIdDelete], getAllCodeActions: function (context) { + // Track a set of deleted nodes that may be ancestors of other marked for deletion -- only delete the ancestors. var deleted = new ts.NodeSet(); var sourceFile = context.sourceFile, program = context.program; var checker = program.getTypeChecker(); return codefix.codeFixAll(context, errorCodes, function (changes, diag) { - var startToken = ts.getTokenAtPosition(sourceFile, diag.start, false); + var startToken = ts.getTokenAtPosition(sourceFile, diag.start, /*includeJsDocComment*/ false); var token = ts.findPrecedingToken(ts.textSpanEnd(diag), diag.file); switch (context.fixId) { case fixIdPrefix: @@ -87496,15 +104576,16 @@ var ts; } break; case fixIdDelete: + // Ignore if this range was already deleted. if (deleted.some(function (d) { return ts.rangeContainsPosition(d, diag.start); })) break; var importDecl = tryGetFullImport(startToken); if (importDecl) { changes.deleteNode(sourceFile, importDecl); } - else if (!tryDeleteFullDestructure(changes, sourceFile, startToken, deleted, checker, true) && + else if (!tryDeleteFullDestructure(changes, sourceFile, startToken, deleted, checker, /*isFixAll*/ true) && !tryDeleteFullVariableStatement(changes, sourceFile, startToken, deleted)) { - tryDeleteDeclaration(changes, sourceFile, token, deleted, checker, true); + tryDeleteDeclaration(changes, sourceFile, token, deleted, checker, /*isFixAll*/ true); } break; default: @@ -87513,25 +104594,26 @@ var ts; }); }, }); + // Sometimes the diagnostic span is an entire ImportDeclaration, so we should remove the whole thing. function tryGetFullImport(startToken) { - return startToken.kind === 91 ? ts.tryCast(startToken.parent, ts.isImportDeclaration) : undefined; + return startToken.kind === 91 /* ImportKeyword */ ? ts.tryCast(startToken.parent, ts.isImportDeclaration) : undefined; } function tryDeleteFullDestructure(changes, sourceFile, startToken, deletedAncestors, checker, isFixAll) { - if (startToken.kind !== 17 || !ts.isObjectBindingPattern(startToken.parent)) + if (startToken.kind !== 17 /* OpenBraceToken */ || !ts.isObjectBindingPattern(startToken.parent)) return false; var decl = ts.cast(startToken.parent, ts.isObjectBindingPattern).parent; switch (decl.kind) { - case 232: + case 232 /* VariableDeclaration */: tryDeleteVariableDeclaration(changes, sourceFile, decl, deletedAncestors); break; - case 149: + case 149 /* Parameter */: if (!mayDeleteParameter(decl, checker, isFixAll)) break; if (deletedAncestors) deletedAncestors.add(decl); changes.deleteNodeInList(sourceFile, decl); break; - case 182: + case 182 /* BindingElement */: if (deletedAncestors) deletedAncestors.add(decl); changes.deleteNode(sourceFile, decl); @@ -87546,29 +104628,31 @@ var ts; if (declarationList && declarationList.getChildren(sourceFile)[0] === startToken) { if (deletedAncestors) deletedAncestors.add(declarationList); - changes.deleteNode(sourceFile, declarationList.parent.kind === 214 ? declarationList.parent : declarationList); + changes.deleteNode(sourceFile, declarationList.parent.kind === 214 /* VariableStatement */ ? declarationList.parent : declarationList); return true; } return false; } function getToken(sourceFile, pos) { - var token = ts.findPrecedingToken(pos, sourceFile, undefined, true); - return token.kind === 22 ? ts.findPrecedingToken(pos - 1, sourceFile) : token; + var token = ts.findPrecedingToken(pos, sourceFile, /*startNode*/ undefined, /*includeJsDoc*/ true); + // this handles var ["computed"] = 12; + return token.kind === 22 /* CloseBracketToken */ ? ts.findPrecedingToken(pos - 1, sourceFile) : token; } function tryPrefixDeclaration(changes, errorCode, sourceFile, token) { + // Don't offer to prefix a property. if (errorCode !== ts.Diagnostics.Property_0_is_declared_but_its_value_is_never_read.code && ts.isIdentifier(token) && canPrefix(token)) { changes.replaceNode(sourceFile, token, ts.createIdentifier("_" + token.text)); } } function canPrefix(token) { switch (token.parent.kind) { - case 149: + case 149 /* Parameter */: return true; - case 232: { + case 232 /* VariableDeclaration */: { var varDecl = token.parent; switch (varDecl.parent.parent.kind) { - case 222: - case 221: + case 222 /* ForOfStatement */: + case 221 /* ForInStatement */: return true; } } @@ -87582,9 +104666,9 @@ var ts; } function deleteAssignments(changes, sourceFile, token, checker) { ts.FindAllReferences.Core.eachSymbolReferenceInFile(token, checker, sourceFile, function (ref) { - if (ref.parent.kind === 185) + if (ref.parent.kind === 185 /* PropertyAccessExpression */) ref = ref.parent; - if (ref.parent.kind === 200 && ref.parent.parent.kind === 216) { + if (ref.parent.kind === 200 /* BinaryExpression */ && ref.parent.parent.kind === 216 /* ExpressionStatement */) { changes.deleteNode(sourceFile, ref.parent.parent); } }); @@ -87592,29 +104676,37 @@ var ts; function tryDeleteDeclarationWorker(changes, sourceFile, token, deletedAncestors, checker, isFixAll) { var parent = token.parent; switch (parent.kind) { - case 232: + case 232 /* VariableDeclaration */: tryDeleteVariableDeclaration(changes, sourceFile, parent, deletedAncestors); break; - case 148: + case 148 /* TypeParameter */: var typeParameters = ts.getEffectiveTypeParameterDeclarations(parent.parent); if (typeParameters.length === 1) { var _a = ts.cast(typeParameters, ts.isNodeArray), pos = _a.pos, end = _a.end; - var previousToken = ts.getTokenAtPosition(sourceFile, pos - 1, false); - var nextToken = ts.getTokenAtPosition(sourceFile, end, false); - ts.Debug.assert(previousToken.kind === 27); - ts.Debug.assert(nextToken.kind === 29); + var previousToken = ts.getTokenAtPosition(sourceFile, pos - 1, /*includeJsDocComment*/ false); + var nextToken = ts.getTokenAtPosition(sourceFile, end, /*includeJsDocComment*/ false); + ts.Debug.assert(previousToken.kind === 27 /* LessThanToken */); + ts.Debug.assert(nextToken.kind === 29 /* GreaterThanToken */); changes.deleteNodeRange(sourceFile, previousToken, nextToken); } else { changes.deleteNodeInList(sourceFile, parent); } break; - case 149: + case 149 /* Parameter */: if (!mayDeleteParameter(parent, checker, isFixAll)) break; var oldFunction = parent.parent; if (ts.isArrowFunction(oldFunction) && oldFunction.parameters.length === 1) { - var newFunction = ts.updateArrowFunction(oldFunction, oldFunction.modifiers, oldFunction.typeParameters, undefined, oldFunction.type, oldFunction.equalsGreaterThanToken, oldFunction.body); + // Lambdas with exactly one parameter are special because, after removal, there + // must be an empty parameter list (i.e. `()`) and this won't necessarily be the + // case if the parameter is simply removed (e.g. in `x => 1`). + var newFunction = ts.updateArrowFunction(oldFunction, oldFunction.modifiers, oldFunction.typeParameters, + /*parameters*/ undefined, // TODO: GH#18217 + oldFunction.type, oldFunction.equalsGreaterThanToken, oldFunction.body); + // Drop leading and trailing trivia of the new function because we're only going + // to replace the span (vs the full span) of the old function - the old leading + // and trailing trivia will remain. ts.suppressLeadingAndTrailingTrivia(newFunction); changes.replaceNode(sourceFile, oldFunction, newFunction); } @@ -87622,9 +104714,9 @@ var ts; changes.deleteNodeInList(sourceFile, parent); } break; - case 182: { + case 182 /* BindingElement */: { var pattern = parent.parent; - var preserveComma = pattern.kind === 181 && parent !== ts.last(pattern.elements); + var preserveComma = pattern.kind === 181 /* ArrayBindingPattern */ && parent !== ts.last(pattern.elements); if (preserveComma) { changes.deleteNode(sourceFile, parent); } @@ -87633,29 +104725,33 @@ var ts; } break; } - case 243: - var importEquals = ts.getAncestor(token, 243); + // handle case where 'import a = A;' + case 243 /* ImportEqualsDeclaration */: + var importEquals = ts.getAncestor(token, 243 /* ImportEqualsDeclaration */); changes.deleteNode(sourceFile, importEquals); break; - case 248: + case 248 /* ImportSpecifier */: var namedImports = parent.parent; if (namedImports.elements.length === 1) { tryDeleteNamedImportBinding(changes, sourceFile, namedImports); } else { + // delete import specifier changes.deleteNodeInList(sourceFile, parent); } break; - case 245: + case 245 /* ImportClause */: // this covers both 'import |d|' and 'import |d,| *' var importClause = parent; - if (!importClause.namedBindings) { - changes.deleteNode(sourceFile, ts.getAncestor(importClause, 244)); + if (!importClause.namedBindings) { // |import d from './file'| + changes.deleteNode(sourceFile, ts.getAncestor(importClause, 244 /* ImportDeclaration */)); } else { + // import |d,| * as ns from './file' var start = importClause.name.getStart(sourceFile); - var nextToken = ts.getTokenAtPosition(sourceFile, importClause.name.end, false); - if (nextToken && nextToken.kind === 26) { - var end = ts.skipTrivia(sourceFile.text, nextToken.end, false, true); + var nextToken = ts.getTokenAtPosition(sourceFile, importClause.name.end, /*includeJsDocComment*/ false); + if (nextToken && nextToken.kind === 26 /* CommaToken */) { + // shift first non-whitespace position after comma to the start position of the node + var end = ts.skipTrivia(sourceFile.text, nextToken.end, /*stopAfterLineBreaks*/ false, /*stopAtComments*/ true); changes.deleteRange(sourceFile, { pos: start, end: end }); } else { @@ -87663,7 +104759,7 @@ var ts; } } break; - case 246: + case 246 /* NamespaceImport */: tryDeleteNamedImportBinding(changes, sourceFile, parent); break; default: @@ -87682,19 +104778,26 @@ var ts; } function tryDeleteNamedImportBinding(changes, sourceFile, namedBindings) { if (namedBindings.parent.name) { - var previousToken = ts.getTokenAtPosition(sourceFile, namedBindings.pos - 1, false); - if (previousToken && previousToken.kind === 26) { + // Delete named imports while preserving the default import + // import d|, * as ns| from './file' + // import d|, { a }| from './file' + var previousToken = ts.getTokenAtPosition(sourceFile, namedBindings.pos - 1, /*includeJsDocComment*/ false); + if (previousToken && previousToken.kind === 26 /* CommaToken */) { changes.deleteRange(sourceFile, { pos: previousToken.getStart(), end: namedBindings.end }); } } else { - var importDecl = ts.getAncestor(namedBindings, 244); + // Delete the entire import declaration + // |import * as ns from './file'| + // |import { a } from './file'| + var importDecl = ts.getAncestor(namedBindings, 244 /* ImportDeclaration */); changes.deleteNode(sourceFile, importDecl); } } + // token.parent is a variableDeclaration function tryDeleteVariableDeclaration(changes, sourceFile, varDecl, deletedAncestors) { switch (varDecl.parent.parent.kind) { - case 220: { + case 220 /* ForStatement */: { var forStatement = varDecl.parent.parent; var forInitializer = forStatement.initializer; if (forInitializer.declarations.length === 1) { @@ -87709,16 +104812,16 @@ var ts; } break; } - case 222: + case 222 /* ForOfStatement */: var forOfStatement = varDecl.parent.parent; - ts.Debug.assert(forOfStatement.initializer.kind === 233); + ts.Debug.assert(forOfStatement.initializer.kind === 233 /* VariableDeclarationList */); var forOfInitializer = forOfStatement.initializer; if (deletedAncestors) deletedAncestors.add(forOfInitializer.declarations[0]); changes.replaceNode(sourceFile, forOfInitializer.declarations[0], ts.createObjectLiteral()); break; - case 221: - case 230: + case 221 /* ForInStatement */: + case 230 /* TryStatement */: break; default: var variableStatement = varDecl.parent.parent; @@ -87737,22 +104840,26 @@ var ts; function mayDeleteParameter(p, checker, isFixAll) { var parent = p.parent; switch (parent.kind) { - case 154: + case 154 /* MethodDeclaration */: + // Don't remove a parameter if this overrides something var symbol = checker.getSymbolAtLocation(parent.name); if (ts.isMemberSymbolInBaseType(symbol, checker)) return false; - case 155: - case 234: - case 192: - case 193: { + // falls through + case 155 /* Constructor */: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: { + // Can't remove a non-last parameter. Can remove a parameter in code-fix-all if future parameters are also unused. var parameters = parent.parameters; var index = parameters.indexOf(p); ts.Debug.assert(index !== -1); return isFixAll - ? parameters.slice(index + 1).every(function (p) { return p.name.kind === 71 && !p.symbol.isReferenced; }) + ? parameters.slice(index + 1).every(function (p) { return p.name.kind === 71 /* Identifier */ && !p.symbol.isReferenced; }) : index === parameters.length - 1; } - case 157: + case 157 /* SetAccessor */: + // Setter must have a parameter return false; default: return ts.Debug.failBadSyntaxKind(parent); @@ -87760,6 +104867,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87776,12 +104884,12 @@ var ts; getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { return doChange(changes, diag.file, diag.start); }); }, }); function doChange(changes, sourceFile, start) { - var token = ts.getTokenAtPosition(sourceFile, start, false); + var token = ts.getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false); var statement = ts.findAncestor(token, ts.isStatement); ts.Debug.assert(statement.getStart(sourceFile) === token.getStart(sourceFile)); var container = (ts.isBlock(statement.parent) ? statement.parent : statement).parent; switch (container.kind) { - case 217: + case 217 /* IfStatement */: if (container.elseStatement) { if (ts.isBlock(statement.parent)) { changes.deleteNodeRange(sourceFile, ts.first(statement.parent.statements), ts.last(statement.parent.statements)); @@ -87791,8 +104899,9 @@ var ts; } break; } - case 219: - case 220: + // falls through + case 219 /* WhileStatement */: + case 220 /* ForStatement */: changes.deleteNode(sourceFile, container); break; default: @@ -87805,18 +104914,20 @@ var ts; } } function shouldRemove(s) { + // Don't remove statements that can validly be used before they appear. return !ts.isFunctionDeclaration(s) && !isPurelyTypeDeclaration(s) && - !(ts.isVariableStatement(s) && !(ts.getCombinedNodeFlags(s) & (1 | 2)) && s.declarationList.declarations.some(function (d) { return !d.initializer; })); + // `var x;` may declare a variable used above + !(ts.isVariableStatement(s) && !(ts.getCombinedNodeFlags(s) & (1 /* Let */ | 2 /* Const */)) && s.declarationList.declarations.some(function (d) { return !d.initializer; })); } function isPurelyTypeDeclaration(s) { switch (s.kind) { - case 236: - case 237: + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: return true; - case 239: - return ts.getModuleInstanceState(s) !== 1; - case 238: - return ts.hasModifier(s, 2048); + case 239 /* ModuleDeclaration */: + return ts.getModuleInstanceState(s) !== 1 /* Instantiated */; + case 238 /* EnumDeclaration */: + return ts.hasModifier(s, 2048 /* Const */); default: return false; } @@ -87826,11 +104937,13 @@ var ts; ts.Debug.assert(index !== -1); return arr.slice(index); } + // Calls 'cb' with the start and end of each range where 'pred' is true. function split(arr, pred, cb) { ts.getRangesWhere(arr, pred, function (start, afterEnd) { return cb(arr[start], arr[afterEnd - 1]); }); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87847,16 +104960,18 @@ var ts; getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { return doChange(changes, diag.file, diag.start); }); }, }); function doChange(changes, sourceFile, start) { - var token = ts.getTokenAtPosition(sourceFile, start, false); + var token = ts.getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false); var labeledStatement = ts.cast(token.parent, ts.isLabeledStatement); var pos = token.getStart(sourceFile); var statementPos = labeledStatement.statement.getStart(sourceFile); + // If label is on a separate line, just delete the rest of that line, but not the indentation of the labeled statement. var end = ts.positionsAreOnSameLine(pos, statementPos, sourceFile) ? statementPos - : ts.skipTrivia(sourceFile.text, ts.findChildOfKind(labeledStatement, 56, sourceFile).end, true); + : ts.skipTrivia(sourceFile.text, ts.findChildOfKind(labeledStatement, 56 /* ColonToken */, sourceFile).end, /*stopAfterLineBreak*/ true); changes.deleteRange(sourceFile, { pos: pos, end: end }); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87875,8 +104990,10 @@ var ts; var typeNode = info.typeNode, type = info.type; var original = typeNode.getText(sourceFile); var actions = [fix(type, fixIdPlain, ts.Diagnostics.Change_all_jsdoc_style_types_to_TypeScript)]; - if (typeNode.kind === 281) { - actions.push(fix(checker.getNullableType(type, 8192), fixIdNullable, ts.Diagnostics.Change_all_jsdoc_style_types_to_TypeScript_and_add_undefined_to_nullable_types)); + if (typeNode.kind === 281 /* JSDocNullableType */) { + // for nullable types, suggest the flow-compatible `T | null | undefined` + // in addition to the jsdoc/closure-compatible `T | null` + actions.push(fix(checker.getNullableType(type, 8192 /* Undefined */), fixIdNullable, ts.Diagnostics.Change_all_jsdoc_style_types_to_TypeScript_and_add_undefined_to_nullable_types)); } return actions; function fix(type, fixId, fixAllDescription) { @@ -87893,37 +105010,39 @@ var ts; if (!info) return; var typeNode = info.typeNode, type = info.type; - var fixedType = typeNode.kind === 281 && fixId === fixIdNullable ? checker.getNullableType(type, 8192) : type; + var fixedType = typeNode.kind === 281 /* JSDocNullableType */ && fixId === fixIdNullable ? checker.getNullableType(type, 8192 /* Undefined */) : type; doChange(changes, sourceFile, typeNode, fixedType, checker); }); } }); function doChange(changes, sourceFile, oldTypeNode, newType, checker) { - changes.replaceNode(sourceFile, oldTypeNode, checker.typeToTypeNode(newType, oldTypeNode)); + changes.replaceNode(sourceFile, oldTypeNode, checker.typeToTypeNode(newType, /*enclosingDeclaration*/ oldTypeNode)); // TODO: GH#18217 } function getInfo(sourceFile, pos, checker) { - var decl = ts.findAncestor(ts.getTokenAtPosition(sourceFile, pos, false), isTypeContainer); + var decl = ts.findAncestor(ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false), isTypeContainer); var typeNode = decl && decl.type; return typeNode && { typeNode: typeNode, type: checker.getTypeFromTypeNode(typeNode) }; } function isTypeContainer(node) { + // NOTE: Some locations are not handled yet: + // MappedTypeNode.typeParameters and SignatureDeclaration.typeParameters, as well as CallExpression.typeArguments switch (node.kind) { - case 208: - case 158: - case 159: - case 234: - case 156: - case 160: - case 177: - case 154: - case 153: - case 149: - case 152: - case 151: - case 157: - case 237: - case 190: - case 232: + case 208 /* AsExpression */: + case 158 /* CallSignature */: + case 159 /* ConstructSignature */: + case 234 /* FunctionDeclaration */: + case 156 /* GetAccessor */: + case 160 /* IndexSignature */: + case 177 /* MappedType */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 149 /* Parameter */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: + case 157 /* SetAccessor */: + case 237 /* TypeAliasDeclaration */: + case 190 /* TypeAssertionExpression */: + case 232 /* VariableDeclaration */: return true; default: return false; @@ -87931,6 +105050,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -87969,22 +105089,22 @@ var ts; } } function getNodes(sourceFile, start) { - var token = ts.getTokenAtPosition(sourceFile, start, false); + var token = ts.getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false); var containingFunction = ts.getContainingFunction(token); if (!containingFunction) { return; } var insertBefore; switch (containingFunction.kind) { - case 154: + case 154 /* MethodDeclaration */: insertBefore = containingFunction.name; break; - case 234: - case 192: - insertBefore = ts.findChildOfKind(containingFunction, 89, sourceFile); + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + insertBefore = ts.findChildOfKind(containingFunction, 89 /* FunctionKeyword */, sourceFile); break; - case 193: - insertBefore = ts.findChildOfKind(containingFunction, 19, sourceFile) || ts.first(containingFunction.parameters); + case 193 /* ArrowFunction */: + insertBefore = ts.findChildOfKind(containingFunction, 19 /* OpenParenToken */, sourceFile) || ts.first(containingFunction.parameters); break; default: return; @@ -87998,14 +105118,15 @@ var ts; var insertBefore = _a.insertBefore, returnType = _a.returnType; if (returnType) { var entityName = ts.getEntityNameFromTypeNode(returnType); - if (!entityName || entityName.kind !== 71 || entityName.text !== "Promise") { + if (!entityName || entityName.kind !== 71 /* Identifier */ || entityName.text !== "Promise") { changes.replaceNode(sourceFile, returnType, ts.createTypeReferenceNode("Promise", ts.createNodeArray([returnType]))); } } - changes.insertModifierBefore(sourceFile, 120, insertBefore); + changes.insertModifierBefore(sourceFile, 120 /* AsyncKeyword */, insertBefore); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -88024,6 +105145,7 @@ var ts; return undefined; } var fixes = [ + // fixId unnecessary because adding `// @ts-nocheck` even once will ignore every error in the file. codefix.createCodeFixActionNoFixId(fixName, [codefix.createFileTextChanges(sourceFile.fileName, [ ts.createTextChange(sourceFile.checkJsDirective ? ts.createTextSpanFromBounds(sourceFile.checkJsDirective.pos, sourceFile.checkJsDirective.end) @@ -88047,16 +105169,24 @@ var ts; }); function makeChange(changes, sourceFile, position, seenLines) { var lineNumber = ts.getLineAndCharacterOfPosition(sourceFile, position).line; + // Only need to add `// @ts-ignore` for a line once. if (!seenLines || ts.addToSeen(seenLines, lineNumber)) { changes.insertCommentBeforeLine(sourceFile, lineNumber, position, " @ts-ignore"); } } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; (function (codefix) { + /** + * Finds members of the resolved type that are missing in the class pointed to by class decl + * and generates source code for the missing members. + * @param possiblyMissingSymbols The collection of symbols to filter and then get insertions for. + * @returns Empty string iff there are no member insertions. + */ function createMissingMemberNodes(classDeclaration, possiblyMissingSymbols, checker, preferences, out) { var classMembers = classDeclaration.symbol.members; for (var _i = 0, possiblyMissingSymbols_1 = possiblyMissingSymbols; _i < possiblyMissingSymbols_1.length; _i++) { @@ -88067,28 +105197,40 @@ var ts; } } codefix.createMissingMemberNodes = createMissingMemberNodes; + /** + * @returns Empty string iff there we can't figure out a representation for `symbol` in `enclosingDeclaration`. + */ function addNewNodeForMemberSymbol(symbol, enclosingDeclaration, checker, preferences, out) { var declarations = symbol.getDeclarations(); if (!(declarations && declarations.length)) { return undefined; } var declaration = declarations[0]; - var name = ts.getSynthesizedDeepClone(ts.getNameOfDeclaration(declaration), false); + var name = ts.getSynthesizedDeepClone(ts.getNameOfDeclaration(declaration), /*includeTrivia*/ false); var visibilityModifier = createVisibilityModifier(ts.getModifierFlags(declaration)); var modifiers = visibilityModifier ? ts.createNodeArray([visibilityModifier]) : undefined; var type = checker.getWidenedType(checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration)); - var optional = !!(symbol.flags & 16777216); + var optional = !!(symbol.flags & 16777216 /* Optional */); switch (declaration.kind) { - case 156: - case 157: - case 151: - case 152: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 151 /* PropertySignature */: + case 152 /* PropertyDeclaration */: var typeNode = checker.typeToTypeNode(type, enclosingDeclaration); - out(ts.createProperty(undefined, modifiers, name, optional ? ts.createToken(55) : undefined, typeNode, undefined)); + out(ts.createProperty( + /*decorators*/ undefined, modifiers, name, optional ? ts.createToken(55 /* QuestionToken */) : undefined, typeNode, + /*initializer*/ undefined)); break; - case 153: - case 154: - var signatures = checker.getSignaturesOfType(type, 0); + case 153 /* MethodSignature */: + case 154 /* MethodDeclaration */: + // The signature for the implementation appears as an entry in `signatures` iff + // there is only one signature. + // If there are overloads and an implementation signature, it appears as an + // extra declaration that isn't a signature for `type`. + // If there is more than one overload but no implementation signature + // (eg: an abstract method or interface declaration), there is a 1-1 + // correspondence of declarations and signatures. + var signatures = checker.getSignaturesOfType(type, 0 /* Call */); if (!ts.some(signatures)) { break; } @@ -88100,7 +105242,8 @@ var ts; } for (var _i = 0, signatures_8 = signatures; _i < signatures_8.length; _i++) { var signature = signatures_8[_i]; - outputMethod(signature, ts.getSynthesizedDeepClones(modifiers, false), ts.getSynthesizedDeepClone(name, false)); + // Need to ensure nodes are fresh each time so they can have different positions. + outputMethod(signature, ts.getSynthesizedDeepClones(modifiers, /*includeTrivia*/ false), ts.getSynthesizedDeepClone(name, /*includeTrivia*/ false)); } if (declarations.length > signatures.length) { var signature = checker.getSignatureFromDeclaration(declarations[declarations.length - 1]); @@ -88119,33 +105262,51 @@ var ts; } } function signatureToMethodDeclaration(checker, signature, enclosingDeclaration, modifiers, name, optional, body) { - var signatureDeclaration = checker.signatureToSignatureDeclaration(signature, 154, enclosingDeclaration, 256); + var signatureDeclaration = checker.signatureToSignatureDeclaration(signature, 154 /* MethodDeclaration */, enclosingDeclaration, 256 /* SuppressAnyReturnType */); if (!signatureDeclaration) { return undefined; } signatureDeclaration.decorators = undefined; signatureDeclaration.modifiers = modifiers; signatureDeclaration.name = name; - signatureDeclaration.questionToken = optional ? ts.createToken(55) : undefined; + signatureDeclaration.questionToken = optional ? ts.createToken(55 /* QuestionToken */) : undefined; signatureDeclaration.body = body; return signatureDeclaration; } function createMethodFromCallExpression(_a, methodName, inJs, makeStatic, preferences) { var typeArguments = _a.typeArguments, args = _a.arguments, parent = _a.parent; - return ts.createMethod(undefined, makeStatic ? [ts.createToken(115)] : undefined, ts.isYieldExpression(parent) ? ts.createToken(39) : undefined, methodName, undefined, inJs ? undefined : ts.map(typeArguments, function (_, i) { - return ts.createTypeParameterDeclaration(84 + typeArguments.length - 1 <= 90 ? String.fromCharCode(84 + i) : "T" + i); - }), createDummyParameters(args.length, undefined, undefined, inJs), inJs ? undefined : ts.createKeywordTypeNode(119), createStubbedMethodBody(preferences)); + return ts.createMethod( + /*decorators*/ undefined, + /*modifiers*/ makeStatic ? [ts.createToken(115 /* StaticKeyword */)] : undefined, + /*asteriskToken*/ ts.isYieldExpression(parent) ? ts.createToken(39 /* AsteriskToken */) : undefined, methodName, + /*questionToken*/ undefined, + /*typeParameters*/ inJs ? undefined : ts.map(typeArguments, function (_, i) { + return ts.createTypeParameterDeclaration(84 /* T */ + typeArguments.length - 1 <= 90 /* Z */ ? String.fromCharCode(84 /* T */ + i) : "T" + i); + }), + /*parameters*/ createDummyParameters(args.length, /*names*/ undefined, /*minArgumentCount*/ undefined, inJs), + /*type*/ inJs ? undefined : ts.createKeywordTypeNode(119 /* AnyKeyword */), createStubbedMethodBody(preferences)); } codefix.createMethodFromCallExpression = createMethodFromCallExpression; function createDummyParameters(argCount, names, minArgumentCount, inJs) { var parameters = []; for (var i = 0; i < argCount; i++) { - var newParameter = ts.createParameter(undefined, undefined, undefined, names && names[i] || "arg" + i, minArgumentCount !== undefined && i >= minArgumentCount ? ts.createToken(55) : undefined, inJs ? undefined : ts.createKeywordTypeNode(119), undefined); + var newParameter = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + /*name*/ names && names[i] || "arg" + i, + /*questionToken*/ minArgumentCount !== undefined && i >= minArgumentCount ? ts.createToken(55 /* QuestionToken */) : undefined, + /*type*/ inJs ? undefined : ts.createKeywordTypeNode(119 /* AnyKeyword */), + /*initializer*/ undefined); parameters.push(newParameter); } return parameters; } function createMethodImplementingSignatures(signatures, name, optional, modifiers, preferences) { + /** This is *a* signature with the maximal number of arguments, + * such that if there is a "maximal" signature without rest arguments, + * this is one of them. + */ var maxArgsSignature = signatures[0]; var minArgumentCount = signatures[0].minArgumentCount; var someSigHasRestParameter = false; @@ -88161,44 +105322,61 @@ var ts; } var maxNonRestArgs = maxArgsSignature.parameters.length - (maxArgsSignature.hasRestParameter ? 1 : 0); var maxArgsParameterSymbolNames = maxArgsSignature.parameters.map(function (symbol) { return symbol.name; }); - var parameters = createDummyParameters(maxNonRestArgs, maxArgsParameterSymbolNames, minArgumentCount, false); + var parameters = createDummyParameters(maxNonRestArgs, maxArgsParameterSymbolNames, minArgumentCount, /*inJs*/ false); if (someSigHasRestParameter) { - var anyArrayType = ts.createArrayTypeNode(ts.createKeywordTypeNode(119)); - var restParameter = ts.createParameter(undefined, undefined, ts.createToken(24), maxArgsParameterSymbolNames[maxNonRestArgs] || "rest", maxNonRestArgs >= minArgumentCount ? ts.createToken(55) : undefined, anyArrayType, undefined); + var anyArrayType = ts.createArrayTypeNode(ts.createKeywordTypeNode(119 /* AnyKeyword */)); + var restParameter = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, ts.createToken(24 /* DotDotDotToken */), maxArgsParameterSymbolNames[maxNonRestArgs] || "rest", + /*questionToken*/ maxNonRestArgs >= minArgumentCount ? ts.createToken(55 /* QuestionToken */) : undefined, anyArrayType, + /*initializer*/ undefined); parameters.push(restParameter); } - return createStubbedMethod(modifiers, name, optional, undefined, parameters, undefined, preferences); + return createStubbedMethod(modifiers, name, optional, + /*typeParameters*/ undefined, parameters, + /*returnType*/ undefined, preferences); } function createStubbedMethod(modifiers, name, optional, typeParameters, parameters, returnType, preferences) { - return ts.createMethod(undefined, modifiers, undefined, name, optional ? ts.createToken(55) : undefined, typeParameters, parameters, returnType, createStubbedMethodBody(preferences)); + return ts.createMethod( + /*decorators*/ undefined, modifiers, + /*asteriskToken*/ undefined, name, optional ? ts.createToken(55 /* QuestionToken */) : undefined, typeParameters, parameters, returnType, createStubbedMethodBody(preferences)); } function createStubbedMethodBody(preferences) { - return ts.createBlock([ts.createThrow(ts.createNew(ts.createIdentifier("Error"), undefined, [ts.createLiteral("Method not implemented.", preferences.quotePreference === "single")]))], true); + return ts.createBlock([ts.createThrow(ts.createNew(ts.createIdentifier("Error"), + /*typeArguments*/ undefined, [ts.createLiteral("Method not implemented.", /*isSingleQuote*/ preferences.quotePreference === "single")]))], + /*multiline*/ true); } function createVisibilityModifier(flags) { - if (flags & 4) { - return ts.createToken(114); + if (flags & 4 /* Public */) { + return ts.createToken(114 /* PublicKeyword */); } - else if (flags & 16) { - return ts.createToken(113); + else if (flags & 16 /* Protected */) { + return ts.createToken(113 /* ProtectedKeyword */); } return undefined; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; (function (codefix) { var fixId = "inferFromUsage"; var errorCodes = [ + // Variable declarations ts.Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code, + // Variable uses ts.Diagnostics.Variable_0_implicitly_has_an_1_type.code, + // Parameter declarations ts.Diagnostics.Parameter_0_implicitly_has_an_1_type.code, ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code, + // Get Accessor declarations ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation.code, ts.Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type.code, + // Set Accessor declarations ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation.code, + // Property declarations ts.Diagnostics.Member_0_implicitly_has_an_1_type.code, ]; codefix.registerCodeFix({ @@ -88206,11 +105384,11 @@ var ts; getCodeActions: function (context) { var sourceFile = context.sourceFile, program = context.program, start = context.span.start, errorCode = context.errorCode, cancellationToken = context.cancellationToken; if (ts.isSourceFileJavaScript(sourceFile)) { - return undefined; + return undefined; // TODO: GH#20113 } - var token = ts.getTokenAtPosition(sourceFile, start, false); + var token = ts.getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false); var declaration; - var changes = ts.textChanges.ChangeTracker.with(context, function (changes) { declaration = doChange(changes, sourceFile, token, errorCode, program, cancellationToken, ts.returnTrue); }); + var changes = ts.textChanges.ChangeTracker.with(context, function (changes) { declaration = doChange(changes, sourceFile, token, errorCode, program, cancellationToken, /*markSeenseen*/ ts.returnTrue); }); return changes.length === 0 ? undefined : [codefix.createCodeFixAction(fixId, changes, [getDiagnostic(errorCode, token), ts.getNameOfDeclaration(declaration).getText(sourceFile)], fixId, ts.Diagnostics.Infer_all_types_from_usage)]; }, @@ -88219,14 +105397,14 @@ var ts; var sourceFile = context.sourceFile, program = context.program, cancellationToken = context.cancellationToken; var markSeen = ts.nodeSeenTracker(); return codefix.codeFixAll(context, errorCodes, function (changes, err) { - doChange(changes, sourceFile, ts.getTokenAtPosition(err.file, err.start, false), err.code, program, cancellationToken, markSeen); + doChange(changes, sourceFile, ts.getTokenAtPosition(err.file, err.start, /*includeJsDocComment*/ false), err.code, program, cancellationToken, markSeen); }); }, }); function getDiagnostic(errorCode, token) { switch (errorCode) { case ts.Diagnostics.Parameter_0_implicitly_has_an_1_type.code: - return ts.isSetAccessor(ts.getContainingFunction(token)) ? ts.Diagnostics.Infer_type_of_0_from_usage : ts.Diagnostics.Infer_parameter_types_from_usage; + return ts.isSetAccessor(ts.getContainingFunction(token)) ? ts.Diagnostics.Infer_type_of_0_from_usage : ts.Diagnostics.Infer_parameter_types_from_usage; // TODO: GH#18217 case ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code: return ts.Diagnostics.Infer_parameter_types_from_usage; default: @@ -88234,14 +105412,15 @@ var ts; } } function doChange(changes, sourceFile, token, errorCode, program, cancellationToken, markSeen) { - if (!ts.isParameterPropertyModifier(token.kind) && token.kind !== 71 && token.kind !== 24) { + if (!ts.isParameterPropertyModifier(token.kind) && token.kind !== 71 /* Identifier */ && token.kind !== 24 /* DotDotDotToken */) { return undefined; } var parent = token.parent; switch (errorCode) { + // Variable and Property declarations case ts.Diagnostics.Member_0_implicitly_has_an_1_type.code: case ts.Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code: - if ((ts.isVariableDeclaration(parent) && markSeen(parent)) || ts.isPropertyDeclaration(parent) || ts.isPropertySignature(parent)) { + if ((ts.isVariableDeclaration(parent) && markSeen(parent)) || ts.isPropertyDeclaration(parent) || ts.isPropertySignature(parent)) { // handle bad location annotateVariableDeclaration(changes, sourceFile, parent, program, cancellationToken); return parent; } @@ -88260,11 +105439,13 @@ var ts; return undefined; } switch (errorCode) { + // Parameter declarations case ts.Diagnostics.Parameter_0_implicitly_has_an_1_type.code: if (ts.isSetAccessor(containingFunction)) { annotateSetAccessor(changes, sourceFile, containingFunction, program, cancellationToken); return containingFunction; } + // falls through case ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code: if (markSeen(containingFunction)) { var param = ts.cast(parent, ts.isParameter); @@ -88272,6 +105453,7 @@ var ts; return param; } return undefined; + // Get Accessor declarations case ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation.code: case ts.Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type.code: if (ts.isGetAccessor(containingFunction) && ts.isIdentifier(containingFunction.name)) { @@ -88279,6 +105461,7 @@ var ts; return containingFunction; } return undefined; + // Set Accessor declarations case ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation.code: if (ts.isSetAccessor(containingFunction)) { annotateSetAccessor(changes, sourceFile, containingFunction, program, cancellationToken); @@ -88296,11 +105479,11 @@ var ts; } function isApplicableFunctionForInference(declaration) { switch (declaration.kind) { - case 234: - case 154: - case 155: + case 234 /* FunctionDeclaration */: + case 154 /* MethodDeclaration */: + case 155 /* Constructor */: return true; - case 192: + case 192 /* FunctionExpression */: return !!declaration.name; } return false; @@ -88311,6 +105494,7 @@ var ts; } var types = inferTypeForParametersFromUsage(containingFunction, sourceFile, program, cancellationToken) || containingFunction.parameters.map(function (p) { return ts.isIdentifier(p.name) ? inferTypeForVariableFromUsage(p.name, program, cancellationToken) : undefined; }); + // We didn't actually find a set of type inference positions matching each parameter position if (!types || containingFunction.parameters.length !== types.length) { return; } @@ -88336,9 +105520,10 @@ var ts; function getTypeNodeIfAccessible(type, enclosingScope, checker) { var typeIsAccessible = true; var notAccessible = function () { typeIsAccessible = false; }; - var res = checker.typeToTypeNode(type, enclosingScope, undefined, { + var res = checker.typeToTypeNode(type, enclosingScope, /*flags*/ undefined, { trackSymbol: function (symbol, declaration, meaning) { - typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, false).accessibility === 0; + // TODO: GH#18217 + typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility === 0 /* Accessible */; }, reportInaccessibleThisError: notAccessible, reportPrivateInBaseOfClassExpression: notAccessible, @@ -88347,6 +105532,7 @@ var ts; return typeIsAccessible ? res : undefined; } function getReferences(token, program, cancellationToken) { + // Position shouldn't matter since token is not a SourceFile. return ts.mapDefined(ts.FindAllReferences.getReferenceEntriesForNode(-1, token, program, program.getSourceFiles(), cancellationToken), function (entry) { return entry.type === "node" ? ts.tryCast(entry.node, ts.isIdentifier) : undefined; }); @@ -88356,13 +105542,13 @@ var ts; } function inferTypeForParametersFromUsage(containingFunction, sourceFile, program, cancellationToken) { switch (containingFunction.kind) { - case 155: - case 192: - case 234: - case 154: - var isConstructor = containingFunction.kind === 155; + case 155 /* Constructor */: + case 192 /* FunctionExpression */: + case 234 /* FunctionDeclaration */: + case 154 /* MethodDeclaration */: + var isConstructor = containingFunction.kind === 155 /* Constructor */; var searchToken = isConstructor ? - ts.findChildOfKind(containingFunction, 123, sourceFile) : + ts.findChildOfKind(containingFunction, 123 /* ConstructorKeyword */, sourceFile) : containingFunction.name; if (searchToken) { return InferFromReference.inferTypeForParametersFromReferences(getReferences(searchToken, program, cancellationToken), containingFunction, program.getTypeChecker(), cancellationToken); @@ -88394,7 +105580,7 @@ var ts; cancellationToken.throwIfCancellationRequested(); inferTypeFromContext(reference, checker, usageContext); } - var isConstructor = declaration.kind === 155; + var isConstructor = declaration.kind === 155 /* Constructor */; var callContexts = isConstructor ? usageContext.constructContexts : usageContext.callContexts; return callContexts && declaration.parameters.map(function (parameter, parameterIndex) { var types = []; @@ -88416,7 +105602,7 @@ var ts; if (!types.length) { return undefined; } - var type = checker.getWidenedType(checker.getUnionType(types, 2)); + var type = checker.getWidenedType(checker.getUnionType(types, 2 /* Subtype */)); return isRest ? checker.createArrayType(type) : type; }); } @@ -88426,21 +105612,21 @@ var ts; node = node.parent; } switch (node.parent.kind) { - case 199: + case 199 /* PostfixUnaryExpression */: usageContext.isNumber = true; break; - case 198: + case 198 /* PrefixUnaryExpression */: inferTypeFromPrefixUnaryExpressionContext(node.parent, usageContext); break; - case 200: + case 200 /* BinaryExpression */: inferTypeFromBinaryExpressionContext(node, node.parent, checker, usageContext); break; - case 266: - case 267: + case 266 /* CaseClause */: + case 267 /* DefaultClause */: inferTypeFromSwitchStatementLabelContext(node.parent, checker, usageContext); break; - case 187: - case 188: + case 187 /* CallExpression */: + case 188 /* NewExpression */: if (node.parent.expression === node) { inferTypeFromCallExpressionContext(node.parent, checker, usageContext); } @@ -88448,21 +105634,22 @@ var ts; inferTypeFromContextualType(node, checker, usageContext); } break; - case 185: + case 185 /* PropertyAccessExpression */: inferTypeFromPropertyAccessExpressionContext(node.parent, checker, usageContext); break; - case 186: + case 186 /* ElementAccessExpression */: inferTypeFromPropertyElementExpressionContext(node.parent, node, checker, usageContext); break; - case 232: { + case 232 /* VariableDeclaration */: { var _a = node.parent, name = _a.name, initializer = _a.initializer; if (node === name) { - if (initializer) { + if (initializer) { // This can happen for `let x = null;` which still has an implicit-any error. addCandidateType(usageContext, checker.getTypeAtLocation(initializer)); } break; } } + // falls through default: return inferTypeFromContextualType(node, checker, usageContext); } @@ -88474,90 +105661,104 @@ var ts; } function inferTypeFromPrefixUnaryExpressionContext(node, usageContext) { switch (node.operator) { - case 43: - case 44: - case 38: - case 52: + case 43 /* PlusPlusToken */: + case 44 /* MinusMinusToken */: + case 38 /* MinusToken */: + case 52 /* TildeToken */: usageContext.isNumber = true; break; - case 37: + case 37 /* PlusToken */: usageContext.isNumberOrString = true; break; + // case SyntaxKind.ExclamationToken: + // no inferences here; } } function inferTypeFromBinaryExpressionContext(node, parent, checker, usageContext) { switch (parent.operatorToken.kind) { - case 40: - case 39: - case 41: - case 42: - case 45: - case 46: - case 47: - case 48: - case 49: - case 50: - case 60: - case 62: - case 61: - case 63: - case 64: - case 68: - case 69: - case 70: - case 65: - case 67: - case 66: - case 38: - case 27: - case 30: - case 29: - case 31: + // ExponentiationOperator + case 40 /* AsteriskAsteriskToken */: + // MultiplicativeOperator + case 39 /* AsteriskToken */: + case 41 /* SlashToken */: + case 42 /* PercentToken */: + // ShiftOperator + case 45 /* LessThanLessThanToken */: + case 46 /* GreaterThanGreaterThanToken */: + case 47 /* GreaterThanGreaterThanGreaterThanToken */: + // BitwiseOperator + case 48 /* AmpersandToken */: + case 49 /* BarToken */: + case 50 /* CaretToken */: + // CompoundAssignmentOperator + case 60 /* MinusEqualsToken */: + case 62 /* AsteriskAsteriskEqualsToken */: + case 61 /* AsteriskEqualsToken */: + case 63 /* SlashEqualsToken */: + case 64 /* PercentEqualsToken */: + case 68 /* AmpersandEqualsToken */: + case 69 /* BarEqualsToken */: + case 70 /* CaretEqualsToken */: + case 65 /* LessThanLessThanEqualsToken */: + case 67 /* GreaterThanGreaterThanGreaterThanEqualsToken */: + case 66 /* GreaterThanGreaterThanEqualsToken */: + // AdditiveOperator + case 38 /* MinusToken */: + // RelationalOperator + case 27 /* LessThanToken */: + case 30 /* LessThanEqualsToken */: + case 29 /* GreaterThanToken */: + case 31 /* GreaterThanEqualsToken */: var operandType = checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left); - if (operandType.flags & 544) { + if (operandType.flags & 544 /* EnumLike */) { addCandidateType(usageContext, operandType); } else { usageContext.isNumber = true; } break; - case 59: - case 37: + case 59 /* PlusEqualsToken */: + case 37 /* PlusToken */: var otherOperandType = checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left); - if (otherOperandType.flags & 544) { + if (otherOperandType.flags & 544 /* EnumLike */) { addCandidateType(usageContext, otherOperandType); } - else if (otherOperandType.flags & 168) { + else if (otherOperandType.flags & 168 /* NumberLike */) { usageContext.isNumber = true; } - else if (otherOperandType.flags & 68) { + else if (otherOperandType.flags & 68 /* StringLike */) { usageContext.isString = true; } else { usageContext.isNumberOrString = true; } break; - case 58: - case 32: - case 34: - case 35: - case 33: + // AssignmentOperators + case 58 /* EqualsToken */: + case 32 /* EqualsEqualsToken */: + case 34 /* EqualsEqualsEqualsToken */: + case 35 /* ExclamationEqualsEqualsToken */: + case 33 /* ExclamationEqualsToken */: addCandidateType(usageContext, checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left)); break; - case 92: + case 92 /* InKeyword */: if (node === parent.left) { usageContext.isString = true; } break; - case 54: + // LogicalOperator + case 54 /* BarBarToken */: if (node === parent.left && - (node.parent.parent.kind === 232 || ts.isAssignmentExpression(node.parent.parent, true))) { + (node.parent.parent.kind === 232 /* VariableDeclaration */ || ts.isAssignmentExpression(node.parent.parent, /*excludeCompoundAssignment*/ true))) { + // var x = x || {}; + // TODO: use getFalsyflagsOfType addCandidateType(usageContext, checker.getTypeAtLocation(parent.right)); } break; - case 53: - case 26: - case 93: + case 53 /* AmpersandAmpersandToken */: + case 26 /* CommaToken */: + case 93 /* InstanceOfKeyword */: + // nothing to infer here break; } } @@ -88576,7 +105777,7 @@ var ts; } } inferTypeFromContext(parent, checker, callContext.returnType); - if (parent.kind === 187) { + if (parent.kind === 187 /* CallExpression */) { (usageContext.callContexts || (usageContext.callContexts = [])).push(callContext); } else { @@ -88601,7 +105802,7 @@ var ts; var indexType = checker.getTypeAtLocation(parent); var indexUsageContext = {}; inferTypeFromContext(parent, checker, indexUsageContext); - if (indexType.flags & 168) { + if (indexType.flags & 168 /* NumberLike */) { usageContext.numberIndexContext = indexUsageContext; } else { @@ -88620,15 +105821,15 @@ var ts; return checker.getStringType(); } else if (usageContext.candidateTypes) { - return checker.getWidenedType(checker.getUnionType(usageContext.candidateTypes.map(function (t) { return checker.getBaseTypeOfLiteralType(t); }), 2)); + return checker.getWidenedType(checker.getUnionType(usageContext.candidateTypes.map(function (t) { return checker.getBaseTypeOfLiteralType(t); }), 2 /* Subtype */)); } else if (usageContext.properties && hasCallContext(usageContext.properties.get("then"))) { - var paramType = getParameterTypeFromCallContexts(0, usageContext.properties.get("then").callContexts, false, checker); + var paramType = getParameterTypeFromCallContexts(0, usageContext.properties.get("then").callContexts, /*isRestParameter*/ false, checker); // TODO: GH#18217 var types = paramType.getCallSignatures().map(function (c) { return c.getReturnType(); }); - return checker.createPromiseType(types.length ? checker.getUnionType(types, 2) : checker.getAnyType()); + return checker.createPromiseType(types.length ? checker.getUnionType(types, 2 /* Subtype */) : checker.getAnyType()); } else if (usageContext.properties && hasCallContext(usageContext.properties.get("push"))) { - return checker.createArrayType(getParameterTypeFromCallContexts(0, usageContext.properties.get("push").callContexts, false, checker)); + return checker.createArrayType(getParameterTypeFromCallContexts(0, usageContext.properties.get("push").callContexts, /*isRestParameter*/ false, checker)); } else if (usageContext.properties || usageContext.callContexts || usageContext.constructContexts || usageContext.numberIndexContext || usageContext.stringIndexContext) { var members_6 = ts.createUnderscoreEscapedMap(); @@ -88638,7 +105839,7 @@ var ts; var numberIndexInfo = void 0; if (usageContext.properties) { usageContext.properties.forEach(function (context, name) { - var symbol = checker.createSymbol(4, name); + var symbol = checker.createSymbol(4 /* Property */, name); symbol.type = getTypeFromUsageContext(context, checker) || checker.getAnyType(); members_6.set(name, symbol); }); @@ -88656,12 +105857,12 @@ var ts; } } if (usageContext.numberIndexContext) { - numberIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.numberIndexContext, checker), false); + numberIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.numberIndexContext, checker), /*isReadonly*/ false); // TODO: GH#18217 } if (usageContext.stringIndexContext) { - stringIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.stringIndexContext, checker), false); + stringIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.stringIndexContext, checker), /*isReadonly*/ false); } - return checker.createAnonymousType(undefined, members_6, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); + return checker.createAnonymousType(/*symbol*/ undefined, members_6, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo); // TODO: GH#18217 } else { return undefined; @@ -88683,7 +105884,7 @@ var ts; } } if (types.length) { - var type = checker.getWidenedType(checker.getUnionType(types, 2)); + var type = checker.getWidenedType(checker.getUnionType(types, 2 /* Subtype */)); return isRestParameter ? checker.createArrayType(type) : type; } return undefined; @@ -88691,15 +105892,16 @@ var ts; function getSignatureFromCallContext(callContext, checker) { var parameters = []; for (var i = 0; i < callContext.argumentTypes.length; i++) { - var symbol = checker.createSymbol(1, ts.escapeLeadingUnderscores("arg" + i)); + var symbol = checker.createSymbol(1 /* FunctionScopedVariable */, ts.escapeLeadingUnderscores("arg" + i)); symbol.type = checker.getWidenedType(checker.getBaseTypeOfLiteralType(callContext.argumentTypes[i])); parameters.push(symbol); } var returnType = getTypeFromUsageContext(callContext.returnType, checker) || checker.getVoidType(); - return checker.createSignature(undefined, undefined, undefined, parameters, returnType, undefined, callContext.argumentTypes.length, false, false); + // TODO: GH#18217 + return checker.createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, parameters, returnType, /*typePredicate*/ undefined, callContext.argumentTypes.length, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false); } function addCandidateType(context, type) { - if (type && !(type.flags & 1) && !(type.flags & 32768)) { + if (type && !(type.flags & 1 /* Any */) && !(type.flags & 32768 /* Never */)) { (context.candidateTypes || (context.candidateTypes = [])).push(type); } } @@ -88709,6 +105911,7 @@ var ts; })(InferFromReference || (InferFromReference = {})); })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -88719,9 +105922,13 @@ var ts; var namespace = ts.getNamespaceDeclarationNode(node); var opts = context.program.getCompilerOptions(); var variations = []; - variations.push(createAction(context, sourceFile, node, ts.makeImport(namespace.name, undefined, node.moduleSpecifier, ts.getQuotePreference(sourceFile, context.preferences)))); + // import Bluebird from "bluebird"; + variations.push(createAction(context, sourceFile, node, ts.makeImport(namespace.name, /*namedImports*/ undefined, node.moduleSpecifier, ts.getQuotePreference(sourceFile, context.preferences)))); if (ts.getEmitModuleKind(opts) === ts.ModuleKind.CommonJS) { - variations.push(createAction(context, sourceFile, node, ts.createImportEqualsDeclaration(undefined, undefined, namespace.name, ts.createExternalModuleReference(node.moduleSpecifier)))); + // import Bluebird = require("bluebird"); + variations.push(createAction(context, sourceFile, node, ts.createImportEqualsDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, namespace.name, ts.createExternalModuleReference(node.moduleSpecifier)))); } return variations; } @@ -88738,8 +105945,8 @@ var ts; }); function getActionsForUsageOfInvalidImport(context) { var sourceFile = context.sourceFile; - var targetKind = ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures.code === context.errorCode ? 187 : 188; - var node = ts.findAncestor(ts.getTokenAtPosition(sourceFile, context.span.start, false), function (a) { return a.kind === targetKind && a.getStart() === context.span.start && a.getEnd() === (context.span.start + context.span.length); }); + var targetKind = ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures.code === context.errorCode ? 187 /* CallExpression */ : 188 /* NewExpression */; + var node = ts.findAncestor(ts.getTokenAtPosition(sourceFile, context.span.start, /*includeJsDocComment*/ false), function (a) { return a.kind === targetKind && a.getStart() === context.span.start && a.getEnd() === (context.span.start + context.span.length); }); if (!node) { return []; } @@ -88748,6 +105955,7 @@ var ts; } codefix.registerCodeFix({ errorCodes: [ + // The following error codes cover pretty much all assignability errors that could involve an expression ts.Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1.code, ts.Diagnostics.Type_0_does_not_satisfy_the_constraint_1.code, ts.Diagnostics.Type_0_is_not_assignable_to_type_1.code, @@ -88765,19 +105973,19 @@ var ts; }); function getActionsForInvalidImportLocation(context) { var sourceFile = context.sourceFile; - var node = ts.findAncestor(ts.getTokenAtPosition(sourceFile, context.span.start, false), function (a) { return a.getStart() === context.span.start && a.getEnd() === (context.span.start + context.span.length); }); + var node = ts.findAncestor(ts.getTokenAtPosition(sourceFile, context.span.start, /*includeJsDocComment*/ false), function (a) { return a.getStart() === context.span.start && a.getEnd() === (context.span.start + context.span.length); }); if (!node) { return []; } return getImportCodeFixesForExpression(context, node); } function getImportCodeFixesForExpression(context, expr) { - var type = context.program.getTypeChecker().getTypeAtLocation(expr); + var type = context.program.getTypeChecker().getTypeAtLocation(expr); // TODO: GH#18217 if (!(type.symbol && type.symbol.originatingImport)) { return []; } var fixes = []; - var relatedImport = type.symbol.originatingImport; + var relatedImport = type.symbol.originatingImport; // TODO: GH#18217 if (!ts.isImportCall(relatedImport)) { ts.addRange(fixes, getCodeFixesForImportDeclaration(context, relatedImport)); } @@ -88790,6 +105998,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -88839,7 +106048,7 @@ var ts; }, }); function getPropertyDeclaration(sourceFile, pos) { - var token = ts.getTokenAtPosition(sourceFile, pos, false); + var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); return ts.isIdentifier(token) ? ts.cast(token.parent, ts.isPropertyDeclaration) : undefined; } function getActionForAddMissingDefiniteAssignmentAssertion(context, propertyDeclaration) { @@ -88847,7 +106056,7 @@ var ts; return codefix.createCodeFixAction(fixName, changes, [ts.Diagnostics.Add_definite_assignment_assertion_to_property_0, propertyDeclaration.getText()], fixIdAddDefiniteAssignmentAssertions, ts.Diagnostics.Add_definite_assignment_assertions_to_all_uninitialized_properties); } function addDefiniteAssignmentAssertion(changeTracker, propertyDeclarationSourceFile, propertyDeclaration) { - var property = ts.updateProperty(propertyDeclaration, propertyDeclaration.decorators, propertyDeclaration.modifiers, propertyDeclaration.name, ts.createToken(51), propertyDeclaration.type, propertyDeclaration.initializer); + var property = ts.updateProperty(propertyDeclaration, propertyDeclaration.decorators, propertyDeclaration.modifiers, propertyDeclaration.name, ts.createToken(51 /* ExclamationToken */), propertyDeclaration.type, propertyDeclaration.initializer); changeTracker.replaceNode(propertyDeclarationSourceFile, propertyDeclaration, property); } function getActionForAddMissingUndefinedType(context, propertyDeclaration) { @@ -88855,8 +106064,8 @@ var ts; return codefix.createCodeFixAction(fixName, changes, [ts.Diagnostics.Add_undefined_type_to_property_0, propertyDeclaration.name.getText()], fixIdAddUndefinedType, ts.Diagnostics.Add_undefined_type_to_all_uninitialized_properties); } function addUndefinedType(changeTracker, propertyDeclarationSourceFile, propertyDeclaration) { - var undefinedTypeNode = ts.createKeywordTypeNode(140); - var type = propertyDeclaration.type; + var undefinedTypeNode = ts.createKeywordTypeNode(140 /* UndefinedKeyword */); + var type = propertyDeclaration.type; // TODO: GH#18217 var types = ts.isUnionTypeNode(type) ? type.types.concat(undefinedTypeNode) : [type, undefinedTypeNode]; changeTracker.replaceNode(propertyDeclarationSourceFile, type, ts.createUnionTypeNode(types)); } @@ -88873,10 +106082,10 @@ var ts; changeTracker.replaceNode(propertyDeclarationSourceFile, propertyDeclaration, property); } function getInitializer(checker, propertyDeclaration) { - return getDefaultValueFromType(checker, checker.getTypeFromTypeNode(propertyDeclaration.type)); + return getDefaultValueFromType(checker, checker.getTypeFromTypeNode(propertyDeclaration.type)); // TODO: GH#18217 } function getDefaultValueFromType(checker, type) { - if (type.flags & 256) { + if (type.flags & 256 /* BooleanLiteral */) { return type === checker.getFalseType() ? ts.createFalse() : ts.createTrue(); } else if (type.isLiteral()) { @@ -88887,12 +106096,12 @@ var ts; } else if (type.isClass()) { var classDeclaration = ts.getClassLikeDeclarationOfSymbol(type.symbol); - if (!classDeclaration || ts.hasModifier(classDeclaration, 128)) + if (!classDeclaration || ts.hasModifier(classDeclaration, 128 /* Abstract */)) return undefined; var constructorDeclaration = ts.getFirstConstructorWithBody(classDeclaration); if (constructorDeclaration && constructorDeclaration.parameters.length) return undefined; - return ts.createNew(ts.createIdentifier(type.symbol.name), undefined, undefined); + return ts.createNew(ts.createIdentifier(type.symbol.name), /*typeArguments*/ undefined, /*argumentsArray*/ undefined); } else if (checker.isArrayLikeType(type)) { return ts.createArrayLiteral(); @@ -88901,6 +106110,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -88919,18 +106129,19 @@ var ts; function doChange(changes, sourceFile, pos, program) { var _a = getInfo(sourceFile, pos), statement = _a.statement, name = _a.name, required = _a.required; changes.replaceNode(sourceFile, statement, ts.getAllowSyntheticDefaultImports(program.getCompilerOptions()) - ? ts.createImportDeclaration(undefined, undefined, ts.createImportClause(name, undefined), required) - : ts.createImportEqualsDeclaration(undefined, undefined, name, ts.createExternalModuleReference(required))); + ? ts.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, ts.createImportClause(name, /*namedBindings*/ undefined), required) + : ts.createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, name, ts.createExternalModuleReference(required))); } function getInfo(sourceFile, pos) { - var parent = ts.getTokenAtPosition(sourceFile, pos, false).parent; - if (!ts.isRequireCall(parent, true)) + var parent = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false).parent; + if (!ts.isRequireCall(parent, /*checkArgumentIsStringLiteralLike*/ true)) throw ts.Debug.failBadSyntaxKind(parent); var decl = ts.cast(parent.parent, ts.isVariableDeclaration); return { statement: ts.cast(decl.parent.parent, ts.isVariableStatement), name: ts.cast(decl.name, ts.isIdentifier), required: parent.arguments[0] }; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -88955,9 +106166,9 @@ var ts; }); }, }); function getInfo(sourceFile, pos) { - var name = ts.getTokenAtPosition(sourceFile, pos, false); + var name = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); if (!ts.isIdentifier(name)) - return undefined; + return undefined; // bad input var parent = name.parent; if (ts.isImportEqualsDeclaration(parent) && ts.isExternalModuleReference(parent.moduleReference)) { return { importNode: parent, name: name, moduleSpecifier: parent.moduleReference.expression }; @@ -88968,10 +106179,11 @@ var ts; } } function doChange(changes, sourceFile, info, preferences) { - changes.replaceNode(sourceFile, info.importNode, ts.makeImport(info.name, undefined, info.moduleSpecifier, ts.getQuotePreference(sourceFile, preferences))); + changes.replaceNode(sourceFile, info.importNode, ts.makeImport(info.name, /*namedImports*/ undefined, info.moduleSpecifier, ts.getQuotePreference(sourceFile, preferences))); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -88993,17 +106205,18 @@ var ts; }); }, }); function getImportTypeNode(sourceFile, pos) { - var token = ts.getTokenAtPosition(sourceFile, pos, false); - ts.Debug.assert(token.kind === 91); - ts.Debug.assert(token.parent.kind === 179); + var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); + ts.Debug.assert(token.kind === 91 /* ImportKeyword */); + ts.Debug.assert(token.parent.kind === 179 /* ImportType */); return token.parent; } function doChange(changes, sourceFile, importType) { - var newTypeNode = ts.updateImportTypeNode(importType, importType.argument, importType.qualifier, importType.typeArguments, true); + var newTypeNode = ts.updateImportTypeNode(importType, importType.argument, importType.qualifier, importType.typeArguments, /* isTypeOf */ true); changes.replaceNode(sourceFile, importType, newTypeNode); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var codefix; @@ -89030,7 +106243,7 @@ var ts; }); } }); function getInfo(sourceFile, pos) { - var token = ts.getTokenAtPosition(sourceFile, pos, false); + var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); var indexSignature = ts.cast(token.parent.parent, ts.isIndexSignatureDeclaration); if (ts.isClassDeclaration(indexSignature.parent)) return undefined; @@ -89046,7 +106259,7 @@ var ts; var otherMembers = members.filter(function (member) { return !ts.isIndexSignatureDeclaration(member); }); var parameter = ts.first(indexSignature.parameters); var mappedTypeParameter = ts.createTypeParameterDeclaration(ts.cast(parameter.name, ts.isIdentifier), parameter.type); - var mappedIntersectionType = ts.createMappedTypeNode(ts.hasReadonlyModifier(indexSignature) ? ts.createModifier(132) : undefined, mappedTypeParameter, indexSignature.questionToken, indexSignature.type); + var mappedIntersectionType = ts.createMappedTypeNode(ts.hasReadonlyModifier(indexSignature) ? ts.createModifier(132 /* ReadonlyKeyword */) : undefined, mappedTypeParameter, indexSignature.questionToken, indexSignature.type); var intersectionType = ts.createIntersectionTypeNode(ts.getAllSuperTypeNodes(container).concat([ mappedIntersectionType ], (otherMembers.length ? [ts.createTypeLiteralNode(otherMembers)] : ts.emptyArray))); @@ -89054,6 +106267,7 @@ var ts; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var refactor; @@ -89068,8 +106282,8 @@ var ts; var i = getImportToConvert(context); if (!i) return undefined; - var description = i.kind === 246 ? ts.Diagnostics.Convert_namespace_import_to_named_imports.message : ts.Diagnostics.Convert_named_imports_to_namespace_import.message; - var actionName = i.kind === 246 ? actionNameNamespaceToNamed : actionNameNamedToNamespace; + var description = i.kind === 246 /* NamespaceImport */ ? ts.Diagnostics.Convert_namespace_import_to_named_imports.message : ts.Diagnostics.Convert_named_imports_to_namespace_import.message; + var actionName = i.kind === 246 /* NamespaceImport */ ? actionNameNamespaceToNamed : actionNameNamedToNamespace; return [{ name: refactorName, description: description, actions: [{ name: actionName, description: description }] }]; }, getEditsForAction: function (context, actionName) { @@ -89078,10 +106292,11 @@ var ts; return { edits: edits, renameFilename: undefined, renameLocation: undefined }; } }); + // Can convert imports of the form `import * as m from "m";` or `import d, { x, y } from "m";`. function getImportToConvert(context) { var file = context.file; var span = ts.getRefactorContextSpan(context); - var token = ts.getTokenAtPosition(file, span.start, false); + var token = ts.getTokenAtPosition(file, span.start, /*includeJsDocComment*/ false); var importDecl = ts.getParentNodeInSpan(token, file, span); if (!importDecl || !ts.isImportDeclaration(importDecl)) return undefined; @@ -89090,7 +106305,7 @@ var ts; } function doChange(sourceFile, program, changes, toConvert) { var checker = program.getTypeChecker(); - if (toConvert.kind === 246) { + if (toConvert.kind === 246 /* NamespaceImport */) { doChangeNamespaceToNamed(sourceFile, checker, changes, toConvert, ts.getAllowSyntheticDefaultImports(program.getCompilerOptions())); } else { @@ -89108,13 +106323,14 @@ var ts; else { var parent = ts.cast(id.parent, ts.isPropertyAccessExpression); var exportName = parent.name.text; - if (checker.resolveName(exportName, id, 67108863, true)) { + if (checker.resolveName(exportName, id, 67108863 /* All */, /*excludeGlobals*/ true)) { conflictingNames.set(exportName, true); } ts.Debug.assert(parent.expression === id); nodesToReplace.push(parent); } }); + // We may need to change `mod.x` to `_x` to avoid a name conflict. var exportNameToImportName = ts.createMap(); for (var _i = 0, nodesToReplace_1 = nodesToReplace; _i < nodesToReplace_1.length; _i++) { var propertyAccess = nodesToReplace_1[_i]; @@ -89131,7 +106347,8 @@ var ts; }); var importDecl = toConvert.parent.parent; if (usedAsNamespaceOrDefault && !allowSyntheticDefaultImports) { - changes.insertNodeAfter(sourceFile, importDecl, updateImport(importDecl, undefined, importSpecifiers)); + // Need to leave the namespace import alone + changes.insertNodeAfter(sourceFile, importDecl, updateImport(importDecl, /*defaultImportName*/ undefined, importSpecifiers)); } else { changes.replaceNode(sourceFile, importDecl, updateImport(importDecl, usedAsNamespaceOrDefault ? ts.createIdentifier(toConvert.name.text) : undefined, importSpecifiers)); @@ -89140,10 +106357,10 @@ var ts; function doChangeNamedToNamespace(sourceFile, checker, changes, toConvert) { var importDecl = toConvert.parent.parent; var moduleSpecifier = importDecl.moduleSpecifier; - var preferredName = moduleSpecifier && ts.isStringLiteral(moduleSpecifier) ? ts.codefix.moduleSpecifierToValidIdentifier(moduleSpecifier.text, 6) : "module"; + var preferredName = moduleSpecifier && ts.isStringLiteral(moduleSpecifier) ? ts.codefix.moduleSpecifierToValidIdentifier(moduleSpecifier.text, 6 /* ESNext */) : "module"; var namespaceNameConflicts = toConvert.elements.some(function (element) { return ts.FindAllReferences.Core.eachSymbolReferenceInFile(element.name, checker, sourceFile, function (id) { - return !!checker.resolveName(preferredName, id, 67108863, true); + return !!checker.resolveName(preferredName, id, 67108863 /* All */, /*excludeGlobals*/ true); }) || false; }); var namespaceImportName = namespaceNameConflicts ? ts.getUniqueName(preferredName, sourceFile) : preferredName; @@ -89171,15 +106388,16 @@ var ts; } changes.replaceNode(sourceFile, toConvert, ts.createNamespaceImport(ts.createIdentifier(namespaceImportName))); if (neededNamedImports.length) { - changes.insertNodeAfter(sourceFile, toConvert.parent.parent, updateImport(importDecl, undefined, neededNamedImports)); + changes.insertNodeAfter(sourceFile, toConvert.parent.parent, updateImport(importDecl, /*defaultImportName*/ undefined, neededNamedImports)); } } function updateImport(old, defaultImportName, elements) { - return ts.createImportDeclaration(undefined, undefined, ts.createImportClause(defaultImportName, elements && elements.length ? ts.createNamedImports(elements) : undefined), old.moduleSpecifier); + return ts.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, ts.createImportClause(defaultImportName, elements && elements.length ? ts.createNamedImports(elements) : undefined), old.moduleSpecifier); } })(generateGetAccessorAndSetAccessor = refactor.generateGetAccessorAndSetAccessor || (refactor.generateGetAccessorAndSetAccessor = {})); })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var refactor; @@ -89188,6 +106406,10 @@ var ts; (function (extractSymbol) { var refactorName = "Extract Symbol"; refactor.registerRefactor(refactorName, { getAvailableActions: getAvailableActions, getEditsForAction: getEditsForAction }); + /** + * Compute the associated code actions + * Exported for tests. + */ function getAvailableActions(context) { var rangeToExtract = getRangeToExtract(context.file, ts.getRefactorContextSpan(context)); var targetRange = rangeToExtract.targetRange; @@ -89196,6 +106418,7 @@ var ts; } var extractions = getPossibleExtractions(targetRange, context); if (extractions === undefined) { + // No extractions possible return undefined; } var functionActions = []; @@ -89205,7 +106428,11 @@ var ts; var i = 0; for (var _i = 0, extractions_1 = extractions; _i < extractions_1.length; _i++) { var _a = extractions_1[_i], functionExtraction = _a.functionExtraction, constantExtraction = _a.constantExtraction; + // Skip these since we don't have a way to report errors yet if (functionExtraction.errors.length === 0) { + // Don't issue refactorings with duplicated names. + // Scopes come back in "innermost first" order, so extractions will + // preferentially go into nearer scopes var description = functionExtraction.description; if (!usedFunctionNames.has(description)) { usedFunctionNames.set(description, true); @@ -89215,7 +106442,11 @@ var ts; }); } } + // Skip these since we don't have a way to report errors yet if (constantExtraction.errors.length === 0) { + // Don't issue refactorings with duplicated names. + // Scopes come back in "innermost first" order, so extractions will + // preferentially go into nearer scopes var description = constantExtraction.description; if (!usedConstantNames.has(description)) { usedConstantNames.set(description, true); @@ -89225,6 +106456,8 @@ var ts; }); } } + // *do* increment i anyway because we'll look for the i-th scope + // later when actually doing the refactoring if the user requests it i++; } var infos = []; @@ -89245,9 +106478,10 @@ var ts; return infos.length ? infos : undefined; } extractSymbol.getAvailableActions = getAvailableActions; + /* Exported for tests */ function getEditsForAction(context, actionName) { var rangeToExtract = getRangeToExtract(context.file, ts.getRefactorContextSpan(context)); - var targetRange = rangeToExtract.targetRange; + var targetRange = rangeToExtract.targetRange; // TODO:GH#18217 var parsedFunctionIndexMatch = /^function_scope_(\d+)$/.exec(actionName); if (parsedFunctionIndexMatch) { var index = +parsedFunctionIndexMatch[1]; @@ -89263,6 +106497,7 @@ var ts; ts.Debug.fail("Unrecognized action name"); } extractSymbol.getEditsForAction = getEditsForAction; + // Move these into diagnostic messages if they become user-facing var Messages; (function (Messages) { function createMessage(message) { @@ -89298,29 +106533,47 @@ var ts; RangeFacts[RangeFacts["IsGenerator"] = 2] = "IsGenerator"; RangeFacts[RangeFacts["IsAsyncFunction"] = 4] = "IsAsyncFunction"; RangeFacts[RangeFacts["UsesThis"] = 8] = "UsesThis"; + /** + * The range is in a function which needs the 'static' modifier in a class + */ RangeFacts[RangeFacts["InStaticRegion"] = 16] = "InStaticRegion"; })(RangeFacts || (RangeFacts = {})); + /** + * getRangeToExtract takes a span inside a text file and returns either an expression or an array + * of statements representing the minimum set of nodes needed to extract the entire span. This + * process may fail, in which case a set of errors is returned instead (these are currently + * not shown to the user, but can be used by us diagnostically) + */ + // exported only for tests function getRangeToExtract(sourceFile, span) { var length = span.length; if (length === 0) { return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractEmpty)] }; } - var start = ts.getParentNodeInSpan(ts.getTokenAtPosition(sourceFile, span.start, false), sourceFile, span); + // Walk up starting from the the start position until we find a non-SourceFile node that subsumes the selected span. + // This may fail (e.g. you select two statements in the root of a source file) + var start = ts.getParentNodeInSpan(ts.getTokenAtPosition(sourceFile, span.start, /*includeJsDocComment*/ false), sourceFile, span); + // Do the same for the ending position var end = ts.getParentNodeInSpan(ts.findTokenOnLeftOfPosition(sourceFile, ts.textSpanEnd(span)), sourceFile, span); var declarations = []; + // We'll modify these flags as we walk the tree to collect data + // about what things need to be done as part of the extraction. var rangeFacts = RangeFacts.None; if (!start || !end) { + // cannot find either start or end node return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; } if (start.parent !== end.parent) { + // start and end nodes belong to different subtrees return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; } if (start !== end) { + // start and end should be statements and parent should be either block or a source file if (!isBlockLike(start.parent)) { return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; } var statements = []; - var start2 = start; + var start2 = start; // TODO: GH#18217 Need to alias `start` to get this to compile. See https://github.com/Microsoft/TypeScript/issues/19955#issuecomment-344118248 for (var _i = 0, _a = start2.parent.statements; _i < _a.length; _i++) { var statement = _a[_i]; if (statement === start || statements.length) { @@ -89335,19 +106588,30 @@ var ts; } } if (!statements.length) { + // https://github.com/Microsoft/TypeScript/issues/20559 + // Ranges like [|case 1: break;|] will fail to populate `statements` because + // they will never find `start` in `start.parent.statements`. + // Consider: We could support ranges like [|case 1:|] by refining them to just + // the expression. return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; } return { targetRange: { range: statements, facts: rangeFacts, declarations: declarations } }; } if (ts.isReturnStatement(start) && !start.expression) { + // Makes no sense to extract an expression-less return statement. return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; } + // We have a single node (start) var node = refineNode(start); var errors = checkRootNode(node) || checkNode(node); if (errors) { return { errors: errors }; } - return { targetRange: { range: getStatementOrExpressionRange(node), facts: rangeFacts, declarations: declarations } }; + return { targetRange: { range: getStatementOrExpressionRange(node), facts: rangeFacts, declarations: declarations } }; // TODO: GH#18217 + /** + * Attempt to refine the extraction node (generally, by shrinking it) to produce better results. + * @param node The unrefined extraction node. + */ function refineNode(node) { if (ts.isReturnStatement(node)) { if (node.expression) { @@ -89367,6 +106631,7 @@ var ts; if (numInitializers === 1) { return lastInitializer; } + // No special handling if there are multiple initializers. } else if (ts.isVariableDeclaration(node)) { if (node.initializer) { @@ -89384,27 +106649,28 @@ var ts; function checkForStaticContext(nodeToCheck, containingClass) { var current = nodeToCheck; while (current !== containingClass) { - if (current.kind === 152) { - if (ts.hasModifier(current, 32)) { + if (current.kind === 152 /* PropertyDeclaration */) { + if (ts.hasModifier(current, 32 /* Static */)) { rangeFacts |= RangeFacts.InStaticRegion; } break; } - else if (current.kind === 149) { + else if (current.kind === 149 /* Parameter */) { var ctorOrMethod = ts.getContainingFunction(current); - if (ctorOrMethod.kind === 155) { + if (ctorOrMethod.kind === 155 /* Constructor */) { rangeFacts |= RangeFacts.InStaticRegion; } break; } - else if (current.kind === 154) { - if (ts.hasModifier(current, 32)) { + else if (current.kind === 154 /* MethodDeclaration */) { + if (ts.hasModifier(current, 32 /* Static */)) { rangeFacts |= RangeFacts.InStaticRegion; } } current = current.parent; } } + // Verifies whether we can actually extract this node or not. function checkNode(nodeToCheck) { var PermittedJumps; (function (PermittedJumps) { @@ -89413,42 +106679,53 @@ var ts; PermittedJumps[PermittedJumps["Continue"] = 2] = "Continue"; PermittedJumps[PermittedJumps["Return"] = 4] = "Return"; })(PermittedJumps || (PermittedJumps = {})); + // We believe it's true because the node is from the (unmodified) tree. ts.Debug.assert(nodeToCheck.pos <= nodeToCheck.end, "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809"); + // For understanding how skipTrivia functioned: ts.Debug.assert(!ts.positionIsSynthesized(nodeToCheck.pos), "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809"); if (!ts.isStatement(nodeToCheck) && !(ts.isExpressionNode(nodeToCheck) && isExtractableExpression(nodeToCheck))) { return [ts.createDiagnosticForNode(nodeToCheck, Messages.statementOrExpressionExpected)]; } - if (nodeToCheck.flags & 4194304) { + if (nodeToCheck.flags & 4194304 /* Ambient */) { return [ts.createDiagnosticForNode(nodeToCheck, Messages.cannotExtractAmbientBlock)]; } + // If we're in a class, see whether we're in a static region (static property initializer, static method, class constructor parameter default) var containingClass = ts.getContainingClass(nodeToCheck); if (containingClass) { checkForStaticContext(nodeToCheck, containingClass); } var errors; - var permittedJumps = 4; + var permittedJumps = 4 /* Return */; var seenLabels; visit(nodeToCheck); return errors; function visit(node) { if (errors) { + // already found an error - can stop now return true; } if (ts.isDeclaration(node)) { - var declaringNode = (node.kind === 232) ? node.parent.parent : node; - if (ts.hasModifier(declaringNode, 1)) { + var declaringNode = (node.kind === 232 /* VariableDeclaration */) ? node.parent.parent : node; + if (ts.hasModifier(declaringNode, 1 /* Export */)) { + // TODO: GH#18217 Silly to use `errors ||` since it's definitely not defined (see top of `visit`) + // Also, if we're only pushing one error, just use `let error: Diagnostic | undefined`! + // Also TODO: GH#19956 (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractExportedEntity)); return true; } declarations.push(node.symbol); } + // Some things can't be extracted in certain situations switch (node.kind) { - case 244: + case 244 /* ImportDeclaration */: (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractImport)); return true; - case 97: - if (node.parent.kind === 187) { - var containingClass_1 = ts.getContainingClass(node); + case 97 /* SuperKeyword */: + // For a super *constructor call*, we have to be extracting the entire class, + // but a super *method call* simply implies a 'this' reference + if (node.parent.kind === 187 /* CallExpression */) { + // Super constructor call + var containingClass_1 = ts.getContainingClass(node); // TODO:GH#18217 if (containingClass_1.pos < span.start || containingClass_1.end >= (span.start + span.length)) { (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractSuper)); return true; @@ -89461,43 +106738,49 @@ var ts; } if (ts.isFunctionLikeDeclaration(node) || ts.isClassLike(node)) { switch (node.kind) { - case 234: - case 235: + case 234 /* FunctionDeclaration */: + case 235 /* ClassDeclaration */: if (ts.isSourceFile(node.parent) && node.parent.externalModuleIndicator === undefined) { + // You cannot extract global declarations (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.functionWillNotBeVisibleInTheNewScope)); } break; } + // do not dive into functions or classes return false; } var savedPermittedJumps = permittedJumps; switch (node.kind) { - case 217: - permittedJumps = 0; + case 217 /* IfStatement */: + permittedJumps = 0 /* None */; break; - case 230: - permittedJumps = 0; + case 230 /* TryStatement */: + // forbid all jumps inside try blocks + permittedJumps = 0 /* None */; break; - case 213: - if (node.parent && node.parent.kind === 230 && node.parent.finallyBlock === node) { - permittedJumps = 4; + case 213 /* Block */: + if (node.parent && node.parent.kind === 230 /* TryStatement */ && node.parent.finallyBlock === node) { + // allow unconditional returns from finally blocks + permittedJumps = 4 /* Return */; } break; - case 266: - permittedJumps |= 1; + case 266 /* CaseClause */: + // allow unlabeled break inside case clauses + permittedJumps |= 1 /* Break */; break; default: - if (ts.isIterationStatement(node, false)) { - permittedJumps |= 1 | 2; + if (ts.isIterationStatement(node, /*lookInLabeledStatements*/ false)) { + // allow unlabeled break/continue inside loops + permittedJumps |= 1 /* Break */ | 2 /* Continue */; } break; } switch (node.kind) { - case 174: - case 99: + case 174 /* ThisType */: + case 99 /* ThisKeyword */: rangeFacts |= RangeFacts.UsesThis; break; - case 228: + case 228 /* LabeledStatement */: { var label = node.label; (seenLabels || (seenLabels = [])).push(label.escapedText); @@ -89505,30 +106788,32 @@ var ts; seenLabels.pop(); break; } - case 224: - case 223: + case 224 /* BreakStatement */: + case 223 /* ContinueStatement */: { var label = node.label; if (label) { if (!ts.contains(seenLabels, label.escapedText)) { + // attempts to jump to label that is not in range to be extracted (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange)); } } else { - if (!(permittedJumps & (node.kind === 224 ? 1 : 2))) { + if (!(permittedJumps & (node.kind === 224 /* BreakStatement */ ? 1 /* Break */ : 2 /* Continue */))) { + // attempt to break or continue in a forbidden context (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements)); } } break; } - case 197: + case 197 /* AwaitExpression */: rangeFacts |= RangeFacts.IsAsyncFunction; break; - case 203: + case 203 /* YieldExpression */: rangeFacts |= RangeFacts.IsGenerator; break; - case 225: - if (permittedJumps & 4) { + case 225 /* ReturnStatement */: + if (permittedJumps & 4 /* Return */) { rangeFacts |= RangeFacts.HasReturn; } else { @@ -89549,6 +106834,10 @@ var ts; return [node]; } else if (ts.isExpressionNode(node)) { + // If our selection is the expression in an ExpressionStatement, expand + // the selection to include the enclosing Statement (this stops us + // from trying to care about the return value of the extracted function + // and eliminates double semicolon insertion in certain scenarios) return ts.isExpressionStatement(node.parent) ? [node.parent] : node; } return undefined; @@ -89556,9 +106845,15 @@ var ts; function isScope(node) { return ts.isFunctionLikeDeclaration(node) || ts.isSourceFile(node) || ts.isModuleBlock(node) || ts.isClassLike(node); } + /** + * Computes possible places we could extract the function into. For example, + * you may be able to extract into a class method *or* local closure *or* namespace function, + * depending on what's in the extracted body. + */ function collectEnclosingScopes(range) { var current = isReadonlyArray(range.range) ? ts.first(range.range) : range.range; if (range.facts & RangeFacts.UsesThis) { + // if range uses this as keyword or as type inside the class then it can only be extracted to a method of the containing class var containingClass = ts.getContainingClass(current); if (containingClass) { var containingFunction = ts.findAncestor(current, ts.isFunctionLikeDeclaration); @@ -89570,12 +106865,19 @@ var ts; var scopes = []; while (true) { current = current.parent; - if (current.kind === 149) { + // A function parameter's initializer is actually in the outer scope, not the function declaration + if (current.kind === 149 /* Parameter */) { + // Skip all the way to the outer scope of the function that declared this parameter current = ts.findAncestor(current, function (parent) { return ts.isFunctionLikeDeclaration(parent); }).parent; } + // We want to find the nearest parent where we can place an "equivalent" sibling to the node we're extracting out of. + // Walk up to the closest parent of a place where we can logically put a sibling: + // * Function declaration + // * Class declaration or expression + // * Module/namespace or source file if (isScope(current)) { scopes.push(current); - if (current.kind === 274) { + if (current.kind === 274 /* SourceFile */) { return scopes; } } @@ -89584,7 +106886,7 @@ var ts; function getFunctionExtractionAtIndex(targetRange, context, requestedChangesIndex) { var _a = getPossibleExtractionsWorker(targetRange, context), scopes = _a.scopes, _b = _a.readsAndWrites, target = _b.target, usagesPerScope = _b.usagesPerScope, functionErrorsPerScope = _b.functionErrorsPerScope, exposedVariableDeclarations = _b.exposedVariableDeclarations; ts.Debug.assert(!functionErrorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?"); - context.cancellationToken.throwIfCancellationRequested(); + context.cancellationToken.throwIfCancellationRequested(); // TODO: GH#18217 return extractFunctionInScope(target, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], exposedVariableDeclarations, targetRange, context); } function getConstantExtractionAtIndex(targetRange, context, requestedChangesIndex) { @@ -89597,8 +106899,14 @@ var ts; : target.statements[0].expression; return extractConstantInScope(expression, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], targetRange.facts, context); } + /** + * Given a piece of text to extract ('targetRange'), computes a list of possible extractions. + * Each returned ExtractResultForScope corresponds to a possible target scope and is either a set of changes + * or an error explaining why we can't extract into that scope. + */ function getPossibleExtractions(targetRange, context) { var _a = getPossibleExtractionsWorker(targetRange, context), scopes = _a.scopes, _b = _a.readsAndWrites, functionErrorsPerScope = _b.functionErrorsPerScope, constantErrorsPerScope = _b.constantErrorsPerScope; + // Need the inner type annotation to avoid https://github.com/Microsoft/TypeScript/issues/7547 var extractions = scopes.map(function (scope, i) { var functionDescriptionPart = getDescriptionForFunctionInScope(scope); var constantDescriptionPart = getDescriptionForConstantInScope(scope); @@ -89609,11 +106917,11 @@ var ts; : getDescriptionForModuleLikeDeclaration(scope); var functionDescription; var constantDescription; - if (scopeDescription === 1) { + if (scopeDescription === 1 /* Global */) { functionDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1_scope), [functionDescriptionPart, "global"]); constantDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1_scope), [constantDescriptionPart, "global"]); } - else if (scopeDescription === 0) { + else if (scopeDescription === 0 /* Module */) { functionDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1_scope), [functionDescriptionPart, "module"]); constantDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1_scope), [constantDescriptionPart, "module"]); } @@ -89621,6 +106929,7 @@ var ts; functionDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1), [functionDescriptionPart, scopeDescription]); constantDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1), [constantDescriptionPart, scopeDescription]); } + // Customize the phrasing for the innermost scope to increase clarity. if (i === 0 && !ts.isClassLike(scope)) { constantDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_enclosing_scope), [constantDescriptionPart]); } @@ -89658,43 +106967,48 @@ var ts; } function getDescriptionForFunctionLikeDeclaration(scope) { switch (scope.kind) { - case 155: + case 155 /* Constructor */: return "constructor"; - case 192: - case 234: + case 192 /* FunctionExpression */: + case 234 /* FunctionDeclaration */: return scope.name ? "function '" + scope.name.text + "'" : "anonymous function"; - case 193: + case 193 /* ArrowFunction */: return "arrow function"; - case 154: + case 154 /* MethodDeclaration */: return "method '" + scope.name.getText(); - case 156: + case 156 /* GetAccessor */: return "'get " + scope.name.getText() + "'"; - case 157: + case 157 /* SetAccessor */: return "'set " + scope.name.getText() + "'"; default: throw ts.Debug.assertNever(scope); } } function getDescriptionForClassLikeDeclaration(scope) { - return scope.kind === 235 + return scope.kind === 235 /* ClassDeclaration */ ? scope.name ? "class '" + scope.name.text + "'" : "anonymous class declaration" : scope.name ? "class expression '" + scope.name.text + "'" : "anonymous class expression"; } function getDescriptionForModuleLikeDeclaration(scope) { - return scope.kind === 240 + return scope.kind === 240 /* ModuleBlock */ ? "namespace '" + scope.parent.name.getText() + "'" - : scope.externalModuleIndicator ? 0 : 1; + : scope.externalModuleIndicator ? 0 /* Module */ : 1 /* Global */; } var SpecialScope; (function (SpecialScope) { SpecialScope[SpecialScope["Module"] = 0] = "Module"; SpecialScope[SpecialScope["Global"] = 1] = "Global"; })(SpecialScope || (SpecialScope = {})); + /** + * Result of 'extractRange' operation for a specific scope. + * Stores either a list of changes that should be applied to extract a range or a list of errors + */ function extractFunctionInScope(node, scope, _a, exposedVariableDeclarations, range, context) { var usagesInScope = _a.usages, typeParameterUsages = _a.typeParameterUsages, substitutions = _a.substitutions; var checker = context.program.getTypeChecker(); + // Make a unique name for the extracted function var file = scope.getSourceFile(); var functionNameText = ts.getUniqueName(ts.isClassLike(scope) ? "newMethod" : "newFunction", file); var isJS = ts.isInJavaScriptFile(scope); @@ -89707,12 +107021,18 @@ var ts; var typeNode; if (!isJS) { var type = checker.getTypeOfSymbolAtLocation(usage.symbol, usage.node); + // Widen the type so we don't emit nonsense annotations like "function fn(x: 3) {" type = checker.getBaseTypeOfLiteralType(type); - typeNode = checker.typeToTypeNode(type, scope, 1); + typeNode = checker.typeToTypeNode(type, scope, 1 /* NoTruncation */); } - var paramDecl = ts.createParameter(undefined, undefined, undefined, name, undefined, typeNode); + var paramDecl = ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + /*name*/ name, + /*questionToken*/ undefined, typeNode); parameters.push(paramDecl); - if (usage.usage === 2) { + if (usage.usage === 2 /* Write */) { (writes || (writes = [])).push(usage); } callArguments.push(ts.createIdentifier(name)); @@ -89722,93 +107042,130 @@ var ts; var typeParameters = sortedTypeParametersAndDeclarations.length === 0 ? undefined : sortedTypeParametersAndDeclarations.map(function (t) { return t.declaration; }); + // Strictly speaking, we should check whether each name actually binds to the appropriate type + // parameter. In cases of shadowing, they may not. var callTypeArguments = typeParameters !== undefined - ? typeParameters.map(function (decl) { return ts.createTypeReferenceNode(decl.name, undefined); }) + ? typeParameters.map(function (decl) { return ts.createTypeReferenceNode(decl.name, /*typeArguments*/ undefined); }) : undefined; + // Provide explicit return types for contextually-typed functions + // to avoid problems when there are literal types present if (ts.isExpression(node) && !isJS) { var contextualType = checker.getContextualType(node); - returnType = checker.typeToTypeNode(contextualType, scope, 1); + returnType = checker.typeToTypeNode(contextualType, scope, 1 /* NoTruncation */); // TODO: GH#18217 } var _b = transformFunctionBody(node, exposedVariableDeclarations, writes, substitutions, !!(range.facts & RangeFacts.HasReturn)), body = _b.body, returnValueProperty = _b.returnValueProperty; ts.suppressLeadingAndTrailingTrivia(body); var newFunction; if (ts.isClassLike(scope)) { - var modifiers = isJS ? [] : [ts.createToken(112)]; + // always create private method in TypeScript files + var modifiers = isJS ? [] : [ts.createToken(112 /* PrivateKeyword */)]; if (range.facts & RangeFacts.InStaticRegion) { - modifiers.push(ts.createToken(115)); + modifiers.push(ts.createToken(115 /* StaticKeyword */)); } if (range.facts & RangeFacts.IsAsyncFunction) { - modifiers.push(ts.createToken(120)); + modifiers.push(ts.createToken(120 /* AsyncKeyword */)); } - newFunction = ts.createMethod(undefined, modifiers.length ? modifiers : undefined, range.facts & RangeFacts.IsGenerator ? ts.createToken(39) : undefined, functionName, undefined, typeParameters, parameters, returnType, body); + newFunction = ts.createMethod( + /*decorators*/ undefined, modifiers.length ? modifiers : undefined, range.facts & RangeFacts.IsGenerator ? ts.createToken(39 /* AsteriskToken */) : undefined, functionName, + /*questionToken*/ undefined, typeParameters, parameters, returnType, body); } else { - newFunction = ts.createFunctionDeclaration(undefined, range.facts & RangeFacts.IsAsyncFunction ? [ts.createToken(120)] : undefined, range.facts & RangeFacts.IsGenerator ? ts.createToken(39) : undefined, functionName, typeParameters, parameters, returnType, body); + newFunction = ts.createFunctionDeclaration( + /*decorators*/ undefined, range.facts & RangeFacts.IsAsyncFunction ? [ts.createToken(120 /* AsyncKeyword */)] : undefined, range.facts & RangeFacts.IsGenerator ? ts.createToken(39 /* AsteriskToken */) : undefined, functionName, typeParameters, parameters, returnType, body); } var changeTracker = ts.textChanges.ChangeTracker.fromContext(context); var minInsertionPos = (isReadonlyArray(range.range) ? ts.last(range.range) : range.range).end; var nodeToInsertBefore = getNodeToInsertFunctionBefore(minInsertionPos, scope); if (nodeToInsertBefore) { - changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newFunction, true); + changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newFunction, /*blankLineBetween*/ true); } else { changeTracker.insertNodeAtEndOfScope(context.file, scope, newFunction); } var newNodes = []; + // replace range with function call var called = getCalledExpression(scope, range, functionNameText); - var call = ts.createCall(called, callTypeArguments, callArguments); + var call = ts.createCall(called, callTypeArguments, // Note that no attempt is made to take advantage of type argument inference + callArguments); if (range.facts & RangeFacts.IsGenerator) { - call = ts.createYield(ts.createToken(39), call); + call = ts.createYield(ts.createToken(39 /* AsteriskToken */), call); } if (range.facts & RangeFacts.IsAsyncFunction) { call = ts.createAwait(call); } if (exposedVariableDeclarations.length && !writes) { + // No need to mix declarations and writes. + // How could any variables be exposed if there's a return statement? ts.Debug.assert(!returnValueProperty); ts.Debug.assert(!(range.facts & RangeFacts.HasReturn)); if (exposedVariableDeclarations.length === 1) { + // Declaring exactly one variable: let x = newFunction(); var variableDeclaration = exposedVariableDeclarations[0]; - newNodes.push(ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.getSynthesizedDeepClone(variableDeclaration.name), ts.getSynthesizedDeepClone(variableDeclaration.type), call)], variableDeclaration.parent.flags))); + newNodes.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.getSynthesizedDeepClone(variableDeclaration.name), /*type*/ ts.getSynthesizedDeepClone(variableDeclaration.type), /*initializer*/ call)], // TODO (acasey): test binding patterns + variableDeclaration.parent.flags))); } else { + // Declaring multiple variables / return properties: + // let {x, y} = newFunction(); var bindingElements = []; var typeElements = []; var commonNodeFlags = exposedVariableDeclarations[0].parent.flags; var sawExplicitType = false; for (var _i = 0, exposedVariableDeclarations_1 = exposedVariableDeclarations; _i < exposedVariableDeclarations_1.length; _i++) { var variableDeclaration = exposedVariableDeclarations_1[_i]; - bindingElements.push(ts.createBindingElement(undefined, undefined, ts.getSynthesizedDeepClone(variableDeclaration.name))); - var variableType = checker.typeToTypeNode(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(variableDeclaration)), scope, 1); - typeElements.push(ts.createPropertySignature(undefined, variableDeclaration.symbol.name, undefined, variableType, undefined)); + bindingElements.push(ts.createBindingElement( + /*dotDotDotToken*/ undefined, + /*propertyName*/ undefined, + /*name*/ ts.getSynthesizedDeepClone(variableDeclaration.name))); + // Being returned through an object literal will have widened the type. + var variableType = checker.typeToTypeNode(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(variableDeclaration)), // TODO: GH#18217 + scope, 1 /* NoTruncation */); + typeElements.push(ts.createPropertySignature( + /*modifiers*/ undefined, + /*name*/ variableDeclaration.symbol.name, + /*questionToken*/ undefined, + /*type*/ variableType, + /*initializer*/ undefined)); sawExplicitType = sawExplicitType || variableDeclaration.type !== undefined; commonNodeFlags = commonNodeFlags & variableDeclaration.parent.flags; } var typeLiteral = sawExplicitType ? ts.createTypeLiteralNode(typeElements) : undefined; if (typeLiteral) { - ts.setEmitFlags(typeLiteral, 1); + ts.setEmitFlags(typeLiteral, 1 /* SingleLine */); } - newNodes.push(ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createObjectBindingPattern(bindingElements), typeLiteral, call)], commonNodeFlags))); + newNodes.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createObjectBindingPattern(bindingElements), + /*type*/ typeLiteral, + /*initializer*/ call)], commonNodeFlags))); } } else if (exposedVariableDeclarations.length || writes) { if (exposedVariableDeclarations.length) { + // CONSIDER: we're going to create one statement per variable, but we could actually preserve their original grouping. for (var _c = 0, exposedVariableDeclarations_2 = exposedVariableDeclarations; _c < exposedVariableDeclarations_2.length; _c++) { var variableDeclaration = exposedVariableDeclarations_2[_c]; var flags = variableDeclaration.parent.flags; - if (flags & 2) { - flags = (flags & ~2) | 1; + if (flags & 2 /* Const */) { + flags = (flags & ~2 /* Const */) | 1 /* Let */; } - newNodes.push(ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(variableDeclaration.symbol.name, getTypeDeepCloneUnionUndefined(variableDeclaration.type))], flags))); + newNodes.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(variableDeclaration.symbol.name, getTypeDeepCloneUnionUndefined(variableDeclaration.type))], flags))); } } if (returnValueProperty) { - newNodes.push(ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(returnValueProperty, getTypeDeepCloneUnionUndefined(returnType))], 1))); + // has both writes and return, need to create variable declaration to hold return value; + newNodes.push(ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(returnValueProperty, getTypeDeepCloneUnionUndefined(returnType))], 1 /* Let */))); } var assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes); if (returnValueProperty) { assignments.unshift(ts.createShorthandPropertyAssignment(returnValueProperty)); } + // propagate writes back if (assignments.length === 1) { + // We would only have introduced a return value property if there had been + // other assignments to make. ts.Debug.assert(!returnValueProperty); newNodes.push(ts.createStatement(ts.createAssignment(assignments[0].name, call))); if (range.facts & RangeFacts.HasReturn) { @@ -89816,6 +107173,9 @@ var ts; } } else { + // emit e.g. + // { a, b, __return } = newFunction(a, b); + // return __return; newNodes.push(ts.createStatement(ts.createAssignment(ts.createObjectLiteral(assignments), call))); if (returnValueProperty) { newNodes.push(ts.createReturn(ts.createIdentifier(returnValueProperty))); @@ -89842,7 +107202,7 @@ var ts; var edits = changeTracker.getChanges(); var renameRange = isReadonlyArray(range.range) ? ts.first(range.range) : range.range; var renameFilename = renameRange.getSourceFile().fileName; - var renameLocation = ts.getRenameLocation(edits, renameFilename, functionNameText, false); + var renameLocation = ts.getRenameLocation(edits, renameFilename, functionNameText, /*isDeclaredBeforeUse*/ false); return { renameFilename: renameFilename, renameLocation: renameLocation, edits: edits }; function getTypeDeepCloneUnionUndefined(typeNode) { if (typeNode === undefined) { @@ -89853,62 +107213,85 @@ var ts; while (ts.isParenthesizedTypeNode(withoutParens)) { withoutParens = withoutParens.type; } - return ts.isUnionTypeNode(withoutParens) && ts.find(withoutParens.types, function (t) { return t.kind === 140; }) + return ts.isUnionTypeNode(withoutParens) && ts.find(withoutParens.types, function (t) { return t.kind === 140 /* UndefinedKeyword */; }) ? clone - : ts.createUnionTypeNode([clone, ts.createKeywordTypeNode(140)]); + : ts.createUnionTypeNode([clone, ts.createKeywordTypeNode(140 /* UndefinedKeyword */)]); } } + /** + * Result of 'extractRange' operation for a specific scope. + * Stores either a list of changes that should be applied to extract a range or a list of errors + */ function extractConstantInScope(node, scope, _a, rangeFacts, context) { var substitutions = _a.substitutions; var checker = context.program.getTypeChecker(); + // Make a unique name for the extracted variable var file = scope.getSourceFile(); var localNameText = ts.getUniqueName(ts.isClassLike(scope) ? "newProperty" : "newLocal", file); var isJS = ts.isInJavaScriptFile(scope); var variableType = isJS || !checker.isContextSensitive(node) ? undefined - : checker.typeToTypeNode(checker.getContextualType(node), scope, 1); + : checker.typeToTypeNode(checker.getContextualType(node), scope, 1 /* NoTruncation */); // TODO: GH#18217 var initializer = transformConstantInitializer(node, substitutions); ts.suppressLeadingAndTrailingTrivia(initializer); var changeTracker = ts.textChanges.ChangeTracker.fromContext(context); if (ts.isClassLike(scope)) { - ts.Debug.assert(!isJS); + ts.Debug.assert(!isJS); // See CannotExtractToJSClass var modifiers = []; - modifiers.push(ts.createToken(112)); + modifiers.push(ts.createToken(112 /* PrivateKeyword */)); if (rangeFacts & RangeFacts.InStaticRegion) { - modifiers.push(ts.createToken(115)); + modifiers.push(ts.createToken(115 /* StaticKeyword */)); } - modifiers.push(ts.createToken(132)); - var newVariable = ts.createProperty(undefined, modifiers, localNameText, undefined, variableType, initializer); + modifiers.push(ts.createToken(132 /* ReadonlyKeyword */)); + var newVariable = ts.createProperty( + /*decorators*/ undefined, modifiers, localNameText, + /*questionToken*/ undefined, variableType, initializer); var localReference = ts.createPropertyAccess(rangeFacts & RangeFacts.InStaticRegion - ? ts.createIdentifier(scope.name.getText()) + ? ts.createIdentifier(scope.name.getText()) // TODO: GH#18217 : ts.createThis(), ts.createIdentifier(localNameText)); + // Declare var maxInsertionPos = node.pos; var nodeToInsertBefore = getNodeToInsertPropertyBefore(maxInsertionPos, scope); - changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newVariable, true); + changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newVariable, /*blankLineBetween*/ true); + // Consume changeTracker.replaceNode(context.file, node, localReference); } else { var newVariableDeclaration = ts.createVariableDeclaration(localNameText, variableType, initializer); + // If the node is part of an initializer in a list of variable declarations, insert a new + // variable declaration into the list (in case it depends on earlier ones). + // CONSIDER: If the declaration list isn't const, we might want to split it into multiple + // lists so that the newly extracted one can be const. var oldVariableDeclaration = getContainingVariableDeclarationIfInList(node, scope); if (oldVariableDeclaration) { + // Declare + // CONSIDER: could detect that each is on a separate line (See `extractConstant_VariableList_MultipleLines` in `extractConstants.ts`) changeTracker.insertNodeBefore(context.file, oldVariableDeclaration, newVariableDeclaration); + // Consume var localReference = ts.createIdentifier(localNameText); changeTracker.replaceNode(context.file, node, localReference); } - else if (node.parent.kind === 216 && scope === ts.findAncestor(node, isScope)) { - var newVariableStatement = ts.createVariableStatement(undefined, ts.createVariableDeclarationList([newVariableDeclaration], 2)); + else if (node.parent.kind === 216 /* ExpressionStatement */ && scope === ts.findAncestor(node, isScope)) { + // If the parent is an expression statement and the target scope is the immediately enclosing one, + // replace the statement with the declaration. + var newVariableStatement = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([newVariableDeclaration], 2 /* Const */)); changeTracker.replaceNode(context.file, node.parent, newVariableStatement); } else { - var newVariableStatement = ts.createVariableStatement(undefined, ts.createVariableDeclarationList([newVariableDeclaration], 2)); + var newVariableStatement = ts.createVariableStatement( + /*modifiers*/ undefined, ts.createVariableDeclarationList([newVariableDeclaration], 2 /* Const */)); + // Declare var nodeToInsertBefore = getNodeToInsertConstantBefore(node, scope); if (nodeToInsertBefore.pos === 0) { - changeTracker.insertNodeAtTopOfFile(context.file, newVariableStatement, false); + changeTracker.insertNodeAtTopOfFile(context.file, newVariableStatement, /*blankLineBetween*/ false); } else { - changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newVariableStatement, false); + changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newVariableStatement, /*blankLineBetween*/ false); } - if (node.parent.kind === 216) { + // Consume + if (node.parent.kind === 216 /* ExpressionStatement */) { + // If the parent is an expression statement, delete it. changeTracker.deleteNode(context.file, node.parent, ts.textChanges.useNonAdjustedPositions); } else { @@ -89919,7 +107302,7 @@ var ts; } var edits = changeTracker.getChanges(); var renameFilename = node.getSourceFile().fileName; - var renameLocation = ts.getRenameLocation(edits, renameFilename, localNameText, true); + var renameLocation = ts.getRenameLocation(edits, renameFilename, localNameText, /*isDeclaredBeforeUse*/ true); return { renameFilename: renameFilename, renameLocation: renameLocation, edits: edits }; } function getContainingVariableDeclarationIfInList(node, scope) { @@ -89958,7 +107341,7 @@ var ts; function getCalledExpression(scope, range, functionNameText) { var functionReference = ts.createIdentifier(functionNameText); if (ts.isClassLike(scope)) { - var lhs = range.facts & RangeFacts.InStaticRegion ? ts.createIdentifier(scope.name.text) : ts.createThis(); + var lhs = range.facts & RangeFacts.InStaticRegion ? ts.createIdentifier(scope.name.text) : ts.createThis(); // TODO: GH#18217 return ts.createPropertyAccess(lhs, functionReference); } else { @@ -89968,14 +107351,18 @@ var ts; function transformFunctionBody(body, exposedVariableDeclarations, writes, substitutions, hasReturn) { var hasWritesOrVariableDeclarations = writes !== undefined || exposedVariableDeclarations.length > 0; if (ts.isBlock(body) && !hasWritesOrVariableDeclarations && substitutions.size === 0) { - return { body: ts.createBlock(body.statements, true), returnValueProperty: undefined }; + // already block, no declarations or writes to propagate back, no substitutions - can use node as is + return { body: ts.createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined }; } var returnValueProperty; var ignoreReturns = false; var statements = ts.createNodeArray(ts.isBlock(body) ? body.statements.slice(0) : [ts.isStatement(body) ? body : ts.createReturn(body)]); + // rewrite body if either there are writes that should be propagated back via return statements or there are substitutions if (hasWritesOrVariableDeclarations || substitutions.size) { var rewrittenStatements = ts.visitNodes(statements, visitor).slice(); if (hasWritesOrVariableDeclarations && !hasReturn && ts.isStatement(body)) { + // add return at the end to propagate writes back in case if control flow falls out of the function body + // it is ok to know that range has at least one return since it we only allow unconditional returns var assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes); if (assignments.length === 1) { rewrittenStatements.push(ts.createReturn(assignments[0].name)); @@ -89984,13 +107371,13 @@ var ts; rewrittenStatements.push(ts.createReturn(ts.createObjectLiteral(assignments))); } } - return { body: ts.createBlock(rewrittenStatements, true), returnValueProperty: returnValueProperty }; + return { body: ts.createBlock(rewrittenStatements, /*multiLine*/ true), returnValueProperty: returnValueProperty }; } else { - return { body: ts.createBlock(statements, true), returnValueProperty: undefined }; + return { body: ts.createBlock(statements, /*multiLine*/ true), returnValueProperty: undefined }; } function visitor(node) { - if (!ignoreReturns && node.kind === 225 && hasWritesOrVariableDeclarations) { + if (!ignoreReturns && node.kind === 225 /* ReturnStatement */ && hasWritesOrVariableDeclarations) { var assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes); if (node.expression) { if (!returnValueProperty) { @@ -90026,7 +107413,7 @@ var ts; } function getStatementsOrClassElements(scope) { if (ts.isFunctionLikeDeclaration(scope)) { - var body = scope.body; + var body = scope.body; // TODO: GH#18217 if (ts.isBlock(body)) { return body.statements; } @@ -90042,6 +107429,10 @@ var ts; } return ts.emptyArray; } + /** + * If `scope` contains a function after `minPos`, then return the first such function. + * Otherwise, return `undefined`. + */ function getNodeToInsertFunctionBefore(minPos, scope) { return ts.find(getStatementsOrClassElements(scope), function (child) { return child.pos >= minPos && ts.isFunctionLikeDeclaration(child) && !ts.isConstructorDeclaration(child); @@ -90049,7 +107440,7 @@ var ts; } function getNodeToInsertPropertyBefore(maxPos, scope) { var members = scope.members; - ts.Debug.assert(members.length > 0); + ts.Debug.assert(members.length > 0); // There must be at least one child, since we extracted from one. var prevMember; var allProperties = true; for (var _i = 0, members_7 = members; _i < members_7.length; _i++) { @@ -90058,6 +107449,8 @@ var ts; return prevMember || members[0]; } if (allProperties && !ts.isPropertyDeclaration(member)) { + // If it is non-vacuously true that all preceding members are properties, + // insert before the current member (i.e. at the end of the list of properties). if (prevMember !== undefined) { return member; } @@ -90066,7 +107459,7 @@ var ts; prevMember = member; } if (prevMember === undefined) - return ts.Debug.fail(); + return ts.Debug.fail(); // If the loop didn't return, then it did set prevMember. return prevMember; } function getNodeToInsertConstantBefore(node, scope) { @@ -90088,9 +107481,11 @@ var ts; prevStatement = statement; } if (!prevStatement && ts.isCaseClause(curr)) { + // We must have been in the expression of the case clause. ts.Debug.assert(ts.isSwitchStatement(curr.parent.parent)); return curr.parent.parent; } + // There must be at least one statement since we started in one. return ts.Debug.assertDefined(prevStatement); } ts.Debug.assert(curr !== scope, "Didn't encounter a block-like before encountering scope"); @@ -90099,6 +107494,7 @@ var ts; function getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes) { var variableAssignments = ts.map(exposedVariableDeclarations, function (v) { return ts.createShorthandPropertyAssignment(v.symbol.name); }); var writeAssignments = ts.map(writes, function (w) { return ts.createShorthandPropertyAssignment(w.symbol.name); }); + // TODO: GH#18217 `variableAssignments` not possibly undefined! return variableAssignments === undefined ? writeAssignments : writeAssignments === undefined @@ -90108,6 +107504,15 @@ var ts; function isReadonlyArray(v) { return ts.isArray(v); } + /** + * Produces a range that spans the entirety of nodes, given a selection + * that might start/end in the middle of nodes. + * + * For example, when the user makes a selection like this + * v---v + * var someThing = foo + bar; + * this returns ^-------^ + */ function getEnclosingTextRange(targetRange, sourceFile) { return isReadonlyArray(targetRange.range) ? { pos: ts.first(targetRange.range).getStart(sourceFile), end: ts.last(targetRange.range).getEnd() } @@ -90115,17 +107520,19 @@ var ts; } var Usage; (function (Usage) { + // value should be passed to extracted method Usage[Usage["Read"] = 1] = "Read"; + // value should be passed to extracted method and propagated back Usage[Usage["Write"] = 2] = "Write"; })(Usage || (Usage = {})); function collectReadsAndWrites(targetRange, scopes, enclosingTextRange, sourceFile, checker, cancellationToken) { - var allTypeParameterUsages = ts.createMap(); + var allTypeParameterUsages = ts.createMap(); // Key is type ID var usagesPerScope = []; var substitutionsPerScope = []; var functionErrorsPerScope = []; var constantErrorsPerScope = []; var visibleDeclarationsInExtractedRange = []; - var exposedVariableSymbolSet = ts.createMap(); + var exposedVariableSymbolSet = ts.createMap(); // Key is symbol ID var exposedVariableDeclarations = []; var firstExposedNonVariableDeclaration; var expression = !isReadonlyArray(targetRange.range) @@ -90140,14 +107547,15 @@ var ts; var end = ts.last(statements).end; expressionDiagnostic = ts.createFileDiagnostic(sourceFile, start, end - start, Messages.expressionExpected); } - else if (checker.getTypeAtLocation(expression).flags & (4096 | 32768)) { + else if (checker.getTypeAtLocation(expression).flags & (4096 /* Void */ | 32768 /* Never */)) { // TODO: GH#18217 expressionDiagnostic = ts.createDiagnosticForNode(expression, Messages.uselessConstantType); } + // initialize results for (var _i = 0, scopes_1 = scopes; _i < scopes_1.length; _i++) { var scope = scopes_1[_i]; usagesPerScope.push({ usages: ts.createMap(), typeParameterUsages: ts.createMap(), substitutions: ts.createMap() }); substitutionsPerScope.push(ts.createMap()); - functionErrorsPerScope.push(ts.isFunctionLikeDeclaration(scope) && scope.kind !== 234 + functionErrorsPerScope.push(ts.isFunctionLikeDeclaration(scope) && scope.kind !== 234 /* FunctionDeclaration */ ? [ts.createDiagnosticForNode(scope, Messages.cannotExtractToOtherFunctionLike)] : []); var constantErrors = []; @@ -90158,6 +107566,7 @@ var ts; constantErrors.push(ts.createDiagnosticForNode(scope, Messages.cannotExtractToJSClass)); } if (ts.isArrowFunction(scope) && !ts.isBlock(scope.body)) { + // TODO (https://github.com/Microsoft/TypeScript/issues/18924): allow this constantErrors.push(ts.createDiagnosticForNode(scope, Messages.cannotExtractToExpressionArrowFunction)); } constantErrorsPerScope.push(constantErrors); @@ -90167,20 +107576,25 @@ var ts; var unmodifiedNode = isReadonlyArray(targetRange.range) ? ts.first(targetRange.range) : targetRange.range; var inGenericContext = isInGenericContext(unmodifiedNode); collectUsages(target); + // Unfortunately, this code takes advantage of the knowledge that the generated method + // will use the contextual type of an expression as the return type of the extracted + // method (and will therefore "use" all the types involved). if (inGenericContext && !isReadonlyArray(targetRange.range)) { - var contextualType = checker.getContextualType(targetRange.range); + var contextualType = checker.getContextualType(targetRange.range); // TODO: GH#18217 recordTypeParameterUsages(contextualType); } if (allTypeParameterUsages.size > 0) { - var seenTypeParameterUsages = ts.createMap(); + var seenTypeParameterUsages = ts.createMap(); // Key is type ID var i_1 = 0; for (var curr = unmodifiedNode; curr !== undefined && i_1 < scopes.length; curr = curr.parent) { if (curr === scopes[i_1]) { + // Copy current contents of seenTypeParameterUsages into scope. seenTypeParameterUsages.forEach(function (typeParameter, id) { usagesPerScope[i_1].typeParameterUsages.set(id, typeParameter); }); i_1++; } + // Note that we add the current node's type parameters *after* updating the corresponding scope. if (ts.isDeclarationWithTypeParameters(curr)) { for (var _a = 0, _b = ts.getEffectiveTypeParameterDeclarations(curr); _a < _b.length; _a++) { var typeParameterDecl = _b[_a]; @@ -90191,8 +107605,13 @@ var ts; } } } + // If we didn't get through all the scopes, then there were some that weren't in our + // parent chain (impossible at time of writing). A conservative solution would be to + // copy allTypeParameterUsages into all remaining scopes. ts.Debug.assert(i_1 === scopes.length); } + // If there are any declarations in the extracted block that are used in the same enclosing + // lexical scope, we can't move the extraction "up" as those declarations will become unreachable if (visibleDeclarationsInExtractedRange.length) { var containingLexicalScopeOfExtraction = ts.isBlockScope(scopes[0], scopes[0].parent) ? scopes[0] @@ -90201,6 +107620,9 @@ var ts; } var _loop_24 = function (i) { var scopeUsages = usagesPerScope[i]; + // Special case: in the innermost scope, all usages are available. + // (The computed value reflects the value at the top-level of the scope, but the + // local will actually be declared at the same level as the extracted expression). if (i > 0 && (scopeUsages.usages.size > 0 || scopeUsages.typeParameterUsages.size > 0)) { var errorNode = isReadonlyArray(targetRange.range) ? targetRange.range[0] : targetRange.range; constantErrorsPerScope[i].push(ts.createDiagnosticForNode(errorNode, Messages.cannotAccessVariablesFromNestedScopes)); @@ -90208,15 +107630,16 @@ var ts; var hasWrite = false; var readonlyClassPropertyWrite; usagesPerScope[i].usages.forEach(function (value) { - if (value.usage === 2) { + if (value.usage === 2 /* Write */) { hasWrite = true; - if (value.symbol.flags & 106500 && + if (value.symbol.flags & 106500 /* ClassMember */ && value.symbol.valueDeclaration && - ts.hasModifier(value.symbol.valueDeclaration, 64)) { + ts.hasModifier(value.symbol.valueDeclaration, 64 /* Readonly */)) { readonlyClassPropertyWrite = value.symbol.valueDeclaration; } } }); + // If an expression was extracted, then there shouldn't have been any variable declarations. ts.Debug.assert(isReadonlyArray(targetRange.range) || exposedVariableDeclarations.length === 0); if (hasWrite && !isReadonlyArray(targetRange.range)) { var diag = ts.createDiagnosticForNode(targetRange.range, Messages.cannotWriteInExpression); @@ -90242,6 +107665,9 @@ var ts; return !!ts.findAncestor(node, function (n) { return ts.isDeclarationWithTypeParameters(n) && ts.getEffectiveTypeParameterDeclarations(n).length !== 0; }); } function recordTypeParameterUsages(type) { + // PERF: This is potentially very expensive. `type` could be a library type with + // a lot of properties, each of which the walker will visit. Unfortunately, the + // solution isn't as trivial as filtering to user types because of (e.g.) Array. var symbolWalker = checker.getSymbolWalker(function () { return (cancellationToken.throwIfCancellationRequested(), true); }); var visitedTypes = symbolWalker.walkType(type).visitedTypes; for (var _i = 0, visitedTypes_1 = visitedTypes; _i < visitedTypes_1.length; _i++) { @@ -90252,22 +107678,24 @@ var ts; } } function collectUsages(node, valueUsage) { - if (valueUsage === void 0) { valueUsage = 1; } + if (valueUsage === void 0) { valueUsage = 1 /* Read */; } if (inGenericContext) { - var type = checker.getTypeAtLocation(node); + var type = checker.getTypeAtLocation(node); // TODO: GH#18217 recordTypeParameterUsages(type); } if (ts.isDeclaration(node) && node.symbol) { visibleDeclarationsInExtractedRange.push(node); } if (ts.isAssignmentExpression(node)) { - collectUsages(node.left, 2); + // use 'write' as default usage for values + collectUsages(node.left, 2 /* Write */); collectUsages(node.right); } else if (ts.isUnaryExpressionWithWrite(node)) { - collectUsages(node.operand, 2); + collectUsages(node.operand, 2 /* Write */); } else if (ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node)) { + // use 'write' as default usage for values ts.forEachChild(node, collectUsages); } else if (ts.isIdentifier(node)) { @@ -90280,7 +107708,7 @@ var ts; if (ts.isPropertyAccessExpression(node.parent) && node !== node.parent.expression) { return; } - recordUsage(node, valueUsage, ts.isPartOfTypeNode(node)); + recordUsage(node, valueUsage, /*isTypeNode*/ ts.isPartOfTypeNode(node)); } else { ts.forEachChild(node, collectUsages); @@ -90290,6 +107718,7 @@ var ts; var symbolId = recordUsagebySymbol(n, usage, isTypeNode); if (symbolId) { for (var i = 0; i < scopes.length; i++) { + // push substitution from map to map to simplify rewriting var substitution = substitutionsPerScope[i].get(symbolId); if (substitution) { usagesPerScope[i].substitutions.set(ts.getNodeId(n).toString(), substitution); @@ -90300,15 +107729,24 @@ var ts; function recordUsagebySymbol(identifier, usage, isTypeName) { var symbol = getSymbolReferencedByIdentifier(identifier); if (!symbol) { + // cannot find symbol - do nothing return undefined; } var symbolId = ts.getSymbolId(symbol).toString(); var lastUsage = seenUsages.get(symbolId); + // there are two kinds of value usages + // - reads - if range contains a read from the value located outside of the range then value should be passed as a parameter + // - writes - if range contains a write to a value located outside the range the value should be passed as a parameter and + // returned as a return value + // 'write' case is a superset of 'read' so if we already have processed 'write' of some symbol there is not need to handle 'read' + // since all information is already recorded if (lastUsage && lastUsage >= usage) { return symbolId; } seenUsages.set(symbolId, usage); if (lastUsage) { + // if we get here this means that we are trying to handle 'write' and 'read' was already processed + // walk scopes and update existing records. for (var _i = 0, usagesPerScope_1 = usagesPerScope; _i < usagesPerScope_1.length; _i++) { var perScope = usagesPerScope_1[_i]; var prevEntry = perScope.usages.get(identifier.text); @@ -90318,15 +107756,19 @@ var ts; } return symbolId; } + // find first declaration in this file var decls = symbol.getDeclarations(); var declInFile = decls && ts.find(decls, function (d) { return d.getSourceFile() === sourceFile; }); if (!declInFile) { return undefined; } if (ts.rangeContainsStartEnd(enclosingTextRange, declInFile.getStart(), declInFile.end)) { + // declaration is located in range to be extracted - do nothing return undefined; } - if (targetRange.facts & RangeFacts.IsGenerator && usage === 2) { + if (targetRange.facts & RangeFacts.IsGenerator && usage === 2 /* Write */) { + // this is write to a reference located outside of the target scope and range is extracted into generator + // currently this is unsupported scenario var diag = ts.createDiagnosticForNode(identifier, Messages.cannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators); for (var _a = 0, functionErrorsPerScope_1 = functionErrorsPerScope; _a < functionErrorsPerScope_1.length; _a++) { var errors = functionErrorsPerScope_1[_a]; @@ -90339,7 +107781,7 @@ var ts; } for (var i = 0; i < scopes.length; i++) { var scope = scopes[i]; - var resolvedSymbol = checker.resolveName(symbol.name, scope, symbol.flags, false); + var resolvedSymbol = checker.resolveName(symbol.name, scope, symbol.flags, /*excludeGlobals*/ false); if (resolvedSymbol === symbol) { continue; } @@ -90349,7 +107791,9 @@ var ts; substitutionsPerScope[i].set(symbolId, substitution); } else if (isTypeName) { - if (!(symbol.flags & 262144)) { + // If the symbol is a type parameter that won't be in scope, we'll pass it as a type argument + // so there's no problem. + if (!(symbol.flags & 262144 /* TypeParameter */)) { var diag = ts.createDiagnosticForNode(identifier, Messages.typeWillNotBeVisibleInTheNewScope); functionErrorsPerScope[i].push(diag); constantErrorsPerScope[i].push(diag); @@ -90363,9 +107807,11 @@ var ts; return symbolId; } function checkForUsedDeclarations(node) { + // If this node is entirely within the original extraction range, we don't need to do anything. if (node === targetRange.range || (isReadonlyArray(targetRange.range) && targetRange.range.indexOf(node) >= 0)) { return; } + // Otherwise check and recurse. var sym = ts.isIdentifier(node) ? getSymbolReferencedByIdentifier(node) : checker.getSymbolAtLocation(node); @@ -90380,13 +107826,20 @@ var ts; } } else { + // CONSIDER: this includes binding elements, which we could + // expose in the same way as variables. firstExposedNonVariableDeclaration = firstExposedNonVariableDeclaration || decl; } } } ts.forEachChild(node, checkForUsedDeclarations); } + /** + * Return the symbol referenced by an identifier (even if it declares a different symbol). + */ function getSymbolReferencedByIdentifier(identifier) { + // If the identifier is both a property name and its value, we're only interested in its value + // (since the name is a declaration and will be included in the extracted range). return identifier.parent && ts.isShorthandPropertyAssignment(identifier.parent) && identifier.parent.name === identifier ? checker.getShorthandAssignmentValueSymbol(identifier.parent) : checker.getSymbolAtLocation(identifier); @@ -90408,33 +107861,40 @@ var ts; : ts.createPropertyAccess(prefix, symbol.name); } } + /** + * Computes whether or not a node represents an expression in a position where it could + * be extracted. + * The isExpression() in utilities.ts returns some false positives we need to handle, + * such as `import x from 'y'` -- the 'y' is a StringLiteral but is *not* an expression + * in the sense of something that you could extract on + */ function isExtractableExpression(node) { var parent = node.parent; switch (parent.kind) { - case 273: + case 273 /* EnumMember */: return false; } switch (node.kind) { - case 9: - return parent.kind !== 244 && - parent.kind !== 248; - case 204: - case 180: - case 182: + case 9 /* StringLiteral */: + return parent.kind !== 244 /* ImportDeclaration */ && + parent.kind !== 248 /* ImportSpecifier */; + case 204 /* SpreadElement */: + case 180 /* ObjectBindingPattern */: + case 182 /* BindingElement */: return false; - case 71: - return parent.kind !== 182 && - parent.kind !== 248 && - parent.kind !== 252; + case 71 /* Identifier */: + return parent.kind !== 182 /* BindingElement */ && + parent.kind !== 248 /* ImportSpecifier */ && + parent.kind !== 252 /* ExportSpecifier */; } return true; } function isBlockLike(node) { switch (node.kind) { - case 213: - case 274: - case 240: - case 266: + case 213 /* Block */: + case 274 /* SourceFile */: + case 240 /* ModuleBlock */: + case 266 /* CaseClause */: return true; default: return false; @@ -90443,6 +107903,7 @@ var ts; })(extractSymbol = refactor.extractSymbol || (refactor.extractSymbol = {})); })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var refactor; @@ -90479,18 +107940,20 @@ var ts; ts.suppressLeadingAndTrailingTrivia(declaration); ts.suppressLeadingAndTrailingTrivia(container); var isInClassLike = ts.isClassLike(container); - var modifierFlags = ts.getModifierFlags(declaration) & ~64; + // avoid Readonly modifier because it will convert to get accessor + var modifierFlags = ts.getModifierFlags(declaration) & ~64 /* Readonly */; var accessorModifiers = isInClassLike - ? !modifierFlags || modifierFlags & 8 - ? getModifiers(isJS, isStatic, 114) + ? !modifierFlags || modifierFlags & 8 /* Private */ + ? getModifiers(isJS, isStatic, 114 /* PublicKeyword */) : ts.createNodeArray(ts.createModifiersFromModifierFlags(modifierFlags)) : undefined; - var fieldModifiers = isInClassLike ? getModifiers(isJS, isStatic, 112) : undefined; + var fieldModifiers = isInClassLike ? getModifiers(isJS, isStatic, 112 /* PrivateKeyword */) : undefined; updateFieldDeclaration(changeTracker, file, declaration, fieldName, fieldModifiers); var getAccessor = generateGetAccessor(fieldName, accessorName, type, accessorModifiers, isStatic, container); ts.suppressLeadingAndTrailingTrivia(getAccessor); insertAccessor(changeTracker, file, getAccessor, declaration, container); if (isReadonly) { + // readonly modifier only existed in classLikeDeclaration var constructor = ts.getFirstConstructorWithBody(container); if (constructor) { updateReadonlyPropertyInitializerStatementConstructor(changeTracker, context, constructor, fieldName, originalName); @@ -90505,7 +107968,7 @@ var ts; var renameFilename = file.fileName; var nameNeedRename = renameAccessor ? accessorName : fieldName; var renameLocationOffset = ts.isIdentifier(nameNeedRename) ? 0 : -1; - var renameLocation = renameLocationOffset + ts.getRenameLocation(edits, renameFilename, nameNeedRename.text, ts.isParameter(declaration)); + var renameLocation = renameLocationOffset + ts.getRenameLocation(edits, renameFilename, nameNeedRename.text, /*preferLastLocation*/ ts.isParameter(declaration)); return { renameFilename: renameFilename, renameLocation: renameLocation, edits: edits }; } function isConvertibleName(name) { @@ -90518,22 +107981,23 @@ var ts; return ts.isIdentifier(originalName) ? ts.createIdentifier(name) : ts.createLiteral(name); } function createAccessorAccessExpression(fieldName, isStatic, container) { - var leftHead = isStatic ? container.name : ts.createThis(); + var leftHead = isStatic ? container.name : ts.createThis(); // TODO: GH#18217 return ts.isIdentifier(fieldName) ? ts.createPropertyAccess(leftHead, fieldName) : ts.createElementAccess(leftHead, ts.createLiteral(fieldName)); } function getModifiers(isJS, isStatic, accessModifier) { - var modifiers = ts.append(!isJS ? [ts.createToken(accessModifier)] : undefined, isStatic ? ts.createToken(115) : undefined); + var modifiers = ts.append(!isJS ? [ts.createToken(accessModifier)] : undefined, isStatic ? ts.createToken(115 /* StaticKeyword */) : undefined); return modifiers && ts.createNodeArray(modifiers); } function startsWithUnderscore(name) { - return name.charCodeAt(0) === 95; + return name.charCodeAt(0) === 95 /* _ */; } function getConvertibleFieldAtPosition(context, file) { var startPosition = context.startPosition, endPosition = context.endPosition; - var node = ts.getTokenAtPosition(file, startPosition, false); + var node = ts.getTokenAtPosition(file, startPosition, /*includeJsDocComment*/ false); var declaration = ts.findAncestor(node.parent, isAcceptedDeclaration); - var meaning = 28 | 32 | 64; - if (!declaration || !ts.rangeOverlapsWithStartEnd(declaration.name, startPosition, endPosition) + // make sure declaration have AccessibilityModifier or Static Modifier or Readonly Modifier + var meaning = 28 /* AccessibilityModifier */ | 32 /* Static */ | 64 /* Readonly */; + if (!declaration || !ts.rangeOverlapsWithStartEnd(declaration.name, startPosition, endPosition) // TODO: GH#18217 || !isConvertibleName(declaration.name) || (ts.getModifierFlags(declaration) | meaning) !== meaning) return undefined; var name = declaration.name.text; @@ -90544,7 +108008,7 @@ var ts; isStatic: ts.hasStaticModifier(declaration), isReadonly: ts.hasReadonlyModifier(declaration), type: ts.getTypeAnnotationNode(declaration), - container: declaration.kind === 149 ? declaration.parent.parent : declaration.parent, + container: declaration.kind === 149 /* Parameter */ ? declaration.parent.parent : declaration.parent, originalName: declaration.name, declaration: declaration, fieldName: fieldName, @@ -90553,14 +108017,22 @@ var ts; }; } function generateGetAccessor(fieldName, accessorName, type, modifiers, isStatic, container) { - return ts.createGetAccessor(undefined, modifiers, accessorName, undefined, type, ts.createBlock([ + return ts.createGetAccessor( + /*decorators*/ undefined, modifiers, accessorName, + /*parameters*/ undefined, // TODO: GH#18217 + type, ts.createBlock([ ts.createReturn(createAccessorAccessExpression(fieldName, isStatic, container)) - ], true)); + ], /*multiLine*/ true)); } function generateSetAccessor(fieldName, accessorName, type, modifiers, isStatic, container) { - return ts.createSetAccessor(undefined, modifiers, accessorName, [ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), undefined, type)], ts.createBlock([ + return ts.createSetAccessor( + /*decorators*/ undefined, modifiers, accessorName, [ts.createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, ts.createIdentifier("value"), + /*questionToken*/ undefined, type)], ts.createBlock([ ts.createStatement(ts.createAssignment(createAccessorAccessExpression(fieldName, isStatic, container), ts.createIdentifier("value"))) - ], true)); + ], /*multiLine*/ true)); } function updatePropertyDeclaration(changeTracker, file, declaration, fieldName, modifiers) { var property = ts.updateProperty(declaration, declaration.decorators, modifiers, fieldName, declaration.questionToken || declaration.exclamationToken, declaration.type, declaration.initializer); @@ -90609,6 +108081,7 @@ var ts; })(generateGetAccessorAndSetAccessor = refactor.generateGetAccessorAndSetAccessor || (refactor.generateGetAccessorAndSetAccessor = {})); })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var refactor; @@ -90639,9 +108112,11 @@ var ts; if (ts.isNamedDeclaration(startStatement) && startStatement.name && ts.rangeContainsRange(startStatement.name, range)) { return { toMove: [statements[startNodeIndex]], afterLast: statements[startNodeIndex + 1] }; } + // Can't only partially include the start node or be partially into the next node if (range.pos > startStatement.getStart(file)) return undefined; var afterEndNodeIndex = ts.findIndex(statements, function (s) { return s.end > range.end; }, startNodeIndex); + // Can't be partially into the next node if (afterEndNodeIndex !== -1 && (afterEndNodeIndex === 0 || statements[afterEndNodeIndex].getStart(file) < range.end)) return undefined; return { @@ -90656,9 +108131,11 @@ var ts; var extension = ts.extensionFromPath(oldFile.fileName); var newModuleName = makeUniqueModuleName(getNewModuleName(usage.movedSymbols), extension, currentDirectory, host); var newFileNameWithExtension = newModuleName + extension; + // If previous file was global, this is easy. changes.createNewFile(oldFile, ts.combinePaths(currentDirectory, newFileNameWithExtension), getNewStatementsAndRemoveFromOldFile(oldFile, usage, changes, toMove, program, newModuleName, preferences)); addNewFileToTsconfig(program, changes, oldFile.fileName, newFileNameWithExtension, ts.hostGetCanonicalFileName(host)); } + // Filters imports out of the range of statements to move. Imports will be copied to the new file anyway, and may still be needed in the old file. function getStatementsToMove(context) { var rangeToMove = getRangeToMove(context); if (rangeToMove === undefined) @@ -90675,12 +108152,12 @@ var ts; } function isPureImport(node) { switch (node.kind) { - case 244: + case 244 /* ImportDeclaration */: return true; - case 243: - return !ts.hasModifier(node, 1); - case 214: - return node.declarationList.declarations.every(function (d) { return !!d.initializer && ts.isRequireCall(d.initializer, true); }); + case 243 /* ImportEqualsDeclaration */: + return !ts.hasModifier(node, 1 /* Export */); + case 214 /* VariableStatement */: + return node.declarationList.declarations.every(function (d) { return !!d.initializer && ts.isRequireCall(d.initializer, /*checkArgumentIsStringLiteralLike*/ true); }); default: return false; } @@ -90742,10 +108219,10 @@ var ts; var shouldMove = function (name) { var symbol = ts.isBindingElement(name.parent) ? ts.getPropertySymbolFromBindingElement(checker, name.parent) - : ts.skipAlias(checker.getSymbolAtLocation(name), checker); + : ts.skipAlias(checker.getSymbolAtLocation(name), checker); // TODO: GH#18217 return !!symbol && movedSymbols.has(symbol); }; - deleteUnusedImports(sourceFile, importNode, changes, shouldMove); + deleteUnusedImports(sourceFile, importNode, changes, shouldMove); // These will be changed to imports from the new file var newModuleSpecifier = ts.combinePaths(ts.getDirectoryPath(moduleSpecifierFromImport(importNode).text), newModuleName); var newImportDeclaration = filterImport(importNode, ts.createLiteral(newModuleSpecifier), shouldMove); if (newImportDeclaration) @@ -90767,25 +108244,25 @@ var ts; } function getNamespaceLikeImport(node) { switch (node.kind) { - case 244: - return node.importClause && node.importClause.namedBindings && node.importClause.namedBindings.kind === 246 ? + case 244 /* ImportDeclaration */: + return node.importClause && node.importClause.namedBindings && node.importClause.namedBindings.kind === 246 /* NamespaceImport */ ? node.importClause.namedBindings.name : undefined; - case 243: + case 243 /* ImportEqualsDeclaration */: return node.name; - case 232: + case 232 /* VariableDeclaration */: return ts.tryCast(node.name, ts.isIdentifier); default: return ts.Debug.assertNever(node); } } function updateNamespaceLikeImport(changes, sourceFile, checker, movedSymbols, newModuleName, newModuleSpecifier, oldImportId, oldImportNode) { - var preferredNewNamespaceName = ts.codefix.moduleSpecifierToValidIdentifier(newModuleName, 6); + var preferredNewNamespaceName = ts.codefix.moduleSpecifierToValidIdentifier(newModuleName, 6 /* ESNext */); var needUniqueName = false; var toChange = []; ts.FindAllReferences.Core.eachSymbolReferenceInFile(oldImportId, checker, sourceFile, function (ref) { if (!ts.isPropertyAccessExpression(ref.parent)) return; - needUniqueName = needUniqueName || !!checker.resolveName(preferredNewNamespaceName, ref, 67108863, true); + needUniqueName = needUniqueName || !!checker.resolveName(preferredNewNamespaceName, ref, 67108863 /* All */, /*excludeGlobals*/ true); if (movedSymbols.has(checker.getSymbolAtLocation(ref.parent.name))) { toChange.push(ref); } @@ -90803,19 +108280,20 @@ var ts; var newNamespaceId = ts.createIdentifier(newNamespaceName); var newModuleString = ts.createLiteral(newModuleSpecifier); switch (node.kind) { - case 244: - return ts.createImportDeclaration(undefined, undefined, ts.createImportClause(undefined, ts.createNamespaceImport(newNamespaceId)), newModuleString); - case 243: - return ts.createImportEqualsDeclaration(undefined, undefined, newNamespaceId, ts.createExternalModuleReference(newModuleString)); - case 232: - return ts.createVariableDeclaration(newNamespaceId, undefined, createRequireCall(newModuleString)); + case 244 /* ImportDeclaration */: + return ts.createImportDeclaration( + /*decorators*/ undefined, /*modifiers*/ undefined, ts.createImportClause(/*name*/ undefined, ts.createNamespaceImport(newNamespaceId)), newModuleString); + case 243 /* ImportEqualsDeclaration */: + return ts.createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, newNamespaceId, ts.createExternalModuleReference(newModuleString)); + case 232 /* VariableDeclaration */: + return ts.createVariableDeclaration(newNamespaceId, /*type*/ undefined, createRequireCall(newModuleString)); default: return ts.Debug.assertNever(node); } } function moduleSpecifierFromImport(i) { - return (i.kind === 244 ? i.moduleSpecifier - : i.kind === 243 ? i.moduleReference.expression + return (i.kind === 244 /* ImportDeclaration */ ? i.moduleSpecifier + : i.kind === 243 /* ImportEqualsDeclaration */ ? i.moduleReference.expression : i.initializer.arguments[0]); } function forEachImportInStatement(statement, cb) { @@ -90831,7 +108309,7 @@ var ts; else if (ts.isVariableStatement(statement)) { for (var _i = 0, _a = statement.declarationList.declarations; _i < _a.length; _i++) { var decl = _a[_i]; - if (decl.initializer && ts.isRequireCall(decl.initializer, true)) { + if (decl.initializer && ts.isRequireCall(decl.initializer, /*checkArgumentIsStringLiteralLike*/ true)) { cb(decl); } } @@ -90841,8 +108319,8 @@ var ts; var defaultImport; var imports = []; newFileNeedExport.forEach(function (symbol) { - if (symbol.escapedName === "default") { - defaultImport = ts.createIdentifier(ts.symbolNameNoDefault(symbol)); + if (symbol.escapedName === "default" /* Default */) { + defaultImport = ts.createIdentifier(ts.symbolNameNoDefault(symbol)); // TODO: GH#18217 } else { imports.push(symbol.name); @@ -90853,23 +108331,23 @@ var ts; function makeImportOrRequire(defaultImport, imports, path, useEs6Imports, quotePreference) { path = ts.ensurePathIsNonModuleName(path); if (useEs6Imports) { - var specifiers = imports.map(function (i) { return ts.createImportSpecifier(undefined, ts.createIdentifier(i)); }); + var specifiers = imports.map(function (i) { return ts.createImportSpecifier(/*propertyName*/ undefined, ts.createIdentifier(i)); }); return ts.makeImportIfNecessary(defaultImport, specifiers, path, quotePreference); } else { - ts.Debug.assert(!defaultImport); - var bindingElements = imports.map(function (i) { return ts.createBindingElement(undefined, undefined, i); }); + ts.Debug.assert(!defaultImport); // If there's a default export, it should have been an es6 module. + var bindingElements = imports.map(function (i) { return ts.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, i); }); return bindingElements.length - ? makeVariableStatement(ts.createObjectBindingPattern(bindingElements), undefined, createRequireCall(ts.createLiteral(path))) + ? makeVariableStatement(ts.createObjectBindingPattern(bindingElements), /*type*/ undefined, createRequireCall(ts.createLiteral(path))) : undefined; } } function makeVariableStatement(name, type, initializer, flags) { - if (flags === void 0) { flags = 2; } - return ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(name, type, initializer)], flags)); + if (flags === void 0) { flags = 2 /* Const */; } + return ts.createVariableStatement(/*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(name, type, initializer)], flags)); } function createRequireCall(moduleSpecifier) { - return ts.createCall(ts.createIdentifier("require"), undefined, [moduleSpecifier]); + return ts.createCall(ts.createIdentifier("require"), /*typeArguments*/ undefined, [moduleSpecifier]); } function addExports(sourceFile, toMove, needExport, useEs6Exports) { return ts.flatMap(toMove, function (statement) { @@ -90885,15 +108363,15 @@ var ts; } function deleteUnusedImports(sourceFile, importDecl, changes, isUnused) { switch (importDecl.kind) { - case 244: + case 244 /* ImportDeclaration */: deleteUnusedImportsInDeclaration(sourceFile, importDecl, changes, isUnused); break; - case 243: + case 243 /* ImportEqualsDeclaration */: if (isUnused(importDecl.name)) { changes.deleteNode(sourceFile, importDecl); } break; - case 232: + case 232 /* VariableDeclaration */: deleteUnusedImportsInVariableDeclaration(sourceFile, importDecl, changes, isUnused); break; default: @@ -90906,7 +108384,7 @@ var ts; var _a = importDecl.importClause, name = _a.name, namedBindings = _a.namedBindings; var defaultUnused = !name || isUnused(name); var namedBindingsUnused = !namedBindings || - (namedBindings.kind === 246 ? isUnused(namedBindings.name) : namedBindings.elements.every(function (e) { return isUnused(e.name); })); + (namedBindings.kind === 246 /* NamespaceImport */ ? isUnused(namedBindings.name) : namedBindings.elements.every(function (e) { return isUnused(e.name); })); if (defaultUnused && namedBindingsUnused) { changes.deleteNode(sourceFile, importDecl); } @@ -90918,7 +108396,7 @@ var ts; if (namedBindingsUnused) { changes.deleteNode(sourceFile, namedBindings); } - else if (namedBindings.kind === 247) { + else if (namedBindings.kind === 247 /* NamedImports */) { for (var _i = 0, _b = namedBindings.elements; _i < _b.length; _i++) { var element = _b[_i]; if (isUnused(element.name)) @@ -90931,14 +108409,14 @@ var ts; function deleteUnusedImportsInVariableDeclaration(sourceFile, varDecl, changes, isUnused) { var name = varDecl.name; switch (name.kind) { - case 71: + case 71 /* Identifier */: if (isUnused(name)) { changes.deleteNode(sourceFile, name); } break; - case 181: + case 181 /* ArrayBindingPattern */: break; - case 180: + case 180 /* ObjectBindingPattern */: if (name.elements.every(function (e) { return ts.isIdentifier(e.name) && isUnused(e.name); })) { changes.deleteNode(sourceFile, ts.isVariableDeclarationList(varDecl.parent) && varDecl.parent.declarations.length === 1 ? varDecl.parent.parent : varDecl); } @@ -90961,9 +108439,10 @@ var ts; ts.append(copiedOldImports, filterImport(i, moduleSpecifierFromImport(i), function (name) { return importsToCopy.has(checker.getSymbolAtLocation(name)); })); }); } + // Also, import things used from the old file, and insert 'export' modifiers as necessary in the old file. var oldFileDefault; var oldFileNamedImports = []; - var markSeenTop = ts.nodeSeenTracker(); + var markSeenTop = ts.nodeSeenTracker(); // Needed because multiple declarations may appear in `const x = 0, y = 1;`. newFileImportsFromOldFile.forEach(function (symbol) { for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var decl = _a[_i]; @@ -90976,7 +108455,7 @@ var ts; if (markSeenTop(top)) { addExportToChanges(oldFile, top, changes, useEs6ModuleSyntax); } - if (ts.hasModifier(decl, 512)) { + if (ts.hasModifier(decl, 512 /* Default */)) { oldFileDefault = name; } else { @@ -90992,7 +108471,7 @@ var ts; for (var i = 1;; i++) { var name = ts.combinePaths(inDirectory, newModuleName + extension); if (!host.fileExists(name)) - return newModuleName; + return newModuleName; // TODO: GH#18217 newModuleName = moduleName + "." + i; } } @@ -91039,15 +108518,16 @@ var ts; } return { movedSymbols: movedSymbols, newFileImportsFromOldFile: newFileImportsFromOldFile, oldFileImportsFromNewFile: oldFileImportsFromNewFile, oldImportsNeededByNewFile: oldImportsNeededByNewFile, unusedImportsFromOldFile: unusedImportsFromOldFile }; } + // Below should all be utilities function isInImport(decl) { switch (decl.kind) { - case 243: - case 248: - case 245: + case 243 /* ImportEqualsDeclaration */: + case 248 /* ImportSpecifier */: + case 245 /* ImportClause */: return true; - case 232: + case 232 /* VariableDeclaration */: return isVariableDeclarationInImport(decl); - case 182: + case 182 /* BindingElement */: return ts.isVariableDeclaration(decl.parent.parent) && isVariableDeclarationInImport(decl.parent.parent); default: return false; @@ -91055,23 +108535,23 @@ var ts; } function isVariableDeclarationInImport(decl) { return ts.isSourceFile(decl.parent.parent.parent) && - decl.initializer && ts.isRequireCall(decl.initializer, true); + decl.initializer && ts.isRequireCall(decl.initializer, /*checkArgumentIsStringLiteralLike*/ true); } function filterImport(i, moduleSpecifier, keep) { switch (i.kind) { - case 244: { + case 244 /* ImportDeclaration */: { var clause = i.importClause; if (!clause) return undefined; var defaultImport = clause.name && keep(clause.name) ? clause.name : undefined; var namedBindings = clause.namedBindings && filterNamedBindings(clause.namedBindings, keep); return defaultImport || namedBindings - ? ts.createImportDeclaration(undefined, undefined, ts.createImportClause(defaultImport, namedBindings), moduleSpecifier) + ? ts.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, ts.createImportClause(defaultImport, namedBindings), moduleSpecifier) : undefined; } - case 243: + case 243 /* ImportEqualsDeclaration */: return keep(i.name) ? i : undefined; - case 232: { + case 232 /* VariableDeclaration */: { var name = filterBindingName(i.name, keep); return name ? makeVariableStatement(name, i.type, createRequireCall(moduleSpecifier), i.parent.flags) : undefined; } @@ -91080,7 +108560,7 @@ var ts; } } function filterNamedBindings(namedBindings, keep) { - if (namedBindings.kind === 246) { + if (namedBindings.kind === 246 /* NamespaceImport */) { return keep(namedBindings.name) ? namedBindings : undefined; } else { @@ -91090,11 +108570,12 @@ var ts; } function filterBindingName(name, keep) { switch (name.kind) { - case 71: + case 71 /* Identifier */: return keep(name) ? name : undefined; - case 181: + case 181 /* ArrayBindingPattern */: return name; - case 180: { + case 180 /* ObjectBindingPattern */: { + // We can't handle nested destructurings or property names well here, so just copy them all. var newElements = name.elements.filter(function (prop) { return prop.propertyName || !ts.isIdentifier(prop.name) || keep(prop.name); }); return newElements.length ? ts.createObjectBindingPattern(newElements) : undefined; } @@ -91112,7 +108593,7 @@ var ts; } }); } - var SymbolSet = (function () { + var SymbolSet = /** @class */ (function () { function SymbolSet() { this.map = ts.createMap(); } @@ -91150,13 +108631,13 @@ var ts; } function isNonVariableTopLevelDeclaration(node) { switch (node.kind) { - case 234: - case 235: - case 239: - case 238: - case 237: - case 236: - case 243: + case 234 /* FunctionDeclaration */: + case 235 /* ClassDeclaration */: + case 239 /* ModuleDeclaration */: + case 238 /* EnumDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 236 /* InterfaceDeclaration */: + case 243 /* ImportEqualsDeclaration */: return true; default: return false; @@ -91164,26 +108645,26 @@ var ts; } function forEachTopLevelDeclaration(statement, cb) { switch (statement.kind) { - case 234: - case 235: - case 239: - case 238: - case 237: - case 236: - case 243: + case 234 /* FunctionDeclaration */: + case 235 /* ClassDeclaration */: + case 239 /* ModuleDeclaration */: + case 238 /* EnumDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 236 /* InterfaceDeclaration */: + case 243 /* ImportEqualsDeclaration */: return cb(statement); - case 214: + case 214 /* VariableStatement */: return ts.forEach(statement.declarationList.declarations, cb); - case 216: { + case 216 /* ExpressionStatement */: { var expression = statement.expression; - return ts.isBinaryExpression(expression) && ts.getSpecialPropertyAssignmentKind(expression) === 1 + return ts.isBinaryExpression(expression) && ts.getSpecialPropertyAssignmentKind(expression) === 1 /* ExportsProperty */ ? cb(statement) : undefined; } } } function nameOfTopLevelDeclaration(d) { - return d.kind === 216 ? d.expression.left.name : ts.tryCast(d.name, ts.isIdentifier); + return d.kind === 216 /* ExpressionStatement */ ? d.expression.left.name : ts.tryCast(d.name, ts.isIdentifier); } function getTopLevelDeclarationStatement(d) { return ts.isVariableDeclaration(d) ? d.parent.parent : d; @@ -91203,7 +108684,7 @@ var ts; } function isExported(sourceFile, decl, useEs6Exports) { if (useEs6Exports) { - return !ts.isExpressionStatement(decl) && ts.hasModifier(decl, 1); + return !ts.isExpressionStatement(decl) && ts.hasModifier(decl, 1 /* Export */); } else { return getNamesToExportInCommonJS(decl).some(function (name) { return sourceFile.symbol.exports.has(ts.escapeLeadingUnderscores(name)); }); @@ -91213,26 +108694,26 @@ var ts; return useEs6Exports ? [addEs6Export(decl)] : addCommonjsExport(decl); } function addEs6Export(d) { - var modifiers = ts.concatenate([ts.createModifier(84)], d.modifiers); + var modifiers = ts.concatenate([ts.createModifier(84 /* ExportKeyword */)], d.modifiers); switch (d.kind) { - case 234: + case 234 /* FunctionDeclaration */: return ts.updateFunctionDeclaration(d, d.decorators, modifiers, d.asteriskToken, d.name, d.typeParameters, d.parameters, d.type, d.body); - case 235: + case 235 /* ClassDeclaration */: return ts.updateClassDeclaration(d, d.decorators, modifiers, d.name, d.typeParameters, d.heritageClauses, d.members); - case 214: + case 214 /* VariableStatement */: return ts.updateVariableStatement(d, modifiers, d.declarationList); - case 239: + case 239 /* ModuleDeclaration */: return ts.updateModuleDeclaration(d, d.decorators, modifiers, d.name, d.body); - case 238: + case 238 /* EnumDeclaration */: return ts.updateEnumDeclaration(d, d.decorators, modifiers, d.name, d.members); - case 237: + case 237 /* TypeAliasDeclaration */: return ts.updateTypeAliasDeclaration(d, d.decorators, modifiers, d.name, d.typeParameters, d.type); - case 236: + case 236 /* InterfaceDeclaration */: return ts.updateInterfaceDeclaration(d, d.decorators, modifiers, d.name, d.typeParameters, d.heritageClauses, d.members); - case 243: + case 243 /* ImportEqualsDeclaration */: return ts.updateImportEqualsDeclaration(d, d.decorators, modifiers, d.name, d.moduleReference); - case 216: - return ts.Debug.fail(); + case 216 /* ExpressionStatement */: + return ts.Debug.fail(); // Shouldn't try to add 'export' keyword to `exports.x = ...` default: return ts.Debug.assertNever(d); } @@ -91242,28 +108723,30 @@ var ts; } function getNamesToExportInCommonJS(decl) { switch (decl.kind) { - case 234: - case 235: - return [decl.name.text]; - case 214: + case 234 /* FunctionDeclaration */: + case 235 /* ClassDeclaration */: + return [decl.name.text]; // TODO: GH#18217 + case 214 /* VariableStatement */: return ts.mapDefined(decl.declarationList.declarations, function (d) { return ts.isIdentifier(d.name) ? d.name.text : undefined; }); - case 239: - case 238: - case 237: - case 236: - case 243: + case 239 /* ModuleDeclaration */: + case 238 /* EnumDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 236 /* InterfaceDeclaration */: + case 243 /* ImportEqualsDeclaration */: return ts.emptyArray; - case 216: - return ts.Debug.fail(); + case 216 /* ExpressionStatement */: + return ts.Debug.fail(); // Shouldn't try to add 'export' keyword to `exports.x = ...` default: return ts.Debug.assertNever(decl); } } + /** Creates `exports.x = x;` */ function createExportAssignment(name) { - return ts.createExpressionStatement(ts.createBinary(ts.createPropertyAccess(ts.createIdentifier("exports"), ts.createIdentifier(name)), 58, ts.createIdentifier(name))); + return ts.createExpressionStatement(ts.createBinary(ts.createPropertyAccess(ts.createIdentifier("exports"), ts.createIdentifier(name)), 58 /* EqualsToken */, ts.createIdentifier(name))); } })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var refactor; @@ -91306,15 +108789,15 @@ var ts; var body; if (actionName === addBracesActionName) { var returnStatement_1 = ts.createReturn(expression); - body = ts.createBlock([returnStatement_1], true); + body = ts.createBlock([returnStatement_1], /* multiLine */ true); ts.suppressLeadingAndTrailingTrivia(body); - ts.copyComments(expression, returnStatement_1, file, 3, true); + ts.copyComments(expression, returnStatement_1, file, 3 /* MultiLineCommentTrivia */, /* hasTrailingNewLine */ true); } else if (actionName === removeBracesActionName && returnStatement) { var actualExpression = expression || ts.createVoidZero(); body = needsParentheses(actualExpression) ? ts.createParen(actualExpression) : actualExpression; ts.suppressLeadingAndTrailingTrivia(body); - ts.copyComments(returnStatement, body, file, 3, false); + ts.copyComments(returnStatement, body, file, 3 /* MultiLineCommentTrivia */, /* hasTrailingNewLine */ false); } else { ts.Debug.fail("invalid action"); @@ -91323,10 +108806,10 @@ var ts; return { renameFilename: undefined, renameLocation: undefined, edits: edits }; } function needsParentheses(expression) { - return ts.isBinaryExpression(expression) && expression.operatorToken.kind === 26 || ts.isObjectLiteralExpression(expression); + return ts.isBinaryExpression(expression) && expression.operatorToken.kind === 26 /* CommaToken */ || ts.isObjectLiteralExpression(expression); } function getConvertibleArrowFunctionAtPosition(file, startPosition) { - var node = ts.getTokenAtPosition(file, startPosition, false); + var node = ts.getTokenAtPosition(file, startPosition, /*includeJsDocComment*/ false); var func = ts.getContainingFunction(node); if (!func || !ts.isArrowFunction(func) || (!ts.rangeContainsRange(func, node) || ts.rangeContainsRange(func.body, node))) return undefined; @@ -91355,25 +108838,27 @@ var ts; })(ts || (ts = {})); var ts; (function (ts) { + /** The version of the language service API */ ts.servicesVersion = "0.8"; function createNode(kind, pos, end, parent) { var node = ts.isNodeKind(kind) ? new NodeObject(kind, pos, end) : - kind === 71 ? new IdentifierObject(71, pos, end) : + kind === 71 /* Identifier */ ? new IdentifierObject(71 /* Identifier */, pos, end) : new TokenObject(kind, pos, end); node.parent = parent; - node.flags = parent.flags & 12679168; + node.flags = parent.flags & 12679168 /* ContextFlags */; return node; } - var NodeObject = (function () { + var NodeObject = /** @class */ (function () { function NodeObject(kind, pos, end) { this.pos = pos; this.end = end; - this.flags = 0; - this.transformFlags = undefined; + this.flags = 0 /* None */; + this.transformFlags = undefined; // TODO: GH#18217 this.parent = undefined; this.kind = kind; } NodeObject.prototype.assertHasRealPosition = function (message) { + // tslint:disable-next-line:debug-assert ts.Debug.assert(!ts.positionIsSynthesized(this.pos) && !ts.positionIsSynthesized(this.end), message || "Node must have a real position for this operation"); }; NodeObject.prototype.getSourceFile = function () { @@ -91430,8 +108915,8 @@ var ts; if (!children.length) { return undefined; } - var child = ts.find(children, function (kid) { return kid.kind < 278 || kid.kind > 299; }); - return child.kind < 146 ? + var child = ts.find(children, function (kid) { return kid.kind < 278 /* FirstJSDocNode */ || kid.kind > 299 /* LastJSDocNode */; }); + return child.kind < 146 /* FirstNode */ ? child : child.getFirstToken(sourceFile); }; @@ -91442,7 +108927,7 @@ var ts; if (!child) { return undefined; } - return child.kind < 146 ? child : child.getLastToken(sourceFile); + return child.kind < 146 /* FirstNode */ ? child : child.getLastToken(sourceFile); }; NodeObject.prototype.forEachChild = function (cbNode, cbNodeArray) { return ts.forEachChild(this, cbNode, cbNodeArray); @@ -91455,6 +108940,7 @@ var ts; } var children = []; if (ts.isJSDocCommentContainingNode(node)) { + /** Don't add trivia for "tokens" since this is in a comment. */ node.forEachChild(function (child) { children.push(child); }); return children; } @@ -91470,7 +108956,11 @@ var ts; children.push(createSyntaxList(nodes, node)); pos = nodes.end; }; + // jsDocComments need to be the first children ts.forEach(node.jsDoc, processNode); + // For syntactic classifications, all trivia are classified together, including jsdoc comments. + // For that to work, the jsdoc comments should still be the leading trivia of the first child. + // Restoring the scanner position ensures that. pos = node.pos; node.forEachChild(processNode, processNodes); addSyntheticNodes(children, pos, node.end, node); @@ -91483,19 +108973,19 @@ var ts; var token = ts.scanner.scan(); var textPos = ts.scanner.getTextPos(); if (textPos <= end) { - if (token === 71) { + if (token === 71 /* Identifier */) { ts.Debug.fail("Did not expect " + ts.Debug.showSyntaxKind(parent) + " to have an Identifier in its trivia"); } nodes.push(createNode(token, pos, textPos, parent)); } pos = textPos; - if (token === 1) { + if (token === 1 /* EndOfFileToken */) { break; } } } function createSyntaxList(nodes, parent) { - var list = createNode(300, nodes.pos, nodes.end, parent); + var list = createNode(300 /* SyntaxList */, nodes.pos, nodes.end, parent); list._children = []; var pos = nodes.pos; for (var _i = 0, nodes_7 = nodes; _i < nodes_7.length; _i++) { @@ -91507,11 +108997,12 @@ var ts; addSyntheticNodes(list._children, pos, nodes.end, parent); return list; } - var TokenOrIdentifierObject = (function () { + var TokenOrIdentifierObject = /** @class */ (function () { function TokenOrIdentifierObject(pos, end) { + // Set properties in same order as NodeObject this.pos = pos; this.end = end; - this.flags = 0; + this.flags = 0 /* None */; this.parent = undefined; } TokenOrIdentifierObject.prototype.getSourceFile = function () { @@ -91548,7 +109039,7 @@ var ts; return 0; }; TokenOrIdentifierObject.prototype.getChildAt = function () { - return undefined; + return undefined; // TODO: GH#18217 }; TokenOrIdentifierObject.prototype.getChildren = function () { return ts.emptyArray; @@ -91564,7 +109055,7 @@ var ts; }; return TokenOrIdentifierObject; }()); - var SymbolObject = (function () { + var SymbolObject = /** @class */ (function () { function SymbolObject(flags, name) { this.flags = flags; this.escapedName = name; @@ -91590,7 +109081,7 @@ var ts; }; SymbolObject.prototype.getDocumentationComment = function (checker) { if (!this.documentationComment) { - this.documentationComment = ts.emptyArray; + this.documentationComment = ts.emptyArray; // Set temporarily to avoid an infinite loop finding inherited docs this.documentationComment = getDocumentationComment(this.declarations, checker); } return this.documentationComment; @@ -91603,7 +109094,7 @@ var ts; }; return SymbolObject; }()); - var TokenObject = (function (_super) { + var TokenObject = /** @class */ (function (_super) { __extends(TokenObject, _super); function TokenObject(kind, pos, end) { var _this = _super.call(this, pos, end) || this; @@ -91612,7 +109103,7 @@ var ts; } return TokenObject; }(TokenOrIdentifierObject)); - var IdentifierObject = (function (_super) { + var IdentifierObject = /** @class */ (function (_super) { __extends(IdentifierObject, _super); function IdentifierObject(_kind, pos, end) { return _super.call(this, pos, end) || this; @@ -91626,8 +109117,8 @@ var ts; }); return IdentifierObject; }(TokenOrIdentifierObject)); - IdentifierObject.prototype.kind = 71; - var TypeObject = (function () { + IdentifierObject.prototype.kind = 71 /* Identifier */; + var TypeObject = /** @class */ (function () { function TypeObject(checker, flags) { this.checker = checker; this.flags = flags; @@ -91648,16 +109139,16 @@ var ts; return this.checker.getAugmentedPropertiesOfType(this); }; TypeObject.prototype.getCallSignatures = function () { - return this.checker.getSignaturesOfType(this, 0); + return this.checker.getSignaturesOfType(this, 0 /* Call */); }; TypeObject.prototype.getConstructSignatures = function () { - return this.checker.getSignaturesOfType(this, 1); + return this.checker.getSignaturesOfType(this, 1 /* Construct */); }; TypeObject.prototype.getStringIndexType = function () { - return this.checker.getIndexTypeOfType(this, 0); + return this.checker.getIndexTypeOfType(this, 0 /* String */); }; TypeObject.prototype.getNumberIndexType = function () { - return this.checker.getIndexTypeOfType(this, 1); + return this.checker.getIndexTypeOfType(this, 1 /* Number */); }; TypeObject.prototype.getBaseTypes = function () { return this.isClassOrInterface() ? this.checker.getBaseTypes(this) : undefined; @@ -91672,35 +109163,35 @@ var ts; return this.checker.getDefaultFromTypeParameter(this); }; TypeObject.prototype.isUnion = function () { - return !!(this.flags & 262144); + return !!(this.flags & 262144 /* Union */); }; TypeObject.prototype.isIntersection = function () { - return !!(this.flags & 524288); + return !!(this.flags & 524288 /* Intersection */); }; TypeObject.prototype.isUnionOrIntersection = function () { - return !!(this.flags & 786432); + return !!(this.flags & 786432 /* UnionOrIntersection */); }; TypeObject.prototype.isLiteral = function () { - return !!(this.flags & 192); + return !!(this.flags & 192 /* StringOrNumberLiteral */); }; TypeObject.prototype.isStringLiteral = function () { - return !!(this.flags & 64); + return !!(this.flags & 64 /* StringLiteral */); }; TypeObject.prototype.isNumberLiteral = function () { - return !!(this.flags & 128); + return !!(this.flags & 128 /* NumberLiteral */); }; TypeObject.prototype.isTypeParameter = function () { - return !!(this.flags & 65536); + return !!(this.flags & 65536 /* TypeParameter */); }; TypeObject.prototype.isClassOrInterface = function () { - return !!(ts.getObjectFlags(this) & 3); + return !!(ts.getObjectFlags(this) & 3 /* ClassOrInterface */); }; TypeObject.prototype.isClass = function () { - return !!(ts.getObjectFlags(this) & 1); + return !!(ts.getObjectFlags(this) & 1 /* Class */); }; return TypeObject; }()); - var SignatureObject = (function () { + var SignatureObject = /** @class */ (function () { function SignatureObject(checker) { this.checker = checker; } @@ -91727,6 +109218,11 @@ var ts; }; return SignatureObject; }()); + /** + * Returns whether or not the given node has a JSDoc "inheritDoc" tag on it. + * @param node the Node in question. + * @returns `true` if `node` has a JSDoc "inheritDoc" tag on it, otherwise `false`. + */ function hasJSDocInheritDocTag(node) { return ts.getJSDocTags(node).some(function (tag) { return tag.tagName.text === "inheritDoc"; }); } @@ -91737,13 +109233,22 @@ var ts; if (doc.length === 0 || declarations.some(hasJSDocInheritDocTag)) { for (var _i = 0, declarations_14 = declarations; _i < declarations_14.length; _i++) { var declaration = declarations_14[_i]; - var inheritedDocs = findInheritedJSDocComments(declaration, declaration.symbol.name, checker); + var inheritedDocs = findInheritedJSDocComments(declaration, declaration.symbol.name, checker); // TODO: GH#18217 + // TODO: GH#16312 Return a ReadonlyArray, avoid copying inheritedDocs if (inheritedDocs) doc = doc.length === 0 ? inheritedDocs.slice() : inheritedDocs.concat(ts.lineBreakPart(), doc); } } return doc; } + /** + * Attempts to find JSDoc comments for possibly-inherited properties. Checks superclasses then traverses + * implemented interfaces until a symbol is found with the same name and with documentation. + * @param declaration The possibly-inherited declaration to find comments for. + * @param propertyName The name of the possibly-inherited property. + * @param typeChecker A TypeChecker, used to find inherited properties. + * @returns A filled array of documentation comments if any were found, otherwise an empty array. + */ function findInheritedJSDocComments(declaration, propertyName, typeChecker) { return ts.firstDefined(declaration.parent ? ts.getAllSuperTypeNodes(declaration.parent) : ts.emptyArray, function (superTypeNode) { var superType = typeChecker.getTypeAtLocation(superTypeNode); @@ -91752,7 +109257,7 @@ var ts; return inheritedDocs && inheritedDocs.length ? inheritedDocs : undefined; }); } - var SourceFileObject = (function (_super) { + var SourceFileObject = /** @class */ (function (_super) { __extends(SourceFileObject, _super); function SourceFileObject(kind, pos, end) { return _super.call(this, kind, pos, end) || this; @@ -91780,6 +109285,7 @@ var ts; lastCharPos = lineStarts[line + 1] - 1; } var fullText = this.getFullText(); + // if the new line is "\r\n", we should return the last non-new-line-character position return fullText[lastCharPos] === "\n" && fullText[lastCharPos - 1] === "\r" ? lastCharPos - 1 : lastCharPos; }; SourceFileObject.prototype.getNamedDeclarations = function () { @@ -91812,16 +109318,19 @@ var ts; } function visit(node) { switch (node.kind) { - case 234: - case 192: - case 154: - case 153: + case 234 /* FunctionDeclaration */: + case 192 /* FunctionExpression */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: var functionDeclaration = node; var declarationName = getDeclarationName(functionDeclaration); if (declarationName) { var declarations = getDeclarations(declarationName); var lastDeclaration = ts.lastOrUndefined(declarations); + // Check whether this declaration belongs to an "overload group". if (lastDeclaration && functionDeclaration.parent === lastDeclaration.parent && functionDeclaration.symbol === lastDeclaration.symbol) { + // Overwrite the last declaration if it was an overload + // and this one is an implementation. if (functionDeclaration.body && !lastDeclaration.body) { declarations[declarations.length - 1] = functionDeclaration; } @@ -91832,29 +109341,31 @@ var ts; } ts.forEachChild(node, visit); break; - case 235: - case 205: - case 236: - case 237: - case 238: - case 239: - case 243: - case 252: - case 248: - case 245: - case 246: - case 156: - case 157: - case 166: + case 235 /* ClassDeclaration */: + case 205 /* ClassExpression */: + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: + case 238 /* EnumDeclaration */: + case 239 /* ModuleDeclaration */: + case 243 /* ImportEqualsDeclaration */: + case 252 /* ExportSpecifier */: + case 248 /* ImportSpecifier */: + case 245 /* ImportClause */: + case 246 /* NamespaceImport */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 166 /* TypeLiteral */: addDeclaration(node); ts.forEachChild(node, visit); break; - case 149: - if (!ts.hasModifier(node, 92)) { + case 149 /* Parameter */: + // Only consider parameter properties + if (!ts.hasModifier(node, 92 /* ParameterPropertyModifier */)) { break; } - case 232: - case 182: { + // falls through + case 232 /* VariableDeclaration */: + case 182 /* BindingElement */: { var decl = node; if (ts.isBindingPattern(decl.name)) { ts.forEachChild(decl.name, visit); @@ -91864,24 +109375,32 @@ var ts; visit(decl.initializer); } } - case 273: - case 152: - case 151: + // falls through + case 273 /* EnumMember */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: addDeclaration(node); break; - case 250: + case 250 /* ExportDeclaration */: + // Handle named exports case e.g.: + // export {a, b as B} from "mod"; if (node.exportClause) { ts.forEach(node.exportClause.elements, visit); } break; - case 244: + case 244 /* ImportDeclaration */: var importClause = node.importClause; if (importClause) { + // Handle default import case e.g.: + // import d from "mod"; if (importClause.name) { addDeclaration(importClause); } + // Handle named bindings in imports e.g.: + // import * as NS from "mod"; + // import {a, b as B} from "mod"; if (importClause.namedBindings) { - if (importClause.namedBindings.kind === 246) { + if (importClause.namedBindings.kind === 246 /* NamespaceImport */) { addDeclaration(importClause.namedBindings); } else { @@ -91890,10 +109409,11 @@ var ts; } } break; - case 200: - if (ts.getSpecialPropertyAssignmentKind(node) !== 0) { + case 200 /* BinaryExpression */: + if (ts.getSpecialPropertyAssignmentKind(node) !== 0 /* None */) { addDeclaration(node); } + // falls through default: ts.forEachChild(node, visit); } @@ -91901,7 +109421,7 @@ var ts; }; return SourceFileObject; }(NodeObject)); - var SourceMapSourceObject = (function () { + var SourceMapSourceObject = /** @class */ (function () { function SourceMapSourceObject(fileName, text, skipTrivia) { this.fileName = fileName; this.text = text; @@ -91956,9 +109476,10 @@ var ts; } ts.displayPartsToString = displayPartsToString; function getDefaultCompilerOptions() { + // Always default to "ScriptTarget.ES5" for the language service return { - target: 1, - jsx: 1 + target: 1 /* ES5 */, + jsx: 1 /* Preserve */ }; } ts.getDefaultCompilerOptions = getDefaultCompilerOptions; @@ -91966,16 +109487,22 @@ var ts; return ts.codefix.getSupportedErrorCodes(); } ts.getSupportedCodeFixes = getSupportedCodeFixes; - var HostCache = (function () { + // Cache host information about script Should be refreshed + // at each language service public entry point, since we don't know when + // the set of scripts handled by the host changes. + var HostCache = /** @class */ (function () { function HostCache(host, getCanonicalFileName) { this.host = host; + // script id => script index this.currentDirectory = host.getCurrentDirectory(); this.fileNameToEntry = ts.createMap(); + // Initialize the list with the root file names var rootFileNames = host.getScriptFileNames(); for (var _i = 0, rootFileNames_1 = rootFileNames; _i < rootFileNames_1.length; _i++) { var fileName = rootFileNames_1[_i]; this.createEntry(fileName, ts.toPath(fileName, this.currentDirectory, getCanonicalFileName)); } + // store the compilation settings this._compilationSettings = host.getCompilationSettings() || getDefaultCompilerOptions(); } HostCache.prototype.compilationSettings = function () { @@ -92010,7 +109537,7 @@ var ts; }; HostCache.prototype.getOrCreateEntryByPath = function (fileName, path) { var info = this.getEntryByPath(path) || this.createEntry(fileName, path); - return ts.isString(info) ? undefined : info; + return ts.isString(info) ? undefined : info; // TODO: GH#18217 }; HostCache.prototype.getRootFileNames = function () { var names = []; @@ -92019,7 +109546,7 @@ var ts; names.push(entry); } else { - if (entry.scriptKind !== 6) { + if (entry.scriptKind !== 6 /* JSON */) { names.push(entry.hostFileName); } } @@ -92028,34 +109555,38 @@ var ts; }; HostCache.prototype.getVersion = function (path) { var file = this.getHostFileInformation(path); - return (file && file.version); + return (file && file.version); // TODO: GH#18217 }; HostCache.prototype.getScriptSnapshot = function (path) { var file = this.getHostFileInformation(path); - return (file && file.scriptSnapshot); + return (file && file.scriptSnapshot); // TODO: GH#18217 }; return HostCache; }()); - var SyntaxTreeCache = (function () { + var SyntaxTreeCache = /** @class */ (function () { function SyntaxTreeCache(host) { this.host = host; } SyntaxTreeCache.prototype.getCurrentSourceFile = function (fileName) { var scriptSnapshot = this.host.getScriptSnapshot(fileName); if (!scriptSnapshot) { + // The host does not know about this file. throw new Error("Could not find file: '" + fileName + "'."); } var scriptKind = ts.getScriptKind(fileName, this.host); var version = this.host.getScriptVersion(fileName); var sourceFile; if (this.currentFileName !== fileName) { - sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, 6, version, true, scriptKind); + // This is a new file, just parse it + sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, 6 /* Latest */, version, /*setNodeParents*/ true, scriptKind); } else if (this.currentFileVersion !== version) { + // This is the same file, just a newer version. Incrementally parse the file. var editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot); sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange); } if (sourceFile) { + // All done, ensure state is up to date this.currentFileVersion = version; this.currentFileName = fileName; this.currentFileScriptSnapshot = scriptSnapshot; @@ -92077,21 +109608,29 @@ var ts; ts.createLanguageServiceSourceFile = createLanguageServiceSourceFile; ts.disableIncrementalParsing = false; function updateLanguageServiceSourceFile(sourceFile, scriptSnapshot, version, textChangeRange, aggressiveChecks) { + // If we were given a text change range, and our version or open-ness changed, then + // incrementally parse this file. if (textChangeRange) { if (version !== sourceFile.version) { + // Once incremental parsing is ready, then just call into this function. if (!ts.disableIncrementalParsing) { var newText = void 0; + // grab the fragment from the beginning of the original text to the beginning of the span var prefix = textChangeRange.span.start !== 0 ? sourceFile.text.substr(0, textChangeRange.span.start) : ""; + // grab the fragment from the end of the span till the end of the original text var suffix = ts.textSpanEnd(textChangeRange.span) !== sourceFile.text.length ? sourceFile.text.substr(ts.textSpanEnd(textChangeRange.span)) : ""; if (textChangeRange.newLength === 0) { + // edit was a deletion - just combine prefix and suffix newText = prefix && suffix ? prefix + suffix : prefix || suffix; } else { + // it was actual edit, fetch the fragment of new text that correspond to new span var changedText = scriptSnapshot.getText(textChangeRange.span.start, textChangeRange.span.start + textChangeRange.newLength); + // combine prefix, changed text and suffix newText = prefix && suffix ? prefix + changedText + suffix : prefix @@ -92100,7 +109639,10 @@ var ts; } var newSourceFile = ts.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); setSourceFileFields(newSourceFile, scriptSnapshot, version); + // after incremental parsing nameTable might not be up-to-date + // drop it so it can be lazily recreated later newSourceFile.nameTable = undefined; + // dispose all resources held by old script snapshot if (sourceFile !== newSourceFile && sourceFile.scriptSnapshot) { if (sourceFile.scriptSnapshot.dispose) { sourceFile.scriptSnapshot.dispose(); @@ -92111,10 +109653,11 @@ var ts; } } } - return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, true, sourceFile.scriptKind); + // Otherwise, just create a new source file. + return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true, sourceFile.scriptKind); } ts.updateLanguageServiceSourceFile = updateLanguageServiceSourceFile; - var CancellationTokenObject = (function () { + var CancellationTokenObject = /** @class */ (function () { function CancellationTokenObject(cancellationToken) { this.cancellationToken = cancellationToken; } @@ -92128,17 +109671,23 @@ var ts; }; return CancellationTokenObject; }()); - var ThrottledCancellationToken = (function () { + /* @internal */ + /** A cancellation that throttles calls to the host */ + var ThrottledCancellationToken = /** @class */ (function () { function ThrottledCancellationToken(hostCancellationToken, throttleWaitMilliseconds) { if (throttleWaitMilliseconds === void 0) { throttleWaitMilliseconds = 20; } this.hostCancellationToken = hostCancellationToken; this.throttleWaitMilliseconds = throttleWaitMilliseconds; + // Store when we last tried to cancel. Checking cancellation can be expensive (as we have + // to marshall over to the host layer). So we only bother actually checking once enough + // time has passed. this.lastCancellationCheckTime = 0; } ThrottledCancellationToken.prototype.isCancellationRequested = function () { var time = ts.timestamp(); var duration = Math.abs(time - this.lastCancellationCheckTime); if (duration >= this.throttleWaitMilliseconds) { + // Check no more than once every throttle wait milliseconds this.lastCancellationCheckTime = time; return this.hostCancellationToken.isCancellationRequested(); } @@ -92162,6 +109711,7 @@ var ts; var lastTypesRootVersion = 0; var cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken()); var currentDirectory = host.getCurrentDirectory(); + // Check if the localized messages json is set, otherwise query the host for it if (!ts.localizedDiagnosticMessages && host.getLocalizedDiagnosticMessages) { ts.localizedDiagnosticMessages = host.getLocalizedDiagnosticMessages(); } @@ -92182,6 +109732,7 @@ var ts; } function synchronizeHostData() { ts.Debug.assert(!syntaxOnly); + // perform fast check if host supports it if (host.getProjectVersion) { var hostProjectVersion = host.getProjectVersion(); if (hostProjectVersion) { @@ -92194,16 +109745,24 @@ var ts; var typeRootsVersion = host.getTypeRootsVersion ? host.getTypeRootsVersion() : 0; if (lastTypesRootVersion !== typeRootsVersion) { log("TypeRoots version has changed; provide new program"); - program = undefined; + program = undefined; // TODO: GH#18217 lastTypesRootVersion = typeRootsVersion; } + // Get a fresh cache of the host information var hostCache = new HostCache(host, getCanonicalFileName); var rootFileNames = hostCache.getRootFileNames(); var hasInvalidatedResolution = host.hasInvalidatedResolution || ts.returnFalse; + // If the program is already up-to-date, we can reuse it if (ts.isProgramUptoDate(program, rootFileNames, hostCache.compilationSettings(), function (path) { return hostCache.getVersion(path); }, fileExists, hasInvalidatedResolution, !!host.hasChangedAutomaticTypeDirectiveNames)) { return; } + // IMPORTANT - It is critical from this moment onward that we do not check + // cancellation tokens. We are about to mutate source files from a previous program + // instance. If we cancel midway through, we may end up in an inconsistent state where + // the program points to old source files that have been invalidated because of + // incremental parsing. var newSettings = hostCache.compilationSettings(); + // Now create a new compiler var compilerHost = { getSourceFile: getOrCreateSourceFile, getSourceFileByPath: getOrCreateSourceFileByPath, @@ -92216,6 +109775,7 @@ var ts; getCurrentDirectory: function () { return currentDirectory; }, fileExists: fileExists, readFile: function (fileName) { + // stub missing host functionality var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); var entry = hostCache.getEntryByPath(path); if (entry) { @@ -92254,8 +109814,15 @@ var ts; projectReferences: hostCache.getProjectReferences() }; program = ts.createProgram(options); + // hostCache is captured in the closure for 'getOrCreateSourceFile' but it should not be used past this point. + // It needs to be cleared to allow all collected snapshots to be released hostCache = undefined; + // We reset this cache on structure invalidation so we don't hold on to outdated files for long; however we can't use the `compilerHost` above, + // Because it only functions until `hostCache` is cleared, while we'll potentially need the functionality to lazily read sourcemap files during + // the course of whatever called `synchronizeHostData` sourcemappedFileCache = ts.createSourceFileLikeCache(host); + // Make sure all the nodes in the program are both bound, and have their parent + // pointers set property. program.getTypeChecker(); return; function fileExists(fileName) { @@ -92265,6 +109832,8 @@ var ts; !ts.isString(entry) : (!!host.fileExists && host.fileExists(fileName)); } + // Release any files we have acquired in the old program but are + // not part of the new program. function onReleaseOldSourceFile(oldSourceFile, oldOptions) { var oldSettingsKey = documentRegistry.getKeyForCompilationSettings(oldOptions); documentRegistry.releaseDocumentWithKey(oldSourceFile.path, oldSettingsKey); @@ -92274,20 +109843,54 @@ var ts; } function getOrCreateSourceFileByPath(fileName, path, _languageVersion, _onError, shouldCreateNewSourceFile) { ts.Debug.assert(hostCache !== undefined); + // The program is asking for this file, check first if the host can locate it. + // If the host can not locate the file, then it does not exist. return undefined + // to the program to allow reporting of errors for missing files. var hostFileInformation = hostCache.getOrCreateEntryByPath(fileName, path); if (!hostFileInformation) { return undefined; } + // Check if the language version has changed since we last created a program; if they are the same, + // it is safe to reuse the sourceFiles; if not, then the shape of the AST can change, and the oldSourceFile + // can not be reused. we have to dump all syntax trees and create new ones. if (!shouldCreateNewSourceFile) { + // Check if the old program had this file already var oldSourceFile = program && program.getSourceFileByPath(path); if (oldSourceFile) { + // We already had a source file for this file name. Go to the registry to + // ensure that we get the right up to date version of it. We need this to + // address the following race-condition. Specifically, say we have the following: + // + // LS1 + // \ + // DocumentRegistry + // / + // LS2 + // + // Each LS has a reference to file 'foo.ts' at version 1. LS2 then updates + // it's version of 'foo.ts' to version 2. This will cause LS2 and the + // DocumentRegistry to have version 2 of the document. HOwever, LS1 will + // have version 1. And *importantly* this source file will be *corrupt*. + // The act of creating version 2 of the file irrevocably damages the version + // 1 file. + // + // So, later when we call into LS1, we need to make sure that it doesn't use + // it's source file any more, and instead defers to DocumentRegistry to get + // either version 1, version 2 (or some other version) depending on what the + // host says should be used. + // We do not support the scenario where a host can modify a registered + // file's script kind, i.e. in one project some file is treated as ".ts" + // and in another as ".js" ts.Debug.assertEqual(hostFileInformation.scriptKind, oldSourceFile.scriptKind, "Registered script kind should match new script kind.", path); return documentRegistry.updateDocumentWithKey(fileName, path, newSettings, documentRegistryBucketKey, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } + // We didn't already have the file. Fall through and acquire it from the registry. } + // Could not find this file in the old program, create a new SourceFile for it. return documentRegistry.acquireDocumentWithKey(fileName, path, newSettings, documentRegistryBucketKey, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } } + // TODO: GH#18217 frequently asserted as defined function getProgram() { if (syntaxOnly) { ts.Debug.assert(program === undefined); @@ -92297,28 +109900,36 @@ var ts; return program; } function cleanupSemanticCache() { - program = undefined; + program = undefined; // TODO: GH#18217 } function dispose() { if (program) { ts.forEach(program.getSourceFiles(), function (f) { return documentRegistry.releaseDocument(f.fileName, program.getCompilerOptions()); }); - program = undefined; + program = undefined; // TODO: GH#18217 } host = undefined; } + /// Diagnostics function getSyntacticDiagnostics(fileName) { synchronizeHostData(); return program.getSyntacticDiagnostics(getValidSourceFile(fileName), cancellationToken).slice(); } + /** + * getSemanticDiagnostics return array of Diagnostics. If '-d' is not enabled, only report semantic errors + * If '-d' enabled, report both semantic and emitter errors + */ function getSemanticDiagnostics(fileName) { synchronizeHostData(); var targetSourceFile = getValidSourceFile(fileName); + // Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file. + // Therefore only get diagnostics for given file. var semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken); if (!program.getCompilerOptions().declaration) { return semanticDiagnostics.slice(); } + // If '-d' is enabled, check for emitter error. One example of emitter error is export class implements non-export interface var declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken); return semanticDiagnostics.concat(declarationDiagnostics); } @@ -92332,6 +109943,7 @@ var ts; } function getCompletionsAtPosition(fileName, position, options) { if (options === void 0) { options = ts.defaultPreferences; } + // Convert from deprecated options names to new names var fullPreferences = __assign({}, ts.identity(options), { includeCompletionsForModuleExports: options.includeCompletionsForModuleExports || options.includeExternalModuleExports, includeCompletionsWithInsertText: options.includeCompletionsWithInsertText || options.includeInsertTextCompletions }); synchronizeHostData(); return ts.Completions.getCompletionsAtPosition(host, program, log, getValidSourceFile(fileName), position, fullPreferences, options.triggerCharacter); @@ -92339,7 +109951,8 @@ var ts; function getCompletionEntryDetails(fileName, position, name, formattingOptions, source, preferences) { if (preferences === void 0) { preferences = ts.defaultPreferences; } synchronizeHostData(); - return ts.Completions.getCompletionEntryDetails(program, log, getValidSourceFile(fileName), position, { name: name, source: source }, host, (formattingOptions && ts.formatting.getFormatContext(formattingOptions)), getCanonicalFileName, preferences, cancellationToken); + return ts.Completions.getCompletionEntryDetails(program, log, getValidSourceFile(fileName), position, { name: name, source: source }, host, (formattingOptions && ts.formatting.getFormatContext(formattingOptions)), // TODO: GH#18217 + getCanonicalFileName, preferences, cancellationToken); } function getCompletionEntrySymbol(fileName, position, name, source) { synchronizeHostData(); @@ -92350,25 +109963,30 @@ var ts; var sourceFile = getValidSourceFile(fileName); var node = ts.getTouchingPropertyName(sourceFile, position); if (node === sourceFile) { + // Avoid giving quickInfo for the sourceFile as a whole. return undefined; } var typeChecker = program.getTypeChecker(); var symbol = getSymbolAtLocationForQuickInfo(node, typeChecker); if (!symbol || typeChecker.isUnknownSymbol(symbol)) { + // Try getting just type at this position and show switch (node.kind) { - case 71: + case 71 /* Identifier */: if (ts.isLabelName(node)) { + // Type here will be 'any', avoid displaying this. return undefined; } - case 185: - case 146: - case 99: - case 174: - case 97: + // falls through + case 185 /* PropertyAccessExpression */: + case 146 /* QualifiedName */: + case 99 /* ThisKeyword */: + case 174 /* ThisType */: + case 97 /* SuperKeyword */: + // For the identifiers/this/super etc get the type at position var type_4 = typeChecker.getTypeAtLocation(node); return type_4 && { - kind: "", - kindModifiers: "", + kind: "" /* unknown */, + kindModifiers: "" /* none */, textSpan: ts.createTextSpanFromNode(node, sourceFile), displayParts: typeChecker.runWithCancellationToken(cancellationToken, function (typeChecker) { return ts.typeToDisplayParts(typeChecker, type_4, ts.getContainerNode(node)); }), documentation: type_4.symbol ? type_4.symbol.getDocumentationComment(typeChecker) : undefined, @@ -92403,9 +110021,10 @@ var ts; } function toLineColumnOffset(fileName, position) { var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); - var file = program.getSourceFile(path) || sourcemappedFileCache.get(path); + var file = program.getSourceFile(path) || sourcemappedFileCache.get(path); // TODO: GH#18217 return file.getLineAndCharacterOfPosition(position); } + // Sometimes tools can sometimes see the following line as a source mapping url comment, so we mangle it a bit (the [M]) var sourceMapCommentRegExp = /^\/\/[@#] source[M]appingURL=(.+)$/gm; var base64UrlRegExp = /^data:(?:application\/json(?:;charset=[uU][tT][fF]-8);base64,([A-Za-z0-9+\/=]+)$)?/; function scanForSourcemapURL(fileName) { @@ -92428,8 +110047,10 @@ var ts; maps = JSON.parse(contents); } catch (_a) { + // swallow error } if (!maps || !maps.sources || !maps.file || !maps.mappings) { + // obviously invalid map return file.sourceMapper = ts.sourcemaps.identitySourceMapper; } return file.sourceMapper = ts.sourcemaps.decode({ @@ -92454,6 +110075,7 @@ var ts; var base64Object = match[1]; return convertDocumentToSourceMapper(file, ts.base64decode(ts.sys, base64Object), fileName); } + // Not a data URL we can parse, skip it mapFileName = undefined; } } @@ -92466,7 +110088,7 @@ var ts; var location = possibleMapLocations_1[_i]; var mapPath = ts.toPath(location, ts.getDirectoryPath(fileName), getCanonicalFileName); if (host.fileExists(mapPath)) { - return convertDocumentToSourceMapper(file, host.readFile(mapPath), mapPath); + return convertDocumentToSourceMapper(file, host.readFile(mapPath), mapPath); // TODO: GH#18217 } } return file.sourceMapper = ts.sourcemaps.identitySourceMapper; @@ -92476,7 +110098,7 @@ var ts; function getTargetOfMappedPosition(input, original) { if (original === void 0) { original = input; } var info = extract(input); - if (ts.endsWith(info.fileName, ".d.ts")) { + if (ts.endsWith(info.fileName, ".d.ts" /* Dts */)) { var file = program.getSourceFile(info.fileName); if (!file) { var path = ts.toPath(info.fileName, currentDirectory, getCanonicalFileName); @@ -92510,6 +110132,7 @@ var ts; function getTargetOfMappedDeclarationFiles(infos) { return ts.map(infos, function (d) { return getTargetOfMappedDeclarationInfo(d); }); } + /// Goto definition function getDefinitionAtPosition(fileName, position) { synchronizeHostData(); return getTargetOfMappedDeclarationFiles(ts.GoToDefinition.getDefinitionAtPosition(program, getValidSourceFile(fileName), position)); @@ -92532,6 +110155,7 @@ var ts; synchronizeHostData(); return getTargetOfMappedDeclarationFiles(ts.GoToDefinition.getTypeDefinitionAtPosition(program.getTypeChecker(), getValidSourceFile(fileName), position)); } + /// Goto implementation var getTargetOfMappedImplementationLocation = makeGetTargetOfMappedPosition(function (info) { return ({ fileName: info.fileName, position: info.textSpan.start }); }, function (newLoc, info) { return ({ fileName: newLoc.fileName, kind: info.kind, @@ -92550,11 +110174,12 @@ var ts; synchronizeHostData(); return getTargetOfMappedImplementationLocations(ts.FindAllReferences.getImplementationsAtPosition(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position)); } + /// References and Occurrences function getOccurrencesAtPosition(fileName, position) { return ts.flatMap(getDocumentHighlights(fileName, position, [fileName]), function (entry) { return entry.highlightSpans.map(function (highlightSpan) { return ({ fileName: entry.fileName, textSpan: highlightSpan.textSpan, - isWriteAccess: highlightSpan.kind === "writtenReference", + isWriteAccess: highlightSpan.kind === "writtenReference" /* writtenReference */, isDefinition: false, isInString: highlightSpan.isInString, }); }); }); @@ -92574,6 +110199,7 @@ var ts; } function getReferences(fileName, position, options) { synchronizeHostData(); + // Exclude default library when renaming as commonly user don't want to change that file. var sourceFiles = options && options.isForRename ? program.getSourceFiles().filter(function (sourceFile) { return !program.isSourceFileDefaultLibrary(sourceFile); }) : program.getSourceFiles(); @@ -92583,6 +110209,7 @@ var ts; synchronizeHostData(); return ts.FindAllReferences.findReferencedSymbols(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position); } + /// NavigateTo function getNavigateToItems(searchValue, maxResultCount, fileName, excludeDtsFiles) { if (excludeDtsFiles === void 0) { excludeDtsFiles = false; } synchronizeHostData(); @@ -92596,56 +110223,71 @@ var ts; var customTransformers = host.getCustomTransformers && host.getCustomTransformers(); return ts.getFileEmitOutput(program, sourceFile, emitOnlyDtsFiles, cancellationToken, customTransformers); } + // Signature help + /** + * This is a semantic operation. + */ function getSignatureHelpItems(fileName, position) { synchronizeHostData(); var sourceFile = getValidSourceFile(fileName); return ts.SignatureHelp.getSignatureHelpItems(program, sourceFile, position, cancellationToken); } + /// Syntactic features function getNonBoundSourceFile(fileName) { return syntaxTreeCache.getCurrentSourceFile(fileName); } function getNameOrDottedNameSpan(fileName, startPos, _endPos) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + // Get node at the location var node = ts.getTouchingPropertyName(sourceFile, startPos); if (node === sourceFile) { return undefined; } switch (node.kind) { - case 185: - case 146: - case 9: - case 86: - case 101: - case 95: - case 97: - case 99: - case 174: - case 71: + case 185 /* PropertyAccessExpression */: + case 146 /* QualifiedName */: + case 9 /* StringLiteral */: + case 86 /* FalseKeyword */: + case 101 /* TrueKeyword */: + case 95 /* NullKeyword */: + case 97 /* SuperKeyword */: + case 99 /* ThisKeyword */: + case 174 /* ThisType */: + case 71 /* Identifier */: break; + // Cant create the text span default: return undefined; } var nodeForStartPos = node; while (true) { if (ts.isRightSideOfPropertyAccess(nodeForStartPos) || ts.isRightSideOfQualifiedName(nodeForStartPos)) { + // If on the span is in right side of the the property or qualified name, return the span from the qualified name pos to end of this node nodeForStartPos = nodeForStartPos.parent; } else if (ts.isNameOfModuleDeclaration(nodeForStartPos)) { - if (nodeForStartPos.parent.parent.kind === 239 && + // If this is name of a module declarations, check if this is right side of dotted module name + // If parent of the module declaration which is parent of this node is module declaration and its body is the module declaration that this node is name of + // Then this name is name from dotted module + if (nodeForStartPos.parent.parent.kind === 239 /* ModuleDeclaration */ && nodeForStartPos.parent.parent.body === nodeForStartPos.parent) { + // Use parent module declarations name for start pos nodeForStartPos = nodeForStartPos.parent.parent.name; } else { + // We have to use this name for start pos break; } } else { + // Is not a member expression so we have found the node for start pos break; } } return ts.createTextSpanFromBounds(nodeForStartPos.getStart(), node.getEnd()); } function getBreakpointStatementAtPosition(fileName, position) { + // doesn't use compiler - no need to synchronize with host var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return ts.BreakpointResolver.spanInSourceFileAtLocation(sourceFile, position); } @@ -92657,10 +110299,11 @@ var ts; } function isTsOrTsxFile(fileName) { var kind = ts.getScriptKind(fileName, host); - return kind === 3 || kind === 4; + return kind === 3 /* TS */ || kind === 4 /* TSX */; } function getSemanticClassifications(fileName, span) { if (!isTsOrTsxFile(fileName)) { + // do not run semantic classification on non-ts-or-tsx files return []; } synchronizeHostData(); @@ -92668,33 +110311,38 @@ var ts; } function getEncodedSemanticClassifications(fileName, span) { if (!isTsOrTsxFile(fileName)) { - return { spans: [], endOfLineState: 0 }; + // do not run semantic classification on non-ts-or-tsx files + return { spans: [], endOfLineState: 0 /* None */ }; } synchronizeHostData(); return ts.getEncodedSemanticClassifications(program.getTypeChecker(), cancellationToken, getValidSourceFile(fileName), program.getClassifiableNames(), span); } function getSyntacticClassifications(fileName, span) { + // doesn't use compiler - no need to synchronize with host return ts.getSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span); } function getEncodedSyntacticClassifications(fileName, span) { + // doesn't use compiler - no need to synchronize with host return ts.getEncodedSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span); } function getOutliningSpans(fileName) { + // doesn't use compiler - no need to synchronize with host var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return ts.OutliningElementsCollector.collectElements(sourceFile, cancellationToken); } var braceMatching = ts.createMapFromTemplate((_a = {}, - _a[17] = 18, - _a[19] = 20, - _a[21] = 22, - _a[29] = 27, + _a[17 /* OpenBraceToken */] = 18 /* CloseBraceToken */, + _a[19 /* OpenParenToken */] = 20 /* CloseParenToken */, + _a[21 /* OpenBracketToken */] = 22 /* CloseBracketToken */, + _a[29 /* GreaterThanToken */] = 27 /* LessThanToken */, _a)); braceMatching.forEach(function (value, key) { return braceMatching.set(value.toString(), Number(key)); }); function getBraceMatchingAtPosition(fileName, position) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - var token = ts.getTouchingToken(sourceFile, position, false); + var token = ts.getTouchingToken(sourceFile, position, /*includeJsDocComment*/ false); var matchKind = token.getStart(sourceFile) === position ? braceMatching.get(token.kind.toString()) : undefined; var match = matchKind && ts.findChildOfKind(token.parent, matchKind, sourceFile); + // We want to order the braces when we return the result. return match ? [ts.createTextSpanFromNode(token, sourceFile), ts.createTextSpanFromNode(match, sourceFile)].sort(function (a, b) { return a.start - b.start; }) : ts.emptyArray; } function getIndentationAtPosition(fileName, position, editorOptions) { @@ -92774,29 +110422,37 @@ var ts; : Promise.reject("Host does not implement `installPackage`"); default: return ts.Debug.fail(); + // TODO: Debug.assertNever(action); will only work if there is more than one type. } } function getDocCommentTemplateAtPosition(fileName, position) { return ts.JsDoc.getDocCommentTemplateAtPosition(ts.getNewLineOrDefaultFromHost(host), syntaxTreeCache.getCurrentSourceFile(fileName), position); } function isValidBraceCompletionAtPosition(fileName, position, openingBrace) { - if (openingBrace === 60) { + // '<' is currently not supported, figuring out if we're in a Generic Type vs. a comparison is too + // expensive to do during typing scenarios + // i.e. whether we're dealing with: + // var x = new foo<| ( with class foo{} ) + // or + // var y = 3 <| + if (openingBrace === 60 /* lessThan */) { return false; } var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + // Check if in a context where we don't want to perform any insertion if (ts.isInString(sourceFile, position)) { return false; } if (ts.isInsideJsxElementOrAttribute(sourceFile, position)) { - return openingBrace === 123; + return openingBrace === 123 /* openBrace */; } if (ts.isInTemplateString(sourceFile, position)) { return false; } switch (openingBrace) { - case 39: - case 34: - case 96: + case 39 /* singleQuote */: + case 34 /* doubleQuote */: + case 96 /* backtick */: return !ts.isInComment(sourceFile, position); } return true; @@ -92806,7 +110462,7 @@ var ts; var token = ts.findPrecedingToken(position, sourceFile); if (!token) return undefined; - var element = token.kind === 29 && ts.isJsxOpeningElement(token.parent) ? token.parent.parent + var element = token.kind === 29 /* GreaterThanToken */ && ts.isJsxOpeningElement(token.parent) ? token.parent.parent : ts.isJsxText(token) ? token.parent : undefined; if (element && !ts.tagNamesAreEquivalent(element.openingElement.tagName, element.closingElement.tagName)) { return { newText: "" }; @@ -92818,20 +110474,46 @@ var ts; return range && ts.createTextSpanFromRange(range); } function getTodoComments(fileName, descriptors) { + // Note: while getting todo comments seems like a syntactic operation, we actually + // treat it as a semantic operation here. This is because we expect our host to call + // this on every single file. If we treat this syntactically, then that will cause + // us to populate and throw away the tree in our syntax tree cache for each file. By + // treating this as a semantic operation, we can access any tree without throwing + // anything away. synchronizeHostData(); var sourceFile = getValidSourceFile(fileName); cancellationToken.throwIfCancellationRequested(); var fileContents = sourceFile.text; var result = []; + // Exclude node_modules files as we don't want to show the todos of external libraries. if (descriptors.length > 0 && !isNodeModulesFile(sourceFile.fileName)) { var regExp = getTodoCommentsRegExp(); var matchArray = void 0; while (matchArray = regExp.exec(fileContents)) { cancellationToken.throwIfCancellationRequested(); + // If we got a match, here is what the match array will look like. Say the source text is: + // + // " // hack 1" + // + // The result array with the regexp: will be: + // + // ["// hack 1", "// ", "hack 1", undefined, "hack"] + // + // Here are the relevant capture groups: + // 0) The full match for the entire regexp. + // 1) The preamble to the message portion. + // 2) The message portion. + // 3...N) The descriptor that was matched - by index. 'undefined' for each + // descriptor that didn't match. an actual value if it did match. + // + // i.e. 'undefined' in position 3 above means TODO(jason) didn't match. + // "hack" in position 4 means HACK did match. var firstDescriptorCaptureIndex = 3; ts.Debug.assert(matchArray.length === descriptors.length + firstDescriptorCaptureIndex); var preamble = matchArray[1]; var matchPosition = matchArray.index + preamble.length; + // OK, we have found a match in the file. This is only an acceptable match if + // it is contained within a comment. if (!ts.isInComment(sourceFile, matchPosition)) { continue; } @@ -92843,6 +110525,8 @@ var ts; } if (descriptor === undefined) return ts.Debug.fail(); + // We don't want to match something like 'TODOBY', so we make sure a non + // letter/digit follows the match. if (isLetterOrDigit(fileContents.charCodeAt(matchPosition + descriptor.text.length))) { continue; } @@ -92855,21 +110539,59 @@ var ts; return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); } function getTodoCommentsRegExp() { + // NOTE: `?:` means 'non-capture group'. It allows us to have groups without having to + // filter them out later in the final result array. + // TODO comments can appear in one of the following forms: + // + // 1) // TODO or /////////// TODO + // + // 2) /* TODO or /********** TODO + // + // 3) /* + // * TODO + // */ + // + // The following three regexps are used to match the start of the text up to the TODO + // comment portion. var singleLineCommentStart = /(?:\/\/+\s*)/.source; var multiLineCommentStart = /(?:\/\*+\s*)/.source; var anyNumberOfSpacesAndAsterisksAtStartOfLine = /(?:^(?:\s|\*)*)/.source; + // Match any of the above three TODO comment start regexps. + // Note that the outermost group *is* a capture group. We want to capture the preamble + // so that we can determine the starting position of the TODO comment match. var preamble = "(" + anyNumberOfSpacesAndAsterisksAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")"; + // Takes the descriptors and forms a regexp that matches them as if they were literals. + // For example, if the descriptors are "TODO(jason)" and "HACK", then this will be: + // + // (?:(TODO\(jason\))|(HACK)) + // + // Note that the outermost group is *not* a capture group, but the innermost groups + // *are* capture groups. By capturing the inner literals we can determine after + // matching which descriptor we are dealing with. var literals = "(?:" + ts.map(descriptors, function (d) { return "(" + escapeRegExp(d.text) + ")"; }).join("|") + ")"; + // After matching a descriptor literal, the following regexp matches the rest of the + // text up to the end of the line (or */). var endOfLineOrEndOfComment = /(?:$|\*\/)/.source; var messageRemainder = /(?:.*?)/.source; + // This is the portion of the match we'll return as part of the TODO comment result. We + // match the literal portion up to the end of the line or end of comment. var messagePortion = "(" + literals + messageRemainder + ")"; var regExpString = preamble + messagePortion + endOfLineOrEndOfComment; + // The final regexp will look like this: + // /((?:\/\/+\s*)|(?:\/\*+\s*)|(?:^(?:\s|\*)*))((?:(TODO\(jason\))|(HACK))(?:.*?))(?:$|\*\/)/gim + // The flags of the regexp are important here. + // 'g' is so that we are doing a global search and can find matches several times + // in the input. + // + // 'i' is for case insensitivity (We do this to match C# TODO comment code). + // + // 'm' is so we can find matches in a multi-line input. return new RegExp(regExpString, "gim"); } function isLetterOrDigit(char) { - return (char >= 97 && char <= 122) || - (char >= 65 && char <= 90) || - (char >= 48 && char <= 57); + return (char >= 97 /* a */ && char <= 122 /* z */) || + (char >= 65 /* A */ && char <= 90 /* Z */) || + (char >= 48 /* _0 */ && char <= 57 /* _9 */); } function isNodeModulesFile(path) { return ts.stringContains(path, "/node_modules/"); @@ -92961,11 +110683,13 @@ var ts; }; } ts.createLanguageService = createLanguageService; + /* @internal */ + /** Names in the name table are escaped, so an identifier `__foo` will have a name table entry `___foo`. */ function getNameTable(sourceFile) { if (!sourceFile.nameTable) { initializeNameTable(sourceFile); } - return sourceFile.nameTable; + return sourceFile.nameTable; // TODO: GH#18217 } ts.getNameTable = getNameTable; function initializeNameTable(sourceFile) { @@ -92984,39 +110708,52 @@ var ts; } }); } + /** + * We want to store any numbers/strings if they were a name that could be + * related to a declaration. So, if we have 'import x = require("something")' + * then we want 'something' to be in the name table. Similarly, if we have + * "a['propname']" then we want to store "propname" in the name table. + */ function literalIsName(node) { return ts.isDeclarationName(node) || - node.parent.kind === 254 || + node.parent.kind === 254 /* ExternalModuleReference */ || isArgumentOfElementAccessExpression(node) || ts.isLiteralComputedPropertyDeclarationName(node); } + /** + * Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 } + */ + /* @internal */ function getContainingObjectLiteralElement(node) { switch (node.kind) { - case 9: - case 8: - if (node.parent.kind === 147) { + case 9 /* StringLiteral */: + case 8 /* NumericLiteral */: + if (node.parent.kind === 147 /* ComputedPropertyName */) { return ts.isObjectLiteralElement(node.parent.parent) ? node.parent.parent : undefined; } - case 71: + // falls through + case 71 /* Identifier */: return ts.isObjectLiteralElement(node.parent) && - (node.parent.parent.kind === 184 || node.parent.parent.kind === 263) && + (node.parent.parent.kind === 184 /* ObjectLiteralExpression */ || node.parent.parent.kind === 263 /* JsxAttributes */) && node.parent.name === node ? node.parent : undefined; } return undefined; } ts.getContainingObjectLiteralElement = getContainingObjectLiteralElement; + /* @internal */ function getPropertySymbolsFromContextualType(typeChecker, node) { var objectLiteral = node.parent; - var contextualType = typeChecker.getContextualType(objectLiteral); - return getPropertySymbolsFromType(contextualType, node.name); + var contextualType = typeChecker.getContextualType(objectLiteral); // TODO: GH#18217 + return getPropertySymbolsFromType(contextualType, node.name); // TODO: GH#18217 } ts.getPropertySymbolsFromContextualType = getPropertySymbolsFromContextualType; + /* @internal */ function getPropertySymbolsFromType(type, propName) { var name = ts.unescapeLeadingUnderscores(ts.getTextOfPropertyName(propName)); if (name && type) { var result_7 = []; var symbol = type.getProperty(name); - if (type.flags & 262144) { + if (type.flags & 262144 /* Union */) { ts.forEach(type.types, function (t) { var symbol = t.getProperty(name); if (symbol) { @@ -93036,10 +110773,16 @@ var ts; function isArgumentOfElementAccessExpression(node) { return node && node.parent && - node.parent.kind === 186 && + node.parent.kind === 186 /* ElementAccessExpression */ && node.parent.argumentExpression === node; } + /** + * Get the path of the default library files (lib.d.ts) as distributed with the typescript + * node package. + * The functionality is not supported if the ts module is consumed outside of a node module. + */ function getDefaultLibFilePath(options) { + // Check __dirname is defined and that we are on a node.js system. if (typeof __dirname !== "undefined") { return __dirname + ts.directorySeparator + ts.getDefaultLibFileName(options); } @@ -93048,26 +110791,39 @@ var ts; ts.getDefaultLibFilePath = getDefaultLibFilePath; ts.objectAllocator = getServicesObjectAllocator(); })(ts || (ts = {})); +/* @internal */ var ts; (function (ts) { var BreakpointResolver; (function (BreakpointResolver) { + /** + * Get the breakpoint span in given sourceFile + */ function spanInSourceFileAtLocation(sourceFile, position) { + // Cannot set breakpoint in dts file if (sourceFile.isDeclarationFile) { return undefined; } - var tokenAtLocation = ts.getTokenAtPosition(sourceFile, position, false); + var tokenAtLocation = ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); var lineOfPosition = sourceFile.getLineAndCharacterOfPosition(position).line; if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart(sourceFile)).line > lineOfPosition) { + // Get previous token if the token is returned starts on new line + // eg: let x =10; |--- cursor is here + // let y = 10; + // token at position will return let keyword on second line as the token but we would like to use + // token on same line if trailing trivia (comments or white spaces on same line) part of the last token on that line var preceding = ts.findPrecedingToken(tokenAtLocation.pos, sourceFile); + // It's a blank line if (!preceding || sourceFile.getLineAndCharacterOfPosition(preceding.getEnd()).line !== lineOfPosition) { return undefined; } tokenAtLocation = preceding; } - if (tokenAtLocation.flags & 4194304) { + // Cannot set breakpoint in ambient declarations + if (tokenAtLocation.flags & 4194304 /* Ambient */) { return undefined; } + // Get the span in the node based on its syntax return spanInNode(tokenAtLocation); function textSpan(startNode, endNode) { var start = startNode.decorators ? @@ -93097,229 +110853,292 @@ var ts; if (node) { var parent = node.parent; switch (node.kind) { - case 214: + case 214 /* VariableStatement */: + // Span on first variable declaration return spanInVariableDeclaration(node.declarationList.declarations[0]); - case 232: - case 152: - case 151: + case 232 /* VariableDeclaration */: + case 152 /* PropertyDeclaration */: + case 151 /* PropertySignature */: return spanInVariableDeclaration(node); - case 149: + case 149 /* Parameter */: return spanInParameterDeclaration(node); - case 234: - case 154: - case 153: - case 156: - case 157: - case 155: - case 192: - case 193: + case 234 /* FunctionDeclaration */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 155 /* Constructor */: + case 192 /* FunctionExpression */: + case 193 /* ArrowFunction */: return spanInFunctionDeclaration(node); - case 213: + case 213 /* Block */: if (ts.isFunctionBlock(node)) { return spanInFunctionBlock(node); } - case 240: + // falls through + case 240 /* ModuleBlock */: return spanInBlock(node); - case 269: + case 269 /* CatchClause */: return spanInBlock(node.block); - case 216: + case 216 /* ExpressionStatement */: + // span on the expression return textSpan(node.expression); - case 225: + case 225 /* ReturnStatement */: + // span on return keyword and expression if present return textSpan(node.getChildAt(0), node.expression); - case 219: + case 219 /* WhileStatement */: + // Span on while(...) return textSpanEndingAtNextToken(node, node.expression); - case 218: + case 218 /* DoStatement */: + // span in statement of the do statement return spanInNode(node.statement); - case 231: + case 231 /* DebuggerStatement */: + // span on debugger keyword return textSpan(node.getChildAt(0)); - case 217: + case 217 /* IfStatement */: + // set on if(..) span return textSpanEndingAtNextToken(node, node.expression); - case 228: + case 228 /* LabeledStatement */: + // span in statement return spanInNode(node.statement); - case 224: - case 223: + case 224 /* BreakStatement */: + case 223 /* ContinueStatement */: + // On break or continue keyword and label if present return textSpan(node.getChildAt(0), node.label); - case 220: + case 220 /* ForStatement */: return spanInForStatement(node); - case 221: + case 221 /* ForInStatement */: + // span of for (a in ...) return textSpanEndingAtNextToken(node, node.expression); - case 222: + case 222 /* ForOfStatement */: + // span in initializer return spanInInitializerOfForLike(node); - case 227: + case 227 /* SwitchStatement */: + // span on switch(...) return textSpanEndingAtNextToken(node, node.expression); - case 266: - case 267: + case 266 /* CaseClause */: + case 267 /* DefaultClause */: + // span in first statement of the clause return spanInNode(node.statements[0]); - case 230: + case 230 /* TryStatement */: + // span in try block return spanInBlock(node.tryBlock); - case 229: + case 229 /* ThrowStatement */: + // span in throw ... return textSpan(node, node.expression); - case 249: + case 249 /* ExportAssignment */: + // span on export = id return textSpan(node, node.expression); - case 243: + case 243 /* ImportEqualsDeclaration */: + // import statement without including semicolon return textSpan(node, node.moduleReference); - case 244: + case 244 /* ImportDeclaration */: + // import statement without including semicolon return textSpan(node, node.moduleSpecifier); - case 250: + case 250 /* ExportDeclaration */: + // import statement without including semicolon return textSpan(node, node.moduleSpecifier); - case 239: - if (ts.getModuleInstanceState(node) !== 1) { + case 239 /* ModuleDeclaration */: + // span on complete module if it is instantiated + if (ts.getModuleInstanceState(node) !== 1 /* Instantiated */) { return undefined; } - case 235: - case 238: - case 273: - case 182: + // falls through + case 235 /* ClassDeclaration */: + case 238 /* EnumDeclaration */: + case 273 /* EnumMember */: + case 182 /* BindingElement */: + // span on complete node return textSpan(node); - case 226: + case 226 /* WithStatement */: + // span in statement return spanInNode(node.statement); - case 150: + case 150 /* Decorator */: return spanInNodeArray(parent.decorators); - case 180: - case 181: + case 180 /* ObjectBindingPattern */: + case 181 /* ArrayBindingPattern */: return spanInBindingPattern(node); - case 236: - case 237: + // No breakpoint in interface, type alias + case 236 /* InterfaceDeclaration */: + case 237 /* TypeAliasDeclaration */: return undefined; - case 25: - case 1: + // Tokens: + case 25 /* SemicolonToken */: + case 1 /* EndOfFileToken */: return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile)); - case 26: + case 26 /* CommaToken */: return spanInPreviousNode(node); - case 17: + case 17 /* OpenBraceToken */: return spanInOpenBraceToken(node); - case 18: + case 18 /* CloseBraceToken */: return spanInCloseBraceToken(node); - case 22: + case 22 /* CloseBracketToken */: return spanInCloseBracketToken(node); - case 19: + case 19 /* OpenParenToken */: return spanInOpenParenToken(node); - case 20: + case 20 /* CloseParenToken */: return spanInCloseParenToken(node); - case 56: + case 56 /* ColonToken */: return spanInColonToken(node); - case 29: - case 27: + case 29 /* GreaterThanToken */: + case 27 /* LessThanToken */: return spanInGreaterThanOrLessThanToken(node); - case 106: + // Keywords: + case 106 /* WhileKeyword */: return spanInWhileKeyword(node); - case 82: - case 74: - case 87: + case 82 /* ElseKeyword */: + case 74 /* CatchKeyword */: + case 87 /* FinallyKeyword */: return spanInNextNode(node); - case 145: + case 145 /* OfKeyword */: return spanInOfKeyword(node); default: + // Destructuring pattern in destructuring assignment + // [a, b, c] of + // [a, b, c] = expression if (ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node)) { return spanInArrayLiteralOrObjectLiteralDestructuringPattern(node); } - if ((node.kind === 71 || - node.kind === 204 || - node.kind === 270 || - node.kind === 271) && + // Set breakpoint on identifier element of destructuring pattern + // `a` or `...c` or `d: x` from + // `[a, b, ...c]` or `{ a, b }` or `{ d: x }` from destructuring pattern + if ((node.kind === 71 /* Identifier */ || + node.kind === 204 /* SpreadElement */ || + node.kind === 270 /* PropertyAssignment */ || + node.kind === 271 /* ShorthandPropertyAssignment */) && ts.isArrayLiteralOrObjectLiteralDestructuringPattern(parent)) { return textSpan(node); } - if (node.kind === 200) { + if (node.kind === 200 /* BinaryExpression */) { var _a = node, left = _a.left, operatorToken = _a.operatorToken; + // Set breakpoint in destructuring pattern if its destructuring assignment + // [a, b, c] or {a, b, c} of + // [a, b, c] = expression or + // {a, b, c} = expression if (ts.isArrayLiteralOrObjectLiteralDestructuringPattern(left)) { return spanInArrayLiteralOrObjectLiteralDestructuringPattern(left); } - if (operatorToken.kind === 58 && ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) { + if (operatorToken.kind === 58 /* EqualsToken */ && ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) { + // Set breakpoint on assignment expression element of destructuring pattern + // a = expression of + // [a = expression, b, c] = someExpression or + // { a = expression, b, c } = someExpression return textSpan(node); } - if (operatorToken.kind === 26) { + if (operatorToken.kind === 26 /* CommaToken */) { return spanInNode(left); } } if (ts.isExpressionNode(node)) { switch (parent.kind) { - case 218: + case 218 /* DoStatement */: + // Set span as if on while keyword return spanInPreviousNode(node); - case 150: + case 150 /* Decorator */: + // Set breakpoint on the decorator emit return spanInNode(node.parent); - case 220: - case 222: + case 220 /* ForStatement */: + case 222 /* ForOfStatement */: return textSpan(node); - case 200: - if (node.parent.operatorToken.kind === 26) { + case 200 /* BinaryExpression */: + if (node.parent.operatorToken.kind === 26 /* CommaToken */) { + // If this is a comma expression, the breakpoint is possible in this expression return textSpan(node); } break; - case 193: + case 193 /* ArrowFunction */: if (node.parent.body === node) { + // If this is body of arrow function, it is allowed to have the breakpoint return textSpan(node); } break; } } switch (node.parent.kind) { - case 270: + case 270 /* PropertyAssignment */: + // If this is name of property assignment, set breakpoint in the initializer if (node.parent.name === node && !ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.parent)) { return spanInNode(node.parent.initializer); } break; - case 190: + case 190 /* TypeAssertionExpression */: + // Breakpoint in type assertion goes to its operand if (node.parent.type === node) { return spanInNextNode(node.parent.type); } break; - case 232: - case 149: { + case 232 /* VariableDeclaration */: + case 149 /* Parameter */: { + // initializer of variable/parameter declaration go to previous node var _b = node.parent, initializer = _b.initializer, type = _b.type; if (initializer === node || type === node || ts.isAssignmentOperator(node.kind)) { return spanInPreviousNode(node); } break; } - case 200: { + case 200 /* BinaryExpression */: { var left = node.parent.left; if (ts.isArrayLiteralOrObjectLiteralDestructuringPattern(left) && node !== left) { + // If initializer of destructuring assignment move to previous token return spanInPreviousNode(node); } break; } default: + // return type of function go to previous token if (ts.isFunctionLike(node.parent) && node.parent.type === node) { return spanInPreviousNode(node); } } + // Default go to parent to set the breakpoint return spanInNode(node.parent); } } function textSpanFromVariableDeclaration(variableDeclaration) { if (ts.isVariableDeclarationList(variableDeclaration.parent) && variableDeclaration.parent.declarations[0] === variableDeclaration) { + // First declaration - include let keyword return textSpan(ts.findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent), variableDeclaration); } else { + // Span only on this declaration return textSpan(variableDeclaration); } } function spanInVariableDeclaration(variableDeclaration) { - if (variableDeclaration.parent.parent.kind === 221) { + // If declaration of for in statement, just set the span in parent + if (variableDeclaration.parent.parent.kind === 221 /* ForInStatement */) { return spanInNode(variableDeclaration.parent.parent); } var parent = variableDeclaration.parent; + // If this is a destructuring pattern, set breakpoint in binding pattern if (ts.isBindingPattern(variableDeclaration.name)) { return spanInBindingPattern(variableDeclaration.name); } + // Breakpoint is possible in variableDeclaration only if there is initialization + // or its declaration from 'for of' if (variableDeclaration.initializer || - ts.hasModifier(variableDeclaration, 1) || - parent.parent.kind === 222) { + ts.hasModifier(variableDeclaration, 1 /* Export */) || + parent.parent.kind === 222 /* ForOfStatement */) { return textSpanFromVariableDeclaration(variableDeclaration); } if (ts.isVariableDeclarationList(variableDeclaration.parent) && variableDeclaration.parent.declarations[0] !== variableDeclaration) { + // If we cannot set breakpoint on this declaration, set it on previous one + // Because the variable declaration may be binding pattern and + // we would like to set breakpoint in last binding element if that's the case, + // use preceding token instead return spanInNode(ts.findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent)); } } function canHaveSpanInParameterDeclaration(parameter) { + // Breakpoint is possible on parameter only if it has initializer, is a rest parameter, or has public or private modifier return !!parameter.initializer || parameter.dotDotDotToken !== undefined || - ts.hasModifier(parameter, 4 | 8); + ts.hasModifier(parameter, 4 /* Public */ | 8 /* Private */); } function spanInParameterDeclaration(parameter) { if (ts.isBindingPattern(parameter.name)) { + // Set breakpoint in binding pattern return spanInBindingPattern(parameter.name); } else if (canHaveSpanInParameterDeclaration(parameter)) { @@ -93330,24 +111149,29 @@ var ts; var indexOfParameter = functionDeclaration.parameters.indexOf(parameter); ts.Debug.assert(indexOfParameter !== -1); if (indexOfParameter !== 0) { + // Not a first parameter, go to previous parameter return spanInParameterDeclaration(functionDeclaration.parameters[indexOfParameter - 1]); } else { + // Set breakpoint in the function declaration body return spanInNode(functionDeclaration.body); } } } function canFunctionHaveSpanInWholeDeclaration(functionDeclaration) { - return ts.hasModifier(functionDeclaration, 1) || - (functionDeclaration.parent.kind === 235 && functionDeclaration.kind !== 155); + return ts.hasModifier(functionDeclaration, 1 /* Export */) || + (functionDeclaration.parent.kind === 235 /* ClassDeclaration */ && functionDeclaration.kind !== 155 /* Constructor */); } function spanInFunctionDeclaration(functionDeclaration) { + // No breakpoints in the function signature if (!functionDeclaration.body) { return undefined; } if (canFunctionHaveSpanInWholeDeclaration(functionDeclaration)) { + // Set the span on whole function declaration return textSpan(functionDeclaration); } + // Set span in function body return spanInNode(functionDeclaration.body); } function spanInFunctionBlock(block) { @@ -93359,28 +111183,34 @@ var ts; } function spanInBlock(block) { switch (block.parent.kind) { - case 239: - if (ts.getModuleInstanceState(block.parent) !== 1) { + case 239 /* ModuleDeclaration */: + if (ts.getModuleInstanceState(block.parent) !== 1 /* Instantiated */) { return undefined; } - case 219: - case 217: - case 221: + // falls through + // Set on parent if on same line otherwise on first statement + case 219 /* WhileStatement */: + case 217 /* IfStatement */: + case 221 /* ForInStatement */: return spanInNodeIfStartsOnSameLine(block.parent, block.statements[0]); - case 220: - case 222: + // Set span on previous token if it starts on same line otherwise on the first statement of the block + case 220 /* ForStatement */: + case 222 /* ForOfStatement */: return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(block.pos, sourceFile, block.parent), block.statements[0]); } + // Default action is to set on first statement return spanInNode(block.statements[0]); } function spanInInitializerOfForLike(forLikeStatement) { - if (forLikeStatement.initializer.kind === 233) { + if (forLikeStatement.initializer.kind === 233 /* VariableDeclarationList */) { + // Declaration list - set breakpoint in first declaration var variableDeclarationList = forLikeStatement.initializer; if (variableDeclarationList.declarations.length > 0) { return spanInNode(variableDeclarationList.declarations[0]); } } else { + // Expression - set breakpoint in it return spanInNode(forLikeStatement.initializer); } } @@ -93396,64 +111226,82 @@ var ts; } } function spanInBindingPattern(bindingPattern) { - var firstBindingElement = ts.forEach(bindingPattern.elements, function (element) { return element.kind !== 206 ? element : undefined; }); + // Set breakpoint in first binding element + var firstBindingElement = ts.forEach(bindingPattern.elements, function (element) { return element.kind !== 206 /* OmittedExpression */ ? element : undefined; }); if (firstBindingElement) { return spanInNode(firstBindingElement); } - if (bindingPattern.parent.kind === 182) { + // Empty binding pattern of binding element, set breakpoint on binding element + if (bindingPattern.parent.kind === 182 /* BindingElement */) { return textSpan(bindingPattern.parent); } + // Variable declaration is used as the span return textSpanFromVariableDeclaration(bindingPattern.parent); } function spanInArrayLiteralOrObjectLiteralDestructuringPattern(node) { - ts.Debug.assert(node.kind !== 181 && node.kind !== 180); - var elements = node.kind === 183 ? node.elements : node.properties; - var firstBindingElement = ts.forEach(elements, function (element) { return element.kind !== 206 ? element : undefined; }); + ts.Debug.assert(node.kind !== 181 /* ArrayBindingPattern */ && node.kind !== 180 /* ObjectBindingPattern */); + var elements = node.kind === 183 /* ArrayLiteralExpression */ ? node.elements : node.properties; + var firstBindingElement = ts.forEach(elements, function (element) { return element.kind !== 206 /* OmittedExpression */ ? element : undefined; }); if (firstBindingElement) { return spanInNode(firstBindingElement); } - return textSpan(node.parent.kind === 200 ? node.parent : node); + // Could be ArrayLiteral from destructuring assignment or + // just nested element in another destructuring assignment + // set breakpoint on assignment when parent is destructuring assignment + // Otherwise set breakpoint for this element + return textSpan(node.parent.kind === 200 /* BinaryExpression */ ? node.parent : node); } + // Tokens: function spanInOpenBraceToken(node) { switch (node.parent.kind) { - case 238: + case 238 /* EnumDeclaration */: var enumDeclaration = node.parent; return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile, node.parent), enumDeclaration.members.length ? enumDeclaration.members[0] : enumDeclaration.getLastToken(sourceFile)); - case 235: + case 235 /* ClassDeclaration */: var classDeclaration = node.parent; return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile, node.parent), classDeclaration.members.length ? classDeclaration.members[0] : classDeclaration.getLastToken(sourceFile)); - case 241: + case 241 /* CaseBlock */: return spanInNodeIfStartsOnSameLine(node.parent.parent, node.parent.clauses[0]); } + // Default to parent node return spanInNode(node.parent); } function spanInCloseBraceToken(node) { switch (node.parent.kind) { - case 240: - if (ts.getModuleInstanceState(node.parent.parent) !== 1) { + case 240 /* ModuleBlock */: + // If this is not an instantiated module block, no bp span + if (ts.getModuleInstanceState(node.parent.parent) !== 1 /* Instantiated */) { return undefined; } - case 238: - case 235: + // falls through + case 238 /* EnumDeclaration */: + case 235 /* ClassDeclaration */: + // Span on close brace token return textSpan(node); - case 213: + case 213 /* Block */: if (ts.isFunctionBlock(node.parent)) { + // Span on close brace token return textSpan(node); } - case 269: + // falls through + case 269 /* CatchClause */: return spanInNode(ts.lastOrUndefined(node.parent.statements)); - case 241: + case 241 /* CaseBlock */: + // breakpoint in last statement of the last clause var caseBlock = node.parent; var lastClause = ts.lastOrUndefined(caseBlock.clauses); if (lastClause) { return spanInNode(ts.lastOrUndefined(lastClause.statements)); } return undefined; - case 180: + case 180 /* ObjectBindingPattern */: + // Breakpoint in last binding element or binding pattern if it contains no elements var bindingPattern = node.parent; return spanInNode(ts.lastOrUndefined(bindingPattern.elements) || bindingPattern); + // Default to parent node default: if (ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) { + // Breakpoint in last binding element or binding pattern if it contains no elements var objectLiteral = node.parent; return textSpan(ts.lastOrUndefined(objectLiteral.properties) || objectLiteral); } @@ -93462,74 +111310,85 @@ var ts; } function spanInCloseBracketToken(node) { switch (node.parent.kind) { - case 181: + case 181 /* ArrayBindingPattern */: + // Breakpoint in last binding element or binding pattern if it contains no elements var bindingPattern = node.parent; return textSpan(ts.lastOrUndefined(bindingPattern.elements) || bindingPattern); default: if (ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) { + // Breakpoint in last binding element or binding pattern if it contains no elements var arrayLiteral = node.parent; return textSpan(ts.lastOrUndefined(arrayLiteral.elements) || arrayLiteral); } + // Default to parent node return spanInNode(node.parent); } } function spanInOpenParenToken(node) { - if (node.parent.kind === 218 || - node.parent.kind === 187 || - node.parent.kind === 188) { + if (node.parent.kind === 218 /* DoStatement */ || // Go to while keyword and do action instead + node.parent.kind === 187 /* CallExpression */ || + node.parent.kind === 188 /* NewExpression */) { return spanInPreviousNode(node); } - if (node.parent.kind === 191) { + if (node.parent.kind === 191 /* ParenthesizedExpression */) { return spanInNextNode(node); } + // Default to parent node return spanInNode(node.parent); } function spanInCloseParenToken(node) { + // Is this close paren token of parameter list, set span in previous token switch (node.parent.kind) { - case 192: - case 234: - case 193: - case 154: - case 153: - case 156: - case 157: - case 155: - case 219: - case 218: - case 220: - case 222: - case 187: - case 188: - case 191: + case 192 /* FunctionExpression */: + case 234 /* FunctionDeclaration */: + case 193 /* ArrowFunction */: + case 154 /* MethodDeclaration */: + case 153 /* MethodSignature */: + case 156 /* GetAccessor */: + case 157 /* SetAccessor */: + case 155 /* Constructor */: + case 219 /* WhileStatement */: + case 218 /* DoStatement */: + case 220 /* ForStatement */: + case 222 /* ForOfStatement */: + case 187 /* CallExpression */: + case 188 /* NewExpression */: + case 191 /* ParenthesizedExpression */: return spanInPreviousNode(node); + // Default to parent node default: return spanInNode(node.parent); } } function spanInColonToken(node) { + // Is this : specifying return annotation of the function declaration if (ts.isFunctionLike(node.parent) || - node.parent.kind === 270 || - node.parent.kind === 149) { + node.parent.kind === 270 /* PropertyAssignment */ || + node.parent.kind === 149 /* Parameter */) { return spanInPreviousNode(node); } return spanInNode(node.parent); } function spanInGreaterThanOrLessThanToken(node) { - if (node.parent.kind === 190) { + if (node.parent.kind === 190 /* TypeAssertionExpression */) { return spanInNextNode(node); } return spanInNode(node.parent); } function spanInWhileKeyword(node) { - if (node.parent.kind === 218) { + if (node.parent.kind === 218 /* DoStatement */) { + // Set span on while expression return textSpanEndingAtNextToken(node, node.parent.expression); } + // Default to parent node return spanInNode(node.parent); } function spanInOfKeyword(node) { - if (node.parent.kind === 222) { + if (node.parent.kind === 222 /* ForOfStatement */) { + // Set using next token return spanInNextNode(node); } + // Default to parent node return spanInNode(node.parent); } } @@ -93539,17 +111398,42 @@ var ts; })(ts || (ts = {})); var ts; (function (ts) { + /** + * Transform one or more nodes using the supplied transformers. + * @param source A single `Node` or an array of `Node` objects. + * @param transformers An array of `TransformerFactory` callbacks used to process the transformation. + * @param compilerOptions Optional compiler options. + */ function transform(source, transformers, compilerOptions) { var diagnostics = []; - compilerOptions = ts.fixupCompilerOptions(compilerOptions, diagnostics); + compilerOptions = ts.fixupCompilerOptions(compilerOptions, diagnostics); // TODO: GH#18217 var nodes = ts.isArray(source) ? source : [source]; - var result = ts.transformNodes(undefined, undefined, compilerOptions, nodes, transformers, true); + var result = ts.transformNodes(/*resolver*/ undefined, /*emitHost*/ undefined, compilerOptions, nodes, transformers, /*allowDtsFiles*/ true); result.diagnostics = ts.concatenate(result.diagnostics, diagnostics); return result; } ts.transform = transform; })(ts || (ts = {})); +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/* @internal */ var debugObjectHost = (function () { return this; })(); +// We need to use 'null' to interface with the managed side. +/* tslint:disable:no-null-keyword */ +/* tslint:disable:no-in-operator */ +/* @internal */ var ts; (function (ts) { function logInternalError(logger, err) { @@ -93557,7 +111441,7 @@ var ts; logger.log("*INTERNAL ERROR* - Exception in typescript services: " + err.message); } } - var ScriptSnapshotShimAdapter = (function () { + var ScriptSnapshotShimAdapter = /** @class */ (function () { function ScriptSnapshotShimAdapter(scriptSnapshotShim) { this.scriptSnapshotShim = scriptSnapshotShim; } @@ -93571,30 +111455,34 @@ var ts; var oldSnapshotShim = oldSnapshot; var encoded = this.scriptSnapshotShim.getChangeRange(oldSnapshotShim.scriptSnapshotShim); if (encoded === null) { - return null; + return null; // TODO: GH#18217 } - var decoded = JSON.parse(encoded); + var decoded = JSON.parse(encoded); // TODO: GH#18217 return ts.createTextChangeRange(ts.createTextSpan(decoded.span.start, decoded.span.length), decoded.newLength); }; ScriptSnapshotShimAdapter.prototype.dispose = function () { + // if scriptSnapshotShim is a COM object then property check becomes method call with no arguments + // 'in' does not have this effect if ("dispose" in this.scriptSnapshotShim) { - this.scriptSnapshotShim.dispose(); + this.scriptSnapshotShim.dispose(); // TODO: GH#18217 Can we just use `if (this.scriptSnapshotShim.dispose)`? } }; return ScriptSnapshotShimAdapter; }()); - var LanguageServiceShimHostAdapter = (function () { + var LanguageServiceShimHostAdapter = /** @class */ (function () { function LanguageServiceShimHostAdapter(shimHost) { var _this = this; this.shimHost = shimHost; this.loggingEnabled = false; this.tracingEnabled = false; + // if shimHost is a COM object then property check will become method call with no arguments. + // 'in' does not have this effect. if ("getModuleResolutionsForFile" in this.shimHost) { this.resolveModuleNames = function (moduleNames, containingFile) { - var resolutionsInFile = JSON.parse(_this.shimHost.getModuleResolutionsForFile(containingFile)); + var resolutionsInFile = JSON.parse(_this.shimHost.getModuleResolutionsForFile(containingFile)); // TODO: GH#18217 return ts.map(moduleNames, function (name) { var result = ts.getProperty(resolutionsInFile, name); - return result ? { resolvedFileName: result, extension: ts.extensionFromPath(result), isExternalLibraryImport: false } : undefined; + return result ? { resolvedFileName: result, extension: ts.extensionFromPath(result), isExternalLibraryImport: false } : undefined; // TODO: GH#18217 }); }; } @@ -93603,8 +111491,8 @@ var ts; } if ("getTypeReferenceDirectiveResolutionsForFile" in this.shimHost) { this.resolveTypeReferenceDirectives = function (typeDirectiveNames, containingFile) { - var typeDirectivesForFile = JSON.parse(_this.shimHost.getTypeReferenceDirectiveResolutionsForFile(containingFile)); - return ts.map(typeDirectiveNames, function (name) { return ts.getProperty(typeDirectivesForFile, name); }); + var typeDirectivesForFile = JSON.parse(_this.shimHost.getTypeReferenceDirectiveResolutionsForFile(containingFile)); // TODO: GH#18217 + return ts.map(typeDirectiveNames, function (name) { return ts.getProperty(typeDirectivesForFile, name); }); // TODO: GH#18217 }; } } @@ -93623,7 +111511,8 @@ var ts; }; LanguageServiceShimHostAdapter.prototype.getProjectVersion = function () { if (!this.shimHost.getProjectVersion) { - return undefined; + // shimmed host does not support getProjectVersion + return undefined; // TODO: GH#18217 } return this.shimHost.getProjectVersion(); }; @@ -93642,6 +111531,7 @@ var ts; throw Error("LanguageServiceShimHostAdapter.getCompilationSettings: empty compilationSettings"); } var compilerOptions = JSON.parse(settingsJson); + // permit language service to handle all files (filtering should be performed on the host side) compilerOptions.allowNonTsExtensions = true; return compilerOptions; }; @@ -93655,10 +111545,10 @@ var ts; }; LanguageServiceShimHostAdapter.prototype.getScriptKind = function (fileName) { if ("getScriptKind" in this.shimHost) { - return this.shimHost.getScriptKind(fileName); + return this.shimHost.getScriptKind(fileName); // TODO: GH#18217 } else { - return 0; + return 0 /* Unknown */; } }; LanguageServiceShimHostAdapter.prototype.getScriptVersion = function (fileName) { @@ -93691,7 +111581,7 @@ var ts; return this.shimHost.getDefaultLibFileName(JSON.stringify(options)); }; LanguageServiceShimHostAdapter.prototype.readDirectory = function (path, extensions, exclude, include, depth) { - var pattern = ts.getFileMatcherPatterns(path, exclude, include, this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory()); + var pattern = ts.getFileMatcherPatterns(path, exclude, include, this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory()); // TODO: GH#18217 return JSON.parse(this.shimHost.readDirectory(path, JSON.stringify(extensions), JSON.stringify(pattern.basePaths), pattern.excludePattern, pattern.includeFilePattern, pattern.includeDirectoryPattern, depth)); }; LanguageServiceShimHostAdapter.prototype.readFile = function (path, encoding) { @@ -93703,7 +111593,7 @@ var ts; return LanguageServiceShimHostAdapter; }()); ts.LanguageServiceShimHostAdapter = LanguageServiceShimHostAdapter; - var CoreServicesShimHostAdapter = (function () { + var CoreServicesShimHostAdapter = /** @class */ (function () { function CoreServicesShimHostAdapter(shimHost) { var _this = this; this.shimHost = shimHost; @@ -93712,11 +111602,11 @@ var ts; this.directoryExists = function (directoryName) { return _this.shimHost.directoryExists(directoryName); }; } if ("realpath" in this.shimHost) { - this.realpath = function (path) { return _this.shimHost.realpath(path); }; + this.realpath = function (path) { return _this.shimHost.realpath(path); }; // TODO: GH#18217 } } CoreServicesShimHostAdapter.prototype.readDirectory = function (rootDir, extensions, exclude, include, depth) { - var pattern = ts.getFileMatcherPatterns(rootDir, exclude, include, this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory()); + var pattern = ts.getFileMatcherPatterns(rootDir, exclude, include, this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory()); // TODO: GH#18217 return JSON.parse(this.shimHost.readDirectory(rootDir, JSON.stringify(extensions), JSON.stringify(pattern.basePaths), pattern.excludePattern, pattern.includeFilePattern, pattern.includeDirectoryPattern, depth)); }; CoreServicesShimHostAdapter.prototype.fileExists = function (fileName) { @@ -93752,7 +111642,7 @@ var ts; return result; } function forwardJSONCall(logger, actionDescription, action, logPerformance) { - return forwardCall(logger, actionDescription, true, action, logPerformance); + return forwardCall(logger, actionDescription, /*returnJson*/ true, action, logPerformance); } function forwardCall(logger, actionDescription, returnJson, action, logPerformance) { try { @@ -93768,7 +111658,7 @@ var ts; return JSON.stringify({ error: err }); } } - var ShimBase = (function () { + var ShimBase = /** @class */ (function () { function ShimBase(factory) { this.factory = factory; factory.registerShim(this); @@ -93792,7 +111682,7 @@ var ts; reportsUnnecessary: diagnostic.reportsUnnecessary, }; } - var LanguageServiceShimObject = (function (_super) { + var LanguageServiceShimObject = /** @class */ (function (_super) { __extends(LanguageServiceShimObject, _super); function LanguageServiceShimObject(factory, host, languageService) { var _this = _super.call(this, factory) || this; @@ -93805,10 +111695,16 @@ var ts; LanguageServiceShimObject.prototype.forwardJSONCall = function (actionDescription, action) { return forwardJSONCall(this.logger, actionDescription, action, this.logPerformance); }; + /// DISPOSE + /** + * Ensure (almost) deterministic release of internal Javascript resources when + * some external native objects holds onto us (e.g. Com/Interop). + */ LanguageServiceShimObject.prototype.dispose = function (dummy) { this.logger.log("dispose()"); this.languageService.dispose(); this.languageService = null; + // force a GC if (debugObjectHost && debugObjectHost.CollectGarbage) { debugObjectHost.CollectGarbage(); this.logger.log("CollectGarbage()"); @@ -93816,6 +111712,10 @@ var ts; this.logger = null; _super.prototype.dispose.call(this, dummy); }; + /// REFRESH + /** + * Update the list of scripts known to the compiler + */ LanguageServiceShimObject.prototype.refresh = function (throwOnError) { this.forwardJSONCall("refresh(" + throwOnError + ")", function () { return null; }); }; @@ -93840,11 +111740,17 @@ var ts; }; LanguageServiceShimObject.prototype.getEncodedSyntacticClassifications = function (fileName, start, length) { var _this = this; - return this.forwardJSONCall("getEncodedSyntacticClassifications('" + fileName + "', " + start + ", " + length + ")", function () { return convertClassifications(_this.languageService.getEncodedSyntacticClassifications(fileName, ts.createTextSpan(start, length))); }); + return this.forwardJSONCall("getEncodedSyntacticClassifications('" + fileName + "', " + start + ", " + length + ")", + // directly serialize the spans out to a string. This is much faster to decode + // on the managed side versus a full JSON array. + function () { return convertClassifications(_this.languageService.getEncodedSyntacticClassifications(fileName, ts.createTextSpan(start, length))); }); }; LanguageServiceShimObject.prototype.getEncodedSemanticClassifications = function (fileName, start, length) { var _this = this; - return this.forwardJSONCall("getEncodedSemanticClassifications('" + fileName + "', " + start + ", " + length + ")", function () { return convertClassifications(_this.languageService.getEncodedSemanticClassifications(fileName, ts.createTextSpan(start, length))); }); + return this.forwardJSONCall("getEncodedSemanticClassifications('" + fileName + "', " + start + ", " + length + ")", + // directly serialize the spans out to a string. This is much faster to decode + // on the managed side versus a full JSON array. + function () { return convertClassifications(_this.languageService.getEncodedSemanticClassifications(fileName, ts.createTextSpan(start, length))); }); }; LanguageServiceShimObject.prototype.getSyntacticDiagnostics = function (fileName) { var _this = this; @@ -93871,34 +111777,68 @@ var ts; return _this.realizeDiagnostics(diagnostics); }); }; + /// QUICKINFO + /** + * Computes a string representation of the type at the requested position + * in the active file. + */ LanguageServiceShimObject.prototype.getQuickInfoAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getQuickInfoAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getQuickInfoAtPosition(fileName, position); }); }; + /// NAMEORDOTTEDNAMESPAN + /** + * Computes span information of the name or dotted name at the requested position + * in the active file. + */ LanguageServiceShimObject.prototype.getNameOrDottedNameSpan = function (fileName, startPos, endPos) { var _this = this; return this.forwardJSONCall("getNameOrDottedNameSpan('" + fileName + "', " + startPos + ", " + endPos + ")", function () { return _this.languageService.getNameOrDottedNameSpan(fileName, startPos, endPos); }); }; + /** + * STATEMENTSPAN + * Computes span information of statement at the requested position in the active file. + */ LanguageServiceShimObject.prototype.getBreakpointStatementAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getBreakpointStatementAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getBreakpointStatementAtPosition(fileName, position); }); }; + /// SIGNATUREHELP LanguageServiceShimObject.prototype.getSignatureHelpItems = function (fileName, position) { var _this = this; return this.forwardJSONCall("getSignatureHelpItems('" + fileName + "', " + position + ")", function () { return _this.languageService.getSignatureHelpItems(fileName, position); }); }; + /// GOTO DEFINITION + /** + * Computes the definition location and file for the symbol + * at the requested position. + */ LanguageServiceShimObject.prototype.getDefinitionAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getDefinitionAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getDefinitionAtPosition(fileName, position); }); }; + /** + * Computes the definition location and file for the symbol + * at the requested position. + */ LanguageServiceShimObject.prototype.getDefinitionAndBoundSpan = function (fileName, position) { var _this = this; return this.forwardJSONCall("getDefinitionAndBoundSpan('" + fileName + "', " + position + ")", function () { return _this.languageService.getDefinitionAndBoundSpan(fileName, position); }); }; + /// GOTO Type + /** + * Computes the definition location of the type of the symbol + * at the requested position. + */ LanguageServiceShimObject.prototype.getTypeDefinitionAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getTypeDefinitionAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getTypeDefinitionAtPosition(fileName, position); }); }; + /// GOTO Implementation + /** + * Computes the implementation location of the symbol + * at the requested position. + */ LanguageServiceShimObject.prototype.getImplementationAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getImplementationAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getImplementationAtPosition(fileName, position); }); @@ -93911,6 +111851,7 @@ var ts; var _this = this; return this.forwardJSONCall("findRenameLocations('" + fileName + "', " + position + ", " + findInStrings + ", " + findInComments + ")", function () { return _this.languageService.findRenameLocations(fileName, position, findInStrings, findInComments); }); }; + /// GET BRACE MATCHING LanguageServiceShimObject.prototype.getBraceMatchingAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getBraceMatchingAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getBraceMatchingAtPosition(fileName, position); }); @@ -93923,13 +111864,15 @@ var ts; var _this = this; return this.forwardJSONCall("getSpanOfEnclosingComment('" + fileName + "', " + position + ")", function () { return _this.languageService.getSpanOfEnclosingComment(fileName, position, onlyMultiLine); }); }; - LanguageServiceShimObject.prototype.getIndentationAtPosition = function (fileName, position, options) { + /// GET SMART INDENT + LanguageServiceShimObject.prototype.getIndentationAtPosition = function (fileName, position, options /*Services.EditorOptions*/) { var _this = this; return this.forwardJSONCall("getIndentationAtPosition('" + fileName + "', " + position + ")", function () { var localOptions = JSON.parse(options); return _this.languageService.getIndentationAtPosition(fileName, position, localOptions); }); }; + /// GET REFERENCES LanguageServiceShimObject.prototype.getReferencesAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getReferencesAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getReferencesAtPosition(fileName, position); }); @@ -93946,14 +111889,22 @@ var ts; var _this = this; return this.forwardJSONCall("getDocumentHighlights('" + fileName + "', " + position + ")", function () { var results = _this.languageService.getDocumentHighlights(fileName, position, JSON.parse(filesToSearch)); + // workaround for VS document highlighting issue - keep only items from the initial file var normalizedName = ts.normalizeSlashes(fileName).toLowerCase(); return ts.filter(results, function (r) { return ts.normalizeSlashes(r.fileName).toLowerCase() === normalizedName; }); }); }; + /// COMPLETION LISTS + /** + * Get a string based representation of the completions + * to provide at the given source position and providing a member completion + * list if requested. + */ LanguageServiceShimObject.prototype.getCompletionsAtPosition = function (fileName, position, preferences) { var _this = this; return this.forwardJSONCall("getCompletionsAtPosition('" + fileName + "', " + position + ", " + preferences + ")", function () { return _this.languageService.getCompletionsAtPosition(fileName, position, preferences); }); }; + /** Get a string based representation of a completion list entry details */ LanguageServiceShimObject.prototype.getCompletionEntryDetails = function (fileName, position, entryName, formatOptions, source, preferences) { var _this = this; return this.forwardJSONCall("getCompletionEntryDetails('" + fileName + "', " + position + ", '" + entryName + "')", function () { @@ -93961,21 +111912,21 @@ var ts; return _this.languageService.getCompletionEntryDetails(fileName, position, entryName, localOptions, source, preferences); }); }; - LanguageServiceShimObject.prototype.getFormattingEditsForRange = function (fileName, start, end, options) { + LanguageServiceShimObject.prototype.getFormattingEditsForRange = function (fileName, start, end, options /*Services.FormatCodeOptions*/) { var _this = this; return this.forwardJSONCall("getFormattingEditsForRange('" + fileName + "', " + start + ", " + end + ")", function () { var localOptions = JSON.parse(options); return _this.languageService.getFormattingEditsForRange(fileName, start, end, localOptions); }); }; - LanguageServiceShimObject.prototype.getFormattingEditsForDocument = function (fileName, options) { + LanguageServiceShimObject.prototype.getFormattingEditsForDocument = function (fileName, options /*Services.FormatCodeOptions*/) { var _this = this; return this.forwardJSONCall("getFormattingEditsForDocument('" + fileName + "')", function () { var localOptions = JSON.parse(options); return _this.languageService.getFormattingEditsForDocument(fileName, localOptions); }); }; - LanguageServiceShimObject.prototype.getFormattingEditsAfterKeystroke = function (fileName, position, key, options) { + LanguageServiceShimObject.prototype.getFormattingEditsAfterKeystroke = function (fileName, position, key, options /*Services.FormatCodeOptions*/) { var _this = this; return this.forwardJSONCall("getFormattingEditsAfterKeystroke('" + fileName + "', " + position + ", '" + key + "')", function () { var localOptions = JSON.parse(options); @@ -93986,6 +111937,8 @@ var ts; var _this = this; return this.forwardJSONCall("getDocCommentTemplateAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getDocCommentTemplateAtPosition(fileName, position); }); }; + /// NAVIGATE TO + /** Return a list of symbols that are interesting to navigate to */ LanguageServiceShimObject.prototype.getNavigateToItems = function (searchValue, maxResultCount, fileName) { var _this = this; return this.forwardJSONCall("getNavigateToItems('" + searchValue + "', " + maxResultCount + ", " + fileName + ")", function () { return _this.languageService.getNavigateToItems(searchValue, maxResultCount, fileName); }); @@ -94006,20 +111959,22 @@ var ts; var _this = this; return this.forwardJSONCall("getTodoComments('" + fileName + "')", function () { return _this.languageService.getTodoComments(fileName, JSON.parse(descriptors)); }); }; + /// Emit LanguageServiceShimObject.prototype.getEmitOutput = function (fileName) { var _this = this; return this.forwardJSONCall("getEmitOutput('" + fileName + "')", function () { return _this.languageService.getEmitOutput(fileName); }); }; LanguageServiceShimObject.prototype.getEmitOutputObject = function (fileName) { var _this = this; - return forwardCall(this.logger, "getEmitOutput('" + fileName + "')", false, function () { return _this.languageService.getEmitOutput(fileName); }, this.logPerformance); + return forwardCall(this.logger, "getEmitOutput('" + fileName + "')", + /*returnJson*/ false, function () { return _this.languageService.getEmitOutput(fileName); }, this.logPerformance); }; return LanguageServiceShimObject; }(ShimBase)); function convertClassifications(classifications) { return { spans: classifications.spans.join(","), endOfLineState: classifications.endOfLineState }; } - var ClassifierShimObject = (function (_super) { + var ClassifierShimObject = /** @class */ (function (_super) { __extends(ClassifierShimObject, _super); function ClassifierShimObject(factory, logger) { var _this = _super.call(this, factory) || this; @@ -94033,6 +111988,7 @@ var ts; if (syntacticClassifierAbsent === void 0) { syntacticClassifierAbsent = false; } return forwardJSONCall(this.logger, "getEncodedLexicalClassifications", function () { return convertClassifications(_this.classifier.getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent)); }, this.logPerformance); }; + /// COLORIZATION ClassifierShimObject.prototype.getClassificationsForLine = function (text, lexState, classifyKeywordsInGenerics) { if (classifyKeywordsInGenerics === void 0) { classifyKeywordsInGenerics = false; } var classification = this.classifier.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics); @@ -94047,7 +112003,7 @@ var ts; }; return ClassifierShimObject; }(ShimBase)); - var CoreServicesShimObject = (function (_super) { + var CoreServicesShimObject = /** @class */ (function (_super) { __extends(CoreServicesShimObject, _super); function CoreServicesShimObject(factory, logger, host) { var _this = _super.call(this, factory) || this; @@ -94065,7 +112021,7 @@ var ts; var compilerOptions = JSON.parse(compilerOptionsJson); var result = ts.resolveModuleName(moduleName, ts.normalizeSlashes(fileName), compilerOptions, _this.host); var resolvedFileName = result.resolvedModule ? result.resolvedModule.resolvedFileName : undefined; - if (result.resolvedModule && result.resolvedModule.extension !== ".ts" && result.resolvedModule.extension !== ".tsx" && result.resolvedModule.extension !== ".d.ts") { + if (result.resolvedModule && result.resolvedModule.extension !== ".ts" /* Ts */ && result.resolvedModule.extension !== ".tsx" /* Tsx */ && result.resolvedModule.extension !== ".d.ts" /* Dts */) { resolvedFileName = undefined; } return { @@ -94089,7 +112045,8 @@ var ts; CoreServicesShimObject.prototype.getPreProcessedFileInfo = function (fileName, sourceTextSnapshot) { var _this = this; return this.forwardJSONCall("getPreProcessedFileInfo('" + fileName + "')", function () { - var result = ts.preProcessFile(ts.getSnapshotText(sourceTextSnapshot), true, true); + // for now treat files as JavaScript + var result = ts.preProcessFile(ts.getSnapshotText(sourceTextSnapshot), /* readImportFiles */ true, /* detectJavaScriptImports */ true); return { referencedFiles: _this.convertFileReferences(result.referencedFiles), importedFiles: _this.convertFileReferences(result.importedFiles), @@ -94127,7 +112084,7 @@ var ts; return this.forwardJSONCall("getTSConfigFileInfo('" + fileName + "')", function () { var result = ts.parseJsonText(fileName, ts.getSnapshotText(sourceTextSnapshot)); var normalizedFileName = ts.normalizeSlashes(fileName); - var configFile = ts.parseJsonSourceFileConfigFileContent(result, _this.host, ts.getDirectoryPath(normalizedFileName), {}, normalizedFileName); + var configFile = ts.parseJsonSourceFileConfigFileContent(result, _this.host, ts.getDirectoryPath(normalizedFileName), /*existingOptions*/ {}, normalizedFileName); return { options: configFile.options, typeAcquisition: configFile.typeAcquisition, @@ -94142,7 +112099,7 @@ var ts; }; CoreServicesShimObject.prototype.discoverTypings = function (discoverTypingsJson) { var _this = this; - var getCanonicalFileName = ts.createGetCanonicalFileName(false); + var getCanonicalFileName = ts.createGetCanonicalFileName(/*useCaseSensitivefileNames:*/ false); return this.forwardJSONCall("discoverTypings()", function () { var info = JSON.parse(discoverTypingsJson); if (_this.safeList === undefined) { @@ -94153,10 +112110,13 @@ var ts; }; return CoreServicesShimObject; }(ShimBase)); - var TypeScriptServicesFactory = (function () { + var TypeScriptServicesFactory = /** @class */ (function () { function TypeScriptServicesFactory() { this._shims = []; } + /* + * Returns script API version. + */ TypeScriptServicesFactory.prototype.getServicesVersion = function () { return ts.servicesVersion; }; @@ -94166,7 +112126,7 @@ var ts; this.documentRegistry = ts.createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory()); } var hostAdapter = new LanguageServiceShimHostAdapter(host); - var languageService = ts.createLanguageService(hostAdapter, this.documentRegistry, false); + var languageService = ts.createLanguageService(hostAdapter, this.documentRegistry, /*syntaxOnly*/ false); return new LanguageServiceShimObject(this, host, languageService); } catch (err) { @@ -94194,6 +112154,7 @@ var ts; } }; TypeScriptServicesFactory.prototype.close = function () { + // Forget all the registered shims ts.clear(this._shims); this.documentRegistry = undefined; }; @@ -94216,6 +112177,10 @@ var ts; module.exports = ts; } })(ts || (ts = {})); +/* tslint:enable:no-in-operator */ +/* tslint:enable:no-null */ +/// TODO: this is used by VS, clean this up on both sides of the interface +/* @internal */ var TypeScript; (function (TypeScript) { var Services; @@ -94223,6 +112188,8 @@ var TypeScript; Services.TypeScriptServicesFactory = ts.TypeScriptServicesFactory; })(Services = TypeScript.Services || (TypeScript.Services = {})); })(TypeScript || (TypeScript = {})); +// 'toolsVersion' gets consumed by the managed side, so it's not unused. +// TODO: it should be moved into a namespace though. +/* @internal */ var toolsVersion = ts.versionMajorMinor; - -//# sourceMappingURL=typescriptServices.js.map +//# sourceMappingURL=typescriptServices.js.map \ No newline at end of file diff --git a/lib/typingsInstaller.js b/lib/typingsInstaller.js index 4ca1a85fb3a..6046364b40a 100644 --- a/lib/typingsInstaller.js +++ b/lib/typingsInstaller.js @@ -65494,7 +65494,7 @@ var ts; name: "typescript:assign", scoped: false, priority: 1, - text: "\n var __assign = (this && this.__assign) || Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };" + text: "\n var __assign = (this && this.__assign) || function () {\n __assign = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign.apply(this, arguments);\n };" }; function createAssignHelper(context, attributesSegments) { if (context.getCompilerOptions().target >= 2 /* ES2015 */) { @@ -69112,7 +69112,7 @@ var ts; name: "typescript:extends", scoped: false, priority: 0, - text: "\n var __extends = (this && this.__extends) || (function () {\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n })();" + text: "\n var __extends = (this && this.__extends) || (function () {\n var extendStatics = function (d, b) {\n extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return extendStatics(d, b);\n }\n\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n })();" }; var templateObjectHelper = { name: "typescript:makeTemplateObject", @@ -76863,15 +76863,19 @@ var ts; var firstLineColumnOffset_1 = writer.getColumn(); // First, decode the old component sourcemap var originalMap_1 = parsed; + var sourcesDirectoryPath_1 = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir; + var resolvedPathCache_1 = ts.createMap(); ts.sourcemaps.calculateDecodedMappings(originalMap_1, function (raw) { // Apply offsets to each position and fixup source entries var rawPath = originalMap_1.sources[raw.sourceIndex]; var relativePath = originalMap_1.sourceRoot ? ts.combinePaths(originalMap_1.sourceRoot, rawPath) : rawPath; var combinedPath = ts.combinePaths(ts.getDirectoryPath(node.sourceMapPath), relativePath); - var sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir; - var resolvedPath = ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, combinedPath, host.getCurrentDirectory(), host.getCanonicalFileName, - /*isAbsolutePathAnUrl*/ true); - var absolutePath = ts.getNormalizedAbsolutePath(resolvedPath, sourcesDirectoryPath); + if (!resolvedPathCache_1.has(combinedPath)) { + resolvedPathCache_1.set(combinedPath, ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath_1, combinedPath, host.getCurrentDirectory(), host.getCanonicalFileName, + /*isAbsolutePathAnUrl*/ true)); + } + var resolvedPath = resolvedPathCache_1.get(combinedPath); + var absolutePath = ts.getNormalizedAbsolutePath(resolvedPath, sourcesDirectoryPath_1); // tslint:disable-next-line:no-null-keyword setupSourceEntry(absolutePath, originalMap_1.sourcesContent ? originalMap_1.sourcesContent[raw.sourceIndex] : null); // TODO: Lookup content for inlining? var newIndex = sourceMapData.sourceMapSources.indexOf(resolvedPath); @@ -82959,7 +82963,7 @@ var ts; } function parseProjectReferenceConfigFile(ref) { // The actual filename (i.e. add "/tsconfig.json" if necessary) - var refPath = resolveProjectReferencePath(host, ref); // TODO: GH#18217 + var refPath = resolveProjectReferencePath(host, ref); // An absolute path pointing to the containing directory of the config file var basePath = ts.getNormalizedAbsolutePath(ts.getDirectoryPath(refPath), host.getCurrentDirectory()); var sourceFile = host.getSourceFile(refPath, 100 /* JSON */); @@ -86542,11 +86546,6 @@ var ts; * Gets the UpToDateStatus for a project */ function getUpToDateStatus(host, project) { - if (project === undefined) { - return { - type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" - }; - } if (project === undefined) { return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" }; } @@ -86633,6 +86632,7 @@ var ts; } var pseudoUpToDate = false; var usesPrepend = false; + var upstreamChangedProject; if (project.projectReferences && host.parseConfigFile) { for (var _c = 0, _d = project.projectReferences; _c < _d.length; _c++) { var ref = _d[_c]; @@ -86662,6 +86662,7 @@ var ts; // *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild if (refStatus.newestDeclarationFileContentChangedTime <= oldestOutputFileTime) { pseudoUpToDate = true; + upstreamChangedProject = ref.path; continue; } // We have an output older than an upstream output - we are out of date @@ -86686,8 +86687,12 @@ var ts; newerInputFileName: newestInputFileName }; } - if (usesPrepend) { - pseudoUpToDate = false; + if (usesPrepend && pseudoUpToDate) { + return { + type: UpToDateStatusType.OutOfDateWithUpstream, + outOfDateOutputFileName: oldestOutputFileName, + newerProjectName: upstreamChangedProject + }; } // Up to date return { @@ -86745,7 +86750,6 @@ var ts; } ts.formatUpToDateStatus = formatUpToDateStatus; })(ts || (ts = {})); - //# sourceMappingURL=compiler.js.map "use strict"; /* @internal */ @@ -87156,7 +87160,6 @@ var ts; }()); ts.Semver = Semver; })(ts || (ts = {})); - //# sourceMappingURL=jsTyping.js.map "use strict"; var ts; @@ -87633,7 +87636,6 @@ var ts; })(typingsInstaller = server.typingsInstaller || (server.typingsInstaller = {})); })(server = ts.server || (ts.server = {})); })(ts || (ts = {})); - //# sourceMappingURL=typingsInstallerCore.js.map var ts; (function (ts) { @@ -87844,5 +87846,4 @@ var ts; })(typingsInstaller = server.typingsInstaller || (server.typingsInstaller = {})); })(server = ts.server || (ts.server = {})); })(ts || (ts = {})); - -//# sourceMappingURL=typingsInstaller.js.map +//# sourceMappingURL=typingsInstaller.js.map \ No newline at end of file diff --git a/lib/watchGuard.js b/lib/watchGuard.js index dd246d6f827..c89356b0dc3 100644 --- a/lib/watchGuard.js +++ b/lib/watchGuard.js @@ -26,5 +26,4 @@ try { } catch (_a) { } process.exit(0); - -//# sourceMappingURL=watchGuard.js.map +//# sourceMappingURL=watchGuard.js.map \ No newline at end of file